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 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1206 API_PARSE ai_parms[5];
1210 static byte esc_chi[35] = {0x02,0x18,0x01};
1211 static byte lli[2] = {0x01,0x00};
1216 for(i=0;i<5;i++) ai_parms[i].length = 0;
1218 dbug(1,dprintf("connect_req(%d)",parms->length));
1219 Info = _WRONG_IDENTIFIER;
1222 if(a->adapter_disabled)
1224 dbug(1,dprintf("adapter disabled"));
1225 Id = ((word)1<<8)|a->Id;
1226 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1230 Info = _OUT_OF_PLCI;
1234 plci = &a->plci[i-1];
1236 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237 /* check 'external controller' bit for codec support */
1238 if(Id & EXT_CONTROLLER)
1240 if(AdvCodecSupport(a, plci, appl, 0) )
1243 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1250 if(bp->length)LinkLayer = bp->info[3];
1255 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1258 if(ai_parms[0].length)
1260 ch = GET_WORD(ai_parms[0].info+1);
1261 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262 if(ch==4) /* explizit CHI in message */
1264 /* check length of B-CH struct */
1265 if((ai_parms[0].info)[3]>=1)
1267 if((ai_parms[0].info)[4]==CHI)
1269 p_chi = &((ai_parms[0].info)[5]);
1273 p_chi = &((ai_parms[0].info)[3]);
1275 if(p_chi[0]>35) /* check length of channel ID */
1277 Info = _WRONG_MESSAGE_FORMAT;
1280 else Info = _WRONG_MESSAGE_FORMAT;
1283 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285 dir = GET_WORD(ai_parms[0].info+3);
1288 for(i=0; i+5<=ai_parms[0].length; i++)
1290 if(ai_parms[0].info[i+5]!=0)
1292 if((ai_parms[0].info[i+5] | m) != 0xff)
1293 Info = _WRONG_MESSAGE_FORMAT;
1304 Info = _WRONG_MESSAGE_FORMAT;
1307 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310 for(i=0; i+5<=ai_parms[0].length; i++)
1311 esc_chi[i+3] = ai_parms[0].info[i+5];
1315 esc_chi[2] = (byte)channel;
1316 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317 add_p(plci,LLI,lli);
1318 add_p(plci,ESC,esc_chi);
1319 plci->State = LOCAL_CONNECT;
1320 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1325 else Info = _WRONG_MESSAGE_FORMAT;
1328 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329 plci->command = _CONNECT_R;
1330 plci->number = Number;
1331 /* x.31 or D-ch free SAPI in LinkLayer? */
1332 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1333 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335 /* B-channel used for B3 connections (ch==0), or no B channel */
1336 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1337 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1338 else Info = add_b1(plci,&parms[5],ch,0);
1339 add_s(plci,OAD,&parms[2]);
1340 add_s(plci,OSA,&parms[4]);
1341 add_s(plci,BC,&parms[6]);
1342 add_s(plci,LLC,&parms[7]);
1343 add_s(plci,HLC,&parms[8]);
1344 CIP = GET_WORD(parms[0].info);
1345 if (a->Info_Mask[appl->Id-1] & 0x200)
1347 /* early B3 connect (CIP mask bit 9) no release after a disc */
1348 add_p(plci,LLI,"\x01\x01");
1350 if(GET_WORD(parms[0].info)<29) {
1351 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355 sig_req(plci,ASSIGN,DSIG_ID);
1359 /* D-Channel used for B3 connections */
1360 plci->Sig.Id = 0xff;
1364 if(!Info && ch!=2 && !noCh ) {
1365 Info = add_b23(plci,&parms[5]);
1367 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1373 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378 plci->spoofed_msg = CALL_REQ;
1379 plci->internal_command = BLOCK_PLCI;
1381 dbug(1,dprintf("Spoof"));
1385 if(ch==4)add_p(plci,CHI,p_chi);
1386 add_s(plci,CPN,&parms[1]);
1387 add_s(plci,DSA,&parms[3]);
1388 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1389 add_ai(plci,&parms[9]);
1390 if(!dir)sig_req(plci,CALL_REQ,0);
1393 plci->command = PERM_LIST_REQ;
1395 sig_req(plci,LISTEN_REQ,0);
1414 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1418 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1421 API_PARSE ai_parms[5];
1425 dbug(1,dprintf("connect_res(no plci)"));
1426 return 0; /* no plci, no send */
1429 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430 for(i=0;i<5;i++) ai_parms[i].length = 0;
1432 dbug(1,dprintf("ai->length=%d",ai->length));
1436 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1438 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1440 if(ai_parms[0].length)
1442 ch = GET_WORD(ai_parms[0].info+1);
1443 dbug(1,dprintf("BCH-I=0x%x",ch));
1448 if(plci->State==INC_CON_CONNECTED_ALERT)
1450 dbug(1,dprintf("Connected Alert Call_Res"));
1451 if (a->Info_Mask[appl->Id-1] & 0x200)
1453 /* early B3 connect (CIP mask bit 9) no release after a disc */
1454 add_p(plci,LLI,"\x01\x01");
1456 add_s(plci, CONN_NR, &parms[2]);
1457 add_s(plci, LLC, &parms[4]);
1458 add_ai(plci, &parms[5]);
1459 plci->State = INC_CON_ACCEPT;
1460 sig_req(plci, CALL_RES,0);
1463 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465 dump_c_ind_mask (plci);
1466 Reject = GET_WORD(parms[0].info);
1467 dbug(1,dprintf("Reject=0x%x",Reject));
1470 if(c_ind_mask_empty (plci))
1472 if((Reject&0xff00)==0x3400)
1474 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475 add_p(plci,ESC,esc_t);
1476 add_ai(plci, &parms[5]);
1477 sig_req(plci,REJECT,0);
1479 else if(Reject==1 || Reject>9)
1481 add_ai(plci, &parms[5]);
1482 sig_req(plci,HANGUP,0);
1486 esc_t[2] = cau_t[(Reject&0x000f)];
1487 add_p(plci,ESC,esc_t);
1488 add_ai(plci, &parms[5]);
1489 sig_req(plci,REJECT,0);
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1500 if(Id & EXT_CONTROLLER){
1501 if(AdvCodecSupport(a, plci, appl, 0)){
1502 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503 sig_req(plci,HANGUP,0);
1506 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508 Info = add_b23(plci, &parms[1]);
1511 dbug(1,dprintf("connect_res(error from add_b23)"));
1512 sig_req(plci,HANGUP,0);
1517 nl_req_ncci(plci, ASSIGN, 0);
1526 Info = add_b23(plci, &parms[1]);
1529 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530 sig_req(plci,HANGUP,0);
1534 nl_req_ncci(plci, ASSIGN, 0);
1537 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1539 api_save_msg(parms, "wsssss", &plci->saved_msg);
1540 plci->spoofed_msg = CALL_RES;
1541 plci->internal_command = BLOCK_PLCI;
1543 dbug(1,dprintf("Spoof"));
1547 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548 if (a->Info_Mask[appl->Id-1] & 0x200)
1550 /* early B3 connect (CIP mask bit 9) no release after a disc */
1551 add_p(plci,LLI,"\x01\x01");
1553 add_s(plci, CONN_NR, &parms[2]);
1554 add_s(plci, LLC, &parms[4]);
1555 add_ai(plci, &parms[5]);
1556 plci->State = INC_CON_ACCEPT;
1557 sig_req(plci, CALL_RES,0);
1560 for(i=0; i<max_appl; i++) {
1561 if(test_c_ind_mask_bit (plci, i)) {
1562 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1570 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1572 dbug(1,dprintf("connect_a_res"));
1576 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1581 dbug(1,dprintf("disconnect_req"));
1583 Info = _WRONG_IDENTIFIER;
1587 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1589 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1591 for(i=0; i<max_appl; i++)
1593 if(test_c_ind_mask_bit (plci, i))
1594 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596 plci->State = OUTG_DIS_PENDING;
1598 if(plci->Sig.Id && plci->appl)
1601 if(plci->Sig.Id!=0xff)
1603 if(plci->State!=INC_DIS_PENDING)
1605 add_ai(plci, &msg[0]);
1606 sig_req(plci,HANGUP,0);
1607 plci->State = OUTG_DIS_PENDING;
1613 if (plci->NL.Id && !plci->nl_remove_id)
1615 mixer_remove (plci);
1616 nl_req_ncci(plci,REMOVE,0);
1617 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619 plci->State = INC_DIS_PENDING;
1626 if(!appl) return false;
1627 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1631 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1633 dbug(1,dprintf("disconnect_res"));
1636 /* clear ind mask bit, just in case of collsion of */
1637 /* DISCONNECT_IND and CONNECT_RES */
1638 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639 ncci_free_receive_buffers (plci, 0);
1640 if(plci_remove_check(plci))
1644 if(plci->State==INC_DIS_PENDING
1645 || plci->State==SUSPENDING) {
1646 if(c_ind_mask_empty (plci)) {
1647 if(plci->State!=SUSPENDING)plci->State = IDLE;
1648 dbug(1,dprintf("chs=%d",plci->channels));
1649 if(!plci->channels) {
1658 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1663 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1665 Info = _WRONG_IDENTIFIER;
1668 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1669 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1670 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1671 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1672 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1675 /* check if external controller listen and switch listen on or off*/
1676 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1677 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1678 dummy_plci.State = IDLE;
1679 a->codec_listen[appl->Id-1] = &dummy_plci;
1680 a->TelOAD[0] = (byte)(parms[3].length);
1681 for(i=1;parms[3].length>=i && i<22;i++) {
1682 a->TelOAD[i] = parms[3].info[i];
1685 a->TelOSA[0] = (byte)(parms[4].length);
1686 for(i=1;parms[4].length>=i && i<22;i++) {
1687 a->TelOSA[i] = parms[4].info[i];
1691 else Info = 0x2002; /* wrong controller, codec not supported */
1693 else{ /* clear listen */
1694 a->codec_listen[appl->Id-1] = (PLCI *)0;
1703 if (a) listen_check(a);
1707 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1711 PLCI * rc_plci = NULL;
1712 API_PARSE ai_parms[5];
1715 dbug(1,dprintf("info_req"));
1716 for(i=0;i<5;i++) ai_parms[i].length = 0;
1722 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1724 dbug(1,dprintf("AddInfo wrong"));
1725 Info = _WRONG_MESSAGE_FORMAT;
1728 if(!a) Info = _WRONG_STATE;
1731 { /* no fac, with CPN, or KEY */
1733 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1735 /* overlap sending option */
1736 dbug(1,dprintf("OvlSnd"));
1737 add_s(plci,CPN,&msg[0]);
1738 add_s(plci,KEY,&ai_parms[1]);
1739 sig_req(plci,INFO_REQ,0);
1744 if(plci->State && ai_parms[2].length)
1746 /* User_Info option */
1747 dbug(1,dprintf("UUI"));
1748 add_s(plci,UUI,&ai_parms[2]);
1749 sig_req(plci,USER_DATA,0);
1751 else if(plci->State && ai_parms[3].length)
1753 /* Facility option */
1754 dbug(1,dprintf("FAC"));
1755 add_s(plci,CPN,&msg[0]);
1756 add_ai(plci, &msg[1]);
1757 sig_req(plci,FACILITY_REQ,0);
1761 Info = _WRONG_STATE;
1764 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766 /* NCR_Facility option -> send UUI and Keypad too */
1767 dbug(1,dprintf("NCR_FAC"));
1770 rc_plci = &a->plci[i-1];
1771 appl->NullCREnable = true;
1772 rc_plci->internal_command = C_NCR_FAC_REQ;
1773 rc_plci->appl = appl;
1774 add_p(rc_plci,CAI,"\x01\x80");
1775 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776 sig_req(rc_plci,ASSIGN,DSIG_ID);
1781 Info = _OUT_OF_PLCI;
1786 add_s(rc_plci,CPN,&msg[0]);
1787 add_ai(rc_plci, &msg[1]);
1788 sig_req(rc_plci,NCR_FACILITY,0);
1791 /* for application controlled supplementary services */
1797 Info = _WRONG_MESSAGE_FORMAT;
1805 { /* appl is not assigned to a PLCI or error condition */
1806 dbug(1,dprintf("localInfoCon"));
1816 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1818 dbug(1,dprintf("info_res"));
1822 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1827 dbug(1,dprintf("alert_req"));
1829 Info = _WRONG_IDENTIFIER;
1832 Info = _ALERT_IGNORED;
1833 if(plci->State!=INC_CON_ALERT) {
1834 Info = _WRONG_STATE;
1835 if(plci->State==INC_CON_PENDING) {
1837 plci->State=INC_CON_ALERT;
1838 add_ai(plci, &msg[0]);
1839 sig_req(plci,CALL_ALERT,0);
1852 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1859 long relatedPLCIvalue;
1860 DIVA_CAPI_ADAPTER * relatedadapter;
1861 byte * SSparms = "";
1862 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1863 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1865 API_PARSE ss_parms[11];
1871 dbug(1,dprintf("facility_req"));
1872 for(i=0;i<9;i++) ss_parms[i].length = 0;
1878 dbug(1,dprintf("wrong Ctrl"));
1879 Info = _WRONG_IDENTIFIER;
1882 selector = GET_WORD(msg[0].info);
1888 case SELECTOR_HANDSET:
1889 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1892 case SELECTOR_SU_SERV:
1895 Info = _WRONG_MESSAGE_FORMAT;
1898 SSreq = GET_WORD(&(msg[1].info[1]));
1899 PUT_WORD(&RCparms[1],SSreq);
1903 case S_GET_SUPPORTED_SERVICES:
1906 rplci = &a->plci[i-1];
1908 add_p(rplci,CAI,"\x01\x80");
1909 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910 sig_req(rplci,ASSIGN,DSIG_ID);
1915 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916 SSparms = (byte *)SSstruct;
1919 rplci->internal_command = GETSERV_REQ_PEND;
1920 rplci->number = Number;
1922 sig_req(rplci,S_SUPPORTED,0);
1928 if(parms->length==7)
1930 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1932 dbug(1,dprintf("format wrong"));
1933 Info = _WRONG_MESSAGE_FORMAT;
1939 Info = _WRONG_MESSAGE_FORMAT;
1942 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1947 rplci = &a->plci[i-1];
1949 add_p(rplci,CAI,"\x01\x80");
1950 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951 sig_req(rplci,ASSIGN,DSIG_ID);
1958 rplci->internal_command = GET_MWI_STATE;
1959 rplci->number = Number;
1960 sig_req(rplci,MWI_POLL,0);
1966 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967 if(plci && plci->State && plci->SuppState==IDLE)
1969 plci->SuppState = HOLD_REQUEST;
1970 plci->command = C_HOLD_REQ;
1971 add_s(plci,CAI,&ss_parms[1]);
1972 sig_req(plci,CALL_HOLD,0);
1976 else Info = 0x3010; /* wrong state */
1979 if(plci && plci->State && plci->SuppState==CALL_HELD)
1981 if(Id & EXT_CONTROLLER)
1983 if(AdvCodecSupport(a, plci, appl, 0))
1985 Info = 0x3010; /* wrong state */
1991 plci->SuppState = RETRIEVE_REQUEST;
1992 plci->command = C_RETRIEVE_REQ;
1993 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1995 plci->spoofed_msg = CALL_RETRIEVE;
1996 plci->internal_command = BLOCK_PLCI;
1998 dbug(1,dprintf("Spoof"));
2003 sig_req(plci,CALL_RETRIEVE,0);
2008 else Info = 0x3010; /* wrong state */
2013 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2015 dbug(1,dprintf("format wrong"));
2016 Info = _WRONG_MESSAGE_FORMAT;
2020 if(plci && plci->State)
2022 add_s(plci,CAI,&ss_parms[2]);
2023 plci->command = SUSPEND_REQ;
2024 sig_req(plci,SUSPEND,0);
2025 plci->State = SUSPENDING;
2028 else Info = 0x3010; /* wrong state */
2032 if(!(i=get_plci(a)) )
2034 Info = _OUT_OF_PLCI;
2037 rplci = &a->plci[i-1];
2039 rplci->number = Number;
2041 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042 /* check 'external controller' bit for codec support */
2043 if(Id & EXT_CONTROLLER)
2045 if(AdvCodecSupport(a, rplci, appl, 0) )
2054 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2056 dbug(1,dprintf("format wrong"));
2058 Info = _WRONG_MESSAGE_FORMAT;
2063 dummy.info = "\x00";
2064 add_b1(rplci, &dummy, 0, 0);
2065 if (a->Info_Mask[appl->Id-1] & 0x200)
2067 /* early B3 connect (CIP mask bit 9) no release after a disc */
2068 add_p(rplci,LLI,"\x01\x01");
2070 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071 sig_req(rplci,ASSIGN,DSIG_ID);
2073 add_s(rplci,CAI,&ss_parms[2]);
2074 rplci->command = RESUME_REQ;
2075 sig_req(rplci,RESUME,0);
2076 rplci->State = RESUMING;
2080 case S_CONF_BEGIN: /* Request */
2082 case S_CONF_ISOLATE:
2083 case S_CONF_REATTACH:
2084 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2086 dbug(1,dprintf("format wrong"));
2087 Info = _WRONG_MESSAGE_FORMAT;
2090 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2092 d = GET_DWORD(ss_parms[2].info);
2095 dbug(1,dprintf("format wrong"));
2096 Info = _WRONG_MESSAGE_FORMAT;
2099 plci->ptyState = (byte)SSreq;
2105 cai[1] = CONF_BEGIN;
2106 plci->internal_command = CONF_BEGIN_REQ_PEND;
2110 plci->internal_command = CONF_DROP_REQ_PEND;
2112 case S_CONF_ISOLATE:
2113 cai[1] = CONF_ISOLATE;
2114 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2116 case S_CONF_REATTACH:
2117 cai[1] = CONF_REATTACH;
2118 plci->internal_command = CONF_REATTACH_REQ_PEND;
2121 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122 add_p(plci,CAI,cai);
2123 sig_req(plci,S_SERVICE,0);
2127 else Info = 0x3010; /* wrong state */
2134 if(parms->length==7)
2136 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2138 dbug(1,dprintf("format wrong"));
2139 Info = _WRONG_MESSAGE_FORMAT;
2143 else if(parms->length==8) /* workaround for the T-View-S */
2145 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2147 dbug(1,dprintf("format wrong"));
2148 Info = _WRONG_MESSAGE_FORMAT;
2154 Info = _WRONG_MESSAGE_FORMAT;
2159 Info = _WRONG_MESSAGE_FORMAT;
2164 Info = _WRONG_IDENTIFIER;
2167 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168 relatedPLCIvalue &= 0x0000FFFF;
2169 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170 /* controller starts with 0 up to (max_adapter - 1) */
2171 if (((relatedPLCIvalue & 0x7f) == 0)
2172 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2175 if(SSreq==S_3PTY_END)
2177 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2182 Info = 0x3010; /* wrong state */
2188 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189 relatedPLCIvalue >>=8;
2191 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2193 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2195 rplci = &relatedadapter->plci[i];
2198 if(!rplci || !relatedPLCIvalue)
2200 if(SSreq==S_3PTY_END)
2202 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2207 Info = 0x3010; /* wrong state */
2213 dbug(1,dprintf("rplci:%x",rplci));
2214 dbug(1,dprintf("plci:%x",plci));
2215 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217 dbug(1,dprintf("SSreq:%x",SSreq));
2218 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2222 /* send PTY/ECT req, cannot check all states because of US stuff */
2223 if( !rplci->internal_command && rplci->appl )
2226 rplci->relatedPTYPLCI = plci;
2227 plci->relatedPTYPLCI = rplci;
2228 rplci->ptyState = (byte)SSreq;
2231 rplci->internal_command = ECT_REQ_PEND;
2232 cai[1] = ECT_EXECUTE;
2234 rplci->vswitchstate=0;
2236 rplci->vsprotdialect=0;
2237 plci->vswitchstate=0;
2239 plci->vsprotdialect=0;
2242 else if(SSreq==S_CONF_ADD)
2244 rplci->internal_command = CONF_ADD_REQ_PEND;
2249 rplci->internal_command = PTY_REQ_PEND;
2250 cai[1] = (byte)(SSreq-3);
2252 rplci->number = Number;
2253 if(plci!=rplci) /* explicit invocation */
2256 cai[2] = plci->Sig.Id;
2257 dbug(1,dprintf("explicit invocation"));
2261 dbug(1,dprintf("implicit invocation"));
2264 add_p(rplci,CAI,cai);
2265 sig_req(rplci,S_SERVICE,0);
2271 dbug(0,dprintf("Wrong line"));
2272 Info = 0x3010; /* wrong state */
2277 case S_CALL_DEFLECTION:
2278 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2280 dbug(1,dprintf("format wrong"));
2281 Info = _WRONG_MESSAGE_FORMAT;
2286 Info = _WRONG_IDENTIFIER;
2289 /* reuse unused screening indicator */
2290 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2292 plci->internal_command = CD_REQ_PEND;
2293 appl->CDEnable = true;
2295 cai[1] = CALL_DEFLECTION;
2296 add_p(plci,CAI,cai);
2297 add_p(plci,CPN,ss_parms[3].info);
2298 sig_req(plci,S_SERVICE,0);
2303 case S_CALL_FORWARDING_START:
2304 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2306 dbug(1,dprintf("format wrong"));
2307 Info = _WRONG_MESSAGE_FORMAT;
2313 rplci = &a->plci[i-1];
2315 add_p(rplci,CAI,"\x01\x80");
2316 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317 sig_req(rplci,ASSIGN,DSIG_ID);
2322 Info = _OUT_OF_PLCI;
2326 /* reuse unused screening indicator */
2327 rplci->internal_command = CF_START_PEND;
2329 rplci->number = Number;
2330 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2332 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334 add_p(rplci,CAI,cai);
2335 add_p(rplci,OAD,ss_parms[5].info);
2336 add_p(rplci,CPN,ss_parms[6].info);
2337 sig_req(rplci,S_SERVICE,0);
2342 case S_INTERROGATE_DIVERSION:
2343 case S_INTERROGATE_NUMBERS:
2344 case S_CALL_FORWARDING_STOP:
2345 case S_CCBS_REQUEST:
2346 case S_CCBS_DEACTIVATE:
2347 case S_CCBS_INTERROGATE:
2350 case S_INTERROGATE_NUMBERS:
2351 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2353 dbug(0,dprintf("format wrong"));
2354 Info = _WRONG_MESSAGE_FORMAT;
2357 case S_CCBS_REQUEST:
2358 case S_CCBS_DEACTIVATE:
2359 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2361 dbug(0,dprintf("format wrong"));
2362 Info = _WRONG_MESSAGE_FORMAT;
2365 case S_CCBS_INTERROGATE:
2366 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2368 dbug(0,dprintf("format wrong"));
2369 Info = _WRONG_MESSAGE_FORMAT;
2373 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2375 dbug(0,dprintf("format wrong"));
2376 Info = _WRONG_MESSAGE_FORMAT;
2385 rplci = &a->plci[i-1];
2388 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2392 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2396 case S_CALL_FORWARDING_STOP:
2397 rplci->internal_command = CF_STOP_PEND;
2398 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400 case S_CCBS_REQUEST:
2401 cai[1] = CCBS_REQUEST;
2402 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2404 case S_CCBS_DEACTIVATE:
2405 cai[1] = CCBS_DEACTIVATE;
2406 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2408 case S_CCBS_INTERROGATE:
2409 cai[1] = CCBS_INTERROGATE;
2410 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2417 rplci->number = Number;
2418 add_p(rplci,CAI,"\x01\x80");
2419 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420 sig_req(rplci,ASSIGN,DSIG_ID);
2425 Info = _OUT_OF_PLCI;
2429 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2432 case S_INTERROGATE_NUMBERS:
2434 add_p(rplci,CAI,cai);
2436 case S_CCBS_REQUEST:
2437 case S_CCBS_DEACTIVATE:
2439 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440 add_p(rplci,CAI,cai);
2442 case S_CCBS_INTERROGATE:
2444 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445 add_p(rplci,CAI,cai);
2446 add_p(rplci,OAD,ss_parms[4].info);
2450 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451 add_p(rplci,CAI,cai);
2452 add_p(rplci,OAD,ss_parms[5].info);
2456 sig_req(rplci,S_SERVICE,0);
2461 case S_MWI_ACTIVATE:
2462 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2464 dbug(1,dprintf("format wrong"));
2465 Info = _WRONG_MESSAGE_FORMAT;
2472 rplci = &a->plci[i-1];
2474 rplci->cr_enquiry=true;
2475 add_p(rplci,CAI,"\x01\x80");
2476 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477 sig_req(rplci,ASSIGN,DSIG_ID);
2482 Info = _OUT_OF_PLCI;
2489 rplci->cr_enquiry=false;
2493 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2495 rplci->number = Number;
2498 cai[1] = ACTIVATION_MWI; /* Function */
2499 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504 add_p(rplci,CAI,cai);
2505 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508 add_p(rplci,UID,ss_parms[10].info); /* Time */
2509 sig_req(rplci,S_SERVICE,0);
2513 case S_MWI_DEACTIVATE:
2514 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2516 dbug(1,dprintf("format wrong"));
2517 Info = _WRONG_MESSAGE_FORMAT;
2524 rplci = &a->plci[i-1];
2526 rplci->cr_enquiry=true;
2527 add_p(rplci,CAI,"\x01\x80");
2528 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529 sig_req(rplci,ASSIGN,DSIG_ID);
2534 Info = _OUT_OF_PLCI;
2541 rplci->cr_enquiry=false;
2545 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2547 rplci->number = Number;
2550 cai[1] = DEACTIVATION_MWI; /* Function */
2551 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553 add_p(rplci,CAI,cai);
2554 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556 sig_req(rplci,S_SERVICE,0);
2561 Info = 0x300E; /* not supported */
2564 break; /* case SELECTOR_SU_SERV: end */
2568 return (dtmf_request (Id, Number, a, plci, appl, msg));
2572 case SELECTOR_LINE_INTERCONNECT:
2573 return (mixer_request (Id, Number, a, plci, appl, msg));
2577 case PRIV_SELECTOR_ECHO_CANCELLER:
2578 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579 return (ec_request (Id, Number, a, plci, appl, msg));
2581 case SELECTOR_ECHO_CANCELLER:
2582 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583 return (ec_request (Id, Number, a, plci, appl, msg));
2586 case SELECTOR_V42BIS:
2588 Info = _FACILITY_NOT_SUPPORTED;
2590 } /* end of switch(selector) */
2593 dbug(1,dprintf("SendFacRc"));
2595 _FACILITY_R|CONFIRM,
2598 "wws",Info,selector,SSparms);
2602 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2604 dbug(1,dprintf("facility_res"));
2608 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2614 word fax_control_bits, fax_feature_bits, fax_info_change;
2618 API_PARSE fax_parms[9];
2622 dbug(1,dprintf("connect_b3_req"));
2625 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2628 Info = _WRONG_STATE;
2632 /* local reply if assign unsuccessfull
2633 or B3 protocol allows only one layer 3 connection
2634 and already connected
2635 or B2 protocol not any LAPD
2636 and connect_b3_req contradicts originate/answer direction */
2638 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639 && ((plci->channels != 0)
2640 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2643 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645 Info = _WRONG_STATE;
2647 _CONNECT_B3_R|CONFIRM,
2653 plci->requested_options_conn = 0;
2657 if(plci->B3_prot==2 || plci->B3_prot==3)
2662 if(ncpi->info[2] || ncpi->info[3])
2664 pvc[0] = ncpi->info[3];
2665 pvc[1] = ncpi->info[2];
2671 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2676 else if(plci->B3_prot==5)
2678 if (plci->NL.Id && !plci->nl_remove_id)
2680 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2681 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2682 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2685 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2686 fax_info_change = false;
2687 if (ncpi->length >= 4)
2689 w = GET_WORD(&ncpi->info[3]);
2690 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2692 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2693 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2695 fax_info_change = true;
2697 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698 if (w & 0x0002) /* Fax-polling request */
2699 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700 if ((w & 0x0004) /* Request to send / poll another document */
2701 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2703 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2705 if (ncpi->length >= 6)
2707 w = GET_WORD(&ncpi->info[5]);
2708 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2710 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2711 fax_info_change = true;
2714 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2717 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2719 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2722 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2724 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2729 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730 Info = _WRONG_MESSAGE_FORMAT;
2733 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2736 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2740 w = fax_parms[4].length;
2743 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744 for (i = 0; i < w; i++)
2745 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2748 w = fax_parms[5].length;
2751 plci->fax_connect_info_buffer[len++] = (byte) w;
2752 for (i = 0; i < w; i++)
2753 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754 w = fax_parms[6].length;
2757 plci->fax_connect_info_buffer[len++] = (byte) w;
2758 for (i = 0; i < w; i++)
2759 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2760 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761 & (1L << PRIVATE_FAX_NONSTANDARD))
2763 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2765 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766 plci->fax_connect_info_buffer[len++] = 0;
2770 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773 for (i = 0; i < fax_parms[7].length; i++)
2774 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2781 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2783 fax_info_change = true;
2786 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2788 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2789 fax_info_change = true;
2794 plci->fax_connect_info_length = len;
2795 if (fax_info_change)
2797 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2799 start_internal_command (Id, plci, fax_connect_info_command);
2804 start_internal_command (Id, plci, fax_adjust_b23_command);
2810 else Info = _WRONG_STATE;
2812 else Info = _WRONG_STATE;
2815 else if (plci->B3_prot == B3_RTP)
2817 plci->internal_req_buffer[0] = ncpi->length + 1;
2818 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819 for (w = 0; w < ncpi->length; w++)
2820 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2827 nl_req_ncci(plci,req,0);
2832 else Info = _WRONG_IDENTIFIER;
2835 _CONNECT_B3_R|CONFIRM,
2842 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2851 API_PARSE fax_parms[9];
2856 dbug(1,dprintf("connect_b3_res"));
2858 ncci = (word)(Id>>16);
2860 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861 if (GET_WORD (&parms[0].info[0]) != 0)
2863 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864 channel_request_xon (plci, a->ncci_ch[ncci]);
2865 channel_xmit_xon (plci);
2866 cleanup_ncci_data (plci, ncci);
2867 nl_req_ncci(plci,N_DISC,(byte)ncci);
2870 a->ncci_state[ncci] = INC_ACT_PENDING;
2872 req = N_CONNECT_ACK;
2874 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2877 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878 & (1L << PRIVATE_FAX_NONSTANDARD))
2880 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2884 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2885 if (plci->fax_connect_info_length < len)
2887 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2890 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2892 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2896 if (plci->fax_connect_info_length <= len)
2897 plci->fax_connect_info_buffer[len] = 0;
2898 len += 1 + plci->fax_connect_info_buffer[len];
2899 if (plci->fax_connect_info_length <= len)
2900 plci->fax_connect_info_buffer[len] = 0;
2901 len += 1 + plci->fax_connect_info_buffer[len];
2902 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905 for (i = 0; i < fax_parms[7].length; i++)
2906 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2908 plci->fax_connect_info_length = len;
2909 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910 start_internal_command (Id, plci, fax_connect_ack_command);
2915 nl_req_ncci(plci,req,(byte)ncci);
2916 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2919 if (plci->B3_prot == 4)
2920 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2922 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2927 else if (plci->B3_prot == B3_RTP)
2929 plci->internal_req_buffer[0] = ncpi->length + 1;
2930 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931 for (w = 0; w < ncpi->length; w++)
2932 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2939 if(ncpi->length>2) {
2940 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2943 nl_req_ncci(plci,req,(byte)ncci);
2944 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945 if (plci->adjust_b_restore)
2947 plci->adjust_b_restore = false;
2948 start_internal_command (Id, plci, adjust_b_restore);
2957 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2961 ncci = (word)(Id>>16);
2962 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2964 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965 && (plci->State != OUTG_DIS_PENDING))
2967 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968 a->ncci_state[ncci] = CONNECTED;
2969 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970 channel_request_xon (plci, a->ncci_ch[ncci]);
2971 channel_xmit_xon (plci);
2977 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2983 dbug(1,dprintf("disconnect_b3_req"));
2985 Info = _WRONG_IDENTIFIER;
2986 ncci = (word)(Id>>16);
2989 Info = _WRONG_STATE;
2990 if ((a->ncci_state[ncci] == CONNECTED)
2991 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992 || (a->ncci_state[ncci] == INC_CON_PENDING)
2993 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2995 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996 channel_request_xon (plci, a->ncci_ch[ncci]);
2997 channel_xmit_xon (plci);
2999 if (a->ncci[ncci].data_pending
3000 && ((plci->B3_prot == B3_TRANSPARENT)
3001 || (plci->B3_prot == B3_T30)
3002 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3004 plci->send_disc = (byte)ncci;
3010 cleanup_ncci_data (plci, ncci);
3012 if(plci->B3_prot==2 || plci->B3_prot==3)
3017 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3020 nl_req_ncci(plci,N_DISC,(byte)ncci);
3026 _DISCONNECT_B3_R|CONFIRM,
3033 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3038 ncci = (word)(Id>>16);
3039 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3041 plci->requested_options_conn = 0;
3042 plci->fax_connect_info_length = 0;
3043 plci->ncpi_state = 0x00;
3044 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3047 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3049 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050 if(i<MAX_CHANNELS_PER_PLCI) {
3051 if(plci->channels)plci->channels--;
3052 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3055 ncci_free_receive_buffers (plci, ncci);
3057 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058 if(plci->State == SUSPENDING){
3063 "ws", (word)3, "\x03\x04\x00\x00");
3064 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3072 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3076 ncci_free_receive_buffers (plci, ncci);
3078 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3080 plci->adapter->ncci_state[ncci] = IDLE;
3081 start_internal_command (Id, plci, fax_disconnect_command);
3089 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3097 dbug(1,dprintf("data_b3_req"));
3099 Info = _WRONG_IDENTIFIER;
3100 ncci = (word)(Id>>16);
3101 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3105 Info = _WRONG_STATE;
3106 if ((a->ncci_state[ncci] == CONNECTED)
3107 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3110 ncci_ptr = &(a->ncci[ncci]);
3111 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112 if (i >= MAX_DATA_B3)
3114 data = &(ncci_ptr->DBuffer[i]);
3115 data->Number = Number;
3116 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3117 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3120 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3124 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125 data->Length = GET_WORD(parms[1].info);
3126 data->Handle = GET_WORD(parms[2].info);
3127 data->Flags = GET_WORD(parms[3].info);
3128 (ncci_ptr->data_pending)++;
3130 /* check for delivery confirmation */
3131 if (data->Flags & 0x0004)
3133 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134 if (i >= MAX_DATA_ACK)
3136 ncci_ptr->DataAck[i].Number = data->Number;
3137 ncci_ptr->DataAck[i].Handle = data->Handle;
3138 (ncci_ptr->data_ack_pending)++;
3149 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3150 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3153 TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3161 "ww",GET_WORD(parms[2].info),Info);
3166 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3172 dbug(1,dprintf("data_b3_res"));
3174 ncci = (word)(Id>>16);
3176 n = GET_WORD(parms[0].info);
3177 dbug(1,dprintf("free(%d)",n));
3178 NCCIcode = ncci | (((word) a->Id) << 8);
3179 if(n<appl->MaxBuffer &&
3180 appl->DataNCCI[n]==NCCIcode &&
3181 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182 dbug(1,dprintf("found"));
3183 appl->DataNCCI[n] = 0;
3185 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186 channel_request_xon (plci, a->ncci_ch[ncci]);
3188 channel_xmit_xon (plci);
3190 if(appl->DataFlags[n] &4) {
3191 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3199 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3204 dbug(1,dprintf("reset_b3_req"));
3206 Info = _WRONG_IDENTIFIER;
3207 ncci = (word)(Id>>16);
3210 Info = _WRONG_STATE;
3211 switch (plci->B3_prot)
3215 if(a->ncci_state[ncci]==CONNECTED)
3217 nl_req_ncci(plci,N_RESET,(byte)ncci);
3222 case B3_TRANSPARENT:
3223 if(a->ncci_state[ncci]==CONNECTED)
3225 start_internal_command (Id, plci, reset_b3_command);
3231 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3233 _RESET_B3_R|CONFIRM,
3240 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3244 dbug(1,dprintf("reset_b3_res"));
3246 ncci = (word)(Id>>16);
3248 switch (plci->B3_prot)
3252 if(a->ncci_state[ncci]==INC_RES_PENDING)
3254 a->ncci_state[ncci] = CONNECTED;
3255 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3264 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3270 dbug(1,dprintf("connect_b3_t90_a_res"));
3272 ncci = (word)(Id>>16);
3274 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275 a->ncci_state[ncci] = CONNECTED;
3277 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278 a->ncci_state[ncci] = CONNECTED;
3280 req = N_CONNECT_ACK;
3282 /* parms[0]==0 for CAPI original message definition! */
3285 if(ncpi->length>2) {
3286 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3290 nl_req_ncci(plci,req,(byte)ncci);
3298 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3303 API_PARSE bp_parms[7];
3307 Info = _WRONG_IDENTIFIER;
3311 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313 dbug(1,dprintf("PlciState=0x%x",plci->State));
3314 for(i=0;i<7;i++) bp_parms[i].length = 0;
3316 /* check if no channel is open, no B3 connected only */
3317 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3320 Info = _WRONG_STATE;
3322 /* check message format and fill bp_parms pointer */
3323 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3325 Info = _WRONG_MESSAGE_FORMAT;
3329 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331 if(Id & EXT_CONTROLLER)
3333 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3336 plci->State=INC_CON_CONNECTED_ALERT;
3338 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339 dump_c_ind_mask (plci);
3340 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341 { /* its quasi a connect */
3342 if(test_c_ind_mask_bit (plci, i))
3343 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3347 api_save_msg(msg, "s", &plci->saved_msg);
3349 if(Id & EXT_CONTROLLER)
3351 if(tel) /* external controller in use by this PLCI */
3353 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3355 dbug(1,dprintf("Ext_Ctrl in use 1"));
3356 Info = _WRONG_STATE;
3359 else /* external controller NOT in use by this PLCI ? */
3361 if(a->AdvSignalPLCI)
3363 dbug(1,dprintf("Ext_Ctrl in use 2"));
3364 Info = _WRONG_STATE;
3366 else /* activate the codec */
3368 dbug(1,dprintf("Ext_Ctrl start"));
3369 if(AdvCodecSupport(a, plci, appl, 0) )
3371 dbug(1,dprintf("Error in codec procedures"));
3372 Info = _WRONG_STATE;
3374 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3376 plci->spoofed_msg = AWAITING_SELECT_B;
3377 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3379 dbug(1,dprintf("continue if codec loaded"));
3385 else /* external controller bit is OFF */
3387 if(tel) /* external controller in use, need to switch off */
3389 if(a->AdvSignalAppl==appl)
3391 CodecIdCheck(a, plci);
3394 dbug(1,dprintf("Ext_Ctrl disable"));
3398 dbug(1,dprintf("Ext_Ctrl not requested"));
3404 if (plci->call_dir & CALL_DIR_OUT)
3405 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406 else if (plci->call_dir & CALL_DIR_IN)
3407 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408 start_internal_command (Id, plci, select_b_command);
3413 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3417 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3418 PLCI *plci, APPL *appl, API_PARSE *parms)
3424 API_PARSE m_parms[5];
3429 static byte chi[2] = {0x01,0x00};
3430 static byte lli[2] = {0x01,0x00};
3431 static byte codec_cai[2] = {0x01,0x01};
3432 static byte null_msg = {0};
3433 static API_PARSE null_parms = { 0, &null_msg };
3437 dbug(1,dprintf("manufacturer_req"));
3438 for(i=0;i<5;i++) m_parms[i].length = 0;
3440 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441 Info = _WRONG_MESSAGE_FORMAT;
3443 command = GET_WORD(parms[1].info);
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
3453 codec = GET_WORD(m_parms[0].info);
3454 ch = m_parms[1].info[0];
3455 dir = m_parms[2].info[0];
3456 if((i=get_plci(a))) {
3457 plci = &a->plci[i-1];
3459 plci->command = _MANUFACTURER_R;
3460 plci->m_command = command;
3461 plci->number = Number;
3462 plci->State = LOCAL_CONNECT;
3463 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3466 if((ch==1 || ch==2) && (dir<=2)) {
3467 chi[1] = (byte)(0x80|ch);
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3473 Info = add_b1(plci,&m_parms[3],0,0);
3476 add_p(plci,CAI,codec_cai);
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3491 plci->State = LOCAL_CONNECT;
3492 plci->manufacturer = true;
3493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
3499 add_p(plci,LLI,lli);
3500 add_p(plci,CHI,chi);
3501 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502 sig_req(plci,ASSIGN,DSIG_ID);
3506 Info = add_b23(plci,&m_parms[3]);
3509 nl_req_ncci(plci,ASSIGN,0);
3515 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3518 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519 plci->spoofed_msg = AWAITING_MANUF_CON;
3520 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3526 sig_req(plci,CALL_REQ,0);
3529 sig_req(plci,LISTEN_REQ,0);
3536 _MANUFACTURER_R|CONFIRM,
3539 "dww",_DI_MANU_ID,command,Info);
3545 else Info = _OUT_OF_PLCI;
3551 Info = _WRONG_IDENTIFIER;
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
3564 plci->b_channel = getChannel(&m_parms[1]);
3565 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3568 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3574 else if(req==LAW_REQ)
3576 plci->cr_enquiry = true;
3578 add_ss(plci,FTY,&m_parms[1]);
3579 sig_req(plci,req,0);
3583 if (plci->NL.Id && !plci->nl_remove_id)
3587 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3589 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3591 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592 cleanup_ncci_data (plci, ncci);
3593 nl_req_ncci(plci,N_DISC,(byte)ncci);
3597 mixer_remove (plci);
3598 nl_req_ncci(plci,REMOVE,0);
3605 /* signalling control for loop activation B-channel */
3608 Info = _WRONG_IDENTIFIER;
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3615 sig_req(plci,SIG_CTRL,0);
3618 else Info = _WRONG_MESSAGE_FORMAT;
3622 /* activation control for receiver/transmitter B-channel */
3625 Info = _WRONG_IDENTIFIER;
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3632 sig_req(plci,DSP_CTRL,0);
3635 else Info = _WRONG_MESSAGE_FORMAT;
3640 /* TEL_CTRL commands to support non standard adjustments: */
3641 /* Ring on/off, Handset micro volume, external micro vol. */
3642 /* handset+external speaker volume, receiver+transm. gain,*/
3643 /* handsfree on (hookinfo off), set mixer command */
3645 if(command == _DI_ADV_CODEC)
3647 if(!a->AdvCodecPLCI) {
3648 Info = _WRONG_STATE;
3651 v_plci = a->AdvCodecPLCI;
3657 && (m->info[1] == 0x1c)
3658 && (m->info[2] >= 1))
3660 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3662 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3664 Info = _WRONG_STATE;
3667 a->adv_voice_coef_length = m->info[2] - 1;
3668 if (a->adv_voice_coef_length > m->length - 3)
3669 a->adv_voice_coef_length = (byte)(m->length - 3);
3670 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672 for (i = 0; i < a->adv_voice_coef_length; i++)
3673 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674 if (plci->B1_facilities & B1_FACILITY_VOICE)
3675 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3678 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3680 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3682 Info = _FACILITY_NOT_SUPPORTED;
3686 plci->dtmf_parameter_length = m->info[2] - 1;
3687 if (plci->dtmf_parameter_length > m->length - 3)
3688 plci->dtmf_parameter_length = (byte)(m->length - 3);
3689 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691 for (i = 0; i < plci->dtmf_parameter_length; i++)
3692 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694 dtmf_parameter_write (plci);
3704 Info = _WRONG_IDENTIFIER;
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3712 else Info = _WRONG_MESSAGE_FORMAT;
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3723 Info = _FACILITY_NOT_SUPPORTED;
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3732 Info = _WRONG_MESSAGE_FORMAT;
3738 _MANUFACTURER_R|CONFIRM,
3741 "dww",_DI_MANU_ID,command,Info);
3746 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3747 PLCI *plci, APPL *appl, API_PARSE *msg)
3751 API_PARSE m_parms[3];
3753 API_PARSE fax_parms[9];
3758 dbug(1,dprintf("manufacturer_res"));
3760 if ((msg[0].length == 0)
3761 || (msg[1].length == 0)
3762 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3766 indication = GET_WORD(msg[1].info);
3770 case _DI_NEGOTIATE_B3:
3773 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3774 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3776 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3779 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3781 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3785 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3786 if (plci->fax_connect_info_length < len)
3788 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3789 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3791 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3793 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3797 if (plci->fax_connect_info_length <= len)
3798 plci->fax_connect_info_buffer[len] = 0;
3799 len += 1 + plci->fax_connect_info_buffer[len];
3800 if (plci->fax_connect_info_length <= len)
3801 plci->fax_connect_info_buffer[len] = 0;
3802 len += 1 + plci->fax_connect_info_buffer[len];
3803 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3804 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3805 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3806 for (i = 0; i < fax_parms[7].length; i++)
3807 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3809 plci->fax_connect_info_length = len;
3810 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3811 start_internal_command (Id, plci, fax_edata_ack_command);
3818 /*------------------------------------------------------------------*/
3819 /* IDI callback function */
3820 /*------------------------------------------------------------------*/
3822 void callback(ENTITY * e)
3824 DIVA_CAPI_ADAPTER * a;
3835 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3836 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3838 a = &(adapter[(byte)e->user[0]]);
3839 plci = &(a->plci[e->user[1]]);
3840 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3843 If new protocol code and new XDI is used then CAPI should work
3844 fully in accordance with IDI cpec an look on callback field instead
3845 of Rc field for return codes.
3847 if (((e->complete == 0xff) && no_cancel_rc) ||
3848 (e->Rc && !no_cancel_rc)) {
3854 if (e->user[0] & 0x8000)
3857 If REMOVE request was sent then we have to wait until
3858 return code with Id set to zero arrives.
3859 All other return codes should be ignored.
3865 dbug(1,dprintf("cancel RC in REMOVE state"));
3868 channel_flow_control_remove (plci);
3869 for (i = 0; i < 256; i++)
3871 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3872 a->FlowControlIdTable[i] = 0;
3874 plci->nl_remove_id = 0;
3875 if (plci->rx_dma_descriptor > 0) {
3876 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3877 plci->rx_dma_descriptor = 0;
3882 a->FlowControlIdTable[ch] = e->Id;
3883 a->FlowControlSkipTable[ch] = 0;
3885 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3886 a->ch_flow_plci[ch] = plci->Id;
3892 Cancel return codes self, if feature was requested
3894 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3895 a->FlowControlIdTable[ch] = 0;
3896 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3897 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3902 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3904 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3912 control_rc (plci, 0, rc, ch, 0, true);
3917 channel_x_on (plci, ch);
3918 if (plci->internal_command)
3919 control_rc (plci, req, rc, ch, 0, true);
3923 if (plci->nl_global_req)
3925 global_req = plci->nl_global_req;
3926 plci->nl_global_req = 0;
3927 if (rc != ASSIGN_OK) {
3929 if (plci->rx_dma_descriptor > 0) {
3930 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3931 plci->rx_dma_descriptor = 0;
3934 channel_xmit_xon (plci);
3935 control_rc (plci, 0, rc, ch, global_req, true);
3937 else if (plci->data_sent)
3939 channel_xmit_xon (plci);
3940 plci->data_sent = false;
3943 if (plci->internal_command)
3944 control_rc (plci, req, rc, ch, 0, true);
3948 channel_xmit_xon (plci);
3949 control_rc (plci, req, rc, ch, 0, true);
3957 If REMOVE request was sent then we have to wait until
3958 return code with Id set to zero arrives.
3959 All other return codes should be ignored.
3965 dbug(1,dprintf("cancel RC in REMOVE state"));
3968 plci->sig_remove_id = 0;
3971 if (plci->sig_global_req)
3973 global_req = plci->sig_global_req;
3974 plci->sig_global_req = 0;
3975 if (rc != ASSIGN_OK)
3977 channel_xmit_xon (plci);
3978 control_rc (plci, 0, rc, ch, global_req, false);
3982 channel_xmit_xon (plci);
3983 control_rc (plci, req, rc, ch, 0, false);
3987 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3988 same callback. Also if new XDI and protocol code used then jump
3992 channel_xmit_xon(plci);
3993 goto capi_callback_suffix;
3997 channel_xmit_xon(plci);
4000 if (e->user[0] &0x8000) {
4001 byte Ind = e->Ind & 0x0f;
4003 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4004 (a->ch_flow_plci[Ch] == plci->Id)) {
4005 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4006 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4008 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4011 if ((e->RNR != 1) &&
4012 (a->ch_flow_plci[Ch] == plci->Id) &&
4013 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4014 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4015 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4023 capi_callback_suffix:
4025 while (!plci->req_in
4026 && !plci->internal_command
4027 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4029 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4031 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4033 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4034 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4035 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4036 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4037 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4039 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4040 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4044 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4046 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4048 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4049 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4051 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4053 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4054 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4056 i = api_put (appl, m);
4059 if (m->header.command == _DATA_B3_R)
4061 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4063 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4067 if (plci->li_notify_update)
4069 plci->li_notify_update = false;
4070 mixer_notify_update (plci, false);
4079 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4088 DIVA_CAPI_ADAPTER * a;
4091 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4092 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4095 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4098 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4099 if(plci->req_in!=plci->req_out)
4101 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4103 dbug(1,dprintf("req_1return"));
4106 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4108 plci->req_in = plci->req_in_start = plci->req_out = 0;
4109 dbug(1,dprintf("control_rc"));
4113 ncci = a->ch_ncci[ch];
4116 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4117 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4118 Number = plci->number;
4119 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));
4120 dbug(1,dprintf("channels=0x%x",plci->channels));
4121 if (plci_remove_check(plci))
4123 if(req==REMOVE && rc==ASSIGN_OK)
4125 sig_req(plci,HANGUP,0);
4126 sig_req(plci,REMOVE,0);
4131 switch(plci->command)
4134 dbug(1,dprintf("HoldRC=0x%x",rc));
4135 SSparms[1] = (byte)S_HOLD;
4138 plci->SuppState = IDLE;
4141 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4144 case C_RETRIEVE_REQ:
4145 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4146 SSparms[1] = (byte)S_RETRIEVE;
4149 plci->SuppState = CALL_HELD;
4152 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4156 dbug(1,dprintf("InfoRC=0x%x",rc));
4157 if(rc!=OK) Info=_WRONG_STATE;
4158 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4162 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4163 if (plci->State == INC_DIS_PENDING)
4165 if(plci->Sig.Id!=0xff)
4167 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4168 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4170 dbug(1,dprintf("No more IDs/Call_Req failed"));
4171 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4176 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4177 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4179 else /* D-ch activation */
4181 if (rc != ASSIGN_OK)
4183 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4184 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4189 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4190 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4191 plci->State = INC_ACT_PENDING;
4195 case _CONNECT_I|RESPONSE:
4196 if (plci->State != INC_DIS_PENDING)
4197 plci->State = INC_CON_ACCEPT;
4201 if (plci->State == INC_DIS_PENDING)
4203 if(plci->Sig.Id!=0xff)
4205 plci->State = OUTG_DIS_PENDING;
4206 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4219 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4222 ncci = get_ncci (plci, ch, 0);
4223 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4227 a->ncci_state[ncci] = INC_ACT_PENDING;
4228 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4229 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4233 a->ncci_state[ncci] = OUTG_CON_PENDING;
4234 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4238 case _CONNECT_B3_I|RESPONSE:
4242 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4245 case _DISCONNECT_B3_R:
4246 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4249 case _MANUFACTURER_R:
4255 Info = _WRONG_IDENTIFIER;
4256 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4260 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4268 else if (plci->internal_command)
4270 switch(plci->internal_command)
4276 if(rc==OK) /* command supported, wait for indication */
4283 /* Get Supported Services */
4284 case GETSERV_REQ_PEND:
4285 if(rc==OK) /* command supported, wait for indication */
4289 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4290 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4294 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4295 case INTERR_NUMBERS_REQ_PEND:
4296 case CF_START_PEND: /* Call Forwarding Start pending */
4297 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4298 case CCBS_REQUEST_REQ_PEND:
4299 case CCBS_DEACTIVATE_REQ_PEND:
4300 case CCBS_INTERROGATE_REQ_PEND:
4301 switch(plci->internal_command)
4303 case INTERR_DIVERSION_REQ_PEND:
4304 SSparms[1] = S_INTERROGATE_DIVERSION;
4306 case INTERR_NUMBERS_REQ_PEND:
4307 SSparms[1] = S_INTERROGATE_NUMBERS;
4310 SSparms[1] = S_CALL_FORWARDING_START;
4313 SSparms[1] = S_CALL_FORWARDING_STOP;
4315 case CCBS_REQUEST_REQ_PEND:
4316 SSparms[1] = S_CCBS_REQUEST;
4318 case CCBS_DEACTIVATE_REQ_PEND:
4319 SSparms[1] = S_CCBS_DEACTIVATE;
4321 case CCBS_INTERROGATE_REQ_PEND:
4322 SSparms[1] = S_CCBS_INTERROGATE;
4325 if(global_req==ASSIGN)
4327 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4330 if(!plci->appl) break;
4331 if(rc==ISDN_GUARD_REJ)
4333 Info = _CAPI_GUARD_ERROR;
4337 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4339 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4340 plci->number,"wws",Info,(word)3,SSparms);
4341 if(Info) plci_remove(plci);
4344 /* 3pty conference pending */
4346 if(!plci->relatedPTYPLCI) break;
4347 rplci = plci->relatedPTYPLCI;
4348 SSparms[1] = plci->ptyState;
4349 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4350 if(rplci->tel) rId|=EXT_CONTROLLER;
4353 Info = 0x300E; /* not supported */
4354 plci->relatedPTYPLCI = NULL;
4358 _FACILITY_R|CONFIRM,
4361 "wws",Info,(word)3,SSparms);
4364 /* Explicit Call Transfer pending */
4366 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4367 if(!plci->relatedPTYPLCI) break;
4368 rplci = plci->relatedPTYPLCI;
4370 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4371 if(rplci->tel) rId|=EXT_CONTROLLER;
4374 Info = 0x300E; /* not supported */
4375 plci->relatedPTYPLCI = NULL;
4379 _FACILITY_R|CONFIRM,
4382 "wws",Info,(word)3,SSparms);
4385 case _MANUFACTURER_R:
4386 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4387 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4389 dbug(1,dprintf("No more IDs"));
4390 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4391 plci_remove(plci); /* after codec init, internal codec commands pending */
4396 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4397 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4399 dbug(1,dprintf("No more IDs"));
4400 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4401 plci_remove(plci); /* after codec init, internal codec commands pending */
4405 case PERM_COD_HOOK: /* finished with Hook_Ind */
4409 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4410 plci->internal_command = PERM_COD_CONN_PEND;
4413 case PERM_COD_ASSIGN:
4414 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4415 if(rc!=ASSIGN_OK) break;
4416 sig_req(plci,CALL_REQ,0);
4418 plci->internal_command = PERM_COD_CALL;
4421 /* Null Call Reference Request pending */
4423 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4424 if(global_req==ASSIGN)
4432 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4433 appl->NullCREnable = false;
4437 else if(req==NCR_FACILITY)
4441 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4445 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4446 appl->NullCREnable = false;
4455 if(a->ncci_state[ncci]==CONNECTED)
4457 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4458 cleanup_ncci_data (plci, ncci);
4459 nl_req_ncci(plci,N_DISC,(byte)ncci);
4466 if (plci->State == INC_DIS_PENDING)
4468 sig_req(plci,CALL_REQ,0);
4470 plci->State=OUTG_CON_PENDING;
4474 case MWI_ACTIVATE_REQ_PEND:
4475 case MWI_DEACTIVATE_REQ_PEND:
4476 if(global_req == ASSIGN && rc==ASSIGN_OK)
4478 dbug(1,dprintf("MWI_REQ assigned"));
4485 Info = 0x2007; /* Illegal message parameter coding */
4486 dbug(1,dprintf("MWI_REQ invalid parameter"));
4490 Info = 0x300B; /* not supported */
4491 dbug(1,dprintf("MWI_REQ not supported"));
4493 /* 0x3010: Request not allowed in this state */
4494 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4497 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4499 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4501 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4503 if(plci->cr_enquiry)
4506 _FACILITY_R|CONFIRM,
4509 "wws",Info,(word)3,SSparms);
4510 if(rc!=OK) plci_remove(plci);
4515 _FACILITY_R|CONFIRM,
4518 "wws",Info,(word)3,SSparms);
4522 case CONF_BEGIN_REQ_PEND:
4523 case CONF_ADD_REQ_PEND:
4524 case CONF_SPLIT_REQ_PEND:
4525 case CONF_DROP_REQ_PEND:
4526 case CONF_ISOLATE_REQ_PEND:
4527 case CONF_REATTACH_REQ_PEND:
4528 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4529 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4532 switch(plci->internal_command)
4534 case CONF_BEGIN_REQ_PEND:
4535 SSparms[1] = S_CONF_BEGIN;
4537 case CONF_ADD_REQ_PEND:
4538 SSparms[1] = S_CONF_ADD;
4539 rplci = plci->relatedPTYPLCI;
4540 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4542 case CONF_SPLIT_REQ_PEND:
4543 SSparms[1] = S_CONF_SPLIT;
4545 case CONF_DROP_REQ_PEND:
4546 SSparms[1] = S_CONF_DROP;
4548 case CONF_ISOLATE_REQ_PEND:
4549 SSparms[1] = S_CONF_ISOLATE;
4551 case CONF_REATTACH_REQ_PEND:
4552 SSparms[1] = S_CONF_REATTACH;
4558 Info = 0x300E; /* not supported */
4559 plci->relatedPTYPLCI = NULL;
4563 _FACILITY_R|CONFIRM,
4566 "wws",Info,(word)3,SSparms);
4569 case VSWITCH_REQ_PEND:
4572 if(plci->relatedPTYPLCI)
4574 plci->relatedPTYPLCI->vswitchstate=0;
4575 plci->relatedPTYPLCI->vsprot=0;
4576 plci->relatedPTYPLCI->vsprotdialect=0;
4578 plci->vswitchstate=0;
4580 plci->vsprotdialect=0;
4584 if(plci->relatedPTYPLCI &&
4585 plci->vswitchstate==1 &&
4586 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4587 plci->vswitchstate=3;
4591 /* Call Deflection Request pending (SSCT) */
4593 SSparms[1] = S_CALL_DEFLECTION;
4596 Info = 0x300E; /* not supported */
4597 plci->appl->CDEnable = 0;
4599 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4600 plci->number,"wws",Info,(word)3,SSparms);
4603 case RTP_CONNECT_B3_REQ_COMMAND_2:
4606 ncci = get_ncci (plci, ch, 0);
4607 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4609 a->ncci_state[ncci] = OUTG_CON_PENDING;
4613 if (plci->internal_command_queue[0])
4615 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4616 if (plci->internal_command)
4621 next_internal_command (Id, plci);
4626 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4627 if(plci->tel) Id|=EXT_CONTROLLER;
4629 switch(plci->internal_command)
4634 case START_L1_SIG_ASSIGN_PEND:
4635 case REM_L1_SIG_ASSIGN_PEND:
4636 if(global_req == ASSIGN)
4642 dbug(1,dprintf("***L1 Req rem PLCI"));
4643 plci->internal_command = 0;
4644 sig_req(plci,REMOVE,0);
4649 /* Call Deflection Request pending, just no appl ptr assigned */
4651 SSparms[1] = S_CALL_DEFLECTION;
4654 Info = 0x300E; /* not supported */
4656 for(i=0; i<max_appl; i++)
4658 if(application[i].CDEnable)
4660 if(!application[i].Id) application[i].CDEnable = 0;
4663 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4664 plci->number,"wws",Info,(word)3,SSparms);
4665 if(Info) application[i].CDEnable = 0;
4669 plci->internal_command = 0;
4672 case PERM_COD_HOOK: /* finished with Hook_Ind */
4676 plci->internal_command = PERM_COD_CONN_PEND;
4677 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4680 case PERM_COD_ASSIGN:
4681 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4682 plci->internal_command = 0;
4683 if(rc!=ASSIGN_OK) break;
4684 plci->internal_command = PERM_COD_CALL;
4685 sig_req(plci,CALL_REQ,0);
4689 case LISTEN_SIG_ASSIGN_PEND:
4692 plci->internal_command = 0;
4693 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4694 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4695 sig_req(plci,INDICATE_REQ,0);
4700 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4708 if(global_req == ASSIGN)
4712 sig_req(plci,LAW_REQ,0);
4714 dbug(1,dprintf("Auto-Law assigned"));
4718 dbug(1,dprintf("Auto-Law assign failed"));
4719 a->automatic_law = 3;
4720 plci->internal_command = 0;
4721 a->automatic_lawPLCI = NULL;
4725 else if(req == LAW_REQ && rc==OK)
4727 dbug(1,dprintf("Auto-Law initiated"));
4728 a->automatic_law = 2;
4729 plci->internal_command = 0;
4733 dbug(1,dprintf("Auto-Law not supported"));
4734 a->automatic_law = 3;
4735 plci->internal_command = 0;
4736 sig_req(plci,REMOVE,0);
4738 a->automatic_lawPLCI = NULL;
4742 plci_remove_check(plci);
4746 static void data_rc(PLCI *plci, byte ch)
4749 DIVA_CAPI_ADAPTER * a;
4756 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4758 ncci = a->ch_ncci[ch];
4759 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4761 ncci_ptr = &(a->ncci[ncci]);
4762 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4763 if (ncci_ptr->data_pending)
4765 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4766 if (!(data->Flags &4) && a->ncci_state[ncci])
4768 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4769 if(plci->tel) Id|=EXT_CONTROLLER;
4770 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4771 "ww",data->Handle,0);
4773 (ncci_ptr->data_out)++;
4774 if (ncci_ptr->data_out == MAX_DATA_B3)
4775 ncci_ptr->data_out = 0;
4776 (ncci_ptr->data_pending)--;
4782 static void data_ack(PLCI *plci, byte ch)
4785 DIVA_CAPI_ADAPTER * a;
4790 ncci = a->ch_ncci[ch];
4791 ncci_ptr = &(a->ncci[ncci]);
4792 if (ncci_ptr->data_ack_pending)
4794 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4796 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4797 if(plci->tel) Id|=EXT_CONTROLLER;
4798 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4799 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4801 (ncci_ptr->data_ack_out)++;
4802 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4803 ncci_ptr->data_ack_out = 0;
4804 (ncci_ptr->data_ack_pending)--;
4808 static void sig_ind(PLCI *plci)
4818 DIVA_CAPI_ADAPTER * a;
4819 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4820 #define MAXPARMSIDS 31
4821 byte * parms[MAXPARMSIDS];
4823 byte * multi_fac_parms[MAX_MULTI_IE];
4824 byte * multi_pi_parms [MAX_MULTI_IE];
4825 byte * multi_ssext_parms [MAX_MULTI_IE];
4826 byte * multi_CiPN_parms [MAX_MULTI_IE];
4828 byte * multi_vswitch_parms [MAX_MULTI_IE];
4835 byte *esc_profile = "";
4838 PLCI * tplci = NULL;
4839 byte chi[] = "\x02\x18\x01";
4840 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4841 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4842 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4843 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4844 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4845 /* (see Info_Mask Bit 4, first IE. then the message type) */
4847 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4848 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4849 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4850 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4851 /* 14 FTY repl by ESC_CHI */
4852 /* 18 PI repl by ESC_LAW */
4853 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4854 word multi_fac_id[] = {1, FTY};
4855 word multi_pi_id[] = {1, PI};
4856 word multi_CiPN_id[] = {1, OAD};
4857 word multi_ssext_id[] = {1, ESC_SSEXT};
4859 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4863 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4864 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4865 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4866 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4867 byte force_mt_info = false;
4873 Id = ((word)plci->Id<<8)|a->Id;
4874 PUT_WORD(&SS_Ind[4],0x0000);
4876 if (plci->sig_remove_id)
4878 plci->Sig.RNR = 2; /* discard */
4879 dbug(1,dprintf("SIG discard while remove pending"));
4882 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4883 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4884 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4885 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4890 if(plci->Sig.Ind==HANGUP && plci->channels)
4893 plci->hangup_flow_ctrl_timer++;
4894 /* recover the network layer after timeout */
4895 if(plci->hangup_flow_ctrl_timer==100)
4897 dbug(1,dprintf("Exceptional disc"));
4899 plci->hangup_flow_ctrl_timer = 0;
4900 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4902 if (a->ncci_plci[ncci] == plci->Id)
4904 cleanup_ncci_data (plci, ncci);
4905 if(plci->channels)plci->channels--;
4907 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4911 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4918 /* do first parse the info with no OAD in, because OAD will be converted */
4919 /* first the multiple facility IE, then mult. progress ind. */
4920 /* then the parameters for the info_ind + conn_ind */
4921 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4922 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4923 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4925 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4927 IndParse(plci,parms_id,parms,0);
4928 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4929 esc_chi = parms[14];
4930 esc_law = parms[18];
4931 pty_cai = parms[24];
4933 esc_profile = parms[27];
4934 if(esc_cr[0] && plci)
4936 if(plci->cr_enquiry && plci->appl)
4938 plci->cr_enquiry = false;
4941 /* b = total length */
4942 /* b = indication type */
4943 /* b = length of all IEs */
4945 /* S = IE1 length + cont. */
4947 /* S = IE2 length + cont. */
4952 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4953 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);
4956 /* create the additional info structure */
4957 add_i[1] = parms[15]; /* KEY of additional info */
4958 add_i[2] = parms[11]; /* UUI of additional info */
4959 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4961 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4962 /* indication returns by the card if requested by the function */
4963 /* AutomaticLaw() after driver init */
4964 if (a->automatic_law<4)
4968 dbug(0,dprintf("u-Law selected"));
4972 dbug(0,dprintf("a-Law selected"));
4975 a->automatic_law = 4;
4976 if(plci==a->automatic_lawPLCI) {
4977 plci->internal_command = 0;
4978 sig_req(plci,REMOVE,0);
4980 a->automatic_lawPLCI = NULL;
4985 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4986 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4987 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4988 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4990 a->profile.Global_Options &= 0x000000ffL;
4991 a->profile.B1_Protocols &= 0x000003ffL;
4992 a->profile.B2_Protocols &= 0x00001fdfL;
4993 a->profile.B3_Protocols &= 0x000000b7L;
4995 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4996 GL_BCHANNEL_OPERATION_SUPPORTED;
4997 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4998 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4999 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5000 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5001 a->man_profile.private_options = 0;
5003 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5005 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5006 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5010 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5011 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5012 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5013 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5016 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5017 a->man_profile.private_options |= 1L << PRIVATE_T38;
5020 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5021 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5024 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5025 a->man_profile.private_options |= 1L << PRIVATE_V18;
5028 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5029 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5032 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5033 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5036 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5037 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5040 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5041 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5044 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5045 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5050 a->profile.Global_Options &= 0x0000007fL;
5051 a->profile.B1_Protocols &= 0x000003dfL;
5052 a->profile.B2_Protocols &= 0x00001adfL;
5053 a->profile.B3_Protocols &= 0x000000b7L;
5054 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5056 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5057 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5059 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5061 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5062 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5063 UnMapController (a->Id), a->profile.Global_Options,
5064 a->profile.B1_Protocols, a->profile.B2_Protocols,
5065 a->profile.B3_Protocols, a->manufacturer_features));
5067 /* codec plci for the handset/hook state support is just an internal id */
5068 if(plci!=a->AdvCodecPLCI)
5070 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5071 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5072 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5073 SendInfo(plci,Id, parms, force_mt_info);
5075 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5079 /* switch the codec to the b-channel */
5080 if(esc_chi[0] && plci && !plci->SuppState){
5081 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5082 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5083 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5084 if(plci->tel==ADV_VOICE && plci->appl) {
5085 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5089 if(plci->appl) Number = plci->appl->Number++;
5091 switch(plci->Sig.Ind) {
5092 /* Response to Get_Supported_Services request */
5094 dbug(1,dprintf("S_Supported"));
5095 if(!plci->appl) break;
5098 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5102 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5104 PUT_WORD (&CF_Ind[1], 0);
5105 PUT_WORD (&CF_Ind[4], 0);
5106 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5110 /* Supplementary Service rejected */
5112 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5113 if(!pty_cai[0]) break;
5118 case THREE_PTY_BEGIN:
5119 if(!plci->relatedPTYPLCI) break;
5120 tplci = plci->relatedPTYPLCI;
5121 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5122 if(tplci->tel) rId|=EXT_CONTROLLER;
5123 if(pty_cai[5]==ECT_EXECUTE)
5125 PUT_WORD(&SS_Ind[1],S_ECT);
5127 plci->vswitchstate=0;
5128 plci->relatedPTYPLCI->vswitchstate=0;
5133 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5135 if(pty_cai[2]!=0xff)
5137 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5141 PUT_WORD(&SS_Ind[4],0x300E);
5143 plci->relatedPTYPLCI = NULL;
5145 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5148 case CALL_DEFLECTION:
5149 if(pty_cai[2]!=0xff)
5151 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5155 PUT_WORD(&SS_Ind[4],0x300E);
5157 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5158 for(i=0; i<max_appl; i++)
5160 if(application[i].CDEnable)
5162 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5163 application[i].CDEnable = false;
5168 case DEACTIVATION_DIVERSION:
5169 case ACTIVATION_DIVERSION:
5170 case DIVERSION_INTERROGATE_CFU:
5171 case DIVERSION_INTERROGATE_CFB:
5172 case DIVERSION_INTERROGATE_CFNR:
5173 case DIVERSION_INTERROGATE_NUM:
5175 case CCBS_DEACTIVATE:
5176 case CCBS_INTERROGATE:
5177 if(!plci->appl) break;
5178 if(pty_cai[2]!=0xff)
5180 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5184 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5188 case DEACTIVATION_DIVERSION:
5189 dbug(1,dprintf("Deact_Div"));
5190 Interr_Err_Ind[0]=0x9;
5191 Interr_Err_Ind[3]=0x6;
5192 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5194 case ACTIVATION_DIVERSION:
5195 dbug(1,dprintf("Act_Div"));
5196 Interr_Err_Ind[0]=0x9;
5197 Interr_Err_Ind[3]=0x6;
5198 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5200 case DIVERSION_INTERROGATE_CFU:
5201 case DIVERSION_INTERROGATE_CFB:
5202 case DIVERSION_INTERROGATE_CFNR:
5203 dbug(1,dprintf("Interr_Div"));
5204 Interr_Err_Ind[0]=0xa;
5205 Interr_Err_Ind[3]=0x7;
5206 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5208 case DIVERSION_INTERROGATE_NUM:
5209 dbug(1,dprintf("Interr_Num"));
5210 Interr_Err_Ind[0]=0xa;
5211 Interr_Err_Ind[3]=0x7;
5212 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5215 dbug(1,dprintf("CCBS Request"));
5216 Interr_Err_Ind[0]=0xd;
5217 Interr_Err_Ind[3]=0xa;
5218 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5220 case CCBS_DEACTIVATE:
5221 dbug(1,dprintf("CCBS Deactivate"));
5222 Interr_Err_Ind[0]=0x9;
5223 Interr_Err_Ind[3]=0x6;
5224 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5226 case CCBS_INTERROGATE:
5227 dbug(1,dprintf("CCBS Interrogate"));
5228 Interr_Err_Ind[0]=0xb;
5229 Interr_Err_Ind[3]=0x8;
5230 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5233 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5234 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5237 case ACTIVATION_MWI:
5238 case DEACTIVATION_MWI:
5239 if(pty_cai[5]==ACTIVATION_MWI)
5241 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5243 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5245 if(pty_cai[2]!=0xff)
5247 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5251 PUT_WORD(&SS_Ind[4],0x300E);
5254 if(plci->cr_enquiry)
5256 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5261 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5264 case CONF_ADD: /* ERROR */
5274 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5280 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5281 plci->ptyState = CONNECTED;
5286 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5287 plci->ptyState = CONNECTED;
5292 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5293 plci->ptyState = CONNECTED;
5296 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5297 plci->relatedPTYPLCI = NULL;
5298 tplci=plci->relatedPTYPLCI;
5299 if(tplci) tplci->ptyState = CONNECTED;
5300 plci->ptyState = CONNECTED;
5304 if(pty_cai[2]!=0xff)
5306 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5310 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5311 within the required time */
5314 PUT_DWORD(&CONF_Ind[6],0x0);
5315 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5320 /* Supplementary Service indicates success */
5322 dbug(1,dprintf("Service_Ind"));
5323 PUT_WORD (&CF_Ind[4], 0);
5327 case THREE_PTY_BEGIN:
5329 if(!plci->relatedPTYPLCI) break;
5330 tplci = plci->relatedPTYPLCI;
5331 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5332 if(tplci->tel) rId|=EXT_CONTROLLER;
5333 if(pty_cai[5]==ECT_EXECUTE)
5335 PUT_WORD(&SS_Ind[1],S_ECT);
5337 if(plci->vswitchstate!=3)
5340 plci->ptyState = IDLE;
5341 plci->relatedPTYPLCI = NULL;
5346 dbug(1,dprintf("ECT OK"));
5347 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5354 switch (plci->ptyState)
5357 plci->ptyState = CONNECTED;
5358 dbug(1,dprintf("3PTY ON"));
5362 plci->ptyState = IDLE;
5363 plci->relatedPTYPLCI = NULL;
5365 dbug(1,dprintf("3PTY OFF"));
5368 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5369 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5373 case CALL_DEFLECTION:
5374 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5375 for(i=0; i<max_appl; i++)
5377 if(application[i].CDEnable)
5379 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5380 application[i].CDEnable = false;
5385 case DEACTIVATION_DIVERSION:
5386 case ACTIVATION_DIVERSION:
5387 if(!plci->appl) break;
5388 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5389 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5390 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5394 case DIVERSION_INTERROGATE_CFU:
5395 case DIVERSION_INTERROGATE_CFB:
5396 case DIVERSION_INTERROGATE_CFNR:
5397 case DIVERSION_INTERROGATE_NUM:
5399 case CCBS_DEACTIVATE:
5400 case CCBS_INTERROGATE:
5401 if(!plci->appl) break;
5404 case DIVERSION_INTERROGATE_CFU:
5405 case DIVERSION_INTERROGATE_CFB:
5406 case DIVERSION_INTERROGATE_CFNR:
5407 dbug(1,dprintf("Interr_Div"));
5408 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5409 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5411 case DIVERSION_INTERROGATE_NUM:
5412 dbug(1,dprintf("Interr_Num"));
5413 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5414 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5417 dbug(1,dprintf("CCBS Request"));
5418 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5419 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5421 case CCBS_DEACTIVATE:
5422 dbug(1,dprintf("CCBS Deactivate"));
5423 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5424 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5426 case CCBS_INTERROGATE:
5427 dbug(1,dprintf("CCBS Interrogate"));
5428 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5429 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5432 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5433 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5434 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5438 case ACTIVATION_MWI:
5439 case DEACTIVATION_MWI:
5440 if(pty_cai[5]==ACTIVATION_MWI)
5442 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5444 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5445 if(plci->cr_enquiry)
5447 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5452 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5455 case MWI_INDICATION:
5456 if(pty_cai[0]>=0x12)
5458 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5459 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5460 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5461 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5463 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5465 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5469 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5474 for(i=0; i<max_appl; i++)
5476 if(a->Notification_Mask[i]&SMASK_MWI)
5478 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5486 facility[2]= 0; /* returncode */
5488 else facility[2]= 0xff;
5493 facility[2]= 0xff; /* returncode */
5496 facility[1]= MWI_RESPONSE; /* Function */
5497 add_p(plci,CAI,facility);
5498 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5499 sig_req(plci,S_SERVICE,0);
5502 next_internal_command (Id, plci);
5504 case CONF_ADD: /* OK */
5509 case CONF_PARTYDISC:
5515 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5519 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5523 PUT_DWORD(&CONF_Ind[6],0x0);
5527 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5532 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5537 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5542 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5544 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5545 tplci=plci->relatedPTYPLCI;
5546 if(tplci) tplci->ptyState = CONNECTED;
5548 case CONF_PARTYDISC:
5551 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5553 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5556 plci->ptyState = CONNECTED;
5557 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5559 case CCBS_INFO_RETAIN:
5560 case CCBS_ERASECALLLINKAGEID:
5561 case CCBS_STOP_ALERTING:
5566 case CCBS_INFO_RETAIN:
5567 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5569 case CCBS_STOP_ALERTING:
5570 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5572 case CCBS_ERASECALLLINKAGEID:
5573 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5581 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5583 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5585 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5589 for(i=0; i<max_appl; i++)
5590 if(a->Notification_Mask[i]&SMASK_CCBS)
5591 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5600 i = _L3_CAUSE | cau[2];
5601 if(cau[2]==0) i = 0x3603;
5607 PUT_WORD(&SS_Ind[1],S_HOLD);
5608 PUT_WORD(&SS_Ind[4],i);
5609 if(plci->SuppState == HOLD_REQUEST)
5611 plci->SuppState = IDLE;
5612 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5617 if(plci->SuppState == HOLD_REQUEST)
5619 plci->SuppState = CALL_HELD;
5620 CodecIdCheck(a, plci);
5621 start_internal_command (Id, plci, hold_save_command);
5625 case CALL_RETRIEVE_REJ:
5629 i = _L3_CAUSE | cau[2];
5630 if(cau[2]==0) i = 0x3603;
5636 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5637 PUT_WORD(&SS_Ind[4],i);
5638 if(plci->SuppState == RETRIEVE_REQUEST)
5640 plci->SuppState = CALL_HELD;
5641 CodecIdCheck(a, plci);
5642 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5646 case CALL_RETRIEVE_ACK:
5647 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5648 if(plci->SuppState == RETRIEVE_REQUEST)
5650 plci->SuppState = IDLE;
5651 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5652 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5655 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5656 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5657 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5658 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5660 dbug(1,dprintf("Get B-ch"));
5661 start_internal_command (Id, plci, retrieve_restore_command);
5664 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5667 start_internal_command (Id, plci, retrieve_restore_command);
5672 if(plci->State != LISTENING) {
5673 sig_req(plci,HANGUP,0);
5677 cip = find_cip(a,parms[4],parms[6]);
5679 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5680 clear_c_ind_mask (plci);
5681 if (!remove_started && !a->adapter_disabled)
5683 set_c_ind_mask_bit (plci, MAX_APPL);
5684 group_optimization(a, plci);
5685 for(i=0; i<max_appl; i++) {
5686 if(application[i].Id
5687 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5688 && CPN_filter_ok(parms[0],a,i)
5689 && test_group_ind_mask_bit (plci, i) ) {
5690 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5691 set_c_ind_mask_bit (plci, i);
5692 dump_c_ind_mask (plci);
5693 plci->State = INC_CON_PENDING;
5694 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5695 CALL_DIR_IN | CALL_DIR_ANSWER;
5697 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5698 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5700 /* if a listen on the ext controller is done, check if hook states */
5701 /* are supported or if just a on board codec must be activated */
5702 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5703 if(a->profile.Global_Options & HANDSET)
5704 plci->tel = ADV_VOICE;
5705 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5707 if(plci->tel) Id|=EXT_CONTROLLER;
5708 a->codec_listen[i] = plci;
5711 sendf(&application[i],_CONNECT_I,Id,0,
5712 "wSSSSSSSbSSSSS", cip, /* CIP */
5713 parms[0], /* CalledPartyNumber */
5714 multi_CiPN_parms[0], /* CallingPartyNumber */
5715 parms[2], /* CalledPartySubad */
5716 parms[3], /* CallingPartySubad */
5717 parms[4], /* BearerCapability */
5718 parms[5], /* LowLC */
5719 parms[6], /* HighLC */
5720 ai_len, /* nested struct add_i */
5721 add_i[0], /* B channel info */
5722 add_i[1], /* keypad facility */
5723 add_i[2], /* user user data */
5724 add_i[3], /* nested facility */
5725 multi_CiPN_parms[1] /* second CiPN(SCR) */
5727 SendSSExtInd(&application[i],
5731 SendSetupInfo(&application[i],
5735 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5738 clear_c_ind_mask_bit (plci, MAX_APPL);
5739 dump_c_ind_mask (plci);
5741 if(c_ind_mask_empty (plci)) {
5742 sig_req(plci,HANGUP,0);
5746 plci->notifiedcall = 0;
5751 case CALL_PEND_NOTIFY:
5752 plci->notifiedcall = 1;
5758 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5760 if(plci->internal_command==PERM_COD_CONN_PEND)
5762 if(plci->State==ADVANCED_VOICE_NOSIG)
5764 dbug(1,dprintf("***Codec OK"));
5765 if(a->AdvSignalPLCI)
5767 tplci = a->AdvSignalPLCI;
5768 if(tplci->spoofed_msg)
5770 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5772 tplci->internal_command = 0;
5773 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5774 switch (tplci->spoofed_msg)
5777 tplci->command = _CONNECT_I|RESPONSE;
5778 api_load_msg (&tplci->saved_msg, saved_parms);
5779 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5780 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5782 /* early B3 connect (CIP mask bit 9) no release after a disc */
5783 add_p(tplci,LLI,"\x01\x01");
5785 add_s(tplci, CONN_NR, &saved_parms[2]);
5786 add_s(tplci, LLC, &saved_parms[4]);
5787 add_ai(tplci, &saved_parms[5]);
5788 tplci->State = INC_CON_ACCEPT;
5789 sig_req(tplci, CALL_RES,0);
5793 case AWAITING_SELECT_B:
5794 dbug(1,dprintf("Select_B continue"));
5795 start_internal_command (x_Id, tplci, select_b_command);
5798 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5801 dbug(1,dprintf("No SigID!"));
5802 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5806 tplci->command = _MANUFACTURER_R;
5807 api_load_msg (&tplci->saved_msg, saved_parms);
5808 dir = saved_parms[2].info[0];
5810 sig_req(tplci,CALL_REQ,0);
5813 sig_req(tplci,LISTEN_REQ,0);
5816 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5819 case (CALL_REQ|AWAITING_MANUF_CON):
5820 sig_req(tplci,CALL_REQ,0);
5827 dbug(1,dprintf("No SigID!"));
5828 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5832 tplci->command = _CONNECT_R;
5833 api_load_msg (&tplci->saved_msg, saved_parms);
5834 add_s(tplci,CPN,&saved_parms[1]);
5835 add_s(tplci,DSA,&saved_parms[3]);
5836 add_ai(tplci,&saved_parms[9]);
5837 sig_req(tplci,CALL_REQ,0);
5842 tplci->command = C_RETRIEVE_REQ;
5843 sig_req(tplci,CALL_RETRIEVE,0);
5847 tplci->spoofed_msg = 0;
5848 if (tplci->internal_command == 0)
5849 next_internal_command (x_Id, tplci);
5852 next_internal_command (Id, plci);
5855 dbug(1,dprintf("***Codec Hook Init Req"));
5856 plci->internal_command = PERM_COD_HOOK;
5857 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5858 sig_req(plci,TEL_CTRL,0);
5862 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5863 && plci->State!=INC_ACT_PENDING)
5865 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5866 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5868 chi[2] = plci->b_channel;
5869 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5871 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5872 plci->State = INC_ACT_PENDING;
5878 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5879 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5880 switch (ie[1]&0x91) {
5881 case 0x80: /* hook off */
5883 if(plci->internal_command==PERM_COD_HOOK)
5885 dbug(1,dprintf("init:hook_off"));
5886 plci->hook_state = ie[1];
5887 next_internal_command (Id, plci);
5890 else /* ignore doubled hook indications */
5892 if( ((plci->hook_state)&0xf0)==0x80)
5894 dbug(1,dprintf("ignore hook"));
5897 plci->hook_state = ie[1]&0x91;
5899 /* check for incoming call pending */
5900 /* and signal '+'.Appl must decide */
5901 /* with connect_res if call must */
5902 /* accepted or not */
5903 for(i=0, tplci=NULL;i<max_appl;i++){
5904 if(a->codec_listen[i]
5905 && (a->codec_listen[i]->State==INC_CON_PENDING
5906 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5907 tplci = a->codec_listen[i];
5908 tplci->appl = &application[i];
5911 /* no incoming call, do outgoing call */
5912 /* and signal '+' if outg. setup */
5913 if(!a->AdvSignalPLCI && !tplci){
5914 if((i=get_plci(a))) {
5915 a->AdvSignalPLCI = &a->plci[i-1];
5916 tplci = a->AdvSignalPLCI;
5917 tplci->tel = ADV_VOICE;
5918 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5919 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5920 /* early B3 connect (CIP mask bit 9) no release after a disc */
5921 add_p(tplci,LLI,"\x01\x01");
5923 add_p(tplci, CAI, voice_cai);
5924 add_p(tplci, OAD, a->TelOAD);
5925 add_p(tplci, OSA, a->TelOSA);
5926 add_p(tplci,SHIFT|6,NULL);
5927 add_p(tplci,SIN,"\x02\x01\x00");
5928 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5929 sig_req(tplci,ASSIGN,DSIG_ID);
5930 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5931 a->AdvSignalPLCI->command = 0;
5932 tplci->appl = a->AdvSignalAppl;
5933 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5940 Id = ((word)tplci->Id<<8)|a->Id;
5946 "ws", (word)0, "\x01+");
5949 case 0x90: /* hook on */
5951 if(plci->internal_command==PERM_COD_HOOK)
5953 dbug(1,dprintf("init:hook_on"));
5954 plci->hook_state = ie[1]&0x91;
5955 next_internal_command (Id, plci);
5958 else /* ignore doubled hook indications */
5960 if( ((plci->hook_state)&0xf0)==0x90) break;
5961 plci->hook_state = ie[1]&0x91;
5963 /* hangup the adv. voice call and signal '-' to the appl */
5964 if(a->AdvSignalPLCI) {
5965 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5966 if(plci->tel) Id|=EXT_CONTROLLER;
5967 sendf(a->AdvSignalAppl,
5971 "ws", (word)0, "\x01-");
5972 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5973 a->AdvSignalPLCI->command = 0;
5974 sig_req(a->AdvSignalPLCI,HANGUP,0);
5975 send_req(a->AdvSignalPLCI);
5983 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5984 PUT_WORD(&resume_cau[4],GOOD);
5985 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5989 clear_c_ind_mask (plci);
5991 if (plci->NL.Id && !plci->nl_remove_id) {
5992 mixer_remove (plci);
5993 nl_req_ncci(plci,REMOVE,0);
5995 if (!plci->sig_remove_id) {
5996 plci->internal_command = 0;
5997 sig_req(plci,REMOVE,0);
6000 if(!plci->channels) {
6001 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6002 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6010 plci->hangup_flow_ctrl_timer=0;
6011 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6014 i = _L3_CAUSE | cau[2];
6015 if(cau[2]==0) i = 0;
6016 else if(cau[2]==8) i = _L1_ERROR;
6017 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6018 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6024 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6026 for(i=0; i<max_appl; i++)
6028 if(test_c_ind_mask_bit (plci, i))
6029 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6034 clear_c_ind_mask (plci);
6038 if (plci->State == LISTENING)
6040 plci->notifiedcall=0;
6043 plci->State = INC_DIS_PENDING;
6044 if(c_ind_mask_empty (plci))
6047 if (plci->NL.Id && !plci->nl_remove_id)
6049 mixer_remove (plci);
6050 nl_req_ncci(plci,REMOVE,0);
6052 if (!plci->sig_remove_id)
6054 plci->internal_command = 0;
6055 sig_req(plci,REMOVE,0);
6062 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6063 /* result in a second HANGUP! Don't generate another */
6065 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6067 if(plci->State==RESUMING)
6069 PUT_WORD(&resume_cau[4],i);
6070 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6072 plci->State = INC_DIS_PENDING;
6073 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6079 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6083 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6086 if(plci->relatedPTYPLCI &&
6087 plci->vswitchstate==3 &&
6088 plci->relatedPTYPLCI->vswitchstate==3 &&
6089 parms[MAXPARMSIDS-1][0])
6091 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6092 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6093 send_req(plci->relatedPTYPLCI);
6095 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6102 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6107 byte * Info_Element;
6110 dbug(1,dprintf("SetupInfo"));
6112 for(i=0; i<MAXPARMSIDS; i++) {
6119 dbug(1,dprintf("CPN "));
6120 Info_Number = 0x0070;
6122 Info_Sent_Flag = true;
6124 case 8: /* display */
6125 dbug(1,dprintf("display(%d)",i));
6126 Info_Number = 0x0028;
6128 Info_Sent_Flag = true;
6130 case 16: /* Channel Id */
6131 dbug(1,dprintf("CHI"));
6132 Info_Number = 0x0018;
6134 Info_Sent_Flag = true;
6135 mixer_set_bchannel_id (plci, Info_Element);
6137 case 19: /* Redirected Number */
6138 dbug(1,dprintf("RDN"));
6139 Info_Number = 0x0074;
6141 Info_Sent_Flag = true;
6143 case 20: /* Redirected Number extended */
6144 dbug(1,dprintf("RDX"));
6145 Info_Number = 0x0073;
6147 Info_Sent_Flag = true;
6149 case 22: /* Redirecing Number */
6150 dbug(1,dprintf("RIN"));
6151 Info_Number = 0x0076;
6153 Info_Sent_Flag = true;
6161 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6162 Info_Number = 0x8000 |5;
6167 if(Info_Sent_Flag && Info_Number){
6168 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6169 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6176 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6183 byte * Info_Element;
6185 static byte charges[5] = {4,0,0,0,0};
6186 static byte cause[] = {0x02,0x80,0x00};
6189 dbug(1,dprintf("InfoParse "));
6194 && plci->Sig.Ind!=NCR_FACILITY
6197 dbug(1,dprintf("NoParse "));
6201 for(i=0; i<MAXPARMSIDS; i++) {
6208 dbug(1,dprintf("CPN "));
6209 Info_Number = 0x0070;
6212 case 7: /* ESC_CAU */
6213 dbug(1,dprintf("cau(0x%x)",ie[2]));
6214 Info_Number = 0x0008;
6217 Info_Element = NULL;
6219 case 8: /* display */
6220 dbug(1,dprintf("display(%d)",i));
6221 Info_Number = 0x0028;
6224 case 9: /* Date display */
6225 dbug(1,dprintf("date(%d)",i));
6226 Info_Number = 0x0029;
6229 case 10: /* charges */
6230 for(j=0;j<4;j++) charges[1+j] = 0;
6231 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6232 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6233 Info_Number = 0x4000;
6235 Info_Element = charges;
6237 case 11: /* user user info */
6238 dbug(1,dprintf("uui"));
6239 Info_Number = 0x007E;
6242 case 12: /* congestion receiver ready */
6243 dbug(1,dprintf("clRDY"));
6244 Info_Number = 0x00B0;
6248 case 13: /* congestion receiver not ready */
6249 dbug(1,dprintf("clNRDY"));
6250 Info_Number = 0x00BF;
6254 case 15: /* Keypad Facility */
6255 dbug(1,dprintf("KEY"));
6256 Info_Number = 0x002C;
6259 case 16: /* Channel Id */
6260 dbug(1,dprintf("CHI"));
6261 Info_Number = 0x0018;
6263 mixer_set_bchannel_id (plci, Info_Element);
6265 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6266 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6267 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6268 Info_Number = 0x0008;
6270 if(cause[2] != ie[2]) Info_Element = cause;
6272 case 19: /* Redirected Number */
6273 dbug(1,dprintf("RDN"));
6274 Info_Number = 0x0074;
6277 case 22: /* Redirecing Number */
6278 dbug(1,dprintf("RIN"));
6279 Info_Number = 0x0076;
6282 case 23: /* Notification Indicator */
6283 dbug(1,dprintf("NI"));
6284 Info_Number = (word)NI;
6287 case 26: /* Call State */
6288 dbug(1,dprintf("CST"));
6289 Info_Number = (word)CST;
6290 Info_Mask = 0x01; /* do with cause i.e. for now */
6292 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6293 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6294 Info_Number = 0x8000 |ie[3];
6295 if(iesent) Info_Mask = 0xffff;
6296 else Info_Mask = 0x10;
6307 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6309 for(j=0; j<max_appl; j++)
6311 appl = &application[j];
6314 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6316 dbug(1,dprintf("NCR_Ind"));
6318 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6322 else if(!plci->appl)
6323 { /* overlap receiving broadcast */
6328 || Info_Number==UUI )
6330 for(j=0; j<max_appl; j++)
6332 if(test_c_ind_mask_bit (plci, j))
6334 dbug(1,dprintf("Ovl_Ind"));
6336 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6340 } /* all other signalling states */
6342 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6344 dbug(1,dprintf("Std_Ind"));
6346 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6352 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6353 dword info_mask, byte setupParse)
6359 byte * Info_Element;
6367 && plci->Sig.Ind!=NCR_FACILITY
6371 dbug(1,dprintf("NoM-IEParse "));
6374 dbug(1,dprintf("M-IEParse "));
6376 for(i=0; i<MAX_MULTI_IE; i++)
6383 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6384 Info_Number = (word)ie_type;
6385 Info_Mask = (word)info_mask;
6388 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6390 for(j=0; j<max_appl; j++)
6392 appl = &application[j];
6395 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6398 dbug(1,dprintf("Mlt_NCR_Ind"));
6399 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6403 else if(!plci->appl && Info_Number)
6404 { /* overlap receiving broadcast */
6405 for(j=0; j<max_appl; j++)
6407 if(test_c_ind_mask_bit (plci, j))
6410 dbug(1,dprintf("Mlt_Ovl_Ind"));
6411 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6414 } /* all other signalling states */
6416 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6419 dbug(1,dprintf("Mlt_Std_Ind"));
6420 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6426 static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6429 /* Format of multi_ssext_parms[i][]:
6432 2 byte SSEXT_REQ/SSEXT_IND
6440 && plci->Sig.Ind!=NCR_FACILITY
6442 for(i=0;i<MAX_MULTI_IE;i++)
6444 if(parms[i][0]<6) continue;
6445 if(parms[i][2]==SSEXT_REQ) continue;
6449 parms[i][0]=0; /* kill it */
6450 sendf(appl,_MANUFACTURER_I,
6460 parms[i][0]=0; /* kill it */
6461 sendf(plci->appl,_MANUFACTURER_I,
6472 static void nl_ind(PLCI *plci)
6477 DIVA_CAPI_ADAPTER * a;
6483 byte len, ncci_state;
6486 word fax_feature_bits;
6487 byte fax_send_edata_ack;
6488 static byte v120_header_buffer[2 + 3];
6489 static word fax_info[] = {
6490 0, /* T30_SUCCESS */
6491 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6492 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6493 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6494 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6495 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6496 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6497 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6498 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6499 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6500 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6501 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6502 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6503 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6504 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6505 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6509 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6511 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6523 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6524 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6525 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6527 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6528 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6529 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6530 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6535 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6536 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6539 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6542 static word rtp_info[] = {
6543 GOOD, /* RTP_SUCCESS */
6544 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6547 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6549 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6550 0x00000000, 0x00000000, 0x00000000, 0x00000000
6553 ch = plci->NL.IndCh;
6555 ncci = a->ch_ncci[ch];
6556 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6557 if(plci->tel) Id|=EXT_CONTROLLER;
6558 APPLptr = plci->appl;
6559 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",
6560 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6562 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6564 if (plci->nl_remove_id)
6566 plci->NL.RNR = 2; /* discard */
6567 dbug(1,dprintf("NL discard while remove pending"));
6570 if((plci->NL.Ind &0x0f)==N_CONNECT)
6572 if(plci->State==INC_DIS_PENDING
6573 || plci->State==OUTG_DIS_PENDING
6574 || plci->State==IDLE)
6576 plci->NL.RNR = 2; /* discard */
6577 dbug(1,dprintf("discard n_connect"));
6580 if(plci->State < INC_ACT_PENDING)
6582 plci->NL.RNR = 1; /* flow control */
6583 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6588 if(!APPLptr) /* no application or invalid data */
6589 { /* while reloading the DSP */
6590 dbug(1,dprintf("discard1"));
6595 if (((plci->NL.Ind &0x0f) == N_UDATA)
6596 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6597 || (plci->B2_prot == 7)
6598 || (plci->B3_prot == 7)) )
6600 plci->ncpi_buffer[0] = 0;
6602 ncpi_state = plci->ncpi_state;
6603 if (plci->NL.complete == 1)
6605 byte * data = &plci->NL.RBuffer->P[0];
6607 if ((plci->NL.RBuffer->length >= 12)
6608 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6609 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6611 word conn_opt, ncpi_opt = 0x00;
6612 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6614 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6615 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6616 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6617 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6619 data++; /* indication code */
6620 data += 2; /* timestamp */
6621 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6622 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6623 data++; /* connected norm */
6624 conn_opt = GET_WORD(data);
6625 data += 2; /* connected options */
6627 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6629 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6631 ncpi_opt |= MDM_NCPI_ECM_V42;
6633 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6635 ncpi_opt |= MDM_NCPI_ECM_MNP;
6639 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6641 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6643 ncpi_opt |= MDM_NCPI_COMPRESSED;
6645 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6646 plci->ncpi_buffer[0] = 4;
6648 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6651 if (plci->B3_prot == 7)
6653 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6654 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6655 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6657 a->ncci_state[ncci] = INC_ACT_PENDING;
6658 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6659 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6663 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6664 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6665 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6666 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6674 if(plci->NL.complete == 2)
6676 if (((plci->NL.Ind &0x0f) == N_UDATA)
6677 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6679 switch(plci->RData[0].P[0])
6682 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6683 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6684 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6686 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6687 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6688 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6690 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6691 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6693 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6694 dtmf_confirmation (Id, plci);
6698 case UDATA_INDICATION_MIXER_TAP_DATA:
6699 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6700 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6703 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6704 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6709 case UDATA_INDICATION_MIXER_COEFS_SET:
6710 mixer_indication_coefs_set (Id, plci);
6712 case UDATA_INDICATION_XCONNECT_FROM:
6713 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6715 case UDATA_INDICATION_XCONNECT_TO:
6716 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6720 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6721 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6732 if ((plci->RData[0].PLength != 0)
6733 && ((plci->B2_prot == B2_V120_ASYNC)
6734 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6735 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6738 sendf(plci->appl,_DATA_B3_I,Id,0,
6741 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6749 sendf(plci->appl,_DATA_B3_I,Id,0,
6752 plci->RData[0].PLength,
6761 fax_feature_bits = 0;
6762 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6763 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6764 (plci->NL.Ind &0x0f)==N_DISC ||
6765 (plci->NL.Ind &0x0f)==N_EDATA ||
6766 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6769 plci->ncpi_buffer[0] = 0;
6770 switch (plci->B3_prot) {
6773 break; /* no network control protocol info - jfr */
6776 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6777 plci->ncpi_buffer[0] = (byte)(i+3);
6778 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6779 plci->ncpi_buffer[2] = 0;
6780 plci->ncpi_buffer[3] = 0;
6782 case 4: /*T.30 - FAX*/
6783 case 5: /*T.30 - FAX*/
6784 if(plci->NL.RLength>=sizeof(T30_INFO))
6786 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6788 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6789 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6790 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6791 if (plci->B3_prot == 5)
6793 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6794 i |= 0x8000; /* This is not an ECM connection */
6795 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6796 i |= 0x4000; /* This is a connection with MMR compression */
6797 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6798 i |= 0x2000; /* This is a connection with MR compression */
6799 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6800 i |= 0x0004; /* More documents */
6801 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6802 i |= 0x0002; /* Fax-polling indication */
6804 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6805 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6806 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6807 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6808 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6809 plci->ncpi_buffer[len] = 0;
6810 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6812 plci->ncpi_buffer[len] = 20;
6813 for (i = 0; i < 20; i++)
6814 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6816 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6818 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6819 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6821 info = _FAX_PROTOCOL_ERROR;
6824 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6825 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6827 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6828 while (i < plci->NL.RBuffer->length)
6829 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6832 plci->ncpi_buffer[0] = len;
6833 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6834 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6836 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6837 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6838 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6839 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6840 || (((plci->NL.Ind &0x0f) == N_EDATA)
6841 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6842 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6843 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6845 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6847 if (((plci->NL.Ind &0x0f) == N_DISC)
6848 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6849 || (((plci->NL.Ind &0x0f) == N_EDATA)
6850 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6852 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6858 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6860 if (plci->NL.RLength != 0)
6862 info = rtp_info[plci->NL.RBuffer->P[0]];
6863 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6864 for (i = 1; i < plci->NL.RLength; i++)
6865 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6873 switch(plci->NL.Ind &0x0f) {
6875 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6877 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6878 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6879 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6881 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6882 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6883 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6884 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6885 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6886 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6888 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6889 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6890 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6891 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6892 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6893 fax_send_edata_ack = false;
6896 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6898 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6901 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6902 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6903 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6904 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6906 a->ncci_state[ncci] = INC_ACT_PENDING;
6907 if (plci->B3_prot == 4)
6908 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6910 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6911 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6915 case EDATA_T30_TRAIN_OK:
6916 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6917 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6920 if (plci->B3_prot == 4)
6921 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6923 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6924 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6928 case EDATA_T30_EOP_CAPI:
6929 if (a->ncci_state[ncci] == CONNECTED)
6931 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6932 a->ncci_state[ncci] = INC_DIS_PENDING;
6933 plci->ncpi_state = 0;
6934 fax_send_edata_ack = false;
6941 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6943 case EDATA_T30_TRAIN_OK:
6944 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6945 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6946 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6948 if (plci->B3_prot == 4)
6949 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6951 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6952 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6957 if (fax_send_edata_ack)
6959 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6960 plci->fax_edata_ack_length = 1;
6961 start_internal_command (Id, plci, fax_edata_ack_command);
6966 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6970 if (!a->ch_ncci[ch])
6972 ncci = get_ncci (plci, ch, 0);
6973 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6975 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6976 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6978 msg = _CONNECT_B3_I;
6979 if (a->ncci_state[ncci] == IDLE)
6981 else if (plci->B3_prot == 1)
6982 msg = _CONNECT_B3_T90_ACTIVE_I;
6984 a->ncci_state[ncci] = INC_CON_PENDING;
6985 if(plci->B3_prot == 4)
6986 sendf(plci->appl,msg,Id,0,"s","");
6988 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6991 dbug(1,dprintf("N_connect_Ack"));
6992 if (plci->internal_command_queue[0]
6993 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6994 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6995 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6997 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6998 if (!plci->internal_command)
6999 next_internal_command (Id, plci);
7002 msg = _CONNECT_B3_ACTIVE_I;
7003 if (plci->B3_prot == 1)
7005 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7006 msg = _CONNECT_B3_T90_ACTIVE_I;
7007 a->ncci_state[ncci] = INC_ACT_PENDING;
7008 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7010 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7012 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7013 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7014 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7016 a->ncci_state[ncci] = INC_ACT_PENDING;
7017 if (plci->B3_prot == 4)
7018 sendf(plci->appl,msg,Id,0,"s","");
7020 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7021 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7026 a->ncci_state[ncci] = INC_ACT_PENDING;
7027 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7029 if (plci->adjust_b_restore)
7031 plci->adjust_b_restore = false;
7032 start_internal_command (Id, plci, adjust_b_restore);
7037 if (plci->internal_command_queue[0]
7038 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7039 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7040 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7042 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7043 if (!plci->internal_command)
7044 next_internal_command (Id, plci);
7046 ncci_state = a->ncci_state[ncci];
7047 ncci_remove (plci, ncci, false);
7049 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7050 /* channel, so we cannot store the state in ncci_state! The */
7051 /* information which channel we received a N_DISC is thus */
7052 /* stored in the inc_dis_ncci_table buffer. */
7053 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7054 plci->inc_dis_ncci_table[i] = (byte) ncci;
7056 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7058 && (plci->B1_resource == 16)
7059 && (plci->State <= CONNECTED))
7062 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7063 PUT_WORD (&plci->ncpi_buffer[1], i);
7064 PUT_WORD (&plci->ncpi_buffer[3], 0);
7065 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7066 PUT_WORD (&plci->ncpi_buffer[5], i);
7067 PUT_WORD (&plci->ncpi_buffer[7], 0);
7068 plci->ncpi_buffer[len] = 0;
7069 plci->ncpi_buffer[0] = len;
7070 if(plci->B3_prot == 4)
7071 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7075 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7076 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7078 plci->ncpi_buffer[++len] = 0;
7079 plci->ncpi_buffer[++len] = 0;
7080 plci->ncpi_buffer[++len] = 0;
7081 plci->ncpi_buffer[0] = len;
7084 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7086 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7087 plci->ncpi_state = 0;
7088 sig_req(plci,HANGUP,0);
7090 plci->State = OUTG_DIS_PENDING;
7093 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7094 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7095 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7097 if (ncci_state == IDLE)
7101 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7102 if(plci->State == SUSPENDING){
7107 "ws", (word)3, "\x03\x04\x00\x00");
7108 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7115 else if (plci->channels)
7117 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7118 plci->ncpi_state = 0;
7119 if ((ncci_state == OUTG_REJ_PENDING)
7120 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7122 sig_req(plci,HANGUP,0);
7124 plci->State = OUTG_DIS_PENDING;
7129 a->ncci_state[ncci] = INC_RES_PENDING;
7130 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7133 a->ncci_state[ncci] = CONNECTED;
7134 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7138 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7140 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7141 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7142 plci->NL.R = plci->RData;
7148 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7149 || (a->ncci_state[ncci] == IDLE)
7150 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7155 if ((a->ncci_state[ncci] != CONNECTED)
7156 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7157 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7159 dbug(1,dprintf("flow control"));
7160 plci->NL.RNR = 1; /* flow control */
7161 channel_x_off (plci, ch, 0);
7165 NCCIcode = ncci | (((word)a->Id) << 8);
7167 /* count all buffers within the Application pool */
7168 /* belonging to the same NCCI. If this is below the */
7169 /* number of buffers available per NCCI we accept */
7170 /* this packet, otherwise we reject it */
7173 for(i=0; i<APPLptr->MaxBuffer; i++) {
7174 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7175 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7178 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7180 dbug(3,dprintf("Flow-Control"));
7182 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7183 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7186 dbug(3,dprintf("DiscardData"));
7188 channel_x_off (plci, ch, 0);
7194 APPLptr->NCCIDataFlowCtrlTimer = 0;
7197 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7198 if(!plci->RData[0].P) {
7200 channel_x_off (plci, ch, 0);
7204 APPLptr->DataNCCI[Num] = NCCIcode;
7205 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7206 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7209 plci->RFlags = plci->NL.Ind>>4;
7210 plci->RData[0].PLength = APPLptr->MaxDataLength;
7211 plci->NL.R = plci->RData;
7212 if ((plci->NL.RLength != 0)
7213 && ((plci->B2_prot == B2_V120_ASYNC)
7214 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7215 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7217 plci->RData[1].P = plci->RData[0].P;
7218 plci->RData[1].PLength = plci->RData[0].PLength;
7219 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7220 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7221 plci->RData[0].PLength = 1;
7223 plci->RData[0].PLength = 2;
7224 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7225 plci->RFlags |= 0x0010;
7226 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7227 plci->RFlags |= 0x8000;
7232 if((plci->NL.Ind &0x0f)==N_UDATA)
7233 plci->RFlags |= 0x0010;
7235 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7236 plci->RFlags |= 0x0001;
7242 data_ack (plci, ch);
7250 /*------------------------------------------------------------------*/
7251 /* find a free PLCI */
7252 /*------------------------------------------------------------------*/
7254 static word get_plci(DIVA_CAPI_ADAPTER *a)
7260 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7261 if(i==a->max_plci) {
7262 dbug(1,dprintf("get_plci: out of PLCIs"));
7266 plci->Id = (byte)(i+1);
7274 plci->relatedPTYPLCI = NULL;
7276 plci->SuppState = IDLE;
7279 plci->B1_resource = 0;
7284 plci->m_command = 0;
7285 init_internal_command_queue (plci);
7287 plci->req_in_start = 0;
7290 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7291 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7292 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7294 plci->data_sent = false;
7295 plci->send_disc = 0;
7296 plci->sig_global_req = 0;
7297 plci->sig_remove_id = 0;
7298 plci->nl_global_req = 0;
7299 plci->nl_remove_id = 0;
7301 plci->manufacturer = false;
7302 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7303 plci->spoofed_msg = 0;
7305 plci->cr_enquiry = false;
7306 plci->hangup_flow_ctrl_timer = 0;
7308 plci->ncci_ring_list = 0;
7309 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7310 clear_c_ind_mask (plci);
7311 set_group_ind_mask (plci);
7312 plci->fax_connect_info_length = 0;
7313 plci->nsf_control_bits = 0;
7314 plci->ncpi_state = 0x00;
7315 plci->ncpi_buffer[0] = 0;
7317 plci->requested_options_conn = 0;
7318 plci->requested_options = 0;
7319 plci->notifiedcall = 0;
7320 plci->vswitchstate = 0;
7322 plci->vsprotdialect = 0;
7323 init_b1_config (plci);
7324 dbug(1,dprintf("get_plci(%x)",plci->Id));
7328 /*------------------------------------------------------------------*/
7329 /* put a parameter in the parameter buffer */
7330 /*------------------------------------------------------------------*/
7332 static void add_p(PLCI * plci, byte code, byte * p)
7337 if(p) p_length = p[0];
7338 add_ie(plci, code, p, p_length);
7341 /*------------------------------------------------------------------*/
7342 /* put a structure in the parameter buffer */
7343 /*------------------------------------------------------------------*/
7344 static void add_s(PLCI * plci, byte code, API_PARSE * p)
7346 if(p) add_ie(plci, code, p->info, (word)p->length);
7349 /*------------------------------------------------------------------*/
7350 /* put multiple structures in the parameter buffer */
7351 /*------------------------------------------------------------------*/
7352 static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7357 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7358 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7359 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7360 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7365 /*------------------------------------------------------------------*/
7366 /* return the channel number sent by the application in a esc_chi */
7367 /*------------------------------------------------------------------*/
7368 static byte getChannel(API_PARSE * p)
7373 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7375 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7383 /*------------------------------------------------------------------*/
7384 /* put an information element in the parameter buffer */
7385 /*------------------------------------------------------------------*/
7387 static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7391 if(!(code &0x80) && !p_length) return;
7393 if(plci->req_in==plci->req_in_start) {
7399 plci->RBuffer[plci->req_in++] = code;
7402 plci->RBuffer[plci->req_in++] = (byte)p_length;
7403 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7406 plci->RBuffer[plci->req_in++] = 0;
7409 /*------------------------------------------------------------------*/
7410 /* put a unstructured data into the buffer */
7411 /*------------------------------------------------------------------*/
7413 static void add_d(PLCI *plci, word length, byte *p)
7417 if(plci->req_in==plci->req_in_start) {
7423 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7426 /*------------------------------------------------------------------*/
7427 /* put parameters from the Additional Info parameter in the */
7428 /* parameter buffer */
7429 /*------------------------------------------------------------------*/
7431 static void add_ai(PLCI *plci, API_PARSE *ai)
7434 API_PARSE ai_parms[5];
7436 for(i=0;i<5;i++) ai_parms[i].length = 0;
7440 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7443 add_s (plci,KEY,&ai_parms[1]);
7444 add_s (plci,UUI,&ai_parms[2]);
7445 add_ss(plci,FTY,&ai_parms[3]);
7448 /*------------------------------------------------------------------*/
7449 /* put parameter for b1 protocol in the parameter buffer */
7450 /*------------------------------------------------------------------*/
7452 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7455 API_PARSE bp_parms[8];
7456 API_PARSE mdm_cfg[9];
7457 API_PARSE global_config[2];
7459 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7460 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7463 API_PARSE mdm_cfg_v18[4];
7468 for(i=0;i<8;i++) bp_parms[i].length = 0;
7469 for(i=0;i<2;i++) global_config[i].length = 0;
7471 dbug(1,dprintf("add_b1"));
7472 api_save_msg(bp, "s", &plci->B_protocol);
7474 if(b_channel_info==2){
7475 plci->B1_resource = 0;
7476 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7477 add_p(plci, CAI, "\x01\x00");
7478 dbug(1,dprintf("Cai=1,0 (no resource)"));
7482 if(plci->tel == CODEC_PERMANENT) return 0;
7483 else if(plci->tel == CODEC){
7484 plci->B1_resource = 1;
7485 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7486 add_p(plci, CAI, "\x01\x01");
7487 dbug(1,dprintf("Cai=1,1 (Codec)"));
7490 else if(plci->tel == ADV_VOICE){
7491 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7492 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7493 voice_cai[1] = plci->B1_resource;
7494 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7495 add_p(plci, CAI, voice_cai);
7496 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7499 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7500 if (plci->call_dir & CALL_DIR_OUT)
7501 plci->call_dir |= CALL_DIR_ORIGINATE;
7502 else if (plci->call_dir & CALL_DIR_IN)
7503 plci->call_dir |= CALL_DIR_ANSWER;
7506 plci->B1_resource = 0x5;
7507 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7508 add_p(plci, CAI, "\x01\x05");
7512 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7513 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7514 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7516 bp_parms[6].length = 0;
7517 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7519 dbug(1,dprintf("b-form.!"));
7520 return _WRONG_MESSAGE_FORMAT;
7523 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7525 dbug(1,dprintf("b-form.!"));
7526 return _WRONG_MESSAGE_FORMAT;
7529 if(bp_parms[6].length)
7531 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7533 return _WRONG_MESSAGE_FORMAT;
7535 switch(GET_WORD(global_config[0].info))
7538 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7541 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7545 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7548 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7549 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7551 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7552 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7553 cai[1] = plci->B1_resource;
7557 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7558 for (i = 0; i < bp_parms[3].length; i++)
7559 cai[7+i] = bp_parms[3].info[1+i];
7560 cai[0] = 6 + bp_parms[3].length;
7561 add_p(plci, CAI, cai);
7566 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7567 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7569 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7570 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7571 cai[1] = plci->B1_resource;
7575 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7577 add_p(plci, CAI, cai);
7582 if ((GET_WORD(bp_parms[0].info) >= 32)
7583 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7584 && ((GET_WORD(bp_parms[0].info) != 3)
7585 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7586 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7588 return _B1_NOT_SUPPORTED;
7590 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7591 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7592 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7594 cai[1] = plci->B1_resource;
7595 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7597 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7598 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7599 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7601 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7603 if (bp_parms[3].length)
7605 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7607 return (_WRONG_MESSAGE_FORMAT);
7610 cai[2] = 0; /* Bit rate for adaptation */
7612 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7614 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7615 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7616 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7617 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7619 cai[3] = 0; /* Async framing parameters */
7620 switch (GET_WORD (mdm_cfg[2].info))
7622 case 1: /* odd parity */
7623 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7624 dbug(1,dprintf("MDM: odd parity"));
7627 case 2: /* even parity */
7628 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7629 dbug(1,dprintf("MDM: even parity"));
7633 dbug(1,dprintf("MDM: no parity"));
7637 switch (GET_WORD (mdm_cfg[3].info))
7639 case 1: /* 2 stop bits */
7640 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7641 dbug(1,dprintf("MDM: 2 stop bits"));
7645 dbug(1,dprintf("MDM: 1 stop bit"));
7649 switch (GET_WORD (mdm_cfg[1].info))
7652 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7653 dbug(1,dprintf("MDM: 5 bits"));
7657 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7658 dbug(1,dprintf("MDM: 6 bits"));
7662 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7663 dbug(1,dprintf("MDM: 7 bits"));
7667 dbug(1,dprintf("MDM: 8 bits"));
7671 cai[7] = 0; /* Line taking options */
7672 cai[8] = 0; /* Modulation negotiation options */
7673 cai[9] = 0; /* Modulation options */
7675 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7677 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7678 dbug(1, dprintf("MDM: Reverse direction"));
7681 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7683 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7684 dbug(1, dprintf("MDM: Disable retrain"));
7687 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7689 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7690 dbug(1, dprintf("MDM: Disable ring tone"));
7693 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7695 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7696 dbug(1, dprintf("MDM: 1800 guard tone"));
7698 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7700 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7701 dbug(1, dprintf("MDM: 550 guard tone"));
7704 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7706 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7707 dbug(1, dprintf("MDM: V100"));
7709 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7711 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7712 dbug(1, dprintf("MDM: IN CLASS"));
7714 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7716 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7717 dbug(1, dprintf("MDM: DISABLED"));
7721 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7722 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7724 plci->requested_options |= 1L << PRIVATE_V18;
7726 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7727 plci->requested_options |= 1L << PRIVATE_VOWN;
7729 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7730 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7732 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7735 if (mdm_cfg[6].length >= 4)
7737 d = GET_DWORD(&mdm_cfg[6].info[1]);
7738 cai[7] |= (byte) d; /* line taking options */
7739 cai[9] |= (byte)(d >> 8); /* modulation options */
7740 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7741 cai[++i] = (byte)(d >> 24);
7742 if (mdm_cfg[6].length >= 8)
7744 d = GET_DWORD(&mdm_cfg[6].info[5]);
7745 cai[10] |= (byte) d; /* disabled modulations mask */
7746 cai[11] |= (byte)(d >> 8);
7747 if (mdm_cfg[6].length >= 12)
7749 d = GET_DWORD(&mdm_cfg[6].info[9]);
7750 cai[12] = (byte) d; /* enabled modulations mask */
7751 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7752 cai[++i] = (byte)(d >> 16);
7753 cai[++i] = (byte)(d >> 24);
7755 if (mdm_cfg[6].length >= 14)
7757 w = GET_WORD(&mdm_cfg[6].info[13]);
7759 PUT_WORD(&cai[13], w); /* min tx speed */
7760 if (mdm_cfg[6].length >= 16)
7762 w = GET_WORD(&mdm_cfg[6].info[15]);
7764 PUT_WORD(&cai[15], w); /* max tx speed */
7765 if (mdm_cfg[6].length >= 18)
7767 w = GET_WORD(&mdm_cfg[6].info[17]);
7769 PUT_WORD(&cai[17], w); /* min rx speed */
7770 if (mdm_cfg[6].length >= 20)
7772 w = GET_WORD(&mdm_cfg[6].info[19]);
7774 PUT_WORD(&cai[19], w); /* max rx speed */
7775 if (mdm_cfg[6].length >= 22)
7777 w = GET_WORD(&mdm_cfg[6].info[21]);
7778 cai[23] = (byte)(-((short) w)); /* transmit level */
7779 if (mdm_cfg[6].length >= 24)
7781 w = GET_WORD(&mdm_cfg[6].info[23]);
7782 cai[22] |= (byte) w; /* info options mask */
7783 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7795 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7797 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7799 for (n = 0; n < 3; n++)
7801 cai[i] = (byte)(mdm_cfg_v18[n].length);
7802 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7803 cai[i+j] = mdm_cfg_v18[n].info[j];
7808 cai[0] = (byte)(i - 1);
7814 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7815 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7817 if(bp_parms[3].length){
7818 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7819 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7822 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7823 dbug(1,dprintf("56k sync HSCX"));
7828 else if(GET_WORD(bp_parms[0].info)==2){
7829 dbug(1,dprintf("56k async DSP"));
7833 case 50: cai[2] = 1; break;
7834 case 75: cai[2] = 1; break;
7835 case 110: cai[2] = 1; break;
7836 case 150: cai[2] = 1; break;
7837 case 200: cai[2] = 1; break;
7838 case 300: cai[2] = 1; break;
7839 case 600: cai[2] = 1; break;
7840 case 1200: cai[2] = 2; break;
7841 case 2400: cai[2] = 3; break;
7842 case 4800: cai[2] = 4; break;
7843 case 7200: cai[2] = 10; break;
7844 case 9600: cai[2] = 5; break;
7845 case 12000: cai[2] = 13; break;
7846 case 24000: cai[2] = 0; break;
7847 case 14400: cai[2] = 11; break;
7848 case 19200: cai[2] = 6; break;
7849 case 28800: cai[2] = 12; break;
7850 case 38400: cai[2] = 7; break;
7851 case 48000: cai[2] = 8; break;
7852 case 76: cai[2] = 15; break; /* 75/1200 */
7853 case 1201: cai[2] = 14; break; /* 1200/75 */
7854 case 56001: cai[2] = 9; break; /* V.110 56000 */
7857 return _B1_PARM_NOT_SUPPORTED;
7860 if (cai[1] == 13) /* v.110 async */
7862 if (bp_parms[3].length >= 8)
7864 switch (GET_WORD (&bp_parms[3].info[3]))
7867 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7870 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7873 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7876 switch (GET_WORD (&bp_parms[3].info[5]))
7878 case 1: /* odd parity */
7879 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7881 case 2: /* even parity */
7882 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7885 switch (GET_WORD (&bp_parms[3].info[7]))
7887 case 1: /* 2 stop bits */
7888 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7894 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7895 dbug(1,dprintf("V.110 default 56k sync"));
7901 dbug(1,dprintf("V.110 default 9600 async"));
7905 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7906 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]));
7907 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7909 add_p(plci, CAI, cai);
7913 /*------------------------------------------------------------------*/
7914 /* put parameter for b2 and B3 protocol in the parameter buffer */
7915 /*------------------------------------------------------------------*/
7917 static word add_b23(PLCI *plci, API_PARSE *bp)
7919 word i, fax_control_bits;
7921 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7922 API_PARSE bp_parms[8];
7923 API_PARSE * b1_config;
7924 API_PARSE * b2_config;
7925 API_PARSE b2_config_parms[8];
7926 API_PARSE * b3_config;
7927 API_PARSE b3_config_parms[6];
7928 API_PARSE global_config[2];
7930 static byte llc[3] = {2,0,0};
7931 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7932 static byte nlc[256];
7933 static byte lli[12] = {1,1};
7935 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7936 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7938 const byte llc3[] = {4,3,2,2,6,6,0};
7939 const byte header[] = {0,2,3,3,0,0,0};
7941 for(i=0;i<8;i++) bp_parms[i].length = 0;
7942 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7943 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7947 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7949 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7952 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7954 if (plci->rx_dma_descriptor <= 0) {
7955 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7956 if (plci->rx_dma_descriptor >= 0)
7957 plci->rx_dma_descriptor++;
7959 if (plci->rx_dma_descriptor > 0) {
7962 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7963 lli[3] = (byte)plci->rx_dma_magic;
7964 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7965 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7966 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7970 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7974 dbug(1,dprintf("add_b23"));
7975 api_save_msg(bp, "s", &plci->B_protocol);
7977 if(!bp->length && plci->tel)
7979 plci->adv_nl = true;
7980 dbug(1,dprintf("Default adv.Nl"));
7981 add_p(plci,LLI,lli);
7982 plci->B2_prot = 1 /*XPARENT*/;
7983 plci->B3_prot = 0 /*XPARENT*/;
7986 add_p(plci, LLC, llc);
7988 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7989 add_p(plci, DLC, dlc);
7993 if(!bp->length) /*default*/
7995 dbug(1,dprintf("ret default"));
7996 add_p(plci,LLI,lli);
7997 plci->B2_prot = 0 /*X.75 */;
7998 plci->B3_prot = 0 /*XPARENT*/;
8001 add_p(plci, LLC, llc);
8003 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8004 add_p(plci, DLC, dlc);
8007 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8008 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8010 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8012 bp_parms[6].length = 0;
8013 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8015 dbug(1,dprintf("b-form.!"));
8016 return _WRONG_MESSAGE_FORMAT;
8019 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8021 dbug(1,dprintf("b-form.!"));
8022 return _WRONG_MESSAGE_FORMAT;
8025 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8027 if(GET_WORD(bp_parms[1].info)!=1
8028 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8029 plci->adv_nl = true;
8031 else if(plci->tel) return _B2_NOT_SUPPORTED;
8034 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8035 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8036 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8038 add_p(plci,LLI,lli);
8039 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8040 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8041 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8043 add_p(plci, LLC, llc);
8045 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8046 dlc[3] = 3; /* Addr A */
8047 dlc[4] = 1; /* Addr B */
8048 dlc[5] = 7; /* modulo mode */
8049 dlc[6] = 7; /* window size */
8050 dlc[7] = 0; /* XID len Lo */
8051 dlc[8] = 0; /* XID len Hi */
8052 for (i = 0; i < bp_parms[4].length; i++)
8053 dlc[9+i] = bp_parms[4].info[1+i];
8054 dlc[0] = (byte)(8 + bp_parms[4].length);
8055 add_p(plci, DLC, dlc);
8056 for (i = 0; i < bp_parms[5].length; i++)
8057 nlc[1+i] = bp_parms[5].info[1+i];
8058 nlc[0] = (byte)(bp_parms[5].length);
8059 add_p(plci, NLC, nlc);
8065 if ((GET_WORD(bp_parms[1].info) >= 32)
8066 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8067 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8068 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8071 return _B2_NOT_SUPPORTED;
8073 if ((GET_WORD(bp_parms[2].info) >= 32)
8074 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8076 return _B3_NOT_SUPPORTED;
8078 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8079 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8080 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8081 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8083 return (add_modem_b23 (plci, bp_parms));
8086 add_p(plci,LLI,lli);
8088 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8089 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8090 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8092 if(bp_parms[6].length)
8094 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8096 return _WRONG_MESSAGE_FORMAT;
8098 switch(GET_WORD(global_config[0].info))
8101 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8104 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8108 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8111 if (plci->B2_prot == B2_PIAFS)
8114 /* IMPLEMENT_PIAFS */
8116 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8117 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8119 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8121 add_p(plci, LLC, llc);
8124 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8125 header[GET_WORD(bp_parms[2].info)]);
8127 b1_config = &bp_parms[3];
8129 if(plci->B3_prot == 4
8130 || plci->B3_prot == 5)
8132 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8133 nlc[0] = sizeof(T30_INFO);
8134 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8135 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8136 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8137 if(b1_config->length>=2)
8139 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8142 b2_config = &bp_parms[4];
8145 if (llc[1] == PIAFS_CRC)
8147 if (plci->B3_prot != B3_TRANSPARENT)
8149 return _B_STACK_NOT_SUPPORTED;
8151 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8152 return _WRONG_MESSAGE_FORMAT;
8154 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8155 dlc[3] = 0; /* Addr A */
8156 dlc[4] = 0; /* Addr B */
8157 dlc[5] = 0; /* modulo mode */
8158 dlc[6] = 0; /* window size */
8159 if (b2_config->length >= 7){
8162 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8163 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8164 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8165 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8166 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8167 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8168 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8170 if(b2_config->length >= 8) { /* PIAFS control abilities */
8172 dlc[16] = 2; /* Length of PIAFS extention */
8173 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8174 dlc[18] = b2_config_parms[4].info[0]; /* value */
8178 else /* default values, 64K, variable, no compression */
8182 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8183 dlc[10] = 0x03; /* V.42bis P0 */
8184 dlc[11] = 0; /* V.42bis P0 */
8185 dlc[12] = 0; /* V.42bis P1 */
8186 dlc[13] = 0; /* V.42bis P1 */
8187 dlc[14] = 0; /* V.42bis P2 */
8188 dlc[15] = 0; /* V.42bis P2 */
8191 add_p(plci, DLC, dlc);
8195 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8197 if (plci->B3_prot != B3_TRANSPARENT)
8198 return _B_STACK_NOT_SUPPORTED;
8201 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8206 if (b2_config->length != 0)
8208 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8209 return _WRONG_MESSAGE_FORMAT;
8211 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8212 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8213 if (b2_config->info[3] != 128)
8215 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8216 return _B2_PARM_NOT_SUPPORTED;
8218 dlc[5] = (byte)(b2_config->info[3] - 1);
8219 dlc[6] = b2_config->info[4];
8220 if(llc[1]==V120_V42BIS){
8221 if (b2_config->length >= 10){
8224 dlc[ 9] = b2_config_parms[4].info[0];
8225 dlc[10] = b2_config_parms[4].info[1];
8226 dlc[11] = b2_config_parms[5].info[0];
8227 dlc[12] = b2_config_parms[5].info[1];
8228 dlc[13] = b2_config_parms[6].info[0];
8229 dlc[14] = b2_config_parms[6].info[1];
8231 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8232 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8233 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8243 if(b2_config->length)
8245 dbug(1,dprintf("B2-Config"));
8246 if(llc[1]==X75_V42BIS){
8247 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8249 return _WRONG_MESSAGE_FORMAT;
8253 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8255 return _WRONG_MESSAGE_FORMAT;
8258 /* if B2 Protocol is LAPD, b2_config structure is different */
8262 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8264 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8266 SAPI = b2_config->info[2]; /* SAPI */
8269 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8271 dlc[3] = 127; /* Mode */
8275 dlc[3] = 7; /* Mode */
8278 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8280 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8281 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8285 dlc[0] = (byte)(b2_config_parms[4].length+6);
8286 dlc[3] = b2_config->info[1];
8287 dlc[4] = b2_config->info[2];
8288 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8289 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8290 return _B2_PARM_NOT_SUPPORTED;
8293 dlc[5] = (byte)(b2_config->info[3]-1);
8294 dlc[6] = b2_config->info[4];
8296 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]));
8297 return _B2_PARM_NOT_SUPPORTED;
8300 if(llc[1]==X75_V42BIS) {
8301 if (b2_config->length >= 10){
8304 dlc[ 9] = b2_config_parms[4].info[0];
8305 dlc[10] = b2_config_parms[4].info[1];
8306 dlc[11] = b2_config_parms[5].info[0];
8307 dlc[12] = b2_config_parms[5].info[1];
8308 dlc[13] = b2_config_parms[6].info[0];
8309 dlc[14] = b2_config_parms[6].info[1];
8311 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8312 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8313 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8321 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8322 for(i=0; i<b2_config_parms[4].length; i++)
8323 dlc[11+i] = b2_config_parms[4].info[1+i];
8328 add_p(plci, DLC, dlc);
8330 b3_config = &bp_parms[5];
8331 if(b3_config->length)
8333 if(plci->B3_prot == 4
8334 || plci->B3_prot == 5)
8336 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8338 return _WRONG_MESSAGE_FORMAT;
8340 i = GET_WORD((byte *)(b3_config_parms[0].info));
8341 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8342 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8343 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8344 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8345 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8346 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8347 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8350 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8351 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8353 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8354 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8355 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8358 ((T30_INFO *)&nlc[1])->recording_properties =
8359 T30_RECORDING_WIDTH_ISO_A3 |
8360 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8361 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8363 if(plci->B3_prot == 5)
8365 if (i & 0x0002) /* Accept incoming fax-polling requests */
8366 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8367 if (i & 0x2000) /* Do not use MR compression */
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8369 if (i & 0x4000) /* Do not use MMR compression */
8370 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8371 if (i & 0x8000) /* Do not use ECM */
8372 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8373 if (plci->fax_connect_info_length != 0)
8375 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8376 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8377 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8378 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8379 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8382 /* copy station id to NLC */
8385 if(i<b3_config_parms[2].length)
8387 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8391 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8394 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8395 /* copy head line to NLC */
8396 if(b3_config_parms[3].length)
8399 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8402 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8406 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8407 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8408 len = (byte)b3_config_parms[2].length;
8411 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8413 for (i = 0; i < len; i++)
8414 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8415 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8416 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8421 len = (byte)b3_config_parms[3].length;
8422 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8423 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8424 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8425 nlc[0] += (byte)(pos + len);
8426 for (i = 0; i < len; i++)
8427 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8430 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8432 plci->nsf_control_bits = 0;
8433 if(plci->B3_prot == 5)
8435 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8436 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8438 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8440 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8441 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8443 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8445 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8446 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8448 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8449 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8452 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8453 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8456 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8457 if (pos < plci->fax_connect_info_length)
8459 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8460 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8464 if (pos < plci->fax_connect_info_length)
8466 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8467 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8471 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8472 & (1L << PRIVATE_FAX_NONSTANDARD))
8474 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8476 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8477 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8478 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8479 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8483 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8485 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8490 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8491 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8492 nlc[++len] = (byte)(b3_config_parms[4].length);
8493 for (i = 0; i < b3_config_parms[4].length; i++)
8494 nlc[++len] = b3_config_parms[4].info[1+i];
8499 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8500 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8502 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8507 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8508 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8509 for (i = 0; i < len; i++)
8510 plci->fax_connect_info_buffer[i] = nlc[1+i];
8511 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8512 i += ((T30_INFO *)&nlc[1])->head_line_len;
8514 plci->fax_connect_info_buffer[len++] = nlc[++i];
8515 plci->fax_connect_info_length = len;
8520 if(b3_config->length!=16)
8521 return _B3_PARM_NOT_SUPPORTED;
8522 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8523 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8524 return _B3_PARM_NOT_SUPPORTED;
8525 nlc[13] = b3_config->info[13];
8526 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8527 return _B3_PARM_NOT_SUPPORTED;
8528 nlc[14] = b3_config->info[15];
8533 if (plci->B3_prot == 4
8534 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8536 add_p(plci, NLC, nlc);
8540 /*----------------------------------------------------------------*/
8541 /* make the same as add_b23, but only for the modem related */
8542 /* L2 and L3 B-Chan protocol. */
8544 /* Enabled L2 and L3 Configurations: */
8545 /* If L1 == Modem all negotiation */
8546 /* only L2 == Modem with full negotiation is allowed */
8547 /* If L1 == Modem async or sync */
8548 /* only L2 == Transparent is allowed */
8549 /* L3 == Modem or L3 == Transparent are allowed */
8550 /* B2 Configuration for modem: */
8551 /* word : enable/disable compression, bitoptions */
8552 /* B3 Configuration for modem: */
8554 /*----------------------------------------------------------------*/
8555 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8557 static byte lli[12] = {1,1};
8558 static byte llc[3] = {2,0,0};
8559 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8560 API_PARSE mdm_config[2];
8564 for(i=0;i<2;i++) mdm_config[i].length = 0;
8565 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8567 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8568 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8569 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8570 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8572 return (_B_STACK_NOT_SUPPORTED);
8574 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8575 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8577 return (_B_STACK_NOT_SUPPORTED);
8580 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8581 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8583 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8585 if (api_parse (&bp_parms[4].info[1],
8586 (word)bp_parms[4].length, "w",
8589 return (_WRONG_MESSAGE_FORMAT);
8591 b2_config = GET_WORD(mdm_config[0].info);
8594 /* OK, L2 is modem */
8598 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8600 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8603 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8605 if (plci->rx_dma_descriptor <= 0) {
8606 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8607 if (plci->rx_dma_descriptor >= 0)
8608 plci->rx_dma_descriptor++;
8610 if (plci->rx_dma_descriptor > 0) {
8613 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8614 lli[3] = (byte)plci->rx_dma_magic;
8615 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8616 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8617 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8621 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8625 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8626 /*V42*/ 10 : /*V42_IN*/ 9;
8627 llc[2] = 4; /* pass L3 always transparent */
8628 add_p(plci, LLI, lli);
8629 add_p(plci, LLC, llc);
8631 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8633 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8635 if (bp_parms[4].length)
8637 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8638 dlc[i++] = 3; /* Addr A */
8639 dlc[i++] = 1; /* Addr B */
8640 dlc[i++] = 7; /* modulo mode */
8641 dlc[i++] = 7; /* window size */
8642 dlc[i++] = 0; /* XID len Lo */
8643 dlc[i++] = 0; /* XID len Hi */
8645 if (b2_config & MDM_B2_DISABLE_V42bis)
8647 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8649 if (b2_config & MDM_B2_DISABLE_MNP)
8651 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8653 if (b2_config & MDM_B2_DISABLE_TRANS)
8655 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8657 if (b2_config & MDM_B2_DISABLE_V42)
8659 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8661 if (b2_config & MDM_B2_DISABLE_COMP)
8663 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8670 dlc[i++] = 3; /* Addr A */
8671 dlc[i++] = 1; /* Addr B */
8672 dlc[i++] = 7; /* modulo mode */
8673 dlc[i++] = 7; /* window size */
8674 dlc[i++] = 0; /* XID len Lo */
8675 dlc[i++] = 0; /* XID len Hi */
8676 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8677 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8678 DLC_MODEMPROT_DISABLE_V42_DETECT |
8679 DLC_MODEMPROT_DISABLE_COMPRESSION;
8681 dlc[0] = (byte)(i - 1);
8682 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8683 add_p(plci, DLC, dlc);
8688 /*------------------------------------------------------------------*/
8689 /* send a request for the signaling entity */
8690 /*------------------------------------------------------------------*/
8692 void sig_req(PLCI * plci, byte req, byte Id)
8695 if(plci->adapter->adapter_disabled) return;
8696 dbug(1,dprintf("sig_req(%x)",req));
8698 plci->sig_remove_id = plci->Sig.Id;
8699 if(plci->req_in==plci->req_in_start) {
8701 plci->RBuffer[plci->req_in++] = 0;
8703 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8704 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8705 plci->RBuffer[plci->req_in++] = req; /* request */
8706 plci->RBuffer[plci->req_in++] = 0; /* channel */
8707 plci->req_in_start = plci->req_in;
8710 /*------------------------------------------------------------------*/
8711 /* send a request for the network layer entity */
8712 /*------------------------------------------------------------------*/
8714 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8717 if(plci->adapter->adapter_disabled) return;
8718 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8721 plci->nl_remove_id = plci->NL.Id;
8722 ncci_remove (plci, 0, (byte)(ncci != 0));
8725 if(plci->req_in==plci->req_in_start) {
8727 plci->RBuffer[plci->req_in++] = 0;
8729 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8730 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8731 plci->RBuffer[plci->req_in++] = req; /* request */
8732 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8733 plci->req_in_start = plci->req_in;
8736 static void send_req(PLCI *plci)
8743 if(plci->adapter->adapter_disabled) return;
8744 channel_xmit_xon (plci);
8746 /* if nothing to do, return */
8747 if(plci->req_in==plci->req_out) return;
8748 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8750 if(plci->nl_req || plci->sig_req) return;
8752 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8754 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8756 if(plci->RBuffer[plci->req_out]==1)
8760 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8761 e->ReqCh = plci->RBuffer[plci->req_out++];
8765 plci->RBuffer[plci->req_out-4] = CAI;
8766 plci->RBuffer[plci->req_out-3] = 1;
8767 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8768 plci->RBuffer[plci->req_out-1] = 0;
8770 plci->nl_global_req = plci->nl_req;
8772 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8777 if(plci->RBuffer[plci->req_out])
8778 e->Id = plci->RBuffer[plci->req_out];
8780 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8781 e->ReqCh = plci->RBuffer[plci->req_out++];
8783 plci->sig_global_req = plci->sig_req;
8784 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8786 plci->XData[0].PLength = l;
8788 plci->adapter->request(e);
8789 dbug(1,dprintf("send_ok"));
8792 void send_data(PLCI * plci)
8794 DIVA_CAPI_ADAPTER * a;
8795 DATA_B3_DESC * data;
8799 if (!plci->nl_req && plci->ncci_ring_list)
8802 ncci = plci->ncci_ring_list;
8805 ncci = a->ncci_next[ncci];
8806 ncci_ptr = &(a->ncci[ncci]);
8807 if (!(a->ncci_ch[ncci]
8808 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8810 if (ncci_ptr->data_pending)
8812 if ((a->ncci_state[ncci] == CONNECTED)
8813 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8814 || (plci->send_disc == ncci))
8816 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8817 if ((plci->B2_prot == B2_V120_ASYNC)
8818 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8819 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8821 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8822 plci->NData[1].PLength = data->Length;
8823 if (data->Flags & 0x10)
8824 plci->NData[0].P = v120_break_header;
8826 plci->NData[0].P = v120_default_header;
8827 plci->NData[0].PLength = 1 ;
8829 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8833 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8834 plci->NData[0].PLength = data->Length;
8835 if (data->Flags & 0x10)
8836 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8838 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8839 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8842 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8844 plci->NL.X = plci->NData;
8845 plci->NL.ReqCh = a->ncci_ch[ncci];
8846 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8847 plci->data_sent = true;
8848 plci->data_sent_ptr = data->P;
8849 a->request(&plci->NL);
8852 cleanup_ncci_data (plci, ncci);
8855 else if (plci->send_disc == ncci)
8857 /* dprintf("N_DISC"); */
8858 plci->NData[0].PLength = 0;
8859 plci->NL.ReqCh = a->ncci_ch[ncci];
8860 plci->NL.Req = plci->nl_req = N_DISC;
8861 a->request(&plci->NL);
8862 plci->command = _DISCONNECT_B3_R;
8863 plci->send_disc = 0;
8866 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8867 plci->ncci_ring_list = ncci;
8871 static void listen_check(DIVA_CAPI_ADAPTER *a)
8875 byte activnotifiedcalls = 0;
8877 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8878 if (!remove_started && !a->adapter_disabled)
8880 for(i=0;i<a->max_plci;i++)
8882 plci = &(a->plci[i]);
8883 if(plci->notifiedcall) activnotifiedcalls++;
8885 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8887 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8888 if((j=get_plci(a))) {
8890 plci = &a->plci[j-1];
8891 plci->State = LISTENING;
8893 add_p(plci,OAD,"\x01\xfd");
8895 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8897 add_p(plci,CAI,"\x01\xc0");
8898 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8899 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8900 add_p(plci,SHIFT|6,NULL);
8901 add_p(plci,SIN,"\x02\x00\x00");
8902 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8903 sig_req(plci,ASSIGN,DSIG_ID);
8910 /*------------------------------------------------------------------*/
8911 /* functions for all parameters sent in INDs */
8912 /*------------------------------------------------------------------*/
8914 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8916 word ploc; /* points to current location within packet */
8928 in = plci->Sig.RBuffer->P;
8929 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8930 { /* element but parms array is larger */
8931 parms[i] = (byte *)"";
8933 for(i=0; i<multiIEsize; i++)
8935 parms[i] = (byte *)"";
8938 while(ploc<plci->Sig.RBuffer->length-1) {
8940 /* read information element id and length */
8944 /* w &=0xf0; removed, cannot detect congestion levels */
8945 /* upper 4 bit masked with w==SHIFT now */
8949 wlen = (byte)(in[ploc+1]+1);
8951 /* check if length valid (not exceeding end of packet) */
8952 if((ploc+wlen) > 270) return ;
8953 if(lock & 0x80) lock &=0x7f;
8954 else codeset = lock;
8956 if((w&0xf0)==SHIFT) {
8958 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8963 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8965 code |= (codeset<<8);
8967 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8969 if(i<parms_id[0]+1) {
8970 if(!multiIEsize) { /* with multiIEs use next field index, */
8971 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8974 parms[mIEindex] = &in[ploc+1];
8975 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8977 || parms_id[i]==CONN_NR
8978 || parms_id[i]==CAD) {
8979 if(in[ploc+2] &0x80) {
8980 in[ploc+0] = (byte)(in[ploc+1]+1);
8981 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8983 parms[mIEindex] = &in[ploc];
8986 mIEindex++; /* effects multiIEs only */
8995 /*------------------------------------------------------------------*/
8996 /* try to match a cip from received BC and HLC */
8997 /*------------------------------------------------------------------*/
8999 static byte ie_compare(byte *ie1, byte *ie2)
9002 if(!ie1 || ! ie2) return false;
9003 if(!ie1[0]) return false;
9004 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9008 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9013 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9016 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9022 static byte AddInfo(byte **add_i,
9032 /* facility is a nested structure */
9033 /* FTY can be more than once */
9035 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9037 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9042 add_i[0] = (byte *)"";
9046 add_i[3] = (byte *)"";
9049 { /* facility array found */
9050 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9052 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9056 facility[j++]=0x1c; /* copy fac IE */
9057 for(k=0;k<=flen;k++,j++)
9059 facility[j]=fty_i[i][k];
9060 /* dbug(1,dprintf("%x ",facility[j])); */
9064 add_i[3] = facility;
9066 /* dbug(1,dprintf("FacArrLen=%d ",len)); */
9067 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9068 len += 4; /* calculate length of all */
9072 /*------------------------------------------------------------------*/
9073 /* voice and codec features */
9074 /*------------------------------------------------------------------*/
9076 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9078 byte voice_chi[] = "\x02\x18\x01";
9081 channel = chi[chi[0]]&0x3;
9082 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9083 voice_chi[2] = (channel) ? channel : 1;
9084 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9085 add_p(plci,ESC,voice_chi); /* Channel */
9086 sig_req(plci,TEL_CTRL,0);
9088 if(a->AdvSignalPLCI)
9090 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9094 static void VoiceChannelOff(PLCI *plci)
9096 dbug(1,dprintf("ExtDevOFF"));
9097 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9098 sig_req(plci,TEL_CTRL,0);
9100 if(plci->adapter->AdvSignalPLCI)
9102 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9107 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9113 /* check if hardware supports handset with hook states (adv.codec) */
9114 /* or if just a on board codec is supported */
9115 /* the advanced codec plci is just for internal use */
9117 /* diva Pro with on-board codec: */
9118 if(a->profile.Global_Options & HANDSET)
9120 /* new call, but hook states are already signalled */
9123 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9125 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9126 return 0x2001; /* codec in use by another application */
9130 a->AdvSignalPLCI = plci;
9131 plci->tel=ADV_VOICE;
9133 return 0; /* adv codec still used */
9137 splci = &a->plci[j-1];
9138 splci->tel = CODEC_PERMANENT;
9139 /* hook_listen indicates if a facility_req with handset/hook support */
9140 /* was sent. Otherwise if just a call on an external device was made */
9141 /* the codec will be used but the hook info will be discarded (just */
9142 /* the external controller is in use */
9143 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9146 splci->State = ADVANCED_VOICE_NOSIG;
9149 plci->spoofed_msg = SPOOFING_REQUIRED;
9151 /* indicate D-ch connect if */
9152 } /* codec is connected OK */
9155 a->AdvSignalPLCI = plci;
9156 plci->tel=ADV_VOICE;
9158 a->AdvSignalAppl = appl;
9159 a->AdvCodecFLAG = true;
9160 a->AdvCodecPLCI = splci;
9161 add_p(splci,CAI,"\x01\x15");
9162 add_p(splci,LLI,"\x01\x00");
9163 add_p(splci,ESC,"\x02\x18\x00");
9164 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9165 splci->internal_command = PERM_COD_ASSIGN;
9166 dbug(1,dprintf("Codec Assign"));
9167 sig_req(splci,ASSIGN,DSIG_ID);
9172 return 0x2001; /* wrong state, no more plcis */
9175 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9177 if(hook_listen) return 0x300B; /* Facility not supported */
9178 /* no hook with SCOM */
9179 if(plci!=NULL) plci->tel = CODEC;
9180 dbug(1,dprintf("S/SCOM codec"));
9181 /* first time we use the scom-s codec we must shut down the internal */
9182 /* handset application of the card. This can be done by an assign with */
9183 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9184 if(!a->scom_appl_disable){
9185 if((j=get_plci(a))) {
9186 splci = &a->plci[j-1];
9187 add_p(splci,CAI,"\x01\x80");
9188 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9189 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9191 a->scom_appl_disable = true;
9194 return 0x2001; /* wrong state, no more plcis */
9198 else return 0x300B; /* Facility not supported */
9204 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9207 dbug(1,dprintf("CodecIdCheck"));
9209 if(a->AdvSignalPLCI == plci)
9211 dbug(1,dprintf("PLCI owns codec"));
9212 VoiceChannelOff(a->AdvCodecPLCI);
9213 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9215 dbug(1,dprintf("remove temp codec PLCI"));
9216 plci_remove(a->AdvCodecPLCI);
9217 a->AdvCodecFLAG = 0;
9218 a->AdvCodecPLCI = NULL;
9219 a->AdvSignalAppl = NULL;
9221 a->AdvSignalPLCI = NULL;
9225 /* -------------------------------------------------------------------
9226 Ask for physical address of card on PCI bus
9227 ------------------------------------------------------------------- */
9228 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9229 IDI_SYNC_REQ * preq) {
9231 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9232 ENTITY * e = (ENTITY *)preq;
9234 e->user[0] = a->Id - 1;
9235 preq->xdi_sdram_bar.info.bar = 0;
9236 preq->xdi_sdram_bar.Req = 0;
9237 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9241 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9242 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9246 /* -------------------------------------------------------------------
9247 Ask XDI about extended features
9248 ------------------------------------------------------------------- */
9249 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9250 IDI_SYNC_REQ * preq;
9251 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9254 preq = (IDI_SYNC_REQ *)&buffer[0];
9256 if (!diva_xdi_extended_features) {
9257 ENTITY * e = (ENTITY *)preq;
9258 diva_xdi_extended_features |= 0x80000000;
9260 e->user[0] = a->Id - 1;
9261 preq->xdi_extended_features.Req = 0;
9262 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9263 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9264 preq->xdi_extended_features.info.features = &features[0];
9268 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9270 Check features located in the byte '0'
9272 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9273 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9275 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9276 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9277 dbug(1,dprintf("XDI provides RxDMA"));
9279 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9280 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9282 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9283 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9284 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9290 diva_ask_for_xdi_sdram_bar (a, preq);
9293 /*------------------------------------------------------------------*/
9295 /*------------------------------------------------------------------*/
9296 /* called from OS specific part after init time to get the Law */
9297 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9298 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9303 if(a->automatic_law) {
9306 if((j=get_plci(a))) {
9307 diva_get_extended_adapter_features (a);
9308 splci = &a->plci[j-1];
9309 a->automatic_lawPLCI = splci;
9310 a->automatic_law = 1;
9311 add_p(splci,CAI,"\x01\x80");
9312 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9313 splci->internal_command = USELAW_REQ;
9316 sig_req(splci,ASSIGN,DSIG_ID);
9321 /* called from OS specific part if an application sends an Capi20Release */
9322 word CapiRelease(word Id)
9324 word i, j, appls_found;
9327 DIVA_CAPI_ADAPTER *a;
9331 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9332 return (_WRONG_APPL_ID);
9335 this = &application[Id-1]; /* get application pointer */
9337 for(i=0,appls_found=0; i<max_appl; i++)
9339 if(application[i].Id) /* an application has been found */
9345 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9350 a->Info_Mask[Id-1] = 0;
9351 a->CIP_Mask[Id-1] = 0;
9352 a->Notification_Mask[Id-1] = 0;
9353 a->codec_listen[Id-1] = NULL;
9354 a->requested_options_table[Id-1] = 0;
9355 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9356 { /* with this application */
9358 if(plci->Id) /* if plci owns no application */
9359 { /* it may be not jet connected */
9360 if(plci->State==INC_CON_PENDING
9361 || plci->State==INC_CON_ALERT)
9363 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9365 clear_c_ind_mask_bit (plci, (word)(Id-1));
9366 if(c_ind_mask_empty (plci))
9368 sig_req(plci,HANGUP,0);
9370 plci->State = OUTG_DIS_PENDING;
9374 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9376 clear_c_ind_mask_bit (plci, (word)(Id-1));
9377 if(c_ind_mask_empty (plci))
9386 if(plci->appl==this)
9396 if(a->flag_dynamic_l1_down)
9398 if(appls_found==1) /* last application does a capi release */
9402 plci = &a->plci[j-1];
9404 add_p(plci,OAD,"\x01\xfd");
9405 add_p(plci,CAI,"\x01\x80");
9406 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9407 add_p(plci,SHIFT|6,NULL);
9408 add_p(plci,SIN,"\x02\x00\x00");
9409 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9410 sig_req(plci,ASSIGN,DSIG_ID);
9411 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9412 sig_req(plci,SIG_CTRL,0);
9417 if(a->AdvSignalAppl==this)
9419 this->NullCREnable = false;
9420 if (a->AdvCodecPLCI)
9422 plci_remove(a->AdvCodecPLCI);
9423 a->AdvCodecPLCI->tel = 0;
9424 a->AdvCodecPLCI->adv_nl = 0;
9426 a->AdvSignalAppl = NULL;
9427 a->AdvSignalPLCI = NULL;
9428 a->AdvCodecFLAG = 0;
9429 a->AdvCodecPLCI = NULL;
9439 static word plci_remove_check(PLCI *plci)
9441 if(!plci) return true;
9442 if(!plci->NL.Id && c_ind_mask_empty (plci))
9444 if(plci->Sig.Id == 0xff)
9448 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9449 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9452 CodecIdCheck(plci->adapter, plci);
9453 clear_b1_config (plci);
9454 ncci_remove (plci, 0, false);
9455 plci_free_msg_in_queue (plci);
9456 channel_flow_control_remove (plci);
9461 plci->notifiedcall = 0;
9463 listen_check(plci->adapter);
9471 /*------------------------------------------------------------------*/
9473 static byte plci_nl_busy (PLCI *plci)
9475 /* only applicable for non-multiplexed protocols */
9476 return (plci->nl_req
9477 || (plci->ncci_ring_list
9478 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9479 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9483 /*------------------------------------------------------------------*/
9484 /* DTMF facilities */
9485 /*------------------------------------------------------------------*/
9494 } dtmf_digit_map[] =
9496 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9497 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9498 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9499 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9500 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9501 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9502 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9503 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9504 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9505 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9506 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9507 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9508 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9509 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9510 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9511 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9512 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9513 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9514 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9515 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9517 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9518 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9519 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9520 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9521 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9522 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9523 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9524 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9525 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9526 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9527 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9528 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9529 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9530 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9531 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9532 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9533 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9534 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9535 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9536 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9537 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9538 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9539 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9540 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9541 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9542 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9543 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9544 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9545 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9546 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9547 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9548 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9549 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9550 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9551 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9552 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9553 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9554 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9555 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9556 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9557 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9558 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9559 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9560 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9561 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9562 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9563 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9564 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9565 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9566 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9567 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9568 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9572 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9575 static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9577 word min_digit_duration, min_gap_duration;
9579 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9580 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9581 (char *)(FILE_), __LINE__, enable_mask));
9583 if (enable_mask != 0)
9585 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9586 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9587 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9588 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9589 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9590 plci->NData[0].PLength = 5;
9592 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9593 plci->NData[0].PLength += 2;
9594 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9599 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9600 plci->NData[0].PLength = 1;
9602 capidtmf_recv_disable (&(plci->capidtmf_state));
9605 plci->NData[0].P = plci->internal_req_buffer;
9606 plci->NL.X = plci->NData;
9608 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9609 plci->adapter->request (&plci->NL);
9613 static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9617 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9618 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9619 (char *)(FILE_), __LINE__, digit_count));
9621 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9622 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9623 PUT_WORD (&plci->internal_req_buffer[1], w);
9624 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9625 PUT_WORD (&plci->internal_req_buffer[3], w);
9626 for (i = 0; i < digit_count; i++)
9629 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9630 && (digit_buffer[i] != dtmf_digit_map[w].character))
9634 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9635 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9637 plci->NData[0].PLength = 5 + digit_count;
9638 plci->NData[0].P = plci->internal_req_buffer;
9639 plci->NL.X = plci->NData;
9641 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9642 plci->adapter->request (&plci->NL);
9646 static void dtmf_rec_clear_config (PLCI *plci)
9649 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9650 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9651 (char *)(FILE_), __LINE__));
9653 plci->dtmf_rec_active = 0;
9654 plci->dtmf_rec_pulse_ms = 0;
9655 plci->dtmf_rec_pause_ms = 0;
9657 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9662 static void dtmf_send_clear_config (PLCI *plci)
9665 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9666 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9667 (char *)(FILE_), __LINE__));
9669 plci->dtmf_send_requests = 0;
9670 plci->dtmf_send_pulse_ms = 0;
9671 plci->dtmf_send_pause_ms = 0;
9675 static void dtmf_prepare_switch (dword Id, PLCI *plci)
9678 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9679 UnMapId (Id), (char *)(FILE_), __LINE__));
9681 while (plci->dtmf_send_requests != 0)
9682 dtmf_confirmation (Id, plci);
9686 static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9689 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9690 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9696 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9700 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9701 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9704 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9706 switch (plci->adjust_b_state)
9708 case ADJUST_B_RESTORE_DTMF_1:
9709 plci->internal_command = plci->adjust_b_command;
9710 if (plci_nl_busy (plci))
9712 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9715 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9716 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9718 case ADJUST_B_RESTORE_DTMF_2:
9719 if ((Rc != OK) && (Rc != OK_FC))
9721 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9722 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9723 Info = _WRONG_STATE;
9733 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9735 word internal_command, Info;
9739 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9740 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9741 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9742 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9746 PUT_WORD (&result[1], DTMF_SUCCESS);
9747 internal_command = plci->internal_command;
9748 plci->internal_command = 0;
9750 switch (plci->dtmf_cmd)
9753 case DTMF_LISTEN_TONE_START:
9755 case DTMF_LISTEN_MF_START:
9758 case DTMF_LISTEN_START:
9759 switch (internal_command)
9762 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9763 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9764 case DTMF_COMMAND_1:
9765 if (adjust_b_process (Id, plci, Rc) != GOOD)
9767 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9768 UnMapId (Id), (char *)(FILE_), __LINE__));
9769 Info = _FACILITY_NOT_SUPPORTED;
9772 if (plci->internal_command)
9774 case DTMF_COMMAND_2:
9775 if (plci_nl_busy (plci))
9777 plci->internal_command = DTMF_COMMAND_2;
9780 plci->internal_command = DTMF_COMMAND_3;
9781 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9783 case DTMF_COMMAND_3:
9784 if ((Rc != OK) && (Rc != OK_FC))
9786 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9787 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9788 Info = _FACILITY_NOT_SUPPORTED;
9792 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9794 plci->dtmf_rec_active |= mask;
9800 case DTMF_LISTEN_TONE_STOP:
9802 case DTMF_LISTEN_MF_STOP:
9805 case DTMF_LISTEN_STOP:
9806 switch (internal_command)
9809 plci->dtmf_rec_active &= ~mask;
9810 if (plci->dtmf_rec_active)
9813 case DTMF_COMMAND_1:
9814 if (plci->dtmf_rec_active)
9816 if (plci_nl_busy (plci))
9818 plci->internal_command = DTMF_COMMAND_1;
9821 plci->dtmf_rec_active &= ~mask;
9822 plci->internal_command = DTMF_COMMAND_2;
9823 dtmf_enable_receiver (plci, false);
9827 case DTMF_COMMAND_2:
9828 if ((Rc != OK) && (Rc != OK_FC))
9830 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9831 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9832 Info = _FACILITY_NOT_SUPPORTED;
9836 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9837 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9838 case DTMF_COMMAND_3:
9839 if (adjust_b_process (Id, plci, Rc) != GOOD)
9841 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9842 UnMapId (Id), (char *)(FILE_), __LINE__));
9843 Info = _FACILITY_NOT_SUPPORTED;
9846 if (plci->internal_command)
9853 case DTMF_SEND_TONE:
9858 case DTMF_DIGITS_SEND:
9859 switch (internal_command)
9862 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9863 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9865 case DTMF_COMMAND_1:
9866 if (adjust_b_process (Id, plci, Rc) != GOOD)
9868 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9869 UnMapId (Id), (char *)(FILE_), __LINE__));
9870 Info = _FACILITY_NOT_SUPPORTED;
9873 if (plci->internal_command)
9875 case DTMF_COMMAND_2:
9876 if (plci_nl_busy (plci))
9878 plci->internal_command = DTMF_COMMAND_2;
9881 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9882 plci->internal_command = DTMF_COMMAND_3;
9883 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9885 case DTMF_COMMAND_3:
9886 if ((Rc != OK) && (Rc != OK_FC))
9888 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9889 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9890 if (plci->dtmf_send_requests != 0)
9891 (plci->dtmf_send_requests)--;
9892 Info = _FACILITY_NOT_SUPPORTED;
9899 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9900 "wws", Info, SELECTOR_DTMF, result);
9904 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9909 API_PARSE dtmf_parms[5];
9912 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9913 UnMapId (Id), (char *)(FILE_), __LINE__));
9917 PUT_WORD (&result[1], DTMF_SUCCESS);
9918 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9920 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9921 UnMapId (Id), (char *)(FILE_), __LINE__));
9922 Info = _FACILITY_NOT_SUPPORTED;
9924 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9926 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9927 UnMapId (Id), (char *)(FILE_), __LINE__));
9928 Info = _WRONG_MESSAGE_FORMAT;
9931 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9932 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9934 if (!((a->requested_options_table[appl->Id-1])
9935 & (1L << PRIVATE_DTMF_TONE)))
9937 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9938 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9939 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9943 for (i = 0; i < 32; i++)
9945 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9949 if (dtmf_digit_map[i].listen_mask != 0)
9950 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9955 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9957 if (dtmf_digit_map[i].send_mask != 0)
9958 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966 else if (plci == NULL)
9968 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9969 UnMapId (Id), (char *)(FILE_), __LINE__));
9970 Info = _WRONG_IDENTIFIER;
9975 || !plci->NL.Id || plci->nl_remove_id)
9977 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9978 UnMapId (Id), (char *)(FILE_), __LINE__));
9979 Info = _WRONG_STATE;
9984 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9986 switch (plci->dtmf_cmd)
9989 case DTMF_LISTEN_TONE_START:
9990 case DTMF_LISTEN_TONE_STOP:
9992 case DTMF_LISTEN_MF_START:
9993 case DTMF_LISTEN_MF_STOP:
9995 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9996 & (1L << PRIVATE_DTMF_TONE)))
9998 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9999 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10000 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10004 case DTMF_LISTEN_START:
10005 case DTMF_LISTEN_STOP:
10006 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10007 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10009 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10010 UnMapId (Id), (char *)(FILE_), __LINE__));
10011 Info = _FACILITY_NOT_SUPPORTED;
10014 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10016 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10018 plci->dtmf_rec_pulse_ms = 0;
10019 plci->dtmf_rec_pause_ms = 0;
10023 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10024 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10027 start_internal_command (Id, plci, dtmf_command);
10031 case DTMF_SEND_TONE:
10035 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10036 & (1L << PRIVATE_DTMF_TONE)))
10038 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10039 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10040 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10044 case DTMF_DIGITS_SEND:
10045 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10047 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10048 UnMapId (Id), (char *)(FILE_), __LINE__));
10049 Info = _WRONG_MESSAGE_FORMAT;
10052 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10054 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10055 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10059 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10062 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10063 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10064 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10070 if (j == DTMF_DIGIT_MAP_ENTRIES)
10072 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10073 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10074 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10077 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10079 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10080 UnMapId (Id), (char *)(FILE_), __LINE__));
10081 Info = _WRONG_STATE;
10084 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10085 start_internal_command (Id, plci, dtmf_command);
10089 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10090 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10091 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10095 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10096 "wws", Info, SELECTOR_DTMF, result);
10101 static void dtmf_confirmation (dword Id, PLCI *plci)
10107 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10108 UnMapId (Id), (char *)(FILE_), __LINE__));
10112 PUT_WORD (&result[1], DTMF_SUCCESS);
10113 if (plci->dtmf_send_requests != 0)
10115 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10116 "wws", GOOD, SELECTOR_DTMF, result);
10117 (plci->dtmf_send_requests)--;
10118 for (i = 0; i < plci->dtmf_send_requests; i++)
10119 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10124 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10128 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10129 UnMapId (Id), (char *)(FILE_), __LINE__));
10132 for (i = 1; i < length; i++)
10135 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10136 && ((msg[i] != dtmf_digit_map[j].code)
10137 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10141 if (j < DTMF_DIGIT_MAP_ENTRIES)
10144 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10145 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10146 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10150 for (i = length; i > n + 1; i--)
10151 msg[i] = msg[i - 1];
10155 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10157 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10159 msg[++n] = dtmf_digit_map[j].character;
10165 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10170 /*------------------------------------------------------------------*/
10171 /* DTMF parameters */
10172 /*------------------------------------------------------------------*/
10174 static void dtmf_parameter_write (PLCI *plci)
10177 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10179 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10180 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10181 (char *)(FILE_), __LINE__));
10183 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10184 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10185 for (i = 0; i < plci->dtmf_parameter_length; i++)
10186 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10187 add_p (plci, FTY, parameter_buffer);
10188 sig_req (plci, TEL_CTRL, 0);
10193 static void dtmf_parameter_clear_config (PLCI *plci)
10196 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10197 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10198 (char *)(FILE_), __LINE__));
10200 plci->dtmf_parameter_length = 0;
10204 static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10207 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10208 UnMapId (Id), (char *)(FILE_), __LINE__));
10213 static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10216 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10217 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10223 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10227 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10228 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10232 && (plci->dtmf_parameter_length != 0))
10234 switch (plci->adjust_b_state)
10236 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10237 plci->internal_command = plci->adjust_b_command;
10240 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10243 dtmf_parameter_write (plci);
10244 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10246 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10247 if ((Rc != OK) && (Rc != OK_FC))
10249 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10250 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10251 Info = _WRONG_STATE;
10261 /*------------------------------------------------------------------*/
10262 /* Line interconnect facilities */
10263 /*------------------------------------------------------------------*/
10266 LI_CONFIG *li_config_table;
10267 word li_total_channels;
10270 /*------------------------------------------------------------------*/
10271 /* translate a CHI information element to a channel number */
10272 /* returns 0xff - any channel */
10273 /* 0xfe - chi wrong coding */
10274 /* 0xfd - D-channel */
10275 /* 0x00 - no channel */
10276 /* else channel number / PRI: timeslot */
10277 /* if channels is provided we accept more than one channel. */
10278 /*------------------------------------------------------------------*/
10280 static byte chi_to_channel (byte *chi, dword *pchannelmap)
10289 if (pchannelmap) *pchannelmap = 0;
10290 if(!chi[0]) return 0xff;
10293 if(chi[1] & 0x20) {
10294 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10295 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10296 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10297 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10298 if(chi[1] &0x08) excl = 0x40;
10300 /* int. id present */
10303 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10304 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10307 /* coding standard, Number/Map, Channel Type */
10309 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10310 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10311 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10317 if((chi[0]-p)==4) ofs = 0;
10318 else if((chi[0]-p)==3) ofs = 1;
10322 for(i=0; i<4 && p<chi[0]; i++) {
10327 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10340 if((byte)(chi[0]-p)>30) return 0xfe;
10342 for(i=p; i<=chi[0]; i++) {
10343 if ((chi[i] &0x7f) > 31) return 0xfe;
10344 map |= (1L << (chi[i] &0x7f));
10348 if(p!=chi[0]) return 0xfe;
10349 if (ch > 31) return 0xfe;
10352 if(chi[p] &0x40) return 0xfe;
10354 if (pchannelmap) *pchannelmap = map;
10355 else if (map != ((dword)(1L << ch))) return 0xfe;
10356 return (byte)(excl | ch);
10358 else { /* not PRI */
10359 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10360 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10361 if(chi[1] &0x08) excl = 0x40;
10363 switch(chi[1] |0x98) {
10364 case 0x98: return 0;
10366 if (pchannelmap) *pchannelmap = 2;
10369 if (pchannelmap) *pchannelmap = 4;
10371 case 0x9b: return 0xff;
10372 case 0x9c: return 0xfd; /* d-ch */
10373 default: return 0xfe;
10379 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10381 DIVA_CAPI_ADAPTER *a;
10386 old_id = plci->li_bchannel_id;
10389 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10390 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10391 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10392 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10393 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10397 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10399 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10400 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10401 plci->li_bchannel_id = bchannel_id & 0x03;
10402 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10404 splci = a->AdvSignalPLCI;
10405 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10407 if ((splci->li_bchannel_id != 0)
10408 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10410 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10412 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10413 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10414 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10415 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10416 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10419 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10420 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10423 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10424 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10426 mixer_clear_config (plci);
10428 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10429 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10430 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10434 static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10436 DIVA_CAPI_ADAPTER *a;
10441 old_id = plci->li_bchannel_id;
10442 ch = chi_to_channel (chi, NULL);
10447 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10448 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10449 plci->li_bchannel_id = (ch & 0x1f) + 1;
10450 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10451 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10455 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10457 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10458 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10459 plci->li_bchannel_id = ch & 0x1f;
10460 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10462 splci = a->AdvSignalPLCI;
10463 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10465 if ((splci->li_bchannel_id != 0)
10466 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10468 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10470 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10471 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10472 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10473 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10474 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10477 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10478 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10482 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10483 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10485 mixer_clear_config (plci);
10487 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10488 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10489 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10493 #define MIXER_MAX_DUMP_CHANNELS 34
10495 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10497 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10500 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10502 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10503 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10505 for (i = 0; i < li_total_channels; i++)
10507 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10508 if (li_config_table[i].chflags != 0)
10509 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10512 for (j = 0; j < li_total_channels; j++)
10514 if (((li_config_table[i].flag_table[j]) != 0)
10515 || ((li_config_table[j].flag_table[i]) != 0))
10517 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10519 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10520 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10522 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10527 for (i = 0; i < li_total_channels; i++)
10529 for (j = 0; j < li_total_channels; j++)
10531 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10532 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10533 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10536 for (n = 0; n < li_total_channels; n++)
10538 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10540 for (i = 0; i < li_total_channels; i++)
10542 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10544 for (j = 0; j < li_total_channels; j++)
10546 li_config_table[i].coef_table[j] |=
10547 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10553 for (i = 0; i < li_total_channels; i++)
10555 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10557 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10558 for (j = 0; j < li_total_channels; j++)
10560 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10561 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10563 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10564 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10567 for (i = 0; i < li_total_channels; i++)
10569 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10571 for (j = 0; j < li_total_channels; j++)
10573 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10574 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10575 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10576 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10577 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10578 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10579 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10580 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10582 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10584 for (j = 0; j < li_total_channels; j++)
10586 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10588 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10589 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10590 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10594 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10596 for (j = 0; j < li_total_channels; j++)
10598 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10599 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10602 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10604 for (j = 0; j < li_total_channels; j++)
10606 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10608 for (n = 0; n < li_total_channels; n++)
10610 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10612 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10613 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10615 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10616 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10617 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10619 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10620 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10628 for (i = 0; i < li_total_channels; i++)
10630 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10632 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10633 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10634 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10635 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10636 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10637 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10638 for (j = 0; j < li_total_channels; j++)
10640 if ((li_config_table[i].flag_table[j] &
10641 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10642 || (li_config_table[j].flag_table[i] &
10643 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10645 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10648 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10650 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10652 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10654 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10655 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10659 for (i = 0; i < li_total_channels; i++)
10661 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10664 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10666 if (j < li_total_channels)
10668 for (j = 0; j < li_total_channels; j++)
10670 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10671 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10672 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10677 n = li_total_channels;
10678 if (n > MIXER_MAX_DUMP_CHANNELS)
10679 n = MIXER_MAX_DUMP_CHANNELS;
10681 for (j = 0; j < n; j++)
10683 if ((j & 0x7) == 0)
10685 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10686 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10689 dbug (1, dprintf ("[%06lx] CURRENT %s",
10690 (dword)(UnMapController (a->Id)), (char *) hex_line));
10692 for (j = 0; j < n; j++)
10694 if ((j & 0x7) == 0)
10696 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10697 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10700 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10701 (dword)(UnMapController (a->Id)), (char *) hex_line));
10703 for (j = 0; j < n; j++)
10705 if ((j & 0x7) == 0)
10707 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10708 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10711 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10712 (dword)(UnMapController (a->Id)), (char *) hex_line));
10713 for (i = 0; i < n; i++)
10716 for (j = 0; j < n; j++)
10718 if ((j & 0x7) == 0)
10720 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10721 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10724 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10725 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10727 for (i = 0; i < n; i++)
10730 for (j = 0; j < n; j++)
10732 if ((j & 0x7) == 0)
10734 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10735 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10738 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10739 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10748 } mixer_write_prog_pri[] =
10750 { LI_COEF_CH_CH, 0 },
10751 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10752 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10753 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10761 byte xconnect_override;
10762 } mixer_write_prog_bri[] =
10764 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10765 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10766 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10767 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10768 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10769 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10770 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10771 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10772 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10773 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10774 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10775 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10776 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10777 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10778 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10779 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10780 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10781 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10782 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10783 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10784 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10785 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10786 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10787 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10788 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10789 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10790 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10791 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10792 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10793 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10794 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10795 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10796 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10797 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10798 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10799 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10802 static byte mixer_swapped_index_bri[] =
10805 19, /* Alt B to B */
10807 21, /* Alt PC to B */
10809 23, /* Alt IC to B */
10811 25, /* Alt B to PC */
10813 27, /* Alt PC to PC */
10815 29, /* Alt IC to PC */
10817 31, /* Alt B to IC */
10819 33, /* Alt PC to IC */
10821 35, /* Alt IC to IC */
10822 0, /* Alt B to Alt B */
10823 1, /* B to Alt B */
10824 2, /* Alt PC to Alt B */
10825 3, /* PC to Alt B */
10826 4, /* Alt IC to Alt B */
10827 5, /* IC to Alt B */
10828 6, /* Alt B to Alt PC */
10829 7, /* B to Alt PC */
10830 8, /* Alt PC to Alt PC */
10831 9, /* PC to Alt PC */
10832 10, /* Alt IC to Alt PC */
10833 11, /* IC to Alt PC */
10834 12, /* Alt B to Alt IC */
10835 13, /* B to Alt IC */
10836 14, /* Alt PC to Alt IC */
10837 15, /* PC to Alt IC */
10838 16, /* Alt IC to Alt IC */
10839 17 /* IC to Alt IC */
10847 } xconnect_write_prog[] =
10849 { LI_COEF_CH_CH, false, false },
10850 { LI_COEF_CH_PC, false, true },
10851 { LI_COEF_PC_CH, true, false },
10852 { LI_COEF_PC_PC, true, true }
10856 static void xconnect_query_addresses (PLCI *plci)
10858 DIVA_CAPI_ADAPTER *a;
10862 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10863 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10864 (char *)(FILE_), __LINE__));
10867 if (a->li_pri && ((plci->li_bchannel_id == 0)
10868 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10870 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10871 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10872 (char *)(FILE_), __LINE__));
10875 p = plci->internal_req_buffer;
10876 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10877 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10880 *(p++) = (byte)(w >> 8);
10881 w = ch | XCONNECT_CHANNEL_PORT_PC;
10883 *(p++) = (byte)(w >> 8);
10884 plci->NData[0].P = plci->internal_req_buffer;
10885 plci->NData[0].PLength = p - plci->internal_req_buffer;
10886 plci->NL.X = plci->NData;
10887 plci->NL.ReqCh = 0;
10888 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10889 plci->adapter->request (&plci->NL);
10893 static void xconnect_write_coefs (PLCI *plci, word internal_command)
10896 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10897 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10898 (char *)(FILE_), __LINE__, internal_command));
10900 plci->li_write_command = internal_command;
10901 plci->li_write_channel = 0;
10905 static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10907 DIVA_CAPI_ADAPTER *a;
10908 word w, n, i, j, r, s, to_ch;
10911 struct xconnect_transfer_address_s *transfer_address;
10912 byte ch_map[MIXER_CHANNELS_BRI];
10914 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10915 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10918 if ((plci->li_bchannel_id == 0)
10919 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10921 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10922 UnMapId (Id), (char *)(FILE_), __LINE__));
10925 i = a->li_base + (plci->li_bchannel_id - 1);
10926 j = plci->li_write_channel;
10927 p = plci->internal_req_buffer;
10930 if ((Rc != OK) && (Rc != OK_FC))
10932 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10933 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10937 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10941 if (j < li_total_channels)
10943 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10945 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10946 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10947 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10948 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10950 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10951 while ((j < li_total_channels)
10953 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10954 || (!li_config_table[j].adapter->li_pri
10955 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10956 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10957 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10958 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10959 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10960 || ((li_config_table[j].adapter->li_base != a->li_base)
10962 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10963 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10964 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10965 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10968 if (j < li_total_channels)
10969 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10972 if (j < li_total_channels)
10974 plci->internal_command = plci->li_write_command;
10975 if (plci_nl_busy (plci))
10977 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10978 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10981 if (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));
10992 if (r & xconnect_write_prog[n].mask)
10994 if (xconnect_write_prog[n].from_pc)
10995 transfer_address = &(li_config_table[j].send_pc);
10997 transfer_address = &(li_config_table[j].send_b);
10998 d = transfer_address->card_address.low;
11000 *(p++) = (byte)(d >> 8);
11001 *(p++) = (byte)(d >> 16);
11002 *(p++) = (byte)(d >> 24);
11003 d = transfer_address->card_address.high;
11005 *(p++) = (byte)(d >> 8);
11006 *(p++) = (byte)(d >> 16);
11007 *(p++) = (byte)(d >> 24);
11008 d = transfer_address->offset;
11010 *(p++) = (byte)(d >> 8);
11011 *(p++) = (byte)(d >> 16);
11012 *(p++) = (byte)(d >> 24);
11013 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11015 *(p++) = (byte)(w >> 8);
11016 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11017 (li_config_table[i].adapter->u_law ?
11018 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11019 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11022 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11025 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11026 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11027 if (n == ARRAY_SIZE(xconnect_write_prog))
11032 if (j < li_total_channels)
11033 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11034 } while ((j < li_total_channels)
11036 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11037 || (!li_config_table[j].adapter->li_pri
11038 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11039 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11040 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11041 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11042 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11043 || ((li_config_table[j].adapter->li_base != a->li_base)
11045 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11046 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11047 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11048 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11050 } while ((j < li_total_channels)
11051 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11053 else if (j == li_total_channels)
11055 plci->internal_command = plci->li_write_command;
11056 if (plci_nl_busy (plci))
11060 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11062 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11063 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11064 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11065 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11067 *(p++) = (byte)(w >> 8);
11071 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11073 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11074 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11076 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11078 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11079 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11080 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11081 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11083 *(p++) = (byte)(w >> 8);
11084 for (j = 0; j < sizeof(ch_map); j += 2)
11086 if (plci->li_bchannel_id == 2)
11088 ch_map[j] = (byte)(j+1);
11089 ch_map[j+1] = (byte) j;
11093 ch_map[j] = (byte) j;
11094 ch_map[j+1] = (byte)(j+1);
11097 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11099 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11100 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11101 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11103 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11104 mixer_write_prog_bri[n].xconnect_override :
11105 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11106 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11108 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11109 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11115 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11117 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11118 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11119 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11125 j = li_total_channels + 1;
11130 if (j <= li_total_channels)
11132 plci->internal_command = plci->li_write_command;
11133 if (plci_nl_busy (plci))
11135 if (j < a->li_base)
11139 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11141 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11142 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11143 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11144 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11146 *(p++) = (byte)(w >> 8);
11147 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11149 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11150 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11152 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11153 if (w & mixer_write_prog_pri[n].mask)
11155 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11156 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11161 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11162 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11164 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11165 if (w & mixer_write_prog_pri[n].mask)
11167 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11168 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11177 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11179 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11180 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11182 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11184 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11185 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11186 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11187 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11189 *(p++) = (byte)(w >> 8);
11190 for (j = 0; j < sizeof(ch_map); j += 2)
11192 if (plci->li_bchannel_id == 2)
11194 ch_map[j] = (byte)(j+1);
11195 ch_map[j+1] = (byte) j;
11199 ch_map[j] = (byte) j;
11200 ch_map[j+1] = (byte)(j+1);
11203 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11205 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11206 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11207 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11209 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11210 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11211 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11216 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11218 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11219 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11220 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11226 j = li_total_channels + 1;
11229 plci->li_write_channel = j;
11230 if (p != plci->internal_req_buffer)
11232 plci->NData[0].P = plci->internal_req_buffer;
11233 plci->NData[0].PLength = p - plci->internal_req_buffer;
11234 plci->NL.X = plci->NData;
11235 plci->NL.ReqCh = 0;
11236 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11237 plci->adapter->request (&plci->NL);
11243 static void mixer_notify_update (PLCI *plci, byte others)
11245 DIVA_CAPI_ADAPTER *a;
11248 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11250 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11251 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11252 (char *)(FILE_), __LINE__, others));
11255 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11258 plci->li_notify_update = true;
11262 notify_plci = NULL;
11265 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11267 if (i < li_total_channels)
11268 notify_plci = li_config_table[i++].plci;
11272 if ((plci->li_bchannel_id != 0)
11273 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11275 notify_plci = plci;
11278 if ((notify_plci != NULL)
11279 && !notify_plci->li_notify_update
11280 && (notify_plci->appl != NULL)
11281 && (notify_plci->State)
11282 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11284 notify_plci->li_notify_update = true;
11285 ((CAPI_MSG *) msg)->header.length = 18;
11286 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11287 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11288 ((CAPI_MSG *) msg)->header.number = 0;
11289 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11290 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11291 ((CAPI_MSG *) msg)->header.ncci = 0;
11292 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11293 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11294 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11295 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11296 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11297 if (w != _QUEUE_FULL)
11301 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11302 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11303 (char *)(FILE_), __LINE__,
11304 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11306 notify_plci->li_notify_update = false;
11309 } while (others && (notify_plci != NULL));
11311 plci->li_notify_update = false;
11316 static void mixer_clear_config (PLCI *plci)
11318 DIVA_CAPI_ADAPTER *a;
11321 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11322 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11323 (char *)(FILE_), __LINE__));
11325 plci->li_notify_update = false;
11326 plci->li_plci_b_write_pos = 0;
11327 plci->li_plci_b_read_pos = 0;
11328 plci->li_plci_b_req_pos = 0;
11330 if ((plci->li_bchannel_id != 0)
11331 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11333 i = a->li_base + (plci->li_bchannel_id - 1);
11334 li_config_table[i].curchnl = 0;
11335 li_config_table[i].channel = 0;
11336 li_config_table[i].chflags = 0;
11337 for (j = 0; j < li_total_channels; j++)
11339 li_config_table[j].flag_table[i] = 0;
11340 li_config_table[i].flag_table[j] = 0;
11341 li_config_table[i].coef_table[j] = 0;
11342 li_config_table[j].coef_table[i] = 0;
11346 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11347 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11349 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11350 li_config_table[i].curchnl = 0;
11351 li_config_table[i].channel = 0;
11352 li_config_table[i].chflags = 0;
11353 for (j = 0; j < li_total_channels; j++)
11355 li_config_table[i].flag_table[j] = 0;
11356 li_config_table[j].flag_table[i] = 0;
11357 li_config_table[i].coef_table[j] = 0;
11358 li_config_table[j].coef_table[i] = 0;
11360 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11362 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11363 li_config_table[i].curchnl = 0;
11364 li_config_table[i].channel = 0;
11365 li_config_table[i].chflags = 0;
11366 for (j = 0; j < li_total_channels; j++)
11368 li_config_table[i].flag_table[j] = 0;
11369 li_config_table[j].flag_table[i] = 0;
11370 li_config_table[i].coef_table[j] = 0;
11371 li_config_table[j].coef_table[i] = 0;
11380 static void mixer_prepare_switch (dword Id, PLCI *plci)
11383 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11384 UnMapId (Id), (char *)(FILE_), __LINE__));
11388 mixer_indication_coefs_set (Id, plci);
11389 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11393 static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11395 DIVA_CAPI_ADAPTER *a;
11398 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11399 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11402 if ((plci->li_bchannel_id != 0)
11403 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11405 i = a->li_base + (plci->li_bchannel_id - 1);
11406 for (j = 0; j < li_total_channels; j++)
11408 li_config_table[i].coef_table[j] &= 0xf;
11409 li_config_table[j].coef_table[i] &= 0xf;
11412 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11418 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11420 DIVA_CAPI_ADAPTER *a;
11423 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11424 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11428 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11429 && (plci->li_bchannel_id != 0)
11430 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11432 switch (plci->adjust_b_state)
11434 case ADJUST_B_RESTORE_MIXER_1:
11435 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11437 plci->internal_command = plci->adjust_b_command;
11438 if (plci_nl_busy (plci))
11440 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11443 xconnect_query_addresses (plci);
11444 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11447 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11449 case ADJUST_B_RESTORE_MIXER_2:
11450 case ADJUST_B_RESTORE_MIXER_3:
11451 case ADJUST_B_RESTORE_MIXER_4:
11452 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11454 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11455 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11456 Info = _WRONG_STATE;
11461 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11462 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11463 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11464 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11469 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11470 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11471 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11473 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11475 plci->internal_command = plci->adjust_b_command;
11478 case ADJUST_B_RESTORE_MIXER_5:
11479 xconnect_write_coefs (plci, plci->adjust_b_command);
11480 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11482 case ADJUST_B_RESTORE_MIXER_6:
11483 if (!xconnect_write_coefs_process (Id, plci, Rc))
11485 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11486 UnMapId (Id), (char *)(FILE_), __LINE__));
11487 Info = _FACILITY_NOT_SUPPORTED;
11490 if (plci->internal_command)
11492 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11493 case ADJUST_B_RESTORE_MIXER_7:
11501 static void mixer_command (dword Id, PLCI *plci, byte Rc)
11503 DIVA_CAPI_ADAPTER *a;
11504 word i, internal_command, Info;
11506 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11507 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11512 internal_command = plci->internal_command;
11513 plci->internal_command = 0;
11514 switch (plci->li_cmd)
11516 case LI_REQ_CONNECT:
11517 case LI_REQ_DISCONNECT:
11518 case LI_REQ_SILENT_UPDATE:
11519 switch (internal_command)
11522 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11524 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11525 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11527 case MIXER_COMMAND_1:
11528 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11530 if (adjust_b_process (Id, plci, Rc) != GOOD)
11532 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11533 UnMapId (Id), (char *)(FILE_), __LINE__));
11534 Info = _FACILITY_NOT_SUPPORTED;
11537 if (plci->internal_command)
11540 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11541 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11543 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11544 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11546 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11552 mixer_indication_coefs_set (Id, plci);
11553 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11555 case MIXER_COMMAND_2:
11556 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11557 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11558 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11559 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11561 if (!xconnect_write_coefs_process (Id, plci, Rc))
11563 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11564 UnMapId (Id), (char *)(FILE_), __LINE__));
11565 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11569 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11570 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11571 i = (plci->li_plci_b_write_pos == 0) ?
11572 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11573 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11574 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11576 Info = _FACILITY_NOT_SUPPORTED;
11579 if (plci->internal_command)
11582 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11584 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11585 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11587 case MIXER_COMMAND_3:
11588 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11590 if (adjust_b_process (Id, plci, Rc) != GOOD)
11592 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11593 UnMapId (Id), (char *)(FILE_), __LINE__));
11594 Info = _FACILITY_NOT_SUPPORTED;
11597 if (plci->internal_command)
11604 if ((plci->li_bchannel_id == 0)
11605 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11607 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11608 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11612 i = a->li_base + (plci->li_bchannel_id - 1);
11613 li_config_table[i].curchnl = plci->li_channel_bits;
11614 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11616 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11617 li_config_table[i].curchnl = plci->li_channel_bits;
11618 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11620 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11621 li_config_table[i].curchnl = plci->li_channel_bits;
11628 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11629 dword plci_b_id, byte connect, dword li_flags)
11631 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11633 DIVA_CAPI_ADAPTER *a_b;
11635 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11636 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11637 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11638 if (!a->li_pri && (plci->tel == ADV_VOICE)
11639 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11641 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11642 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11643 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11650 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11651 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11652 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11654 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11655 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11656 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11665 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11666 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11667 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11671 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11672 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11673 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11674 if (ch_a_v == ch_b_v)
11676 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11677 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11681 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11683 for (i = 0; i < li_total_channels; i++)
11686 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11689 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11691 for (i = 0; i < li_total_channels; i++)
11694 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11697 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11699 for (i = 0; i < li_total_channels; i++)
11702 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11705 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11707 for (i = 0; i < li_total_channels; i++)
11710 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11714 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11716 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11717 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11718 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11721 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11723 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11724 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11725 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11728 if (li_flags & LI_FLAG_MONITOR_A)
11730 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11731 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11733 if (li_flags & LI_FLAG_MONITOR_B)
11735 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11736 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11738 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11740 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11745 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11746 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11748 if (li_flags & LI_FLAG_MIX_A)
11750 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11751 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11753 if (li_flags & LI_FLAG_MIX_B)
11755 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11756 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11758 if (ch_a_v != ch_a_s)
11760 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11761 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11763 if (ch_b_v != ch_b_s)
11765 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11766 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11771 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11772 dword plci_b_id, byte connect, dword li_flags)
11774 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11776 DIVA_CAPI_ADAPTER *a_b;
11778 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11779 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11780 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11781 if (!a->li_pri && (plci->tel == ADV_VOICE)
11782 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11784 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11785 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11786 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11793 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11794 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11795 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11797 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11798 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11799 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11808 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11809 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11810 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11811 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11812 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11813 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11815 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11825 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11826 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11827 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11830 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11832 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11833 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11834 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11837 if (li_flags & LI2_FLAG_MONITOR_B)
11839 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11840 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11842 if (li_flags & LI2_FLAG_MIX_B)
11844 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11845 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11847 if (li_flags & LI2_FLAG_MONITOR_X)
11848 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11849 if (li_flags & LI2_FLAG_MIX_X)
11850 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11851 if (li_flags & LI2_FLAG_LOOP_B)
11853 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11854 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11858 if (li_flags & LI2_FLAG_LOOP_PC)
11859 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11860 if (li_flags & LI2_FLAG_LOOP_X)
11861 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11862 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11863 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11864 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11865 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11866 if (ch_a_v != ch_a_s)
11868 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11869 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11871 if (ch_b_v != ch_b_s)
11873 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11874 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11879 static word li_check_main_plci (dword Id, PLCI *plci)
11883 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11884 UnMapId (Id), (char *)(FILE_), __LINE__));
11885 return (_WRONG_IDENTIFIER);
11888 || !plci->NL.Id || plci->nl_remove_id
11889 || (plci->li_bchannel_id == 0))
11891 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11892 UnMapId (Id), (char *)(FILE_), __LINE__));
11893 return (_WRONG_STATE);
11895 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11900 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11901 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11906 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11907 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11909 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11910 UnMapId (Id), (char *)(FILE_), __LINE__));
11911 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11915 if ((plci_b_id & 0x7f) != 0)
11917 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11918 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11922 || (((plci_b_id >> 8) & 0xff) == 0)
11923 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11925 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11926 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11927 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11930 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11932 || !plci_b->NL.Id || plci_b->nl_remove_id
11933 || (plci_b->li_bchannel_id == 0))
11935 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11936 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11937 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11940 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11941 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11942 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11943 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11944 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11946 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11947 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11948 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11951 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11952 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11954 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11955 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11956 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11963 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11964 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11969 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11970 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11972 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11973 UnMapId (Id), (char *)(FILE_), __LINE__));
11974 PUT_WORD (p_result, _WRONG_STATE);
11978 if ((plci_b_id & 0x7f) != 0)
11980 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11981 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11985 || (((plci_b_id >> 8) & 0xff) == 0)
11986 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11988 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11989 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11990 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11993 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11995 || !plci_b->NL.Id || plci_b->nl_remove_id
11996 || (plci_b->li_bchannel_id == 0)
11997 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11999 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12000 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12001 PUT_WORD (p_result, _WRONG_STATE);
12004 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12005 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12006 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12009 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12010 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12011 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12014 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12015 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12017 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12018 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12019 PUT_WORD (p_result, _WRONG_STATE);
12026 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12030 dword d, li_flags, plci_b_id;
12032 API_PARSE li_parms[3];
12033 API_PARSE li_req_parms[3];
12034 API_PARSE li_participant_struct[2];
12035 API_PARSE li_participant_parms[3];
12036 word participant_parms_pos;
12037 byte result_buffer[32];
12040 word plci_b_write_pos;
12042 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12043 UnMapId (Id), (char *)(FILE_), __LINE__));
12046 result = result_buffer;
12047 result_buffer[0] = 0;
12048 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12050 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12051 UnMapId (Id), (char *)(FILE_), __LINE__));
12052 Info = _FACILITY_NOT_SUPPORTED;
12054 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12056 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12057 UnMapId (Id), (char *)(FILE_), __LINE__));
12058 Info = _WRONG_MESSAGE_FORMAT;
12062 result_buffer[0] = 3;
12063 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12064 result_buffer[3] = 0;
12065 switch (GET_WORD (li_parms[0].info))
12067 case LI_GET_SUPPORTED_SERVICES:
12068 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12070 result_buffer[0] = 17;
12071 result_buffer[3] = 14;
12072 PUT_WORD (&result_buffer[4], GOOD);
12074 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12075 d |= LI_CONFERENCING_SUPPORTED;
12076 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12077 d |= LI_MONITORING_SUPPORTED;
12078 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12079 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12080 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12081 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12082 PUT_DWORD (&result_buffer[6], d);
12083 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12086 for (i = 0; i < li_total_channels; i++)
12088 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12089 && (li_config_table[i].adapter->li_pri
12090 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12098 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12100 PUT_DWORD (&result_buffer[10], d / 2);
12101 PUT_DWORD (&result_buffer[14], d);
12105 result_buffer[0] = 25;
12106 result_buffer[3] = 22;
12107 PUT_WORD (&result_buffer[4], GOOD);
12108 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12109 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12110 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12111 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12112 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12113 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12114 d |= LI2_PC_LOOPING_SUPPORTED;
12115 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12116 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12117 PUT_DWORD (&result_buffer[6], d);
12118 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12119 PUT_DWORD (&result_buffer[10], d / 2);
12120 PUT_DWORD (&result_buffer[14], d - 1);
12121 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12124 for (i = 0; i < li_total_channels; i++)
12126 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12127 && (li_config_table[i].adapter->li_pri
12128 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12134 PUT_DWORD (&result_buffer[18], d / 2);
12135 PUT_DWORD (&result_buffer[22], d - 1);
12139 case LI_REQ_CONNECT:
12140 if (li_parms[1].length == 8)
12142 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12143 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12145 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12146 UnMapId (Id), (char *)(FILE_), __LINE__));
12147 Info = _WRONG_MESSAGE_FORMAT;
12150 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12151 li_flags = GET_DWORD (li_req_parms[1].info);
12152 Info = li_check_main_plci (Id, plci);
12153 result_buffer[0] = 9;
12154 result_buffer[3] = 6;
12155 PUT_DWORD (&result_buffer[4], plci_b_id);
12156 PUT_WORD (&result_buffer[8], GOOD);
12159 result = plci->saved_msg.info;
12160 for (i = 0; i <= result_buffer[0]; i++)
12161 result[i] = result_buffer[i];
12162 plci_b_write_pos = plci->li_plci_b_write_pos;
12163 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12164 if (plci_b == NULL)
12166 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12167 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12168 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12169 plci->li_plci_b_write_pos = plci_b_write_pos;
12173 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12174 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12176 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12177 UnMapId (Id), (char *)(FILE_), __LINE__));
12178 Info = _WRONG_MESSAGE_FORMAT;
12181 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12182 Info = li_check_main_plci (Id, plci);
12183 result_buffer[0] = 7;
12184 result_buffer[3] = 4;
12185 PUT_WORD (&result_buffer[4], Info);
12186 result_buffer[6] = 0;
12189 result = plci->saved_msg.info;
12190 for (i = 0; i <= result_buffer[0]; i++)
12191 result[i] = result_buffer[i];
12192 plci_b_write_pos = plci->li_plci_b_write_pos;
12193 participant_parms_pos = 0;
12195 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12196 while (participant_parms_pos < li_req_parms[1].length)
12198 result[result_pos] = 6;
12200 PUT_DWORD (&result[result_pos - 6], 0);
12201 PUT_WORD (&result[result_pos - 2], GOOD);
12202 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12203 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12205 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12206 UnMapId (Id), (char *)(FILE_), __LINE__));
12207 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210 if (api_parse (&li_participant_struct[0].info[1],
12211 li_participant_struct[0].length, "dd", li_participant_parms))
12213 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12214 UnMapId (Id), (char *)(FILE_), __LINE__));
12215 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12219 li_flags = GET_DWORD (li_participant_parms[1].info);
12220 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12221 if (sizeof(result) - result_pos < 7)
12223 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12224 UnMapId (Id), (char *)(FILE_), __LINE__));
12225 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12228 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12229 if (plci_b != NULL)
12231 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12232 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12233 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12234 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12235 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12237 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12238 (&li_req_parms[1].info[1]));
12240 result[0] = (byte)(result_pos - 1);
12241 result[3] = (byte)(result_pos - 4);
12242 result[6] = (byte)(result_pos - 7);
12243 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12244 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12245 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12247 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12248 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12251 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12252 plci->li_plci_b_write_pos = plci_b_write_pos;
12254 mixer_calculate_coefs (a);
12255 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12256 mixer_notify_update (plci, true);
12257 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12258 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12260 plci->li_cmd = GET_WORD (li_parms[0].info);
12261 start_internal_command (Id, plci, mixer_command);
12264 case LI_REQ_DISCONNECT:
12265 if (li_parms[1].length == 4)
12267 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12268 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12270 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12271 UnMapId (Id), (char *)(FILE_), __LINE__));
12272 Info = _WRONG_MESSAGE_FORMAT;
12275 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12276 Info = li_check_main_plci (Id, plci);
12277 result_buffer[0] = 9;
12278 result_buffer[3] = 6;
12279 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12280 PUT_WORD (&result_buffer[8], GOOD);
12283 result = plci->saved_msg.info;
12284 for (i = 0; i <= result_buffer[0]; i++)
12285 result[i] = result_buffer[i];
12286 plci_b_write_pos = plci->li_plci_b_write_pos;
12287 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12288 if (plci_b == NULL)
12290 li_update_connect (Id, a, plci, plci_b_id, false, 0);
12291 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12292 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12293 plci->li_plci_b_write_pos = plci_b_write_pos;
12297 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12298 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12300 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12301 UnMapId (Id), (char *)(FILE_), __LINE__));
12302 Info = _WRONG_MESSAGE_FORMAT;
12305 Info = li_check_main_plci (Id, plci);
12306 result_buffer[0] = 7;
12307 result_buffer[3] = 4;
12308 PUT_WORD (&result_buffer[4], Info);
12309 result_buffer[6] = 0;
12312 result = plci->saved_msg.info;
12313 for (i = 0; i <= result_buffer[0]; i++)
12314 result[i] = result_buffer[i];
12315 plci_b_write_pos = plci->li_plci_b_write_pos;
12316 participant_parms_pos = 0;
12318 while (participant_parms_pos < li_req_parms[0].length)
12320 result[result_pos] = 6;
12322 PUT_DWORD (&result[result_pos - 6], 0);
12323 PUT_WORD (&result[result_pos - 2], GOOD);
12324 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12325 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12327 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12328 UnMapId (Id), (char *)(FILE_), __LINE__));
12329 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332 if (api_parse (&li_participant_struct[0].info[1],
12333 li_participant_struct[0].length, "d", li_participant_parms))
12335 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12336 UnMapId (Id), (char *)(FILE_), __LINE__));
12337 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12340 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12341 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12342 if (sizeof(result) - result_pos < 7)
12344 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12345 UnMapId (Id), (char *)(FILE_), __LINE__));
12346 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12349 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12350 if (plci_b != NULL)
12352 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12353 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12354 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12356 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12357 (&li_req_parms[0].info[1]));
12359 result[0] = (byte)(result_pos - 1);
12360 result[3] = (byte)(result_pos - 4);
12361 result[6] = (byte)(result_pos - 7);
12362 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12363 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12364 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12366 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12367 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12370 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12371 plci->li_plci_b_write_pos = plci_b_write_pos;
12373 mixer_calculate_coefs (a);
12374 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12375 mixer_notify_update (plci, true);
12376 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12377 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12379 plci->li_cmd = GET_WORD (li_parms[0].info);
12380 start_internal_command (Id, plci, mixer_command);
12383 case LI_REQ_SILENT_UPDATE:
12384 if (!plci || !plci->State
12385 || !plci->NL.Id || plci->nl_remove_id
12386 || (plci->li_bchannel_id == 0)
12387 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12389 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12390 UnMapId (Id), (char *)(FILE_), __LINE__));
12393 plci_b_write_pos = plci->li_plci_b_write_pos;
12394 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12395 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12397 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12398 UnMapId (Id), (char *)(FILE_), __LINE__));
12401 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12402 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12403 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12405 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12406 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12409 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12410 plci->li_plci_b_write_pos = plci_b_write_pos;
12411 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12413 plci->li_cmd = GET_WORD (li_parms[0].info);
12414 start_internal_command (Id, plci, mixer_command);
12418 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12419 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12420 Info = _FACILITY_NOT_SUPPORTED;
12423 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12424 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12429 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12432 DIVA_CAPI_ADAPTER *a;
12435 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12436 UnMapId (Id), (char *)(FILE_), __LINE__));
12439 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12443 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12444 if (!(d & LI_PLCI_B_SKIP_FLAG))
12446 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12448 if (d & LI_PLCI_B_DISC_FLAG)
12451 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12453 PUT_WORD (&result[4], _LI_USER_INITIATED);
12458 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12460 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12465 if (d & LI_PLCI_B_DISC_FLAG)
12468 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12470 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12471 PUT_WORD (&result[8], _LI_USER_INITIATED);
12476 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12478 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12481 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12482 "ws", SELECTOR_LINE_INTERCONNECT, result);
12484 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12485 0 : plci->li_plci_b_read_pos + 1;
12486 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12491 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12494 struct xconnect_transfer_address_s s, *p;
12495 DIVA_CAPI_ADAPTER *a;
12497 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12498 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12502 for (i = 1; i < length; i += 16)
12504 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12505 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12506 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12507 ch = msg[i+12] | (msg[i+13] << 8);
12508 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12509 if (!a->li_pri && (plci->li_bchannel_id == 2))
12512 if (ch & XCONNECT_CHANNEL_PORT_PC)
12513 p = &(li_config_table[j].send_pc);
12515 p = &(li_config_table[j].send_b);
12516 p->card_address.low = s.card_address.low;
12517 p->card_address.high = s.card_address.high;
12518 p->offset = s.offset;
12519 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12521 if (plci->internal_command_queue[0]
12522 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12523 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12524 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12526 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12527 if (!plci->internal_command)
12528 next_internal_command (Id, plci);
12530 mixer_notify_update (plci, true);
12534 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12537 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12538 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12543 static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12545 word plci_b_write_pos;
12547 plci_b_write_pos = plci->li_plci_b_write_pos;
12548 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12549 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12551 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12552 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12553 (char *)(FILE_), __LINE__));
12556 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12557 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12558 plci->li_plci_b_write_pos = plci_b_write_pos;
12563 static void mixer_remove (PLCI *plci)
12565 DIVA_CAPI_ADAPTER *a;
12570 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12571 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12572 (char *)(FILE_), __LINE__));
12575 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12576 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12578 if ((plci->li_bchannel_id != 0)
12579 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12581 i = a->li_base + (plci->li_bchannel_id - 1);
12582 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12584 for (j = 0; j < li_total_channels; j++)
12586 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12587 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12589 notify_plci = li_config_table[j].plci;
12590 if ((notify_plci != NULL)
12591 && (notify_plci != plci)
12592 && (notify_plci->appl != NULL)
12593 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12594 && (notify_plci->State)
12595 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12597 mixer_notify_source_removed (notify_plci, plci_b_id);
12601 mixer_clear_config (plci);
12602 mixer_calculate_coefs (a);
12603 mixer_notify_update (plci, true);
12605 li_config_table[i].plci = NULL;
12606 plci->li_bchannel_id = 0;
12612 /*------------------------------------------------------------------*/
12613 /* Echo canceller facilities */
12614 /*------------------------------------------------------------------*/
12617 static void ec_write_parameters (PLCI *plci)
12620 byte parameter_buffer[6];
12622 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12623 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12624 (char *)(FILE_), __LINE__));
12626 parameter_buffer[0] = 5;
12627 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12628 PUT_WORD (¶meter_buffer[2], plci->ec_idi_options);
12629 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12630 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12631 PUT_WORD (¶meter_buffer[4], w);
12632 add_p (plci, FTY, parameter_buffer);
12633 sig_req (plci, TEL_CTRL, 0);
12638 static void ec_clear_config (PLCI *plci)
12641 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12642 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12643 (char *)(FILE_), __LINE__));
12645 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12646 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12647 plci->ec_tail_length = 0;
12651 static void ec_prepare_switch (dword Id, PLCI *plci)
12654 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12655 UnMapId (Id), (char *)(FILE_), __LINE__));
12660 static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12663 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12664 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12670 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12674 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12675 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12678 if (plci->B1_facilities & B1_FACILITY_EC)
12680 switch (plci->adjust_b_state)
12682 case ADJUST_B_RESTORE_EC_1:
12683 plci->internal_command = plci->adjust_b_command;
12686 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12689 ec_write_parameters (plci);
12690 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12692 case ADJUST_B_RESTORE_EC_2:
12693 if ((Rc != OK) && (Rc != OK_FC))
12695 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12697 Info = _WRONG_STATE;
12707 static void ec_command (dword Id, PLCI *plci, byte Rc)
12709 word internal_command, Info;
12712 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12713 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12714 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12717 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12720 PUT_WORD (&result[1], EC_SUCCESS);
12725 PUT_WORD (&result[1], plci->ec_cmd);
12727 PUT_WORD (&result[4], GOOD);
12729 internal_command = plci->internal_command;
12730 plci->internal_command = 0;
12731 switch (plci->ec_cmd)
12733 case EC_ENABLE_OPERATION:
12734 case EC_FREEZE_COEFFICIENTS:
12735 case EC_RESUME_COEFFICIENT_UPDATE:
12736 case EC_RESET_COEFFICIENTS:
12737 switch (internal_command)
12740 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12741 B1_FACILITY_EC), EC_COMMAND_1);
12743 if (adjust_b_process (Id, plci, Rc) != GOOD)
12745 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12746 UnMapId (Id), (char *)(FILE_), __LINE__));
12747 Info = _FACILITY_NOT_SUPPORTED;
12750 if (plci->internal_command)
12755 plci->internal_command = EC_COMMAND_2;
12758 plci->internal_command = EC_COMMAND_3;
12759 ec_write_parameters (plci);
12762 if ((Rc != OK) && (Rc != OK_FC))
12764 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12765 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12766 Info = _FACILITY_NOT_SUPPORTED;
12773 case EC_DISABLE_OPERATION:
12774 switch (internal_command)
12778 if (plci->B1_facilities & B1_FACILITY_EC)
12782 plci->internal_command = EC_COMMAND_1;
12785 plci->internal_command = EC_COMMAND_2;
12786 ec_write_parameters (plci);
12791 if ((Rc != OK) && (Rc != OK_FC))
12793 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12794 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12795 Info = _FACILITY_NOT_SUPPORTED;
12798 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12799 ~B1_FACILITY_EC), EC_COMMAND_3);
12801 if (adjust_b_process (Id, plci, Rc) != GOOD)
12803 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12804 UnMapId (Id), (char *)(FILE_), __LINE__));
12805 Info = _FACILITY_NOT_SUPPORTED;
12808 if (plci->internal_command)
12814 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12815 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12816 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12820 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12824 API_PARSE ec_parms[3];
12827 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12828 UnMapId (Id), (char *)(FILE_), __LINE__));
12832 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12834 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12835 UnMapId (Id), (char *)(FILE_), __LINE__));
12836 Info = _FACILITY_NOT_SUPPORTED;
12840 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12842 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12844 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12845 UnMapId (Id), (char *)(FILE_), __LINE__));
12846 Info = _WRONG_MESSAGE_FORMAT;
12852 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12853 UnMapId (Id), (char *)(FILE_), __LINE__));
12854 Info = _WRONG_IDENTIFIER;
12856 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12858 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12859 UnMapId (Id), (char *)(FILE_), __LINE__));
12860 Info = _WRONG_STATE;
12865 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12866 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12868 PUT_WORD (&result[1], EC_SUCCESS);
12869 if (msg[1].length >= 4)
12871 opt = GET_WORD (&ec_parms[0].info[2]);
12872 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12873 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12874 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12875 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12876 if (opt & EC_DETECT_DISABLE_TONE)
12877 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12878 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12879 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12880 if (msg[1].length >= 6)
12882 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12885 switch (plci->ec_cmd)
12887 case EC_ENABLE_OPERATION:
12888 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12889 start_internal_command (Id, plci, ec_command);
12892 case EC_DISABLE_OPERATION:
12893 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12894 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12895 LEC_RESET_COEFFICIENTS;
12896 start_internal_command (Id, plci, ec_command);
12899 case EC_FREEZE_COEFFICIENTS:
12900 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12901 start_internal_command (Id, plci, ec_command);
12904 case EC_RESUME_COEFFICIENT_UPDATE:
12905 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12906 start_internal_command (Id, plci, ec_command);
12909 case EC_RESET_COEFFICIENTS:
12910 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12911 start_internal_command (Id, plci, ec_command);
12915 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12916 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12917 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12924 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12926 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12927 UnMapId (Id), (char *)(FILE_), __LINE__));
12928 Info = _WRONG_MESSAGE_FORMAT;
12932 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12935 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12937 PUT_WORD (&result[4], GOOD);
12938 PUT_WORD (&result[6], 0x0007);
12939 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12940 PUT_WORD (&result[10], 0);
12942 else if (plci == NULL)
12944 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12945 UnMapId (Id), (char *)(FILE_), __LINE__));
12946 Info = _WRONG_IDENTIFIER;
12948 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12950 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12951 UnMapId (Id), (char *)(FILE_), __LINE__));
12952 Info = _WRONG_STATE;
12957 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12958 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12960 PUT_WORD (&result[1], plci->ec_cmd);
12962 PUT_WORD (&result[4], GOOD);
12963 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12964 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12965 plci->ec_tail_length = 0;
12966 if (ec_parms[1].length >= 2)
12968 opt = GET_WORD (&ec_parms[1].info[1]);
12969 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12970 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12971 if (opt & EC_DETECT_DISABLE_TONE)
12972 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12973 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12974 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12975 if (ec_parms[1].length >= 4)
12977 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12980 switch (plci->ec_cmd)
12982 case EC_ENABLE_OPERATION:
12983 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12984 start_internal_command (Id, plci, ec_command);
12987 case EC_DISABLE_OPERATION:
12988 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12989 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12990 LEC_RESET_COEFFICIENTS;
12991 start_internal_command (Id, plci, ec_command);
12995 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12996 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12997 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13003 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13004 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13005 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13010 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13014 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13015 UnMapId (Id), (char *)(FILE_), __LINE__));
13017 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13019 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13022 PUT_WORD (&result[1], 0);
13025 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13026 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13028 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13029 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13031 case LEC_DISABLE_RELEASED:
13032 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13039 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13041 PUT_WORD (&result[4], 0);
13044 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13047 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13050 case LEC_DISABLE_RELEASED:
13051 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13055 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13056 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13062 /*------------------------------------------------------------------*/
13063 /* Advanced voice */
13064 /*------------------------------------------------------------------*/
13066 static void adv_voice_write_coefs (PLCI *plci, word write_command)
13068 DIVA_CAPI_ADAPTER *a;
13073 byte ch_map[MIXER_CHANNELS_BRI];
13075 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13077 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13078 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13079 (char *)(FILE_), __LINE__, write_command));
13082 p = coef_buffer + 1;
13083 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13085 while (i + sizeof(word) <= a->adv_voice_coef_length)
13087 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13091 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13093 PUT_WORD (p, 0x8000);
13098 if (!a->li_pri && (plci->li_bchannel_id == 0))
13100 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13102 plci->li_bchannel_id = 1;
13103 li_config_table[a->li_base].plci = plci;
13104 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13105 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13106 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13108 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13110 plci->li_bchannel_id = 2;
13111 li_config_table[a->li_base + 1].plci = plci;
13112 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13114 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13117 if (!a->li_pri && (plci->li_bchannel_id != 0)
13118 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13120 i = a->li_base + (plci->li_bchannel_id - 1);
13121 switch (write_command)
13123 case ADV_VOICE_WRITE_ACTIVATION:
13124 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13125 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13126 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13128 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13133 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13134 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13135 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13136 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13138 mixer_calculate_coefs (a);
13139 li_config_table[i].curchnl = li_config_table[i].channel;
13140 li_config_table[j].curchnl = li_config_table[j].channel;
13141 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13142 li_config_table[k].curchnl = li_config_table[k].channel;
13145 case ADV_VOICE_WRITE_DEACTIVATION:
13146 for (j = 0; j < li_total_channels; j++)
13148 li_config_table[i].flag_table[j] = 0;
13149 li_config_table[j].flag_table[i] = 0;
13151 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13152 for (j = 0; j < li_total_channels; j++)
13154 li_config_table[k].flag_table[j] = 0;
13155 li_config_table[j].flag_table[k] = 0;
13157 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13159 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13160 for (j = 0; j < li_total_channels; j++)
13162 li_config_table[k].flag_table[j] = 0;
13163 li_config_table[j].flag_table[k] = 0;
13166 mixer_calculate_coefs (a);
13169 if (plci->B1_facilities & B1_FACILITY_MIXER)
13172 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13173 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13174 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13175 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13176 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13177 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13179 *(p++) = (byte)(w >> 8);
13180 for (j = 0; j < sizeof(ch_map); j += 2)
13182 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13183 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13185 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13187 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13188 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13189 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13191 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13192 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13193 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13197 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13198 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13204 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13205 *(p++) = a->adv_voice_coef_buffer[i];
13211 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212 *(p++) = a->adv_voice_coef_buffer[i];
13214 coef_buffer[0] = (p - coef_buffer) - 1;
13215 add_p (plci, FTY, coef_buffer);
13216 sig_req (plci, TEL_CTRL, 0);
13221 static void adv_voice_clear_config (PLCI *plci)
13223 DIVA_CAPI_ADAPTER *a;
13228 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13229 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13230 (char *)(FILE_), __LINE__));
13233 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13235 a->adv_voice_coef_length = 0;
13237 if (!a->li_pri && (plci->li_bchannel_id != 0)
13238 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13240 i = a->li_base + (plci->li_bchannel_id - 1);
13241 li_config_table[i].curchnl = 0;
13242 li_config_table[i].channel = 0;
13243 li_config_table[i].chflags = 0;
13244 for (j = 0; j < li_total_channels; j++)
13246 li_config_table[i].flag_table[j] = 0;
13247 li_config_table[j].flag_table[i] = 0;
13248 li_config_table[i].coef_table[j] = 0;
13249 li_config_table[j].coef_table[i] = 0;
13251 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13252 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13253 li_config_table[i].curchnl = 0;
13254 li_config_table[i].channel = 0;
13255 li_config_table[i].chflags = 0;
13256 for (j = 0; j < li_total_channels; j++)
13258 li_config_table[i].flag_table[j] = 0;
13259 li_config_table[j].flag_table[i] = 0;
13260 li_config_table[i].coef_table[j] = 0;
13261 li_config_table[j].coef_table[i] = 0;
13263 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13265 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13266 li_config_table[i].curchnl = 0;
13267 li_config_table[i].channel = 0;
13268 li_config_table[i].chflags = 0;
13269 for (j = 0; j < li_total_channels; j++)
13271 li_config_table[i].flag_table[j] = 0;
13272 li_config_table[j].flag_table[i] = 0;
13273 li_config_table[i].coef_table[j] = 0;
13274 li_config_table[j].coef_table[i] = 0;
13283 static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13286 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13287 UnMapId (Id), (char *)(FILE_), __LINE__));
13292 static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13295 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13296 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13302 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13304 DIVA_CAPI_ADAPTER *a;
13307 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13308 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13312 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13313 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13315 switch (plci->adjust_b_state)
13317 case ADJUST_B_RESTORE_VOICE_1:
13318 plci->internal_command = plci->adjust_b_command;
13321 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13324 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13325 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13327 case ADJUST_B_RESTORE_VOICE_2:
13328 if ((Rc != OK) && (Rc != OK_FC))
13330 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13331 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13332 Info = _WRONG_STATE;
13344 /*------------------------------------------------------------------*/
13345 /* B1 resource switching */
13346 /*------------------------------------------------------------------*/
13348 static byte b1_facilities_table[] =
13350 0x00, /* 0 No bchannel resources */
13351 0x00, /* 1 Codec (automatic law) */
13352 0x00, /* 2 Codec (A-law) */
13353 0x00, /* 3 Codec (y-law) */
13354 0x00, /* 4 HDLC for X.21 */
13356 0x00, /* 6 External Device 0 */
13357 0x00, /* 7 External Device 1 */
13358 0x00, /* 8 HDLC 56k */
13359 0x00, /* 9 Transparent */
13360 0x00, /* 10 Loopback to network */
13361 0x00, /* 11 Test pattern to net */
13362 0x00, /* 12 Rate adaptation sync */
13363 0x00, /* 13 Rate adaptation async */
13364 0x00, /* 14 R-Interface */
13365 0x00, /* 15 HDLC 128k leased line */
13367 0x00, /* 17 Modem async */
13368 0x00, /* 18 Modem sync HDLC */
13369 0x00, /* 19 V.110 async HDLC */
13370 0x12, /* 20 Adv voice (Trans,mixer) */
13371 0x00, /* 21 Codec connected to IC */
13372 0x0c, /* 22 Trans,DTMF */
13373 0x1e, /* 23 Trans,DTMF+mixer */
13374 0x1f, /* 24 Trans,DTMF+mixer+local */
13375 0x13, /* 25 Trans,mixer+local */
13376 0x12, /* 26 HDLC,mixer */
13377 0x12, /* 27 HDLC 56k,mixer */
13378 0x2c, /* 28 Trans,LEC+DTMF */
13379 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13380 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13381 0x2c, /* 31 RTP,LEC+DTMF */
13382 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13383 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13384 0x00, /* 34 Signaling task */
13385 0x00, /* 35 PIAFS */
13386 0x0c, /* 36 Trans,DTMF+TONE */
13387 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13388 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13392 static word get_b1_facilities (PLCI * plci, byte b1_resource)
13394 word b1_facilities;
13396 b1_facilities = b1_facilities_table[b1_resource];
13397 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13400 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13401 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13404 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13405 b1_facilities |= B1_FACILITY_DTMFX;
13406 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13407 b1_facilities |= B1_FACILITY_DTMFR;
13410 if ((b1_resource == 17) || (b1_resource == 18))
13412 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13413 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13416 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13417 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13418 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13420 return (b1_facilities);
13424 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13428 switch (b1_resource)
13432 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13440 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13458 if (b1_facilities & B1_FACILITY_EC)
13460 if (b1_facilities & B1_FACILITY_LOCAL)
13462 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13468 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13469 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13470 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13472 if (b1_facilities & B1_FACILITY_LOCAL)
13474 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13480 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13481 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13482 || ((b1_facilities & B1_FACILITY_DTMFR)
13483 && ((b1_facilities & B1_FACILITY_MIXER)
13484 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13485 || ((b1_facilities & B1_FACILITY_DTMFX)
13486 && ((b1_facilities & B1_FACILITY_MIXER)
13487 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13489 if (b1_facilities & B1_FACILITY_LOCAL)
13491 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13498 if (b1_facilities & B1_FACILITY_LOCAL)
13500 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13510 if (b1_facilities & B1_FACILITY_LOCAL)
13512 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13521 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13522 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13523 (char *)(FILE_), __LINE__,
13524 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13529 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13531 word removed_facilities;
13533 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13534 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13535 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13536 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13538 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13539 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13541 if (removed_facilities & B1_FACILITY_EC)
13542 ec_clear_config (plci);
13545 if (removed_facilities & B1_FACILITY_DTMFR)
13547 dtmf_rec_clear_config (plci);
13548 dtmf_parameter_clear_config (plci);
13550 if (removed_facilities & B1_FACILITY_DTMFX)
13551 dtmf_send_clear_config (plci);
13554 if (removed_facilities & B1_FACILITY_MIXER)
13555 mixer_clear_config (plci);
13557 if (removed_facilities & B1_FACILITY_VOICE)
13558 adv_voice_clear_config (plci);
13559 plci->B1_facilities = new_b1_facilities;
13563 static void adjust_b_clear (PLCI *plci)
13566 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13567 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13568 (char *)(FILE_), __LINE__));
13570 plci->adjust_b_restore = false;
13574 static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13581 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13582 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13585 switch (plci->adjust_b_state)
13587 case ADJUST_B_START:
13588 if ((plci->adjust_b_parms_msg == NULL)
13589 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13590 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13591 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13593 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13594 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13595 if (b1_resource == plci->B1_resource)
13597 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13600 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13602 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13603 UnMapId (Id), (char *)(FILE_), __LINE__,
13604 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13605 Info = _WRONG_STATE;
13609 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13612 mixer_prepare_switch (Id, plci);
13615 dtmf_prepare_switch (Id, plci);
13616 dtmf_parameter_prepare_switch (Id, plci);
13619 ec_prepare_switch (Id, plci);
13621 adv_voice_prepare_switch (Id, plci);
13623 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13625 case ADJUST_B_SAVE_MIXER_1:
13626 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13629 Info = mixer_save_config (Id, plci, Rc);
13630 if ((Info != GOOD) || plci->internal_command)
13634 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13636 case ADJUST_B_SAVE_DTMF_1:
13637 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13640 Info = dtmf_save_config (Id, plci, Rc);
13641 if ((Info != GOOD) || plci->internal_command)
13645 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13646 case ADJUST_B_REMOVE_L23_1:
13647 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13648 && plci->NL.Id && !plci->nl_remove_id)
13650 plci->internal_command = plci->adjust_b_command;
13651 if (plci->adjust_b_ncci != 0)
13653 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13654 while (ncci_ptr->data_pending)
13656 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13657 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13659 while (ncci_ptr->data_ack_pending)
13660 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13662 nl_req_ncci (plci, REMOVE,
13663 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13665 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13668 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13670 case ADJUST_B_REMOVE_L23_2:
13671 if ((Rc != OK) && (Rc != OK_FC))
13673 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13674 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13675 Info = _WRONG_STATE;
13678 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13680 if (plci_nl_busy (plci))
13682 plci->internal_command = plci->adjust_b_command;
13686 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13688 case ADJUST_B_SAVE_EC_1:
13689 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13692 Info = ec_save_config (Id, plci, Rc);
13693 if ((Info != GOOD) || plci->internal_command)
13697 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13699 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13700 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13703 Info = dtmf_parameter_save_config (Id, plci, Rc);
13704 if ((Info != GOOD) || plci->internal_command)
13708 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13710 case ADJUST_B_SAVE_VOICE_1:
13711 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13713 Info = adv_voice_save_config (Id, plci, Rc);
13714 if ((Info != GOOD) || plci->internal_command)
13717 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13718 case ADJUST_B_SWITCH_L1_1:
13719 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13723 plci->internal_command = plci->adjust_b_command;
13726 if (plci->adjust_b_parms_msg != NULL)
13727 api_load_msg (plci->adjust_b_parms_msg, bp);
13729 api_load_msg (&plci->B_protocol, bp);
13730 Info = add_b1 (plci, bp,
13731 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13732 plci->adjust_b_facilities);
13735 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13736 UnMapId (Id), (char *)(FILE_), __LINE__,
13737 plci->B1_resource, plci->adjust_b_facilities));
13740 plci->internal_command = plci->adjust_b_command;
13741 sig_req (plci, RESOURCES, 0);
13743 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13746 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13748 case ADJUST_B_SWITCH_L1_2:
13749 if ((Rc != OK) && (Rc != OK_FC))
13751 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13752 UnMapId (Id), (char *)(FILE_), __LINE__,
13753 Rc, plci->B1_resource, plci->adjust_b_facilities));
13754 Info = _WRONG_STATE;
13757 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13759 case ADJUST_B_RESTORE_VOICE_1:
13760 case ADJUST_B_RESTORE_VOICE_2:
13761 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13763 Info = adv_voice_restore_config (Id, plci, Rc);
13764 if ((Info != GOOD) || plci->internal_command)
13767 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13769 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13771 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13774 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13775 if ((Info != GOOD) || plci->internal_command)
13779 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13781 case ADJUST_B_RESTORE_EC_1:
13782 case ADJUST_B_RESTORE_EC_2:
13783 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13786 Info = ec_restore_config (Id, plci, Rc);
13787 if ((Info != GOOD) || plci->internal_command)
13791 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13792 case ADJUST_B_ASSIGN_L23_1:
13793 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13795 if (plci_nl_busy (plci))
13797 plci->internal_command = plci->adjust_b_command;
13800 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13801 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13802 if (plci->adjust_b_parms_msg != NULL)
13803 api_load_msg (plci->adjust_b_parms_msg, bp);
13805 api_load_msg (&plci->B_protocol, bp);
13806 Info = add_b23 (plci, bp);
13809 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13810 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13813 plci->internal_command = plci->adjust_b_command;
13814 nl_req_ncci (plci, ASSIGN, 0);
13816 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13819 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13821 case ADJUST_B_ASSIGN_L23_2:
13822 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13824 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13825 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13826 Info = _WRONG_STATE;
13829 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13831 if (Rc != ASSIGN_OK)
13833 plci->internal_command = plci->adjust_b_command;
13837 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13839 plci->adjust_b_restore = true;
13842 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13843 case ADJUST_B_CONNECT_1:
13844 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13846 plci->internal_command = plci->adjust_b_command;
13847 if (plci_nl_busy (plci))
13849 nl_req_ncci (plci, N_CONNECT, 0);
13851 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13854 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13856 case ADJUST_B_CONNECT_2:
13857 case ADJUST_B_CONNECT_3:
13858 case ADJUST_B_CONNECT_4:
13859 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13861 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13862 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13863 Info = _WRONG_STATE;
13868 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13870 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13871 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13873 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13874 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13875 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13876 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13880 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13882 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13883 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13885 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13887 plci->internal_command = plci->adjust_b_command;
13891 case ADJUST_B_RESTORE_DTMF_1:
13892 case ADJUST_B_RESTORE_DTMF_2:
13893 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13896 Info = dtmf_restore_config (Id, plci, Rc);
13897 if ((Info != GOOD) || plci->internal_command)
13901 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13903 case ADJUST_B_RESTORE_MIXER_1:
13904 case ADJUST_B_RESTORE_MIXER_2:
13905 case ADJUST_B_RESTORE_MIXER_3:
13906 case ADJUST_B_RESTORE_MIXER_4:
13907 case ADJUST_B_RESTORE_MIXER_5:
13908 case ADJUST_B_RESTORE_MIXER_6:
13909 case ADJUST_B_RESTORE_MIXER_7:
13910 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13913 Info = mixer_restore_config (Id, plci, Rc);
13914 if ((Info != GOOD) || plci->internal_command)
13918 plci->adjust_b_state = ADJUST_B_END;
13926 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13929 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13930 UnMapId (Id), (char *)(FILE_), __LINE__,
13931 plci->B1_resource, b1_facilities));
13933 plci->adjust_b_parms_msg = bp_msg;
13934 plci->adjust_b_facilities = b1_facilities;
13935 plci->adjust_b_command = internal_command;
13936 plci->adjust_b_ncci = (word)(Id >> 16);
13937 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13938 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13940 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13941 plci->adjust_b_state = ADJUST_B_START;
13942 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13943 UnMapId (Id), (char *)(FILE_), __LINE__,
13944 plci->B1_resource, b1_facilities));
13948 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13950 word internal_command;
13952 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13953 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13955 internal_command = plci->internal_command;
13956 plci->internal_command = 0;
13957 switch (internal_command)
13961 if (plci->req_in != 0)
13963 plci->internal_command = ADJUST_B_RESTORE_1;
13967 case ADJUST_B_RESTORE_1:
13968 if ((Rc != OK) && (Rc != OK_FC))
13970 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13971 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13973 plci->adjust_b_parms_msg = NULL;
13974 plci->adjust_b_facilities = plci->B1_facilities;
13975 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13976 plci->adjust_b_ncci = (word)(Id >> 16);
13977 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13978 plci->adjust_b_state = ADJUST_B_START;
13979 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13980 UnMapId (Id), (char *)(FILE_), __LINE__));
13981 case ADJUST_B_RESTORE_2:
13982 if (adjust_b_process (Id, plci, Rc) != GOOD)
13984 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13985 UnMapId (Id), (char *)(FILE_), __LINE__));
13987 if (plci->internal_command)
13994 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13997 word internal_command;
13999 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14000 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14003 internal_command = plci->internal_command;
14004 plci->internal_command = 0;
14005 switch (internal_command)
14009 plci->adjust_b_parms_msg = NULL;
14010 plci->adjust_b_facilities = plci->B1_facilities;
14011 plci->adjust_b_command = RESET_B3_COMMAND_1;
14012 plci->adjust_b_ncci = (word)(Id >> 16);
14013 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14014 plci->adjust_b_state = ADJUST_B_START;
14015 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14016 UnMapId (Id), (char *)(FILE_), __LINE__));
14017 case RESET_B3_COMMAND_1:
14018 Info = adjust_b_process (Id, plci, Rc);
14021 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14022 UnMapId (Id), (char *)(FILE_), __LINE__));
14025 if (plci->internal_command)
14029 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14030 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14034 static void select_b_command (dword Id, PLCI *plci, byte Rc)
14037 word internal_command;
14040 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14041 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14044 internal_command = plci->internal_command;
14045 plci->internal_command = 0;
14046 switch (internal_command)
14050 plci->adjust_b_parms_msg = &plci->saved_msg;
14051 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14052 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14054 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14055 plci->adjust_b_command = SELECT_B_COMMAND_1;
14056 plci->adjust_b_ncci = (word)(Id >> 16);
14057 if (plci->saved_msg.parms[0].length == 0)
14059 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060 ADJUST_B_MODE_NO_RESOURCE;
14064 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14065 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14067 plci->adjust_b_state = ADJUST_B_START;
14068 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14069 UnMapId (Id), (char *)(FILE_), __LINE__));
14070 case SELECT_B_COMMAND_1:
14071 Info = adjust_b_process (Id, plci, Rc);
14074 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14075 UnMapId (Id), (char *)(FILE_), __LINE__));
14078 if (plci->internal_command)
14080 if (plci->tel == ADV_VOICE)
14084 esc_chi[2] = plci->b_channel;
14085 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14089 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14093 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14096 word internal_command;
14098 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14099 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14102 internal_command = plci->internal_command;
14103 plci->internal_command = 0;
14104 switch (internal_command)
14108 case FAX_CONNECT_ACK_COMMAND_1:
14109 if (plci_nl_busy (plci))
14111 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14114 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14115 plci->NData[0].P = plci->fax_connect_info_buffer;
14116 plci->NData[0].PLength = plci->fax_connect_info_length;
14117 plci->NL.X = plci->NData;
14118 plci->NL.ReqCh = 0;
14119 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14120 plci->adapter->request (&plci->NL);
14122 case FAX_CONNECT_ACK_COMMAND_2:
14123 if ((Rc != OK) && (Rc != OK_FC))
14125 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14126 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14130 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14131 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14133 if (plci->B3_prot == 4)
14134 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14136 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14137 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14142 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14145 word internal_command;
14147 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14148 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14151 internal_command = plci->internal_command;
14152 plci->internal_command = 0;
14153 switch (internal_command)
14157 case FAX_EDATA_ACK_COMMAND_1:
14158 if (plci_nl_busy (plci))
14160 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14163 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14164 plci->NData[0].P = plci->fax_connect_info_buffer;
14165 plci->NData[0].PLength = plci->fax_edata_ack_length;
14166 plci->NL.X = plci->NData;
14167 plci->NL.ReqCh = 0;
14168 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14169 plci->adapter->request (&plci->NL);
14171 case FAX_EDATA_ACK_COMMAND_2:
14172 if ((Rc != OK) && (Rc != OK_FC))
14174 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14175 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14182 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14185 word internal_command;
14187 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14188 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14191 internal_command = plci->internal_command;
14192 plci->internal_command = 0;
14193 switch (internal_command)
14197 case FAX_CONNECT_INFO_COMMAND_1:
14198 if (plci_nl_busy (plci))
14200 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14203 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14204 plci->NData[0].P = plci->fax_connect_info_buffer;
14205 plci->NData[0].PLength = plci->fax_connect_info_length;
14206 plci->NL.X = plci->NData;
14207 plci->NL.ReqCh = 0;
14208 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14209 plci->adapter->request (&plci->NL);
14211 case FAX_CONNECT_INFO_COMMAND_2:
14212 if ((Rc != OK) && (Rc != OK_FC))
14214 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14215 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14216 Info = _WRONG_STATE;
14219 if (plci_nl_busy (plci))
14221 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14224 plci->command = _CONNECT_B3_R;
14225 nl_req_ncci (plci, N_CONNECT, 0);
14229 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14236 word internal_command;
14238 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14239 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14242 internal_command = plci->internal_command;
14243 plci->internal_command = 0;
14244 switch (internal_command)
14248 plci->adjust_b_parms_msg = NULL;
14249 plci->adjust_b_facilities = plci->B1_facilities;
14250 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14251 plci->adjust_b_ncci = (word)(Id >> 16);
14252 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14253 plci->adjust_b_state = ADJUST_B_START;
14254 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14255 UnMapId (Id), (char *)(FILE_), __LINE__));
14256 case FAX_ADJUST_B23_COMMAND_1:
14257 Info = adjust_b_process (Id, plci, Rc);
14260 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14261 UnMapId (Id), (char *)(FILE_), __LINE__));
14264 if (plci->internal_command)
14266 case FAX_ADJUST_B23_COMMAND_2:
14267 if (plci_nl_busy (plci))
14269 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14272 plci->command = _CONNECT_B3_R;
14273 nl_req_ncci (plci, N_CONNECT, 0);
14277 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14281 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14283 word internal_command;
14285 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14286 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14288 internal_command = plci->internal_command;
14289 plci->internal_command = 0;
14290 switch (internal_command)
14294 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14296 case FAX_DISCONNECT_COMMAND_1:
14297 case FAX_DISCONNECT_COMMAND_2:
14298 case FAX_DISCONNECT_COMMAND_3:
14299 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14301 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14302 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14307 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14308 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14310 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14315 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14316 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14324 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14327 word internal_command;
14329 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14330 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14333 internal_command = plci->internal_command;
14334 plci->internal_command = 0;
14335 switch (internal_command)
14339 case RTP_CONNECT_B3_REQ_COMMAND_1:
14340 if (plci_nl_busy (plci))
14342 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14345 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14346 nl_req_ncci (plci, N_CONNECT, 0);
14349 case RTP_CONNECT_B3_REQ_COMMAND_2:
14350 if ((Rc != OK) && (Rc != OK_FC))
14352 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14353 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14354 Info = _WRONG_STATE;
14357 if (plci_nl_busy (plci))
14359 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14362 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14363 plci->NData[0].PLength = plci->internal_req_buffer[0];
14364 plci->NData[0].P = plci->internal_req_buffer + 1;
14365 plci->NL.X = plci->NData;
14366 plci->NL.ReqCh = 0;
14367 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14368 plci->adapter->request (&plci->NL);
14370 case RTP_CONNECT_B3_REQ_COMMAND_3:
14373 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14377 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14380 word internal_command;
14382 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14383 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14386 internal_command = plci->internal_command;
14387 plci->internal_command = 0;
14388 switch (internal_command)
14392 case RTP_CONNECT_B3_RES_COMMAND_1:
14393 if (plci_nl_busy (plci))
14395 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14398 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14399 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14402 case RTP_CONNECT_B3_RES_COMMAND_2:
14403 if ((Rc != OK) && (Rc != OK_FC))
14405 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14406 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14407 Info = _WRONG_STATE;
14410 if (plci_nl_busy (plci))
14412 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14415 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14416 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14417 plci->NData[0].PLength = plci->internal_req_buffer[0];
14418 plci->NData[0].P = plci->internal_req_buffer + 1;
14419 plci->NL.X = plci->NData;
14420 plci->NL.ReqCh = 0;
14421 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422 plci->adapter->request (&plci->NL);
14424 case RTP_CONNECT_B3_RES_COMMAND_3:
14431 static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14433 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14435 word internal_command;
14437 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14438 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14441 internal_command = plci->internal_command;
14442 plci->internal_command = 0;
14443 switch (internal_command)
14449 plci->adjust_b_parms_msg = NULL;
14450 plci->adjust_b_facilities = plci->B1_facilities;
14451 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14452 plci->adjust_b_ncci = (word)(Id >> 16);
14453 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14454 plci->adjust_b_state = ADJUST_B_START;
14455 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14456 UnMapId (Id), (char *)(FILE_), __LINE__));
14457 case HOLD_SAVE_COMMAND_1:
14458 Info = adjust_b_process (Id, plci, Rc);
14461 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14462 UnMapId (Id), (char *)(FILE_), __LINE__));
14465 if (plci->internal_command)
14468 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14472 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14474 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14476 word internal_command;
14478 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14482 internal_command = plci->internal_command;
14483 plci->internal_command = 0;
14484 switch (internal_command)
14488 plci->adjust_b_parms_msg = NULL;
14489 plci->adjust_b_facilities = plci->B1_facilities;
14490 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14491 plci->adjust_b_ncci = (word)(Id >> 16);
14492 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14493 plci->adjust_b_state = ADJUST_B_START;
14494 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14495 UnMapId (Id), (char *)(FILE_), __LINE__));
14496 case RETRIEVE_RESTORE_COMMAND_1:
14497 Info = adjust_b_process (Id, plci, Rc);
14500 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14501 UnMapId (Id), (char *)(FILE_), __LINE__));
14504 if (plci->internal_command)
14507 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14511 static void init_b1_config (PLCI *plci)
14514 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14515 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14516 (char *)(FILE_), __LINE__));
14518 plci->B1_resource = 0;
14519 plci->B1_facilities = 0;
14521 plci->li_bchannel_id = 0;
14522 mixer_clear_config (plci);
14525 ec_clear_config (plci);
14528 dtmf_rec_clear_config (plci);
14529 dtmf_send_clear_config (plci);
14530 dtmf_parameter_clear_config (plci);
14532 adv_voice_clear_config (plci);
14533 adjust_b_clear (plci);
14537 static void clear_b1_config (PLCI *plci)
14540 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14541 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14542 (char *)(FILE_), __LINE__));
14544 adv_voice_clear_config (plci);
14545 adjust_b_clear (plci);
14547 ec_clear_config (plci);
14550 dtmf_rec_clear_config (plci);
14551 dtmf_send_clear_config (plci);
14552 dtmf_parameter_clear_config (plci);
14555 if ((plci->li_bchannel_id != 0)
14556 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14558 mixer_clear_config (plci);
14559 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560 plci->li_bchannel_id = 0;
14563 plci->B1_resource = 0;
14564 plci->B1_facilities = 0;
14568 /* -----------------------------------------------------------------
14569 XON protocol local helpers
14570 ----------------------------------------------------------------- */
14571 static void channel_flow_control_remove (PLCI * plci) {
14572 DIVA_CAPI_ADAPTER * a = plci->adapter;
14574 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14575 if (a->ch_flow_plci[i] == plci->Id) {
14576 a->ch_flow_plci[i] = 0;
14577 a->ch_flow_control[i] = 0;
14582 static void channel_x_on (PLCI * plci, byte ch) {
14583 DIVA_CAPI_ADAPTER * a = plci->adapter;
14584 if (a->ch_flow_control[ch] & N_XON_SENT) {
14585 a->ch_flow_control[ch] &= ~N_XON_SENT;
14589 static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14590 DIVA_CAPI_ADAPTER * a = plci->adapter;
14591 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593 a->ch_flow_plci[ch] = plci->Id;
14594 a->ch_flow_control_pending++;
14598 static void channel_request_xon (PLCI * plci, byte ch) {
14599 DIVA_CAPI_ADAPTER * a = plci->adapter;
14601 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602 a->ch_flow_control[ch] |= N_XON_REQ;
14603 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14604 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14608 static void channel_xmit_extended_xon (PLCI * plci) {
14609 DIVA_CAPI_ADAPTER * a;
14610 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14611 int i, one_requested = 0;
14613 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14617 for (i = 0; i < max_ch; i++) {
14618 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620 (plci->Id == a->ch_flow_plci[i])) {
14621 channel_request_xon (plci, (byte)i);
14626 if (one_requested) {
14627 channel_xmit_xon (plci);
14632 Try to xmit next X_ON
14634 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14635 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14638 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14642 if (a->last_flow_control_ch >= max_ch) {
14643 a->last_flow_control_ch = 1;
14645 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14646 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647 (plci->Id == a->ch_flow_plci[i])) {
14648 a->last_flow_control_ch = i+1;
14653 for (i = 1; i < a->last_flow_control_ch; i++) {
14654 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655 (plci->Id == a->ch_flow_plci[i])) {
14656 a->last_flow_control_ch = i+1;
14664 static void channel_xmit_xon (PLCI * plci) {
14665 DIVA_CAPI_ADAPTER * a = plci->adapter;
14668 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14671 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14674 a->ch_flow_control[ch] &= ~N_XON_REQ;
14675 a->ch_flow_control[ch] |= N_XON_SENT;
14677 plci->NL.Req = plci->nl_req = (byte)N_XON;
14678 plci->NL.ReqCh = ch;
14679 plci->NL.X = plci->NData;
14681 plci->NData[0].P = &plci->RBuffer[0];
14682 plci->NData[0].PLength = 0;
14684 plci->adapter->request(&plci->NL);
14687 static int channel_can_xon (PLCI * plci, byte ch) {
14689 DIVA_CAPI_ADAPTER * a;
14695 APPLptr = plci->appl;
14701 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14703 /* count all buffers within the Application pool */
14704 /* belonging to the same NCCI. XON if a first is */
14708 for(i=0; i<APPLptr->MaxBuffer; i++) {
14709 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14710 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14712 if ((count > 2) || (Num == 0xffff)) {
14719 /*------------------------------------------------------------------*/
14721 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14728 /**********************************************************************************/
14729 /* function groups the listening applications according to the CIP mask and the */
14730 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14733 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14734 /* OS specific part (per adapter). */
14735 /**********************************************************************************/
14736 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14738 word i,j,k,busy,group_found;
14739 dword info_mask_group[MAX_CIP_TYPES];
14740 dword cip_mask_group[MAX_CIP_TYPES];
14741 word appl_number_group_type[MAX_APPL];
14744 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14746 if(!a->group_optimization_enabled)
14748 dbug(1,dprintf("No group optimization"));
14752 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14754 for(i=0;i<MAX_CIP_TYPES;i++)
14756 info_mask_group[i] = 0;
14757 cip_mask_group [i] = 0;
14759 for(i=0;i<MAX_APPL;i++)
14761 appl_number_group_type[i] = 0;
14763 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14764 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14767 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14768 return; /* allow good application unfiltered access */
14771 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14773 if(application[i].Id && a->CIP_Mask[i] )
14775 for(k=0,busy=false; k<a->max_plci; k++)
14779 auxplci = &a->plci[k];
14780 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14783 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14785 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14788 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14793 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14795 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14796 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797 appl_number_group_type[i] = MAX_CIP_TYPES;
14799 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14801 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14802 { /* is group already present ? */
14803 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14805 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]));
14807 else if(!info_mask_group[j])
14808 { /* establish a new group */
14809 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14810 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14811 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14813 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]));
14819 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14821 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14823 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14825 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14829 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14830 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14832 if(appl_number_group_type[i] == appl_number_group_type[j])
14834 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14835 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14836 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14841 else /* application should not get a call */
14843 clear_group_ind_mask_bit (plci, i);
14851 /* OS notifies the driver about a application Capi_Register */
14852 word CapiRegister(word id)
14854 word i,j,appls_found;
14857 DIVA_CAPI_ADAPTER *a;
14859 for(i=0,appls_found=0; i<max_appl; i++)
14861 if( application[i].Id && (application[i].Id!=id) )
14863 appls_found++; /* an application has been found */
14867 if(appls_found) return true;
14868 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14873 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14875 if(!appls_found) /* first application does a capi register */
14877 if((j=get_plci(a))) /* activate L1 of all adapters */
14879 plci = &a->plci[j-1];
14881 add_p(plci,OAD,"\x01\xfd");
14882 add_p(plci,CAI,"\x01\x80");
14883 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14884 add_p(plci,SHIFT|6,NULL);
14885 add_p(plci,SIN,"\x02\x00\x00");
14886 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14887 sig_req(plci,ASSIGN,DSIG_ID);
14888 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14889 sig_req(plci,SIG_CTRL,0);
14899 /*------------------------------------------------------------------*/
14901 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14903 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14906 /* Format of vswitch_t:
14909 2 byte VSWITCH_REQ/VSWITCH_IND
14911 4 word VSwitchcommand
14918 plci->Sig.Ind==NCR_FACILITY
14922 for(i=0;i<MAX_MULTI_IE;i++)
14924 if(!parms[i][0]) continue;
14927 parms[i][0]=0; /* kill it */
14930 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14931 switch(parms[i][4])
14934 if(!plci->relatedPTYPLCI ||
14935 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14939 /* remember all necessary informations */
14940 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14944 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14945 { /* first indication after ECT-Request on Consultation Call */
14946 plci->vswitchstate=parms[i][9];
14947 parms[i][9]=2; /* State */
14948 /* now ask first Call to join */
14950 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14951 { /* Answer of VSWITCH_REQ from first Call */
14952 plci->vswitchstate=parms[i][9];
14953 /* tell consultation call to join
14954 and the protocol capabilities of the first call */
14960 plci->vsprot=parms[i][10]; /* protocol */
14961 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14962 /* send join request to related PLCI */
14963 parms[i][1]=VSWITCHIE;
14964 parms[i][2]=VSWITCH_REQ;
14966 plci->relatedPTYPLCI->command = 0;
14967 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14968 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14969 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14970 send_req(plci->relatedPTYPLCI);
14974 if(plci->relatedPTYPLCI &&
14975 plci->vswitchstate==3 &&
14976 plci->relatedPTYPLCI->vswitchstate==3)
14978 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14979 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14980 send_req(plci->relatedPTYPLCI);
14984 parms[i][0]=0; /* kill it */
14989 /*------------------------------------------------------------------*/
14991 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14993 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14995 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14999 pReq->xdi_dma_descriptor_operation.Req = 0;
15000 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15002 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15003 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15004 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15007 e.user[0] = plci->adapter->Id - 1;
15008 plci->adapter->request((ENTITY*)pReq);
15010 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15016 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15018 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15020 dbug(1,dprintf("dma_alloc failed"));
15025 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15027 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15033 pReq->xdi_dma_descriptor_operation.Req = 0;
15034 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15036 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15037 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15038 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15041 e.user[0] = plci->adapter->Id - 1;
15042 plci->adapter->request((ENTITY*)pReq);
15044 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045 dbug(1,dprintf("dma_free(%d)", nr));
15047 dbug(1,dprintf("dma_free failed (%d)", nr));
15051 /*------------------------------------------------------------------*/