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 *, const 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; i < ARRAY_SIZE(ftable); i++) {
556 if (ftable[i].command == msg->header.command) {
557 /* break loop if the message is correct, otherwise continue scan */
558 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
559 if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
563 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
567 dbug(1, dprintf("BAD_MSG"));
568 if (plci) plci->command = 0;
573 c = ftable[i].function(GET_DWORD(&msg->header.controller),
580 channel_xmit_extended_xon(plci);
582 if (c == 1) send_req(plci);
583 if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584 if (plci && !plci->req_in) plci->command = 0;
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages */
591 /*------------------------------------------------------------------*/
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
598 for (i = 0, p = 0; format[i]; i++) {
601 parms[i].info = &msg[p];
614 if (msg[p] == 0xff) {
616 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617 p += (parms[i].length + 3);
620 parms[i].length = msg[p];
621 p += (parms[i].length + 1);
626 if (p > length) return true;
628 if (parms) parms[i].info = NULL;
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
638 for (i = 0; format[i] != '\0'; i++)
640 out->parms[i].info = p;
641 out->parms[i].length = in[i].length;
654 n = in[i].length + 1;
657 for (j = 0; j < n; j++)
658 *(p++) = in[i].info[j];
660 out->parms[i].info = NULL;
661 out->parms[i].length = 0;
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
671 out[i].info = in->parms[i].info;
672 out[i].length = in->parms[i].length;
673 } while (in->parms[i++].info);
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function */
679 /*------------------------------------------------------------------*/
681 word api_remove_start(void)
686 if (!remove_started) {
687 remove_started = true;
688 for (i = 0; i < max_adapter; i++) {
689 if (adapter[i].request) {
690 for (j = 0; j < adapter[i].max_plci; j++) {
691 if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
698 for (i = 0; i < max_adapter; i++) {
699 if (adapter[i].request) {
700 for (j = 0; j < adapter[i].max_plci; j++) {
701 if (adapter[i].plci[j].Sig.Id) return 1;
706 api_remove_complete();
711 /*------------------------------------------------------------------*/
712 /* internal command queue */
713 /*------------------------------------------------------------------*/
715 static void init_internal_command_queue(PLCI *plci)
719 dbug(1, dprintf("%s,%d: init_internal_command_queue",
720 (char *)(FILE_), __LINE__));
722 plci->internal_command = 0;
723 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724 plci->internal_command_queue[i] = NULL;
728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
732 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733 UnMapId(Id), (char *)(FILE_), __LINE__));
735 if (plci->internal_command == 0)
737 plci->internal_command_queue[0] = command_function;
738 (*command_function)(Id, plci, OK);
743 while (plci->internal_command_queue[i] != NULL)
745 plci->internal_command_queue[i] = command_function;
750 static void next_internal_command(dword Id, PLCI *plci)
754 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755 UnMapId(Id), (char *)(FILE_), __LINE__));
757 plci->internal_command = 0;
758 plci->internal_command_queue[0] = NULL;
759 while (plci->internal_command_queue[1] != NULL)
761 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762 plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765 if (plci->internal_command != 0)
767 plci->internal_command_queue[0] = NULL;
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function */
774 /*------------------------------------------------------------------*/
776 static dword ncci_mapping_bug = 0;
778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
780 DIVA_CAPI_ADAPTER *a;
784 if (!ch || a->ch_ncci[ch])
787 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
797 if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
802 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
804 if (ncci == MAX_NCCI + 1)
811 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
814 if (j < MAX_NCCI + 1)
819 } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
821 } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822 if (i < MAX_NL_CHANNEL + 1)
824 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 ncci_mapping_bug, ch, force_ncci, i, k, j));
829 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830 ncci_mapping_bug, ch, force_ncci));
835 a->ncci_plci[ncci] = plci->Id;
836 a->ncci_state[ncci] = IDLE;
837 if (!plci->ncci_ring_list)
838 plci->ncci_ring_list = ncci;
840 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
843 a->ncci_ch[ncci] = ch;
844 a->ch_ncci[ch] = (byte) ncci;
845 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846 ncci_mapping_bug, ch, force_ncci, ch, ncci));
852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
854 DIVA_CAPI_ADAPTER *a;
860 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863 if (a->ncci_plci[ncci] == plci->Id)
868 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869 ncci_mapping_bug, Id));
874 ncci_code = ncci | (((word) a->Id) << 8);
875 for (i = 0; i < appl->MaxBuffer; i++)
877 if ((appl->DataNCCI[i] == ncci_code)
878 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
880 appl->DataNCCI[i] = 0;
888 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
890 if (a->ncci_plci[ncci] == plci->Id)
895 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896 ncci_mapping_bug, Id));
901 ncci_code = ncci | (((word) a->Id) << 8);
902 for (i = 0; i < appl->MaxBuffer; i++)
904 if ((appl->DataNCCI[i] == ncci_code)
905 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
907 appl->DataNCCI[i] = 0;
917 static void cleanup_ncci_data(PLCI *plci, word ncci)
921 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
923 ncci_ptr = &(plci->adapter->ncci[ncci]);
926 while (ncci_ptr->data_pending != 0)
928 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929 TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930 (ncci_ptr->data_out)++;
931 if (ncci_ptr->data_out == MAX_DATA_B3)
932 ncci_ptr->data_out = 0;
933 (ncci_ptr->data_pending)--;
936 ncci_ptr->data_out = 0;
937 ncci_ptr->data_pending = 0;
938 ncci_ptr->data_ack_out = 0;
939 ncci_ptr->data_ack_pending = 0;
944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
946 DIVA_CAPI_ADAPTER *a;
951 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
953 ncci_free_receive_buffers(plci, ncci);
956 if (a->ncci_plci[ncci] != plci->Id)
959 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 ncci_mapping_bug, Id, preserve_ncci));
964 cleanup_ncci_data(plci, ncci);
965 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967 a->ch_ncci[a->ncci_ch[ncci]] = 0;
970 a->ncci_ch[ncci] = 0;
971 a->ncci_plci[ncci] = 0;
972 a->ncci_state[ncci] = IDLE;
973 i = plci->ncci_ring_list;
974 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
976 if ((i != 0) && (a->ncci_next[i] == ncci))
979 plci->ncci_ring_list = 0;
980 else if (plci->ncci_ring_list == ncci)
981 plci->ncci_ring_list = i;
982 a->ncci_next[i] = a->ncci_next[ncci];
984 a->ncci_next[ncci] = 0;
990 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
992 if (a->ncci_plci[ncci] == plci->Id)
994 cleanup_ncci_data(plci, ncci);
995 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000 a->ncci_ch[ncci] = 0;
1001 a->ncci_plci[ncci] = 0;
1002 a->ncci_state[ncci] = IDLE;
1003 a->ncci_next[ncci] = 0;
1008 plci->ncci_ring_list = 0;
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function */
1015 /*------------------------------------------------------------------*/
1017 static void plci_free_msg_in_queue(PLCI *plci)
1023 i = plci->msg_in_read_pos;
1024 while (i != plci->msg_in_write_pos)
1026 if (i == plci->msg_in_wrap_pos)
1028 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031 TransmitBufferFree(plci->appl,
1032 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037 MSG_IN_OVERHEAD + 3) & 0xfffc;
1041 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047 static void plci_remove(PLCI *plci)
1051 dbug(1, dprintf("plci_remove(no plci)"));
1054 init_internal_command_queue(plci);
1055 dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056 if (plci_remove_check(plci))
1060 if (plci->Sig.Id == 0xff)
1062 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063 if (plci->NL.Id && !plci->nl_remove_id)
1065 nl_req_ncci(plci, REMOVE, 0);
1071 if (!plci->sig_remove_id
1073 || (plci->req_in != plci->req_out)
1074 || (plci->nl_req || plci->sig_req)))
1076 sig_req(plci, HANGUP, 0);
1080 ncci_remove(plci, 0, false);
1081 plci_free_msg_in_queue(plci);
1085 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086 plci->State = OUTG_DIS_PENDING;
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers */
1091 /*------------------------------------------------------------------*/
1093 static void set_group_ind_mask(PLCI *plci)
1097 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098 plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1103 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1108 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL */
1113 /*------------------------------------------------------------------*/
1115 static void clear_c_ind_mask(PLCI *plci)
1119 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120 plci->c_ind_mask_table[i] = 0;
1123 static byte c_ind_mask_empty(PLCI *plci)
1128 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1130 return (i == C_IND_MASK_DWORDS);
1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1135 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1140 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1145 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 static void dump_c_ind_mask(PLCI *plci)
1155 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1159 for (j = 0; j < 4; j++)
1161 if (i + j < C_IND_MASK_DWORDS)
1163 d = plci->c_ind_mask_table[i + j];
1164 for (k = 0; k < 8; k++)
1166 *(--p) = hex_asc_lo(d);
1172 for (k = 0; k < 8; k++)
1177 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1185 #define dump_plcis(a)
1189 /*------------------------------------------------------------------*/
1190 /* translation function for each message */
1191 /*------------------------------------------------------------------*/
1193 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1194 PLCI *plci, APPL *appl, API_PARSE *parms)
1202 API_PARSE ai_parms[5];
1206 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1207 static byte lli[2] = {0x01, 0x00};
1212 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1214 dbug(1, dprintf("connect_req(%d)", parms->length));
1215 Info = _WRONG_IDENTIFIER;
1218 if (a->adapter_disabled)
1220 dbug(1, dprintf("adapter disabled"));
1221 Id = ((word)1 << 8) | a->Id;
1222 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1223 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1226 Info = _OUT_OF_PLCI;
1227 if ((i = get_plci(a)))
1230 plci = &a->plci[i - 1];
1232 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1233 /* check 'external controller' bit for codec support */
1234 if (Id & EXT_CONTROLLER)
1236 if (AdvCodecSupport(a, plci, appl, 0))
1239 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1246 if (bp->length)LinkLayer = bp->info[3];
1251 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1254 if (ai_parms[0].length)
1256 ch = GET_WORD(ai_parms[0].info + 1);
1257 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1258 if (ch == 4) /* explizit CHI in message */
1260 /* check length of B-CH struct */
1261 if ((ai_parms[0].info)[3] >= 1)
1263 if ((ai_parms[0].info)[4] == CHI)
1265 p_chi = &((ai_parms[0].info)[5]);
1269 p_chi = &((ai_parms[0].info)[3]);
1271 if (p_chi[0] > 35) /* check length of channel ID */
1273 Info = _WRONG_MESSAGE_FORMAT;
1276 else Info = _WRONG_MESSAGE_FORMAT;
1279 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1281 dir = GET_WORD(ai_parms[0].info + 3);
1284 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1286 if (ai_parms[0].info[i + 5] != 0)
1288 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1289 Info = _WRONG_MESSAGE_FORMAT;
1300 Info = _WRONG_MESSAGE_FORMAT;
1303 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1305 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1306 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1307 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1311 esc_chi[2] = (byte)channel;
1312 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1313 add_p(plci, LLI, lli);
1314 add_p(plci, ESC, esc_chi);
1315 plci->State = LOCAL_CONNECT;
1316 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1321 else Info = _WRONG_MESSAGE_FORMAT;
1324 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1325 plci->command = _CONNECT_R;
1326 plci->number = Number;
1327 /* x.31 or D-ch free SAPI in LinkLayer? */
1328 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1329 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1331 /* B-channel used for B3 connections (ch==0), or no B channel */
1332 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1333 if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1334 else Info = add_b1(plci, &parms[5], ch, 0);
1335 add_s(plci, OAD, &parms[2]);
1336 add_s(plci, OSA, &parms[4]);
1337 add_s(plci, BC, &parms[6]);
1338 add_s(plci, LLC, &parms[7]);
1339 add_s(plci, HLC, &parms[8]);
1340 if (a->Info_Mask[appl->Id - 1] & 0x200)
1342 /* early B3 connect (CIP mask bit 9) no release after a disc */
1343 add_p(plci, LLI, "\x01\x01");
1345 if (GET_WORD(parms[0].info) < 29) {
1346 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1347 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1349 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1350 sig_req(plci, ASSIGN, DSIG_ID);
1354 /* D-Channel used for B3 connections */
1355 plci->Sig.Id = 0xff;
1359 if (!Info && ch != 2 && !noCh) {
1360 Info = add_b23(plci, &parms[5]);
1362 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1368 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1370 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1372 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1373 plci->spoofed_msg = CALL_REQ;
1374 plci->internal_command = BLOCK_PLCI;
1376 dbug(1, dprintf("Spoof"));
1380 if (ch == 4)add_p(plci, CHI, p_chi);
1381 add_s(plci, CPN, &parms[1]);
1382 add_s(plci, DSA, &parms[3]);
1383 if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1384 add_ai(plci, &parms[9]);
1385 if (!dir)sig_req(plci, CALL_REQ, 0);
1388 plci->command = PERM_LIST_REQ;
1390 sig_req(plci, LISTEN_REQ, 0);
1402 _CONNECT_R | CONFIRM,
1409 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1410 PLCI *plci, APPL *appl, API_PARSE *parms)
1414 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1415 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1417 API_PARSE ai_parms[5];
1421 dbug(1, dprintf("connect_res(no plci)"));
1422 return 0; /* no plci, no send */
1425 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1426 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1428 dbug(1, dprintf("ai->length=%d", ai->length));
1432 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1434 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1436 if (ai_parms[0].length)
1438 ch = GET_WORD(ai_parms[0].info + 1);
1439 dbug(1, dprintf("BCH-I=0x%x", ch));
1444 if (plci->State == INC_CON_CONNECTED_ALERT)
1446 dbug(1, dprintf("Connected Alert Call_Res"));
1447 if (a->Info_Mask[appl->Id - 1] & 0x200)
1449 /* early B3 connect (CIP mask bit 9) no release after a disc */
1450 add_p(plci, LLI, "\x01\x01");
1452 add_s(plci, CONN_NR, &parms[2]);
1453 add_s(plci, LLC, &parms[4]);
1454 add_ai(plci, &parms[5]);
1455 plci->State = INC_CON_ACCEPT;
1456 sig_req(plci, CALL_RES, 0);
1459 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1460 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1461 dump_c_ind_mask(plci);
1462 Reject = GET_WORD(parms[0].info);
1463 dbug(1, dprintf("Reject=0x%x", Reject));
1466 if (c_ind_mask_empty(plci))
1468 if ((Reject & 0xff00) == 0x3400)
1470 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1471 add_p(plci, ESC, esc_t);
1472 add_ai(plci, &parms[5]);
1473 sig_req(plci, REJECT, 0);
1475 else if (Reject == 1 || Reject >= 9)
1477 add_ai(plci, &parms[5]);
1478 sig_req(plci, HANGUP, 0);
1482 esc_t[2] = cau_t[(Reject&0x000f)];
1483 add_p(plci, ESC, esc_t);
1484 add_ai(plci, &parms[5]);
1485 sig_req(plci, REJECT, 0);
1491 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496 if (Id & EXT_CONTROLLER) {
1497 if (AdvCodecSupport(a, plci, appl, 0)) {
1498 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1499 sig_req(plci, HANGUP, 0);
1502 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1504 Info = add_b23(plci, &parms[1]);
1507 dbug(1, dprintf("connect_res(error from add_b23)"));
1508 sig_req(plci, HANGUP, 0);
1513 nl_req_ncci(plci, ASSIGN, 0);
1522 Info = add_b23(plci, &parms[1]);
1525 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1526 sig_req(plci, HANGUP, 0);
1530 nl_req_ncci(plci, ASSIGN, 0);
1533 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1535 api_save_msg(parms, "wsssss", &plci->saved_msg);
1536 plci->spoofed_msg = CALL_RES;
1537 plci->internal_command = BLOCK_PLCI;
1539 dbug(1, dprintf("Spoof"));
1543 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1544 if (a->Info_Mask[appl->Id - 1] & 0x200)
1546 /* early B3 connect (CIP mask bit 9) no release after a disc */
1547 add_p(plci, LLI, "\x01\x01");
1549 add_s(plci, CONN_NR, &parms[2]);
1550 add_s(plci, LLC, &parms[4]);
1551 add_ai(plci, &parms[5]);
1552 plci->State = INC_CON_ACCEPT;
1553 sig_req(plci, CALL_RES, 0);
1556 for (i = 0; i < max_appl; i++) {
1557 if (test_c_ind_mask_bit(plci, i)) {
1558 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1566 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1567 PLCI *plci, APPL *appl, API_PARSE *msg)
1569 dbug(1, dprintf("connect_a_res"));
1573 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1574 PLCI *plci, APPL *appl, API_PARSE *msg)
1579 dbug(1, dprintf("disconnect_req"));
1581 Info = _WRONG_IDENTIFIER;
1585 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1587 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1589 for (i = 0; i < max_appl; i++)
1591 if (test_c_ind_mask_bit(plci, i))
1592 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1594 plci->State = OUTG_DIS_PENDING;
1596 if (plci->Sig.Id && plci->appl)
1599 if (plci->Sig.Id != 0xff)
1601 if (plci->State != INC_DIS_PENDING)
1603 add_ai(plci, &msg[0]);
1604 sig_req(plci, HANGUP, 0);
1605 plci->State = OUTG_DIS_PENDING;
1611 if (plci->NL.Id && !plci->nl_remove_id)
1614 nl_req_ncci(plci, REMOVE, 0);
1615 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1616 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1617 plci->State = INC_DIS_PENDING;
1624 if (!appl) return false;
1625 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1629 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1630 PLCI *plci, APPL *appl, API_PARSE *msg)
1632 dbug(1, dprintf("disconnect_res"));
1635 /* clear ind mask bit, just in case of collsion of */
1636 /* DISCONNECT_IND and CONNECT_RES */
1637 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1638 ncci_free_receive_buffers(plci, 0);
1639 if (plci_remove_check(plci))
1643 if (plci->State == INC_DIS_PENDING
1644 || plci->State == SUSPENDING) {
1645 if (c_ind_mask_empty(plci)) {
1646 if (plci->State != SUSPENDING) plci->State = IDLE;
1647 dbug(1, dprintf("chs=%d", plci->channels));
1648 if (!plci->channels) {
1657 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1658 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;
1698 _LISTEN_R | CONFIRM,
1703 if (a) listen_check(a);
1707 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1708 PLCI *plci, APPL *appl, API_PARSE *msg)
1712 PLCI *rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1716 dbug(1, dprintf("info_req"));
1717 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1723 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1725 dbug(1, dprintf("AddInfo wrong"));
1726 Info = _WRONG_MESSAGE_FORMAT;
1729 if (!a) Info = _WRONG_STATE;
1732 { /* no fac, with CPN, or KEY */
1734 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1736 /* overlap sending option */
1737 dbug(1, dprintf("OvlSnd"));
1738 add_s(plci, CPN, &msg[0]);
1739 add_s(plci, KEY, &ai_parms[1]);
1740 sig_req(plci, INFO_REQ, 0);
1745 if (plci->State && ai_parms[2].length)
1747 /* User_Info option */
1748 dbug(1, dprintf("UUI"));
1749 add_s(plci, UUI, &ai_parms[2]);
1750 sig_req(plci, USER_DATA, 0);
1752 else if (plci->State && ai_parms[3].length)
1754 /* Facility option */
1755 dbug(1, dprintf("FAC"));
1756 add_s(plci, CPN, &msg[0]);
1757 add_ai(plci, &msg[1]);
1758 sig_req(plci, FACILITY_REQ, 0);
1762 Info = _WRONG_STATE;
1765 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1, dprintf("NCR_FAC"));
1769 if ((i = get_plci(a)))
1771 rc_plci = &a->plci[i - 1];
1772 appl->NullCREnable = true;
1773 rc_plci->internal_command = C_NCR_FAC_REQ;
1774 rc_plci->appl = appl;
1775 add_p(rc_plci, CAI, "\x01\x80");
1776 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci, ASSIGN, DSIG_ID);
1782 Info = _OUT_OF_PLCI;
1787 add_s(rc_plci, CPN, &msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci, NCR_FACILITY, 0);
1792 /* for application controlled supplementary services */
1798 Info = _WRONG_MESSAGE_FORMAT;
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1, dprintf("localInfoCon"));
1817 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1818 PLCI *plci, APPL *appl, API_PARSE *msg)
1820 dbug(1, dprintf("info_res"));
1824 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1825 PLCI *plci, APPL *appl, API_PARSE *msg)
1830 dbug(1, dprintf("alert_req"));
1832 Info = _WRONG_IDENTIFIER;
1835 Info = _ALERT_IGNORED;
1836 if (plci->State != INC_CON_ALERT) {
1837 Info = _WRONG_STATE;
1838 if (plci->State == INC_CON_PENDING) {
1840 plci->State = INC_CON_ALERT;
1841 add_ai(plci, &msg[0]);
1842 sig_req(plci, CALL_ALERT, 0);
1855 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1856 PLCI *plci, APPL *appl, API_PARSE *msg)
1863 long relatedPLCIvalue;
1864 DIVA_CAPI_ADAPTER *relatedadapter;
1866 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1867 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1869 API_PARSE ss_parms[11];
1875 dbug(1, dprintf("facility_req"));
1876 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1882 dbug(1, dprintf("wrong Ctrl"));
1883 Info = _WRONG_IDENTIFIER;
1886 selector = GET_WORD(msg[0].info);
1892 case SELECTOR_HANDSET:
1893 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1896 case SELECTOR_SU_SERV:
1899 Info = _WRONG_MESSAGE_FORMAT;
1902 SSreq = GET_WORD(&(msg[1].info[1]));
1903 PUT_WORD(&RCparms[1], SSreq);
1907 case S_GET_SUPPORTED_SERVICES:
1908 if ((i = get_plci(a)))
1910 rplci = &a->plci[i - 1];
1912 add_p(rplci, CAI, "\x01\x80");
1913 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1914 sig_req(rplci, ASSIGN, DSIG_ID);
1919 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1920 SSparms = (byte *)SSstruct;
1923 rplci->internal_command = GETSERV_REQ_PEND;
1924 rplci->number = Number;
1926 sig_req(rplci, S_SUPPORTED, 0);
1932 if (parms->length == 7)
1934 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1936 dbug(1, dprintf("format wrong"));
1937 Info = _WRONG_MESSAGE_FORMAT;
1943 Info = _WRONG_MESSAGE_FORMAT;
1946 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1947 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1949 if ((i = get_plci(a)))
1951 rplci = &a->plci[i - 1];
1953 add_p(rplci, CAI, "\x01\x80");
1954 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1955 sig_req(rplci, ASSIGN, DSIG_ID);
1962 rplci->internal_command = GET_MWI_STATE;
1963 rplci->number = Number;
1964 sig_req(rplci, MWI_POLL, 0);
1970 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1971 if (plci && plci->State && plci->SuppState == IDLE)
1973 plci->SuppState = HOLD_REQUEST;
1974 plci->command = C_HOLD_REQ;
1975 add_s(plci, CAI, &ss_parms[1]);
1976 sig_req(plci, CALL_HOLD, 0);
1980 else Info = 0x3010; /* wrong state */
1983 if (plci && plci->State && plci->SuppState == CALL_HELD)
1985 if (Id & EXT_CONTROLLER)
1987 if (AdvCodecSupport(a, plci, appl, 0))
1989 Info = 0x3010; /* wrong state */
1995 plci->SuppState = RETRIEVE_REQUEST;
1996 plci->command = C_RETRIEVE_REQ;
1997 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1999 plci->spoofed_msg = CALL_RETRIEVE;
2000 plci->internal_command = BLOCK_PLCI;
2002 dbug(1, dprintf("Spoof"));
2007 sig_req(plci, CALL_RETRIEVE, 0);
2012 else Info = 0x3010; /* wrong state */
2017 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2019 dbug(1, dprintf("format wrong"));
2020 Info = _WRONG_MESSAGE_FORMAT;
2024 if (plci && plci->State)
2026 add_s(plci, CAI, &ss_parms[2]);
2027 plci->command = SUSPEND_REQ;
2028 sig_req(plci, SUSPEND, 0);
2029 plci->State = SUSPENDING;
2032 else Info = 0x3010; /* wrong state */
2036 if (!(i = get_plci(a)))
2038 Info = _OUT_OF_PLCI;
2041 rplci = &a->plci[i - 1];
2043 rplci->number = Number;
2045 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2046 /* check 'external controller' bit for codec support */
2047 if (Id & EXT_CONTROLLER)
2049 if (AdvCodecSupport(a, rplci, appl, 0))
2058 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2060 dbug(1, dprintf("format wrong"));
2062 Info = _WRONG_MESSAGE_FORMAT;
2067 dummy.info = "\x00";
2068 add_b1(rplci, &dummy, 0, 0);
2069 if (a->Info_Mask[appl->Id - 1] & 0x200)
2071 /* early B3 connect (CIP mask bit 9) no release after a disc */
2072 add_p(rplci, LLI, "\x01\x01");
2074 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2075 sig_req(rplci, ASSIGN, DSIG_ID);
2077 add_s(rplci, CAI, &ss_parms[2]);
2078 rplci->command = RESUME_REQ;
2079 sig_req(rplci, RESUME, 0);
2080 rplci->State = RESUMING;
2084 case S_CONF_BEGIN: /* Request */
2086 case S_CONF_ISOLATE:
2087 case S_CONF_REATTACH:
2088 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2090 dbug(1, dprintf("format wrong"));
2091 Info = _WRONG_MESSAGE_FORMAT;
2094 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2096 d = GET_DWORD(ss_parms[2].info);
2099 dbug(1, dprintf("format wrong"));
2100 Info = _WRONG_MESSAGE_FORMAT;
2103 plci->ptyState = (byte)SSreq;
2109 cai[1] = CONF_BEGIN;
2110 plci->internal_command = CONF_BEGIN_REQ_PEND;
2114 plci->internal_command = CONF_DROP_REQ_PEND;
2116 case S_CONF_ISOLATE:
2117 cai[1] = CONF_ISOLATE;
2118 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2120 case S_CONF_REATTACH:
2121 cai[1] = CONF_REATTACH;
2122 plci->internal_command = CONF_REATTACH_REQ_PEND;
2125 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2126 add_p(plci, CAI, cai);
2127 sig_req(plci, S_SERVICE, 0);
2131 else Info = 0x3010; /* wrong state */
2138 if (parms->length == 7)
2140 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2142 dbug(1, dprintf("format wrong"));
2143 Info = _WRONG_MESSAGE_FORMAT;
2147 else if (parms->length == 8) /* workaround for the T-View-S */
2149 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2151 dbug(1, dprintf("format wrong"));
2152 Info = _WRONG_MESSAGE_FORMAT;
2158 Info = _WRONG_MESSAGE_FORMAT;
2163 Info = _WRONG_MESSAGE_FORMAT;
2168 Info = _WRONG_IDENTIFIER;
2171 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2172 relatedPLCIvalue &= 0x0000FFFF;
2173 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2174 /* controller starts with 0 up to (max_adapter - 1) */
2175 if (((relatedPLCIvalue & 0x7f) == 0)
2176 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2177 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2179 if (SSreq == S_3PTY_END)
2181 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186 Info = 0x3010; /* wrong state */
2192 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2193 relatedPLCIvalue >>= 8;
2195 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2197 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2199 rplci = &relatedadapter->plci[i];
2202 if (!rplci || !relatedPLCIvalue)
2204 if (SSreq == S_3PTY_END)
2206 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211 Info = 0x3010; /* wrong state */
2217 dbug(1, dprintf("rplci:%x", rplci));
2218 dbug(1, dprintf("plci:%x", plci));
2219 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2220 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2221 dbug(1, dprintf("SSreq:%x", SSreq));
2222 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2223 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2224 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2226 /* send PTY/ECT req, cannot check all states because of US stuff */
2227 if (!rplci->internal_command && rplci->appl)
2230 rplci->relatedPTYPLCI = plci;
2231 plci->relatedPTYPLCI = rplci;
2232 rplci->ptyState = (byte)SSreq;
2235 rplci->internal_command = ECT_REQ_PEND;
2236 cai[1] = ECT_EXECUTE;
2238 rplci->vswitchstate = 0;
2240 rplci->vsprotdialect = 0;
2241 plci->vswitchstate = 0;
2243 plci->vsprotdialect = 0;
2246 else if (SSreq == S_CONF_ADD)
2248 rplci->internal_command = CONF_ADD_REQ_PEND;
2253 rplci->internal_command = PTY_REQ_PEND;
2254 cai[1] = (byte)(SSreq - 3);
2256 rplci->number = Number;
2257 if (plci != rplci) /* explicit invocation */
2260 cai[2] = plci->Sig.Id;
2261 dbug(1, dprintf("explicit invocation"));
2265 dbug(1, dprintf("implicit invocation"));
2268 add_p(rplci, CAI, cai);
2269 sig_req(rplci, S_SERVICE, 0);
2275 dbug(0, dprintf("Wrong line"));
2276 Info = 0x3010; /* wrong state */
2281 case S_CALL_DEFLECTION:
2282 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2284 dbug(1, dprintf("format wrong"));
2285 Info = _WRONG_MESSAGE_FORMAT;
2290 Info = _WRONG_IDENTIFIER;
2293 /* reuse unused screening indicator */
2294 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2296 plci->internal_command = CD_REQ_PEND;
2297 appl->CDEnable = true;
2299 cai[1] = CALL_DEFLECTION;
2300 add_p(plci, CAI, cai);
2301 add_p(plci, CPN, ss_parms[3].info);
2302 sig_req(plci, S_SERVICE, 0);
2307 case S_CALL_FORWARDING_START:
2308 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2310 dbug(1, dprintf("format wrong"));
2311 Info = _WRONG_MESSAGE_FORMAT;
2315 if ((i = get_plci(a)))
2317 rplci = &a->plci[i - 1];
2319 add_p(rplci, CAI, "\x01\x80");
2320 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2321 sig_req(rplci, ASSIGN, DSIG_ID);
2326 Info = _OUT_OF_PLCI;
2330 /* reuse unused screening indicator */
2331 rplci->internal_command = CF_START_PEND;
2333 rplci->number = Number;
2334 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2336 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2337 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2338 add_p(rplci, CAI, cai);
2339 add_p(rplci, OAD, ss_parms[5].info);
2340 add_p(rplci, CPN, ss_parms[6].info);
2341 sig_req(rplci, S_SERVICE, 0);
2346 case S_INTERROGATE_DIVERSION:
2347 case S_INTERROGATE_NUMBERS:
2348 case S_CALL_FORWARDING_STOP:
2349 case S_CCBS_REQUEST:
2350 case S_CCBS_DEACTIVATE:
2351 case S_CCBS_INTERROGATE:
2354 case S_INTERROGATE_NUMBERS:
2355 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2357 dbug(0, dprintf("format wrong"));
2358 Info = _WRONG_MESSAGE_FORMAT;
2361 case S_CCBS_REQUEST:
2362 case S_CCBS_DEACTIVATE:
2363 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2365 dbug(0, dprintf("format wrong"));
2366 Info = _WRONG_MESSAGE_FORMAT;
2369 case S_CCBS_INTERROGATE:
2370 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2372 dbug(0, dprintf("format wrong"));
2373 Info = _WRONG_MESSAGE_FORMAT;
2377 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2379 dbug(0, dprintf("format wrong"));
2380 Info = _WRONG_MESSAGE_FORMAT;
2387 if ((i = get_plci(a)))
2389 rplci = &a->plci[i - 1];
2392 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2393 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2394 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2396 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2397 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2398 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2400 case S_CALL_FORWARDING_STOP:
2401 rplci->internal_command = CF_STOP_PEND;
2402 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2404 case S_CCBS_REQUEST:
2405 cai[1] = CCBS_REQUEST;
2406 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2408 case S_CCBS_DEACTIVATE:
2409 cai[1] = CCBS_DEACTIVATE;
2410 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2412 case S_CCBS_INTERROGATE:
2413 cai[1] = CCBS_INTERROGATE;
2414 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2421 rplci->number = Number;
2422 add_p(rplci, CAI, "\x01\x80");
2423 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2424 sig_req(rplci, ASSIGN, DSIG_ID);
2429 Info = _OUT_OF_PLCI;
2433 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2436 case S_INTERROGATE_NUMBERS:
2438 add_p(rplci, CAI, cai);
2440 case S_CCBS_REQUEST:
2441 case S_CCBS_DEACTIVATE:
2443 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2444 add_p(rplci, CAI, cai);
2446 case S_CCBS_INTERROGATE:
2448 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2449 add_p(rplci, CAI, cai);
2450 add_p(rplci, OAD, ss_parms[4].info);
2454 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2455 add_p(rplci, CAI, cai);
2456 add_p(rplci, OAD, ss_parms[5].info);
2460 sig_req(rplci, S_SERVICE, 0);
2465 case S_MWI_ACTIVATE:
2466 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2468 dbug(1, dprintf("format wrong"));
2469 Info = _WRONG_MESSAGE_FORMAT;
2474 if ((i = get_plci(a)))
2476 rplci = &a->plci[i - 1];
2478 rplci->cr_enquiry = true;
2479 add_p(rplci, CAI, "\x01\x80");
2480 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2481 sig_req(rplci, ASSIGN, DSIG_ID);
2486 Info = _OUT_OF_PLCI;
2493 rplci->cr_enquiry = false;
2497 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2499 rplci->number = Number;
2502 cai[1] = ACTIVATION_MWI; /* Function */
2503 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2504 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2505 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2506 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2507 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2508 add_p(rplci, CAI, cai);
2509 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2510 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2511 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2512 add_p(rplci, UID, ss_parms[10].info); /* Time */
2513 sig_req(rplci, S_SERVICE, 0);
2517 case S_MWI_DEACTIVATE:
2518 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2520 dbug(1, dprintf("format wrong"));
2521 Info = _WRONG_MESSAGE_FORMAT;
2526 if ((i = get_plci(a)))
2528 rplci = &a->plci[i - 1];
2530 rplci->cr_enquiry = true;
2531 add_p(rplci, CAI, "\x01\x80");
2532 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2533 sig_req(rplci, ASSIGN, DSIG_ID);
2538 Info = _OUT_OF_PLCI;
2545 rplci->cr_enquiry = false;
2549 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2551 rplci->number = Number;
2554 cai[1] = DEACTIVATION_MWI; /* Function */
2555 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2556 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2557 add_p(rplci, CAI, cai);
2558 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2559 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2560 sig_req(rplci, S_SERVICE, 0);
2565 Info = 0x300E; /* not supported */
2568 break; /* case SELECTOR_SU_SERV: end */
2572 return (dtmf_request(Id, Number, a, plci, appl, msg));
2576 case SELECTOR_LINE_INTERCONNECT:
2577 return (mixer_request(Id, Number, a, plci, appl, msg));
2581 case PRIV_SELECTOR_ECHO_CANCELLER:
2582 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2583 return (ec_request(Id, Number, a, plci, appl, msg));
2585 case SELECTOR_ECHO_CANCELLER:
2586 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2587 return (ec_request(Id, Number, a, plci, appl, msg));
2590 case SELECTOR_V42BIS:
2592 Info = _FACILITY_NOT_SUPPORTED;
2594 } /* end of switch (selector) */
2597 dbug(1, dprintf("SendFacRc"));
2599 _FACILITY_R | CONFIRM,
2602 "wws", Info, selector, SSparms);
2606 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2607 PLCI *plci, APPL *appl, API_PARSE *msg)
2609 dbug(1, dprintf("facility_res"));
2613 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2614 PLCI *plci, APPL *appl, API_PARSE *parms)
2620 word fax_control_bits, fax_feature_bits, fax_info_change;
2624 API_PARSE fax_parms[9];
2628 dbug(1, dprintf("connect_b3_req"));
2631 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2632 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2634 Info = _WRONG_STATE;
2638 /* local reply if assign unsuccessful
2639 or B3 protocol allows only one layer 3 connection
2640 and already connected
2641 or B2 protocol not any LAPD
2642 and connect_b3_req contradicts originate/answer direction */
2644 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2645 && ((plci->channels != 0)
2646 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2647 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2649 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2650 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2651 Info = _WRONG_STATE;
2653 _CONNECT_B3_R | CONFIRM,
2659 plci->requested_options_conn = 0;
2663 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2665 if (ncpi->length > 2)
2668 if (ncpi->info[2] || ncpi->info[3])
2670 pvc[0] = ncpi->info[3];
2671 pvc[1] = ncpi->info[2];
2672 add_d(plci, 2, pvc);
2677 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2678 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2682 else if (plci->B3_prot == 5)
2684 if (plci->NL.Id && !plci->nl_remove_id)
2686 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2687 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2688 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2689 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2691 len = offsetof(T30_INFO, universal_6);
2692 fax_info_change = false;
2693 if (ncpi->length >= 4)
2695 w = GET_WORD(&ncpi->info[3]);
2696 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2698 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2699 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2700 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2701 fax_info_change = true;
2703 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2704 if (w & 0x0002) /* Fax-polling request */
2705 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2706 if ((w & 0x0004) /* Request to send / poll another document */
2707 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2709 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2711 if (ncpi->length >= 6)
2713 w = GET_WORD(&ncpi->info[5]);
2714 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2716 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2717 fax_info_change = true;
2720 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2721 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2723 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2725 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2726 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2728 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2730 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2731 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2732 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2733 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2735 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2736 Info = _WRONG_MESSAGE_FORMAT;
2739 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2740 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2742 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2743 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2744 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2746 w = fax_parms[4].length;
2749 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2750 for (i = 0; i < w; i++)
2751 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2752 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2753 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2754 w = fax_parms[5].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[5].info[1 + i];
2760 w = fax_parms[6].length;
2763 plci->fax_connect_info_buffer[len++] = (byte) w;
2764 for (i = 0; i < w; i++)
2765 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2766 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2767 & (1L << PRIVATE_FAX_NONSTANDARD))
2769 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2771 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2772 plci->fax_connect_info_buffer[len++] = 0;
2776 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2777 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2778 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2779 for (i = 0; i < fax_parms[7].length; i++)
2780 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2787 len = offsetof(T30_INFO, universal_6);
2789 fax_info_change = true;
2792 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2794 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2795 fax_info_change = true;
2800 plci->fax_connect_info_length = len;
2801 if (fax_info_change)
2803 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2805 start_internal_command(Id, plci, fax_connect_info_command);
2810 start_internal_command(Id, plci, fax_adjust_b23_command);
2816 else Info = _WRONG_STATE;
2818 else Info = _WRONG_STATE;
2821 else if (plci->B3_prot == B3_RTP)
2823 plci->internal_req_buffer[0] = ncpi->length + 1;
2824 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2825 for (w = 0; w < ncpi->length; w++)
2826 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2827 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2833 nl_req_ncci(plci, req, 0);
2838 else Info = _WRONG_IDENTIFIER;
2841 _CONNECT_B3_R | CONFIRM,
2848 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2849 PLCI *plci, APPL *appl, API_PARSE *parms)
2858 API_PARSE fax_parms[9];
2863 dbug(1, dprintf("connect_b3_res"));
2865 ncci = (word)(Id >> 16);
2867 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2868 if (GET_WORD(&parms[0].info[0]) != 0)
2870 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2871 channel_request_xon(plci, a->ncci_ch[ncci]);
2872 channel_xmit_xon(plci);
2873 cleanup_ncci_data(plci, ncci);
2874 nl_req_ncci(plci, N_DISC, (byte)ncci);
2877 a->ncci_state[ncci] = INC_ACT_PENDING;
2879 req = N_CONNECT_ACK;
2881 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2885 & (1L << PRIVATE_FAX_NONSTANDARD))
2887 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2888 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2889 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2891 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2892 if (plci->fax_connect_info_length < len)
2894 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2895 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2897 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2899 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2903 if (plci->fax_connect_info_length <= len)
2904 plci->fax_connect_info_buffer[len] = 0;
2905 len += 1 + plci->fax_connect_info_buffer[len];
2906 if (plci->fax_connect_info_length <= len)
2907 plci->fax_connect_info_buffer[len] = 0;
2908 len += 1 + plci->fax_connect_info_buffer[len];
2909 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2910 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2911 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2912 for (i = 0; i < fax_parms[7].length; i++)
2913 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2915 plci->fax_connect_info_length = len;
2916 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2917 start_internal_command(Id, plci, fax_connect_ack_command);
2922 nl_req_ncci(plci, req, (byte)ncci);
2923 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2924 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2926 if (plci->B3_prot == 4)
2927 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2929 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2930 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2934 else if (plci->B3_prot == B3_RTP)
2936 plci->internal_req_buffer[0] = ncpi->length + 1;
2937 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2938 for (w = 0; w < ncpi->length; w++)
2939 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2940 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2946 if (ncpi->length > 2) {
2947 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2948 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2950 nl_req_ncci(plci, req, (byte)ncci);
2951 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2952 if (plci->adjust_b_restore)
2954 plci->adjust_b_restore = false;
2955 start_internal_command(Id, plci, adjust_b_restore);
2964 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2965 PLCI *plci, APPL *appl, API_PARSE *parms)
2969 ncci = (word)(Id >> 16);
2970 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2972 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2973 && (plci->State != OUTG_DIS_PENDING))
2975 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2976 a->ncci_state[ncci] = CONNECTED;
2977 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2978 channel_request_xon(plci, a->ncci_ch[ncci]);
2979 channel_xmit_xon(plci);
2985 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2986 PLCI *plci, APPL *appl, API_PARSE *parms)
2992 dbug(1, dprintf("disconnect_b3_req"));
2994 Info = _WRONG_IDENTIFIER;
2995 ncci = (word)(Id >> 16);
2998 Info = _WRONG_STATE;
2999 if ((a->ncci_state[ncci] == CONNECTED)
3000 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3001 || (a->ncci_state[ncci] == INC_CON_PENDING)
3002 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3004 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3005 channel_request_xon(plci, a->ncci_ch[ncci]);
3006 channel_xmit_xon(plci);
3008 if (a->ncci[ncci].data_pending
3009 && ((plci->B3_prot == B3_TRANSPARENT)
3010 || (plci->B3_prot == B3_T30)
3011 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3013 plci->send_disc = (byte)ncci;
3019 cleanup_ncci_data(plci, ncci);
3021 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3024 if (ncpi->length > 3)
3026 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029 nl_req_ncci(plci, N_DISC, (byte)ncci);
3035 _DISCONNECT_B3_R | CONFIRM,
3042 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3043 PLCI *plci, APPL *appl, API_PARSE *parms)
3048 ncci = (word)(Id >> 16);
3049 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3051 plci->requested_options_conn = 0;
3052 plci->fax_connect_info_length = 0;
3053 plci->ncpi_state = 0x00;
3054 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3055 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3057 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3059 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3060 if (i < MAX_CHANNELS_PER_PLCI) {
3061 if (plci->channels)plci->channels--;
3062 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3063 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3065 ncci_free_receive_buffers(plci, ncci);
3067 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3068 if (plci->State == SUSPENDING) {
3073 "ws", (word)3, "\x03\x04\x00\x00");
3074 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3082 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3083 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3084 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3086 ncci_free_receive_buffers(plci, ncci);
3088 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3090 plci->adapter->ncci_state[ncci] = IDLE;
3091 start_internal_command(Id, plci, fax_disconnect_command);
3099 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3100 PLCI *plci, APPL *appl, API_PARSE *parms)
3108 dbug(1, dprintf("data_b3_req"));
3110 Info = _WRONG_IDENTIFIER;
3111 ncci = (word)(Id >> 16);
3112 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3116 Info = _WRONG_STATE;
3117 if ((a->ncci_state[ncci] == CONNECTED)
3118 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3121 ncci_ptr = &(a->ncci[ncci]);
3122 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3123 if (i >= MAX_DATA_B3)
3125 data = &(ncci_ptr->DBuffer[i]);
3126 data->Number = Number;
3127 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3128 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3135 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3136 data->Length = GET_WORD(parms[1].info);
3137 data->Handle = GET_WORD(parms[2].info);
3138 data->Flags = GET_WORD(parms[3].info);
3139 (ncci_ptr->data_pending)++;
3141 /* check for delivery confirmation */
3142 if (data->Flags & 0x0004)
3144 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3145 if (i >= MAX_DATA_ACK)
3147 ncci_ptr->DataAck[i].Number = data->Number;
3148 ncci_ptr->DataAck[i].Handle = data->Handle;
3149 (ncci_ptr->data_ack_pending)++;
3160 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3161 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3169 _DATA_B3_R | CONFIRM,
3172 "ww", GET_WORD(parms[2].info), Info);
3177 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3178 PLCI *plci, APPL *appl, API_PARSE *parms)
3184 dbug(1, dprintf("data_b3_res"));
3186 ncci = (word)(Id >> 16);
3188 n = GET_WORD(parms[0].info);
3189 dbug(1, dprintf("free(%d)", n));
3190 NCCIcode = ncci | (((word) a->Id) << 8);
3191 if (n < appl->MaxBuffer &&
3192 appl->DataNCCI[n] == NCCIcode &&
3193 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3194 dbug(1, dprintf("found"));
3195 appl->DataNCCI[n] = 0;
3197 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3198 channel_request_xon(plci, a->ncci_ch[ncci]);
3200 channel_xmit_xon(plci);
3202 if (appl->DataFlags[n] & 4) {
3203 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3211 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3212 PLCI *plci, APPL *appl, API_PARSE *parms)
3217 dbug(1, dprintf("reset_b3_req"));
3219 Info = _WRONG_IDENTIFIER;
3220 ncci = (word)(Id >> 16);
3223 Info = _WRONG_STATE;
3224 switch (plci->B3_prot)
3228 if (a->ncci_state[ncci] == CONNECTED)
3230 nl_req_ncci(plci, N_RESET, (byte)ncci);
3235 case B3_TRANSPARENT:
3236 if (a->ncci_state[ncci] == CONNECTED)
3238 start_internal_command(Id, plci, reset_b3_command);
3244 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3246 _RESET_B3_R | CONFIRM,
3253 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3254 PLCI *plci, APPL *appl, API_PARSE *parms)
3258 dbug(1, dprintf("reset_b3_res"));
3260 ncci = (word)(Id >> 16);
3262 switch (plci->B3_prot)
3266 if (a->ncci_state[ncci] == INC_RES_PENDING)
3268 a->ncci_state[ncci] = CONNECTED;
3269 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3278 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3279 PLCI *plci, APPL *appl, API_PARSE *parms)
3285 dbug(1, dprintf("connect_b3_t90_a_res"));
3287 ncci = (word)(Id >> 16);
3289 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3290 a->ncci_state[ncci] = CONNECTED;
3292 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3293 a->ncci_state[ncci] = CONNECTED;
3295 req = N_CONNECT_ACK;
3297 /* parms[0]==0 for CAPI original message definition! */
3298 if (parms[0].info) {
3300 if (ncpi->length > 2) {
3301 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3302 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305 nl_req_ncci(plci, req, (byte)ncci);
3313 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3314 PLCI *plci, APPL *appl, API_PARSE *msg)
3319 API_PARSE bp_parms[7];
3323 Info = _WRONG_IDENTIFIER;
3327 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3328 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3329 dbug(1, dprintf("PlciState=0x%x", plci->State));
3330 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3332 /* check if no channel is open, no B3 connected only */
3333 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3334 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3336 Info = _WRONG_STATE;
3338 /* check message format and fill bp_parms pointer */
3339 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3341 Info = _WRONG_MESSAGE_FORMAT;
3345 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3346 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3347 if (Id & EXT_CONTROLLER)
3349 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3352 plci->State = INC_CON_CONNECTED_ALERT;
3354 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3355 dump_c_ind_mask(plci);
3356 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3357 { /* its quasi a connect */
3358 if (test_c_ind_mask_bit(plci, i))
3359 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3363 api_save_msg(msg, "s", &plci->saved_msg);
3365 if (Id & EXT_CONTROLLER)
3367 if (tel) /* external controller in use by this PLCI */
3369 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3371 dbug(1, dprintf("Ext_Ctrl in use 1"));
3372 Info = _WRONG_STATE;
3375 else /* external controller NOT in use by this PLCI ? */
3377 if (a->AdvSignalPLCI)
3379 dbug(1, dprintf("Ext_Ctrl in use 2"));
3380 Info = _WRONG_STATE;
3382 else /* activate the codec */
3384 dbug(1, dprintf("Ext_Ctrl start"));
3385 if (AdvCodecSupport(a, plci, appl, 0))
3387 dbug(1, dprintf("Error in codec procedures"));
3388 Info = _WRONG_STATE;
3390 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3392 plci->spoofed_msg = AWAITING_SELECT_B;
3393 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3395 dbug(1, dprintf("continue if codec loaded"));
3401 else /* external controller bit is OFF */
3403 if (tel) /* external controller in use, need to switch off */
3405 if (a->AdvSignalAppl == appl)
3407 CodecIdCheck(a, plci);
3410 dbug(1, dprintf("Ext_Ctrl disable"));
3414 dbug(1, dprintf("Ext_Ctrl not requested"));
3420 if (plci->call_dir & CALL_DIR_OUT)
3421 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3422 else if (plci->call_dir & CALL_DIR_IN)
3423 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3424 start_internal_command(Id, plci, select_b_command);
3429 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3433 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3434 PLCI *plci, APPL *appl, API_PARSE *parms)
3440 API_PARSE m_parms[5];
3445 static byte chi[2] = {0x01, 0x00};
3446 static byte lli[2] = {0x01, 0x00};
3447 static byte codec_cai[2] = {0x01, 0x01};
3448 static byte null_msg = {0};
3449 static API_PARSE null_parms = { 0, &null_msg };
3453 dbug(1, dprintf("manufacturer_req"));
3454 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3456 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3457 Info = _WRONG_MESSAGE_FORMAT;
3459 command = GET_WORD(parms[1].info);
3464 case _DI_ASSIGN_PLCI:
3465 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3466 Info = _WRONG_MESSAGE_FORMAT;
3469 codec = GET_WORD(m_parms[0].info);
3470 ch = m_parms[1].info[0];
3471 dir = m_parms[2].info[0];
3472 if ((i = get_plci(a))) {
3473 plci = &a->plci[i - 1];
3475 plci->command = _MANUFACTURER_R;
3476 plci->m_command = command;
3477 plci->number = Number;
3478 plci->State = LOCAL_CONNECT;
3479 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3480 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3482 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3483 chi[1] = (byte)(0x80 | ch);
3485 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3489 Info = add_b1(plci, &m_parms[3], 0, 0);
3492 add_p(plci, CAI, codec_cai);
3494 /* manual 'swich on' to the codec support without signalling */
3495 /* first 'assign plci' with this function, then use */
3497 if (AdvCodecSupport(a, plci, appl, 0)) {
3498 Info = _RESOURCE_ERROR;
3501 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3502 lli[1] = 0x10; /* local call codec stream */
3507 plci->State = LOCAL_CONNECT;
3508 plci->manufacturer = true;
3509 plci->command = _MANUFACTURER_R;
3510 plci->m_command = command;
3511 plci->number = Number;
3515 add_p(plci, LLI, lli);
3516 add_p(plci, CHI, chi);
3517 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3518 sig_req(plci, ASSIGN, DSIG_ID);
3522 Info = add_b23(plci, &m_parms[3]);
3525 nl_req_ncci(plci, ASSIGN, 0);
3531 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3532 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3534 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3535 plci->spoofed_msg = AWAITING_MANUF_CON;
3536 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3542 sig_req(plci, CALL_REQ, 0);
3545 sig_req(plci, LISTEN_REQ, 0);
3552 _MANUFACTURER_R | CONFIRM,
3555 "dww", _DI_MANU_ID, command, Info);
3561 else Info = _OUT_OF_PLCI;
3567 Info = _WRONG_IDENTIFIER;
3570 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3571 Info = _WRONG_MESSAGE_FORMAT;
3574 req = m_parms[0].info[0];
3575 plci->command = _MANUFACTURER_R;
3576 plci->m_command = command;
3577 plci->number = Number;
3578 if (req == CALL_REQ)
3580 plci->b_channel = getChannel(&m_parms[1]);
3581 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3582 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3584 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3585 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3590 else if (req == LAW_REQ)
3592 plci->cr_enquiry = true;
3594 add_ss(plci, FTY, &m_parms[1]);
3595 sig_req(plci, req, 0);
3599 if (plci->NL.Id && !plci->nl_remove_id)
3603 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3605 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3607 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3608 cleanup_ncci_data(plci, ncci);
3609 nl_req_ncci(plci, N_DISC, (byte)ncci);
3614 nl_req_ncci(plci, REMOVE, 0);
3621 /* signalling control for loop activation B-channel */
3624 Info = _WRONG_IDENTIFIER;
3628 plci->command = _MANUFACTURER_R;
3629 plci->number = Number;
3630 add_ss(plci, FTY, m);
3631 sig_req(plci, SIG_CTRL, 0);
3634 else Info = _WRONG_MESSAGE_FORMAT;
3638 /* activation control for receiver/transmitter B-channel */
3641 Info = _WRONG_IDENTIFIER;
3645 plci->command = _MANUFACTURER_R;
3646 plci->number = Number;
3647 add_ss(plci, FTY, m);
3648 sig_req(plci, DSP_CTRL, 0);
3651 else Info = _WRONG_MESSAGE_FORMAT;
3656 /* TEL_CTRL commands to support non standard adjustments: */
3657 /* Ring on/off, Handset micro volume, external micro vol. */
3658 /* handset+external speaker volume, receiver+transm. gain,*/
3659 /* handsfree on (hookinfo off), set mixer command */
3661 if (command == _DI_ADV_CODEC)
3663 if (!a->AdvCodecPLCI) {
3664 Info = _WRONG_STATE;
3667 v_plci = a->AdvCodecPLCI;
3673 && (m->info[1] == 0x1c)
3674 && (m->info[2] >= 1))
3676 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3678 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3680 Info = _WRONG_STATE;
3683 a->adv_voice_coef_length = m->info[2] - 1;
3684 if (a->adv_voice_coef_length > m->length - 3)
3685 a->adv_voice_coef_length = (byte)(m->length - 3);
3686 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3687 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3688 for (i = 0; i < a->adv_voice_coef_length; i++)
3689 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3690 if (plci->B1_facilities & B1_FACILITY_VOICE)
3691 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3694 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3696 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3698 Info = _FACILITY_NOT_SUPPORTED;
3702 plci->dtmf_parameter_length = m->info[2] - 1;
3703 if (plci->dtmf_parameter_length > m->length - 3)
3704 plci->dtmf_parameter_length = (byte)(m->length - 3);
3705 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3706 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3707 for (i = 0; i < plci->dtmf_parameter_length; i++)
3708 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3709 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3710 dtmf_parameter_write(plci);
3720 Info = _WRONG_IDENTIFIER;
3724 add_ss(v_plci, FTY, m);
3725 sig_req(v_plci, TEL_CTRL, 0);
3728 else Info = _WRONG_MESSAGE_FORMAT;
3732 case _DI_OPTIONS_REQUEST:
3733 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3734 Info = _WRONG_MESSAGE_FORMAT;
3737 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3739 Info = _FACILITY_NOT_SUPPORTED;
3742 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3748 Info = _WRONG_MESSAGE_FORMAT;
3754 _MANUFACTURER_R | CONFIRM,
3757 "dww", _DI_MANU_ID, command, Info);
3762 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3763 PLCI *plci, APPL *appl, API_PARSE *msg)
3767 API_PARSE m_parms[3];
3769 API_PARSE fax_parms[9];
3774 dbug(1, dprintf("manufacturer_res"));
3776 if ((msg[0].length == 0)
3777 || (msg[1].length == 0)
3778 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3782 indication = GET_WORD(msg[1].info);
3786 case _DI_NEGOTIATE_B3:
3789 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3790 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3792 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3797 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3801 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3802 if (plci->fax_connect_info_length < len)
3804 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3805 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3807 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3809 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3813 if (plci->fax_connect_info_length <= len)
3814 plci->fax_connect_info_buffer[len] = 0;
3815 len += 1 + plci->fax_connect_info_buffer[len];
3816 if (plci->fax_connect_info_length <= len)
3817 plci->fax_connect_info_buffer[len] = 0;
3818 len += 1 + plci->fax_connect_info_buffer[len];
3819 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3820 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3821 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3822 for (i = 0; i < fax_parms[7].length; i++)
3823 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3825 plci->fax_connect_info_length = len;
3826 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3827 start_internal_command(Id, plci, fax_edata_ack_command);
3834 /*------------------------------------------------------------------*/
3835 /* IDI callback function */
3836 /*------------------------------------------------------------------*/
3838 void callback(ENTITY *e)
3840 DIVA_CAPI_ADAPTER *a;
3851 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3852 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3854 a = &(adapter[(byte)e->user[0]]);
3855 plci = &(a->plci[e->user[1]]);
3856 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859 If new protocol code and new XDI is used then CAPI should work
3860 fully in accordance with IDI cpec an look on callback field instead
3861 of Rc field for return codes.
3863 if (((e->complete == 0xff) && no_cancel_rc) ||
3864 (e->Rc && !no_cancel_rc)) {
3870 if (e->user[0] & 0x8000)
3873 If REMOVE request was sent then we have to wait until
3874 return code with Id set to zero arrives.
3875 All other return codes should be ignored.
3881 dbug(1, dprintf("cancel RC in REMOVE state"));
3884 channel_flow_control_remove(plci);
3885 for (i = 0; i < 256; i++)
3887 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3888 a->FlowControlIdTable[i] = 0;
3890 plci->nl_remove_id = 0;
3891 if (plci->rx_dma_descriptor > 0) {
3892 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3893 plci->rx_dma_descriptor = 0;
3898 a->FlowControlIdTable[ch] = e->Id;
3899 a->FlowControlSkipTable[ch] = 0;
3901 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3902 a->ch_flow_plci[ch] = plci->Id;
3908 Cancel return codes self, if feature was requested
3910 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3911 a->FlowControlIdTable[ch] = 0;
3912 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3913 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3918 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3920 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3928 control_rc(plci, 0, rc, ch, 0, true);
3933 channel_x_on(plci, ch);
3934 if (plci->internal_command)
3935 control_rc(plci, req, rc, ch, 0, true);
3939 if (plci->nl_global_req)
3941 global_req = plci->nl_global_req;
3942 plci->nl_global_req = 0;
3943 if (rc != ASSIGN_OK) {
3945 if (plci->rx_dma_descriptor > 0) {
3946 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3947 plci->rx_dma_descriptor = 0;
3950 channel_xmit_xon(plci);
3951 control_rc(plci, 0, rc, ch, global_req, true);
3953 else if (plci->data_sent)
3955 channel_xmit_xon(plci);
3956 plci->data_sent = false;
3959 if (plci->internal_command)
3960 control_rc(plci, req, rc, ch, 0, true);
3964 channel_xmit_xon(plci);
3965 control_rc(plci, req, rc, ch, 0, true);
3973 If REMOVE request was sent then we have to wait until
3974 return code with Id set to zero arrives.
3975 All other return codes should be ignored.
3981 dbug(1, dprintf("cancel RC in REMOVE state"));
3984 plci->sig_remove_id = 0;
3987 if (plci->sig_global_req)
3989 global_req = plci->sig_global_req;
3990 plci->sig_global_req = 0;
3991 if (rc != ASSIGN_OK)
3993 channel_xmit_xon(plci);
3994 control_rc(plci, 0, rc, ch, global_req, false);
3998 channel_xmit_xon(plci);
3999 control_rc(plci, req, rc, ch, 0, false);
4003 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4004 same callback. Also if new XDI and protocol code used then jump
4008 channel_xmit_xon(plci);
4009 goto capi_callback_suffix;
4013 channel_xmit_xon(plci);
4016 if (e->user[0] & 0x8000) {
4017 byte Ind = e->Ind & 0x0f;
4019 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4020 (a->ch_flow_plci[Ch] == plci->Id)) {
4021 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4022 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4024 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4027 if ((e->RNR != 1) &&
4028 (a->ch_flow_plci[Ch] == plci->Id) &&
4029 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4030 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4031 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4039 capi_callback_suffix:
4041 while (!plci->req_in
4042 && !plci->internal_command
4043 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4045 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4047 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4049 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4050 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4051 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4052 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4053 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4055 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4056 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4060 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4062 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4064 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4065 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4067 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4069 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4072 i = api_put(appl, m);
4075 if (m->header.command == _DATA_B3_R)
4077 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4079 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4083 if (plci->li_notify_update)
4085 plci->li_notify_update = false;
4086 mixer_notify_update(plci, false);
4095 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4104 DIVA_CAPI_ADAPTER *a;
4107 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4108 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4114 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4115 if (plci->req_in != plci->req_out)
4117 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4119 dbug(1, dprintf("req_1return"));
4122 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4124 plci->req_in = plci->req_in_start = plci->req_out = 0;
4125 dbug(1, dprintf("control_rc"));
4129 ncci = a->ch_ncci[ch];
4132 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4133 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4134 Number = plci->number;
4135 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));
4136 dbug(1, dprintf("channels=0x%x", plci->channels));
4137 if (plci_remove_check(plci))
4139 if (req == REMOVE && rc == ASSIGN_OK)
4141 sig_req(plci, HANGUP, 0);
4142 sig_req(plci, REMOVE, 0);
4147 switch (plci->command)
4150 dbug(1, dprintf("HoldRC=0x%x", rc));
4151 SSparms[1] = (byte)S_HOLD;
4154 plci->SuppState = IDLE;
4157 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4160 case C_RETRIEVE_REQ:
4161 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4162 SSparms[1] = (byte)S_RETRIEVE;
4165 plci->SuppState = CALL_HELD;
4168 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4172 dbug(1, dprintf("InfoRC=0x%x", rc));
4173 if (rc != OK) Info = _WRONG_STATE;
4174 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4178 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4179 if (plci->State == INC_DIS_PENDING)
4181 if (plci->Sig.Id != 0xff)
4183 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4184 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4186 dbug(1, dprintf("No more IDs/Call_Req failed"));
4187 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4192 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4193 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4195 else /* D-ch activation */
4197 if (rc != ASSIGN_OK)
4199 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4200 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4205 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4206 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4207 plci->State = INC_ACT_PENDING;
4211 case _CONNECT_I | RESPONSE:
4212 if (plci->State != INC_DIS_PENDING)
4213 plci->State = INC_CON_ACCEPT;
4217 if (plci->State == INC_DIS_PENDING)
4219 if (plci->Sig.Id != 0xff)
4221 plci->State = OUTG_DIS_PENDING;
4222 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4235 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4238 ncci = get_ncci(plci, ch, 0);
4239 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4243 a->ncci_state[ncci] = INC_ACT_PENDING;
4244 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4245 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4249 a->ncci_state[ncci] = OUTG_CON_PENDING;
4250 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4254 case _CONNECT_B3_I | RESPONSE:
4258 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261 case _DISCONNECT_B3_R:
4262 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4265 case _MANUFACTURER_R:
4271 Info = _WRONG_IDENTIFIER;
4272 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4276 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4284 else if (plci->internal_command)
4286 switch (plci->internal_command)
4292 if (rc == OK) /* command supported, wait for indication */
4299 /* Get Supported Services */
4300 case GETSERV_REQ_PEND:
4301 if (rc == OK) /* command supported, wait for indication */
4305 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4306 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4310 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4311 case INTERR_NUMBERS_REQ_PEND:
4312 case CF_START_PEND: /* Call Forwarding Start pending */
4313 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4314 case CCBS_REQUEST_REQ_PEND:
4315 case CCBS_DEACTIVATE_REQ_PEND:
4316 case CCBS_INTERROGATE_REQ_PEND:
4317 switch (plci->internal_command)
4319 case INTERR_DIVERSION_REQ_PEND:
4320 SSparms[1] = S_INTERROGATE_DIVERSION;
4322 case INTERR_NUMBERS_REQ_PEND:
4323 SSparms[1] = S_INTERROGATE_NUMBERS;
4326 SSparms[1] = S_CALL_FORWARDING_START;
4329 SSparms[1] = S_CALL_FORWARDING_STOP;
4331 case CCBS_REQUEST_REQ_PEND:
4332 SSparms[1] = S_CCBS_REQUEST;
4334 case CCBS_DEACTIVATE_REQ_PEND:
4335 SSparms[1] = S_CCBS_DEACTIVATE;
4337 case CCBS_INTERROGATE_REQ_PEND:
4338 SSparms[1] = S_CCBS_INTERROGATE;
4341 if (global_req == ASSIGN)
4343 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4346 if (!plci->appl) break;
4347 if (rc == ISDN_GUARD_REJ)
4349 Info = _CAPI_GUARD_ERROR;
4353 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4355 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4356 plci->number, "wws", Info, (word)3, SSparms);
4357 if (Info) plci_remove(plci);
4360 /* 3pty conference pending */
4362 if (!plci->relatedPTYPLCI) break;
4363 rplci = plci->relatedPTYPLCI;
4364 SSparms[1] = plci->ptyState;
4365 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4366 if (rplci->tel) rId |= EXT_CONTROLLER;
4369 Info = 0x300E; /* not supported */
4370 plci->relatedPTYPLCI = NULL;
4374 _FACILITY_R | CONFIRM,
4377 "wws", Info, (word)3, SSparms);
4380 /* Explicit Call Transfer pending */
4382 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4383 if (!plci->relatedPTYPLCI) break;
4384 rplci = plci->relatedPTYPLCI;
4386 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4387 if (rplci->tel) rId |= EXT_CONTROLLER;
4390 Info = 0x300E; /* not supported */
4391 plci->relatedPTYPLCI = NULL;
4395 _FACILITY_R | CONFIRM,
4398 "wws", Info, (word)3, SSparms);
4401 case _MANUFACTURER_R:
4402 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4403 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4405 dbug(1, dprintf("No more IDs"));
4406 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4407 plci_remove(plci); /* after codec init, internal codec commands pending */
4412 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4413 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4415 dbug(1, dprintf("No more IDs"));
4416 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4417 plci_remove(plci); /* after codec init, internal codec commands pending */
4421 case PERM_COD_HOOK: /* finished with Hook_Ind */
4425 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4426 plci->internal_command = PERM_COD_CONN_PEND;
4429 case PERM_COD_ASSIGN:
4430 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4431 if (rc != ASSIGN_OK) break;
4432 sig_req(plci, CALL_REQ, 0);
4434 plci->internal_command = PERM_COD_CALL;
4437 /* Null Call Reference Request pending */
4439 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4440 if (global_req == ASSIGN)
4442 if (rc == ASSIGN_OK)
4448 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4449 appl->NullCREnable = false;
4453 else if (req == NCR_FACILITY)
4457 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4461 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4462 appl->NullCREnable = false;
4471 if (a->ncci_state[ncci] == CONNECTED)
4473 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4474 cleanup_ncci_data(plci, ncci);
4475 nl_req_ncci(plci, N_DISC, (byte)ncci);
4482 if (plci->State == INC_DIS_PENDING)
4484 sig_req(plci, CALL_REQ, 0);
4486 plci->State = OUTG_CON_PENDING;
4490 case MWI_ACTIVATE_REQ_PEND:
4491 case MWI_DEACTIVATE_REQ_PEND:
4492 if (global_req == ASSIGN && rc == ASSIGN_OK)
4494 dbug(1, dprintf("MWI_REQ assigned"));
4501 Info = 0x2007; /* Illegal message parameter coding */
4502 dbug(1, dprintf("MWI_REQ invalid parameter"));
4506 Info = 0x300B; /* not supported */
4507 dbug(1, dprintf("MWI_REQ not supported"));
4509 /* 0x3010: Request not allowed in this state */
4510 PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4515 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4517 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4519 if (plci->cr_enquiry)
4522 _FACILITY_R | CONFIRM,
4525 "wws", Info, (word)3, SSparms);
4526 if (rc != OK) plci_remove(plci);
4531 _FACILITY_R | CONFIRM,
4534 "wws", Info, (word)3, SSparms);
4538 case CONF_BEGIN_REQ_PEND:
4539 case CONF_ADD_REQ_PEND:
4540 case CONF_SPLIT_REQ_PEND:
4541 case CONF_DROP_REQ_PEND:
4542 case CONF_ISOLATE_REQ_PEND:
4543 case CONF_REATTACH_REQ_PEND:
4544 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4545 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4548 switch (plci->internal_command)
4550 case CONF_BEGIN_REQ_PEND:
4551 SSparms[1] = S_CONF_BEGIN;
4553 case CONF_ADD_REQ_PEND:
4554 SSparms[1] = S_CONF_ADD;
4555 rplci = plci->relatedPTYPLCI;
4556 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4558 case CONF_SPLIT_REQ_PEND:
4559 SSparms[1] = S_CONF_SPLIT;
4561 case CONF_DROP_REQ_PEND:
4562 SSparms[1] = S_CONF_DROP;
4564 case CONF_ISOLATE_REQ_PEND:
4565 SSparms[1] = S_CONF_ISOLATE;
4567 case CONF_REATTACH_REQ_PEND:
4568 SSparms[1] = S_CONF_REATTACH;
4574 Info = 0x300E; /* not supported */
4575 plci->relatedPTYPLCI = NULL;
4579 _FACILITY_R | CONFIRM,
4582 "wws", Info, (word)3, SSparms);
4585 case VSWITCH_REQ_PEND:
4588 if (plci->relatedPTYPLCI)
4590 plci->relatedPTYPLCI->vswitchstate = 0;
4591 plci->relatedPTYPLCI->vsprot = 0;
4592 plci->relatedPTYPLCI->vsprotdialect = 0;
4594 plci->vswitchstate = 0;
4596 plci->vsprotdialect = 0;
4600 if (plci->relatedPTYPLCI &&
4601 plci->vswitchstate == 1 &&
4602 plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4603 plci->vswitchstate = 3;
4607 /* Call Deflection Request pending (SSCT) */
4609 SSparms[1] = S_CALL_DEFLECTION;
4612 Info = 0x300E; /* not supported */
4613 plci->appl->CDEnable = 0;
4615 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4616 plci->number, "wws", Info, (word)3, SSparms);
4619 case RTP_CONNECT_B3_REQ_COMMAND_2:
4622 ncci = get_ncci(plci, ch, 0);
4623 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4625 a->ncci_state[ncci] = OUTG_CON_PENDING;
4629 if (plci->internal_command_queue[0])
4631 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4632 if (plci->internal_command)
4637 next_internal_command(Id, plci);
4642 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4643 if (plci->tel) Id |= EXT_CONTROLLER;
4645 switch (plci->internal_command)
4650 case START_L1_SIG_ASSIGN_PEND:
4651 case REM_L1_SIG_ASSIGN_PEND:
4652 if (global_req == ASSIGN)
4658 dbug(1, dprintf("***L1 Req rem PLCI"));
4659 plci->internal_command = 0;
4660 sig_req(plci, REMOVE, 0);
4665 /* Call Deflection Request pending, just no appl ptr assigned */
4667 SSparms[1] = S_CALL_DEFLECTION;
4670 Info = 0x300E; /* not supported */
4672 for (i = 0; i < max_appl; i++)
4674 if (application[i].CDEnable)
4676 if (!application[i].Id) application[i].CDEnable = 0;
4679 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4680 plci->number, "wws", Info, (word)3, SSparms);
4681 if (Info) application[i].CDEnable = 0;
4685 plci->internal_command = 0;
4688 case PERM_COD_HOOK: /* finished with Hook_Ind */
4692 plci->internal_command = PERM_COD_CONN_PEND;
4693 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4696 case PERM_COD_ASSIGN:
4697 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4698 plci->internal_command = 0;
4699 if (rc != ASSIGN_OK) break;
4700 plci->internal_command = PERM_COD_CALL;
4701 sig_req(plci, CALL_REQ, 0);
4705 case LISTEN_SIG_ASSIGN_PEND:
4706 if (rc == ASSIGN_OK)
4708 plci->internal_command = 0;
4709 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4710 add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4711 sig_req(plci, INDICATE_REQ, 0);
4716 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4724 if (global_req == ASSIGN)
4726 if (rc == ASSIGN_OK)
4728 sig_req(plci, LAW_REQ, 0);
4730 dbug(1, dprintf("Auto-Law assigned"));
4734 dbug(1, dprintf("Auto-Law assign failed"));
4735 a->automatic_law = 3;
4736 plci->internal_command = 0;
4737 a->automatic_lawPLCI = NULL;
4741 else if (req == LAW_REQ && rc == OK)
4743 dbug(1, dprintf("Auto-Law initiated"));
4744 a->automatic_law = 2;
4745 plci->internal_command = 0;
4749 dbug(1, dprintf("Auto-Law not supported"));
4750 a->automatic_law = 3;
4751 plci->internal_command = 0;
4752 sig_req(plci, REMOVE, 0);
4754 a->automatic_lawPLCI = NULL;
4758 plci_remove_check(plci);
4762 static void data_rc(PLCI *plci, byte ch)
4765 DIVA_CAPI_ADAPTER *a;
4772 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4774 ncci = a->ch_ncci[ch];
4775 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4777 ncci_ptr = &(a->ncci[ncci]);
4778 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4779 if (ncci_ptr->data_pending)
4781 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4782 if (!(data->Flags & 4) && a->ncci_state[ncci])
4784 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4785 if (plci->tel) Id |= EXT_CONTROLLER;
4786 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4787 "ww", data->Handle, 0);
4789 (ncci_ptr->data_out)++;
4790 if (ncci_ptr->data_out == MAX_DATA_B3)
4791 ncci_ptr->data_out = 0;
4792 (ncci_ptr->data_pending)--;
4798 static void data_ack(PLCI *plci, byte ch)
4801 DIVA_CAPI_ADAPTER *a;
4806 ncci = a->ch_ncci[ch];
4807 ncci_ptr = &(a->ncci[ncci]);
4808 if (ncci_ptr->data_ack_pending)
4810 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4812 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4813 if (plci->tel) Id |= EXT_CONTROLLER;
4814 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4815 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4817 (ncci_ptr->data_ack_out)++;
4818 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4819 ncci_ptr->data_ack_out = 0;
4820 (ncci_ptr->data_ack_pending)--;
4824 static void sig_ind(PLCI *plci)
4833 DIVA_CAPI_ADAPTER *a;
4834 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4835 #define MAXPARMSIDS 31
4836 byte *parms[MAXPARMSIDS];
4838 byte *multi_fac_parms[MAX_MULTI_IE];
4839 byte *multi_pi_parms[MAX_MULTI_IE];
4840 byte *multi_ssext_parms[MAX_MULTI_IE];
4841 byte *multi_CiPN_parms[MAX_MULTI_IE];
4843 byte *multi_vswitch_parms[MAX_MULTI_IE];
4850 byte *esc_profile = "";
4854 byte chi[] = "\x02\x18\x01";
4855 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4856 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4857 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4858 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4859 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4860 /* (see Info_Mask Bit 4, first IE. then the message type) */
4861 static const word parms_id[] =
4862 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4863 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4864 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4865 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4866 /* 14 FTY repl by ESC_CHI */
4867 /* 18 PI repl by ESC_LAW */
4868 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4869 static const word multi_fac_id[] = {1, FTY};
4870 static const word multi_pi_id[] = {1, PI};
4871 static const word multi_CiPN_id[] = {1, OAD};
4872 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4874 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4878 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4879 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4880 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4881 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4882 byte force_mt_info = false;
4888 Id = ((word)plci->Id << 8) | a->Id;
4889 PUT_WORD(&SS_Ind[4], 0x0000);
4891 if (plci->sig_remove_id)
4893 plci->Sig.RNR = 2; /* discard */
4894 dbug(1, dprintf("SIG discard while remove pending"));
4897 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4898 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4899 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4900 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4905 if (plci->Sig.Ind == HANGUP && plci->channels)
4908 plci->hangup_flow_ctrl_timer++;
4909 /* recover the network layer after timeout */
4910 if (plci->hangup_flow_ctrl_timer == 100)
4912 dbug(1, dprintf("Exceptional disc"));
4914 plci->hangup_flow_ctrl_timer = 0;
4915 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4917 if (a->ncci_plci[ncci] == plci->Id)
4919 cleanup_ncci_data(plci, ncci);
4920 if (plci->channels)plci->channels--;
4922 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4926 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4933 /* do first parse the info with no OAD in, because OAD will be converted */
4934 /* first the multiple facility IE, then mult. progress ind. */
4935 /* then the parameters for the info_ind + conn_ind */
4936 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4937 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4938 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4940 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4942 IndParse(plci, parms_id, parms, 0);
4943 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4944 esc_chi = parms[14];
4945 esc_law = parms[18];
4946 pty_cai = parms[24];
4948 esc_profile = parms[27];
4949 if (esc_cr[0] && plci)
4951 if (plci->cr_enquiry && plci->appl)
4953 plci->cr_enquiry = false;
4956 /* b = total length */
4957 /* b = indication type */
4958 /* b = length of all IEs */
4960 /* S = IE1 length + cont. */
4962 /* S = IE2 length + cont. */
4967 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4968 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);
4971 /* create the additional info structure */
4972 add_i[1] = parms[15]; /* KEY of additional info */
4973 add_i[2] = parms[11]; /* UUI of additional info */
4974 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4976 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4977 /* indication returns by the card if requested by the function */
4978 /* AutomaticLaw() after driver init */
4979 if (a->automatic_law < 4)
4983 dbug(0, dprintf("u-Law selected"));
4987 dbug(0, dprintf("a-Law selected"));
4990 a->automatic_law = 4;
4991 if (plci == a->automatic_lawPLCI) {
4992 plci->internal_command = 0;
4993 sig_req(plci, REMOVE, 0);
4995 a->automatic_lawPLCI = NULL;
5000 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5001 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5002 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5003 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5005 a->profile.Global_Options &= 0x000000ffL;
5006 a->profile.B1_Protocols &= 0x000003ffL;
5007 a->profile.B2_Protocols &= 0x00001fdfL;
5008 a->profile.B3_Protocols &= 0x000000b7L;
5010 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5011 GL_BCHANNEL_OPERATION_SUPPORTED;
5012 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5013 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5014 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5015 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5016 a->man_profile.private_options = 0;
5018 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5020 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5021 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5025 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5026 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5027 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5028 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5032 a->man_profile.private_options |= 1L << PRIVATE_T38;
5035 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5036 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5040 a->man_profile.private_options |= 1L << PRIVATE_V18;
5043 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5044 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5048 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5052 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5056 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5060 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5065 a->profile.Global_Options &= 0x0000007fL;
5066 a->profile.B1_Protocols &= 0x000003dfL;
5067 a->profile.B2_Protocols &= 0x00001adfL;
5068 a->profile.B3_Protocols &= 0x000000b7L;
5069 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5071 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5072 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5074 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5076 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5077 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5078 UnMapController(a->Id), a->profile.Global_Options,
5079 a->profile.B1_Protocols, a->profile.B2_Protocols,
5080 a->profile.B3_Protocols, a->manufacturer_features));
5082 /* codec plci for the handset/hook state support is just an internal id */
5083 if (plci != a->AdvCodecPLCI)
5085 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5086 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5087 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5088 SendInfo(plci, Id, parms, force_mt_info);
5090 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5094 /* switch the codec to the b-channel */
5095 if (esc_chi[0] && plci && !plci->SuppState) {
5096 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5097 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5098 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5099 if (plci->tel == ADV_VOICE && plci->appl) {
5100 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5104 if (plci->appl) plci->appl->Number++;
5106 switch (plci->Sig.Ind) {
5107 /* Response to Get_Supported_Services request */
5109 dbug(1, dprintf("S_Supported"));
5110 if (!plci->appl) break;
5111 if (pty_cai[0] == 4)
5113 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5117 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5119 PUT_WORD(&CF_Ind[1], 0);
5120 PUT_WORD(&CF_Ind[4], 0);
5121 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5125 /* Supplementary Service rejected */
5127 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5128 if (!pty_cai[0]) break;
5133 case THREE_PTY_BEGIN:
5134 if (!plci->relatedPTYPLCI) break;
5135 tplci = plci->relatedPTYPLCI;
5136 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5137 if (tplci->tel) rId |= EXT_CONTROLLER;
5138 if (pty_cai[5] == ECT_EXECUTE)
5140 PUT_WORD(&SS_Ind[1], S_ECT);
5142 plci->vswitchstate = 0;
5143 plci->relatedPTYPLCI->vswitchstate = 0;
5148 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5150 if (pty_cai[2] != 0xff)
5152 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5156 PUT_WORD(&SS_Ind[4], 0x300E);
5158 plci->relatedPTYPLCI = NULL;
5160 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163 case CALL_DEFLECTION:
5164 if (pty_cai[2] != 0xff)
5166 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5170 PUT_WORD(&SS_Ind[4], 0x300E);
5172 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5173 for (i = 0; i < max_appl; i++)
5175 if (application[i].CDEnable)
5177 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5178 application[i].CDEnable = false;
5183 case DEACTIVATION_DIVERSION:
5184 case ACTIVATION_DIVERSION:
5185 case DIVERSION_INTERROGATE_CFU:
5186 case DIVERSION_INTERROGATE_CFB:
5187 case DIVERSION_INTERROGATE_CFNR:
5188 case DIVERSION_INTERROGATE_NUM:
5190 case CCBS_DEACTIVATE:
5191 case CCBS_INTERROGATE:
5192 if (!plci->appl) break;
5193 if (pty_cai[2] != 0xff)
5195 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5199 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5203 case DEACTIVATION_DIVERSION:
5204 dbug(1, dprintf("Deact_Div"));
5205 Interr_Err_Ind[0] = 0x9;
5206 Interr_Err_Ind[3] = 0x6;
5207 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5209 case ACTIVATION_DIVERSION:
5210 dbug(1, dprintf("Act_Div"));
5211 Interr_Err_Ind[0] = 0x9;
5212 Interr_Err_Ind[3] = 0x6;
5213 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5215 case DIVERSION_INTERROGATE_CFU:
5216 case DIVERSION_INTERROGATE_CFB:
5217 case DIVERSION_INTERROGATE_CFNR:
5218 dbug(1, dprintf("Interr_Div"));
5219 Interr_Err_Ind[0] = 0xa;
5220 Interr_Err_Ind[3] = 0x7;
5221 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5223 case DIVERSION_INTERROGATE_NUM:
5224 dbug(1, dprintf("Interr_Num"));
5225 Interr_Err_Ind[0] = 0xa;
5226 Interr_Err_Ind[3] = 0x7;
5227 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230 dbug(1, dprintf("CCBS Request"));
5231 Interr_Err_Ind[0] = 0xd;
5232 Interr_Err_Ind[3] = 0xa;
5233 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5235 case CCBS_DEACTIVATE:
5236 dbug(1, dprintf("CCBS Deactivate"));
5237 Interr_Err_Ind[0] = 0x9;
5238 Interr_Err_Ind[3] = 0x6;
5239 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5241 case CCBS_INTERROGATE:
5242 dbug(1, dprintf("CCBS Interrogate"));
5243 Interr_Err_Ind[0] = 0xb;
5244 Interr_Err_Ind[3] = 0x8;
5245 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5249 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252 case ACTIVATION_MWI:
5253 case DEACTIVATION_MWI:
5254 if (pty_cai[5] == ACTIVATION_MWI)
5256 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5258 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5260 if (pty_cai[2] != 0xff)
5262 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5266 PUT_WORD(&SS_Ind[4], 0x300E);
5269 if (plci->cr_enquiry)
5271 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5276 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279 case CONF_ADD: /* ERROR */
5289 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5295 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5296 plci->ptyState = CONNECTED;
5301 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5302 plci->ptyState = CONNECTED;
5307 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5308 plci->ptyState = CONNECTED;
5311 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5312 plci->relatedPTYPLCI = NULL;
5313 tplci = plci->relatedPTYPLCI;
5314 if (tplci) tplci->ptyState = CONNECTED;
5315 plci->ptyState = CONNECTED;
5319 if (pty_cai[2] != 0xff)
5321 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5325 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5326 within the required time */
5329 PUT_DWORD(&CONF_Ind[6], 0x0);
5330 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5335 /* Supplementary Service indicates success */
5337 dbug(1, dprintf("Service_Ind"));
5338 PUT_WORD(&CF_Ind[4], 0);
5342 case THREE_PTY_BEGIN:
5344 if (!plci->relatedPTYPLCI) break;
5345 tplci = plci->relatedPTYPLCI;
5346 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5347 if (tplci->tel) rId |= EXT_CONTROLLER;
5348 if (pty_cai[5] == ECT_EXECUTE)
5350 PUT_WORD(&SS_Ind[1], S_ECT);
5352 if (plci->vswitchstate != 3)
5355 plci->ptyState = IDLE;
5356 plci->relatedPTYPLCI = NULL;
5361 dbug(1, dprintf("ECT OK"));
5362 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5369 switch (plci->ptyState)
5372 plci->ptyState = CONNECTED;
5373 dbug(1, dprintf("3PTY ON"));
5377 plci->ptyState = IDLE;
5378 plci->relatedPTYPLCI = NULL;
5380 dbug(1, dprintf("3PTY OFF"));
5383 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5384 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5388 case CALL_DEFLECTION:
5389 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5390 for (i = 0; i < max_appl; i++)
5392 if (application[i].CDEnable)
5394 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5395 application[i].CDEnable = false;
5400 case DEACTIVATION_DIVERSION:
5401 case ACTIVATION_DIVERSION:
5402 if (!plci->appl) break;
5403 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5404 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5405 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5409 case DIVERSION_INTERROGATE_CFU:
5410 case DIVERSION_INTERROGATE_CFB:
5411 case DIVERSION_INTERROGATE_CFNR:
5412 case DIVERSION_INTERROGATE_NUM:
5414 case CCBS_DEACTIVATE:
5415 case CCBS_INTERROGATE:
5416 if (!plci->appl) break;
5419 case DIVERSION_INTERROGATE_CFU:
5420 case DIVERSION_INTERROGATE_CFB:
5421 case DIVERSION_INTERROGATE_CFNR:
5422 dbug(1, dprintf("Interr_Div"));
5423 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5424 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5426 case DIVERSION_INTERROGATE_NUM:
5427 dbug(1, dprintf("Interr_Num"));
5428 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5429 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432 dbug(1, dprintf("CCBS Request"));
5433 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5434 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5436 case CCBS_DEACTIVATE:
5437 dbug(1, dprintf("CCBS Deactivate"));
5438 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5439 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5441 case CCBS_INTERROGATE:
5442 dbug(1, dprintf("CCBS Interrogate"));
5443 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5444 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447 PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5448 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5449 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5453 case ACTIVATION_MWI:
5454 case DEACTIVATION_MWI:
5455 if (pty_cai[5] == ACTIVATION_MWI)
5457 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5459 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5460 if (plci->cr_enquiry)
5462 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5467 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470 case MWI_INDICATION:
5471 if (pty_cai[0] >= 0x12)
5473 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5474 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5475 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5476 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5478 if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5480 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5484 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5489 for (i = 0; i < max_appl; i++)
5491 if (a->Notification_Mask[i]&SMASK_MWI)
5493 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5501 facility[2] = 0; /* returncode */
5503 else facility[2] = 0xff;
5508 facility[2] = 0xff; /* returncode */
5511 facility[1] = MWI_RESPONSE; /* Function */
5512 add_p(plci, CAI, facility);
5513 add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5514 sig_req(plci, S_SERVICE, 0);
5517 next_internal_command(Id, plci);
5519 case CONF_ADD: /* OK */
5524 case CONF_PARTYDISC:
5530 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5531 if (pty_cai[0] == 6)
5534 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5538 PUT_DWORD(&CONF_Ind[6], 0x0);
5542 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5547 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5552 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5557 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5559 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5560 tplci = plci->relatedPTYPLCI;
5561 if (tplci) tplci->ptyState = CONNECTED;
5563 case CONF_PARTYDISC:
5566 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5568 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571 plci->ptyState = CONNECTED;
5572 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5574 case CCBS_INFO_RETAIN:
5575 case CCBS_ERASECALLLINKAGEID:
5576 case CCBS_STOP_ALERTING:
5581 case CCBS_INFO_RETAIN:
5582 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5584 case CCBS_STOP_ALERTING:
5585 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5587 case CCBS_ERASECALLLINKAGEID:
5588 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5596 PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5598 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5600 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5604 for (i = 0; i < max_appl; i++)
5605 if (a->Notification_Mask[i] & SMASK_CCBS)
5606 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5615 i = _L3_CAUSE | cau[2];
5616 if (cau[2] == 0) i = 0x3603;
5622 PUT_WORD(&SS_Ind[1], S_HOLD);
5623 PUT_WORD(&SS_Ind[4], i);
5624 if (plci->SuppState == HOLD_REQUEST)
5626 plci->SuppState = IDLE;
5627 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5632 if (plci->SuppState == HOLD_REQUEST)
5634 plci->SuppState = CALL_HELD;
5635 CodecIdCheck(a, plci);
5636 start_internal_command(Id, plci, hold_save_command);
5640 case CALL_RETRIEVE_REJ:
5644 i = _L3_CAUSE | cau[2];
5645 if (cau[2] == 0) i = 0x3603;
5651 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5652 PUT_WORD(&SS_Ind[4], i);
5653 if (plci->SuppState == RETRIEVE_REQUEST)
5655 plci->SuppState = CALL_HELD;
5656 CodecIdCheck(a, plci);
5657 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5661 case CALL_RETRIEVE_ACK:
5662 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5663 if (plci->SuppState == RETRIEVE_REQUEST)
5665 plci->SuppState = IDLE;
5666 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5667 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5671 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5672 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5673 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5675 dbug(1, dprintf("Get B-ch"));
5676 start_internal_command(Id, plci, retrieve_restore_command);
5679 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682 start_internal_command(Id, plci, retrieve_restore_command);
5687 if (plci->State != LISTENING) {
5688 sig_req(plci, HANGUP, 0);
5692 cip = find_cip(a, parms[4], parms[6]);
5693 cip_mask = 1L << cip;
5694 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5695 clear_c_ind_mask(plci);
5696 if (!remove_started && !a->adapter_disabled)
5698 set_c_ind_mask_bit(plci, MAX_APPL);
5699 group_optimization(a, plci);
5700 for (i = 0; i < max_appl; i++) {
5701 if (application[i].Id
5702 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5703 && CPN_filter_ok(parms[0], a, i)
5704 && test_group_ind_mask_bit(plci, i)) {
5705 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5706 set_c_ind_mask_bit(plci, i);
5707 dump_c_ind_mask(plci);
5708 plci->State = INC_CON_PENDING;
5709 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5710 CALL_DIR_IN | CALL_DIR_ANSWER;
5712 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5713 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5715 /* if a listen on the ext controller is done, check if hook states */
5716 /* are supported or if just a on board codec must be activated */
5717 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5718 if (a->profile.Global_Options & HANDSET)
5719 plci->tel = ADV_VOICE;
5720 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5722 if (plci->tel) Id |= EXT_CONTROLLER;
5723 a->codec_listen[i] = plci;
5726 sendf(&application[i], _CONNECT_I, Id, 0,
5727 "wSSSSSSSbSSSSS", cip, /* CIP */
5728 parms[0], /* CalledPartyNumber */
5729 multi_CiPN_parms[0], /* CallingPartyNumber */
5730 parms[2], /* CalledPartySubad */
5731 parms[3], /* CallingPartySubad */
5732 parms[4], /* BearerCapability */
5733 parms[5], /* LowLC */
5734 parms[6], /* HighLC */
5735 ai_len, /* nested struct add_i */
5736 add_i[0], /* B channel info */
5737 add_i[1], /* keypad facility */
5738 add_i[2], /* user user data */
5739 add_i[3], /* nested facility */
5740 multi_CiPN_parms[1] /* second CiPN(SCR) */
5742 SendSSExtInd(&application[i],
5746 SendSetupInfo(&application[i],
5750 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753 clear_c_ind_mask_bit(plci, MAX_APPL);
5754 dump_c_ind_mask(plci);
5756 if (c_ind_mask_empty(plci)) {
5757 sig_req(plci, HANGUP, 0);
5761 plci->notifiedcall = 0;
5766 case CALL_PEND_NOTIFY:
5767 plci->notifiedcall = 1;
5773 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5775 if (plci->internal_command == PERM_COD_CONN_PEND)
5777 if (plci->State == ADVANCED_VOICE_NOSIG)
5779 dbug(1, dprintf("***Codec OK"));
5780 if (a->AdvSignalPLCI)
5782 tplci = a->AdvSignalPLCI;
5783 if (tplci->spoofed_msg)
5785 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5787 tplci->internal_command = 0;
5788 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5789 switch (tplci->spoofed_msg)
5792 tplci->command = _CONNECT_I | RESPONSE;
5793 api_load_msg(&tplci->saved_msg, saved_parms);
5794 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5795 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5797 /* early B3 connect (CIP mask bit 9) no release after a disc */
5798 add_p(tplci, LLI, "\x01\x01");
5800 add_s(tplci, CONN_NR, &saved_parms[2]);
5801 add_s(tplci, LLC, &saved_parms[4]);
5802 add_ai(tplci, &saved_parms[5]);
5803 tplci->State = INC_CON_ACCEPT;
5804 sig_req(tplci, CALL_RES, 0);
5808 case AWAITING_SELECT_B:
5809 dbug(1, dprintf("Select_B continue"));
5810 start_internal_command(x_Id, tplci, select_b_command);
5813 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816 dbug(1, dprintf("No SigID!"));
5817 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5821 tplci->command = _MANUFACTURER_R;
5822 api_load_msg(&tplci->saved_msg, saved_parms);
5823 dir = saved_parms[2].info[0];
5825 sig_req(tplci, CALL_REQ, 0);
5828 sig_req(tplci, LISTEN_REQ, 0);
5831 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834 case (CALL_REQ | AWAITING_MANUF_CON):
5835 sig_req(tplci, CALL_REQ, 0);
5842 dbug(1, dprintf("No SigID!"));
5843 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5847 tplci->command = _CONNECT_R;
5848 api_load_msg(&tplci->saved_msg, saved_parms);
5849 add_s(tplci, CPN, &saved_parms[1]);
5850 add_s(tplci, DSA, &saved_parms[3]);
5851 add_ai(tplci, &saved_parms[9]);
5852 sig_req(tplci, CALL_REQ, 0);
5857 tplci->command = C_RETRIEVE_REQ;
5858 sig_req(tplci, CALL_RETRIEVE, 0);
5862 tplci->spoofed_msg = 0;
5863 if (tplci->internal_command == 0)
5864 next_internal_command(x_Id, tplci);
5867 next_internal_command(Id, plci);
5870 dbug(1, dprintf("***Codec Hook Init Req"));
5871 plci->internal_command = PERM_COD_HOOK;
5872 add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5873 sig_req(plci, TEL_CTRL, 0);
5877 else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5878 && plci->State != INC_ACT_PENDING)
5880 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5881 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5883 chi[2] = plci->b_channel;
5884 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5886 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5887 plci->State = INC_ACT_PENDING;
5892 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5893 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5894 switch (ie[1] & 0x91) {
5895 case 0x80: /* hook off */
5897 if (plci->internal_command == PERM_COD_HOOK)
5899 dbug(1, dprintf("init:hook_off"));
5900 plci->hook_state = ie[1];
5901 next_internal_command(Id, plci);
5904 else /* ignore doubled hook indications */
5906 if (((plci->hook_state) & 0xf0) == 0x80)
5908 dbug(1, dprintf("ignore hook"));
5911 plci->hook_state = ie[1]&0x91;
5913 /* check for incoming call pending */
5914 /* and signal '+'.Appl must decide */
5915 /* with connect_res if call must */
5916 /* accepted or not */
5917 for (i = 0, tplci = NULL; i < max_appl; i++) {
5918 if (a->codec_listen[i]
5919 && (a->codec_listen[i]->State == INC_CON_PENDING
5920 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5921 tplci = a->codec_listen[i];
5922 tplci->appl = &application[i];
5925 /* no incoming call, do outgoing call */
5926 /* and signal '+' if outg. setup */
5927 if (!a->AdvSignalPLCI && !tplci) {
5928 if ((i = get_plci(a))) {
5929 a->AdvSignalPLCI = &a->plci[i - 1];
5930 tplci = a->AdvSignalPLCI;
5931 tplci->tel = ADV_VOICE;
5932 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5933 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5934 /* early B3 connect (CIP mask bit 9) no release after a disc */
5935 add_p(tplci, LLI, "\x01\x01");
5937 add_p(tplci, CAI, voice_cai);
5938 add_p(tplci, OAD, a->TelOAD);
5939 add_p(tplci, OSA, a->TelOSA);
5940 add_p(tplci, SHIFT | 6, NULL);
5941 add_p(tplci, SIN, "\x02\x01\x00");
5942 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5943 sig_req(tplci, ASSIGN, DSIG_ID);
5944 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5945 a->AdvSignalPLCI->command = 0;
5946 tplci->appl = a->AdvSignalAppl;
5947 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5954 Id = ((word)tplci->Id << 8) | a->Id;
5955 Id |= EXT_CONTROLLER;
5960 "ws", (word)0, "\x01+");
5963 case 0x90: /* hook on */
5965 if (plci->internal_command == PERM_COD_HOOK)
5967 dbug(1, dprintf("init:hook_on"));
5968 plci->hook_state = ie[1] & 0x91;
5969 next_internal_command(Id, plci);
5972 else /* ignore doubled hook indications */
5974 if (((plci->hook_state) & 0xf0) == 0x90) break;
5975 plci->hook_state = ie[1] & 0x91;
5977 /* hangup the adv. voice call and signal '-' to the appl */
5978 if (a->AdvSignalPLCI) {
5979 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5980 if (plci->tel) Id |= EXT_CONTROLLER;
5981 sendf(a->AdvSignalAppl,
5985 "ws", (word)0, "\x01-");
5986 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5987 a->AdvSignalPLCI->command = 0;
5988 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5989 send_req(a->AdvSignalPLCI);
5997 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
5998 PUT_WORD(&resume_cau[4], GOOD);
5999 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6003 clear_c_ind_mask(plci);
6005 if (plci->NL.Id && !plci->nl_remove_id) {
6007 nl_req_ncci(plci, REMOVE, 0);
6009 if (!plci->sig_remove_id) {
6010 plci->internal_command = 0;
6011 sig_req(plci, REMOVE, 0);
6014 if (!plci->channels) {
6015 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6016 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6024 plci->hangup_flow_ctrl_timer = 0;
6025 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028 i = _L3_CAUSE | cau[2];
6029 if (cau[2] == 0) i = 0;
6030 else if (cau[2] == 8) i = _L1_ERROR;
6031 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6032 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6038 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6040 for (i = 0; i < max_appl; i++)
6042 if (test_c_ind_mask_bit(plci, i))
6043 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6048 clear_c_ind_mask(plci);
6052 if (plci->State == LISTENING)
6054 plci->notifiedcall = 0;
6057 plci->State = INC_DIS_PENDING;
6058 if (c_ind_mask_empty(plci))
6061 if (plci->NL.Id && !plci->nl_remove_id)
6064 nl_req_ncci(plci, REMOVE, 0);
6066 if (!plci->sig_remove_id)
6068 plci->internal_command = 0;
6069 sig_req(plci, REMOVE, 0);
6076 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6077 /* result in a second HANGUP! Don't generate another */
6079 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6081 if (plci->State == RESUMING)
6083 PUT_WORD(&resume_cau[4], i);
6084 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6086 plci->State = INC_DIS_PENDING;
6087 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6093 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6097 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100 if (plci->relatedPTYPLCI &&
6101 plci->vswitchstate == 3 &&
6102 plci->relatedPTYPLCI->vswitchstate == 3 &&
6103 parms[MAXPARMSIDS - 1][0])
6105 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6106 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6107 send_req(plci->relatedPTYPLCI);
6109 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6116 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6124 dbug(1, dprintf("SetupInfo"));
6126 for (i = 0; i < MAXPARMSIDS; i++) {
6133 dbug(1, dprintf("CPN "));
6134 Info_Number = 0x0070;
6136 Info_Sent_Flag = true;
6138 case 8: /* display */
6139 dbug(1, dprintf("display(%d)", i));
6140 Info_Number = 0x0028;
6142 Info_Sent_Flag = true;
6144 case 16: /* Channel Id */
6145 dbug(1, dprintf("CHI"));
6146 Info_Number = 0x0018;
6148 Info_Sent_Flag = true;
6149 mixer_set_bchannel_id(plci, Info_Element);
6151 case 19: /* Redirected Number */
6152 dbug(1, dprintf("RDN"));
6153 Info_Number = 0x0074;
6155 Info_Sent_Flag = true;
6157 case 20: /* Redirected Number extended */
6158 dbug(1, dprintf("RDX"));
6159 Info_Number = 0x0073;
6161 Info_Sent_Flag = true;
6163 case 22: /* Redirecing Number */
6164 dbug(1, dprintf("RIN"));
6165 Info_Number = 0x0076;
6167 Info_Sent_Flag = true;
6175 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6176 Info_Number = 0x8000 | 5;
6181 if (Info_Sent_Flag && Info_Number) {
6182 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6183 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6190 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6199 static byte charges[5] = {4, 0, 0, 0, 0};
6200 static byte cause[] = {0x02, 0x80, 0x00};
6203 dbug(1, dprintf("InfoParse "));
6208 && plci->Sig.Ind != NCR_FACILITY
6211 dbug(1, dprintf("NoParse "));
6215 for (i = 0; i < MAXPARMSIDS; i++) {
6222 dbug(1, dprintf("CPN "));
6223 Info_Number = 0x0070;
6226 case 7: /* ESC_CAU */
6227 dbug(1, dprintf("cau(0x%x)", ie[2]));
6228 Info_Number = 0x0008;
6231 Info_Element = NULL;
6233 case 8: /* display */
6234 dbug(1, dprintf("display(%d)", i));
6235 Info_Number = 0x0028;
6238 case 9: /* Date display */
6239 dbug(1, dprintf("date(%d)", i));
6240 Info_Number = 0x0029;
6243 case 10: /* charges */
6244 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6245 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6246 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6247 Info_Number = 0x4000;
6249 Info_Element = charges;
6251 case 11: /* user user info */
6252 dbug(1, dprintf("uui"));
6253 Info_Number = 0x007E;
6256 case 12: /* congestion receiver ready */
6257 dbug(1, dprintf("clRDY"));
6258 Info_Number = 0x00B0;
6262 case 13: /* congestion receiver not ready */
6263 dbug(1, dprintf("clNRDY"));
6264 Info_Number = 0x00BF;
6268 case 15: /* Keypad Facility */
6269 dbug(1, dprintf("KEY"));
6270 Info_Number = 0x002C;
6273 case 16: /* Channel Id */
6274 dbug(1, dprintf("CHI"));
6275 Info_Number = 0x0018;
6277 mixer_set_bchannel_id(plci, Info_Element);
6279 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6280 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6281 if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6282 Info_Number = 0x0008;
6284 if (cause[2] != ie[2]) Info_Element = cause;
6286 case 19: /* Redirected Number */
6287 dbug(1, dprintf("RDN"));
6288 Info_Number = 0x0074;
6291 case 22: /* Redirecing Number */
6292 dbug(1, dprintf("RIN"));
6293 Info_Number = 0x0076;
6296 case 23: /* Notification Indicator */
6297 dbug(1, dprintf("NI"));
6298 Info_Number = (word)NI;
6301 case 26: /* Call State */
6302 dbug(1, dprintf("CST"));
6303 Info_Number = (word)CST;
6304 Info_Mask = 0x01; /* do with cause i.e. for now */
6306 case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6307 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6308 Info_Number = 0x8000 | ie[3];
6309 if (iesent) Info_Mask = 0xffff;
6310 else Info_Mask = 0x10;
6321 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6323 for (j = 0; j < max_appl; j++)
6325 appl = &application[j];
6328 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6330 dbug(1, dprintf("NCR_Ind"));
6332 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6336 else if (!plci->appl)
6337 { /* overlap receiving broadcast */
6338 if (Info_Number == CPN
6339 || Info_Number == KEY
6340 || Info_Number == NI
6341 || Info_Number == DSP
6342 || Info_Number == UUI)
6344 for (j = 0; j < max_appl; j++)
6346 if (test_c_ind_mask_bit(plci, j))
6348 dbug(1, dprintf("Ovl_Ind"));
6350 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6354 } /* all other signalling states */
6355 else if (Info_Number
6356 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6358 dbug(1, dprintf("Std_Ind"));
6360 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6366 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6367 dword info_mask, byte setupParse)
6381 && plci->Sig.Ind != NCR_FACILITY
6385 dbug(1, dprintf("NoM-IEParse "));
6388 dbug(1, dprintf("M-IEParse "));
6390 for (i = 0; i < MAX_MULTI_IE; i++)
6397 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6398 Info_Number = (word)ie_type;
6399 Info_Mask = (word)info_mask;
6402 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6404 for (j = 0; j < max_appl; j++)
6406 appl = &application[j];
6409 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6412 dbug(1, dprintf("Mlt_NCR_Ind"));
6413 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6417 else if (!plci->appl && Info_Number)
6418 { /* overlap receiving broadcast */
6419 for (j = 0; j < max_appl; j++)
6421 if (test_c_ind_mask_bit(plci, j))
6424 dbug(1, dprintf("Mlt_Ovl_Ind"));
6425 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428 } /* all other signalling states */
6429 else if (Info_Number
6430 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6433 dbug(1, dprintf("Mlt_Std_Ind"));
6434 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6440 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6443 /* Format of multi_ssext_parms[i][]:
6446 2 byte SSEXT_REQ/SSEXT_IND
6454 && plci->Sig.Ind != NCR_FACILITY
6456 for (i = 0; i < MAX_MULTI_IE; i++)
6458 if (parms[i][0] < 6) continue;
6459 if (parms[i][2] == SSEXT_REQ) continue;
6463 parms[i][0] = 0; /* kill it */
6464 sendf(appl, _MANUFACTURER_I,
6472 else if (plci->appl)
6474 parms[i][0] = 0; /* kill it */
6475 sendf(plci->appl, _MANUFACTURER_I,
6486 static void nl_ind(PLCI *plci)
6491 DIVA_CAPI_ADAPTER *a;
6497 byte len, ncci_state;
6500 word fax_feature_bits;
6501 byte fax_send_edata_ack;
6502 static byte v120_header_buffer[2 + 3];
6503 static word fax_info[] = {
6504 0, /* T30_SUCCESS */
6505 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6510 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6511 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6512 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6513 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6514 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6515 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6516 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6517 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6518 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6523 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6524 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6525 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6537 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6538 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6539 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6540 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6541 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6542 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6543 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6544 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6545 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6546 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6547 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6548 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6549 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6550 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6553 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556 static word rtp_info[] = {
6557 GOOD, /* RTP_SUCCESS */
6558 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6561 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6563 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6564 0x00000000, 0x00000000, 0x00000000, 0x00000000
6567 ch = plci->NL.IndCh;
6569 ncci = a->ch_ncci[ch];
6570 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6571 if (plci->tel) Id |= EXT_CONTROLLER;
6572 APPLptr = plci->appl;
6573 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",
6574 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6576 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6578 if (plci->nl_remove_id)
6580 plci->NL.RNR = 2; /* discard */
6581 dbug(1, dprintf("NL discard while remove pending"));
6584 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6586 if (plci->State == INC_DIS_PENDING
6587 || plci->State == OUTG_DIS_PENDING
6588 || plci->State == IDLE)
6590 plci->NL.RNR = 2; /* discard */
6591 dbug(1, dprintf("discard n_connect"));
6594 if (plci->State < INC_ACT_PENDING)
6596 plci->NL.RNR = 1; /* flow control */
6597 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6602 if (!APPLptr) /* no application or invalid data */
6603 { /* while reloading the DSP */
6604 dbug(1, dprintf("discard1"));
6609 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6610 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6611 || (plci->B2_prot == 7)
6612 || (plci->B3_prot == 7)))
6614 plci->ncpi_buffer[0] = 0;
6616 ncpi_state = plci->ncpi_state;
6617 if (plci->NL.complete == 1)
6619 byte *data = &plci->NL.RBuffer->P[0];
6621 if ((plci->NL.RBuffer->length >= 12)
6622 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6623 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6625 word conn_opt, ncpi_opt = 0x00;
6626 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6628 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6629 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6630 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6631 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6633 data++; /* indication code */
6634 data += 2; /* timestamp */
6635 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6636 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6637 data++; /* connected norm */
6638 conn_opt = GET_WORD(data);
6639 data += 2; /* connected options */
6641 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6643 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6645 ncpi_opt |= MDM_NCPI_ECM_V42;
6647 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6649 ncpi_opt |= MDM_NCPI_ECM_MNP;
6653 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6655 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6657 ncpi_opt |= MDM_NCPI_COMPRESSED;
6659 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6660 plci->ncpi_buffer[0] = 4;
6662 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6665 if (plci->B3_prot == 7)
6667 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6668 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6669 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6671 a->ncci_state[ncci] = INC_ACT_PENDING;
6672 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6673 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6677 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6678 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6679 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6680 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6688 if (plci->NL.complete == 2)
6690 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6691 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6693 switch (plci->RData[0].P[0])
6696 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6697 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6698 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6700 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6701 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6702 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6704 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6705 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6707 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6708 dtmf_confirmation(Id, plci);
6712 case UDATA_INDICATION_MIXER_TAP_DATA:
6713 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6714 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6717 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6718 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6723 case UDATA_INDICATION_MIXER_COEFS_SET:
6724 mixer_indication_coefs_set(Id, plci);
6726 case UDATA_INDICATION_XCONNECT_FROM:
6727 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6729 case UDATA_INDICATION_XCONNECT_TO:
6730 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6734 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6735 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6746 if ((plci->RData[0].PLength != 0)
6747 && ((plci->B2_prot == B2_V120_ASYNC)
6748 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6749 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752 sendf(plci->appl, _DATA_B3_I, Id, 0,
6755 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6763 sendf(plci->appl, _DATA_B3_I, Id, 0,
6766 plci->RData[0].PLength,
6775 fax_feature_bits = 0;
6776 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6777 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6778 (plci->NL.Ind & 0x0f) == N_DISC ||
6779 (plci->NL.Ind & 0x0f) == N_EDATA ||
6780 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6783 plci->ncpi_buffer[0] = 0;
6784 switch (plci->B3_prot) {
6787 break; /* no network control protocol info - jfr */
6790 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6791 plci->ncpi_buffer[0] = (byte)(i + 3);
6792 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6793 plci->ncpi_buffer[2] = 0;
6794 plci->ncpi_buffer[3] = 0;
6796 case 4: /*T.30 - FAX*/
6797 case 5: /*T.30 - FAX*/
6798 if (plci->NL.RLength >= sizeof(T30_INFO))
6800 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6802 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6803 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6804 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6805 if (plci->B3_prot == 5)
6807 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6808 i |= 0x8000; /* This is not an ECM connection */
6809 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6810 i |= 0x4000; /* This is a connection with MMR compression */
6811 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6812 i |= 0x2000; /* This is a connection with MR compression */
6813 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6814 i |= 0x0004; /* More documents */
6815 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6816 i |= 0x0002; /* Fax-polling indication */
6818 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6819 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6820 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6821 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6822 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6823 plci->ncpi_buffer[len] = 0;
6824 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6826 plci->ncpi_buffer[len] = 20;
6827 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6828 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6830 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6832 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6833 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6835 info = _FAX_PROTOCOL_ERROR;
6838 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6839 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6841 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6842 while (i < plci->NL.RBuffer->length)
6843 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846 plci->ncpi_buffer[0] = len;
6847 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6848 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6850 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6851 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6852 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6853 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6854 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6855 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6856 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6857 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6859 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6861 if (((plci->NL.Ind & 0x0f) == N_DISC)
6862 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6863 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6864 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6866 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6872 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6874 if (plci->NL.RLength != 0)
6876 info = rtp_info[plci->NL.RBuffer->P[0]];
6877 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6878 for (i = 1; i < plci->NL.RLength; i++)
6879 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6887 switch (plci->NL.Ind & 0x0f) {
6889 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6891 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6892 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6893 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6895 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6896 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6897 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6898 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6899 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6900 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6902 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6903 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6904 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6905 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6906 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6907 fax_send_edata_ack = false;
6910 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6912 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6915 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6916 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6917 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6920 a->ncci_state[ncci] = INC_ACT_PENDING;
6921 if (plci->B3_prot == 4)
6922 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6924 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6925 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6929 case EDATA_T30_TRAIN_OK:
6930 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6931 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6932 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6934 if (plci->B3_prot == 4)
6935 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6937 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6938 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6942 case EDATA_T30_EOP_CAPI:
6943 if (a->ncci_state[ncci] == CONNECTED)
6945 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6946 a->ncci_state[ncci] = INC_DIS_PENDING;
6947 plci->ncpi_state = 0;
6948 fax_send_edata_ack = false;
6955 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6957 case EDATA_T30_TRAIN_OK:
6958 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6959 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6960 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6962 if (plci->B3_prot == 4)
6963 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6965 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6966 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6971 if (fax_send_edata_ack)
6973 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6974 plci->fax_edata_ack_length = 1;
6975 start_internal_command(Id, plci, fax_edata_ack_command);
6980 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6984 if (!a->ch_ncci[ch])
6986 ncci = get_ncci(plci, ch, 0);
6987 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6989 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6990 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6992 msg = _CONNECT_B3_I;
6993 if (a->ncci_state[ncci] == IDLE)
6995 else if (plci->B3_prot == 1)
6996 msg = _CONNECT_B3_T90_ACTIVE_I;
6998 a->ncci_state[ncci] = INC_CON_PENDING;
6999 if (plci->B3_prot == 4)
7000 sendf(plci->appl, msg, Id, 0, "s", "");
7002 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7005 dbug(1, dprintf("N_connect_Ack"));
7006 if (plci->internal_command_queue[0]
7007 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7008 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7009 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7011 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7012 if (!plci->internal_command)
7013 next_internal_command(Id, plci);
7016 msg = _CONNECT_B3_ACTIVE_I;
7017 if (plci->B3_prot == 1)
7019 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7020 msg = _CONNECT_B3_T90_ACTIVE_I;
7021 a->ncci_state[ncci] = INC_ACT_PENDING;
7022 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7024 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7026 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7027 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7028 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7030 a->ncci_state[ncci] = INC_ACT_PENDING;
7031 if (plci->B3_prot == 4)
7032 sendf(plci->appl, msg, Id, 0, "s", "");
7034 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7035 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7040 a->ncci_state[ncci] = INC_ACT_PENDING;
7041 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7043 if (plci->adjust_b_restore)
7045 plci->adjust_b_restore = false;
7046 start_internal_command(Id, plci, adjust_b_restore);
7051 if (plci->internal_command_queue[0]
7052 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7053 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7054 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7056 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7057 if (!plci->internal_command)
7058 next_internal_command(Id, plci);
7060 ncci_state = a->ncci_state[ncci];
7061 ncci_remove(plci, ncci, false);
7063 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7064 /* channel, so we cannot store the state in ncci_state! The */
7065 /* information which channel we received a N_DISC is thus */
7066 /* stored in the inc_dis_ncci_table buffer. */
7067 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7068 plci->inc_dis_ncci_table[i] = (byte) ncci;
7070 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7072 && (plci->B1_resource == 16)
7073 && (plci->State <= CONNECTED))
7076 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7077 PUT_WORD(&plci->ncpi_buffer[1], i);
7078 PUT_WORD(&plci->ncpi_buffer[3], 0);
7079 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7080 PUT_WORD(&plci->ncpi_buffer[5], i);
7081 PUT_WORD(&plci->ncpi_buffer[7], 0);
7082 plci->ncpi_buffer[len] = 0;
7083 plci->ncpi_buffer[0] = len;
7084 if (plci->B3_prot == 4)
7085 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7089 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7090 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7092 plci->ncpi_buffer[++len] = 0;
7093 plci->ncpi_buffer[++len] = 0;
7094 plci->ncpi_buffer[++len] = 0;
7095 plci->ncpi_buffer[0] = len;
7098 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7100 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7101 plci->ncpi_state = 0;
7102 sig_req(plci, HANGUP, 0);
7104 plci->State = OUTG_DIS_PENDING;
7107 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7108 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7109 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7111 if (ncci_state == IDLE)
7115 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7116 if (plci->State == SUSPENDING) {
7121 "ws", (word)3, "\x03\x04\x00\x00");
7122 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7129 else if (plci->channels)
7131 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7132 plci->ncpi_state = 0;
7133 if ((ncci_state == OUTG_REJ_PENDING)
7134 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7136 sig_req(plci, HANGUP, 0);
7138 plci->State = OUTG_DIS_PENDING;
7143 a->ncci_state[ncci] = INC_RES_PENDING;
7144 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7147 a->ncci_state[ncci] = CONNECTED;
7148 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7152 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7154 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7155 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7156 plci->NL.R = plci->RData;
7162 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7163 || (a->ncci_state[ncci] == IDLE)
7164 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7169 if ((a->ncci_state[ncci] != CONNECTED)
7170 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7171 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7173 dbug(1, dprintf("flow control"));
7174 plci->NL.RNR = 1; /* flow control */
7175 channel_x_off(plci, ch, 0);
7179 NCCIcode = ncci | (((word)a->Id) << 8);
7181 /* count all buffers within the Application pool */
7182 /* belonging to the same NCCI. If this is below the */
7183 /* number of buffers available per NCCI we accept */
7184 /* this packet, otherwise we reject it */
7187 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7188 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7189 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7194 dbug(3, dprintf("Flow-Control"));
7196 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7197 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7200 dbug(3, dprintf("DiscardData"));
7202 channel_x_off(plci, ch, 0);
7208 APPLptr->NCCIDataFlowCtrlTimer = 0;
7211 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7212 if (!plci->RData[0].P) {
7214 channel_x_off(plci, ch, 0);
7218 APPLptr->DataNCCI[Num] = NCCIcode;
7219 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7220 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7223 plci->RFlags = plci->NL.Ind >> 4;
7224 plci->RData[0].PLength = APPLptr->MaxDataLength;
7225 plci->NL.R = plci->RData;
7226 if ((plci->NL.RLength != 0)
7227 && ((plci->B2_prot == B2_V120_ASYNC)
7228 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7229 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7231 plci->RData[1].P = plci->RData[0].P;
7232 plci->RData[1].PLength = plci->RData[0].PLength;
7233 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7234 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7235 plci->RData[0].PLength = 1;
7237 plci->RData[0].PLength = 2;
7238 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7239 plci->RFlags |= 0x0010;
7240 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7241 plci->RFlags |= 0x8000;
7246 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7247 plci->RFlags |= 0x0010;
7249 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7250 plci->RFlags |= 0x0001;
7264 /*------------------------------------------------------------------*/
7265 /* find a free PLCI */
7266 /*------------------------------------------------------------------*/
7268 static word get_plci(DIVA_CAPI_ADAPTER *a)
7274 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7275 if (i == a->max_plci) {
7276 dbug(1, dprintf("get_plci: out of PLCIs"));
7280 plci->Id = (byte)(i + 1);
7288 plci->relatedPTYPLCI = NULL;
7290 plci->SuppState = IDLE;
7293 plci->B1_resource = 0;
7298 plci->m_command = 0;
7299 init_internal_command_queue(plci);
7301 plci->req_in_start = 0;
7304 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7305 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7306 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7308 plci->data_sent = false;
7309 plci->send_disc = 0;
7310 plci->sig_global_req = 0;
7311 plci->sig_remove_id = 0;
7312 plci->nl_global_req = 0;
7313 plci->nl_remove_id = 0;
7315 plci->manufacturer = false;
7316 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7317 plci->spoofed_msg = 0;
7319 plci->cr_enquiry = false;
7320 plci->hangup_flow_ctrl_timer = 0;
7322 plci->ncci_ring_list = 0;
7323 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7324 clear_c_ind_mask(plci);
7325 set_group_ind_mask(plci);
7326 plci->fax_connect_info_length = 0;
7327 plci->nsf_control_bits = 0;
7328 plci->ncpi_state = 0x00;
7329 plci->ncpi_buffer[0] = 0;
7331 plci->requested_options_conn = 0;
7332 plci->requested_options = 0;
7333 plci->notifiedcall = 0;
7334 plci->vswitchstate = 0;
7336 plci->vsprotdialect = 0;
7337 init_b1_config(plci);
7338 dbug(1, dprintf("get_plci(%x)", plci->Id));
7342 /*------------------------------------------------------------------*/
7343 /* put a parameter in the parameter buffer */
7344 /*------------------------------------------------------------------*/
7346 static void add_p(PLCI *plci, byte code, byte *p)
7351 if (p) p_length = p[0];
7352 add_ie(plci, code, p, p_length);
7355 /*------------------------------------------------------------------*/
7356 /* put a structure in the parameter buffer */
7357 /*------------------------------------------------------------------*/
7358 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7360 if (p) add_ie(plci, code, p->info, (word)p->length);
7363 /*------------------------------------------------------------------*/
7364 /* put multiple structures in the parameter buffer */
7365 /*------------------------------------------------------------------*/
7366 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7371 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7372 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7373 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7374 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7379 /*------------------------------------------------------------------*/
7380 /* return the channel number sent by the application in a esc_chi */
7381 /*------------------------------------------------------------------*/
7382 static byte getChannel(API_PARSE *p)
7387 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7388 if (p->info[i] == 2) {
7389 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7397 /*------------------------------------------------------------------*/
7398 /* put an information element in the parameter buffer */
7399 /*------------------------------------------------------------------*/
7401 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7405 if (!(code & 0x80) && !p_length) return;
7407 if (plci->req_in == plci->req_in_start) {
7413 plci->RBuffer[plci->req_in++] = code;
7416 plci->RBuffer[plci->req_in++] = (byte)p_length;
7417 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420 plci->RBuffer[plci->req_in++] = 0;
7423 /*------------------------------------------------------------------*/
7424 /* put a unstructured data into the buffer */
7425 /*------------------------------------------------------------------*/
7427 static void add_d(PLCI *plci, word length, byte *p)
7431 if (plci->req_in == plci->req_in_start) {
7437 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440 /*------------------------------------------------------------------*/
7441 /* put parameters from the Additional Info parameter in the */
7442 /* parameter buffer */
7443 /*------------------------------------------------------------------*/
7445 static void add_ai(PLCI *plci, API_PARSE *ai)
7448 API_PARSE ai_parms[5];
7450 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7454 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7457 add_s(plci, KEY, &ai_parms[1]);
7458 add_s(plci, UUI, &ai_parms[2]);
7459 add_ss(plci, FTY, &ai_parms[3]);
7462 /*------------------------------------------------------------------*/
7463 /* put parameter for b1 protocol in the parameter buffer */
7464 /*------------------------------------------------------------------*/
7466 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7469 API_PARSE bp_parms[8];
7470 API_PARSE mdm_cfg[9];
7471 API_PARSE global_config[2];
7473 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7474 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7477 API_PARSE mdm_cfg_v18[4];
7482 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7483 for (i = 0; i < 2; i++) global_config[i].length = 0;
7485 dbug(1, dprintf("add_b1"));
7486 api_save_msg(bp, "s", &plci->B_protocol);
7488 if (b_channel_info == 2) {
7489 plci->B1_resource = 0;
7490 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7491 add_p(plci, CAI, "\x01\x00");
7492 dbug(1, dprintf("Cai=1,0 (no resource)"));
7496 if (plci->tel == CODEC_PERMANENT) return 0;
7497 else if (plci->tel == CODEC) {
7498 plci->B1_resource = 1;
7499 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7500 add_p(plci, CAI, "\x01\x01");
7501 dbug(1, dprintf("Cai=1,1 (Codec)"));
7504 else if (plci->tel == ADV_VOICE) {
7505 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7506 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7507 voice_cai[1] = plci->B1_resource;
7508 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7509 add_p(plci, CAI, voice_cai);
7510 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7513 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7514 if (plci->call_dir & CALL_DIR_OUT)
7515 plci->call_dir |= CALL_DIR_ORIGINATE;
7516 else if (plci->call_dir & CALL_DIR_IN)
7517 plci->call_dir |= CALL_DIR_ANSWER;
7520 plci->B1_resource = 0x5;
7521 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7522 add_p(plci, CAI, "\x01\x05");
7526 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7527 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7528 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7530 bp_parms[6].length = 0;
7531 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7533 dbug(1, dprintf("b-form.!"));
7534 return _WRONG_MESSAGE_FORMAT;
7537 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7539 dbug(1, dprintf("b-form.!"));
7540 return _WRONG_MESSAGE_FORMAT;
7543 if (bp_parms[6].length)
7545 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7547 return _WRONG_MESSAGE_FORMAT;
7549 switch (GET_WORD(global_config[0].info))
7552 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7555 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7559 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7563 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7565 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567 cai[1] = plci->B1_resource;
7571 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7572 for (i = 0; i < bp_parms[3].length; i++)
7573 cai[7 + i] = bp_parms[3].info[1 + i];
7574 cai[0] = 6 + bp_parms[3].length;
7575 add_p(plci, CAI, cai);
7580 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7581 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7583 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7584 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7585 cai[1] = plci->B1_resource;
7589 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7591 add_p(plci, CAI, cai);
7596 if ((GET_WORD(bp_parms[0].info) >= 32)
7597 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7598 && ((GET_WORD(bp_parms[0].info) != 3)
7599 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7600 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7602 return _B1_NOT_SUPPORTED;
7604 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7605 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7606 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608 cai[1] = plci->B1_resource;
7609 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7611 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7612 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7613 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7615 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7617 if (bp_parms[3].length)
7619 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7621 return (_WRONG_MESSAGE_FORMAT);
7624 cai[2] = 0; /* Bit rate for adaptation */
7626 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7628 PUT_WORD(&cai[13], 0); /* Min Tx speed */
7629 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7630 PUT_WORD(&cai[17], 0); /* Min Rx speed */
7631 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7633 cai[3] = 0; /* Async framing parameters */
7634 switch (GET_WORD(mdm_cfg[2].info))
7636 case 1: /* odd parity */
7637 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7638 dbug(1, dprintf("MDM: odd parity"));
7641 case 2: /* even parity */
7642 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7643 dbug(1, dprintf("MDM: even parity"));
7647 dbug(1, dprintf("MDM: no parity"));
7651 switch (GET_WORD(mdm_cfg[3].info))
7653 case 1: /* 2 stop bits */
7654 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7655 dbug(1, dprintf("MDM: 2 stop bits"));
7659 dbug(1, dprintf("MDM: 1 stop bit"));
7663 switch (GET_WORD(mdm_cfg[1].info))
7666 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7667 dbug(1, dprintf("MDM: 5 bits"));
7671 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7672 dbug(1, dprintf("MDM: 6 bits"));
7676 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7677 dbug(1, dprintf("MDM: 7 bits"));
7681 dbug(1, dprintf("MDM: 8 bits"));
7685 cai[7] = 0; /* Line taking options */
7686 cai[8] = 0; /* Modulation negotiation options */
7687 cai[9] = 0; /* Modulation options */
7689 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7691 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7692 dbug(1, dprintf("MDM: Reverse direction"));
7695 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7697 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7698 dbug(1, dprintf("MDM: Disable retrain"));
7701 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7703 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7704 dbug(1, dprintf("MDM: Disable ring tone"));
7707 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7709 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7710 dbug(1, dprintf("MDM: 1800 guard tone"));
7712 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7714 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7715 dbug(1, dprintf("MDM: 550 guard tone"));
7718 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7720 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7721 dbug(1, dprintf("MDM: V100"));
7723 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7725 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7726 dbug(1, dprintf("MDM: IN CLASS"));
7728 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7730 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7731 dbug(1, dprintf("MDM: DISABLED"));
7735 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7736 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7738 plci->requested_options |= 1L << PRIVATE_V18;
7740 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7741 plci->requested_options |= 1L << PRIVATE_VOWN;
7743 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7744 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7746 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7749 if (mdm_cfg[6].length >= 4)
7751 d = GET_DWORD(&mdm_cfg[6].info[1]);
7752 cai[7] |= (byte) d; /* line taking options */
7753 cai[9] |= (byte)(d >> 8); /* modulation options */
7754 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7755 cai[++i] = (byte)(d >> 24);
7756 if (mdm_cfg[6].length >= 8)
7758 d = GET_DWORD(&mdm_cfg[6].info[5]);
7759 cai[10] |= (byte) d; /* disabled modulations mask */
7760 cai[11] |= (byte)(d >> 8);
7761 if (mdm_cfg[6].length >= 12)
7763 d = GET_DWORD(&mdm_cfg[6].info[9]);
7764 cai[12] = (byte) d; /* enabled modulations mask */
7765 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7766 cai[++i] = (byte)(d >> 16);
7767 cai[++i] = (byte)(d >> 24);
7769 if (mdm_cfg[6].length >= 14)
7771 w = GET_WORD(&mdm_cfg[6].info[13]);
7773 PUT_WORD(&cai[13], w); /* min tx speed */
7774 if (mdm_cfg[6].length >= 16)
7776 w = GET_WORD(&mdm_cfg[6].info[15]);
7778 PUT_WORD(&cai[15], w); /* max tx speed */
7779 if (mdm_cfg[6].length >= 18)
7781 w = GET_WORD(&mdm_cfg[6].info[17]);
7783 PUT_WORD(&cai[17], w); /* min rx speed */
7784 if (mdm_cfg[6].length >= 20)
7786 w = GET_WORD(&mdm_cfg[6].info[19]);
7788 PUT_WORD(&cai[19], w); /* max rx speed */
7789 if (mdm_cfg[6].length >= 22)
7791 w = GET_WORD(&mdm_cfg[6].info[21]);
7792 cai[23] = (byte)(-((short) w)); /* transmit level */
7793 if (mdm_cfg[6].length >= 24)
7795 w = GET_WORD(&mdm_cfg[6].info[23]);
7796 cai[22] |= (byte) w; /* info options mask */
7797 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7809 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7811 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7813 for (n = 0; n < 3; n++)
7815 cai[i] = (byte)(mdm_cfg_v18[n].length);
7816 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7817 cai[i + j] = mdm_cfg_v18[n].info[j];
7822 cai[0] = (byte)(i - 1);
7828 if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7829 GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7831 if (bp_parms[3].length) {
7832 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7833 switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7836 if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7837 dbug(1, dprintf("56k sync HSCX"));
7842 else if (GET_WORD(bp_parms[0].info) == 2) {
7843 dbug(1, dprintf("56k async DSP"));
7847 case 50: cai[2] = 1; break;
7848 case 75: cai[2] = 1; break;
7849 case 110: cai[2] = 1; break;
7850 case 150: cai[2] = 1; break;
7851 case 200: cai[2] = 1; break;
7852 case 300: cai[2] = 1; break;
7853 case 600: cai[2] = 1; break;
7854 case 1200: cai[2] = 2; break;
7855 case 2400: cai[2] = 3; break;
7856 case 4800: cai[2] = 4; break;
7857 case 7200: cai[2] = 10; break;
7858 case 9600: cai[2] = 5; break;
7859 case 12000: cai[2] = 13; break;
7860 case 24000: cai[2] = 0; break;
7861 case 14400: cai[2] = 11; break;
7862 case 19200: cai[2] = 6; break;
7863 case 28800: cai[2] = 12; break;
7864 case 38400: cai[2] = 7; break;
7865 case 48000: cai[2] = 8; break;
7866 case 76: cai[2] = 15; break; /* 75/1200 */
7867 case 1201: cai[2] = 14; break; /* 1200/75 */
7868 case 56001: cai[2] = 9; break; /* V.110 56000 */
7871 return _B1_PARM_NOT_SUPPORTED;
7874 if (cai[1] == 13) /* v.110 async */
7876 if (bp_parms[3].length >= 8)
7878 switch (GET_WORD(&bp_parms[3].info[3]))
7881 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7884 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7887 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7890 switch (GET_WORD(&bp_parms[3].info[5]))
7892 case 1: /* odd parity */
7893 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7895 case 2: /* even parity */
7896 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7899 switch (GET_WORD(&bp_parms[3].info[7]))
7901 case 1: /* 2 stop bits */
7902 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7908 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7909 dbug(1, dprintf("V.110 default 56k sync"));
7915 dbug(1, dprintf("V.110 default 9600 async"));
7919 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7920 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]));
7921 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7923 add_p(plci, CAI, cai);
7927 /*------------------------------------------------------------------*/
7928 /* put parameter for b2 and B3 protocol in the parameter buffer */
7929 /*------------------------------------------------------------------*/
7931 static word add_b23(PLCI *plci, API_PARSE *bp)
7933 word i, fax_control_bits;
7935 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7936 API_PARSE bp_parms[8];
7937 API_PARSE *b1_config;
7938 API_PARSE *b2_config;
7939 API_PARSE b2_config_parms[8];
7940 API_PARSE *b3_config;
7941 API_PARSE b3_config_parms[6];
7942 API_PARSE global_config[2];
7944 static byte llc[3] = {2,0,0};
7945 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7946 static byte nlc[256];
7947 static byte lli[12] = {1,1};
7949 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7950 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952 const byte llc3[] = {4,3,2,2,6,6,0};
7953 const byte header[] = {0,2,3,3,0,0,0};
7955 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7956 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7957 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7961 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7963 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7966 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7968 if (plci->rx_dma_descriptor <= 0) {
7969 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7970 if (plci->rx_dma_descriptor >= 0)
7971 plci->rx_dma_descriptor++;
7973 if (plci->rx_dma_descriptor > 0) {
7976 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7977 lli[3] = (byte)plci->rx_dma_magic;
7978 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7979 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7980 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7984 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7988 dbug(1, dprintf("add_b23"));
7989 api_save_msg(bp, "s", &plci->B_protocol);
7991 if (!bp->length && plci->tel)
7993 plci->adv_nl = true;
7994 dbug(1, dprintf("Default adv.Nl"));
7995 add_p(plci, LLI, lli);
7996 plci->B2_prot = 1 /*XPARENT*/;
7997 plci->B3_prot = 0 /*XPARENT*/;
8000 add_p(plci, LLC, llc);
8002 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8003 add_p(plci, DLC, dlc);
8007 if (!bp->length) /*default*/
8009 dbug(1, dprintf("ret default"));
8010 add_p(plci, LLI, lli);
8011 plci->B2_prot = 0 /*X.75 */;
8012 plci->B3_prot = 0 /*XPARENT*/;
8015 add_p(plci, LLC, llc);
8017 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8018 add_p(plci, DLC, dlc);
8021 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8022 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8024 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8026 bp_parms[6].length = 0;
8027 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8029 dbug(1, dprintf("b-form.!"));
8030 return _WRONG_MESSAGE_FORMAT;
8033 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8035 dbug(1, dprintf("b-form.!"));
8036 return _WRONG_MESSAGE_FORMAT;
8039 if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8041 if (GET_WORD(bp_parms[1].info) != 1
8042 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8043 plci->adv_nl = true;
8045 else if (plci->tel) return _B2_NOT_SUPPORTED;
8048 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8049 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8050 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8052 add_p(plci, LLI, lli);
8053 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8054 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8055 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8057 add_p(plci, LLC, llc);
8059 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8060 dlc[3] = 3; /* Addr A */
8061 dlc[4] = 1; /* Addr B */
8062 dlc[5] = 7; /* modulo mode */
8063 dlc[6] = 7; /* window size */
8064 dlc[7] = 0; /* XID len Lo */
8065 dlc[8] = 0; /* XID len Hi */
8066 for (i = 0; i < bp_parms[4].length; i++)
8067 dlc[9 + i] = bp_parms[4].info[1 + i];
8068 dlc[0] = (byte)(8 + bp_parms[4].length);
8069 add_p(plci, DLC, dlc);
8070 for (i = 0; i < bp_parms[5].length; i++)
8071 nlc[1 + i] = bp_parms[5].info[1 + i];
8072 nlc[0] = (byte)(bp_parms[5].length);
8073 add_p(plci, NLC, nlc);
8079 if ((GET_WORD(bp_parms[1].info) >= 32)
8080 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8081 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8082 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085 return _B2_NOT_SUPPORTED;
8087 if ((GET_WORD(bp_parms[2].info) >= 32)
8088 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8090 return _B3_NOT_SUPPORTED;
8092 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8093 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8094 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8095 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8097 return (add_modem_b23(plci, bp_parms));
8100 add_p(plci, LLI, lli);
8102 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8103 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8104 if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8106 if (bp_parms[6].length)
8108 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8110 return _WRONG_MESSAGE_FORMAT;
8112 switch (GET_WORD(global_config[0].info))
8115 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8118 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8122 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125 if (plci->B2_prot == B2_PIAFS)
8128 /* IMPLEMENT_PIAFS */
8130 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8131 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8133 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8135 add_p(plci, LLC, llc);
8138 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8139 header[GET_WORD(bp_parms[2].info)]);
8141 b1_config = &bp_parms[3];
8143 if (plci->B3_prot == 4
8144 || plci->B3_prot == 5)
8146 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8147 nlc[0] = sizeof(T30_INFO);
8148 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8149 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8150 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8151 if (b1_config->length >= 2)
8153 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156 b2_config = &bp_parms[4];
8159 if (llc[1] == PIAFS_CRC)
8161 if (plci->B3_prot != B3_TRANSPARENT)
8163 return _B_STACK_NOT_SUPPORTED;
8165 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8166 return _WRONG_MESSAGE_FORMAT;
8168 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8169 dlc[3] = 0; /* Addr A */
8170 dlc[4] = 0; /* Addr B */
8171 dlc[5] = 0; /* modulo mode */
8172 dlc[6] = 0; /* window size */
8173 if (b2_config->length >= 7) {
8176 dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8177 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8178 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8179 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8180 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8181 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8182 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8184 if (b2_config->length >= 8) { /* PIAFS control abilities */
8186 dlc[16] = 2; /* Length of PIAFS extension */
8187 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8188 dlc[18] = b2_config_parms[4].info[0]; /* value */
8192 else /* default values, 64K, variable, no compression */
8196 dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8197 dlc[10] = 0x03; /* V.42bis P0 */
8198 dlc[11] = 0; /* V.42bis P0 */
8199 dlc[12] = 0; /* V.42bis P1 */
8200 dlc[13] = 0; /* V.42bis P1 */
8201 dlc[14] = 0; /* V.42bis P2 */
8202 dlc[15] = 0; /* V.42bis P2 */
8205 add_p(plci, DLC, dlc);
8209 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8211 if (plci->B3_prot != B3_TRANSPARENT)
8212 return _B_STACK_NOT_SUPPORTED;
8215 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8220 if (b2_config->length != 0)
8222 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8223 return _WRONG_MESSAGE_FORMAT;
8225 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8226 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8227 if (b2_config->info[3] != 128)
8229 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8230 return _B2_PARM_NOT_SUPPORTED;
8232 dlc[5] = (byte)(b2_config->info[3] - 1);
8233 dlc[6] = b2_config->info[4];
8234 if (llc[1] == V120_V42BIS) {
8235 if (b2_config->length >= 10) {
8238 dlc[9] = b2_config_parms[4].info[0];
8239 dlc[10] = b2_config_parms[4].info[1];
8240 dlc[11] = b2_config_parms[5].info[0];
8241 dlc[12] = b2_config_parms[5].info[1];
8242 dlc[13] = b2_config_parms[6].info[0];
8243 dlc[14] = b2_config_parms[6].info[1];
8245 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8246 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8247 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8257 if (b2_config->length)
8259 dbug(1, dprintf("B2-Config"));
8260 if (llc[1] == X75_V42BIS) {
8261 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8263 return _WRONG_MESSAGE_FORMAT;
8267 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8269 return _WRONG_MESSAGE_FORMAT;
8272 /* if B2 Protocol is LAPD, b2_config structure is different */
8276 if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8278 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8280 SAPI = b2_config->info[2]; /* SAPI */
8283 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8285 dlc[3] = 127; /* Mode */
8289 dlc[3] = 7; /* Mode */
8292 if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8294 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8295 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8299 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8300 dlc[3] = b2_config->info[1];
8301 dlc[4] = b2_config->info[2];
8302 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8303 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8304 return _B2_PARM_NOT_SUPPORTED;
8307 dlc[5] = (byte)(b2_config->info[3] - 1);
8308 dlc[6] = b2_config->info[4];
8309 if (dlc[6] > dlc[5]) {
8310 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]));
8311 return _B2_PARM_NOT_SUPPORTED;
8314 if (llc[1] == X75_V42BIS) {
8315 if (b2_config->length >= 10) {
8318 dlc[9] = b2_config_parms[4].info[0];
8319 dlc[10] = b2_config_parms[4].info[1];
8320 dlc[11] = b2_config_parms[5].info[0];
8321 dlc[12] = b2_config_parms[5].info[1];
8322 dlc[13] = b2_config_parms[6].info[0];
8323 dlc[14] = b2_config_parms[6].info[1];
8325 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8326 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8327 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8335 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8336 for (i = 0; i < b2_config_parms[4].length; i++)
8337 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8342 add_p(plci, DLC, dlc);
8344 b3_config = &bp_parms[5];
8345 if (b3_config->length)
8347 if (plci->B3_prot == 4
8348 || plci->B3_prot == 5)
8350 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8352 return _WRONG_MESSAGE_FORMAT;
8354 i = GET_WORD((byte *)(b3_config_parms[0].info));
8355 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8356 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8357 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8358 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8359 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8360 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8361 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8364 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8365 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8367 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8368 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8369 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8372 ((T30_INFO *)&nlc[1])->recording_properties =
8373 T30_RECORDING_WIDTH_ISO_A3 |
8374 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8375 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8377 if (plci->B3_prot == 5)
8379 if (i & 0x0002) /* Accept incoming fax-polling requests */
8380 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8381 if (i & 0x2000) /* Do not use MR compression */
8382 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8383 if (i & 0x4000) /* Do not use MMR compression */
8384 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8385 if (i & 0x8000) /* Do not use ECM */
8386 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8387 if (plci->fax_connect_info_length != 0)
8389 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8390 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8391 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8392 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8393 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8396 /* copy station id to NLC */
8397 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8399 if (i < b3_config_parms[2].length)
8401 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8405 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8409 /* copy head line to NLC */
8410 if (b3_config_parms[3].length)
8413 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8416 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8420 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8421 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8422 len = (byte)b3_config_parms[2].length;
8425 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8427 for (i = 0; i < len; i++)
8428 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8429 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8430 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8435 len = (byte)b3_config_parms[3].length;
8436 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8437 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8438 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8439 nlc[0] += (byte)(pos + len);
8440 for (i = 0; i < len; i++)
8441 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8443 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8445 plci->nsf_control_bits = 0;
8446 if (plci->B3_prot == 5)
8448 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8449 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8451 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8453 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8454 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8456 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8458 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8459 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8461 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8462 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8464 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8465 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8466 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8469 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8470 if (pos < plci->fax_connect_info_length)
8472 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8473 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8477 if (pos < plci->fax_connect_info_length)
8479 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8484 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8485 & (1L << PRIVATE_FAX_NONSTANDARD))
8487 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8489 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8490 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8491 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8492 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8496 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8498 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8503 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8504 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8505 nlc[++len] = (byte)(b3_config_parms[4].length);
8506 for (i = 0; i < b3_config_parms[4].length; i++)
8507 nlc[++len] = b3_config_parms[4].info[1 + i];
8512 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8513 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8515 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8520 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8521 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8522 for (i = 0; i < len; i++)
8523 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8524 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8525 i += ((T30_INFO *)&nlc[1])->head_line_len;
8527 plci->fax_connect_info_buffer[len++] = nlc[++i];
8528 plci->fax_connect_info_length = len;
8533 if (b3_config->length != 16)
8534 return _B3_PARM_NOT_SUPPORTED;
8535 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8536 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8537 return _B3_PARM_NOT_SUPPORTED;
8538 nlc[13] = b3_config->info[13];
8539 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8540 return _B3_PARM_NOT_SUPPORTED;
8541 nlc[14] = b3_config->info[15];
8546 if (plci->B3_prot == 4
8547 || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8549 add_p(plci, NLC, nlc);
8553 /*----------------------------------------------------------------*/
8554 /* make the same as add_b23, but only for the modem related */
8555 /* L2 and L3 B-Chan protocol. */
8557 /* Enabled L2 and L3 Configurations: */
8558 /* If L1 == Modem all negotiation */
8559 /* only L2 == Modem with full negotiation is allowed */
8560 /* If L1 == Modem async or sync */
8561 /* only L2 == Transparent is allowed */
8562 /* L3 == Modem or L3 == Transparent are allowed */
8563 /* B2 Configuration for modem: */
8564 /* word : enable/disable compression, bitoptions */
8565 /* B3 Configuration for modem: */
8567 /*----------------------------------------------------------------*/
8568 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8570 static byte lli[12] = {1,1};
8571 static byte llc[3] = {2,0,0};
8572 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8573 API_PARSE mdm_config[2];
8577 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8578 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8580 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8581 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8582 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8583 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8585 return (_B_STACK_NOT_SUPPORTED);
8587 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8588 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8590 return (_B_STACK_NOT_SUPPORTED);
8593 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8594 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8596 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8598 if (api_parse(&bp_parms[4].info[1],
8599 (word)bp_parms[4].length, "w",
8602 return (_WRONG_MESSAGE_FORMAT);
8604 b2_config = GET_WORD(mdm_config[0].info);
8607 /* OK, L2 is modem */
8611 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8613 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8616 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8618 if (plci->rx_dma_descriptor <= 0) {
8619 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8620 if (plci->rx_dma_descriptor >= 0)
8621 plci->rx_dma_descriptor++;
8623 if (plci->rx_dma_descriptor > 0) {
8626 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8627 lli[3] = (byte)plci->rx_dma_magic;
8628 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8629 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8630 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8634 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8638 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8639 /*V42*/ 10 : /*V42_IN*/ 9;
8640 llc[2] = 4; /* pass L3 always transparent */
8641 add_p(plci, LLI, lli);
8642 add_p(plci, LLC, llc);
8644 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8646 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8648 if (bp_parms[4].length)
8650 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8651 dlc[i++] = 3; /* Addr A */
8652 dlc[i++] = 1; /* Addr B */
8653 dlc[i++] = 7; /* modulo mode */
8654 dlc[i++] = 7; /* window size */
8655 dlc[i++] = 0; /* XID len Lo */
8656 dlc[i++] = 0; /* XID len Hi */
8658 if (b2_config & MDM_B2_DISABLE_V42bis)
8660 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8662 if (b2_config & MDM_B2_DISABLE_MNP)
8664 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8666 if (b2_config & MDM_B2_DISABLE_TRANS)
8668 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8670 if (b2_config & MDM_B2_DISABLE_V42)
8672 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8674 if (b2_config & MDM_B2_DISABLE_COMP)
8676 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8683 dlc[i++] = 3; /* Addr A */
8684 dlc[i++] = 1; /* Addr B */
8685 dlc[i++] = 7; /* modulo mode */
8686 dlc[i++] = 7; /* window size */
8687 dlc[i++] = 0; /* XID len Lo */
8688 dlc[i++] = 0; /* XID len Hi */
8689 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8690 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8691 DLC_MODEMPROT_DISABLE_V42_DETECT |
8692 DLC_MODEMPROT_DISABLE_COMPRESSION;
8694 dlc[0] = (byte)(i - 1);
8695 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8696 add_p(plci, DLC, dlc);
8701 /*------------------------------------------------------------------*/
8702 /* send a request for the signaling entity */
8703 /*------------------------------------------------------------------*/
8705 static void sig_req(PLCI *plci, byte req, byte Id)
8708 if (plci->adapter->adapter_disabled) return;
8709 dbug(1, dprintf("sig_req(%x)", req));
8711 plci->sig_remove_id = plci->Sig.Id;
8712 if (plci->req_in == plci->req_in_start) {
8714 plci->RBuffer[plci->req_in++] = 0;
8716 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8717 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8718 plci->RBuffer[plci->req_in++] = req; /* request */
8719 plci->RBuffer[plci->req_in++] = 0; /* channel */
8720 plci->req_in_start = plci->req_in;
8723 /*------------------------------------------------------------------*/
8724 /* send a request for the network layer entity */
8725 /*------------------------------------------------------------------*/
8727 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8730 if (plci->adapter->adapter_disabled) return;
8731 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8734 plci->nl_remove_id = plci->NL.Id;
8735 ncci_remove(plci, 0, (byte)(ncci != 0));
8738 if (plci->req_in == plci->req_in_start) {
8740 plci->RBuffer[plci->req_in++] = 0;
8742 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8743 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8744 plci->RBuffer[plci->req_in++] = req; /* request */
8745 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8746 plci->req_in_start = plci->req_in;
8749 static void send_req(PLCI *plci)
8756 if (plci->adapter->adapter_disabled) return;
8757 channel_xmit_xon(plci);
8759 /* if nothing to do, return */
8760 if (plci->req_in == plci->req_out) return;
8761 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8763 if (plci->nl_req || plci->sig_req) return;
8765 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8767 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8769 if (plci->RBuffer[plci->req_out] == 1)
8773 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8774 e->ReqCh = plci->RBuffer[plci->req_out++];
8775 if (!(e->Id & 0x1f))
8778 plci->RBuffer[plci->req_out - 4] = CAI;
8779 plci->RBuffer[plci->req_out - 3] = 1;
8780 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8781 plci->RBuffer[plci->req_out - 1] = 0;
8783 plci->nl_global_req = plci->nl_req;
8785 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8790 if (plci->RBuffer[plci->req_out])
8791 e->Id = plci->RBuffer[plci->req_out];
8793 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8794 e->ReqCh = plci->RBuffer[plci->req_out++];
8795 if (!(e->Id & 0x1f))
8796 plci->sig_global_req = plci->sig_req;
8797 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8799 plci->XData[0].PLength = l;
8801 plci->adapter->request(e);
8802 dbug(1, dprintf("send_ok"));
8805 static void send_data(PLCI *plci)
8807 DIVA_CAPI_ADAPTER *a;
8812 if (!plci->nl_req && plci->ncci_ring_list)
8815 ncci = plci->ncci_ring_list;
8818 ncci = a->ncci_next[ncci];
8819 ncci_ptr = &(a->ncci[ncci]);
8820 if (!(a->ncci_ch[ncci]
8821 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8823 if (ncci_ptr->data_pending)
8825 if ((a->ncci_state[ncci] == CONNECTED)
8826 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8827 || (plci->send_disc == ncci))
8829 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8830 if ((plci->B2_prot == B2_V120_ASYNC)
8831 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8832 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8834 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8835 plci->NData[1].PLength = data->Length;
8836 if (data->Flags & 0x10)
8837 plci->NData[0].P = v120_break_header;
8839 plci->NData[0].P = v120_default_header;
8840 plci->NData[0].PLength = 1;
8842 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8846 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8847 plci->NData[0].PLength = data->Length;
8848 if (data->Flags & 0x10)
8849 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8851 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8852 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8855 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8857 plci->NL.X = plci->NData;
8858 plci->NL.ReqCh = a->ncci_ch[ncci];
8859 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8860 plci->data_sent = true;
8861 plci->data_sent_ptr = data->P;
8862 a->request(&plci->NL);
8865 cleanup_ncci_data(plci, ncci);
8868 else if (plci->send_disc == ncci)
8870 /* dprintf("N_DISC"); */
8871 plci->NData[0].PLength = 0;
8872 plci->NL.ReqCh = a->ncci_ch[ncci];
8873 plci->NL.Req = plci->nl_req = N_DISC;
8874 a->request(&plci->NL);
8875 plci->command = _DISCONNECT_B3_R;
8876 plci->send_disc = 0;
8879 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8880 plci->ncci_ring_list = ncci;
8884 static void listen_check(DIVA_CAPI_ADAPTER *a)
8888 byte activnotifiedcalls = 0;
8890 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8891 if (!remove_started && !a->adapter_disabled)
8893 for (i = 0; i < a->max_plci; i++)
8895 plci = &(a->plci[i]);
8896 if (plci->notifiedcall) activnotifiedcalls++;
8898 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8900 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8901 if ((j = get_plci(a))) {
8903 plci = &a->plci[j - 1];
8904 plci->State = LISTENING;
8906 add_p(plci, OAD, "\x01\xfd");
8908 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8910 add_p(plci, CAI, "\x01\xc0");
8911 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8912 add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8913 add_p(plci, SHIFT | 6, NULL);
8914 add_p(plci, SIN, "\x02\x00\x00");
8915 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8916 sig_req(plci, ASSIGN, DSIG_ID);
8923 /*------------------------------------------------------------------*/
8924 /* functions for all parameters sent in INDs */
8925 /*------------------------------------------------------------------*/
8927 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8929 word ploc; /* points to current location within packet */
8941 in = plci->Sig.RBuffer->P;
8942 for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8943 { /* element but parms array is larger */
8944 parms[i] = (byte *)"";
8946 for (i = 0; i < multiIEsize; i++)
8948 parms[i] = (byte *)"";
8951 while (ploc < plci->Sig.RBuffer->length - 1) {
8953 /* read information element id and length */
8957 /* w &=0xf0; removed, cannot detect congestion levels */
8958 /* upper 4 bit masked with w==SHIFT now */
8962 wlen = (byte)(in[ploc + 1] + 1);
8964 /* check if length valid (not exceeding end of packet) */
8965 if ((ploc + wlen) > 270) return;
8966 if (lock & 0x80) lock &= 0x7f;
8967 else codeset = lock;
8969 if ((w & 0xf0) == SHIFT) {
8971 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8976 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8978 code |= (codeset << 8);
8980 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8982 if (i < parms_id[0] + 1) {
8983 if (!multiIEsize) { /* with multiIEs use next field index, */
8984 mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8987 parms[mIEindex] = &in[ploc + 1];
8988 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8989 if (parms_id[i] == OAD
8990 || parms_id[i] == CONN_NR
8991 || parms_id[i] == CAD) {
8992 if (in[ploc + 2] & 0x80) {
8993 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8994 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8995 in[ploc + 2] = 0x80;
8996 parms[mIEindex] = &in[ploc];
8999 mIEindex++; /* effects multiIEs only */
9008 /*------------------------------------------------------------------*/
9009 /* try to match a cip from received BC and HLC */
9010 /*------------------------------------------------------------------*/
9012 static byte ie_compare(byte *ie1, byte *ie2)
9015 if (!ie1 || !ie2) return false;
9016 if (!ie1[0]) return false;
9017 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9021 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9026 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9028 for (j = 16; j < 29 &&
9029 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9030 if (j == 29) return i;
9035 static byte AddInfo(byte **add_i,
9045 /* facility is a nested structure */
9046 /* FTY can be more than once */
9048 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9050 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9055 add_i[0] = (byte *)"";
9059 add_i[3] = (byte *)"";
9062 { /* facility array found */
9063 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9065 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9069 facility[j++] = 0x1c; /* copy fac IE */
9070 for (k = 0; k <= flen; k++, j++)
9072 facility[j] = fty_i[i][k];
9073 /* dbug(1, dprintf("%x ",facility[j])); */
9077 add_i[3] = facility;
9079 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
9080 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9081 len += 4; /* calculate length of all */
9085 /*------------------------------------------------------------------*/
9086 /* voice and codec features */
9087 /*------------------------------------------------------------------*/
9089 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9091 byte voice_chi[] = "\x02\x18\x01";
9094 channel = chi[chi[0]] & 0x3;
9095 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9096 voice_chi[2] = (channel) ? channel : 1;
9097 add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
9098 add_p(plci, ESC, voice_chi); /* Channel */
9099 sig_req(plci, TEL_CTRL, 0);
9101 if (a->AdvSignalPLCI)
9103 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9107 static void VoiceChannelOff(PLCI *plci)
9109 dbug(1, dprintf("ExtDevOFF"));
9110 add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
9111 sig_req(plci, TEL_CTRL, 0);
9113 if (plci->adapter->AdvSignalPLCI)
9115 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9120 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9126 /* check if hardware supports handset with hook states (adv.codec) */
9127 /* or if just a on board codec is supported */
9128 /* the advanced codec plci is just for internal use */
9130 /* diva Pro with on-board codec: */
9131 if (a->profile.Global_Options & HANDSET)
9133 /* new call, but hook states are already signalled */
9134 if (a->AdvCodecFLAG)
9136 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9138 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9139 return 0x2001; /* codec in use by another application */
9143 a->AdvSignalPLCI = plci;
9144 plci->tel = ADV_VOICE;
9146 return 0; /* adv codec still used */
9148 if ((j = get_plci(a)))
9150 splci = &a->plci[j - 1];
9151 splci->tel = CODEC_PERMANENT;
9152 /* hook_listen indicates if a facility_req with handset/hook support */
9153 /* was sent. Otherwise if just a call on an external device was made */
9154 /* the codec will be used but the hook info will be discarded (just */
9155 /* the external controller is in use */
9156 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9159 splci->State = ADVANCED_VOICE_NOSIG;
9162 plci->spoofed_msg = SPOOFING_REQUIRED;
9164 /* indicate D-ch connect if */
9165 } /* codec is connected OK */
9168 a->AdvSignalPLCI = plci;
9169 plci->tel = ADV_VOICE;
9171 a->AdvSignalAppl = appl;
9172 a->AdvCodecFLAG = true;
9173 a->AdvCodecPLCI = splci;
9174 add_p(splci, CAI, "\x01\x15");
9175 add_p(splci, LLI, "\x01\x00");
9176 add_p(splci, ESC, "\x02\x18\x00");
9177 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9178 splci->internal_command = PERM_COD_ASSIGN;
9179 dbug(1, dprintf("Codec Assign"));
9180 sig_req(splci, ASSIGN, DSIG_ID);
9185 return 0x2001; /* wrong state, no more plcis */
9188 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9190 if (hook_listen) return 0x300B; /* Facility not supported */
9191 /* no hook with SCOM */
9192 if (plci != NULL) plci->tel = CODEC;
9193 dbug(1, dprintf("S/SCOM codec"));
9194 /* first time we use the scom-s codec we must shut down the internal */
9195 /* handset application of the card. This can be done by an assign with */
9196 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9197 if (!a->scom_appl_disable) {
9198 if ((j = get_plci(a))) {
9199 splci = &a->plci[j - 1];
9200 add_p(splci, CAI, "\x01\x80");
9201 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9202 sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9204 a->scom_appl_disable = true;
9207 return 0x2001; /* wrong state, no more plcis */
9211 else return 0x300B; /* Facility not supported */
9217 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220 dbug(1, dprintf("CodecIdCheck"));
9222 if (a->AdvSignalPLCI == plci)
9224 dbug(1, dprintf("PLCI owns codec"));
9225 VoiceChannelOff(a->AdvCodecPLCI);
9226 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9228 dbug(1, dprintf("remove temp codec PLCI"));
9229 plci_remove(a->AdvCodecPLCI);
9230 a->AdvCodecFLAG = 0;
9231 a->AdvCodecPLCI = NULL;
9232 a->AdvSignalAppl = NULL;
9234 a->AdvSignalPLCI = NULL;
9238 /* -------------------------------------------------------------------
9239 Ask for physical address of card on PCI bus
9240 ------------------------------------------------------------------- */
9241 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9242 IDI_SYNC_REQ *preq) {
9244 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9245 ENTITY *e = (ENTITY *)preq;
9247 e->user[0] = a->Id - 1;
9248 preq->xdi_sdram_bar.info.bar = 0;
9249 preq->xdi_sdram_bar.Req = 0;
9250 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9254 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9255 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9259 /* -------------------------------------------------------------------
9260 Ask XDI about extended features
9261 ------------------------------------------------------------------- */
9262 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9264 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9267 preq = (IDI_SYNC_REQ *)&buffer[0];
9269 if (!diva_xdi_extended_features) {
9270 ENTITY *e = (ENTITY *)preq;
9271 diva_xdi_extended_features |= 0x80000000;
9273 e->user[0] = a->Id - 1;
9274 preq->xdi_extended_features.Req = 0;
9275 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9276 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9277 preq->xdi_extended_features.info.features = &features[0];
9281 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9283 Check features located in the byte '0'
9285 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9286 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9288 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9289 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9290 dbug(1, dprintf("XDI provides RxDMA"));
9292 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9293 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9295 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9296 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9297 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9303 diva_ask_for_xdi_sdram_bar(a, preq);
9306 /*------------------------------------------------------------------*/
9308 /*------------------------------------------------------------------*/
9309 /* called from OS specific part after init time to get the Law */
9310 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9311 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9316 if (a->automatic_law) {
9319 if ((j = get_plci(a))) {
9320 diva_get_extended_adapter_features(a);
9321 splci = &a->plci[j - 1];
9322 a->automatic_lawPLCI = splci;
9323 a->automatic_law = 1;
9324 add_p(splci, CAI, "\x01\x80");
9325 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9326 splci->internal_command = USELAW_REQ;
9329 sig_req(splci, ASSIGN, DSIG_ID);
9334 /* called from OS specific part if an application sends an Capi20Release */
9335 word CapiRelease(word Id)
9337 word i, j, appls_found;
9340 DIVA_CAPI_ADAPTER *a;
9344 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9345 return (_WRONG_APPL_ID);
9348 this = &application[Id - 1]; /* get application pointer */
9350 for (i = 0, appls_found = 0; i < max_appl; i++)
9352 if (application[i].Id) /* an application has been found */
9358 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9363 a->Info_Mask[Id - 1] = 0;
9364 a->CIP_Mask[Id - 1] = 0;
9365 a->Notification_Mask[Id - 1] = 0;
9366 a->codec_listen[Id - 1] = NULL;
9367 a->requested_options_table[Id - 1] = 0;
9368 for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9369 { /* with this application */
9371 if (plci->Id) /* if plci owns no application */
9372 { /* it may be not jet connected */
9373 if (plci->State == INC_CON_PENDING
9374 || plci->State == INC_CON_ALERT)
9376 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9378 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9379 if (c_ind_mask_empty(plci))
9381 sig_req(plci, HANGUP, 0);
9383 plci->State = OUTG_DIS_PENDING;
9387 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9389 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9390 if (c_ind_mask_empty(plci))
9399 if (plci->appl == this)
9409 if (a->flag_dynamic_l1_down)
9411 if (appls_found == 1) /* last application does a capi release */
9413 if ((j = get_plci(a)))
9415 plci = &a->plci[j - 1];
9417 add_p(plci, OAD, "\x01\xfd");
9418 add_p(plci, CAI, "\x01\x80");
9419 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9420 add_p(plci, SHIFT | 6, NULL);
9421 add_p(plci, SIN, "\x02\x00\x00");
9422 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9423 sig_req(plci, ASSIGN, DSIG_ID);
9424 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9425 sig_req(plci, SIG_CTRL, 0);
9430 if (a->AdvSignalAppl == this)
9432 this->NullCREnable = false;
9433 if (a->AdvCodecPLCI)
9435 plci_remove(a->AdvCodecPLCI);
9436 a->AdvCodecPLCI->tel = 0;
9437 a->AdvCodecPLCI->adv_nl = 0;
9439 a->AdvSignalAppl = NULL;
9440 a->AdvSignalPLCI = NULL;
9441 a->AdvCodecFLAG = 0;
9442 a->AdvCodecPLCI = NULL;
9452 static word plci_remove_check(PLCI *plci)
9454 if (!plci) return true;
9455 if (!plci->NL.Id && c_ind_mask_empty(plci))
9457 if (plci->Sig.Id == 0xff)
9461 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9462 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9465 CodecIdCheck(plci->adapter, plci);
9466 clear_b1_config(plci);
9467 ncci_remove(plci, 0, false);
9468 plci_free_msg_in_queue(plci);
9469 channel_flow_control_remove(plci);
9474 plci->notifiedcall = 0;
9476 listen_check(plci->adapter);
9484 /*------------------------------------------------------------------*/
9486 static byte plci_nl_busy(PLCI *plci)
9488 /* only applicable for non-multiplexed protocols */
9489 return (plci->nl_req
9490 || (plci->ncci_ring_list
9491 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9492 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9496 /*------------------------------------------------------------------*/
9497 /* DTMF facilities */
9498 /*------------------------------------------------------------------*/
9507 } dtmf_digit_map[] =
9509 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9510 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9511 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9512 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9513 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9514 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9515 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9516 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9517 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9518 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9519 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9520 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9521 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9522 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9523 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9524 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9525 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9526 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9527 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9528 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9530 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9531 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9532 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9533 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9534 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9535 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9536 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9537 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9538 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9539 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9540 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9541 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9542 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9543 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9544 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9545 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9546 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9547 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9548 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9549 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9550 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9551 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9552 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9553 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9554 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9555 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9556 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9557 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9558 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9559 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9560 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9561 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9562 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9563 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9564 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9565 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9566 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9567 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9568 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9569 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9570 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9571 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9572 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9573 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9574 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9575 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9576 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9577 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9578 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9579 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9580 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9581 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9585 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9590 word min_digit_duration, min_gap_duration;
9592 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9593 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9594 (char *)(FILE_), __LINE__, enable_mask));
9596 if (enable_mask != 0)
9598 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9599 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9600 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9601 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9602 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9603 plci->NData[0].PLength = 5;
9605 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9606 plci->NData[0].PLength += 2;
9607 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9612 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9613 plci->NData[0].PLength = 1;
9615 capidtmf_recv_disable(&(plci->capidtmf_state));
9618 plci->NData[0].P = plci->internal_req_buffer;
9619 plci->NL.X = plci->NData;
9621 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9622 plci->adapter->request(&plci->NL);
9626 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9630 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9631 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9632 (char *)(FILE_), __LINE__, digit_count));
9634 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9635 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9636 PUT_WORD(&plci->internal_req_buffer[1], w);
9637 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9638 PUT_WORD(&plci->internal_req_buffer[3], w);
9639 for (i = 0; i < digit_count; i++)
9642 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9643 && (digit_buffer[i] != dtmf_digit_map[w].character))
9647 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9648 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9650 plci->NData[0].PLength = 5 + digit_count;
9651 plci->NData[0].P = plci->internal_req_buffer;
9652 plci->NL.X = plci->NData;
9654 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9655 plci->adapter->request(&plci->NL);
9659 static void dtmf_rec_clear_config(PLCI *plci)
9662 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9663 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9664 (char *)(FILE_), __LINE__));
9666 plci->dtmf_rec_active = 0;
9667 plci->dtmf_rec_pulse_ms = 0;
9668 plci->dtmf_rec_pause_ms = 0;
9670 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9675 static void dtmf_send_clear_config(PLCI *plci)
9678 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9679 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9680 (char *)(FILE_), __LINE__));
9682 plci->dtmf_send_requests = 0;
9683 plci->dtmf_send_pulse_ms = 0;
9684 plci->dtmf_send_pause_ms = 0;
9688 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9692 UnMapId(Id), (char *)(FILE_), __LINE__));
9694 while (plci->dtmf_send_requests != 0)
9695 dtmf_confirmation(Id, plci);
9699 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9703 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9709 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9713 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9714 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9717 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9719 switch (plci->adjust_b_state)
9721 case ADJUST_B_RESTORE_DTMF_1:
9722 plci->internal_command = plci->adjust_b_command;
9723 if (plci_nl_busy(plci))
9725 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9728 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9729 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9731 case ADJUST_B_RESTORE_DTMF_2:
9732 if ((Rc != OK) && (Rc != OK_FC))
9734 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9735 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9736 Info = _WRONG_STATE;
9746 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9748 word internal_command, Info;
9752 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9753 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9754 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9755 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9759 PUT_WORD(&result[1], DTMF_SUCCESS);
9760 internal_command = plci->internal_command;
9761 plci->internal_command = 0;
9763 switch (plci->dtmf_cmd)
9766 case DTMF_LISTEN_TONE_START:
9768 case DTMF_LISTEN_MF_START:
9771 case DTMF_LISTEN_START:
9772 switch (internal_command)
9775 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9776 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9777 case DTMF_COMMAND_1:
9778 if (adjust_b_process(Id, plci, Rc) != GOOD)
9780 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9781 UnMapId(Id), (char *)(FILE_), __LINE__));
9782 Info = _FACILITY_NOT_SUPPORTED;
9785 if (plci->internal_command)
9787 case DTMF_COMMAND_2:
9788 if (plci_nl_busy(plci))
9790 plci->internal_command = DTMF_COMMAND_2;
9793 plci->internal_command = DTMF_COMMAND_3;
9794 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9796 case DTMF_COMMAND_3:
9797 if ((Rc != OK) && (Rc != OK_FC))
9799 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9800 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9801 Info = _FACILITY_NOT_SUPPORTED;
9805 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9807 plci->dtmf_rec_active |= mask;
9813 case DTMF_LISTEN_TONE_STOP:
9815 case DTMF_LISTEN_MF_STOP:
9818 case DTMF_LISTEN_STOP:
9819 switch (internal_command)
9822 plci->dtmf_rec_active &= ~mask;
9823 if (plci->dtmf_rec_active)
9826 case DTMF_COMMAND_1:
9827 if (plci->dtmf_rec_active)
9829 if (plci_nl_busy (plci))
9831 plci->internal_command = DTMF_COMMAND_1;
9834 plci->dtmf_rec_active &= ~mask;
9835 plci->internal_command = DTMF_COMMAND_2;
9836 dtmf_enable_receiver (plci, false);
9840 case DTMF_COMMAND_2:
9841 if ((Rc != OK) && (Rc != OK_FC))
9843 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9844 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9845 Info = _FACILITY_NOT_SUPPORTED;
9849 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9850 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9851 case DTMF_COMMAND_3:
9852 if (adjust_b_process(Id, plci, Rc) != GOOD)
9854 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9855 UnMapId(Id), (char *)(FILE_), __LINE__));
9856 Info = _FACILITY_NOT_SUPPORTED;
9859 if (plci->internal_command)
9866 case DTMF_SEND_TONE:
9871 case DTMF_DIGITS_SEND:
9872 switch (internal_command)
9875 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9876 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9878 case DTMF_COMMAND_1:
9879 if (adjust_b_process(Id, plci, Rc) != GOOD)
9881 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9882 UnMapId(Id), (char *)(FILE_), __LINE__));
9883 Info = _FACILITY_NOT_SUPPORTED;
9886 if (plci->internal_command)
9888 case DTMF_COMMAND_2:
9889 if (plci_nl_busy(plci))
9891 plci->internal_command = DTMF_COMMAND_2;
9894 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9895 plci->internal_command = DTMF_COMMAND_3;
9896 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9898 case DTMF_COMMAND_3:
9899 if ((Rc != OK) && (Rc != OK_FC))
9901 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9902 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9903 if (plci->dtmf_send_requests != 0)
9904 (plci->dtmf_send_requests)--;
9905 Info = _FACILITY_NOT_SUPPORTED;
9912 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9913 "wws", Info, SELECTOR_DTMF, result);
9917 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9922 API_PARSE dtmf_parms[5];
9925 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9926 UnMapId(Id), (char *)(FILE_), __LINE__));
9930 PUT_WORD(&result[1], DTMF_SUCCESS);
9931 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9933 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9934 UnMapId(Id), (char *)(FILE_), __LINE__));
9935 Info = _FACILITY_NOT_SUPPORTED;
9937 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9939 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9940 UnMapId(Id), (char *)(FILE_), __LINE__));
9941 Info = _WRONG_MESSAGE_FORMAT;
9944 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9945 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9947 if (!((a->requested_options_table[appl->Id - 1])
9948 & (1L << PRIVATE_DTMF_TONE)))
9950 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9951 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9952 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9956 for (i = 0; i < 32; i++)
9958 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9960 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9962 if (dtmf_digit_map[i].listen_mask != 0)
9963 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9968 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9970 if (dtmf_digit_map[i].send_mask != 0)
9971 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9979 else if (plci == NULL)
9981 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9982 UnMapId(Id), (char *)(FILE_), __LINE__));
9983 Info = _WRONG_IDENTIFIER;
9988 || !plci->NL.Id || plci->nl_remove_id)
9990 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9991 UnMapId(Id), (char *)(FILE_), __LINE__));
9992 Info = _WRONG_STATE;
9997 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9999 switch (plci->dtmf_cmd)
10002 case DTMF_LISTEN_TONE_START:
10003 case DTMF_LISTEN_TONE_STOP:
10005 case DTMF_LISTEN_MF_START:
10006 case DTMF_LISTEN_MF_STOP:
10008 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10009 & (1L << PRIVATE_DTMF_TONE)))
10011 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10012 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10013 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10017 case DTMF_LISTEN_START:
10018 case DTMF_LISTEN_STOP:
10019 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10020 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10022 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10023 UnMapId(Id), (char *)(FILE_), __LINE__));
10024 Info = _FACILITY_NOT_SUPPORTED;
10027 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10029 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10031 plci->dtmf_rec_pulse_ms = 0;
10032 plci->dtmf_rec_pause_ms = 0;
10036 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10037 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040 start_internal_command(Id, plci, dtmf_command);
10044 case DTMF_SEND_TONE:
10048 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10049 & (1L << PRIVATE_DTMF_TONE)))
10051 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10052 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10053 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10057 case DTMF_DIGITS_SEND:
10058 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10060 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10061 UnMapId(Id), (char *)(FILE_), __LINE__));
10062 Info = _WRONG_MESSAGE_FORMAT;
10065 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10067 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10068 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10072 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10075 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10076 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10077 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10083 if (j == DTMF_DIGIT_MAP_ENTRIES)
10085 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10086 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10087 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10090 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10092 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10093 UnMapId(Id), (char *)(FILE_), __LINE__));
10094 Info = _WRONG_STATE;
10097 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10098 start_internal_command(Id, plci, dtmf_command);
10102 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10103 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10104 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10108 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10109 "wws", Info, SELECTOR_DTMF, result);
10114 static void dtmf_confirmation(dword Id, PLCI *plci)
10119 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10120 UnMapId(Id), (char *)(FILE_), __LINE__));
10123 PUT_WORD(&result[1], DTMF_SUCCESS);
10124 if (plci->dtmf_send_requests != 0)
10126 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10127 "wws", GOOD, SELECTOR_DTMF, result);
10128 (plci->dtmf_send_requests)--;
10129 for (i = 0; i < plci->dtmf_send_requests; i++)
10130 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10135 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10139 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10140 UnMapId(Id), (char *)(FILE_), __LINE__));
10143 for (i = 1; i < length; i++)
10146 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10147 && ((msg[i] != dtmf_digit_map[j].code)
10148 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10152 if (j < DTMF_DIGIT_MAP_ENTRIES)
10155 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10156 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10157 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10161 for (i = length; i > n + 1; i--)
10162 msg[i] = msg[i - 1];
10166 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10168 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10170 msg[++n] = dtmf_digit_map[j].character;
10176 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10181 /*------------------------------------------------------------------*/
10182 /* DTMF parameters */
10183 /*------------------------------------------------------------------*/
10185 static void dtmf_parameter_write(PLCI *plci)
10188 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10190 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10191 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10192 (char *)(FILE_), __LINE__));
10194 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10195 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10196 for (i = 0; i < plci->dtmf_parameter_length; i++)
10197 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10198 add_p(plci, FTY, parameter_buffer);
10199 sig_req(plci, TEL_CTRL, 0);
10204 static void dtmf_parameter_clear_config(PLCI *plci)
10207 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10208 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10209 (char *)(FILE_), __LINE__));
10211 plci->dtmf_parameter_length = 0;
10215 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10219 UnMapId(Id), (char *)(FILE_), __LINE__));
10224 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10228 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10234 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10238 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10239 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10242 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10243 && (plci->dtmf_parameter_length != 0))
10245 switch (plci->adjust_b_state)
10247 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10248 plci->internal_command = plci->adjust_b_command;
10251 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10254 dtmf_parameter_write(plci);
10255 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10257 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10258 if ((Rc != OK) && (Rc != OK_FC))
10260 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10261 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10262 Info = _WRONG_STATE;
10272 /*------------------------------------------------------------------*/
10273 /* Line interconnect facilities */
10274 /*------------------------------------------------------------------*/
10277 LI_CONFIG *li_config_table;
10278 word li_total_channels;
10281 /*------------------------------------------------------------------*/
10282 /* translate a CHI information element to a channel number */
10283 /* returns 0xff - any channel */
10284 /* 0xfe - chi wrong coding */
10285 /* 0xfd - D-channel */
10286 /* 0x00 - no channel */
10287 /* else channel number / PRI: timeslot */
10288 /* if channels is provided we accept more than one channel. */
10289 /*------------------------------------------------------------------*/
10291 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10300 if (pchannelmap) *pchannelmap = 0;
10301 if (!chi[0]) return 0xff;
10304 if (chi[1] & 0x20) {
10305 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10306 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10307 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10308 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10309 if (chi[1] & 0x08) excl = 0x40;
10311 /* int. id present */
10312 if (chi[1] & 0x40) {
10314 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10315 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318 /* coding standard, Number/Map, Channel Type */
10320 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10321 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10322 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10325 if (chi[p] & 0x10) {
10328 if ((chi[0] - p) == 4) ofs = 0;
10329 else if ((chi[0] - p) == 3) ofs = 1;
10333 for (i = 0; i < 4 && p < chi[0]; i++) {
10338 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10349 ch = chi[p] & 0x3f;
10351 if ((byte)(chi[0] - p) > 30) return 0xfe;
10353 for (i = p; i <= chi[0]; i++) {
10354 if ((chi[i] & 0x7f) > 31) return 0xfe;
10355 map |= (1L << (chi[i] & 0x7f));
10359 if (p != chi[0]) return 0xfe;
10360 if (ch > 31) return 0xfe;
10363 if (chi[p] & 0x40) return 0xfe;
10365 if (pchannelmap) *pchannelmap = map;
10366 else if (map != ((dword)(1L << ch))) return 0xfe;
10367 return (byte)(excl | ch);
10369 else { /* not PRI */
10370 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10371 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10372 if (chi[1] & 0x08) excl = 0x40;
10374 switch (chi[1] | 0x98) {
10375 case 0x98: return 0;
10377 if (pchannelmap) *pchannelmap = 2;
10380 if (pchannelmap) *pchannelmap = 4;
10382 case 0x9b: return 0xff;
10383 case 0x9c: return 0xfd; /* d-ch */
10384 default: return 0xfe;
10390 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10392 DIVA_CAPI_ADAPTER *a;
10397 old_id = plci->li_bchannel_id;
10400 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10401 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10402 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10403 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10404 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10408 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10410 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10411 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10412 plci->li_bchannel_id = bchannel_id & 0x03;
10413 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10415 splci = a->AdvSignalPLCI;
10416 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10418 if ((splci->li_bchannel_id != 0)
10419 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10421 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10423 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10424 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10425 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10426 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10427 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10431 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10435 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10437 mixer_clear_config(plci);
10439 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10440 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10441 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10445 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10447 DIVA_CAPI_ADAPTER *a;
10452 old_id = plci->li_bchannel_id;
10453 ch = chi_to_channel(chi, NULL);
10458 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10459 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10460 plci->li_bchannel_id = (ch & 0x1f) + 1;
10461 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10462 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10466 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10468 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10469 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10470 plci->li_bchannel_id = ch & 0x1f;
10471 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10473 splci = a->AdvSignalPLCI;
10474 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10476 if ((splci->li_bchannel_id != 0)
10477 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10479 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10481 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10482 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10483 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10484 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10485 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10489 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10493 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10494 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10496 mixer_clear_config(plci);
10498 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10499 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10500 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10504 #define MIXER_MAX_DUMP_CHANNELS 34
10506 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10510 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10512 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10513 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10515 for (i = 0; i < li_total_channels; i++)
10517 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10518 if (li_config_table[i].chflags != 0)
10519 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10522 for (j = 0; j < li_total_channels; j++)
10524 if (((li_config_table[i].flag_table[j]) != 0)
10525 || ((li_config_table[j].flag_table[i]) != 0))
10527 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10529 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10530 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10532 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10537 for (i = 0; i < li_total_channels; i++)
10539 for (j = 0; j < li_total_channels; j++)
10541 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10542 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10543 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10546 for (n = 0; n < li_total_channels; n++)
10548 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10550 for (i = 0; i < li_total_channels; i++)
10552 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10554 for (j = 0; j < li_total_channels; j++)
10556 li_config_table[i].coef_table[j] |=
10557 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10563 for (i = 0; i < li_total_channels; i++)
10565 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10567 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10568 for (j = 0; j < li_total_channels; j++)
10570 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10571 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10573 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10574 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10577 for (i = 0; i < li_total_channels; i++)
10579 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10581 for (j = 0; j < li_total_channels; j++)
10583 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10584 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10585 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10586 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10587 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10588 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10589 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10590 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10592 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10594 for (j = 0; j < li_total_channels; j++)
10596 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10598 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10599 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10600 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10606 for (j = 0; j < li_total_channels; j++)
10608 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10609 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10612 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10614 for (j = 0; j < li_total_channels; j++)
10616 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10618 for (n = 0; n < li_total_channels; n++)
10620 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10622 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10623 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10625 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10626 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10627 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10629 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10638 for (i = 0; i < li_total_channels; i++)
10640 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10642 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10643 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10644 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10645 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10646 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10647 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10648 for (j = 0; j < li_total_channels; j++)
10650 if ((li_config_table[i].flag_table[j] &
10651 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10652 || (li_config_table[j].flag_table[i] &
10653 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10655 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10657 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10658 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10659 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10660 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10662 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10664 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10665 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669 for (i = 0; i < li_total_channels; i++)
10671 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10674 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10676 if (j < li_total_channels)
10678 for (j = 0; j < li_total_channels; j++)
10680 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10681 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10682 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10687 n = li_total_channels;
10688 if (n > MIXER_MAX_DUMP_CHANNELS)
10689 n = MIXER_MAX_DUMP_CHANNELS;
10692 for (j = 0; j < n; j++)
10694 if ((j & 0x7) == 0)
10696 p = hex_byte_pack(p, li_config_table[j].curchnl);
10699 dbug(1, dprintf("[%06lx] CURRENT %s",
10700 (dword)(UnMapController(a->Id)), (char *)hex_line));
10702 for (j = 0; j < n; j++)
10704 if ((j & 0x7) == 0)
10706 p = hex_byte_pack(p, li_config_table[j].channel);
10709 dbug(1, dprintf("[%06lx] CHANNEL %s",
10710 (dword)(UnMapController(a->Id)), (char *)hex_line));
10712 for (j = 0; j < n; j++)
10714 if ((j & 0x7) == 0)
10716 p = hex_byte_pack(p, li_config_table[j].chflags);
10719 dbug(1, dprintf("[%06lx] CHFLAG %s",
10720 (dword)(UnMapController(a->Id)), (char *)hex_line));
10721 for (i = 0; i < n; i++)
10724 for (j = 0; j < n; j++)
10726 if ((j & 0x7) == 0)
10728 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10731 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10732 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10734 for (i = 0; i < n; i++)
10737 for (j = 0; j < n; j++)
10739 if ((j & 0x7) == 0)
10741 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10744 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10745 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10754 } mixer_write_prog_pri[] =
10756 { LI_COEF_CH_CH, 0 },
10757 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10758 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10759 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10767 byte xconnect_override;
10768 } mixer_write_prog_bri[] =
10770 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10771 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10772 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10773 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10774 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10775 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10776 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10777 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10778 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10779 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10780 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10781 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10782 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10783 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10784 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10785 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10786 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10787 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10788 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10789 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10790 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10791 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10792 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10793 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10794 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10795 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10796 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10797 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10798 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10799 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10800 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10801 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10802 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10803 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10804 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10805 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10808 static byte mixer_swapped_index_bri[] =
10811 19, /* Alt B to B */
10813 21, /* Alt PC to B */
10815 23, /* Alt IC to B */
10817 25, /* Alt B to PC */
10819 27, /* Alt PC to PC */
10821 29, /* Alt IC to PC */
10823 31, /* Alt B to IC */
10825 33, /* Alt PC to IC */
10827 35, /* Alt IC to IC */
10828 0, /* Alt B to Alt B */
10829 1, /* B to Alt B */
10830 2, /* Alt PC to Alt B */
10831 3, /* PC to Alt B */
10832 4, /* Alt IC to Alt B */
10833 5, /* IC to Alt B */
10834 6, /* Alt B to Alt PC */
10835 7, /* B to Alt PC */
10836 8, /* Alt PC to Alt PC */
10837 9, /* PC to Alt PC */
10838 10, /* Alt IC to Alt PC */
10839 11, /* IC to Alt PC */
10840 12, /* Alt B to Alt IC */
10841 13, /* B to Alt IC */
10842 14, /* Alt PC to Alt IC */
10843 15, /* PC to Alt IC */
10844 16, /* Alt IC to Alt IC */
10845 17 /* IC to Alt IC */
10853 } xconnect_write_prog[] =
10855 { LI_COEF_CH_CH, false, false },
10856 { LI_COEF_CH_PC, false, true },
10857 { LI_COEF_PC_CH, true, false },
10858 { LI_COEF_PC_PC, true, true }
10862 static void xconnect_query_addresses(PLCI *plci)
10864 DIVA_CAPI_ADAPTER *a;
10868 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10869 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10870 (char *)(FILE_), __LINE__));
10873 if (a->li_pri && ((plci->li_bchannel_id == 0)
10874 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10876 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10877 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10878 (char *)(FILE_), __LINE__));
10881 p = plci->internal_req_buffer;
10882 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10883 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10886 *(p++) = (byte)(w >> 8);
10887 w = ch | XCONNECT_CHANNEL_PORT_PC;
10889 *(p++) = (byte)(w >> 8);
10890 plci->NData[0].P = plci->internal_req_buffer;
10891 plci->NData[0].PLength = p - plci->internal_req_buffer;
10892 plci->NL.X = plci->NData;
10893 plci->NL.ReqCh = 0;
10894 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10895 plci->adapter->request(&plci->NL);
10899 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10902 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10903 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10904 (char *)(FILE_), __LINE__, internal_command));
10906 plci->li_write_command = internal_command;
10907 plci->li_write_channel = 0;
10911 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10913 DIVA_CAPI_ADAPTER *a;
10914 word w, n, i, j, r, s, to_ch;
10917 struct xconnect_transfer_address_s *transfer_address;
10918 byte ch_map[MIXER_CHANNELS_BRI];
10920 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10921 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10924 if ((plci->li_bchannel_id == 0)
10925 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10927 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10928 UnMapId(Id), (char *)(FILE_), __LINE__));
10931 i = a->li_base + (plci->li_bchannel_id - 1);
10932 j = plci->li_write_channel;
10933 p = plci->internal_req_buffer;
10936 if ((Rc != OK) && (Rc != OK_FC))
10938 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10939 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10943 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10947 if (j < li_total_channels)
10949 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10951 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10952 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10953 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10954 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10956 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10957 while ((j < li_total_channels)
10959 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10960 || (!li_config_table[j].adapter->li_pri
10961 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10962 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10963 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10964 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10965 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10966 || ((li_config_table[j].adapter->li_base != a->li_base)
10968 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10969 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10970 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10971 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10974 if (j < li_total_channels)
10975 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10978 if (j < li_total_channels)
10980 plci->internal_command = plci->li_write_command;
10981 if (plci_nl_busy(plci))
10983 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10984 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10987 if (li_config_table[j].adapter->li_base != a->li_base)
10990 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10991 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10992 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10993 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10998 if (r & xconnect_write_prog[n].mask)
11000 if (xconnect_write_prog[n].from_pc)
11001 transfer_address = &(li_config_table[j].send_pc);
11003 transfer_address = &(li_config_table[j].send_b);
11004 d = transfer_address->card_address.low;
11006 *(p++) = (byte)(d >> 8);
11007 *(p++) = (byte)(d >> 16);
11008 *(p++) = (byte)(d >> 24);
11009 d = transfer_address->card_address.high;
11011 *(p++) = (byte)(d >> 8);
11012 *(p++) = (byte)(d >> 16);
11013 *(p++) = (byte)(d >> 24);
11014 d = transfer_address->offset;
11016 *(p++) = (byte)(d >> 8);
11017 *(p++) = (byte)(d >> 16);
11018 *(p++) = (byte)(d >> 24);
11019 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11021 *(p++) = (byte)(w >> 8);
11022 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11023 (li_config_table[i].adapter->u_law ?
11024 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11025 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11028 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11031 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11032 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11033 if (n == ARRAY_SIZE(xconnect_write_prog))
11038 if (j < li_total_channels)
11039 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11040 } while ((j < li_total_channels)
11042 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11043 || (!li_config_table[j].adapter->li_pri
11044 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11045 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11046 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11047 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11048 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11049 || ((li_config_table[j].adapter->li_base != a->li_base)
11051 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11052 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11053 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11054 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11056 } while ((j < li_total_channels)
11057 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11059 else if (j == li_total_channels)
11061 plci->internal_command = plci->li_write_command;
11062 if (plci_nl_busy(plci))
11066 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11068 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11069 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11070 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11071 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11073 *(p++) = (byte)(w >> 8);
11077 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11079 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11080 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11082 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11084 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11085 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11086 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11087 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11089 *(p++) = (byte)(w >> 8);
11090 for (j = 0; j < sizeof(ch_map); j += 2)
11092 if (plci->li_bchannel_id == 2)
11094 ch_map[j] = (byte)(j + 1);
11095 ch_map[j + 1] = (byte) j;
11099 ch_map[j] = (byte) j;
11100 ch_map[j + 1] = (byte)(j + 1);
11103 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11105 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11106 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11107 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11109 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11110 mixer_write_prog_bri[n].xconnect_override :
11111 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11112 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11114 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11115 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11121 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11123 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11124 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11125 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11131 j = li_total_channels + 1;
11136 if (j <= li_total_channels)
11138 plci->internal_command = plci->li_write_command;
11139 if (plci_nl_busy(plci))
11141 if (j < a->li_base)
11145 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11147 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11148 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11149 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11150 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11152 *(p++) = (byte)(w >> 8);
11153 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11155 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11156 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11158 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11159 if (w & mixer_write_prog_pri[n].mask)
11161 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11167 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11168 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11170 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11171 if (w & mixer_write_prog_pri[n].mask)
11173 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11174 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11183 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11185 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11186 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11188 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11190 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11191 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11192 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11193 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11195 *(p++) = (byte)(w >> 8);
11196 for (j = 0; j < sizeof(ch_map); j += 2)
11198 if (plci->li_bchannel_id == 2)
11200 ch_map[j] = (byte)(j + 1);
11201 ch_map[j + 1] = (byte) j;
11205 ch_map[j] = (byte) j;
11206 ch_map[j + 1] = (byte)(j + 1);
11209 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11211 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11212 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11213 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11215 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11216 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11217 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11222 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11224 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11225 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11226 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11232 j = li_total_channels + 1;
11235 plci->li_write_channel = j;
11236 if (p != plci->internal_req_buffer)
11238 plci->NData[0].P = plci->internal_req_buffer;
11239 plci->NData[0].PLength = p - plci->internal_req_buffer;
11240 plci->NL.X = plci->NData;
11241 plci->NL.ReqCh = 0;
11242 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11243 plci->adapter->request(&plci->NL);
11249 static void mixer_notify_update(PLCI *plci, byte others)
11251 DIVA_CAPI_ADAPTER *a;
11254 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11256 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11257 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11258 (char *)(FILE_), __LINE__, others));
11261 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11264 plci->li_notify_update = true;
11268 notify_plci = NULL;
11271 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11273 if (i < li_total_channels)
11274 notify_plci = li_config_table[i++].plci;
11278 if ((plci->li_bchannel_id != 0)
11279 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11281 notify_plci = plci;
11284 if ((notify_plci != NULL)
11285 && !notify_plci->li_notify_update
11286 && (notify_plci->appl != NULL)
11287 && (notify_plci->State)
11288 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11290 notify_plci->li_notify_update = true;
11291 ((CAPI_MSG *) msg)->header.length = 18;
11292 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11293 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11294 ((CAPI_MSG *) msg)->header.number = 0;
11295 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11296 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11297 ((CAPI_MSG *) msg)->header.ncci = 0;
11298 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11299 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11300 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11301 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11302 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11303 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11304 if (w != _QUEUE_FULL)
11308 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11309 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11310 (char *)(FILE_), __LINE__,
11311 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11313 notify_plci->li_notify_update = false;
11316 } while (others && (notify_plci != NULL));
11318 plci->li_notify_update = false;
11323 static void mixer_clear_config(PLCI *plci)
11325 DIVA_CAPI_ADAPTER *a;
11328 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11329 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11330 (char *)(FILE_), __LINE__));
11332 plci->li_notify_update = false;
11333 plci->li_plci_b_write_pos = 0;
11334 plci->li_plci_b_read_pos = 0;
11335 plci->li_plci_b_req_pos = 0;
11337 if ((plci->li_bchannel_id != 0)
11338 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11340 i = a->li_base + (plci->li_bchannel_id - 1);
11341 li_config_table[i].curchnl = 0;
11342 li_config_table[i].channel = 0;
11343 li_config_table[i].chflags = 0;
11344 for (j = 0; j < li_total_channels; j++)
11346 li_config_table[j].flag_table[i] = 0;
11347 li_config_table[i].flag_table[j] = 0;
11348 li_config_table[i].coef_table[j] = 0;
11349 li_config_table[j].coef_table[i] = 0;
11353 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11354 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11356 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11357 li_config_table[i].curchnl = 0;
11358 li_config_table[i].channel = 0;
11359 li_config_table[i].chflags = 0;
11360 for (j = 0; j < li_total_channels; j++)
11362 li_config_table[i].flag_table[j] = 0;
11363 li_config_table[j].flag_table[i] = 0;
11364 li_config_table[i].coef_table[j] = 0;
11365 li_config_table[j].coef_table[i] = 0;
11367 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11369 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11370 li_config_table[i].curchnl = 0;
11371 li_config_table[i].channel = 0;
11372 li_config_table[i].chflags = 0;
11373 for (j = 0; j < li_total_channels; j++)
11375 li_config_table[i].flag_table[j] = 0;
11376 li_config_table[j].flag_table[i] = 0;
11377 li_config_table[i].coef_table[j] = 0;
11378 li_config_table[j].coef_table[i] = 0;
11387 static void mixer_prepare_switch(dword Id, PLCI *plci)
11390 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11391 UnMapId(Id), (char *)(FILE_), __LINE__));
11395 mixer_indication_coefs_set(Id, plci);
11396 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11400 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11402 DIVA_CAPI_ADAPTER *a;
11405 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11406 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11409 if ((plci->li_bchannel_id != 0)
11410 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11412 i = a->li_base + (plci->li_bchannel_id - 1);
11413 for (j = 0; j < li_total_channels; j++)
11415 li_config_table[i].coef_table[j] &= 0xf;
11416 li_config_table[j].coef_table[i] &= 0xf;
11419 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11425 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11427 DIVA_CAPI_ADAPTER *a;
11430 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11431 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11435 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11436 && (plci->li_bchannel_id != 0)
11437 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11439 switch (plci->adjust_b_state)
11441 case ADJUST_B_RESTORE_MIXER_1:
11442 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11444 plci->internal_command = plci->adjust_b_command;
11445 if (plci_nl_busy(plci))
11447 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11450 xconnect_query_addresses(plci);
11451 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11454 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11456 case ADJUST_B_RESTORE_MIXER_2:
11457 case ADJUST_B_RESTORE_MIXER_3:
11458 case ADJUST_B_RESTORE_MIXER_4:
11459 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11461 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11462 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11463 Info = _WRONG_STATE;
11468 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11469 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11470 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11471 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11475 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11476 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11477 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11478 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11480 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11482 plci->internal_command = plci->adjust_b_command;
11485 case ADJUST_B_RESTORE_MIXER_5:
11486 xconnect_write_coefs(plci, plci->adjust_b_command);
11487 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11489 case ADJUST_B_RESTORE_MIXER_6:
11490 if (!xconnect_write_coefs_process(Id, plci, Rc))
11492 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11493 UnMapId(Id), (char *)(FILE_), __LINE__));
11494 Info = _FACILITY_NOT_SUPPORTED;
11497 if (plci->internal_command)
11499 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11500 case ADJUST_B_RESTORE_MIXER_7:
11508 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11510 DIVA_CAPI_ADAPTER *a;
11511 word i, internal_command;
11513 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11514 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11518 internal_command = plci->internal_command;
11519 plci->internal_command = 0;
11520 switch (plci->li_cmd)
11522 case LI_REQ_CONNECT:
11523 case LI_REQ_DISCONNECT:
11524 case LI_REQ_SILENT_UPDATE:
11525 switch (internal_command)
11528 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11530 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11531 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11533 case MIXER_COMMAND_1:
11534 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11536 if (adjust_b_process(Id, plci, Rc) != GOOD)
11538 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11539 UnMapId(Id), (char *)(FILE_), __LINE__));
11542 if (plci->internal_command)
11545 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11546 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11547 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11548 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11549 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11551 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11557 mixer_indication_coefs_set(Id, plci);
11558 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11560 case MIXER_COMMAND_2:
11561 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11562 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11563 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11564 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11566 if (!xconnect_write_coefs_process(Id, plci, Rc))
11568 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11569 UnMapId(Id), (char *)(FILE_), __LINE__));
11570 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11574 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11575 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11576 i = (plci->li_plci_b_write_pos == 0) ?
11577 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11578 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11579 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11583 if (plci->internal_command)
11586 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11588 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11589 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11591 case MIXER_COMMAND_3:
11592 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11594 if (adjust_b_process(Id, plci, Rc) != GOOD)
11596 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11597 UnMapId(Id), (char *)(FILE_), __LINE__));
11600 if (plci->internal_command)
11607 if ((plci->li_bchannel_id == 0)
11608 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11610 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11611 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11615 i = a->li_base + (plci->li_bchannel_id - 1);
11616 li_config_table[i].curchnl = plci->li_channel_bits;
11617 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11619 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11620 li_config_table[i].curchnl = plci->li_channel_bits;
11621 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11623 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11624 li_config_table[i].curchnl = plci->li_channel_bits;
11631 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11632 dword plci_b_id, byte connect, dword li_flags)
11634 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11636 DIVA_CAPI_ADAPTER *a_b;
11638 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11639 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11640 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11641 if (!a->li_pri && (plci->tel == ADV_VOICE)
11642 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11644 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11645 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11646 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11653 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11654 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11655 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11657 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11658 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11659 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11668 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11669 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11670 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11671 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11673 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677 if (ch_a_v == ch_b_v)
11679 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11680 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11684 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11686 for (i = 0; i < li_total_channels; i++)
11689 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11692 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11694 for (i = 0; i < li_total_channels; i++)
11697 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11700 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11702 for (i = 0; i < li_total_channels; i++)
11705 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11708 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11710 for (i = 0; i < li_total_channels; i++)
11713 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11717 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11719 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11722 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11724 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11726 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11727 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11728 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11729 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11731 if (li_flags & LI_FLAG_MONITOR_A)
11733 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11734 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11736 if (li_flags & LI_FLAG_MONITOR_B)
11738 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11739 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11741 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11743 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11744 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11746 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11748 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11749 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751 if (li_flags & LI_FLAG_MIX_A)
11753 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11754 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11756 if (li_flags & LI_FLAG_MIX_B)
11758 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11759 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11761 if (ch_a_v != ch_a_s)
11763 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11764 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11766 if (ch_b_v != ch_b_s)
11768 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11769 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11774 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11775 dword plci_b_id, byte connect, dword li_flags)
11777 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11779 DIVA_CAPI_ADAPTER *a_b;
11781 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11782 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11783 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11784 if (!a->li_pri && (plci->tel == ADV_VOICE)
11785 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11787 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11788 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11789 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11796 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11797 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11798 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11800 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11801 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11802 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11811 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11812 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11813 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11815 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11816 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11818 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11828 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11831 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11833 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11835 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11836 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11837 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11838 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11840 if (li_flags & LI2_FLAG_MONITOR_B)
11842 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11843 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11845 if (li_flags & LI2_FLAG_MIX_B)
11847 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11848 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11850 if (li_flags & LI2_FLAG_MONITOR_X)
11851 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11852 if (li_flags & LI2_FLAG_MIX_X)
11853 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11854 if (li_flags & LI2_FLAG_LOOP_B)
11856 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11858 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11861 if (li_flags & LI2_FLAG_LOOP_PC)
11862 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11863 if (li_flags & LI2_FLAG_LOOP_X)
11864 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11865 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11866 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11867 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11868 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11869 if (ch_a_v != ch_a_s)
11871 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11872 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11874 if (ch_b_v != ch_b_s)
11876 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11877 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11882 static word li_check_main_plci(dword Id, PLCI *plci)
11886 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11887 UnMapId(Id), (char *)(FILE_), __LINE__));
11888 return (_WRONG_IDENTIFIER);
11891 || !plci->NL.Id || plci->nl_remove_id
11892 || (plci->li_bchannel_id == 0))
11894 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11895 UnMapId(Id), (char *)(FILE_), __LINE__));
11896 return (_WRONG_STATE);
11898 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11903 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11904 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11909 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11910 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11912 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11913 UnMapId(Id), (char *)(FILE_), __LINE__));
11914 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11918 if ((plci_b_id & 0x7f) != 0)
11920 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11921 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11925 || (((plci_b_id >> 8) & 0xff) == 0)
11926 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11928 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11929 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11930 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11933 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11935 || !plci_b->NL.Id || plci_b->nl_remove_id
11936 || (plci_b->li_bchannel_id == 0))
11938 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11939 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11940 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11943 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11944 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11945 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11946 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11947 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11949 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11950 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11951 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11954 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11955 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11957 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11958 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11959 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11966 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11967 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11972 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11973 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11975 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11976 UnMapId(Id), (char *)(FILE_), __LINE__));
11977 PUT_WORD(p_result, _WRONG_STATE);
11981 if ((plci_b_id & 0x7f) != 0)
11983 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11984 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11988 || (((plci_b_id >> 8) & 0xff) == 0)
11989 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11991 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11992 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11993 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11996 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11998 || !plci_b->NL.Id || plci_b->nl_remove_id
11999 || (plci_b->li_bchannel_id == 0)
12000 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12002 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12003 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12004 PUT_WORD(p_result, _WRONG_STATE);
12007 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12008 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12009 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12010 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12012 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12013 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12014 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12017 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12018 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12020 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12021 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12022 PUT_WORD(p_result, _WRONG_STATE);
12029 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12033 dword d, li_flags, plci_b_id;
12035 API_PARSE li_parms[3];
12036 API_PARSE li_req_parms[3];
12037 API_PARSE li_participant_struct[2];
12038 API_PARSE li_participant_parms[3];
12039 word participant_parms_pos;
12040 byte result_buffer[32];
12043 word plci_b_write_pos;
12045 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12046 UnMapId(Id), (char *)(FILE_), __LINE__));
12049 result = result_buffer;
12050 result_buffer[0] = 0;
12051 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12053 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12054 UnMapId(Id), (char *)(FILE_), __LINE__));
12055 Info = _FACILITY_NOT_SUPPORTED;
12057 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12059 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12060 UnMapId(Id), (char *)(FILE_), __LINE__));
12061 Info = _WRONG_MESSAGE_FORMAT;
12065 result_buffer[0] = 3;
12066 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12067 result_buffer[3] = 0;
12068 switch (GET_WORD(li_parms[0].info))
12070 case LI_GET_SUPPORTED_SERVICES:
12071 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12073 result_buffer[0] = 17;
12074 result_buffer[3] = 14;
12075 PUT_WORD(&result_buffer[4], GOOD);
12077 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12078 d |= LI_CONFERENCING_SUPPORTED;
12079 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12080 d |= LI_MONITORING_SUPPORTED;
12081 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12082 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12083 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12085 PUT_DWORD(&result_buffer[6], d);
12086 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12089 for (i = 0; i < li_total_channels; i++)
12091 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12092 && (li_config_table[i].adapter->li_pri
12093 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12101 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12103 PUT_DWORD(&result_buffer[10], d / 2);
12104 PUT_DWORD(&result_buffer[14], d);
12108 result_buffer[0] = 25;
12109 result_buffer[3] = 22;
12110 PUT_WORD(&result_buffer[4], GOOD);
12111 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12112 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12113 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12114 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12115 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12116 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12117 d |= LI2_PC_LOOPING_SUPPORTED;
12118 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12119 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12120 PUT_DWORD(&result_buffer[6], d);
12121 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12122 PUT_DWORD(&result_buffer[10], d / 2);
12123 PUT_DWORD(&result_buffer[14], d - 1);
12124 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12127 for (i = 0; i < li_total_channels; i++)
12129 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12130 && (li_config_table[i].adapter->li_pri
12131 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12137 PUT_DWORD(&result_buffer[18], d / 2);
12138 PUT_DWORD(&result_buffer[22], d - 1);
12142 case LI_REQ_CONNECT:
12143 if (li_parms[1].length == 8)
12145 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12146 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12148 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12149 UnMapId(Id), (char *)(FILE_), __LINE__));
12150 Info = _WRONG_MESSAGE_FORMAT;
12153 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12154 li_flags = GET_DWORD(li_req_parms[1].info);
12155 Info = li_check_main_plci(Id, plci);
12156 result_buffer[0] = 9;
12157 result_buffer[3] = 6;
12158 PUT_DWORD(&result_buffer[4], plci_b_id);
12159 PUT_WORD(&result_buffer[8], GOOD);
12162 result = plci->saved_msg.info;
12163 for (i = 0; i <= result_buffer[0]; i++)
12164 result[i] = result_buffer[i];
12165 plci_b_write_pos = plci->li_plci_b_write_pos;
12166 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12167 if (plci_b == NULL)
12169 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12170 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12171 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12172 plci->li_plci_b_write_pos = plci_b_write_pos;
12176 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12177 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12179 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12180 UnMapId(Id), (char *)(FILE_), __LINE__));
12181 Info = _WRONG_MESSAGE_FORMAT;
12184 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12185 Info = li_check_main_plci(Id, plci);
12186 result_buffer[0] = 7;
12187 result_buffer[3] = 4;
12188 PUT_WORD(&result_buffer[4], Info);
12189 result_buffer[6] = 0;
12192 result = plci->saved_msg.info;
12193 for (i = 0; i <= result_buffer[0]; i++)
12194 result[i] = result_buffer[i];
12195 plci_b_write_pos = plci->li_plci_b_write_pos;
12196 participant_parms_pos = 0;
12198 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12199 while (participant_parms_pos < li_req_parms[1].length)
12201 result[result_pos] = 6;
12203 PUT_DWORD(&result[result_pos - 6], 0);
12204 PUT_WORD(&result[result_pos - 2], GOOD);
12205 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12206 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12208 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12209 UnMapId(Id), (char *)(FILE_), __LINE__));
12210 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12213 if (api_parse(&li_participant_struct[0].info[1],
12214 li_participant_struct[0].length, "dd", li_participant_parms))
12216 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12217 UnMapId(Id), (char *)(FILE_), __LINE__));
12218 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12221 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12222 li_flags = GET_DWORD(li_participant_parms[1].info);
12223 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12224 if (sizeof(result) - result_pos < 7)
12226 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12227 UnMapId(Id), (char *)(FILE_), __LINE__));
12228 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12231 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12232 if (plci_b != NULL)
12234 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12235 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12236 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12237 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12238 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12240 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12241 (&li_req_parms[1].info[1]));
12243 result[0] = (byte)(result_pos - 1);
12244 result[3] = (byte)(result_pos - 4);
12245 result[6] = (byte)(result_pos - 7);
12246 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12247 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12248 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12250 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12251 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12254 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12255 plci->li_plci_b_write_pos = plci_b_write_pos;
12257 mixer_calculate_coefs(a);
12258 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12259 mixer_notify_update(plci, true);
12260 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12261 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12263 plci->li_cmd = GET_WORD(li_parms[0].info);
12264 start_internal_command(Id, plci, mixer_command);
12267 case LI_REQ_DISCONNECT:
12268 if (li_parms[1].length == 4)
12270 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12271 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12273 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12274 UnMapId(Id), (char *)(FILE_), __LINE__));
12275 Info = _WRONG_MESSAGE_FORMAT;
12278 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12279 Info = li_check_main_plci(Id, plci);
12280 result_buffer[0] = 9;
12281 result_buffer[3] = 6;
12282 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12283 PUT_WORD(&result_buffer[8], GOOD);
12286 result = plci->saved_msg.info;
12287 for (i = 0; i <= result_buffer[0]; i++)
12288 result[i] = result_buffer[i];
12289 plci_b_write_pos = plci->li_plci_b_write_pos;
12290 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12291 if (plci_b == NULL)
12293 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12294 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12295 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12296 plci->li_plci_b_write_pos = plci_b_write_pos;
12300 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12301 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12303 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12304 UnMapId(Id), (char *)(FILE_), __LINE__));
12305 Info = _WRONG_MESSAGE_FORMAT;
12308 Info = li_check_main_plci(Id, plci);
12309 result_buffer[0] = 7;
12310 result_buffer[3] = 4;
12311 PUT_WORD(&result_buffer[4], Info);
12312 result_buffer[6] = 0;
12315 result = plci->saved_msg.info;
12316 for (i = 0; i <= result_buffer[0]; i++)
12317 result[i] = result_buffer[i];
12318 plci_b_write_pos = plci->li_plci_b_write_pos;
12319 participant_parms_pos = 0;
12321 while (participant_parms_pos < li_req_parms[0].length)
12323 result[result_pos] = 6;
12325 PUT_DWORD(&result[result_pos - 6], 0);
12326 PUT_WORD(&result[result_pos - 2], GOOD);
12327 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12328 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12330 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12331 UnMapId(Id), (char *)(FILE_), __LINE__));
12332 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12335 if (api_parse(&li_participant_struct[0].info[1],
12336 li_participant_struct[0].length, "d", li_participant_parms))
12338 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12339 UnMapId(Id), (char *)(FILE_), __LINE__));
12340 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12343 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12344 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12345 if (sizeof(result) - result_pos < 7)
12347 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12348 UnMapId(Id), (char *)(FILE_), __LINE__));
12349 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12352 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12353 if (plci_b != NULL)
12355 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12356 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12357 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12359 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12360 (&li_req_parms[0].info[1]));
12362 result[0] = (byte)(result_pos - 1);
12363 result[3] = (byte)(result_pos - 4);
12364 result[6] = (byte)(result_pos - 7);
12365 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12366 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12367 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12369 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12370 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12373 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12374 plci->li_plci_b_write_pos = plci_b_write_pos;
12376 mixer_calculate_coefs(a);
12377 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12378 mixer_notify_update(plci, true);
12379 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12380 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12382 plci->li_cmd = GET_WORD(li_parms[0].info);
12383 start_internal_command(Id, plci, mixer_command);
12386 case LI_REQ_SILENT_UPDATE:
12387 if (!plci || !plci->State
12388 || !plci->NL.Id || plci->nl_remove_id
12389 || (plci->li_bchannel_id == 0)
12390 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12392 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12393 UnMapId(Id), (char *)(FILE_), __LINE__));
12396 plci_b_write_pos = plci->li_plci_b_write_pos;
12397 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12398 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12400 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12401 UnMapId(Id), (char *)(FILE_), __LINE__));
12404 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12405 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12406 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12408 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12409 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12412 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12413 plci->li_plci_b_write_pos = plci_b_write_pos;
12414 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12416 plci->li_cmd = GET_WORD(li_parms[0].info);
12417 start_internal_command(Id, plci, mixer_command);
12421 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12422 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12423 Info = _FACILITY_NOT_SUPPORTED;
12426 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12427 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12432 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12437 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12438 UnMapId(Id), (char *)(FILE_), __LINE__));
12440 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12444 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12445 if (!(d & LI_PLCI_B_SKIP_FLAG))
12447 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12449 if (d & LI_PLCI_B_DISC_FLAG)
12452 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12454 PUT_WORD(&result[4], _LI_USER_INITIATED);
12459 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12461 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12466 if (d & LI_PLCI_B_DISC_FLAG)
12469 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12471 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12472 PUT_WORD(&result[8], _LI_USER_INITIATED);
12477 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12479 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12482 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12483 "ws", SELECTOR_LINE_INTERCONNECT, result);
12485 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12486 0 : plci->li_plci_b_read_pos + 1;
12487 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12492 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12495 struct xconnect_transfer_address_s s, *p;
12496 DIVA_CAPI_ADAPTER *a;
12498 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12499 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12503 for (i = 1; i < length; i += 16)
12505 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12506 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12507 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12508 ch = msg[i + 12] | (msg[i + 13] << 8);
12509 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12510 if (!a->li_pri && (plci->li_bchannel_id == 2))
12513 if (ch & XCONNECT_CHANNEL_PORT_PC)
12514 p = &(li_config_table[j].send_pc);
12516 p = &(li_config_table[j].send_b);
12517 p->card_address.low = s.card_address.low;
12518 p->card_address.high = s.card_address.high;
12519 p->offset = s.offset;
12520 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12522 if (plci->internal_command_queue[0]
12523 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12524 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12525 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12527 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12528 if (!plci->internal_command)
12529 next_internal_command(Id, plci);
12531 mixer_notify_update(plci, true);
12535 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12538 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12539 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12544 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12546 word plci_b_write_pos;
12548 plci_b_write_pos = plci->li_plci_b_write_pos;
12549 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12550 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12552 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12553 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12554 (char *)(FILE_), __LINE__));
12557 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12558 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12559 plci->li_plci_b_write_pos = plci_b_write_pos;
12564 static void mixer_remove(PLCI *plci)
12566 DIVA_CAPI_ADAPTER *a;
12571 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12572 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12573 (char *)(FILE_), __LINE__));
12576 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12577 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12579 if ((plci->li_bchannel_id != 0)
12580 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12582 i = a->li_base + (plci->li_bchannel_id - 1);
12583 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12585 for (j = 0; j < li_total_channels; j++)
12587 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12588 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12590 notify_plci = li_config_table[j].plci;
12591 if ((notify_plci != NULL)
12592 && (notify_plci != plci)
12593 && (notify_plci->appl != NULL)
12594 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12595 && (notify_plci->State)
12596 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12598 mixer_notify_source_removed(notify_plci, plci_b_id);
12602 mixer_clear_config(plci);
12603 mixer_calculate_coefs(a);
12604 mixer_notify_update(plci, true);
12606 li_config_table[i].plci = NULL;
12607 plci->li_bchannel_id = 0;
12613 /*------------------------------------------------------------------*/
12614 /* Echo canceller facilities */
12615 /*------------------------------------------------------------------*/
12618 static void ec_write_parameters(PLCI *plci)
12621 byte parameter_buffer[6];
12623 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12624 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12625 (char *)(FILE_), __LINE__));
12627 parameter_buffer[0] = 5;
12628 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12629 PUT_WORD(¶meter_buffer[2], plci->ec_idi_options);
12630 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12631 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12632 PUT_WORD(¶meter_buffer[4], w);
12633 add_p(plci, FTY, parameter_buffer);
12634 sig_req(plci, TEL_CTRL, 0);
12639 static void ec_clear_config(PLCI *plci)
12642 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12643 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12644 (char *)(FILE_), __LINE__));
12646 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12647 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12648 plci->ec_tail_length = 0;
12652 static void ec_prepare_switch(dword Id, PLCI *plci)
12655 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12656 UnMapId(Id), (char *)(FILE_), __LINE__));
12661 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12664 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12665 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12671 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12675 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12676 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12679 if (plci->B1_facilities & B1_FACILITY_EC)
12681 switch (plci->adjust_b_state)
12683 case ADJUST_B_RESTORE_EC_1:
12684 plci->internal_command = plci->adjust_b_command;
12687 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12690 ec_write_parameters(plci);
12691 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12693 case ADJUST_B_RESTORE_EC_2:
12694 if ((Rc != OK) && (Rc != OK_FC))
12696 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12697 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12698 Info = _WRONG_STATE;
12708 static void ec_command(dword Id, PLCI *plci, byte Rc)
12710 word internal_command, Info;
12713 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12714 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12715 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12718 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12721 PUT_WORD(&result[1], EC_SUCCESS);
12726 PUT_WORD(&result[1], plci->ec_cmd);
12728 PUT_WORD(&result[4], GOOD);
12730 internal_command = plci->internal_command;
12731 plci->internal_command = 0;
12732 switch (plci->ec_cmd)
12734 case EC_ENABLE_OPERATION:
12735 case EC_FREEZE_COEFFICIENTS:
12736 case EC_RESUME_COEFFICIENT_UPDATE:
12737 case EC_RESET_COEFFICIENTS:
12738 switch (internal_command)
12741 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12742 B1_FACILITY_EC), EC_COMMAND_1);
12744 if (adjust_b_process(Id, plci, Rc) != GOOD)
12746 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12747 UnMapId(Id), (char *)(FILE_), __LINE__));
12748 Info = _FACILITY_NOT_SUPPORTED;
12751 if (plci->internal_command)
12756 plci->internal_command = EC_COMMAND_2;
12759 plci->internal_command = EC_COMMAND_3;
12760 ec_write_parameters(plci);
12763 if ((Rc != OK) && (Rc != OK_FC))
12765 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12766 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12767 Info = _FACILITY_NOT_SUPPORTED;
12774 case EC_DISABLE_OPERATION:
12775 switch (internal_command)
12779 if (plci->B1_facilities & B1_FACILITY_EC)
12783 plci->internal_command = EC_COMMAND_1;
12786 plci->internal_command = EC_COMMAND_2;
12787 ec_write_parameters(plci);
12792 if ((Rc != OK) && (Rc != OK_FC))
12794 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12795 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12796 Info = _FACILITY_NOT_SUPPORTED;
12799 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12800 ~B1_FACILITY_EC), EC_COMMAND_3);
12802 if (adjust_b_process(Id, plci, Rc) != GOOD)
12804 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12805 UnMapId(Id), (char *)(FILE_), __LINE__));
12806 Info = _FACILITY_NOT_SUPPORTED;
12809 if (plci->internal_command)
12815 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12816 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12817 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12821 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12825 API_PARSE ec_parms[3];
12828 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12829 UnMapId(Id), (char *)(FILE_), __LINE__));
12833 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12835 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12836 UnMapId(Id), (char *)(FILE_), __LINE__));
12837 Info = _FACILITY_NOT_SUPPORTED;
12841 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12843 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12845 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12846 UnMapId(Id), (char *)(FILE_), __LINE__));
12847 Info = _WRONG_MESSAGE_FORMAT;
12853 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12854 UnMapId(Id), (char *)(FILE_), __LINE__));
12855 Info = _WRONG_IDENTIFIER;
12857 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12859 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12860 UnMapId(Id), (char *)(FILE_), __LINE__));
12861 Info = _WRONG_STATE;
12866 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12867 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12869 PUT_WORD(&result[1], EC_SUCCESS);
12870 if (msg[1].length >= 4)
12872 opt = GET_WORD(&ec_parms[0].info[2]);
12873 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12874 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12875 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12876 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12877 if (opt & EC_DETECT_DISABLE_TONE)
12878 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12879 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12880 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12881 if (msg[1].length >= 6)
12883 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12886 switch (plci->ec_cmd)
12888 case EC_ENABLE_OPERATION:
12889 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12890 start_internal_command(Id, plci, ec_command);
12893 case EC_DISABLE_OPERATION:
12894 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12895 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12896 LEC_RESET_COEFFICIENTS;
12897 start_internal_command(Id, plci, ec_command);
12900 case EC_FREEZE_COEFFICIENTS:
12901 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12902 start_internal_command(Id, plci, ec_command);
12905 case EC_RESUME_COEFFICIENT_UPDATE:
12906 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12907 start_internal_command(Id, plci, ec_command);
12910 case EC_RESET_COEFFICIENTS:
12911 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12912 start_internal_command(Id, plci, ec_command);
12916 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12917 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12918 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12925 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12927 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12928 UnMapId(Id), (char *)(FILE_), __LINE__));
12929 Info = _WRONG_MESSAGE_FORMAT;
12933 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12936 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12938 PUT_WORD(&result[4], GOOD);
12939 PUT_WORD(&result[6], 0x0007);
12940 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12941 PUT_WORD(&result[10], 0);
12943 else if (plci == NULL)
12945 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12946 UnMapId(Id), (char *)(FILE_), __LINE__));
12947 Info = _WRONG_IDENTIFIER;
12949 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12951 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12952 UnMapId(Id), (char *)(FILE_), __LINE__));
12953 Info = _WRONG_STATE;
12958 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12959 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12961 PUT_WORD(&result[1], plci->ec_cmd);
12963 PUT_WORD(&result[4], GOOD);
12964 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12965 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12966 plci->ec_tail_length = 0;
12967 if (ec_parms[1].length >= 2)
12969 opt = GET_WORD(&ec_parms[1].info[1]);
12970 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12971 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12972 if (opt & EC_DETECT_DISABLE_TONE)
12973 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12974 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12975 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12976 if (ec_parms[1].length >= 4)
12978 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12981 switch (plci->ec_cmd)
12983 case EC_ENABLE_OPERATION:
12984 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12985 start_internal_command(Id, plci, ec_command);
12988 case EC_DISABLE_OPERATION:
12989 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12990 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12991 LEC_RESET_COEFFICIENTS;
12992 start_internal_command(Id, plci, ec_command);
12996 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12997 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12998 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13004 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13005 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13006 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13011 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13015 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13016 UnMapId(Id), (char *)(FILE_), __LINE__));
13018 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13020 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13023 PUT_WORD(&result[1], 0);
13026 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13027 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13029 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13030 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13032 case LEC_DISABLE_RELEASED:
13033 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13040 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13042 PUT_WORD(&result[4], 0);
13045 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13046 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13048 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13049 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13051 case LEC_DISABLE_RELEASED:
13052 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13056 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13057 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13063 /*------------------------------------------------------------------*/
13064 /* Advanced voice */
13065 /*------------------------------------------------------------------*/
13067 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13069 DIVA_CAPI_ADAPTER *a;
13074 byte ch_map[MIXER_CHANNELS_BRI];
13076 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13078 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13079 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13080 (char *)(FILE_), __LINE__, write_command));
13083 p = coef_buffer + 1;
13084 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13086 while (i + sizeof(word) <= a->adv_voice_coef_length)
13088 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13092 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13094 PUT_WORD(p, 0x8000);
13099 if (!a->li_pri && (plci->li_bchannel_id == 0))
13101 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13103 plci->li_bchannel_id = 1;
13104 li_config_table[a->li_base].plci = plci;
13105 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13106 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13107 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13109 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13111 plci->li_bchannel_id = 2;
13112 li_config_table[a->li_base + 1].plci = plci;
13113 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13114 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13115 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13118 if (!a->li_pri && (plci->li_bchannel_id != 0)
13119 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121 i = a->li_base + (plci->li_bchannel_id - 1);
13122 switch (write_command)
13124 case ADV_VOICE_WRITE_ACTIVATION:
13125 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13126 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13127 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13129 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13132 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13134 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13135 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13136 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13137 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13139 mixer_calculate_coefs(a);
13140 li_config_table[i].curchnl = li_config_table[i].channel;
13141 li_config_table[j].curchnl = li_config_table[j].channel;
13142 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13143 li_config_table[k].curchnl = li_config_table[k].channel;
13146 case ADV_VOICE_WRITE_DEACTIVATION:
13147 for (j = 0; j < li_total_channels; j++)
13149 li_config_table[i].flag_table[j] = 0;
13150 li_config_table[j].flag_table[i] = 0;
13152 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13153 for (j = 0; j < li_total_channels; j++)
13155 li_config_table[k].flag_table[j] = 0;
13156 li_config_table[j].flag_table[k] = 0;
13158 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13160 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13161 for (j = 0; j < li_total_channels; j++)
13163 li_config_table[k].flag_table[j] = 0;
13164 li_config_table[j].flag_table[k] = 0;
13167 mixer_calculate_coefs(a);
13170 if (plci->B1_facilities & B1_FACILITY_MIXER)
13173 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13174 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13175 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13176 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13177 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13178 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13180 *(p++) = (byte)(w >> 8);
13181 for (j = 0; j < sizeof(ch_map); j += 2)
13183 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13184 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13186 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13188 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13189 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13190 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13192 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13193 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13194 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13198 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13199 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13205 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206 *(p++) = a->adv_voice_coef_buffer[i];
13212 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213 *(p++) = a->adv_voice_coef_buffer[i];
13215 coef_buffer[0] = (p - coef_buffer) - 1;
13216 add_p(plci, FTY, coef_buffer);
13217 sig_req(plci, TEL_CTRL, 0);
13222 static void adv_voice_clear_config(PLCI *plci)
13224 DIVA_CAPI_ADAPTER *a;
13229 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13230 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13231 (char *)(FILE_), __LINE__));
13234 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13236 a->adv_voice_coef_length = 0;
13238 if (!a->li_pri && (plci->li_bchannel_id != 0)
13239 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13241 i = a->li_base + (plci->li_bchannel_id - 1);
13242 li_config_table[i].curchnl = 0;
13243 li_config_table[i].channel = 0;
13244 li_config_table[i].chflags = 0;
13245 for (j = 0; j < li_total_channels; j++)
13247 li_config_table[i].flag_table[j] = 0;
13248 li_config_table[j].flag_table[i] = 0;
13249 li_config_table[i].coef_table[j] = 0;
13250 li_config_table[j].coef_table[i] = 0;
13252 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13253 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13254 li_config_table[i].curchnl = 0;
13255 li_config_table[i].channel = 0;
13256 li_config_table[i].chflags = 0;
13257 for (j = 0; j < li_total_channels; j++)
13259 li_config_table[i].flag_table[j] = 0;
13260 li_config_table[j].flag_table[i] = 0;
13261 li_config_table[i].coef_table[j] = 0;
13262 li_config_table[j].coef_table[i] = 0;
13264 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13266 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13267 li_config_table[i].curchnl = 0;
13268 li_config_table[i].channel = 0;
13269 li_config_table[i].chflags = 0;
13270 for (j = 0; j < li_total_channels; j++)
13272 li_config_table[i].flag_table[j] = 0;
13273 li_config_table[j].flag_table[i] = 0;
13274 li_config_table[i].coef_table[j] = 0;
13275 li_config_table[j].coef_table[i] = 0;
13284 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13287 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13288 UnMapId(Id), (char *)(FILE_), __LINE__));
13293 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13296 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13297 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13303 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13305 DIVA_CAPI_ADAPTER *a;
13308 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13309 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13313 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13314 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13316 switch (plci->adjust_b_state)
13318 case ADJUST_B_RESTORE_VOICE_1:
13319 plci->internal_command = plci->adjust_b_command;
13322 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13325 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13326 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13328 case ADJUST_B_RESTORE_VOICE_2:
13329 if ((Rc != OK) && (Rc != OK_FC))
13331 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13332 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13333 Info = _WRONG_STATE;
13345 /*------------------------------------------------------------------*/
13346 /* B1 resource switching */
13347 /*------------------------------------------------------------------*/
13349 static byte b1_facilities_table[] =
13351 0x00, /* 0 No bchannel resources */
13352 0x00, /* 1 Codec (automatic law) */
13353 0x00, /* 2 Codec (A-law) */
13354 0x00, /* 3 Codec (y-law) */
13355 0x00, /* 4 HDLC for X.21 */
13357 0x00, /* 6 External Device 0 */
13358 0x00, /* 7 External Device 1 */
13359 0x00, /* 8 HDLC 56k */
13360 0x00, /* 9 Transparent */
13361 0x00, /* 10 Loopback to network */
13362 0x00, /* 11 Test pattern to net */
13363 0x00, /* 12 Rate adaptation sync */
13364 0x00, /* 13 Rate adaptation async */
13365 0x00, /* 14 R-Interface */
13366 0x00, /* 15 HDLC 128k leased line */
13368 0x00, /* 17 Modem async */
13369 0x00, /* 18 Modem sync HDLC */
13370 0x00, /* 19 V.110 async HDLC */
13371 0x12, /* 20 Adv voice (Trans,mixer) */
13372 0x00, /* 21 Codec connected to IC */
13373 0x0c, /* 22 Trans,DTMF */
13374 0x1e, /* 23 Trans,DTMF+mixer */
13375 0x1f, /* 24 Trans,DTMF+mixer+local */
13376 0x13, /* 25 Trans,mixer+local */
13377 0x12, /* 26 HDLC,mixer */
13378 0x12, /* 27 HDLC 56k,mixer */
13379 0x2c, /* 28 Trans,LEC+DTMF */
13380 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13381 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13382 0x2c, /* 31 RTP,LEC+DTMF */
13383 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13384 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13385 0x00, /* 34 Signaling task */
13386 0x00, /* 35 PIAFS */
13387 0x0c, /* 36 Trans,DTMF+TONE */
13388 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13389 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13393 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13395 word b1_facilities;
13397 b1_facilities = b1_facilities_table[b1_resource];
13398 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13401 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13402 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13405 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13406 b1_facilities |= B1_FACILITY_DTMFX;
13407 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13408 b1_facilities |= B1_FACILITY_DTMFR;
13411 if ((b1_resource == 17) || (b1_resource == 18))
13413 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13414 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13417 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13418 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13419 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13421 return (b1_facilities);
13425 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13429 switch (b1_resource)
13433 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13459 if (b1_facilities & B1_FACILITY_EC)
13461 if (b1_facilities & B1_FACILITY_LOCAL)
13463 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13469 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13470 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13471 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13473 if (b1_facilities & B1_FACILITY_LOCAL)
13475 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13481 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13482 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13483 || ((b1_facilities & B1_FACILITY_DTMFR)
13484 && ((b1_facilities & B1_FACILITY_MIXER)
13485 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13486 || ((b1_facilities & B1_FACILITY_DTMFX)
13487 && ((b1_facilities & B1_FACILITY_MIXER)
13488 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13490 if (b1_facilities & B1_FACILITY_LOCAL)
13492 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13499 if (b1_facilities & B1_FACILITY_LOCAL)
13501 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13511 if (b1_facilities & B1_FACILITY_LOCAL)
13513 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13522 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13523 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13524 (char *)(FILE_), __LINE__,
13525 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13530 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13532 word removed_facilities;
13534 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13535 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13536 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13537 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13539 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13540 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13542 if (removed_facilities & B1_FACILITY_EC)
13543 ec_clear_config(plci);
13546 if (removed_facilities & B1_FACILITY_DTMFR)
13548 dtmf_rec_clear_config(plci);
13549 dtmf_parameter_clear_config(plci);
13551 if (removed_facilities & B1_FACILITY_DTMFX)
13552 dtmf_send_clear_config(plci);
13555 if (removed_facilities & B1_FACILITY_MIXER)
13556 mixer_clear_config(plci);
13558 if (removed_facilities & B1_FACILITY_VOICE)
13559 adv_voice_clear_config(plci);
13560 plci->B1_facilities = new_b1_facilities;
13564 static void adjust_b_clear(PLCI *plci)
13567 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13568 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13569 (char *)(FILE_), __LINE__));
13571 plci->adjust_b_restore = false;
13575 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13582 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13583 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13586 switch (plci->adjust_b_state)
13588 case ADJUST_B_START:
13589 if ((plci->adjust_b_parms_msg == NULL)
13590 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13591 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13592 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13594 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13595 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13596 if (b1_resource == plci->B1_resource)
13598 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13601 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13603 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13604 UnMapId(Id), (char *)(FILE_), __LINE__,
13605 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13606 Info = _WRONG_STATE;
13610 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13613 mixer_prepare_switch(Id, plci);
13616 dtmf_prepare_switch(Id, plci);
13617 dtmf_parameter_prepare_switch(Id, plci);
13620 ec_prepare_switch(Id, plci);
13622 adv_voice_prepare_switch(Id, plci);
13624 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13626 case ADJUST_B_SAVE_MIXER_1:
13627 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13630 Info = mixer_save_config(Id, plci, Rc);
13631 if ((Info != GOOD) || plci->internal_command)
13635 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13637 case ADJUST_B_SAVE_DTMF_1:
13638 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13641 Info = dtmf_save_config(Id, plci, Rc);
13642 if ((Info != GOOD) || plci->internal_command)
13646 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13647 case ADJUST_B_REMOVE_L23_1:
13648 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13649 && plci->NL.Id && !plci->nl_remove_id)
13651 plci->internal_command = plci->adjust_b_command;
13652 if (plci->adjust_b_ncci != 0)
13654 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13655 while (ncci_ptr->data_pending)
13657 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13658 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13660 while (ncci_ptr->data_ack_pending)
13661 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13663 nl_req_ncci(plci, REMOVE,
13664 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13666 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13669 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13671 case ADJUST_B_REMOVE_L23_2:
13672 if ((Rc != OK) && (Rc != OK_FC))
13674 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13675 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13676 Info = _WRONG_STATE;
13679 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13681 if (plci_nl_busy(plci))
13683 plci->internal_command = plci->adjust_b_command;
13687 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13689 case ADJUST_B_SAVE_EC_1:
13690 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13693 Info = ec_save_config(Id, plci, Rc);
13694 if ((Info != GOOD) || plci->internal_command)
13698 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13700 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13701 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13704 Info = dtmf_parameter_save_config(Id, plci, Rc);
13705 if ((Info != GOOD) || plci->internal_command)
13709 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13711 case ADJUST_B_SAVE_VOICE_1:
13712 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13714 Info = adv_voice_save_config(Id, plci, Rc);
13715 if ((Info != GOOD) || plci->internal_command)
13718 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13719 case ADJUST_B_SWITCH_L1_1:
13720 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13724 plci->internal_command = plci->adjust_b_command;
13727 if (plci->adjust_b_parms_msg != NULL)
13728 api_load_msg(plci->adjust_b_parms_msg, bp);
13730 api_load_msg(&plci->B_protocol, bp);
13731 Info = add_b1(plci, bp,
13732 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13733 plci->adjust_b_facilities);
13736 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13737 UnMapId(Id), (char *)(FILE_), __LINE__,
13738 plci->B1_resource, plci->adjust_b_facilities));
13741 plci->internal_command = plci->adjust_b_command;
13742 sig_req(plci, RESOURCES, 0);
13744 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13747 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13749 case ADJUST_B_SWITCH_L1_2:
13750 if ((Rc != OK) && (Rc != OK_FC))
13752 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13753 UnMapId(Id), (char *)(FILE_), __LINE__,
13754 Rc, plci->B1_resource, plci->adjust_b_facilities));
13755 Info = _WRONG_STATE;
13758 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13760 case ADJUST_B_RESTORE_VOICE_1:
13761 case ADJUST_B_RESTORE_VOICE_2:
13762 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13764 Info = adv_voice_restore_config(Id, plci, Rc);
13765 if ((Info != GOOD) || plci->internal_command)
13768 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13771 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13772 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13775 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13776 if ((Info != GOOD) || plci->internal_command)
13780 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13782 case ADJUST_B_RESTORE_EC_1:
13783 case ADJUST_B_RESTORE_EC_2:
13784 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13787 Info = ec_restore_config(Id, plci, Rc);
13788 if ((Info != GOOD) || plci->internal_command)
13792 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13793 case ADJUST_B_ASSIGN_L23_1:
13794 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13796 if (plci_nl_busy(plci))
13798 plci->internal_command = plci->adjust_b_command;
13801 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13802 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13803 if (plci->adjust_b_parms_msg != NULL)
13804 api_load_msg(plci->adjust_b_parms_msg, bp);
13806 api_load_msg(&plci->B_protocol, bp);
13807 Info = add_b23(plci, bp);
13810 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13811 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13814 plci->internal_command = plci->adjust_b_command;
13815 nl_req_ncci(plci, ASSIGN, 0);
13817 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13820 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13822 case ADJUST_B_ASSIGN_L23_2:
13823 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13825 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13826 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13827 Info = _WRONG_STATE;
13830 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13832 if (Rc != ASSIGN_OK)
13834 plci->internal_command = plci->adjust_b_command;
13838 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13840 plci->adjust_b_restore = true;
13843 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13844 case ADJUST_B_CONNECT_1:
13845 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13847 plci->internal_command = plci->adjust_b_command;
13848 if (plci_nl_busy(plci))
13850 nl_req_ncci(plci, N_CONNECT, 0);
13852 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13855 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13857 case ADJUST_B_CONNECT_2:
13858 case ADJUST_B_CONNECT_3:
13859 case ADJUST_B_CONNECT_4:
13860 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13862 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13863 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13864 Info = _WRONG_STATE;
13869 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13871 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13872 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13874 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13876 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13877 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13881 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13883 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13884 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13886 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13888 plci->internal_command = plci->adjust_b_command;
13892 case ADJUST_B_RESTORE_DTMF_1:
13893 case ADJUST_B_RESTORE_DTMF_2:
13894 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13897 Info = dtmf_restore_config(Id, plci, Rc);
13898 if ((Info != GOOD) || plci->internal_command)
13902 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13904 case ADJUST_B_RESTORE_MIXER_1:
13905 case ADJUST_B_RESTORE_MIXER_2:
13906 case ADJUST_B_RESTORE_MIXER_3:
13907 case ADJUST_B_RESTORE_MIXER_4:
13908 case ADJUST_B_RESTORE_MIXER_5:
13909 case ADJUST_B_RESTORE_MIXER_6:
13910 case ADJUST_B_RESTORE_MIXER_7:
13911 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13914 Info = mixer_restore_config(Id, plci, Rc);
13915 if ((Info != GOOD) || plci->internal_command)
13919 plci->adjust_b_state = ADJUST_B_END;
13927 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13930 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13931 UnMapId(Id), (char *)(FILE_), __LINE__,
13932 plci->B1_resource, b1_facilities));
13934 plci->adjust_b_parms_msg = bp_msg;
13935 plci->adjust_b_facilities = b1_facilities;
13936 plci->adjust_b_command = internal_command;
13937 plci->adjust_b_ncci = (word)(Id >> 16);
13938 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13939 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13941 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13942 plci->adjust_b_state = ADJUST_B_START;
13943 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13944 UnMapId(Id), (char *)(FILE_), __LINE__,
13945 plci->B1_resource, b1_facilities));
13949 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13951 word internal_command;
13953 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13954 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13956 internal_command = plci->internal_command;
13957 plci->internal_command = 0;
13958 switch (internal_command)
13962 if (plci->req_in != 0)
13964 plci->internal_command = ADJUST_B_RESTORE_1;
13968 case ADJUST_B_RESTORE_1:
13969 if ((Rc != OK) && (Rc != OK_FC))
13971 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13972 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13974 plci->adjust_b_parms_msg = NULL;
13975 plci->adjust_b_facilities = plci->B1_facilities;
13976 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13977 plci->adjust_b_ncci = (word)(Id >> 16);
13978 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13979 plci->adjust_b_state = ADJUST_B_START;
13980 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13981 UnMapId(Id), (char *)(FILE_), __LINE__));
13982 case ADJUST_B_RESTORE_2:
13983 if (adjust_b_process(Id, plci, Rc) != GOOD)
13985 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13986 UnMapId(Id), (char *)(FILE_), __LINE__));
13988 if (plci->internal_command)
13995 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13998 word internal_command;
14000 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14001 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14004 internal_command = plci->internal_command;
14005 plci->internal_command = 0;
14006 switch (internal_command)
14010 plci->adjust_b_parms_msg = NULL;
14011 plci->adjust_b_facilities = plci->B1_facilities;
14012 plci->adjust_b_command = RESET_B3_COMMAND_1;
14013 plci->adjust_b_ncci = (word)(Id >> 16);
14014 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14015 plci->adjust_b_state = ADJUST_B_START;
14016 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14017 UnMapId(Id), (char *)(FILE_), __LINE__));
14018 case RESET_B3_COMMAND_1:
14019 Info = adjust_b_process(Id, plci, Rc);
14022 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14023 UnMapId(Id), (char *)(FILE_), __LINE__));
14026 if (plci->internal_command)
14030 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14031 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14035 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14038 word internal_command;
14041 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14042 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14045 internal_command = plci->internal_command;
14046 plci->internal_command = 0;
14047 switch (internal_command)
14051 plci->adjust_b_parms_msg = &plci->saved_msg;
14052 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14053 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14055 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14056 plci->adjust_b_command = SELECT_B_COMMAND_1;
14057 plci->adjust_b_ncci = (word)(Id >> 16);
14058 if (plci->saved_msg.parms[0].length == 0)
14060 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061 ADJUST_B_MODE_NO_RESOURCE;
14065 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14066 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14068 plci->adjust_b_state = ADJUST_B_START;
14069 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14070 UnMapId(Id), (char *)(FILE_), __LINE__));
14071 case SELECT_B_COMMAND_1:
14072 Info = adjust_b_process(Id, plci, Rc);
14075 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14076 UnMapId(Id), (char *)(FILE_), __LINE__));
14079 if (plci->internal_command)
14081 if (plci->tel == ADV_VOICE)
14085 esc_chi[2] = plci->b_channel;
14086 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14090 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14094 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));
14101 internal_command = plci->internal_command;
14102 plci->internal_command = 0;
14103 switch (internal_command)
14107 case FAX_CONNECT_ACK_COMMAND_1:
14108 if (plci_nl_busy(plci))
14110 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14113 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14114 plci->NData[0].P = plci->fax_connect_info_buffer;
14115 plci->NData[0].PLength = plci->fax_connect_info_length;
14116 plci->NL.X = plci->NData;
14117 plci->NL.ReqCh = 0;
14118 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14119 plci->adapter->request(&plci->NL);
14121 case FAX_CONNECT_ACK_COMMAND_2:
14122 if ((Rc != OK) && (Rc != OK_FC))
14124 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14125 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14129 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14130 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14132 if (plci->B3_prot == 4)
14133 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14135 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14136 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14141 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14143 word internal_command;
14145 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14146 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14148 internal_command = plci->internal_command;
14149 plci->internal_command = 0;
14150 switch (internal_command)
14154 case FAX_EDATA_ACK_COMMAND_1:
14155 if (plci_nl_busy(plci))
14157 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14160 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14161 plci->NData[0].P = plci->fax_connect_info_buffer;
14162 plci->NData[0].PLength = plci->fax_edata_ack_length;
14163 plci->NL.X = plci->NData;
14164 plci->NL.ReqCh = 0;
14165 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14166 plci->adapter->request(&plci->NL);
14168 case FAX_EDATA_ACK_COMMAND_2:
14169 if ((Rc != OK) && (Rc != OK_FC))
14171 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14172 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14179 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14182 word internal_command;
14184 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14185 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14188 internal_command = plci->internal_command;
14189 plci->internal_command = 0;
14190 switch (internal_command)
14194 case FAX_CONNECT_INFO_COMMAND_1:
14195 if (plci_nl_busy(plci))
14197 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14200 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14201 plci->NData[0].P = plci->fax_connect_info_buffer;
14202 plci->NData[0].PLength = plci->fax_connect_info_length;
14203 plci->NL.X = plci->NData;
14204 plci->NL.ReqCh = 0;
14205 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14206 plci->adapter->request(&plci->NL);
14208 case FAX_CONNECT_INFO_COMMAND_2:
14209 if ((Rc != OK) && (Rc != OK_FC))
14211 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14212 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213 Info = _WRONG_STATE;
14216 if (plci_nl_busy(plci))
14218 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14221 plci->command = _CONNECT_B3_R;
14222 nl_req_ncci(plci, N_CONNECT, 0);
14226 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14230 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14233 word internal_command;
14235 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14236 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14239 internal_command = plci->internal_command;
14240 plci->internal_command = 0;
14241 switch (internal_command)
14245 plci->adjust_b_parms_msg = NULL;
14246 plci->adjust_b_facilities = plci->B1_facilities;
14247 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14248 plci->adjust_b_ncci = (word)(Id >> 16);
14249 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14250 plci->adjust_b_state = ADJUST_B_START;
14251 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14252 UnMapId(Id), (char *)(FILE_), __LINE__));
14253 case FAX_ADJUST_B23_COMMAND_1:
14254 Info = adjust_b_process(Id, plci, Rc);
14257 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14258 UnMapId(Id), (char *)(FILE_), __LINE__));
14261 if (plci->internal_command)
14263 case FAX_ADJUST_B23_COMMAND_2:
14264 if (plci_nl_busy(plci))
14266 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14269 plci->command = _CONNECT_B3_R;
14270 nl_req_ncci(plci, N_CONNECT, 0);
14274 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14278 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14280 word internal_command;
14282 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14283 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14285 internal_command = plci->internal_command;
14286 plci->internal_command = 0;
14287 switch (internal_command)
14291 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14293 case FAX_DISCONNECT_COMMAND_1:
14294 case FAX_DISCONNECT_COMMAND_2:
14295 case FAX_DISCONNECT_COMMAND_3:
14296 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14298 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14299 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14304 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14305 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14307 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14312 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14313 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14321 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14324 word internal_command;
14326 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14327 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14330 internal_command = plci->internal_command;
14331 plci->internal_command = 0;
14332 switch (internal_command)
14336 case RTP_CONNECT_B3_REQ_COMMAND_1:
14337 if (plci_nl_busy(plci))
14339 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14342 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14343 nl_req_ncci(plci, N_CONNECT, 0);
14346 case RTP_CONNECT_B3_REQ_COMMAND_2:
14347 if ((Rc != OK) && (Rc != OK_FC))
14349 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14350 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14351 Info = _WRONG_STATE;
14354 if (plci_nl_busy(plci))
14356 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14359 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14360 plci->NData[0].PLength = plci->internal_req_buffer[0];
14361 plci->NData[0].P = plci->internal_req_buffer + 1;
14362 plci->NL.X = plci->NData;
14363 plci->NL.ReqCh = 0;
14364 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14365 plci->adapter->request(&plci->NL);
14367 case RTP_CONNECT_B3_REQ_COMMAND_3:
14370 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14374 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14376 word internal_command;
14378 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14379 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14381 internal_command = plci->internal_command;
14382 plci->internal_command = 0;
14383 switch (internal_command)
14387 case RTP_CONNECT_B3_RES_COMMAND_1:
14388 if (plci_nl_busy(plci))
14390 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14393 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14394 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14397 case RTP_CONNECT_B3_RES_COMMAND_2:
14398 if ((Rc != OK) && (Rc != OK_FC))
14400 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14401 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14404 if (plci_nl_busy(plci))
14406 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14409 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14410 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14411 plci->NData[0].PLength = plci->internal_req_buffer[0];
14412 plci->NData[0].P = plci->internal_req_buffer + 1;
14413 plci->NL.X = plci->NData;
14414 plci->NL.ReqCh = 0;
14415 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14416 plci->adapter->request(&plci->NL);
14418 case RTP_CONNECT_B3_RES_COMMAND_3:
14425 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14427 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14429 word internal_command;
14431 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14432 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14435 internal_command = plci->internal_command;
14436 plci->internal_command = 0;
14437 switch (internal_command)
14443 plci->adjust_b_parms_msg = NULL;
14444 plci->adjust_b_facilities = plci->B1_facilities;
14445 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14446 plci->adjust_b_ncci = (word)(Id >> 16);
14447 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14448 plci->adjust_b_state = ADJUST_B_START;
14449 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14450 UnMapId(Id), (char *)(FILE_), __LINE__));
14451 case HOLD_SAVE_COMMAND_1:
14452 Info = adjust_b_process(Id, plci, Rc);
14455 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14456 UnMapId(Id), (char *)(FILE_), __LINE__));
14459 if (plci->internal_command)
14462 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14466 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14468 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14470 word internal_command;
14472 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14473 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14476 internal_command = plci->internal_command;
14477 plci->internal_command = 0;
14478 switch (internal_command)
14482 plci->adjust_b_parms_msg = NULL;
14483 plci->adjust_b_facilities = plci->B1_facilities;
14484 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14485 plci->adjust_b_ncci = (word)(Id >> 16);
14486 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14487 plci->adjust_b_state = ADJUST_B_START;
14488 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14489 UnMapId(Id), (char *)(FILE_), __LINE__));
14490 case RETRIEVE_RESTORE_COMMAND_1:
14491 Info = adjust_b_process(Id, plci, Rc);
14494 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14495 UnMapId(Id), (char *)(FILE_), __LINE__));
14498 if (plci->internal_command)
14501 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14505 static void init_b1_config(PLCI *plci)
14508 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14509 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14510 (char *)(FILE_), __LINE__));
14512 plci->B1_resource = 0;
14513 plci->B1_facilities = 0;
14515 plci->li_bchannel_id = 0;
14516 mixer_clear_config(plci);
14519 ec_clear_config(plci);
14522 dtmf_rec_clear_config(plci);
14523 dtmf_send_clear_config(plci);
14524 dtmf_parameter_clear_config(plci);
14526 adv_voice_clear_config(plci);
14527 adjust_b_clear(plci);
14531 static void clear_b1_config(PLCI *plci)
14534 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14535 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14536 (char *)(FILE_), __LINE__));
14538 adv_voice_clear_config(plci);
14539 adjust_b_clear(plci);
14541 ec_clear_config(plci);
14544 dtmf_rec_clear_config(plci);
14545 dtmf_send_clear_config(plci);
14546 dtmf_parameter_clear_config(plci);
14549 if ((plci->li_bchannel_id != 0)
14550 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14552 mixer_clear_config(plci);
14553 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14554 plci->li_bchannel_id = 0;
14557 plci->B1_resource = 0;
14558 plci->B1_facilities = 0;
14562 /* -----------------------------------------------------------------
14563 XON protocol local helpers
14564 ----------------------------------------------------------------- */
14565 static void channel_flow_control_remove(PLCI *plci) {
14566 DIVA_CAPI_ADAPTER *a = plci->adapter;
14568 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14569 if (a->ch_flow_plci[i] == plci->Id) {
14570 a->ch_flow_plci[i] = 0;
14571 a->ch_flow_control[i] = 0;
14576 static void channel_x_on(PLCI *plci, byte ch) {
14577 DIVA_CAPI_ADAPTER *a = plci->adapter;
14578 if (a->ch_flow_control[ch] & N_XON_SENT) {
14579 a->ch_flow_control[ch] &= ~N_XON_SENT;
14583 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14584 DIVA_CAPI_ADAPTER *a = plci->adapter;
14585 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14586 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14587 a->ch_flow_plci[ch] = plci->Id;
14588 a->ch_flow_control_pending++;
14592 static void channel_request_xon(PLCI *plci, byte ch) {
14593 DIVA_CAPI_ADAPTER *a = plci->adapter;
14595 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14596 a->ch_flow_control[ch] |= N_XON_REQ;
14597 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14598 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14602 static void channel_xmit_extended_xon(PLCI *plci) {
14603 DIVA_CAPI_ADAPTER *a;
14604 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14605 int i, one_requested = 0;
14607 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14611 for (i = 0; i < max_ch; i++) {
14612 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14613 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14614 (plci->Id == a->ch_flow_plci[i])) {
14615 channel_request_xon(plci, (byte)i);
14620 if (one_requested) {
14621 channel_xmit_xon(plci);
14626 Try to xmit next X_ON
14628 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14629 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14632 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14636 if (a->last_flow_control_ch >= max_ch) {
14637 a->last_flow_control_ch = 1;
14639 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14640 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14641 (plci->Id == a->ch_flow_plci[i])) {
14642 a->last_flow_control_ch = i + 1;
14647 for (i = 1; i < a->last_flow_control_ch; i++) {
14648 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649 (plci->Id == a->ch_flow_plci[i])) {
14650 a->last_flow_control_ch = i + 1;
14658 static void channel_xmit_xon(PLCI *plci) {
14659 DIVA_CAPI_ADAPTER *a = plci->adapter;
14662 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14665 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14668 a->ch_flow_control[ch] &= ~N_XON_REQ;
14669 a->ch_flow_control[ch] |= N_XON_SENT;
14671 plci->NL.Req = plci->nl_req = (byte)N_XON;
14672 plci->NL.ReqCh = ch;
14673 plci->NL.X = plci->NData;
14675 plci->NData[0].P = &plci->RBuffer[0];
14676 plci->NData[0].PLength = 0;
14678 plci->adapter->request(&plci->NL);
14681 static int channel_can_xon(PLCI *plci, byte ch) {
14683 DIVA_CAPI_ADAPTER *a;
14689 APPLptr = plci->appl;
14695 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14697 /* count all buffers within the Application pool */
14698 /* belonging to the same NCCI. XON if a first is */
14702 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14703 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14704 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14706 if ((count > 2) || (Num == 0xffff)) {
14713 /*------------------------------------------------------------------*/
14715 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14722 /**********************************************************************************/
14723 /* function groups the listening applications according to the CIP mask and the */
14724 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14725 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14726 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14727 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14728 /* OS specific part (per adapter). */
14729 /**********************************************************************************/
14730 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14732 word i, j, k, busy, group_found;
14733 dword info_mask_group[MAX_CIP_TYPES];
14734 dword cip_mask_group[MAX_CIP_TYPES];
14735 word appl_number_group_type[MAX_APPL];
14738 set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14740 if (!a->group_optimization_enabled)
14742 dbug(1, dprintf("No group optimization"));
14746 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14748 for (i = 0; i < MAX_CIP_TYPES; i++)
14750 info_mask_group[i] = 0;
14751 cip_mask_group[i] = 0;
14753 for (i = 0; i < MAX_APPL; i++)
14755 appl_number_group_type[i] = 0;
14757 for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14758 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14759 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14761 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14762 return; /* allow good application unfiltered access */
14765 for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14767 if (application[i].Id && a->CIP_Mask[i])
14769 for (k = 0, busy = false; k < a->max_plci; k++)
14773 auxplci = &a->plci[k];
14774 if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14777 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14779 else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14782 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14787 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14789 if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14790 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14791 appl_number_group_type[i] = MAX_CIP_TYPES;
14792 group_found = true;
14793 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14795 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14796 { /* is group already present ? */
14797 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14798 group_found = true;
14799 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]));
14801 else if (!info_mask_group[j])
14802 { /* establish a new group */
14803 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14804 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14805 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14806 group_found = true;
14807 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]));
14813 for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14815 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14817 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14819 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14823 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14824 for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14826 if (appl_number_group_type[i] == appl_number_group_type[j])
14828 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14829 clear_group_ind_mask_bit(plci, j); /* disable call on other group members */
14830 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14835 else /* application should not get a call */
14837 clear_group_ind_mask_bit(plci, i);
14845 /* OS notifies the driver about a application Capi_Register */
14846 word CapiRegister(word id)
14848 word i, j, appls_found;
14851 DIVA_CAPI_ADAPTER *a;
14853 for (i = 0, appls_found = 0; i < max_appl; i++)
14855 if (application[i].Id && (application[i].Id != id))
14857 appls_found++; /* an application has been found */
14861 if (appls_found) return true;
14862 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14867 if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14869 if (!appls_found) /* first application does a capi register */
14871 if ((j = get_plci(a))) /* activate L1 of all adapters */
14873 plci = &a->plci[j - 1];
14875 add_p(plci, OAD, "\x01\xfd");
14876 add_p(plci, CAI, "\x01\x80");
14877 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14878 add_p(plci, SHIFT | 6, NULL);
14879 add_p(plci, SIN, "\x02\x00\x00");
14880 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14881 sig_req(plci, ASSIGN, DSIG_ID);
14882 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14883 sig_req(plci, SIG_CTRL, 0);
14893 /*------------------------------------------------------------------*/
14895 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14897 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14900 /* Format of vswitch_t:
14903 2 byte VSWITCH_REQ/VSWITCH_IND
14905 4 word VSwitchcommand
14912 plci->Sig.Ind == NCR_FACILITY
14916 for (i = 0; i < MAX_MULTI_IE; i++)
14918 if (!parms[i][0]) continue;
14919 if (parms[i][0] < 7)
14921 parms[i][0] = 0; /* kill it */
14924 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14925 switch (parms[i][4])
14928 if (!plci->relatedPTYPLCI ||
14929 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14933 /* remember all necessary informations */
14934 if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14938 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14939 { /* first indication after ECT-Request on Consultation Call */
14940 plci->vswitchstate = parms[i][9];
14941 parms[i][9] = 2; /* State */
14942 /* now ask first Call to join */
14944 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14945 { /* Answer of VSWITCH_REQ from first Call */
14946 plci->vswitchstate = parms[i][9];
14947 /* tell consultation call to join
14948 and the protocol capabilities of the first call */
14954 plci->vsprot = parms[i][10]; /* protocol */
14955 plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14956 /* send join request to related PLCI */
14957 parms[i][1] = VSWITCHIE;
14958 parms[i][2] = VSWITCH_REQ;
14960 plci->relatedPTYPLCI->command = 0;
14961 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14962 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14963 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14964 send_req(plci->relatedPTYPLCI);
14968 if (plci->relatedPTYPLCI &&
14969 plci->vswitchstate == 3 &&
14970 plci->relatedPTYPLCI->vswitchstate == 3)
14972 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14973 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14974 send_req(plci->relatedPTYPLCI);
14978 parms[i][0] = 0; /* kill it */
14983 /*------------------------------------------------------------------*/
14985 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14987 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14989 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14993 pReq->xdi_dma_descriptor_operation.Req = 0;
14994 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14996 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14997 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14998 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14999 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15001 e.user[0] = plci->adapter->Id - 1;
15002 plci->adapter->request((ENTITY *)pReq);
15004 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15005 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15006 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15007 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15008 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15010 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15012 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15014 dbug(1, dprintf("dma_alloc failed"));
15019 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15021 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15027 pReq->xdi_dma_descriptor_operation.Req = 0;
15028 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15030 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15031 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15032 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15033 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15035 e.user[0] = plci->adapter->Id - 1;
15036 plci->adapter->request((ENTITY *)pReq);
15038 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15039 dbug(1, dprintf("dma_free(%d)", nr));
15041 dbug(1, dprintf("dma_free failed (%d)", nr));
15045 /*------------------------------------------------------------------*/