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)
1150 static char hex_digit_table[0x10] =
1151 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1157 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1161 for (j = 0; j < 4; j++)
1163 if (i + j < C_IND_MASK_DWORDS)
1165 d = plci->c_ind_mask_table[i + j];
1166 for (k = 0; k < 8; k++)
1168 *(--p) = hex_digit_table[d & 0xf];
1174 for (k = 0; k < 8; k++)
1179 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1187 #define dump_plcis(a)
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message */
1193 /*------------------------------------------------------------------*/
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196 PLCI *plci, APPL *appl, API_PARSE *parms)
1204 API_PARSE ai_parms[5];
1208 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1209 static byte lli[2] = {0x01, 0x00};
1214 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1216 dbug(1, dprintf("connect_req(%d)", parms->length));
1217 Info = _WRONG_IDENTIFIER;
1220 if (a->adapter_disabled)
1222 dbug(1, dprintf("adapter disabled"));
1223 Id = ((word)1 << 8) | a->Id;
1224 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1225 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1228 Info = _OUT_OF_PLCI;
1229 if ((i = get_plci(a)))
1232 plci = &a->plci[i - 1];
1234 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1235 /* check 'external controller' bit for codec support */
1236 if (Id & EXT_CONTROLLER)
1238 if (AdvCodecSupport(a, plci, appl, 0))
1241 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1248 if (bp->length)LinkLayer = bp->info[3];
1253 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1256 if (ai_parms[0].length)
1258 ch = GET_WORD(ai_parms[0].info + 1);
1259 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1260 if (ch == 4) /* explizit CHI in message */
1262 /* check length of B-CH struct */
1263 if ((ai_parms[0].info)[3] >= 1)
1265 if ((ai_parms[0].info)[4] == CHI)
1267 p_chi = &((ai_parms[0].info)[5]);
1271 p_chi = &((ai_parms[0].info)[3]);
1273 if (p_chi[0] > 35) /* check length of channel ID */
1275 Info = _WRONG_MESSAGE_FORMAT;
1278 else Info = _WRONG_MESSAGE_FORMAT;
1281 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1283 dir = GET_WORD(ai_parms[0].info + 3);
1286 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1288 if (ai_parms[0].info[i + 5] != 0)
1290 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1291 Info = _WRONG_MESSAGE_FORMAT;
1302 Info = _WRONG_MESSAGE_FORMAT;
1305 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1307 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1308 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1309 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1313 esc_chi[2] = (byte)channel;
1314 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1315 add_p(plci, LLI, lli);
1316 add_p(plci, ESC, esc_chi);
1317 plci->State = LOCAL_CONNECT;
1318 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1323 else Info = _WRONG_MESSAGE_FORMAT;
1326 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1327 plci->command = _CONNECT_R;
1328 plci->number = Number;
1329 /* x.31 or D-ch free SAPI in LinkLayer? */
1330 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1331 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1333 /* B-channel used for B3 connections (ch==0), or no B channel */
1334 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1335 if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1336 else Info = add_b1(plci, &parms[5], ch, 0);
1337 add_s(plci, OAD, &parms[2]);
1338 add_s(plci, OSA, &parms[4]);
1339 add_s(plci, BC, &parms[6]);
1340 add_s(plci, LLC, &parms[7]);
1341 add_s(plci, HLC, &parms[8]);
1342 if (a->Info_Mask[appl->Id - 1] & 0x200)
1344 /* early B3 connect (CIP mask bit 9) no release after a disc */
1345 add_p(plci, LLI, "\x01\x01");
1347 if (GET_WORD(parms[0].info) < 29) {
1348 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1349 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1351 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1352 sig_req(plci, ASSIGN, DSIG_ID);
1356 /* D-Channel used for B3 connections */
1357 plci->Sig.Id = 0xff;
1361 if (!Info && ch != 2 && !noCh) {
1362 Info = add_b23(plci, &parms[5]);
1364 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1370 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1372 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1374 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1375 plci->spoofed_msg = CALL_REQ;
1376 plci->internal_command = BLOCK_PLCI;
1378 dbug(1, dprintf("Spoof"));
1382 if (ch == 4)add_p(plci, CHI, p_chi);
1383 add_s(plci, CPN, &parms[1]);
1384 add_s(plci, DSA, &parms[3]);
1385 if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1386 add_ai(plci, &parms[9]);
1387 if (!dir)sig_req(plci, CALL_REQ, 0);
1390 plci->command = PERM_LIST_REQ;
1392 sig_req(plci, LISTEN_REQ, 0);
1404 _CONNECT_R | CONFIRM,
1411 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1412 PLCI *plci, APPL *appl, API_PARSE *parms)
1416 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1417 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1419 API_PARSE ai_parms[5];
1423 dbug(1, dprintf("connect_res(no plci)"));
1424 return 0; /* no plci, no send */
1427 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1428 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1430 dbug(1, dprintf("ai->length=%d", ai->length));
1434 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1436 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1438 if (ai_parms[0].length)
1440 ch = GET_WORD(ai_parms[0].info + 1);
1441 dbug(1, dprintf("BCH-I=0x%x", ch));
1446 if (plci->State == INC_CON_CONNECTED_ALERT)
1448 dbug(1, dprintf("Connected Alert Call_Res"));
1449 if (a->Info_Mask[appl->Id - 1] & 0x200)
1451 /* early B3 connect (CIP mask bit 9) no release after a disc */
1452 add_p(plci, LLI, "\x01\x01");
1454 add_s(plci, CONN_NR, &parms[2]);
1455 add_s(plci, LLC, &parms[4]);
1456 add_ai(plci, &parms[5]);
1457 plci->State = INC_CON_ACCEPT;
1458 sig_req(plci, CALL_RES, 0);
1461 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1462 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1463 dump_c_ind_mask(plci);
1464 Reject = GET_WORD(parms[0].info);
1465 dbug(1, dprintf("Reject=0x%x", Reject));
1468 if (c_ind_mask_empty(plci))
1470 if ((Reject & 0xff00) == 0x3400)
1472 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1473 add_p(plci, ESC, esc_t);
1474 add_ai(plci, &parms[5]);
1475 sig_req(plci, REJECT, 0);
1477 else if (Reject == 1 || Reject >= 9)
1479 add_ai(plci, &parms[5]);
1480 sig_req(plci, HANGUP, 0);
1484 esc_t[2] = cau_t[(Reject&0x000f)];
1485 add_p(plci, ESC, esc_t);
1486 add_ai(plci, &parms[5]);
1487 sig_req(plci, REJECT, 0);
1493 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1498 if (Id & EXT_CONTROLLER) {
1499 if (AdvCodecSupport(a, plci, appl, 0)) {
1500 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1501 sig_req(plci, HANGUP, 0);
1504 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1506 Info = add_b23(plci, &parms[1]);
1509 dbug(1, dprintf("connect_res(error from add_b23)"));
1510 sig_req(plci, HANGUP, 0);
1515 nl_req_ncci(plci, ASSIGN, 0);
1524 Info = add_b23(plci, &parms[1]);
1527 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1528 sig_req(plci, HANGUP, 0);
1532 nl_req_ncci(plci, ASSIGN, 0);
1535 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1537 api_save_msg(parms, "wsssss", &plci->saved_msg);
1538 plci->spoofed_msg = CALL_RES;
1539 plci->internal_command = BLOCK_PLCI;
1541 dbug(1, dprintf("Spoof"));
1545 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1546 if (a->Info_Mask[appl->Id - 1] & 0x200)
1548 /* early B3 connect (CIP mask bit 9) no release after a disc */
1549 add_p(plci, LLI, "\x01\x01");
1551 add_s(plci, CONN_NR, &parms[2]);
1552 add_s(plci, LLC, &parms[4]);
1553 add_ai(plci, &parms[5]);
1554 plci->State = INC_CON_ACCEPT;
1555 sig_req(plci, CALL_RES, 0);
1558 for (i = 0; i < max_appl; i++) {
1559 if (test_c_ind_mask_bit(plci, i)) {
1560 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1568 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1569 PLCI *plci, APPL *appl, API_PARSE *msg)
1571 dbug(1, dprintf("connect_a_res"));
1575 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1576 PLCI *plci, APPL *appl, API_PARSE *msg)
1581 dbug(1, dprintf("disconnect_req"));
1583 Info = _WRONG_IDENTIFIER;
1587 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1589 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1591 for (i = 0; i < max_appl; i++)
1593 if (test_c_ind_mask_bit(plci, i))
1594 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596 plci->State = OUTG_DIS_PENDING;
1598 if (plci->Sig.Id && plci->appl)
1601 if (plci->Sig.Id != 0xff)
1603 if (plci->State != INC_DIS_PENDING)
1605 add_ai(plci, &msg[0]);
1606 sig_req(plci, HANGUP, 0);
1607 plci->State = OUTG_DIS_PENDING;
1613 if (plci->NL.Id && !plci->nl_remove_id)
1616 nl_req_ncci(plci, REMOVE, 0);
1617 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1618 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619 plci->State = INC_DIS_PENDING;
1626 if (!appl) return false;
1627 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1631 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1632 PLCI *plci, APPL *appl, API_PARSE *msg)
1634 dbug(1, dprintf("disconnect_res"));
1637 /* clear ind mask bit, just in case of collsion of */
1638 /* DISCONNECT_IND and CONNECT_RES */
1639 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1640 ncci_free_receive_buffers(plci, 0);
1641 if (plci_remove_check(plci))
1645 if (plci->State == INC_DIS_PENDING
1646 || plci->State == SUSPENDING) {
1647 if (c_ind_mask_empty(plci)) {
1648 if (plci->State != SUSPENDING) plci->State = IDLE;
1649 dbug(1, dprintf("chs=%d", plci->channels));
1650 if (!plci->channels) {
1659 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1660 PLCI *plci, APPL *appl, API_PARSE *parms)
1665 dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1667 Info = _WRONG_IDENTIFIER;
1670 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1671 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1672 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1673 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1674 a->Info_Mask[appl->Id - 1] |= 0x10; /* call progression infos */
1677 /* check if external controller listen and switch listen on or off*/
1678 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1679 if (a->profile.Global_Options & ON_BOARD_CODEC) {
1680 dummy_plci.State = IDLE;
1681 a->codec_listen[appl->Id - 1] = &dummy_plci;
1682 a->TelOAD[0] = (byte)(parms[3].length);
1683 for (i = 1; parms[3].length >= i && i < 22; i++) {
1684 a->TelOAD[i] = parms[3].info[i];
1687 a->TelOSA[0] = (byte)(parms[4].length);
1688 for (i = 1; parms[4].length >= i && i < 22; i++) {
1689 a->TelOSA[i] = parms[4].info[i];
1693 else Info = 0x2002; /* wrong controller, codec not supported */
1695 else{ /* clear listen */
1696 a->codec_listen[appl->Id - 1] = (PLCI *)0;
1700 _LISTEN_R | CONFIRM,
1705 if (a) listen_check(a);
1709 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1710 PLCI *plci, APPL *appl, API_PARSE *msg)
1714 PLCI *rc_plci = NULL;
1715 API_PARSE ai_parms[5];
1718 dbug(1, dprintf("info_req"));
1719 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1725 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1727 dbug(1, dprintf("AddInfo wrong"));
1728 Info = _WRONG_MESSAGE_FORMAT;
1731 if (!a) Info = _WRONG_STATE;
1734 { /* no fac, with CPN, or KEY */
1736 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1738 /* overlap sending option */
1739 dbug(1, dprintf("OvlSnd"));
1740 add_s(plci, CPN, &msg[0]);
1741 add_s(plci, KEY, &ai_parms[1]);
1742 sig_req(plci, INFO_REQ, 0);
1747 if (plci->State && ai_parms[2].length)
1749 /* User_Info option */
1750 dbug(1, dprintf("UUI"));
1751 add_s(plci, UUI, &ai_parms[2]);
1752 sig_req(plci, USER_DATA, 0);
1754 else if (plci->State && ai_parms[3].length)
1756 /* Facility option */
1757 dbug(1, dprintf("FAC"));
1758 add_s(plci, CPN, &msg[0]);
1759 add_ai(plci, &msg[1]);
1760 sig_req(plci, FACILITY_REQ, 0);
1764 Info = _WRONG_STATE;
1767 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1769 /* NCR_Facility option -> send UUI and Keypad too */
1770 dbug(1, dprintf("NCR_FAC"));
1771 if ((i = get_plci(a)))
1773 rc_plci = &a->plci[i - 1];
1774 appl->NullCREnable = true;
1775 rc_plci->internal_command = C_NCR_FAC_REQ;
1776 rc_plci->appl = appl;
1777 add_p(rc_plci, CAI, "\x01\x80");
1778 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1779 sig_req(rc_plci, ASSIGN, DSIG_ID);
1784 Info = _OUT_OF_PLCI;
1789 add_s(rc_plci, CPN, &msg[0]);
1790 add_ai(rc_plci, &msg[1]);
1791 sig_req(rc_plci, NCR_FACILITY, 0);
1794 /* for application controlled supplementary services */
1800 Info = _WRONG_MESSAGE_FORMAT;
1808 { /* appl is not assigned to a PLCI or error condition */
1809 dbug(1, dprintf("localInfoCon"));
1819 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1820 PLCI *plci, APPL *appl, API_PARSE *msg)
1822 dbug(1, dprintf("info_res"));
1826 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1827 PLCI *plci, APPL *appl, API_PARSE *msg)
1832 dbug(1, dprintf("alert_req"));
1834 Info = _WRONG_IDENTIFIER;
1837 Info = _ALERT_IGNORED;
1838 if (plci->State != INC_CON_ALERT) {
1839 Info = _WRONG_STATE;
1840 if (plci->State == INC_CON_PENDING) {
1842 plci->State = INC_CON_ALERT;
1843 add_ai(plci, &msg[0]);
1844 sig_req(plci, CALL_ALERT, 0);
1857 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1858 PLCI *plci, APPL *appl, API_PARSE *msg)
1865 long relatedPLCIvalue;
1866 DIVA_CAPI_ADAPTER *relatedadapter;
1868 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1869 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1871 API_PARSE ss_parms[11];
1877 dbug(1, dprintf("facility_req"));
1878 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1884 dbug(1, dprintf("wrong Ctrl"));
1885 Info = _WRONG_IDENTIFIER;
1888 selector = GET_WORD(msg[0].info);
1894 case SELECTOR_HANDSET:
1895 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1898 case SELECTOR_SU_SERV:
1901 Info = _WRONG_MESSAGE_FORMAT;
1904 SSreq = GET_WORD(&(msg[1].info[1]));
1905 PUT_WORD(&RCparms[1], SSreq);
1909 case S_GET_SUPPORTED_SERVICES:
1910 if ((i = get_plci(a)))
1912 rplci = &a->plci[i - 1];
1914 add_p(rplci, CAI, "\x01\x80");
1915 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1916 sig_req(rplci, ASSIGN, DSIG_ID);
1921 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1922 SSparms = (byte *)SSstruct;
1925 rplci->internal_command = GETSERV_REQ_PEND;
1926 rplci->number = Number;
1928 sig_req(rplci, S_SUPPORTED, 0);
1934 if (parms->length == 7)
1936 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1938 dbug(1, dprintf("format wrong"));
1939 Info = _WRONG_MESSAGE_FORMAT;
1945 Info = _WRONG_MESSAGE_FORMAT;
1948 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1949 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1951 if ((i = get_plci(a)))
1953 rplci = &a->plci[i - 1];
1955 add_p(rplci, CAI, "\x01\x80");
1956 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1957 sig_req(rplci, ASSIGN, DSIG_ID);
1964 rplci->internal_command = GET_MWI_STATE;
1965 rplci->number = Number;
1966 sig_req(rplci, MWI_POLL, 0);
1972 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1973 if (plci && plci->State && plci->SuppState == IDLE)
1975 plci->SuppState = HOLD_REQUEST;
1976 plci->command = C_HOLD_REQ;
1977 add_s(plci, CAI, &ss_parms[1]);
1978 sig_req(plci, CALL_HOLD, 0);
1982 else Info = 0x3010; /* wrong state */
1985 if (plci && plci->State && plci->SuppState == CALL_HELD)
1987 if (Id & EXT_CONTROLLER)
1989 if (AdvCodecSupport(a, plci, appl, 0))
1991 Info = 0x3010; /* wrong state */
1997 plci->SuppState = RETRIEVE_REQUEST;
1998 plci->command = C_RETRIEVE_REQ;
1999 if (plci->spoofed_msg == SPOOFING_REQUIRED)
2001 plci->spoofed_msg = CALL_RETRIEVE;
2002 plci->internal_command = BLOCK_PLCI;
2004 dbug(1, dprintf("Spoof"));
2009 sig_req(plci, CALL_RETRIEVE, 0);
2014 else Info = 0x3010; /* wrong state */
2019 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2021 dbug(1, dprintf("format wrong"));
2022 Info = _WRONG_MESSAGE_FORMAT;
2026 if (plci && plci->State)
2028 add_s(plci, CAI, &ss_parms[2]);
2029 plci->command = SUSPEND_REQ;
2030 sig_req(plci, SUSPEND, 0);
2031 plci->State = SUSPENDING;
2034 else Info = 0x3010; /* wrong state */
2038 if (!(i = get_plci(a)))
2040 Info = _OUT_OF_PLCI;
2043 rplci = &a->plci[i - 1];
2045 rplci->number = Number;
2047 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2048 /* check 'external controller' bit for codec support */
2049 if (Id & EXT_CONTROLLER)
2051 if (AdvCodecSupport(a, rplci, appl, 0))
2060 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2062 dbug(1, dprintf("format wrong"));
2064 Info = _WRONG_MESSAGE_FORMAT;
2069 dummy.info = "\x00";
2070 add_b1(rplci, &dummy, 0, 0);
2071 if (a->Info_Mask[appl->Id - 1] & 0x200)
2073 /* early B3 connect (CIP mask bit 9) no release after a disc */
2074 add_p(rplci, LLI, "\x01\x01");
2076 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2077 sig_req(rplci, ASSIGN, DSIG_ID);
2079 add_s(rplci, CAI, &ss_parms[2]);
2080 rplci->command = RESUME_REQ;
2081 sig_req(rplci, RESUME, 0);
2082 rplci->State = RESUMING;
2086 case S_CONF_BEGIN: /* Request */
2088 case S_CONF_ISOLATE:
2089 case S_CONF_REATTACH:
2090 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2092 dbug(1, dprintf("format wrong"));
2093 Info = _WRONG_MESSAGE_FORMAT;
2096 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2098 d = GET_DWORD(ss_parms[2].info);
2101 dbug(1, dprintf("format wrong"));
2102 Info = _WRONG_MESSAGE_FORMAT;
2105 plci->ptyState = (byte)SSreq;
2111 cai[1] = CONF_BEGIN;
2112 plci->internal_command = CONF_BEGIN_REQ_PEND;
2116 plci->internal_command = CONF_DROP_REQ_PEND;
2118 case S_CONF_ISOLATE:
2119 cai[1] = CONF_ISOLATE;
2120 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2122 case S_CONF_REATTACH:
2123 cai[1] = CONF_REATTACH;
2124 plci->internal_command = CONF_REATTACH_REQ_PEND;
2127 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2128 add_p(plci, CAI, cai);
2129 sig_req(plci, S_SERVICE, 0);
2133 else Info = 0x3010; /* wrong state */
2140 if (parms->length == 7)
2142 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2144 dbug(1, dprintf("format wrong"));
2145 Info = _WRONG_MESSAGE_FORMAT;
2149 else if (parms->length == 8) /* workaround for the T-View-S */
2151 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2153 dbug(1, dprintf("format wrong"));
2154 Info = _WRONG_MESSAGE_FORMAT;
2160 Info = _WRONG_MESSAGE_FORMAT;
2165 Info = _WRONG_MESSAGE_FORMAT;
2170 Info = _WRONG_IDENTIFIER;
2173 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2174 relatedPLCIvalue &= 0x0000FFFF;
2175 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2176 /* controller starts with 0 up to (max_adapter - 1) */
2177 if (((relatedPLCIvalue & 0x7f) == 0)
2178 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2179 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2181 if (SSreq == S_3PTY_END)
2183 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2188 Info = 0x3010; /* wrong state */
2194 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2195 relatedPLCIvalue >>= 8;
2197 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2199 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2201 rplci = &relatedadapter->plci[i];
2204 if (!rplci || !relatedPLCIvalue)
2206 if (SSreq == S_3PTY_END)
2208 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2213 Info = 0x3010; /* wrong state */
2219 dbug(1, dprintf("rplci:%x", rplci));
2220 dbug(1, dprintf("plci:%x", plci));
2221 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2222 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2223 dbug(1, dprintf("SSreq:%x", SSreq));
2224 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2225 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2226 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2228 /* send PTY/ECT req, cannot check all states because of US stuff */
2229 if (!rplci->internal_command && rplci->appl)
2232 rplci->relatedPTYPLCI = plci;
2233 plci->relatedPTYPLCI = rplci;
2234 rplci->ptyState = (byte)SSreq;
2237 rplci->internal_command = ECT_REQ_PEND;
2238 cai[1] = ECT_EXECUTE;
2240 rplci->vswitchstate = 0;
2242 rplci->vsprotdialect = 0;
2243 plci->vswitchstate = 0;
2245 plci->vsprotdialect = 0;
2248 else if (SSreq == S_CONF_ADD)
2250 rplci->internal_command = CONF_ADD_REQ_PEND;
2255 rplci->internal_command = PTY_REQ_PEND;
2256 cai[1] = (byte)(SSreq - 3);
2258 rplci->number = Number;
2259 if (plci != rplci) /* explicit invocation */
2262 cai[2] = plci->Sig.Id;
2263 dbug(1, dprintf("explicit invocation"));
2267 dbug(1, dprintf("implicit invocation"));
2270 add_p(rplci, CAI, cai);
2271 sig_req(rplci, S_SERVICE, 0);
2277 dbug(0, dprintf("Wrong line"));
2278 Info = 0x3010; /* wrong state */
2283 case S_CALL_DEFLECTION:
2284 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2286 dbug(1, dprintf("format wrong"));
2287 Info = _WRONG_MESSAGE_FORMAT;
2292 Info = _WRONG_IDENTIFIER;
2295 /* reuse unused screening indicator */
2296 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2298 plci->internal_command = CD_REQ_PEND;
2299 appl->CDEnable = true;
2301 cai[1] = CALL_DEFLECTION;
2302 add_p(plci, CAI, cai);
2303 add_p(plci, CPN, ss_parms[3].info);
2304 sig_req(plci, S_SERVICE, 0);
2309 case S_CALL_FORWARDING_START:
2310 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2312 dbug(1, dprintf("format wrong"));
2313 Info = _WRONG_MESSAGE_FORMAT;
2317 if ((i = get_plci(a)))
2319 rplci = &a->plci[i - 1];
2321 add_p(rplci, CAI, "\x01\x80");
2322 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2323 sig_req(rplci, ASSIGN, DSIG_ID);
2328 Info = _OUT_OF_PLCI;
2332 /* reuse unused screening indicator */
2333 rplci->internal_command = CF_START_PEND;
2335 rplci->number = Number;
2336 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2338 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2339 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2340 add_p(rplci, CAI, cai);
2341 add_p(rplci, OAD, ss_parms[5].info);
2342 add_p(rplci, CPN, ss_parms[6].info);
2343 sig_req(rplci, S_SERVICE, 0);
2348 case S_INTERROGATE_DIVERSION:
2349 case S_INTERROGATE_NUMBERS:
2350 case S_CALL_FORWARDING_STOP:
2351 case S_CCBS_REQUEST:
2352 case S_CCBS_DEACTIVATE:
2353 case S_CCBS_INTERROGATE:
2356 case S_INTERROGATE_NUMBERS:
2357 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2359 dbug(0, dprintf("format wrong"));
2360 Info = _WRONG_MESSAGE_FORMAT;
2363 case S_CCBS_REQUEST:
2364 case S_CCBS_DEACTIVATE:
2365 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2367 dbug(0, dprintf("format wrong"));
2368 Info = _WRONG_MESSAGE_FORMAT;
2371 case S_CCBS_INTERROGATE:
2372 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2374 dbug(0, dprintf("format wrong"));
2375 Info = _WRONG_MESSAGE_FORMAT;
2379 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2381 dbug(0, dprintf("format wrong"));
2382 Info = _WRONG_MESSAGE_FORMAT;
2389 if ((i = get_plci(a)))
2391 rplci = &a->plci[i - 1];
2394 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2395 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2396 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2398 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2399 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2400 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2402 case S_CALL_FORWARDING_STOP:
2403 rplci->internal_command = CF_STOP_PEND;
2404 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2406 case S_CCBS_REQUEST:
2407 cai[1] = CCBS_REQUEST;
2408 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2410 case S_CCBS_DEACTIVATE:
2411 cai[1] = CCBS_DEACTIVATE;
2412 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2414 case S_CCBS_INTERROGATE:
2415 cai[1] = CCBS_INTERROGATE;
2416 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2423 rplci->number = Number;
2424 add_p(rplci, CAI, "\x01\x80");
2425 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2426 sig_req(rplci, ASSIGN, DSIG_ID);
2431 Info = _OUT_OF_PLCI;
2435 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2438 case S_INTERROGATE_NUMBERS:
2440 add_p(rplci, CAI, cai);
2442 case S_CCBS_REQUEST:
2443 case S_CCBS_DEACTIVATE:
2445 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2446 add_p(rplci, CAI, cai);
2448 case S_CCBS_INTERROGATE:
2450 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2451 add_p(rplci, CAI, cai);
2452 add_p(rplci, OAD, ss_parms[4].info);
2456 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2457 add_p(rplci, CAI, cai);
2458 add_p(rplci, OAD, ss_parms[5].info);
2462 sig_req(rplci, S_SERVICE, 0);
2467 case S_MWI_ACTIVATE:
2468 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2470 dbug(1, dprintf("format wrong"));
2471 Info = _WRONG_MESSAGE_FORMAT;
2476 if ((i = get_plci(a)))
2478 rplci = &a->plci[i - 1];
2480 rplci->cr_enquiry = true;
2481 add_p(rplci, CAI, "\x01\x80");
2482 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2483 sig_req(rplci, ASSIGN, DSIG_ID);
2488 Info = _OUT_OF_PLCI;
2495 rplci->cr_enquiry = false;
2499 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2501 rplci->number = Number;
2504 cai[1] = ACTIVATION_MWI; /* Function */
2505 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2506 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2507 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2508 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2509 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2510 add_p(rplci, CAI, cai);
2511 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2512 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2513 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2514 add_p(rplci, UID, ss_parms[10].info); /* Time */
2515 sig_req(rplci, S_SERVICE, 0);
2519 case S_MWI_DEACTIVATE:
2520 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2522 dbug(1, dprintf("format wrong"));
2523 Info = _WRONG_MESSAGE_FORMAT;
2528 if ((i = get_plci(a)))
2530 rplci = &a->plci[i - 1];
2532 rplci->cr_enquiry = true;
2533 add_p(rplci, CAI, "\x01\x80");
2534 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2535 sig_req(rplci, ASSIGN, DSIG_ID);
2540 Info = _OUT_OF_PLCI;
2547 rplci->cr_enquiry = false;
2551 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2553 rplci->number = Number;
2556 cai[1] = DEACTIVATION_MWI; /* Function */
2557 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2558 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2559 add_p(rplci, CAI, cai);
2560 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2561 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2562 sig_req(rplci, S_SERVICE, 0);
2567 Info = 0x300E; /* not supported */
2570 break; /* case SELECTOR_SU_SERV: end */
2574 return (dtmf_request(Id, Number, a, plci, appl, msg));
2578 case SELECTOR_LINE_INTERCONNECT:
2579 return (mixer_request(Id, Number, a, plci, appl, msg));
2583 case PRIV_SELECTOR_ECHO_CANCELLER:
2584 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2585 return (ec_request(Id, Number, a, plci, appl, msg));
2587 case SELECTOR_ECHO_CANCELLER:
2588 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2589 return (ec_request(Id, Number, a, plci, appl, msg));
2592 case SELECTOR_V42BIS:
2594 Info = _FACILITY_NOT_SUPPORTED;
2596 } /* end of switch (selector) */
2599 dbug(1, dprintf("SendFacRc"));
2601 _FACILITY_R | CONFIRM,
2604 "wws", Info, selector, SSparms);
2608 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2609 PLCI *plci, APPL *appl, API_PARSE *msg)
2611 dbug(1, dprintf("facility_res"));
2615 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2616 PLCI *plci, APPL *appl, API_PARSE *parms)
2622 word fax_control_bits, fax_feature_bits, fax_info_change;
2626 API_PARSE fax_parms[9];
2630 dbug(1, dprintf("connect_b3_req"));
2633 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2634 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2636 Info = _WRONG_STATE;
2640 /* local reply if assign unsuccessful
2641 or B3 protocol allows only one layer 3 connection
2642 and already connected
2643 or B2 protocol not any LAPD
2644 and connect_b3_req contradicts originate/answer direction */
2646 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2647 && ((plci->channels != 0)
2648 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2649 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2651 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2652 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2653 Info = _WRONG_STATE;
2655 _CONNECT_B3_R | CONFIRM,
2661 plci->requested_options_conn = 0;
2665 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2667 if (ncpi->length > 2)
2670 if (ncpi->info[2] || ncpi->info[3])
2672 pvc[0] = ncpi->info[3];
2673 pvc[1] = ncpi->info[2];
2674 add_d(plci, 2, pvc);
2679 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2680 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2684 else if (plci->B3_prot == 5)
2686 if (plci->NL.Id && !plci->nl_remove_id)
2688 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2689 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2690 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2691 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2693 len = offsetof(T30_INFO, universal_6);
2694 fax_info_change = false;
2695 if (ncpi->length >= 4)
2697 w = GET_WORD(&ncpi->info[3]);
2698 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2700 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2701 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2702 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2703 fax_info_change = true;
2705 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2706 if (w & 0x0002) /* Fax-polling request */
2707 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2708 if ((w & 0x0004) /* Request to send / poll another document */
2709 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2711 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2713 if (ncpi->length >= 6)
2715 w = GET_WORD(&ncpi->info[5]);
2716 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2718 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2719 fax_info_change = true;
2722 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2723 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2725 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2727 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2728 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2730 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2732 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2733 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2734 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2735 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2737 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2738 Info = _WRONG_MESSAGE_FORMAT;
2741 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2742 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2744 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2745 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2746 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2748 w = fax_parms[4].length;
2751 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2752 for (i = 0; i < w; i++)
2753 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2754 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2755 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2756 w = fax_parms[5].length;
2759 plci->fax_connect_info_buffer[len++] = (byte) w;
2760 for (i = 0; i < w; i++)
2761 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2762 w = fax_parms[6].length;
2765 plci->fax_connect_info_buffer[len++] = (byte) w;
2766 for (i = 0; i < w; i++)
2767 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2768 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2769 & (1L << PRIVATE_FAX_NONSTANDARD))
2771 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2773 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2774 plci->fax_connect_info_buffer[len++] = 0;
2778 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2779 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2780 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2781 for (i = 0; i < fax_parms[7].length; i++)
2782 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2789 len = offsetof(T30_INFO, universal_6);
2791 fax_info_change = true;
2794 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2796 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2797 fax_info_change = true;
2802 plci->fax_connect_info_length = len;
2803 if (fax_info_change)
2805 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2807 start_internal_command(Id, plci, fax_connect_info_command);
2812 start_internal_command(Id, plci, fax_adjust_b23_command);
2818 else Info = _WRONG_STATE;
2820 else Info = _WRONG_STATE;
2823 else if (plci->B3_prot == B3_RTP)
2825 plci->internal_req_buffer[0] = ncpi->length + 1;
2826 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2827 for (w = 0; w < ncpi->length; w++)
2828 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2829 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2835 nl_req_ncci(plci, req, 0);
2840 else Info = _WRONG_IDENTIFIER;
2843 _CONNECT_B3_R | CONFIRM,
2850 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2851 PLCI *plci, APPL *appl, API_PARSE *parms)
2860 API_PARSE fax_parms[9];
2865 dbug(1, dprintf("connect_b3_res"));
2867 ncci = (word)(Id >> 16);
2869 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2870 if (GET_WORD(&parms[0].info[0]) != 0)
2872 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2873 channel_request_xon(plci, a->ncci_ch[ncci]);
2874 channel_xmit_xon(plci);
2875 cleanup_ncci_data(plci, ncci);
2876 nl_req_ncci(plci, N_DISC, (byte)ncci);
2879 a->ncci_state[ncci] = INC_ACT_PENDING;
2881 req = N_CONNECT_ACK;
2883 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2886 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2887 & (1L << PRIVATE_FAX_NONSTANDARD))
2889 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2890 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2891 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2893 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2894 if (plci->fax_connect_info_length < len)
2896 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2897 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2899 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2901 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2905 if (plci->fax_connect_info_length <= len)
2906 plci->fax_connect_info_buffer[len] = 0;
2907 len += 1 + plci->fax_connect_info_buffer[len];
2908 if (plci->fax_connect_info_length <= len)
2909 plci->fax_connect_info_buffer[len] = 0;
2910 len += 1 + plci->fax_connect_info_buffer[len];
2911 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2912 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2913 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2914 for (i = 0; i < fax_parms[7].length; i++)
2915 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2917 plci->fax_connect_info_length = len;
2918 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2919 start_internal_command(Id, plci, fax_connect_ack_command);
2924 nl_req_ncci(plci, req, (byte)ncci);
2925 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2926 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2928 if (plci->B3_prot == 4)
2929 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2931 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2932 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2936 else if (plci->B3_prot == B3_RTP)
2938 plci->internal_req_buffer[0] = ncpi->length + 1;
2939 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2940 for (w = 0; w < ncpi->length; w++)
2941 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2942 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2948 if (ncpi->length > 2) {
2949 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2950 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2952 nl_req_ncci(plci, req, (byte)ncci);
2953 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2954 if (plci->adjust_b_restore)
2956 plci->adjust_b_restore = false;
2957 start_internal_command(Id, plci, adjust_b_restore);
2966 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2967 PLCI *plci, APPL *appl, API_PARSE *parms)
2971 ncci = (word)(Id >> 16);
2972 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2974 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2975 && (plci->State != OUTG_DIS_PENDING))
2977 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2978 a->ncci_state[ncci] = CONNECTED;
2979 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2980 channel_request_xon(plci, a->ncci_ch[ncci]);
2981 channel_xmit_xon(plci);
2987 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2988 PLCI *plci, APPL *appl, API_PARSE *parms)
2994 dbug(1, dprintf("disconnect_b3_req"));
2996 Info = _WRONG_IDENTIFIER;
2997 ncci = (word)(Id >> 16);
3000 Info = _WRONG_STATE;
3001 if ((a->ncci_state[ncci] == CONNECTED)
3002 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3003 || (a->ncci_state[ncci] == INC_CON_PENDING)
3004 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3006 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3007 channel_request_xon(plci, a->ncci_ch[ncci]);
3008 channel_xmit_xon(plci);
3010 if (a->ncci[ncci].data_pending
3011 && ((plci->B3_prot == B3_TRANSPARENT)
3012 || (plci->B3_prot == B3_T30)
3013 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3015 plci->send_disc = (byte)ncci;
3021 cleanup_ncci_data(plci, ncci);
3023 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3026 if (ncpi->length > 3)
3028 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3031 nl_req_ncci(plci, N_DISC, (byte)ncci);
3037 _DISCONNECT_B3_R | CONFIRM,
3044 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3045 PLCI *plci, APPL *appl, API_PARSE *parms)
3050 ncci = (word)(Id >> 16);
3051 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3053 plci->requested_options_conn = 0;
3054 plci->fax_connect_info_length = 0;
3055 plci->ncpi_state = 0x00;
3056 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3057 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3059 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3061 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3062 if (i < MAX_CHANNELS_PER_PLCI) {
3063 if (plci->channels)plci->channels--;
3064 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3065 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3067 ncci_free_receive_buffers(plci, ncci);
3069 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3070 if (plci->State == SUSPENDING) {
3075 "ws", (word)3, "\x03\x04\x00\x00");
3076 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3084 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3085 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3086 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3088 ncci_free_receive_buffers(plci, ncci);
3090 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3092 plci->adapter->ncci_state[ncci] = IDLE;
3093 start_internal_command(Id, plci, fax_disconnect_command);
3101 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3102 PLCI *plci, APPL *appl, API_PARSE *parms)
3110 dbug(1, dprintf("data_b3_req"));
3112 Info = _WRONG_IDENTIFIER;
3113 ncci = (word)(Id >> 16);
3114 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3118 Info = _WRONG_STATE;
3119 if ((a->ncci_state[ncci] == CONNECTED)
3120 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3123 ncci_ptr = &(a->ncci[ncci]);
3124 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3125 if (i >= MAX_DATA_B3)
3127 data = &(ncci_ptr->DBuffer[i]);
3128 data->Number = Number;
3129 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3130 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3133 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3137 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3138 data->Length = GET_WORD(parms[1].info);
3139 data->Handle = GET_WORD(parms[2].info);
3140 data->Flags = GET_WORD(parms[3].info);
3141 (ncci_ptr->data_pending)++;
3143 /* check for delivery confirmation */
3144 if (data->Flags & 0x0004)
3146 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3147 if (i >= MAX_DATA_ACK)
3149 ncci_ptr->DataAck[i].Number = data->Number;
3150 ncci_ptr->DataAck[i].Handle = data->Handle;
3151 (ncci_ptr->data_ack_pending)++;
3162 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3163 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3166 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3171 _DATA_B3_R | CONFIRM,
3174 "ww", GET_WORD(parms[2].info), Info);
3179 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3180 PLCI *plci, APPL *appl, API_PARSE *parms)
3186 dbug(1, dprintf("data_b3_res"));
3188 ncci = (word)(Id >> 16);
3190 n = GET_WORD(parms[0].info);
3191 dbug(1, dprintf("free(%d)", n));
3192 NCCIcode = ncci | (((word) a->Id) << 8);
3193 if (n < appl->MaxBuffer &&
3194 appl->DataNCCI[n] == NCCIcode &&
3195 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3196 dbug(1, dprintf("found"));
3197 appl->DataNCCI[n] = 0;
3199 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3200 channel_request_xon(plci, a->ncci_ch[ncci]);
3202 channel_xmit_xon(plci);
3204 if (appl->DataFlags[n] & 4) {
3205 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3213 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3214 PLCI *plci, APPL *appl, API_PARSE *parms)
3219 dbug(1, dprintf("reset_b3_req"));
3221 Info = _WRONG_IDENTIFIER;
3222 ncci = (word)(Id >> 16);
3225 Info = _WRONG_STATE;
3226 switch (plci->B3_prot)
3230 if (a->ncci_state[ncci] == CONNECTED)
3232 nl_req_ncci(plci, N_RESET, (byte)ncci);
3237 case B3_TRANSPARENT:
3238 if (a->ncci_state[ncci] == CONNECTED)
3240 start_internal_command(Id, plci, reset_b3_command);
3246 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3248 _RESET_B3_R | CONFIRM,
3255 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3256 PLCI *plci, APPL *appl, API_PARSE *parms)
3260 dbug(1, dprintf("reset_b3_res"));
3262 ncci = (word)(Id >> 16);
3264 switch (plci->B3_prot)
3268 if (a->ncci_state[ncci] == INC_RES_PENDING)
3270 a->ncci_state[ncci] = CONNECTED;
3271 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3280 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3281 PLCI *plci, APPL *appl, API_PARSE *parms)
3287 dbug(1, dprintf("connect_b3_t90_a_res"));
3289 ncci = (word)(Id >> 16);
3291 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3292 a->ncci_state[ncci] = CONNECTED;
3294 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3295 a->ncci_state[ncci] = CONNECTED;
3297 req = N_CONNECT_ACK;
3299 /* parms[0]==0 for CAPI original message definition! */
3300 if (parms[0].info) {
3302 if (ncpi->length > 2) {
3303 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3304 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3307 nl_req_ncci(plci, req, (byte)ncci);
3315 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3316 PLCI *plci, APPL *appl, API_PARSE *msg)
3321 API_PARSE bp_parms[7];
3325 Info = _WRONG_IDENTIFIER;
3329 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3330 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3331 dbug(1, dprintf("PlciState=0x%x", plci->State));
3332 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3334 /* check if no channel is open, no B3 connected only */
3335 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3336 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3338 Info = _WRONG_STATE;
3340 /* check message format and fill bp_parms pointer */
3341 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3343 Info = _WRONG_MESSAGE_FORMAT;
3347 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3348 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3349 if (Id & EXT_CONTROLLER)
3351 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3354 plci->State = INC_CON_CONNECTED_ALERT;
3356 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3357 dump_c_ind_mask(plci);
3358 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3359 { /* its quasi a connect */
3360 if (test_c_ind_mask_bit(plci, i))
3361 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3365 api_save_msg(msg, "s", &plci->saved_msg);
3367 if (Id & EXT_CONTROLLER)
3369 if (tel) /* external controller in use by this PLCI */
3371 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3373 dbug(1, dprintf("Ext_Ctrl in use 1"));
3374 Info = _WRONG_STATE;
3377 else /* external controller NOT in use by this PLCI ? */
3379 if (a->AdvSignalPLCI)
3381 dbug(1, dprintf("Ext_Ctrl in use 2"));
3382 Info = _WRONG_STATE;
3384 else /* activate the codec */
3386 dbug(1, dprintf("Ext_Ctrl start"));
3387 if (AdvCodecSupport(a, plci, appl, 0))
3389 dbug(1, dprintf("Error in codec procedures"));
3390 Info = _WRONG_STATE;
3392 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3394 plci->spoofed_msg = AWAITING_SELECT_B;
3395 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3397 dbug(1, dprintf("continue if codec loaded"));
3403 else /* external controller bit is OFF */
3405 if (tel) /* external controller in use, need to switch off */
3407 if (a->AdvSignalAppl == appl)
3409 CodecIdCheck(a, plci);
3412 dbug(1, dprintf("Ext_Ctrl disable"));
3416 dbug(1, dprintf("Ext_Ctrl not requested"));
3422 if (plci->call_dir & CALL_DIR_OUT)
3423 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3424 else if (plci->call_dir & CALL_DIR_IN)
3425 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3426 start_internal_command(Id, plci, select_b_command);
3431 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3435 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3436 PLCI *plci, APPL *appl, API_PARSE *parms)
3442 API_PARSE m_parms[5];
3447 static byte chi[2] = {0x01, 0x00};
3448 static byte lli[2] = {0x01, 0x00};
3449 static byte codec_cai[2] = {0x01, 0x01};
3450 static byte null_msg = {0};
3451 static API_PARSE null_parms = { 0, &null_msg };
3455 dbug(1, dprintf("manufacturer_req"));
3456 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3458 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3459 Info = _WRONG_MESSAGE_FORMAT;
3461 command = GET_WORD(parms[1].info);
3466 case _DI_ASSIGN_PLCI:
3467 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3468 Info = _WRONG_MESSAGE_FORMAT;
3471 codec = GET_WORD(m_parms[0].info);
3472 ch = m_parms[1].info[0];
3473 dir = m_parms[2].info[0];
3474 if ((i = get_plci(a))) {
3475 plci = &a->plci[i - 1];
3477 plci->command = _MANUFACTURER_R;
3478 plci->m_command = command;
3479 plci->number = Number;
3480 plci->State = LOCAL_CONNECT;
3481 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3482 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3484 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3485 chi[1] = (byte)(0x80 | ch);
3487 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3491 Info = add_b1(plci, &m_parms[3], 0, 0);
3494 add_p(plci, CAI, codec_cai);
3496 /* manual 'swich on' to the codec support without signalling */
3497 /* first 'assign plci' with this function, then use */
3499 if (AdvCodecSupport(a, plci, appl, 0)) {
3500 Info = _RESOURCE_ERROR;
3503 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3504 lli[1] = 0x10; /* local call codec stream */
3509 plci->State = LOCAL_CONNECT;
3510 plci->manufacturer = true;
3511 plci->command = _MANUFACTURER_R;
3512 plci->m_command = command;
3513 plci->number = Number;
3517 add_p(plci, LLI, lli);
3518 add_p(plci, CHI, chi);
3519 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3520 sig_req(plci, ASSIGN, DSIG_ID);
3524 Info = add_b23(plci, &m_parms[3]);
3527 nl_req_ncci(plci, ASSIGN, 0);
3533 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3534 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3536 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3537 plci->spoofed_msg = AWAITING_MANUF_CON;
3538 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3544 sig_req(plci, CALL_REQ, 0);
3547 sig_req(plci, LISTEN_REQ, 0);
3554 _MANUFACTURER_R | CONFIRM,
3557 "dww", _DI_MANU_ID, command, Info);
3563 else Info = _OUT_OF_PLCI;
3569 Info = _WRONG_IDENTIFIER;
3572 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3573 Info = _WRONG_MESSAGE_FORMAT;
3576 req = m_parms[0].info[0];
3577 plci->command = _MANUFACTURER_R;
3578 plci->m_command = command;
3579 plci->number = Number;
3580 if (req == CALL_REQ)
3582 plci->b_channel = getChannel(&m_parms[1]);
3583 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3584 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3586 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3587 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3592 else if (req == LAW_REQ)
3594 plci->cr_enquiry = true;
3596 add_ss(plci, FTY, &m_parms[1]);
3597 sig_req(plci, req, 0);
3601 if (plci->NL.Id && !plci->nl_remove_id)
3605 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3607 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3609 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3610 cleanup_ncci_data(plci, ncci);
3611 nl_req_ncci(plci, N_DISC, (byte)ncci);
3616 nl_req_ncci(plci, REMOVE, 0);
3623 /* signalling control for loop activation B-channel */
3626 Info = _WRONG_IDENTIFIER;
3630 plci->command = _MANUFACTURER_R;
3631 plci->number = Number;
3632 add_ss(plci, FTY, m);
3633 sig_req(plci, SIG_CTRL, 0);
3636 else Info = _WRONG_MESSAGE_FORMAT;
3640 /* activation control for receiver/transmitter B-channel */
3643 Info = _WRONG_IDENTIFIER;
3647 plci->command = _MANUFACTURER_R;
3648 plci->number = Number;
3649 add_ss(plci, FTY, m);
3650 sig_req(plci, DSP_CTRL, 0);
3653 else Info = _WRONG_MESSAGE_FORMAT;
3658 /* TEL_CTRL commands to support non standard adjustments: */
3659 /* Ring on/off, Handset micro volume, external micro vol. */
3660 /* handset+external speaker volume, receiver+transm. gain,*/
3661 /* handsfree on (hookinfo off), set mixer command */
3663 if (command == _DI_ADV_CODEC)
3665 if (!a->AdvCodecPLCI) {
3666 Info = _WRONG_STATE;
3669 v_plci = a->AdvCodecPLCI;
3675 && (m->info[1] == 0x1c)
3676 && (m->info[2] >= 1))
3678 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3680 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3682 Info = _WRONG_STATE;
3685 a->adv_voice_coef_length = m->info[2] - 1;
3686 if (a->adv_voice_coef_length > m->length - 3)
3687 a->adv_voice_coef_length = (byte)(m->length - 3);
3688 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3689 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3690 for (i = 0; i < a->adv_voice_coef_length; i++)
3691 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3692 if (plci->B1_facilities & B1_FACILITY_VOICE)
3693 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3696 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3698 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3700 Info = _FACILITY_NOT_SUPPORTED;
3704 plci->dtmf_parameter_length = m->info[2] - 1;
3705 if (plci->dtmf_parameter_length > m->length - 3)
3706 plci->dtmf_parameter_length = (byte)(m->length - 3);
3707 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3708 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3709 for (i = 0; i < plci->dtmf_parameter_length; i++)
3710 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3711 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3712 dtmf_parameter_write(plci);
3722 Info = _WRONG_IDENTIFIER;
3726 add_ss(v_plci, FTY, m);
3727 sig_req(v_plci, TEL_CTRL, 0);
3730 else Info = _WRONG_MESSAGE_FORMAT;
3734 case _DI_OPTIONS_REQUEST:
3735 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3736 Info = _WRONG_MESSAGE_FORMAT;
3739 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3741 Info = _FACILITY_NOT_SUPPORTED;
3744 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3750 Info = _WRONG_MESSAGE_FORMAT;
3756 _MANUFACTURER_R | CONFIRM,
3759 "dww", _DI_MANU_ID, command, Info);
3764 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3765 PLCI *plci, APPL *appl, API_PARSE *msg)
3769 API_PARSE m_parms[3];
3771 API_PARSE fax_parms[9];
3776 dbug(1, dprintf("manufacturer_res"));
3778 if ((msg[0].length == 0)
3779 || (msg[1].length == 0)
3780 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3784 indication = GET_WORD(msg[1].info);
3788 case _DI_NEGOTIATE_B3:
3791 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3792 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3794 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3797 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3799 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3803 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3804 if (plci->fax_connect_info_length < len)
3806 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3807 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3809 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3811 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3815 if (plci->fax_connect_info_length <= len)
3816 plci->fax_connect_info_buffer[len] = 0;
3817 len += 1 + plci->fax_connect_info_buffer[len];
3818 if (plci->fax_connect_info_length <= len)
3819 plci->fax_connect_info_buffer[len] = 0;
3820 len += 1 + plci->fax_connect_info_buffer[len];
3821 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3822 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3823 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3824 for (i = 0; i < fax_parms[7].length; i++)
3825 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3827 plci->fax_connect_info_length = len;
3828 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3829 start_internal_command(Id, plci, fax_edata_ack_command);
3836 /*------------------------------------------------------------------*/
3837 /* IDI callback function */
3838 /*------------------------------------------------------------------*/
3840 void callback(ENTITY *e)
3842 DIVA_CAPI_ADAPTER *a;
3853 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3854 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3856 a = &(adapter[(byte)e->user[0]]);
3857 plci = &(a->plci[e->user[1]]);
3858 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3861 If new protocol code and new XDI is used then CAPI should work
3862 fully in accordance with IDI cpec an look on callback field instead
3863 of Rc field for return codes.
3865 if (((e->complete == 0xff) && no_cancel_rc) ||
3866 (e->Rc && !no_cancel_rc)) {
3872 if (e->user[0] & 0x8000)
3875 If REMOVE request was sent then we have to wait until
3876 return code with Id set to zero arrives.
3877 All other return codes should be ignored.
3883 dbug(1, dprintf("cancel RC in REMOVE state"));
3886 channel_flow_control_remove(plci);
3887 for (i = 0; i < 256; i++)
3889 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3890 a->FlowControlIdTable[i] = 0;
3892 plci->nl_remove_id = 0;
3893 if (plci->rx_dma_descriptor > 0) {
3894 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3895 plci->rx_dma_descriptor = 0;
3900 a->FlowControlIdTable[ch] = e->Id;
3901 a->FlowControlSkipTable[ch] = 0;
3903 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3904 a->ch_flow_plci[ch] = plci->Id;
3910 Cancel return codes self, if feature was requested
3912 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3913 a->FlowControlIdTable[ch] = 0;
3914 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3915 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3920 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3922 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3930 control_rc(plci, 0, rc, ch, 0, true);
3935 channel_x_on(plci, ch);
3936 if (plci->internal_command)
3937 control_rc(plci, req, rc, ch, 0, true);
3941 if (plci->nl_global_req)
3943 global_req = plci->nl_global_req;
3944 plci->nl_global_req = 0;
3945 if (rc != ASSIGN_OK) {
3947 if (plci->rx_dma_descriptor > 0) {
3948 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3949 plci->rx_dma_descriptor = 0;
3952 channel_xmit_xon(plci);
3953 control_rc(plci, 0, rc, ch, global_req, true);
3955 else if (plci->data_sent)
3957 channel_xmit_xon(plci);
3958 plci->data_sent = false;
3961 if (plci->internal_command)
3962 control_rc(plci, req, rc, ch, 0, true);
3966 channel_xmit_xon(plci);
3967 control_rc(plci, req, rc, ch, 0, true);
3975 If REMOVE request was sent then we have to wait until
3976 return code with Id set to zero arrives.
3977 All other return codes should be ignored.
3983 dbug(1, dprintf("cancel RC in REMOVE state"));
3986 plci->sig_remove_id = 0;
3989 if (plci->sig_global_req)
3991 global_req = plci->sig_global_req;
3992 plci->sig_global_req = 0;
3993 if (rc != ASSIGN_OK)
3995 channel_xmit_xon(plci);
3996 control_rc(plci, 0, rc, ch, global_req, false);
4000 channel_xmit_xon(plci);
4001 control_rc(plci, req, rc, ch, 0, false);
4005 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4006 same callback. Also if new XDI and protocol code used then jump
4010 channel_xmit_xon(plci);
4011 goto capi_callback_suffix;
4015 channel_xmit_xon(plci);
4018 if (e->user[0] & 0x8000) {
4019 byte Ind = e->Ind & 0x0f;
4021 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4022 (a->ch_flow_plci[Ch] == plci->Id)) {
4023 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4024 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4026 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4029 if ((e->RNR != 1) &&
4030 (a->ch_flow_plci[Ch] == plci->Id) &&
4031 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4032 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4041 capi_callback_suffix:
4043 while (!plci->req_in
4044 && !plci->internal_command
4045 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4047 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4049 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4051 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4052 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4053 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4054 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4055 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4057 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4058 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4062 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4064 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4066 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4067 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4069 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4071 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4074 i = api_put(appl, m);
4077 if (m->header.command == _DATA_B3_R)
4079 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4081 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4085 if (plci->li_notify_update)
4087 plci->li_notify_update = false;
4088 mixer_notify_update(plci, false);
4097 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4106 DIVA_CAPI_ADAPTER *a;
4109 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4110 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4113 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4116 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4117 if (plci->req_in != plci->req_out)
4119 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4121 dbug(1, dprintf("req_1return"));
4124 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4126 plci->req_in = plci->req_in_start = plci->req_out = 0;
4127 dbug(1, dprintf("control_rc"));
4131 ncci = a->ch_ncci[ch];
4134 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4135 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4136 Number = plci->number;
4137 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));
4138 dbug(1, dprintf("channels=0x%x", plci->channels));
4139 if (plci_remove_check(plci))
4141 if (req == REMOVE && rc == ASSIGN_OK)
4143 sig_req(plci, HANGUP, 0);
4144 sig_req(plci, REMOVE, 0);
4149 switch (plci->command)
4152 dbug(1, dprintf("HoldRC=0x%x", rc));
4153 SSparms[1] = (byte)S_HOLD;
4156 plci->SuppState = IDLE;
4159 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4162 case C_RETRIEVE_REQ:
4163 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4164 SSparms[1] = (byte)S_RETRIEVE;
4167 plci->SuppState = CALL_HELD;
4170 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4174 dbug(1, dprintf("InfoRC=0x%x", rc));
4175 if (rc != OK) Info = _WRONG_STATE;
4176 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4180 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4181 if (plci->State == INC_DIS_PENDING)
4183 if (plci->Sig.Id != 0xff)
4185 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4186 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4188 dbug(1, dprintf("No more IDs/Call_Req failed"));
4189 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4194 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4195 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4197 else /* D-ch activation */
4199 if (rc != ASSIGN_OK)
4201 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4202 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4207 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4208 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4209 plci->State = INC_ACT_PENDING;
4213 case _CONNECT_I | RESPONSE:
4214 if (plci->State != INC_DIS_PENDING)
4215 plci->State = INC_CON_ACCEPT;
4219 if (plci->State == INC_DIS_PENDING)
4221 if (plci->Sig.Id != 0xff)
4223 plci->State = OUTG_DIS_PENDING;
4224 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4237 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4240 ncci = get_ncci(plci, ch, 0);
4241 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4245 a->ncci_state[ncci] = INC_ACT_PENDING;
4246 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4247 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4251 a->ncci_state[ncci] = OUTG_CON_PENDING;
4252 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4256 case _CONNECT_B3_I | RESPONSE:
4260 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4263 case _DISCONNECT_B3_R:
4264 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4267 case _MANUFACTURER_R:
4273 Info = _WRONG_IDENTIFIER;
4274 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4278 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4286 else if (plci->internal_command)
4288 switch (plci->internal_command)
4294 if (rc == OK) /* command supported, wait for indication */
4301 /* Get Supported Services */
4302 case GETSERV_REQ_PEND:
4303 if (rc == OK) /* command supported, wait for indication */
4307 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4308 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4312 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4313 case INTERR_NUMBERS_REQ_PEND:
4314 case CF_START_PEND: /* Call Forwarding Start pending */
4315 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4316 case CCBS_REQUEST_REQ_PEND:
4317 case CCBS_DEACTIVATE_REQ_PEND:
4318 case CCBS_INTERROGATE_REQ_PEND:
4319 switch (plci->internal_command)
4321 case INTERR_DIVERSION_REQ_PEND:
4322 SSparms[1] = S_INTERROGATE_DIVERSION;
4324 case INTERR_NUMBERS_REQ_PEND:
4325 SSparms[1] = S_INTERROGATE_NUMBERS;
4328 SSparms[1] = S_CALL_FORWARDING_START;
4331 SSparms[1] = S_CALL_FORWARDING_STOP;
4333 case CCBS_REQUEST_REQ_PEND:
4334 SSparms[1] = S_CCBS_REQUEST;
4336 case CCBS_DEACTIVATE_REQ_PEND:
4337 SSparms[1] = S_CCBS_DEACTIVATE;
4339 case CCBS_INTERROGATE_REQ_PEND:
4340 SSparms[1] = S_CCBS_INTERROGATE;
4343 if (global_req == ASSIGN)
4345 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4348 if (!plci->appl) break;
4349 if (rc == ISDN_GUARD_REJ)
4351 Info = _CAPI_GUARD_ERROR;
4355 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4357 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4358 plci->number, "wws", Info, (word)3, SSparms);
4359 if (Info) plci_remove(plci);
4362 /* 3pty conference pending */
4364 if (!plci->relatedPTYPLCI) break;
4365 rplci = plci->relatedPTYPLCI;
4366 SSparms[1] = plci->ptyState;
4367 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4368 if (rplci->tel) rId |= EXT_CONTROLLER;
4371 Info = 0x300E; /* not supported */
4372 plci->relatedPTYPLCI = NULL;
4376 _FACILITY_R | CONFIRM,
4379 "wws", Info, (word)3, SSparms);
4382 /* Explicit Call Transfer pending */
4384 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4385 if (!plci->relatedPTYPLCI) break;
4386 rplci = plci->relatedPTYPLCI;
4388 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4389 if (rplci->tel) rId |= EXT_CONTROLLER;
4392 Info = 0x300E; /* not supported */
4393 plci->relatedPTYPLCI = NULL;
4397 _FACILITY_R | CONFIRM,
4400 "wws", Info, (word)3, SSparms);
4403 case _MANUFACTURER_R:
4404 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4405 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4407 dbug(1, dprintf("No more IDs"));
4408 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4409 plci_remove(plci); /* after codec init, internal codec commands pending */
4414 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4415 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4417 dbug(1, dprintf("No more IDs"));
4418 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4419 plci_remove(plci); /* after codec init, internal codec commands pending */
4423 case PERM_COD_HOOK: /* finished with Hook_Ind */
4427 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4428 plci->internal_command = PERM_COD_CONN_PEND;
4431 case PERM_COD_ASSIGN:
4432 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4433 if (rc != ASSIGN_OK) break;
4434 sig_req(plci, CALL_REQ, 0);
4436 plci->internal_command = PERM_COD_CALL;
4439 /* Null Call Reference Request pending */
4441 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4442 if (global_req == ASSIGN)
4444 if (rc == ASSIGN_OK)
4450 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4451 appl->NullCREnable = false;
4455 else if (req == NCR_FACILITY)
4459 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4463 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4464 appl->NullCREnable = false;
4473 if (a->ncci_state[ncci] == CONNECTED)
4475 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4476 cleanup_ncci_data(plci, ncci);
4477 nl_req_ncci(plci, N_DISC, (byte)ncci);
4484 if (plci->State == INC_DIS_PENDING)
4486 sig_req(plci, CALL_REQ, 0);
4488 plci->State = OUTG_CON_PENDING;
4492 case MWI_ACTIVATE_REQ_PEND:
4493 case MWI_DEACTIVATE_REQ_PEND:
4494 if (global_req == ASSIGN && rc == ASSIGN_OK)
4496 dbug(1, dprintf("MWI_REQ assigned"));
4503 Info = 0x2007; /* Illegal message parameter coding */
4504 dbug(1, dprintf("MWI_REQ invalid parameter"));
4508 Info = 0x300B; /* not supported */
4509 dbug(1, dprintf("MWI_REQ not supported"));
4511 /* 0x3010: Request not allowed in this state */
4512 PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4515 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4517 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4519 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4521 if (plci->cr_enquiry)
4524 _FACILITY_R | CONFIRM,
4527 "wws", Info, (word)3, SSparms);
4528 if (rc != OK) plci_remove(plci);
4533 _FACILITY_R | CONFIRM,
4536 "wws", Info, (word)3, SSparms);
4540 case CONF_BEGIN_REQ_PEND:
4541 case CONF_ADD_REQ_PEND:
4542 case CONF_SPLIT_REQ_PEND:
4543 case CONF_DROP_REQ_PEND:
4544 case CONF_ISOLATE_REQ_PEND:
4545 case CONF_REATTACH_REQ_PEND:
4546 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4547 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4550 switch (plci->internal_command)
4552 case CONF_BEGIN_REQ_PEND:
4553 SSparms[1] = S_CONF_BEGIN;
4555 case CONF_ADD_REQ_PEND:
4556 SSparms[1] = S_CONF_ADD;
4557 rplci = plci->relatedPTYPLCI;
4558 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4560 case CONF_SPLIT_REQ_PEND:
4561 SSparms[1] = S_CONF_SPLIT;
4563 case CONF_DROP_REQ_PEND:
4564 SSparms[1] = S_CONF_DROP;
4566 case CONF_ISOLATE_REQ_PEND:
4567 SSparms[1] = S_CONF_ISOLATE;
4569 case CONF_REATTACH_REQ_PEND:
4570 SSparms[1] = S_CONF_REATTACH;
4576 Info = 0x300E; /* not supported */
4577 plci->relatedPTYPLCI = NULL;
4581 _FACILITY_R | CONFIRM,
4584 "wws", Info, (word)3, SSparms);
4587 case VSWITCH_REQ_PEND:
4590 if (plci->relatedPTYPLCI)
4592 plci->relatedPTYPLCI->vswitchstate = 0;
4593 plci->relatedPTYPLCI->vsprot = 0;
4594 plci->relatedPTYPLCI->vsprotdialect = 0;
4596 plci->vswitchstate = 0;
4598 plci->vsprotdialect = 0;
4602 if (plci->relatedPTYPLCI &&
4603 plci->vswitchstate == 1 &&
4604 plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4605 plci->vswitchstate = 3;
4609 /* Call Deflection Request pending (SSCT) */
4611 SSparms[1] = S_CALL_DEFLECTION;
4614 Info = 0x300E; /* not supported */
4615 plci->appl->CDEnable = 0;
4617 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4618 plci->number, "wws", Info, (word)3, SSparms);
4621 case RTP_CONNECT_B3_REQ_COMMAND_2:
4624 ncci = get_ncci(plci, ch, 0);
4625 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4627 a->ncci_state[ncci] = OUTG_CON_PENDING;
4631 if (plci->internal_command_queue[0])
4633 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4634 if (plci->internal_command)
4639 next_internal_command(Id, plci);
4644 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4645 if (plci->tel) Id |= EXT_CONTROLLER;
4647 switch (plci->internal_command)
4652 case START_L1_SIG_ASSIGN_PEND:
4653 case REM_L1_SIG_ASSIGN_PEND:
4654 if (global_req == ASSIGN)
4660 dbug(1, dprintf("***L1 Req rem PLCI"));
4661 plci->internal_command = 0;
4662 sig_req(plci, REMOVE, 0);
4667 /* Call Deflection Request pending, just no appl ptr assigned */
4669 SSparms[1] = S_CALL_DEFLECTION;
4672 Info = 0x300E; /* not supported */
4674 for (i = 0; i < max_appl; i++)
4676 if (application[i].CDEnable)
4678 if (!application[i].Id) application[i].CDEnable = 0;
4681 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4682 plci->number, "wws", Info, (word)3, SSparms);
4683 if (Info) application[i].CDEnable = 0;
4687 plci->internal_command = 0;
4690 case PERM_COD_HOOK: /* finished with Hook_Ind */
4694 plci->internal_command = PERM_COD_CONN_PEND;
4695 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4698 case PERM_COD_ASSIGN:
4699 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4700 plci->internal_command = 0;
4701 if (rc != ASSIGN_OK) break;
4702 plci->internal_command = PERM_COD_CALL;
4703 sig_req(plci, CALL_REQ, 0);
4707 case LISTEN_SIG_ASSIGN_PEND:
4708 if (rc == ASSIGN_OK)
4710 plci->internal_command = 0;
4711 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4712 add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4713 sig_req(plci, INDICATE_REQ, 0);
4718 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4726 if (global_req == ASSIGN)
4728 if (rc == ASSIGN_OK)
4730 sig_req(plci, LAW_REQ, 0);
4732 dbug(1, dprintf("Auto-Law assigned"));
4736 dbug(1, dprintf("Auto-Law assign failed"));
4737 a->automatic_law = 3;
4738 plci->internal_command = 0;
4739 a->automatic_lawPLCI = NULL;
4743 else if (req == LAW_REQ && rc == OK)
4745 dbug(1, dprintf("Auto-Law initiated"));
4746 a->automatic_law = 2;
4747 plci->internal_command = 0;
4751 dbug(1, dprintf("Auto-Law not supported"));
4752 a->automatic_law = 3;
4753 plci->internal_command = 0;
4754 sig_req(plci, REMOVE, 0);
4756 a->automatic_lawPLCI = NULL;
4760 plci_remove_check(plci);
4764 static void data_rc(PLCI *plci, byte ch)
4767 DIVA_CAPI_ADAPTER *a;
4774 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4776 ncci = a->ch_ncci[ch];
4777 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4779 ncci_ptr = &(a->ncci[ncci]);
4780 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4781 if (ncci_ptr->data_pending)
4783 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4784 if (!(data->Flags & 4) && a->ncci_state[ncci])
4786 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4787 if (plci->tel) Id |= EXT_CONTROLLER;
4788 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4789 "ww", data->Handle, 0);
4791 (ncci_ptr->data_out)++;
4792 if (ncci_ptr->data_out == MAX_DATA_B3)
4793 ncci_ptr->data_out = 0;
4794 (ncci_ptr->data_pending)--;
4800 static void data_ack(PLCI *plci, byte ch)
4803 DIVA_CAPI_ADAPTER *a;
4808 ncci = a->ch_ncci[ch];
4809 ncci_ptr = &(a->ncci[ncci]);
4810 if (ncci_ptr->data_ack_pending)
4812 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4814 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4815 if (plci->tel) Id |= EXT_CONTROLLER;
4816 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4817 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4819 (ncci_ptr->data_ack_out)++;
4820 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4821 ncci_ptr->data_ack_out = 0;
4822 (ncci_ptr->data_ack_pending)--;
4826 static void sig_ind(PLCI *plci)
4835 DIVA_CAPI_ADAPTER *a;
4836 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4837 #define MAXPARMSIDS 31
4838 byte *parms[MAXPARMSIDS];
4840 byte *multi_fac_parms[MAX_MULTI_IE];
4841 byte *multi_pi_parms[MAX_MULTI_IE];
4842 byte *multi_ssext_parms[MAX_MULTI_IE];
4843 byte *multi_CiPN_parms[MAX_MULTI_IE];
4845 byte *multi_vswitch_parms[MAX_MULTI_IE];
4852 byte *esc_profile = "";
4856 byte chi[] = "\x02\x18\x01";
4857 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4858 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4859 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4860 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4861 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4862 /* (see Info_Mask Bit 4, first IE. then the message type) */
4863 static const word parms_id[] =
4864 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4865 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4866 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4867 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4868 /* 14 FTY repl by ESC_CHI */
4869 /* 18 PI repl by ESC_LAW */
4870 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4871 static const word multi_fac_id[] = {1, FTY};
4872 static const word multi_pi_id[] = {1, PI};
4873 static const word multi_CiPN_id[] = {1, OAD};
4874 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4876 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4880 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4884 byte force_mt_info = false;
4890 Id = ((word)plci->Id << 8) | a->Id;
4891 PUT_WORD(&SS_Ind[4], 0x0000);
4893 if (plci->sig_remove_id)
4895 plci->Sig.RNR = 2; /* discard */
4896 dbug(1, dprintf("SIG discard while remove pending"));
4899 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4907 if (plci->Sig.Ind == HANGUP && plci->channels)
4910 plci->hangup_flow_ctrl_timer++;
4911 /* recover the network layer after timeout */
4912 if (plci->hangup_flow_ctrl_timer == 100)
4914 dbug(1, dprintf("Exceptional disc"));
4916 plci->hangup_flow_ctrl_timer = 0;
4917 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4919 if (a->ncci_plci[ncci] == plci->Id)
4921 cleanup_ncci_data(plci, ncci);
4922 if (plci->channels)plci->channels--;
4924 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4928 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4935 /* do first parse the info with no OAD in, because OAD will be converted */
4936 /* first the multiple facility IE, then mult. progress ind. */
4937 /* then the parameters for the info_ind + conn_ind */
4938 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4942 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4944 IndParse(plci, parms_id, parms, 0);
4945 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946 esc_chi = parms[14];
4947 esc_law = parms[18];
4948 pty_cai = parms[24];
4950 esc_profile = parms[27];
4951 if (esc_cr[0] && plci)
4953 if (plci->cr_enquiry && plci->appl)
4955 plci->cr_enquiry = false;
4958 /* b = total length */
4959 /* b = indication type */
4960 /* b = length of all IEs */
4962 /* S = IE1 length + cont. */
4964 /* S = IE2 length + cont. */
4969 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970 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);
4973 /* create the additional info structure */
4974 add_i[1] = parms[15]; /* KEY of additional info */
4975 add_i[2] = parms[11]; /* UUI of additional info */
4976 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4978 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4979 /* indication returns by the card if requested by the function */
4980 /* AutomaticLaw() after driver init */
4981 if (a->automatic_law < 4)
4985 dbug(0, dprintf("u-Law selected"));
4989 dbug(0, dprintf("a-Law selected"));
4992 a->automatic_law = 4;
4993 if (plci == a->automatic_lawPLCI) {
4994 plci->internal_command = 0;
4995 sig_req(plci, REMOVE, 0);
4997 a->automatic_lawPLCI = NULL;
5002 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5007 a->profile.Global_Options &= 0x000000ffL;
5008 a->profile.B1_Protocols &= 0x000003ffL;
5009 a->profile.B2_Protocols &= 0x00001fdfL;
5010 a->profile.B3_Protocols &= 0x000000b7L;
5012 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5013 GL_BCHANNEL_OPERATION_SUPPORTED;
5014 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5018 a->man_profile.private_options = 0;
5020 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5022 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5023 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5027 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5028 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5029 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5033 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5034 a->man_profile.private_options |= 1L << PRIVATE_T38;
5037 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5038 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5041 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5042 a->man_profile.private_options |= 1L << PRIVATE_V18;
5045 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5046 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5049 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5050 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5053 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5054 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5057 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5058 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5061 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5062 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5067 a->profile.Global_Options &= 0x0000007fL;
5068 a->profile.B1_Protocols &= 0x000003dfL;
5069 a->profile.B2_Protocols &= 0x00001adfL;
5070 a->profile.B3_Protocols &= 0x000000b7L;
5071 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5073 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5074 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5076 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5078 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5079 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5080 UnMapController(a->Id), a->profile.Global_Options,
5081 a->profile.B1_Protocols, a->profile.B2_Protocols,
5082 a->profile.B3_Protocols, a->manufacturer_features));
5084 /* codec plci for the handset/hook state support is just an internal id */
5085 if (plci != a->AdvCodecPLCI)
5087 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090 SendInfo(plci, Id, parms, force_mt_info);
5092 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5096 /* switch the codec to the b-channel */
5097 if (esc_chi[0] && plci && !plci->SuppState) {
5098 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101 if (plci->tel == ADV_VOICE && plci->appl) {
5102 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5106 if (plci->appl) plci->appl->Number++;
5108 switch (plci->Sig.Ind) {
5109 /* Response to Get_Supported_Services request */
5111 dbug(1, dprintf("S_Supported"));
5112 if (!plci->appl) break;
5113 if (pty_cai[0] == 4)
5115 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5119 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5121 PUT_WORD(&CF_Ind[1], 0);
5122 PUT_WORD(&CF_Ind[4], 0);
5123 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5127 /* Supplementary Service rejected */
5129 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130 if (!pty_cai[0]) break;
5135 case THREE_PTY_BEGIN:
5136 if (!plci->relatedPTYPLCI) break;
5137 tplci = plci->relatedPTYPLCI;
5138 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139 if (tplci->tel) rId |= EXT_CONTROLLER;
5140 if (pty_cai[5] == ECT_EXECUTE)
5142 PUT_WORD(&SS_Ind[1], S_ECT);
5144 plci->vswitchstate = 0;
5145 plci->relatedPTYPLCI->vswitchstate = 0;
5150 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5152 if (pty_cai[2] != 0xff)
5154 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5158 PUT_WORD(&SS_Ind[4], 0x300E);
5160 plci->relatedPTYPLCI = NULL;
5162 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5165 case CALL_DEFLECTION:
5166 if (pty_cai[2] != 0xff)
5168 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5172 PUT_WORD(&SS_Ind[4], 0x300E);
5174 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175 for (i = 0; i < max_appl; i++)
5177 if (application[i].CDEnable)
5179 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180 application[i].CDEnable = false;
5185 case DEACTIVATION_DIVERSION:
5186 case ACTIVATION_DIVERSION:
5187 case DIVERSION_INTERROGATE_CFU:
5188 case DIVERSION_INTERROGATE_CFB:
5189 case DIVERSION_INTERROGATE_CFNR:
5190 case DIVERSION_INTERROGATE_NUM:
5192 case CCBS_DEACTIVATE:
5193 case CCBS_INTERROGATE:
5194 if (!plci->appl) break;
5195 if (pty_cai[2] != 0xff)
5197 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5201 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5205 case DEACTIVATION_DIVERSION:
5206 dbug(1, dprintf("Deact_Div"));
5207 Interr_Err_Ind[0] = 0x9;
5208 Interr_Err_Ind[3] = 0x6;
5209 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5211 case ACTIVATION_DIVERSION:
5212 dbug(1, dprintf("Act_Div"));
5213 Interr_Err_Ind[0] = 0x9;
5214 Interr_Err_Ind[3] = 0x6;
5215 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5217 case DIVERSION_INTERROGATE_CFU:
5218 case DIVERSION_INTERROGATE_CFB:
5219 case DIVERSION_INTERROGATE_CFNR:
5220 dbug(1, dprintf("Interr_Div"));
5221 Interr_Err_Ind[0] = 0xa;
5222 Interr_Err_Ind[3] = 0x7;
5223 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5225 case DIVERSION_INTERROGATE_NUM:
5226 dbug(1, dprintf("Interr_Num"));
5227 Interr_Err_Ind[0] = 0xa;
5228 Interr_Err_Ind[3] = 0x7;
5229 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5232 dbug(1, dprintf("CCBS Request"));
5233 Interr_Err_Ind[0] = 0xd;
5234 Interr_Err_Ind[3] = 0xa;
5235 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5237 case CCBS_DEACTIVATE:
5238 dbug(1, dprintf("CCBS Deactivate"));
5239 Interr_Err_Ind[0] = 0x9;
5240 Interr_Err_Ind[3] = 0x6;
5241 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5243 case CCBS_INTERROGATE:
5244 dbug(1, dprintf("CCBS Interrogate"));
5245 Interr_Err_Ind[0] = 0xb;
5246 Interr_Err_Ind[3] = 0x8;
5247 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5250 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5254 case ACTIVATION_MWI:
5255 case DEACTIVATION_MWI:
5256 if (pty_cai[5] == ACTIVATION_MWI)
5258 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5260 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5262 if (pty_cai[2] != 0xff)
5264 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5268 PUT_WORD(&SS_Ind[4], 0x300E);
5271 if (plci->cr_enquiry)
5273 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5278 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5281 case CONF_ADD: /* ERROR */
5291 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5297 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298 plci->ptyState = CONNECTED;
5303 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304 plci->ptyState = CONNECTED;
5309 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310 plci->ptyState = CONNECTED;
5313 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314 plci->relatedPTYPLCI = NULL;
5315 tplci = plci->relatedPTYPLCI;
5316 if (tplci) tplci->ptyState = CONNECTED;
5317 plci->ptyState = CONNECTED;
5321 if (pty_cai[2] != 0xff)
5323 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5327 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328 within the required time */
5331 PUT_DWORD(&CONF_Ind[6], 0x0);
5332 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5337 /* Supplementary Service indicates success */
5339 dbug(1, dprintf("Service_Ind"));
5340 PUT_WORD(&CF_Ind[4], 0);
5344 case THREE_PTY_BEGIN:
5346 if (!plci->relatedPTYPLCI) break;
5347 tplci = plci->relatedPTYPLCI;
5348 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349 if (tplci->tel) rId |= EXT_CONTROLLER;
5350 if (pty_cai[5] == ECT_EXECUTE)
5352 PUT_WORD(&SS_Ind[1], S_ECT);
5354 if (plci->vswitchstate != 3)
5357 plci->ptyState = IDLE;
5358 plci->relatedPTYPLCI = NULL;
5363 dbug(1, dprintf("ECT OK"));
5364 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5371 switch (plci->ptyState)
5374 plci->ptyState = CONNECTED;
5375 dbug(1, dprintf("3PTY ON"));
5379 plci->ptyState = IDLE;
5380 plci->relatedPTYPLCI = NULL;
5382 dbug(1, dprintf("3PTY OFF"));
5385 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5390 case CALL_DEFLECTION:
5391 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392 for (i = 0; i < max_appl; i++)
5394 if (application[i].CDEnable)
5396 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397 application[i].CDEnable = false;
5402 case DEACTIVATION_DIVERSION:
5403 case ACTIVATION_DIVERSION:
5404 if (!plci->appl) break;
5405 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5411 case DIVERSION_INTERROGATE_CFU:
5412 case DIVERSION_INTERROGATE_CFB:
5413 case DIVERSION_INTERROGATE_CFNR:
5414 case DIVERSION_INTERROGATE_NUM:
5416 case CCBS_DEACTIVATE:
5417 case CCBS_INTERROGATE:
5418 if (!plci->appl) break;
5421 case DIVERSION_INTERROGATE_CFU:
5422 case DIVERSION_INTERROGATE_CFB:
5423 case DIVERSION_INTERROGATE_CFNR:
5424 dbug(1, dprintf("Interr_Div"));
5425 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5428 case DIVERSION_INTERROGATE_NUM:
5429 dbug(1, dprintf("Interr_Num"));
5430 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5434 dbug(1, dprintf("CCBS Request"));
5435 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5438 case CCBS_DEACTIVATE:
5439 dbug(1, dprintf("CCBS Deactivate"));
5440 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5443 case CCBS_INTERROGATE:
5444 dbug(1, dprintf("CCBS Interrogate"));
5445 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5449 PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5455 case ACTIVATION_MWI:
5456 case DEACTIVATION_MWI:
5457 if (pty_cai[5] == ACTIVATION_MWI)
5459 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5461 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462 if (plci->cr_enquiry)
5464 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5469 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5472 case MWI_INDICATION:
5473 if (pty_cai[0] >= 0x12)
5475 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5480 if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5482 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5486 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5491 for (i = 0; i < max_appl; i++)
5493 if (a->Notification_Mask[i]&SMASK_MWI)
5495 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5503 facility[2] = 0; /* returncode */
5505 else facility[2] = 0xff;
5510 facility[2] = 0xff; /* returncode */
5513 facility[1] = MWI_RESPONSE; /* Function */
5514 add_p(plci, CAI, facility);
5515 add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516 sig_req(plci, S_SERVICE, 0);
5519 next_internal_command(Id, plci);
5521 case CONF_ADD: /* OK */
5526 case CONF_PARTYDISC:
5532 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533 if (pty_cai[0] == 6)
5536 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5540 PUT_DWORD(&CONF_Ind[6], 0x0);
5544 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5549 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5554 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5559 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5561 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562 tplci = plci->relatedPTYPLCI;
5563 if (tplci) tplci->ptyState = CONNECTED;
5565 case CONF_PARTYDISC:
5568 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5570 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5573 plci->ptyState = CONNECTED;
5574 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5576 case CCBS_INFO_RETAIN:
5577 case CCBS_ERASECALLLINKAGEID:
5578 case CCBS_STOP_ALERTING:
5583 case CCBS_INFO_RETAIN:
5584 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5586 case CCBS_STOP_ALERTING:
5587 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5589 case CCBS_ERASECALLLINKAGEID:
5590 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5598 PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5600 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5602 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5606 for (i = 0; i < max_appl; i++)
5607 if (a->Notification_Mask[i] & SMASK_CCBS)
5608 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5617 i = _L3_CAUSE | cau[2];
5618 if (cau[2] == 0) i = 0x3603;
5624 PUT_WORD(&SS_Ind[1], S_HOLD);
5625 PUT_WORD(&SS_Ind[4], i);
5626 if (plci->SuppState == HOLD_REQUEST)
5628 plci->SuppState = IDLE;
5629 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5634 if (plci->SuppState == HOLD_REQUEST)
5636 plci->SuppState = CALL_HELD;
5637 CodecIdCheck(a, plci);
5638 start_internal_command(Id, plci, hold_save_command);
5642 case CALL_RETRIEVE_REJ:
5646 i = _L3_CAUSE | cau[2];
5647 if (cau[2] == 0) i = 0x3603;
5653 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654 PUT_WORD(&SS_Ind[4], i);
5655 if (plci->SuppState == RETRIEVE_REQUEST)
5657 plci->SuppState = CALL_HELD;
5658 CodecIdCheck(a, plci);
5659 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5663 case CALL_RETRIEVE_ACK:
5664 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665 if (plci->SuppState == RETRIEVE_REQUEST)
5667 plci->SuppState = IDLE;
5668 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5669 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5672 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5677 dbug(1, dprintf("Get B-ch"));
5678 start_internal_command(Id, plci, retrieve_restore_command);
5681 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5684 start_internal_command(Id, plci, retrieve_restore_command);
5689 if (plci->State != LISTENING) {
5690 sig_req(plci, HANGUP, 0);
5694 cip = find_cip(a, parms[4], parms[6]);
5695 cip_mask = 1L << cip;
5696 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697 clear_c_ind_mask(plci);
5698 if (!remove_started && !a->adapter_disabled)
5700 set_c_ind_mask_bit(plci, MAX_APPL);
5701 group_optimization(a, plci);
5702 for (i = 0; i < max_appl; i++) {
5703 if (application[i].Id
5704 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705 && CPN_filter_ok(parms[0], a, i)
5706 && test_group_ind_mask_bit(plci, i)) {
5707 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708 set_c_ind_mask_bit(plci, i);
5709 dump_c_ind_mask(plci);
5710 plci->State = INC_CON_PENDING;
5711 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5712 CALL_DIR_IN | CALL_DIR_ANSWER;
5714 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5717 /* if a listen on the ext controller is done, check if hook states */
5718 /* are supported or if just a on board codec must be activated */
5719 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720 if (a->profile.Global_Options & HANDSET)
5721 plci->tel = ADV_VOICE;
5722 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5724 if (plci->tel) Id |= EXT_CONTROLLER;
5725 a->codec_listen[i] = plci;
5728 sendf(&application[i], _CONNECT_I, Id, 0,
5729 "wSSSSSSSbSSSSS", cip, /* CIP */
5730 parms[0], /* CalledPartyNumber */
5731 multi_CiPN_parms[0], /* CallingPartyNumber */
5732 parms[2], /* CalledPartySubad */
5733 parms[3], /* CallingPartySubad */
5734 parms[4], /* BearerCapability */
5735 parms[5], /* LowLC */
5736 parms[6], /* HighLC */
5737 ai_len, /* nested struct add_i */
5738 add_i[0], /* B channel info */
5739 add_i[1], /* keypad facility */
5740 add_i[2], /* user user data */
5741 add_i[3], /* nested facility */
5742 multi_CiPN_parms[1] /* second CiPN(SCR) */
5744 SendSSExtInd(&application[i],
5748 SendSetupInfo(&application[i],
5752 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5755 clear_c_ind_mask_bit(plci, MAX_APPL);
5756 dump_c_ind_mask(plci);
5758 if (c_ind_mask_empty(plci)) {
5759 sig_req(plci, HANGUP, 0);
5763 plci->notifiedcall = 0;
5768 case CALL_PEND_NOTIFY:
5769 plci->notifiedcall = 1;
5775 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5777 if (plci->internal_command == PERM_COD_CONN_PEND)
5779 if (plci->State == ADVANCED_VOICE_NOSIG)
5781 dbug(1, dprintf("***Codec OK"));
5782 if (a->AdvSignalPLCI)
5784 tplci = a->AdvSignalPLCI;
5785 if (tplci->spoofed_msg)
5787 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5789 tplci->internal_command = 0;
5790 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791 switch (tplci->spoofed_msg)
5794 tplci->command = _CONNECT_I | RESPONSE;
5795 api_load_msg(&tplci->saved_msg, saved_parms);
5796 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5799 /* early B3 connect (CIP mask bit 9) no release after a disc */
5800 add_p(tplci, LLI, "\x01\x01");
5802 add_s(tplci, CONN_NR, &saved_parms[2]);
5803 add_s(tplci, LLC, &saved_parms[4]);
5804 add_ai(tplci, &saved_parms[5]);
5805 tplci->State = INC_CON_ACCEPT;
5806 sig_req(tplci, CALL_RES, 0);
5810 case AWAITING_SELECT_B:
5811 dbug(1, dprintf("Select_B continue"));
5812 start_internal_command(x_Id, tplci, select_b_command);
5815 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5818 dbug(1, dprintf("No SigID!"));
5819 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5823 tplci->command = _MANUFACTURER_R;
5824 api_load_msg(&tplci->saved_msg, saved_parms);
5825 dir = saved_parms[2].info[0];
5827 sig_req(tplci, CALL_REQ, 0);
5830 sig_req(tplci, LISTEN_REQ, 0);
5833 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5836 case (CALL_REQ | AWAITING_MANUF_CON):
5837 sig_req(tplci, CALL_REQ, 0);
5844 dbug(1, dprintf("No SigID!"));
5845 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5849 tplci->command = _CONNECT_R;
5850 api_load_msg(&tplci->saved_msg, saved_parms);
5851 add_s(tplci, CPN, &saved_parms[1]);
5852 add_s(tplci, DSA, &saved_parms[3]);
5853 add_ai(tplci, &saved_parms[9]);
5854 sig_req(tplci, CALL_REQ, 0);
5859 tplci->command = C_RETRIEVE_REQ;
5860 sig_req(tplci, CALL_RETRIEVE, 0);
5864 tplci->spoofed_msg = 0;
5865 if (tplci->internal_command == 0)
5866 next_internal_command(x_Id, tplci);
5869 next_internal_command(Id, plci);
5872 dbug(1, dprintf("***Codec Hook Init Req"));
5873 plci->internal_command = PERM_COD_HOOK;
5874 add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5875 sig_req(plci, TEL_CTRL, 0);
5879 else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5880 && plci->State != INC_ACT_PENDING)
5882 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5885 chi[2] = plci->b_channel;
5886 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5888 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889 plci->State = INC_ACT_PENDING;
5894 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896 switch (ie[1] & 0x91) {
5897 case 0x80: /* hook off */
5899 if (plci->internal_command == PERM_COD_HOOK)
5901 dbug(1, dprintf("init:hook_off"));
5902 plci->hook_state = ie[1];
5903 next_internal_command(Id, plci);
5906 else /* ignore doubled hook indications */
5908 if (((plci->hook_state) & 0xf0) == 0x80)
5910 dbug(1, dprintf("ignore hook"));
5913 plci->hook_state = ie[1]&0x91;
5915 /* check for incoming call pending */
5916 /* and signal '+'.Appl must decide */
5917 /* with connect_res if call must */
5918 /* accepted or not */
5919 for (i = 0, tplci = NULL; i < max_appl; i++) {
5920 if (a->codec_listen[i]
5921 && (a->codec_listen[i]->State == INC_CON_PENDING
5922 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5923 tplci = a->codec_listen[i];
5924 tplci->appl = &application[i];
5927 /* no incoming call, do outgoing call */
5928 /* and signal '+' if outg. setup */
5929 if (!a->AdvSignalPLCI && !tplci) {
5930 if ((i = get_plci(a))) {
5931 a->AdvSignalPLCI = &a->plci[i - 1];
5932 tplci = a->AdvSignalPLCI;
5933 tplci->tel = ADV_VOICE;
5934 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936 /* early B3 connect (CIP mask bit 9) no release after a disc */
5937 add_p(tplci, LLI, "\x01\x01");
5939 add_p(tplci, CAI, voice_cai);
5940 add_p(tplci, OAD, a->TelOAD);
5941 add_p(tplci, OSA, a->TelOSA);
5942 add_p(tplci, SHIFT | 6, NULL);
5943 add_p(tplci, SIN, "\x02\x01\x00");
5944 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945 sig_req(tplci, ASSIGN, DSIG_ID);
5946 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5947 a->AdvSignalPLCI->command = 0;
5948 tplci->appl = a->AdvSignalAppl;
5949 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5956 Id = ((word)tplci->Id << 8) | a->Id;
5957 Id |= EXT_CONTROLLER;
5962 "ws", (word)0, "\x01+");
5965 case 0x90: /* hook on */
5967 if (plci->internal_command == PERM_COD_HOOK)
5969 dbug(1, dprintf("init:hook_on"));
5970 plci->hook_state = ie[1] & 0x91;
5971 next_internal_command(Id, plci);
5974 else /* ignore doubled hook indications */
5976 if (((plci->hook_state) & 0xf0) == 0x90) break;
5977 plci->hook_state = ie[1] & 0x91;
5979 /* hangup the adv. voice call and signal '-' to the appl */
5980 if (a->AdvSignalPLCI) {
5981 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982 if (plci->tel) Id |= EXT_CONTROLLER;
5983 sendf(a->AdvSignalAppl,
5987 "ws", (word)0, "\x01-");
5988 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5989 a->AdvSignalPLCI->command = 0;
5990 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991 send_req(a->AdvSignalPLCI);
5999 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000 PUT_WORD(&resume_cau[4], GOOD);
6001 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6005 clear_c_ind_mask(plci);
6007 if (plci->NL.Id && !plci->nl_remove_id) {
6009 nl_req_ncci(plci, REMOVE, 0);
6011 if (!plci->sig_remove_id) {
6012 plci->internal_command = 0;
6013 sig_req(plci, REMOVE, 0);
6016 if (!plci->channels) {
6017 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6026 plci->hangup_flow_ctrl_timer = 0;
6027 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6030 i = _L3_CAUSE | cau[2];
6031 if (cau[2] == 0) i = 0;
6032 else if (cau[2] == 8) i = _L1_ERROR;
6033 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6040 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6042 for (i = 0; i < max_appl; i++)
6044 if (test_c_ind_mask_bit(plci, i))
6045 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6050 clear_c_ind_mask(plci);
6054 if (plci->State == LISTENING)
6056 plci->notifiedcall = 0;
6059 plci->State = INC_DIS_PENDING;
6060 if (c_ind_mask_empty(plci))
6063 if (plci->NL.Id && !plci->nl_remove_id)
6066 nl_req_ncci(plci, REMOVE, 0);
6068 if (!plci->sig_remove_id)
6070 plci->internal_command = 0;
6071 sig_req(plci, REMOVE, 0);
6078 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6079 /* result in a second HANGUP! Don't generate another */
6081 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6083 if (plci->State == RESUMING)
6085 PUT_WORD(&resume_cau[4], i);
6086 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6088 plci->State = INC_DIS_PENDING;
6089 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6095 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6099 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6102 if (plci->relatedPTYPLCI &&
6103 plci->vswitchstate == 3 &&
6104 plci->relatedPTYPLCI->vswitchstate == 3 &&
6105 parms[MAXPARMSIDS - 1][0])
6107 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109 send_req(plci->relatedPTYPLCI);
6111 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6118 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6126 dbug(1, dprintf("SetupInfo"));
6128 for (i = 0; i < MAXPARMSIDS; i++) {
6135 dbug(1, dprintf("CPN "));
6136 Info_Number = 0x0070;
6138 Info_Sent_Flag = true;
6140 case 8: /* display */
6141 dbug(1, dprintf("display(%d)", i));
6142 Info_Number = 0x0028;
6144 Info_Sent_Flag = true;
6146 case 16: /* Channel Id */
6147 dbug(1, dprintf("CHI"));
6148 Info_Number = 0x0018;
6150 Info_Sent_Flag = true;
6151 mixer_set_bchannel_id(plci, Info_Element);
6153 case 19: /* Redirected Number */
6154 dbug(1, dprintf("RDN"));
6155 Info_Number = 0x0074;
6157 Info_Sent_Flag = true;
6159 case 20: /* Redirected Number extended */
6160 dbug(1, dprintf("RDX"));
6161 Info_Number = 0x0073;
6163 Info_Sent_Flag = true;
6165 case 22: /* Redirecing Number */
6166 dbug(1, dprintf("RIN"));
6167 Info_Number = 0x0076;
6169 Info_Sent_Flag = true;
6177 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6178 Info_Number = 0x8000 | 5;
6183 if (Info_Sent_Flag && Info_Number) {
6184 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6185 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6192 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6201 static byte charges[5] = {4, 0, 0, 0, 0};
6202 static byte cause[] = {0x02, 0x80, 0x00};
6205 dbug(1, dprintf("InfoParse "));
6210 && plci->Sig.Ind != NCR_FACILITY
6213 dbug(1, dprintf("NoParse "));
6217 for (i = 0; i < MAXPARMSIDS; i++) {
6224 dbug(1, dprintf("CPN "));
6225 Info_Number = 0x0070;
6228 case 7: /* ESC_CAU */
6229 dbug(1, dprintf("cau(0x%x)", ie[2]));
6230 Info_Number = 0x0008;
6233 Info_Element = NULL;
6235 case 8: /* display */
6236 dbug(1, dprintf("display(%d)", i));
6237 Info_Number = 0x0028;
6240 case 9: /* Date display */
6241 dbug(1, dprintf("date(%d)", i));
6242 Info_Number = 0x0029;
6245 case 10: /* charges */
6246 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6247 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6248 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6249 Info_Number = 0x4000;
6251 Info_Element = charges;
6253 case 11: /* user user info */
6254 dbug(1, dprintf("uui"));
6255 Info_Number = 0x007E;
6258 case 12: /* congestion receiver ready */
6259 dbug(1, dprintf("clRDY"));
6260 Info_Number = 0x00B0;
6264 case 13: /* congestion receiver not ready */
6265 dbug(1, dprintf("clNRDY"));
6266 Info_Number = 0x00BF;
6270 case 15: /* Keypad Facility */
6271 dbug(1, dprintf("KEY"));
6272 Info_Number = 0x002C;
6275 case 16: /* Channel Id */
6276 dbug(1, dprintf("CHI"));
6277 Info_Number = 0x0018;
6279 mixer_set_bchannel_id(plci, Info_Element);
6281 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6282 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6283 if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6284 Info_Number = 0x0008;
6286 if (cause[2] != ie[2]) Info_Element = cause;
6288 case 19: /* Redirected Number */
6289 dbug(1, dprintf("RDN"));
6290 Info_Number = 0x0074;
6293 case 22: /* Redirecing Number */
6294 dbug(1, dprintf("RIN"));
6295 Info_Number = 0x0076;
6298 case 23: /* Notification Indicator */
6299 dbug(1, dprintf("NI"));
6300 Info_Number = (word)NI;
6303 case 26: /* Call State */
6304 dbug(1, dprintf("CST"));
6305 Info_Number = (word)CST;
6306 Info_Mask = 0x01; /* do with cause i.e. for now */
6308 case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6309 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6310 Info_Number = 0x8000 | ie[3];
6311 if (iesent) Info_Mask = 0xffff;
6312 else Info_Mask = 0x10;
6323 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6325 for (j = 0; j < max_appl; j++)
6327 appl = &application[j];
6330 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6332 dbug(1, dprintf("NCR_Ind"));
6334 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6338 else if (!plci->appl)
6339 { /* overlap receiving broadcast */
6340 if (Info_Number == CPN
6341 || Info_Number == KEY
6342 || Info_Number == NI
6343 || Info_Number == DSP
6344 || Info_Number == UUI)
6346 for (j = 0; j < max_appl; j++)
6348 if (test_c_ind_mask_bit(plci, j))
6350 dbug(1, dprintf("Ovl_Ind"));
6352 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6356 } /* all other signalling states */
6357 else if (Info_Number
6358 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6360 dbug(1, dprintf("Std_Ind"));
6362 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6368 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6369 dword info_mask, byte setupParse)
6383 && plci->Sig.Ind != NCR_FACILITY
6387 dbug(1, dprintf("NoM-IEParse "));
6390 dbug(1, dprintf("M-IEParse "));
6392 for (i = 0; i < MAX_MULTI_IE; i++)
6399 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6400 Info_Number = (word)ie_type;
6401 Info_Mask = (word)info_mask;
6404 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6406 for (j = 0; j < max_appl; j++)
6408 appl = &application[j];
6411 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6414 dbug(1, dprintf("Mlt_NCR_Ind"));
6415 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6419 else if (!plci->appl && Info_Number)
6420 { /* overlap receiving broadcast */
6421 for (j = 0; j < max_appl; j++)
6423 if (test_c_ind_mask_bit(plci, j))
6426 dbug(1, dprintf("Mlt_Ovl_Ind"));
6427 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6430 } /* all other signalling states */
6431 else if (Info_Number
6432 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6435 dbug(1, dprintf("Mlt_Std_Ind"));
6436 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6442 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6445 /* Format of multi_ssext_parms[i][]:
6448 2 byte SSEXT_REQ/SSEXT_IND
6456 && plci->Sig.Ind != NCR_FACILITY
6458 for (i = 0; i < MAX_MULTI_IE; i++)
6460 if (parms[i][0] < 6) continue;
6461 if (parms[i][2] == SSEXT_REQ) continue;
6465 parms[i][0] = 0; /* kill it */
6466 sendf(appl, _MANUFACTURER_I,
6474 else if (plci->appl)
6476 parms[i][0] = 0; /* kill it */
6477 sendf(plci->appl, _MANUFACTURER_I,
6488 static void nl_ind(PLCI *plci)
6493 DIVA_CAPI_ADAPTER *a;
6499 byte len, ncci_state;
6502 word fax_feature_bits;
6503 byte fax_send_edata_ack;
6504 static byte v120_header_buffer[2 + 3];
6505 static word fax_info[] = {
6506 0, /* T30_SUCCESS */
6507 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6511 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6512 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6513 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6514 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6515 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6516 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6517 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6518 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6519 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6520 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6523 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6524 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6525 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6527 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6537 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6538 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6539 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6540 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6541 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6542 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6543 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6544 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6545 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6546 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6547 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6548 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6549 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6550 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6551 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6552 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6555 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6558 static word rtp_info[] = {
6559 GOOD, /* RTP_SUCCESS */
6560 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6563 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6565 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6566 0x00000000, 0x00000000, 0x00000000, 0x00000000
6569 ch = plci->NL.IndCh;
6571 ncci = a->ch_ncci[ch];
6572 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6573 if (plci->tel) Id |= EXT_CONTROLLER;
6574 APPLptr = plci->appl;
6575 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",
6576 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6578 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6580 if (plci->nl_remove_id)
6582 plci->NL.RNR = 2; /* discard */
6583 dbug(1, dprintf("NL discard while remove pending"));
6586 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6588 if (plci->State == INC_DIS_PENDING
6589 || plci->State == OUTG_DIS_PENDING
6590 || plci->State == IDLE)
6592 plci->NL.RNR = 2; /* discard */
6593 dbug(1, dprintf("discard n_connect"));
6596 if (plci->State < INC_ACT_PENDING)
6598 plci->NL.RNR = 1; /* flow control */
6599 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6604 if (!APPLptr) /* no application or invalid data */
6605 { /* while reloading the DSP */
6606 dbug(1, dprintf("discard1"));
6611 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6612 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6613 || (plci->B2_prot == 7)
6614 || (plci->B3_prot == 7)))
6616 plci->ncpi_buffer[0] = 0;
6618 ncpi_state = plci->ncpi_state;
6619 if (plci->NL.complete == 1)
6621 byte *data = &plci->NL.RBuffer->P[0];
6623 if ((plci->NL.RBuffer->length >= 12)
6624 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6625 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6627 word conn_opt, ncpi_opt = 0x00;
6628 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6630 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6631 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6632 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6633 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6635 data++; /* indication code */
6636 data += 2; /* timestamp */
6637 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6638 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6639 data++; /* connected norm */
6640 conn_opt = GET_WORD(data);
6641 data += 2; /* connected options */
6643 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6645 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6647 ncpi_opt |= MDM_NCPI_ECM_V42;
6649 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6651 ncpi_opt |= MDM_NCPI_ECM_MNP;
6655 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6657 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6659 ncpi_opt |= MDM_NCPI_COMPRESSED;
6661 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6662 plci->ncpi_buffer[0] = 4;
6664 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6667 if (plci->B3_prot == 7)
6669 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6670 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6671 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6673 a->ncci_state[ncci] = INC_ACT_PENDING;
6674 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6675 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6679 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6680 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6681 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6682 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6690 if (plci->NL.complete == 2)
6692 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6693 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6695 switch (plci->RData[0].P[0])
6698 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6699 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6700 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6702 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6703 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6706 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6707 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6709 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6710 dtmf_confirmation(Id, plci);
6714 case UDATA_INDICATION_MIXER_TAP_DATA:
6715 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6716 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6719 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6720 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6725 case UDATA_INDICATION_MIXER_COEFS_SET:
6726 mixer_indication_coefs_set(Id, plci);
6728 case UDATA_INDICATION_XCONNECT_FROM:
6729 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6731 case UDATA_INDICATION_XCONNECT_TO:
6732 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6736 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6737 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6748 if ((plci->RData[0].PLength != 0)
6749 && ((plci->B2_prot == B2_V120_ASYNC)
6750 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6751 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6754 sendf(plci->appl, _DATA_B3_I, Id, 0,
6757 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6765 sendf(plci->appl, _DATA_B3_I, Id, 0,
6768 plci->RData[0].PLength,
6777 fax_feature_bits = 0;
6778 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6779 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6780 (plci->NL.Ind & 0x0f) == N_DISC ||
6781 (plci->NL.Ind & 0x0f) == N_EDATA ||
6782 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6785 plci->ncpi_buffer[0] = 0;
6786 switch (plci->B3_prot) {
6789 break; /* no network control protocol info - jfr */
6792 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6793 plci->ncpi_buffer[0] = (byte)(i + 3);
6794 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6795 plci->ncpi_buffer[2] = 0;
6796 plci->ncpi_buffer[3] = 0;
6798 case 4: /*T.30 - FAX*/
6799 case 5: /*T.30 - FAX*/
6800 if (plci->NL.RLength >= sizeof(T30_INFO))
6802 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6804 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6805 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6806 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6807 if (plci->B3_prot == 5)
6809 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6810 i |= 0x8000; /* This is not an ECM connection */
6811 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6812 i |= 0x4000; /* This is a connection with MMR compression */
6813 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6814 i |= 0x2000; /* This is a connection with MR compression */
6815 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6816 i |= 0x0004; /* More documents */
6817 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6818 i |= 0x0002; /* Fax-polling indication */
6820 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6821 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6822 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6823 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6824 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6825 plci->ncpi_buffer[len] = 0;
6826 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6828 plci->ncpi_buffer[len] = 20;
6829 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6830 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6832 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6834 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6835 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6837 info = _FAX_PROTOCOL_ERROR;
6840 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6841 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6843 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6844 while (i < plci->NL.RBuffer->length)
6845 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6848 plci->ncpi_buffer[0] = len;
6849 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6850 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6852 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6853 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6854 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6855 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6856 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6857 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6858 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6859 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6861 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6863 if (((plci->NL.Ind & 0x0f) == N_DISC)
6864 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6865 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6866 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6868 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6874 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6876 if (plci->NL.RLength != 0)
6878 info = rtp_info[plci->NL.RBuffer->P[0]];
6879 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6880 for (i = 1; i < plci->NL.RLength; i++)
6881 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6889 switch (plci->NL.Ind & 0x0f) {
6891 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6893 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6894 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6895 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6897 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6898 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6899 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6900 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6901 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6902 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6904 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6905 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6906 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6907 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6908 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6909 fax_send_edata_ack = false;
6912 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6914 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6917 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6918 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6919 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6920 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6922 a->ncci_state[ncci] = INC_ACT_PENDING;
6923 if (plci->B3_prot == 4)
6924 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6926 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6927 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6931 case EDATA_T30_TRAIN_OK:
6932 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6933 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6934 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6936 if (plci->B3_prot == 4)
6937 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6939 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6940 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6944 case EDATA_T30_EOP_CAPI:
6945 if (a->ncci_state[ncci] == CONNECTED)
6947 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6948 a->ncci_state[ncci] = INC_DIS_PENDING;
6949 plci->ncpi_state = 0;
6950 fax_send_edata_ack = false;
6957 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6959 case EDATA_T30_TRAIN_OK:
6960 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6961 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6962 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6964 if (plci->B3_prot == 4)
6965 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6967 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6968 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6973 if (fax_send_edata_ack)
6975 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6976 plci->fax_edata_ack_length = 1;
6977 start_internal_command(Id, plci, fax_edata_ack_command);
6982 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6986 if (!a->ch_ncci[ch])
6988 ncci = get_ncci(plci, ch, 0);
6989 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6991 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6992 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6994 msg = _CONNECT_B3_I;
6995 if (a->ncci_state[ncci] == IDLE)
6997 else if (plci->B3_prot == 1)
6998 msg = _CONNECT_B3_T90_ACTIVE_I;
7000 a->ncci_state[ncci] = INC_CON_PENDING;
7001 if (plci->B3_prot == 4)
7002 sendf(plci->appl, msg, Id, 0, "s", "");
7004 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7007 dbug(1, dprintf("N_connect_Ack"));
7008 if (plci->internal_command_queue[0]
7009 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7010 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7011 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7013 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7014 if (!plci->internal_command)
7015 next_internal_command(Id, plci);
7018 msg = _CONNECT_B3_ACTIVE_I;
7019 if (plci->B3_prot == 1)
7021 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7022 msg = _CONNECT_B3_T90_ACTIVE_I;
7023 a->ncci_state[ncci] = INC_ACT_PENDING;
7024 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7026 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7028 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7029 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7030 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7032 a->ncci_state[ncci] = INC_ACT_PENDING;
7033 if (plci->B3_prot == 4)
7034 sendf(plci->appl, msg, Id, 0, "s", "");
7036 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7037 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7042 a->ncci_state[ncci] = INC_ACT_PENDING;
7043 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7045 if (plci->adjust_b_restore)
7047 plci->adjust_b_restore = false;
7048 start_internal_command(Id, plci, adjust_b_restore);
7053 if (plci->internal_command_queue[0]
7054 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7055 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7056 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7058 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7059 if (!plci->internal_command)
7060 next_internal_command(Id, plci);
7062 ncci_state = a->ncci_state[ncci];
7063 ncci_remove(plci, ncci, false);
7065 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7066 /* channel, so we cannot store the state in ncci_state! The */
7067 /* information which channel we received a N_DISC is thus */
7068 /* stored in the inc_dis_ncci_table buffer. */
7069 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7070 plci->inc_dis_ncci_table[i] = (byte) ncci;
7072 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7074 && (plci->B1_resource == 16)
7075 && (plci->State <= CONNECTED))
7078 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7079 PUT_WORD(&plci->ncpi_buffer[1], i);
7080 PUT_WORD(&plci->ncpi_buffer[3], 0);
7081 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7082 PUT_WORD(&plci->ncpi_buffer[5], i);
7083 PUT_WORD(&plci->ncpi_buffer[7], 0);
7084 plci->ncpi_buffer[len] = 0;
7085 plci->ncpi_buffer[0] = len;
7086 if (plci->B3_prot == 4)
7087 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7091 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7092 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7094 plci->ncpi_buffer[++len] = 0;
7095 plci->ncpi_buffer[++len] = 0;
7096 plci->ncpi_buffer[++len] = 0;
7097 plci->ncpi_buffer[0] = len;
7100 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7102 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7103 plci->ncpi_state = 0;
7104 sig_req(plci, HANGUP, 0);
7106 plci->State = OUTG_DIS_PENDING;
7109 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7110 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7111 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7113 if (ncci_state == IDLE)
7117 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7118 if (plci->State == SUSPENDING) {
7123 "ws", (word)3, "\x03\x04\x00\x00");
7124 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7131 else if (plci->channels)
7133 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7134 plci->ncpi_state = 0;
7135 if ((ncci_state == OUTG_REJ_PENDING)
7136 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7138 sig_req(plci, HANGUP, 0);
7140 plci->State = OUTG_DIS_PENDING;
7145 a->ncci_state[ncci] = INC_RES_PENDING;
7146 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7149 a->ncci_state[ncci] = CONNECTED;
7150 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7154 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7156 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7157 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7158 plci->NL.R = plci->RData;
7164 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7165 || (a->ncci_state[ncci] == IDLE)
7166 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7171 if ((a->ncci_state[ncci] != CONNECTED)
7172 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7173 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7175 dbug(1, dprintf("flow control"));
7176 plci->NL.RNR = 1; /* flow control */
7177 channel_x_off(plci, ch, 0);
7181 NCCIcode = ncci | (((word)a->Id) << 8);
7183 /* count all buffers within the Application pool */
7184 /* belonging to the same NCCI. If this is below the */
7185 /* number of buffers available per NCCI we accept */
7186 /* this packet, otherwise we reject it */
7189 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7190 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7191 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7194 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7196 dbug(3, dprintf("Flow-Control"));
7198 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7199 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7202 dbug(3, dprintf("DiscardData"));
7204 channel_x_off(plci, ch, 0);
7210 APPLptr->NCCIDataFlowCtrlTimer = 0;
7213 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7214 if (!plci->RData[0].P) {
7216 channel_x_off(plci, ch, 0);
7220 APPLptr->DataNCCI[Num] = NCCIcode;
7221 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7222 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7225 plci->RFlags = plci->NL.Ind >> 4;
7226 plci->RData[0].PLength = APPLptr->MaxDataLength;
7227 plci->NL.R = plci->RData;
7228 if ((plci->NL.RLength != 0)
7229 && ((plci->B2_prot == B2_V120_ASYNC)
7230 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7231 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7233 plci->RData[1].P = plci->RData[0].P;
7234 plci->RData[1].PLength = plci->RData[0].PLength;
7235 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7236 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7237 plci->RData[0].PLength = 1;
7239 plci->RData[0].PLength = 2;
7240 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7241 plci->RFlags |= 0x0010;
7242 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7243 plci->RFlags |= 0x8000;
7248 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7249 plci->RFlags |= 0x0010;
7251 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7252 plci->RFlags |= 0x0001;
7266 /*------------------------------------------------------------------*/
7267 /* find a free PLCI */
7268 /*------------------------------------------------------------------*/
7270 static word get_plci(DIVA_CAPI_ADAPTER *a)
7276 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7277 if (i == a->max_plci) {
7278 dbug(1, dprintf("get_plci: out of PLCIs"));
7282 plci->Id = (byte)(i + 1);
7290 plci->relatedPTYPLCI = NULL;
7292 plci->SuppState = IDLE;
7295 plci->B1_resource = 0;
7300 plci->m_command = 0;
7301 init_internal_command_queue(plci);
7303 plci->req_in_start = 0;
7306 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7307 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7308 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7310 plci->data_sent = false;
7311 plci->send_disc = 0;
7312 plci->sig_global_req = 0;
7313 plci->sig_remove_id = 0;
7314 plci->nl_global_req = 0;
7315 plci->nl_remove_id = 0;
7317 plci->manufacturer = false;
7318 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7319 plci->spoofed_msg = 0;
7321 plci->cr_enquiry = false;
7322 plci->hangup_flow_ctrl_timer = 0;
7324 plci->ncci_ring_list = 0;
7325 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7326 clear_c_ind_mask(plci);
7327 set_group_ind_mask(plci);
7328 plci->fax_connect_info_length = 0;
7329 plci->nsf_control_bits = 0;
7330 plci->ncpi_state = 0x00;
7331 plci->ncpi_buffer[0] = 0;
7333 plci->requested_options_conn = 0;
7334 plci->requested_options = 0;
7335 plci->notifiedcall = 0;
7336 plci->vswitchstate = 0;
7338 plci->vsprotdialect = 0;
7339 init_b1_config(plci);
7340 dbug(1, dprintf("get_plci(%x)", plci->Id));
7344 /*------------------------------------------------------------------*/
7345 /* put a parameter in the parameter buffer */
7346 /*------------------------------------------------------------------*/
7348 static void add_p(PLCI *plci, byte code, byte *p)
7353 if (p) p_length = p[0];
7354 add_ie(plci, code, p, p_length);
7357 /*------------------------------------------------------------------*/
7358 /* put a structure in the parameter buffer */
7359 /*------------------------------------------------------------------*/
7360 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7362 if (p) add_ie(plci, code, p->info, (word)p->length);
7365 /*------------------------------------------------------------------*/
7366 /* put multiple structures in the parameter buffer */
7367 /*------------------------------------------------------------------*/
7368 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7373 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7374 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7375 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7376 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7381 /*------------------------------------------------------------------*/
7382 /* return the channel number sent by the application in a esc_chi */
7383 /*------------------------------------------------------------------*/
7384 static byte getChannel(API_PARSE *p)
7389 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7390 if (p->info[i] == 2) {
7391 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7399 /*------------------------------------------------------------------*/
7400 /* put an information element in the parameter buffer */
7401 /*------------------------------------------------------------------*/
7403 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7407 if (!(code & 0x80) && !p_length) return;
7409 if (plci->req_in == plci->req_in_start) {
7415 plci->RBuffer[plci->req_in++] = code;
7418 plci->RBuffer[plci->req_in++] = (byte)p_length;
7419 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7422 plci->RBuffer[plci->req_in++] = 0;
7425 /*------------------------------------------------------------------*/
7426 /* put a unstructured data into the buffer */
7427 /*------------------------------------------------------------------*/
7429 static void add_d(PLCI *plci, word length, byte *p)
7433 if (plci->req_in == plci->req_in_start) {
7439 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7442 /*------------------------------------------------------------------*/
7443 /* put parameters from the Additional Info parameter in the */
7444 /* parameter buffer */
7445 /*------------------------------------------------------------------*/
7447 static void add_ai(PLCI *plci, API_PARSE *ai)
7450 API_PARSE ai_parms[5];
7452 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7456 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7459 add_s(plci, KEY, &ai_parms[1]);
7460 add_s(plci, UUI, &ai_parms[2]);
7461 add_ss(plci, FTY, &ai_parms[3]);
7464 /*------------------------------------------------------------------*/
7465 /* put parameter for b1 protocol in the parameter buffer */
7466 /*------------------------------------------------------------------*/
7468 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7471 API_PARSE bp_parms[8];
7472 API_PARSE mdm_cfg[9];
7473 API_PARSE global_config[2];
7475 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7476 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7479 API_PARSE mdm_cfg_v18[4];
7484 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7485 for (i = 0; i < 2; i++) global_config[i].length = 0;
7487 dbug(1, dprintf("add_b1"));
7488 api_save_msg(bp, "s", &plci->B_protocol);
7490 if (b_channel_info == 2) {
7491 plci->B1_resource = 0;
7492 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7493 add_p(plci, CAI, "\x01\x00");
7494 dbug(1, dprintf("Cai=1,0 (no resource)"));
7498 if (plci->tel == CODEC_PERMANENT) return 0;
7499 else if (plci->tel == CODEC) {
7500 plci->B1_resource = 1;
7501 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7502 add_p(plci, CAI, "\x01\x01");
7503 dbug(1, dprintf("Cai=1,1 (Codec)"));
7506 else if (plci->tel == ADV_VOICE) {
7507 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7508 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7509 voice_cai[1] = plci->B1_resource;
7510 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7511 add_p(plci, CAI, voice_cai);
7512 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7515 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7516 if (plci->call_dir & CALL_DIR_OUT)
7517 plci->call_dir |= CALL_DIR_ORIGINATE;
7518 else if (plci->call_dir & CALL_DIR_IN)
7519 plci->call_dir |= CALL_DIR_ANSWER;
7522 plci->B1_resource = 0x5;
7523 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7524 add_p(plci, CAI, "\x01\x05");
7528 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7529 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7530 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7532 bp_parms[6].length = 0;
7533 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7535 dbug(1, dprintf("b-form.!"));
7536 return _WRONG_MESSAGE_FORMAT;
7539 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7541 dbug(1, dprintf("b-form.!"));
7542 return _WRONG_MESSAGE_FORMAT;
7545 if (bp_parms[6].length)
7547 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7549 return _WRONG_MESSAGE_FORMAT;
7551 switch (GET_WORD(global_config[0].info))
7554 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7557 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7561 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7564 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7565 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7567 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7568 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7569 cai[1] = plci->B1_resource;
7573 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7574 for (i = 0; i < bp_parms[3].length; i++)
7575 cai[7 + i] = bp_parms[3].info[1 + i];
7576 cai[0] = 6 + bp_parms[3].length;
7577 add_p(plci, CAI, cai);
7582 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7583 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7585 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7586 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587 cai[1] = plci->B1_resource;
7591 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7593 add_p(plci, CAI, cai);
7598 if ((GET_WORD(bp_parms[0].info) >= 32)
7599 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7600 && ((GET_WORD(bp_parms[0].info) != 3)
7601 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7602 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7604 return _B1_NOT_SUPPORTED;
7606 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7607 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7610 cai[1] = plci->B1_resource;
7611 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7613 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7614 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7615 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7617 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7619 if (bp_parms[3].length)
7621 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7623 return (_WRONG_MESSAGE_FORMAT);
7626 cai[2] = 0; /* Bit rate for adaptation */
7628 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7630 PUT_WORD(&cai[13], 0); /* Min Tx speed */
7631 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7632 PUT_WORD(&cai[17], 0); /* Min Rx speed */
7633 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7635 cai[3] = 0; /* Async framing parameters */
7636 switch (GET_WORD(mdm_cfg[2].info))
7638 case 1: /* odd parity */
7639 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7640 dbug(1, dprintf("MDM: odd parity"));
7643 case 2: /* even parity */
7644 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7645 dbug(1, dprintf("MDM: even parity"));
7649 dbug(1, dprintf("MDM: no parity"));
7653 switch (GET_WORD(mdm_cfg[3].info))
7655 case 1: /* 2 stop bits */
7656 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7657 dbug(1, dprintf("MDM: 2 stop bits"));
7661 dbug(1, dprintf("MDM: 1 stop bit"));
7665 switch (GET_WORD(mdm_cfg[1].info))
7668 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7669 dbug(1, dprintf("MDM: 5 bits"));
7673 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7674 dbug(1, dprintf("MDM: 6 bits"));
7678 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7679 dbug(1, dprintf("MDM: 7 bits"));
7683 dbug(1, dprintf("MDM: 8 bits"));
7687 cai[7] = 0; /* Line taking options */
7688 cai[8] = 0; /* Modulation negotiation options */
7689 cai[9] = 0; /* Modulation options */
7691 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7693 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7694 dbug(1, dprintf("MDM: Reverse direction"));
7697 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7699 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7700 dbug(1, dprintf("MDM: Disable retrain"));
7703 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7705 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7706 dbug(1, dprintf("MDM: Disable ring tone"));
7709 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7711 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7712 dbug(1, dprintf("MDM: 1800 guard tone"));
7714 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7716 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7717 dbug(1, dprintf("MDM: 550 guard tone"));
7720 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7722 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7723 dbug(1, dprintf("MDM: V100"));
7725 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7727 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7728 dbug(1, dprintf("MDM: IN CLASS"));
7730 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7732 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7733 dbug(1, dprintf("MDM: DISABLED"));
7737 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7738 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7740 plci->requested_options |= 1L << PRIVATE_V18;
7742 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7743 plci->requested_options |= 1L << PRIVATE_VOWN;
7745 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7746 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7748 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7751 if (mdm_cfg[6].length >= 4)
7753 d = GET_DWORD(&mdm_cfg[6].info[1]);
7754 cai[7] |= (byte) d; /* line taking options */
7755 cai[9] |= (byte)(d >> 8); /* modulation options */
7756 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7757 cai[++i] = (byte)(d >> 24);
7758 if (mdm_cfg[6].length >= 8)
7760 d = GET_DWORD(&mdm_cfg[6].info[5]);
7761 cai[10] |= (byte) d; /* disabled modulations mask */
7762 cai[11] |= (byte)(d >> 8);
7763 if (mdm_cfg[6].length >= 12)
7765 d = GET_DWORD(&mdm_cfg[6].info[9]);
7766 cai[12] = (byte) d; /* enabled modulations mask */
7767 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7768 cai[++i] = (byte)(d >> 16);
7769 cai[++i] = (byte)(d >> 24);
7771 if (mdm_cfg[6].length >= 14)
7773 w = GET_WORD(&mdm_cfg[6].info[13]);
7775 PUT_WORD(&cai[13], w); /* min tx speed */
7776 if (mdm_cfg[6].length >= 16)
7778 w = GET_WORD(&mdm_cfg[6].info[15]);
7780 PUT_WORD(&cai[15], w); /* max tx speed */
7781 if (mdm_cfg[6].length >= 18)
7783 w = GET_WORD(&mdm_cfg[6].info[17]);
7785 PUT_WORD(&cai[17], w); /* min rx speed */
7786 if (mdm_cfg[6].length >= 20)
7788 w = GET_WORD(&mdm_cfg[6].info[19]);
7790 PUT_WORD(&cai[19], w); /* max rx speed */
7791 if (mdm_cfg[6].length >= 22)
7793 w = GET_WORD(&mdm_cfg[6].info[21]);
7794 cai[23] = (byte)(-((short) w)); /* transmit level */
7795 if (mdm_cfg[6].length >= 24)
7797 w = GET_WORD(&mdm_cfg[6].info[23]);
7798 cai[22] |= (byte) w; /* info options mask */
7799 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7811 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7813 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7815 for (n = 0; n < 3; n++)
7817 cai[i] = (byte)(mdm_cfg_v18[n].length);
7818 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7819 cai[i + j] = mdm_cfg_v18[n].info[j];
7824 cai[0] = (byte)(i - 1);
7830 if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7831 GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7833 if (bp_parms[3].length) {
7834 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7835 switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7838 if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7839 dbug(1, dprintf("56k sync HSCX"));
7844 else if (GET_WORD(bp_parms[0].info) == 2) {
7845 dbug(1, dprintf("56k async DSP"));
7849 case 50: cai[2] = 1; break;
7850 case 75: cai[2] = 1; break;
7851 case 110: cai[2] = 1; break;
7852 case 150: cai[2] = 1; break;
7853 case 200: cai[2] = 1; break;
7854 case 300: cai[2] = 1; break;
7855 case 600: cai[2] = 1; break;
7856 case 1200: cai[2] = 2; break;
7857 case 2400: cai[2] = 3; break;
7858 case 4800: cai[2] = 4; break;
7859 case 7200: cai[2] = 10; break;
7860 case 9600: cai[2] = 5; break;
7861 case 12000: cai[2] = 13; break;
7862 case 24000: cai[2] = 0; break;
7863 case 14400: cai[2] = 11; break;
7864 case 19200: cai[2] = 6; break;
7865 case 28800: cai[2] = 12; break;
7866 case 38400: cai[2] = 7; break;
7867 case 48000: cai[2] = 8; break;
7868 case 76: cai[2] = 15; break; /* 75/1200 */
7869 case 1201: cai[2] = 14; break; /* 1200/75 */
7870 case 56001: cai[2] = 9; break; /* V.110 56000 */
7873 return _B1_PARM_NOT_SUPPORTED;
7876 if (cai[1] == 13) /* v.110 async */
7878 if (bp_parms[3].length >= 8)
7880 switch (GET_WORD(&bp_parms[3].info[3]))
7883 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7886 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7889 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7892 switch (GET_WORD(&bp_parms[3].info[5]))
7894 case 1: /* odd parity */
7895 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7897 case 2: /* even parity */
7898 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7901 switch (GET_WORD(&bp_parms[3].info[7]))
7903 case 1: /* 2 stop bits */
7904 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7910 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7911 dbug(1, dprintf("V.110 default 56k sync"));
7917 dbug(1, dprintf("V.110 default 9600 async"));
7921 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7922 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]));
7923 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7925 add_p(plci, CAI, cai);
7929 /*------------------------------------------------------------------*/
7930 /* put parameter for b2 and B3 protocol in the parameter buffer */
7931 /*------------------------------------------------------------------*/
7933 static word add_b23(PLCI *plci, API_PARSE *bp)
7935 word i, fax_control_bits;
7937 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7938 API_PARSE bp_parms[8];
7939 API_PARSE *b1_config;
7940 API_PARSE *b2_config;
7941 API_PARSE b2_config_parms[8];
7942 API_PARSE *b3_config;
7943 API_PARSE b3_config_parms[6];
7944 API_PARSE global_config[2];
7946 static byte llc[3] = {2,0,0};
7947 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7948 static byte nlc[256];
7949 static byte lli[12] = {1,1};
7951 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7954 const byte llc3[] = {4,3,2,2,6,6,0};
7955 const byte header[] = {0,2,3,3,0,0,0};
7957 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7958 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7959 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7963 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7965 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7968 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7970 if (plci->rx_dma_descriptor <= 0) {
7971 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7972 if (plci->rx_dma_descriptor >= 0)
7973 plci->rx_dma_descriptor++;
7975 if (plci->rx_dma_descriptor > 0) {
7978 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7979 lli[3] = (byte)plci->rx_dma_magic;
7980 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7981 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7982 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7986 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7990 dbug(1, dprintf("add_b23"));
7991 api_save_msg(bp, "s", &plci->B_protocol);
7993 if (!bp->length && plci->tel)
7995 plci->adv_nl = true;
7996 dbug(1, dprintf("Default adv.Nl"));
7997 add_p(plci, LLI, lli);
7998 plci->B2_prot = 1 /*XPARENT*/;
7999 plci->B3_prot = 0 /*XPARENT*/;
8002 add_p(plci, LLC, llc);
8004 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8005 add_p(plci, DLC, dlc);
8009 if (!bp->length) /*default*/
8011 dbug(1, dprintf("ret default"));
8012 add_p(plci, LLI, lli);
8013 plci->B2_prot = 0 /*X.75 */;
8014 plci->B3_prot = 0 /*XPARENT*/;
8017 add_p(plci, LLC, llc);
8019 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8020 add_p(plci, DLC, dlc);
8023 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8024 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8026 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8028 bp_parms[6].length = 0;
8029 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8031 dbug(1, dprintf("b-form.!"));
8032 return _WRONG_MESSAGE_FORMAT;
8035 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8037 dbug(1, dprintf("b-form.!"));
8038 return _WRONG_MESSAGE_FORMAT;
8041 if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8043 if (GET_WORD(bp_parms[1].info) != 1
8044 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8045 plci->adv_nl = true;
8047 else if (plci->tel) return _B2_NOT_SUPPORTED;
8050 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8051 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8052 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8054 add_p(plci, LLI, lli);
8055 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8056 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8057 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8059 add_p(plci, LLC, llc);
8061 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8062 dlc[3] = 3; /* Addr A */
8063 dlc[4] = 1; /* Addr B */
8064 dlc[5] = 7; /* modulo mode */
8065 dlc[6] = 7; /* window size */
8066 dlc[7] = 0; /* XID len Lo */
8067 dlc[8] = 0; /* XID len Hi */
8068 for (i = 0; i < bp_parms[4].length; i++)
8069 dlc[9 + i] = bp_parms[4].info[1 + i];
8070 dlc[0] = (byte)(8 + bp_parms[4].length);
8071 add_p(plci, DLC, dlc);
8072 for (i = 0; i < bp_parms[5].length; i++)
8073 nlc[1 + i] = bp_parms[5].info[1 + i];
8074 nlc[0] = (byte)(bp_parms[5].length);
8075 add_p(plci, NLC, nlc);
8081 if ((GET_WORD(bp_parms[1].info) >= 32)
8082 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8083 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8084 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8087 return _B2_NOT_SUPPORTED;
8089 if ((GET_WORD(bp_parms[2].info) >= 32)
8090 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8092 return _B3_NOT_SUPPORTED;
8094 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8095 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8096 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8097 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8099 return (add_modem_b23(plci, bp_parms));
8102 add_p(plci, LLI, lli);
8104 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8105 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8106 if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8108 if (bp_parms[6].length)
8110 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8112 return _WRONG_MESSAGE_FORMAT;
8114 switch (GET_WORD(global_config[0].info))
8117 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8120 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8124 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8127 if (plci->B2_prot == B2_PIAFS)
8130 /* IMPLEMENT_PIAFS */
8132 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8133 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8135 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8137 add_p(plci, LLC, llc);
8140 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8141 header[GET_WORD(bp_parms[2].info)]);
8143 b1_config = &bp_parms[3];
8145 if (plci->B3_prot == 4
8146 || plci->B3_prot == 5)
8148 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8149 nlc[0] = sizeof(T30_INFO);
8150 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8151 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8152 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8153 if (b1_config->length >= 2)
8155 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8158 b2_config = &bp_parms[4];
8161 if (llc[1] == PIAFS_CRC)
8163 if (plci->B3_prot != B3_TRANSPARENT)
8165 return _B_STACK_NOT_SUPPORTED;
8167 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8168 return _WRONG_MESSAGE_FORMAT;
8170 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8171 dlc[3] = 0; /* Addr A */
8172 dlc[4] = 0; /* Addr B */
8173 dlc[5] = 0; /* modulo mode */
8174 dlc[6] = 0; /* window size */
8175 if (b2_config->length >= 7) {
8178 dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8179 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8180 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8181 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8182 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8183 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8184 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8186 if (b2_config->length >= 8) { /* PIAFS control abilities */
8188 dlc[16] = 2; /* Length of PIAFS extension */
8189 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8190 dlc[18] = b2_config_parms[4].info[0]; /* value */
8194 else /* default values, 64K, variable, no compression */
8198 dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8199 dlc[10] = 0x03; /* V.42bis P0 */
8200 dlc[11] = 0; /* V.42bis P0 */
8201 dlc[12] = 0; /* V.42bis P1 */
8202 dlc[13] = 0; /* V.42bis P1 */
8203 dlc[14] = 0; /* V.42bis P2 */
8204 dlc[15] = 0; /* V.42bis P2 */
8207 add_p(plci, DLC, dlc);
8211 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8213 if (plci->B3_prot != B3_TRANSPARENT)
8214 return _B_STACK_NOT_SUPPORTED;
8217 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8222 if (b2_config->length != 0)
8224 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8225 return _WRONG_MESSAGE_FORMAT;
8227 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8228 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8229 if (b2_config->info[3] != 128)
8231 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8232 return _B2_PARM_NOT_SUPPORTED;
8234 dlc[5] = (byte)(b2_config->info[3] - 1);
8235 dlc[6] = b2_config->info[4];
8236 if (llc[1] == V120_V42BIS) {
8237 if (b2_config->length >= 10) {
8240 dlc[9] = b2_config_parms[4].info[0];
8241 dlc[10] = b2_config_parms[4].info[1];
8242 dlc[11] = b2_config_parms[5].info[0];
8243 dlc[12] = b2_config_parms[5].info[1];
8244 dlc[13] = b2_config_parms[6].info[0];
8245 dlc[14] = b2_config_parms[6].info[1];
8247 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8248 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8249 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8259 if (b2_config->length)
8261 dbug(1, dprintf("B2-Config"));
8262 if (llc[1] == X75_V42BIS) {
8263 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8265 return _WRONG_MESSAGE_FORMAT;
8269 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8271 return _WRONG_MESSAGE_FORMAT;
8274 /* if B2 Protocol is LAPD, b2_config structure is different */
8278 if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8280 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8282 SAPI = b2_config->info[2]; /* SAPI */
8285 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8287 dlc[3] = 127; /* Mode */
8291 dlc[3] = 7; /* Mode */
8294 if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8296 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8297 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8301 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8302 dlc[3] = b2_config->info[1];
8303 dlc[4] = b2_config->info[2];
8304 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8305 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8306 return _B2_PARM_NOT_SUPPORTED;
8309 dlc[5] = (byte)(b2_config->info[3] - 1);
8310 dlc[6] = b2_config->info[4];
8311 if (dlc[6] > dlc[5]) {
8312 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]));
8313 return _B2_PARM_NOT_SUPPORTED;
8316 if (llc[1] == X75_V42BIS) {
8317 if (b2_config->length >= 10) {
8320 dlc[9] = b2_config_parms[4].info[0];
8321 dlc[10] = b2_config_parms[4].info[1];
8322 dlc[11] = b2_config_parms[5].info[0];
8323 dlc[12] = b2_config_parms[5].info[1];
8324 dlc[13] = b2_config_parms[6].info[0];
8325 dlc[14] = b2_config_parms[6].info[1];
8327 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8328 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8329 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8337 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8338 for (i = 0; i < b2_config_parms[4].length; i++)
8339 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8344 add_p(plci, DLC, dlc);
8346 b3_config = &bp_parms[5];
8347 if (b3_config->length)
8349 if (plci->B3_prot == 4
8350 || plci->B3_prot == 5)
8352 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8354 return _WRONG_MESSAGE_FORMAT;
8356 i = GET_WORD((byte *)(b3_config_parms[0].info));
8357 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8358 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8359 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8360 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8361 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8362 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8363 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8366 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8367 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8369 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8370 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8371 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8374 ((T30_INFO *)&nlc[1])->recording_properties =
8375 T30_RECORDING_WIDTH_ISO_A3 |
8376 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8377 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8379 if (plci->B3_prot == 5)
8381 if (i & 0x0002) /* Accept incoming fax-polling requests */
8382 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8383 if (i & 0x2000) /* Do not use MR compression */
8384 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8385 if (i & 0x4000) /* Do not use MMR compression */
8386 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8387 if (i & 0x8000) /* Do not use ECM */
8388 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8389 if (plci->fax_connect_info_length != 0)
8391 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8392 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8393 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8394 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8395 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8398 /* copy station id to NLC */
8399 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8401 if (i < b3_config_parms[2].length)
8403 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8407 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8410 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8411 /* copy head line to NLC */
8412 if (b3_config_parms[3].length)
8415 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8418 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8422 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8423 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8424 len = (byte)b3_config_parms[2].length;
8427 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8429 for (i = 0; i < len; i++)
8430 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8431 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8432 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8437 len = (byte)b3_config_parms[3].length;
8438 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8439 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8440 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8441 nlc[0] += (byte)(pos + len);
8442 for (i = 0; i < len; i++)
8443 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8445 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8447 plci->nsf_control_bits = 0;
8448 if (plci->B3_prot == 5)
8450 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8453 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8455 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8456 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8458 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8460 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8461 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8463 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8464 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8466 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8467 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8468 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8471 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8472 if (pos < plci->fax_connect_info_length)
8474 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8479 if (pos < plci->fax_connect_info_length)
8481 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8486 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8487 & (1L << PRIVATE_FAX_NONSTANDARD))
8489 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8491 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8492 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8493 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8494 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8498 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8500 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8505 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8506 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8507 nlc[++len] = (byte)(b3_config_parms[4].length);
8508 for (i = 0; i < b3_config_parms[4].length; i++)
8509 nlc[++len] = b3_config_parms[4].info[1 + i];
8514 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8515 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8517 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8522 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8523 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8524 for (i = 0; i < len; i++)
8525 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8526 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8527 i += ((T30_INFO *)&nlc[1])->head_line_len;
8529 plci->fax_connect_info_buffer[len++] = nlc[++i];
8530 plci->fax_connect_info_length = len;
8535 if (b3_config->length != 16)
8536 return _B3_PARM_NOT_SUPPORTED;
8537 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8538 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8539 return _B3_PARM_NOT_SUPPORTED;
8540 nlc[13] = b3_config->info[13];
8541 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8542 return _B3_PARM_NOT_SUPPORTED;
8543 nlc[14] = b3_config->info[15];
8548 if (plci->B3_prot == 4
8549 || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8551 add_p(plci, NLC, nlc);
8555 /*----------------------------------------------------------------*/
8556 /* make the same as add_b23, but only for the modem related */
8557 /* L2 and L3 B-Chan protocol. */
8559 /* Enabled L2 and L3 Configurations: */
8560 /* If L1 == Modem all negotiation */
8561 /* only L2 == Modem with full negotiation is allowed */
8562 /* If L1 == Modem async or sync */
8563 /* only L2 == Transparent is allowed */
8564 /* L3 == Modem or L3 == Transparent are allowed */
8565 /* B2 Configuration for modem: */
8566 /* word : enable/disable compression, bitoptions */
8567 /* B3 Configuration for modem: */
8569 /*----------------------------------------------------------------*/
8570 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8572 static byte lli[12] = {1,1};
8573 static byte llc[3] = {2,0,0};
8574 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8575 API_PARSE mdm_config[2];
8579 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8580 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8582 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8583 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8584 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8585 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8587 return (_B_STACK_NOT_SUPPORTED);
8589 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8590 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8592 return (_B_STACK_NOT_SUPPORTED);
8595 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8596 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8598 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8600 if (api_parse(&bp_parms[4].info[1],
8601 (word)bp_parms[4].length, "w",
8604 return (_WRONG_MESSAGE_FORMAT);
8606 b2_config = GET_WORD(mdm_config[0].info);
8609 /* OK, L2 is modem */
8613 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8615 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8618 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8620 if (plci->rx_dma_descriptor <= 0) {
8621 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8622 if (plci->rx_dma_descriptor >= 0)
8623 plci->rx_dma_descriptor++;
8625 if (plci->rx_dma_descriptor > 0) {
8628 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8629 lli[3] = (byte)plci->rx_dma_magic;
8630 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8631 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8632 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8636 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8640 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8641 /*V42*/ 10 : /*V42_IN*/ 9;
8642 llc[2] = 4; /* pass L3 always transparent */
8643 add_p(plci, LLI, lli);
8644 add_p(plci, LLC, llc);
8646 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8648 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8650 if (bp_parms[4].length)
8652 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8653 dlc[i++] = 3; /* Addr A */
8654 dlc[i++] = 1; /* Addr B */
8655 dlc[i++] = 7; /* modulo mode */
8656 dlc[i++] = 7; /* window size */
8657 dlc[i++] = 0; /* XID len Lo */
8658 dlc[i++] = 0; /* XID len Hi */
8660 if (b2_config & MDM_B2_DISABLE_V42bis)
8662 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8664 if (b2_config & MDM_B2_DISABLE_MNP)
8666 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8668 if (b2_config & MDM_B2_DISABLE_TRANS)
8670 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8672 if (b2_config & MDM_B2_DISABLE_V42)
8674 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8676 if (b2_config & MDM_B2_DISABLE_COMP)
8678 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8685 dlc[i++] = 3; /* Addr A */
8686 dlc[i++] = 1; /* Addr B */
8687 dlc[i++] = 7; /* modulo mode */
8688 dlc[i++] = 7; /* window size */
8689 dlc[i++] = 0; /* XID len Lo */
8690 dlc[i++] = 0; /* XID len Hi */
8691 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8692 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8693 DLC_MODEMPROT_DISABLE_V42_DETECT |
8694 DLC_MODEMPROT_DISABLE_COMPRESSION;
8696 dlc[0] = (byte)(i - 1);
8697 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8698 add_p(plci, DLC, dlc);
8703 /*------------------------------------------------------------------*/
8704 /* send a request for the signaling entity */
8705 /*------------------------------------------------------------------*/
8707 static void sig_req(PLCI *plci, byte req, byte Id)
8710 if (plci->adapter->adapter_disabled) return;
8711 dbug(1, dprintf("sig_req(%x)", req));
8713 plci->sig_remove_id = plci->Sig.Id;
8714 if (plci->req_in == plci->req_in_start) {
8716 plci->RBuffer[plci->req_in++] = 0;
8718 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8719 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8720 plci->RBuffer[plci->req_in++] = req; /* request */
8721 plci->RBuffer[plci->req_in++] = 0; /* channel */
8722 plci->req_in_start = plci->req_in;
8725 /*------------------------------------------------------------------*/
8726 /* send a request for the network layer entity */
8727 /*------------------------------------------------------------------*/
8729 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8732 if (plci->adapter->adapter_disabled) return;
8733 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8736 plci->nl_remove_id = plci->NL.Id;
8737 ncci_remove(plci, 0, (byte)(ncci != 0));
8740 if (plci->req_in == plci->req_in_start) {
8742 plci->RBuffer[plci->req_in++] = 0;
8744 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8745 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8746 plci->RBuffer[plci->req_in++] = req; /* request */
8747 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8748 plci->req_in_start = plci->req_in;
8751 static void send_req(PLCI *plci)
8758 if (plci->adapter->adapter_disabled) return;
8759 channel_xmit_xon(plci);
8761 /* if nothing to do, return */
8762 if (plci->req_in == plci->req_out) return;
8763 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8765 if (plci->nl_req || plci->sig_req) return;
8767 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8769 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8771 if (plci->RBuffer[plci->req_out] == 1)
8775 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8776 e->ReqCh = plci->RBuffer[plci->req_out++];
8777 if (!(e->Id & 0x1f))
8780 plci->RBuffer[plci->req_out - 4] = CAI;
8781 plci->RBuffer[plci->req_out - 3] = 1;
8782 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8783 plci->RBuffer[plci->req_out - 1] = 0;
8785 plci->nl_global_req = plci->nl_req;
8787 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8792 if (plci->RBuffer[plci->req_out])
8793 e->Id = plci->RBuffer[plci->req_out];
8795 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8796 e->ReqCh = plci->RBuffer[plci->req_out++];
8797 if (!(e->Id & 0x1f))
8798 plci->sig_global_req = plci->sig_req;
8799 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8801 plci->XData[0].PLength = l;
8803 plci->adapter->request(e);
8804 dbug(1, dprintf("send_ok"));
8807 static void send_data(PLCI *plci)
8809 DIVA_CAPI_ADAPTER *a;
8814 if (!plci->nl_req && plci->ncci_ring_list)
8817 ncci = plci->ncci_ring_list;
8820 ncci = a->ncci_next[ncci];
8821 ncci_ptr = &(a->ncci[ncci]);
8822 if (!(a->ncci_ch[ncci]
8823 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8825 if (ncci_ptr->data_pending)
8827 if ((a->ncci_state[ncci] == CONNECTED)
8828 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8829 || (plci->send_disc == ncci))
8831 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8832 if ((plci->B2_prot == B2_V120_ASYNC)
8833 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8834 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8836 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8837 plci->NData[1].PLength = data->Length;
8838 if (data->Flags & 0x10)
8839 plci->NData[0].P = v120_break_header;
8841 plci->NData[0].P = v120_default_header;
8842 plci->NData[0].PLength = 1;
8844 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8848 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8849 plci->NData[0].PLength = data->Length;
8850 if (data->Flags & 0x10)
8851 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8853 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8854 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8857 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8859 plci->NL.X = plci->NData;
8860 plci->NL.ReqCh = a->ncci_ch[ncci];
8861 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8862 plci->data_sent = true;
8863 plci->data_sent_ptr = data->P;
8864 a->request(&plci->NL);
8867 cleanup_ncci_data(plci, ncci);
8870 else if (plci->send_disc == ncci)
8872 /* dprintf("N_DISC"); */
8873 plci->NData[0].PLength = 0;
8874 plci->NL.ReqCh = a->ncci_ch[ncci];
8875 plci->NL.Req = plci->nl_req = N_DISC;
8876 a->request(&plci->NL);
8877 plci->command = _DISCONNECT_B3_R;
8878 plci->send_disc = 0;
8881 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8882 plci->ncci_ring_list = ncci;
8886 static void listen_check(DIVA_CAPI_ADAPTER *a)
8890 byte activnotifiedcalls = 0;
8892 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8893 if (!remove_started && !a->adapter_disabled)
8895 for (i = 0; i < a->max_plci; i++)
8897 plci = &(a->plci[i]);
8898 if (plci->notifiedcall) activnotifiedcalls++;
8900 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8902 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8903 if ((j = get_plci(a))) {
8905 plci = &a->plci[j - 1];
8906 plci->State = LISTENING;
8908 add_p(plci, OAD, "\x01\xfd");
8910 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8912 add_p(plci, CAI, "\x01\xc0");
8913 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8914 add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8915 add_p(plci, SHIFT | 6, NULL);
8916 add_p(plci, SIN, "\x02\x00\x00");
8917 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8918 sig_req(plci, ASSIGN, DSIG_ID);
8925 /*------------------------------------------------------------------*/
8926 /* functions for all parameters sent in INDs */
8927 /*------------------------------------------------------------------*/
8929 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8931 word ploc; /* points to current location within packet */
8943 in = plci->Sig.RBuffer->P;
8944 for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8945 { /* element but parms array is larger */
8946 parms[i] = (byte *)"";
8948 for (i = 0; i < multiIEsize; i++)
8950 parms[i] = (byte *)"";
8953 while (ploc < plci->Sig.RBuffer->length - 1) {
8955 /* read information element id and length */
8959 /* w &=0xf0; removed, cannot detect congestion levels */
8960 /* upper 4 bit masked with w==SHIFT now */
8964 wlen = (byte)(in[ploc + 1] + 1);
8966 /* check if length valid (not exceeding end of packet) */
8967 if ((ploc + wlen) > 270) return;
8968 if (lock & 0x80) lock &= 0x7f;
8969 else codeset = lock;
8971 if ((w & 0xf0) == SHIFT) {
8973 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8978 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8980 code |= (codeset << 8);
8982 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8984 if (i < parms_id[0] + 1) {
8985 if (!multiIEsize) { /* with multiIEs use next field index, */
8986 mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8989 parms[mIEindex] = &in[ploc + 1];
8990 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8991 if (parms_id[i] == OAD
8992 || parms_id[i] == CONN_NR
8993 || parms_id[i] == CAD) {
8994 if (in[ploc + 2] & 0x80) {
8995 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8996 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8997 in[ploc + 2] = 0x80;
8998 parms[mIEindex] = &in[ploc];
9001 mIEindex++; /* effects multiIEs only */
9010 /*------------------------------------------------------------------*/
9011 /* try to match a cip from received BC and HLC */
9012 /*------------------------------------------------------------------*/
9014 static byte ie_compare(byte *ie1, byte *ie2)
9017 if (!ie1 || !ie2) return false;
9018 if (!ie1[0]) return false;
9019 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9023 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9028 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9030 for (j = 16; j < 29 &&
9031 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9032 if (j == 29) return i;
9037 static byte AddInfo(byte **add_i,
9047 /* facility is a nested structure */
9048 /* FTY can be more than once */
9050 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9052 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9057 add_i[0] = (byte *)"";
9061 add_i[3] = (byte *)"";
9064 { /* facility array found */
9065 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9067 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9071 facility[j++] = 0x1c; /* copy fac IE */
9072 for (k = 0; k <= flen; k++, j++)
9074 facility[j] = fty_i[i][k];
9075 /* dbug(1, dprintf("%x ",facility[j])); */
9079 add_i[3] = facility;
9081 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
9082 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9083 len += 4; /* calculate length of all */
9087 /*------------------------------------------------------------------*/
9088 /* voice and codec features */
9089 /*------------------------------------------------------------------*/
9091 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9093 byte voice_chi[] = "\x02\x18\x01";
9096 channel = chi[chi[0]] & 0x3;
9097 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9098 voice_chi[2] = (channel) ? channel : 1;
9099 add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
9100 add_p(plci, ESC, voice_chi); /* Channel */
9101 sig_req(plci, TEL_CTRL, 0);
9103 if (a->AdvSignalPLCI)
9105 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9109 static void VoiceChannelOff(PLCI *plci)
9111 dbug(1, dprintf("ExtDevOFF"));
9112 add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
9113 sig_req(plci, TEL_CTRL, 0);
9115 if (plci->adapter->AdvSignalPLCI)
9117 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9122 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9128 /* check if hardware supports handset with hook states (adv.codec) */
9129 /* or if just a on board codec is supported */
9130 /* the advanced codec plci is just for internal use */
9132 /* diva Pro with on-board codec: */
9133 if (a->profile.Global_Options & HANDSET)
9135 /* new call, but hook states are already signalled */
9136 if (a->AdvCodecFLAG)
9138 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9140 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9141 return 0x2001; /* codec in use by another application */
9145 a->AdvSignalPLCI = plci;
9146 plci->tel = ADV_VOICE;
9148 return 0; /* adv codec still used */
9150 if ((j = get_plci(a)))
9152 splci = &a->plci[j - 1];
9153 splci->tel = CODEC_PERMANENT;
9154 /* hook_listen indicates if a facility_req with handset/hook support */
9155 /* was sent. Otherwise if just a call on an external device was made */
9156 /* the codec will be used but the hook info will be discarded (just */
9157 /* the external controller is in use */
9158 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9161 splci->State = ADVANCED_VOICE_NOSIG;
9164 plci->spoofed_msg = SPOOFING_REQUIRED;
9166 /* indicate D-ch connect if */
9167 } /* codec is connected OK */
9170 a->AdvSignalPLCI = plci;
9171 plci->tel = ADV_VOICE;
9173 a->AdvSignalAppl = appl;
9174 a->AdvCodecFLAG = true;
9175 a->AdvCodecPLCI = splci;
9176 add_p(splci, CAI, "\x01\x15");
9177 add_p(splci, LLI, "\x01\x00");
9178 add_p(splci, ESC, "\x02\x18\x00");
9179 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9180 splci->internal_command = PERM_COD_ASSIGN;
9181 dbug(1, dprintf("Codec Assign"));
9182 sig_req(splci, ASSIGN, DSIG_ID);
9187 return 0x2001; /* wrong state, no more plcis */
9190 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9192 if (hook_listen) return 0x300B; /* Facility not supported */
9193 /* no hook with SCOM */
9194 if (plci != NULL) plci->tel = CODEC;
9195 dbug(1, dprintf("S/SCOM codec"));
9196 /* first time we use the scom-s codec we must shut down the internal */
9197 /* handset application of the card. This can be done by an assign with */
9198 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9199 if (!a->scom_appl_disable) {
9200 if ((j = get_plci(a))) {
9201 splci = &a->plci[j - 1];
9202 add_p(splci, CAI, "\x01\x80");
9203 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9204 sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9206 a->scom_appl_disable = true;
9209 return 0x2001; /* wrong state, no more plcis */
9213 else return 0x300B; /* Facility not supported */
9219 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9222 dbug(1, dprintf("CodecIdCheck"));
9224 if (a->AdvSignalPLCI == plci)
9226 dbug(1, dprintf("PLCI owns codec"));
9227 VoiceChannelOff(a->AdvCodecPLCI);
9228 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9230 dbug(1, dprintf("remove temp codec PLCI"));
9231 plci_remove(a->AdvCodecPLCI);
9232 a->AdvCodecFLAG = 0;
9233 a->AdvCodecPLCI = NULL;
9234 a->AdvSignalAppl = NULL;
9236 a->AdvSignalPLCI = NULL;
9240 /* -------------------------------------------------------------------
9241 Ask for physical address of card on PCI bus
9242 ------------------------------------------------------------------- */
9243 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9244 IDI_SYNC_REQ *preq) {
9246 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9247 ENTITY *e = (ENTITY *)preq;
9249 e->user[0] = a->Id - 1;
9250 preq->xdi_sdram_bar.info.bar = 0;
9251 preq->xdi_sdram_bar.Req = 0;
9252 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9256 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9257 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9261 /* -------------------------------------------------------------------
9262 Ask XDI about extended features
9263 ------------------------------------------------------------------- */
9264 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9266 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9269 preq = (IDI_SYNC_REQ *)&buffer[0];
9271 if (!diva_xdi_extended_features) {
9272 ENTITY *e = (ENTITY *)preq;
9273 diva_xdi_extended_features |= 0x80000000;
9275 e->user[0] = a->Id - 1;
9276 preq->xdi_extended_features.Req = 0;
9277 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9278 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9279 preq->xdi_extended_features.info.features = &features[0];
9283 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9285 Check features located in the byte '0'
9287 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9288 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9290 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9291 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9292 dbug(1, dprintf("XDI provides RxDMA"));
9294 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9295 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9297 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9298 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9299 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9305 diva_ask_for_xdi_sdram_bar(a, preq);
9308 /*------------------------------------------------------------------*/
9310 /*------------------------------------------------------------------*/
9311 /* called from OS specific part after init time to get the Law */
9312 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9313 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9318 if (a->automatic_law) {
9321 if ((j = get_plci(a))) {
9322 diva_get_extended_adapter_features(a);
9323 splci = &a->plci[j - 1];
9324 a->automatic_lawPLCI = splci;
9325 a->automatic_law = 1;
9326 add_p(splci, CAI, "\x01\x80");
9327 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9328 splci->internal_command = USELAW_REQ;
9331 sig_req(splci, ASSIGN, DSIG_ID);
9336 /* called from OS specific part if an application sends an Capi20Release */
9337 word CapiRelease(word Id)
9339 word i, j, appls_found;
9342 DIVA_CAPI_ADAPTER *a;
9346 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9347 return (_WRONG_APPL_ID);
9350 this = &application[Id - 1]; /* get application pointer */
9352 for (i = 0, appls_found = 0; i < max_appl; i++)
9354 if (application[i].Id) /* an application has been found */
9360 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9365 a->Info_Mask[Id - 1] = 0;
9366 a->CIP_Mask[Id - 1] = 0;
9367 a->Notification_Mask[Id - 1] = 0;
9368 a->codec_listen[Id - 1] = NULL;
9369 a->requested_options_table[Id - 1] = 0;
9370 for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9371 { /* with this application */
9373 if (plci->Id) /* if plci owns no application */
9374 { /* it may be not jet connected */
9375 if (plci->State == INC_CON_PENDING
9376 || plci->State == INC_CON_ALERT)
9378 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9380 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9381 if (c_ind_mask_empty(plci))
9383 sig_req(plci, HANGUP, 0);
9385 plci->State = OUTG_DIS_PENDING;
9389 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9391 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9392 if (c_ind_mask_empty(plci))
9401 if (plci->appl == this)
9411 if (a->flag_dynamic_l1_down)
9413 if (appls_found == 1) /* last application does a capi release */
9415 if ((j = get_plci(a)))
9417 plci = &a->plci[j - 1];
9419 add_p(plci, OAD, "\x01\xfd");
9420 add_p(plci, CAI, "\x01\x80");
9421 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9422 add_p(plci, SHIFT | 6, NULL);
9423 add_p(plci, SIN, "\x02\x00\x00");
9424 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9425 sig_req(plci, ASSIGN, DSIG_ID);
9426 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9427 sig_req(plci, SIG_CTRL, 0);
9432 if (a->AdvSignalAppl == this)
9434 this->NullCREnable = false;
9435 if (a->AdvCodecPLCI)
9437 plci_remove(a->AdvCodecPLCI);
9438 a->AdvCodecPLCI->tel = 0;
9439 a->AdvCodecPLCI->adv_nl = 0;
9441 a->AdvSignalAppl = NULL;
9442 a->AdvSignalPLCI = NULL;
9443 a->AdvCodecFLAG = 0;
9444 a->AdvCodecPLCI = NULL;
9454 static word plci_remove_check(PLCI *plci)
9456 if (!plci) return true;
9457 if (!plci->NL.Id && c_ind_mask_empty(plci))
9459 if (plci->Sig.Id == 0xff)
9463 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9464 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9467 CodecIdCheck(plci->adapter, plci);
9468 clear_b1_config(plci);
9469 ncci_remove(plci, 0, false);
9470 plci_free_msg_in_queue(plci);
9471 channel_flow_control_remove(plci);
9476 plci->notifiedcall = 0;
9478 listen_check(plci->adapter);
9486 /*------------------------------------------------------------------*/
9488 static byte plci_nl_busy(PLCI *plci)
9490 /* only applicable for non-multiplexed protocols */
9491 return (plci->nl_req
9492 || (plci->ncci_ring_list
9493 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9494 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9498 /*------------------------------------------------------------------*/
9499 /* DTMF facilities */
9500 /*------------------------------------------------------------------*/
9509 } dtmf_digit_map[] =
9511 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9512 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9513 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9514 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9515 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9516 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9517 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9518 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9519 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9520 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9521 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9522 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9523 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9524 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9525 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9526 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9527 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9528 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9529 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9530 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9532 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9533 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9534 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9535 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9536 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9537 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9538 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9539 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9540 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9541 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9542 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9543 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9544 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9545 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9546 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9547 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9548 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9549 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9550 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9551 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9552 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9553 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9554 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9555 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9556 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9557 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9558 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9559 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9560 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9561 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9562 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9563 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9564 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9565 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9566 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9567 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9568 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9569 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9570 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9571 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9572 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9573 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9574 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9575 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9576 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9577 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9578 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9579 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9580 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9581 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9582 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9583 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9587 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9590 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9592 word min_digit_duration, min_gap_duration;
9594 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9595 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9596 (char *)(FILE_), __LINE__, enable_mask));
9598 if (enable_mask != 0)
9600 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9601 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9602 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9603 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9604 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9605 plci->NData[0].PLength = 5;
9607 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9608 plci->NData[0].PLength += 2;
9609 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9614 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9615 plci->NData[0].PLength = 1;
9617 capidtmf_recv_disable(&(plci->capidtmf_state));
9620 plci->NData[0].P = plci->internal_req_buffer;
9621 plci->NL.X = plci->NData;
9623 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9624 plci->adapter->request(&plci->NL);
9628 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9632 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9633 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9634 (char *)(FILE_), __LINE__, digit_count));
9636 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9637 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9638 PUT_WORD(&plci->internal_req_buffer[1], w);
9639 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9640 PUT_WORD(&plci->internal_req_buffer[3], w);
9641 for (i = 0; i < digit_count; i++)
9644 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9645 && (digit_buffer[i] != dtmf_digit_map[w].character))
9649 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9650 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9652 plci->NData[0].PLength = 5 + digit_count;
9653 plci->NData[0].P = plci->internal_req_buffer;
9654 plci->NL.X = plci->NData;
9656 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9657 plci->adapter->request(&plci->NL);
9661 static void dtmf_rec_clear_config(PLCI *plci)
9664 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9665 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9666 (char *)(FILE_), __LINE__));
9668 plci->dtmf_rec_active = 0;
9669 plci->dtmf_rec_pulse_ms = 0;
9670 plci->dtmf_rec_pause_ms = 0;
9672 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9677 static void dtmf_send_clear_config(PLCI *plci)
9680 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9681 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9682 (char *)(FILE_), __LINE__));
9684 plci->dtmf_send_requests = 0;
9685 plci->dtmf_send_pulse_ms = 0;
9686 plci->dtmf_send_pause_ms = 0;
9690 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9693 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9694 UnMapId(Id), (char *)(FILE_), __LINE__));
9696 while (plci->dtmf_send_requests != 0)
9697 dtmf_confirmation(Id, plci);
9701 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9704 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9705 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9711 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9715 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9716 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9719 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9721 switch (plci->adjust_b_state)
9723 case ADJUST_B_RESTORE_DTMF_1:
9724 plci->internal_command = plci->adjust_b_command;
9725 if (plci_nl_busy(plci))
9727 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9730 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9731 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9733 case ADJUST_B_RESTORE_DTMF_2:
9734 if ((Rc != OK) && (Rc != OK_FC))
9736 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9737 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9738 Info = _WRONG_STATE;
9748 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9750 word internal_command, Info;
9754 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9755 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9756 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9757 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9761 PUT_WORD(&result[1], DTMF_SUCCESS);
9762 internal_command = plci->internal_command;
9763 plci->internal_command = 0;
9765 switch (plci->dtmf_cmd)
9768 case DTMF_LISTEN_TONE_START:
9770 case DTMF_LISTEN_MF_START:
9773 case DTMF_LISTEN_START:
9774 switch (internal_command)
9777 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9778 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9779 case DTMF_COMMAND_1:
9780 if (adjust_b_process(Id, plci, Rc) != GOOD)
9782 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9783 UnMapId(Id), (char *)(FILE_), __LINE__));
9784 Info = _FACILITY_NOT_SUPPORTED;
9787 if (plci->internal_command)
9789 case DTMF_COMMAND_2:
9790 if (plci_nl_busy(plci))
9792 plci->internal_command = DTMF_COMMAND_2;
9795 plci->internal_command = DTMF_COMMAND_3;
9796 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9798 case DTMF_COMMAND_3:
9799 if ((Rc != OK) && (Rc != OK_FC))
9801 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9802 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9803 Info = _FACILITY_NOT_SUPPORTED;
9807 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9809 plci->dtmf_rec_active |= mask;
9815 case DTMF_LISTEN_TONE_STOP:
9817 case DTMF_LISTEN_MF_STOP:
9820 case DTMF_LISTEN_STOP:
9821 switch (internal_command)
9824 plci->dtmf_rec_active &= ~mask;
9825 if (plci->dtmf_rec_active)
9828 case DTMF_COMMAND_1:
9829 if (plci->dtmf_rec_active)
9831 if (plci_nl_busy (plci))
9833 plci->internal_command = DTMF_COMMAND_1;
9836 plci->dtmf_rec_active &= ~mask;
9837 plci->internal_command = DTMF_COMMAND_2;
9838 dtmf_enable_receiver (plci, false);
9842 case DTMF_COMMAND_2:
9843 if ((Rc != OK) && (Rc != OK_FC))
9845 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9846 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9847 Info = _FACILITY_NOT_SUPPORTED;
9851 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9852 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9853 case DTMF_COMMAND_3:
9854 if (adjust_b_process(Id, plci, Rc) != GOOD)
9856 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9857 UnMapId(Id), (char *)(FILE_), __LINE__));
9858 Info = _FACILITY_NOT_SUPPORTED;
9861 if (plci->internal_command)
9868 case DTMF_SEND_TONE:
9873 case DTMF_DIGITS_SEND:
9874 switch (internal_command)
9877 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9878 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9880 case DTMF_COMMAND_1:
9881 if (adjust_b_process(Id, plci, Rc) != GOOD)
9883 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9884 UnMapId(Id), (char *)(FILE_), __LINE__));
9885 Info = _FACILITY_NOT_SUPPORTED;
9888 if (plci->internal_command)
9890 case DTMF_COMMAND_2:
9891 if (plci_nl_busy(plci))
9893 plci->internal_command = DTMF_COMMAND_2;
9896 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9897 plci->internal_command = DTMF_COMMAND_3;
9898 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9900 case DTMF_COMMAND_3:
9901 if ((Rc != OK) && (Rc != OK_FC))
9903 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9904 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9905 if (plci->dtmf_send_requests != 0)
9906 (plci->dtmf_send_requests)--;
9907 Info = _FACILITY_NOT_SUPPORTED;
9914 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9915 "wws", Info, SELECTOR_DTMF, result);
9919 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9924 API_PARSE dtmf_parms[5];
9927 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9928 UnMapId(Id), (char *)(FILE_), __LINE__));
9932 PUT_WORD(&result[1], DTMF_SUCCESS);
9933 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9935 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9936 UnMapId(Id), (char *)(FILE_), __LINE__));
9937 Info = _FACILITY_NOT_SUPPORTED;
9939 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9941 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9942 UnMapId(Id), (char *)(FILE_), __LINE__));
9943 Info = _WRONG_MESSAGE_FORMAT;
9946 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9949 if (!((a->requested_options_table[appl->Id - 1])
9950 & (1L << PRIVATE_DTMF_TONE)))
9952 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9953 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9954 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9958 for (i = 0; i < 32; i++)
9960 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9962 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9964 if (dtmf_digit_map[i].listen_mask != 0)
9965 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9970 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9972 if (dtmf_digit_map[i].send_mask != 0)
9973 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9981 else if (plci == NULL)
9983 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9984 UnMapId(Id), (char *)(FILE_), __LINE__));
9985 Info = _WRONG_IDENTIFIER;
9990 || !plci->NL.Id || plci->nl_remove_id)
9992 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9993 UnMapId(Id), (char *)(FILE_), __LINE__));
9994 Info = _WRONG_STATE;
9999 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
10001 switch (plci->dtmf_cmd)
10004 case DTMF_LISTEN_TONE_START:
10005 case DTMF_LISTEN_TONE_STOP:
10007 case DTMF_LISTEN_MF_START:
10008 case DTMF_LISTEN_MF_STOP:
10010 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10011 & (1L << PRIVATE_DTMF_TONE)))
10013 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10014 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10015 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10019 case DTMF_LISTEN_START:
10020 case DTMF_LISTEN_STOP:
10021 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10022 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10024 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10025 UnMapId(Id), (char *)(FILE_), __LINE__));
10026 Info = _FACILITY_NOT_SUPPORTED;
10029 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10031 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10033 plci->dtmf_rec_pulse_ms = 0;
10034 plci->dtmf_rec_pause_ms = 0;
10038 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10039 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10042 start_internal_command(Id, plci, dtmf_command);
10046 case DTMF_SEND_TONE:
10050 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10051 & (1L << PRIVATE_DTMF_TONE)))
10053 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10054 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10055 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10059 case DTMF_DIGITS_SEND:
10060 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10062 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10063 UnMapId(Id), (char *)(FILE_), __LINE__));
10064 Info = _WRONG_MESSAGE_FORMAT;
10067 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10069 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10070 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10074 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10077 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10078 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10079 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10085 if (j == DTMF_DIGIT_MAP_ENTRIES)
10087 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10088 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10089 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10092 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10094 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10095 UnMapId(Id), (char *)(FILE_), __LINE__));
10096 Info = _WRONG_STATE;
10099 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10100 start_internal_command(Id, plci, dtmf_command);
10104 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10105 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10106 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10110 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10111 "wws", Info, SELECTOR_DTMF, result);
10116 static void dtmf_confirmation(dword Id, PLCI *plci)
10121 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10122 UnMapId(Id), (char *)(FILE_), __LINE__));
10125 PUT_WORD(&result[1], DTMF_SUCCESS);
10126 if (plci->dtmf_send_requests != 0)
10128 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10129 "wws", GOOD, SELECTOR_DTMF, result);
10130 (plci->dtmf_send_requests)--;
10131 for (i = 0; i < plci->dtmf_send_requests; i++)
10132 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10137 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10141 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10142 UnMapId(Id), (char *)(FILE_), __LINE__));
10145 for (i = 1; i < length; i++)
10148 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10149 && ((msg[i] != dtmf_digit_map[j].code)
10150 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10154 if (j < DTMF_DIGIT_MAP_ENTRIES)
10157 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10158 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10159 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10163 for (i = length; i > n + 1; i--)
10164 msg[i] = msg[i - 1];
10168 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10170 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10172 msg[++n] = dtmf_digit_map[j].character;
10178 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10183 /*------------------------------------------------------------------*/
10184 /* DTMF parameters */
10185 /*------------------------------------------------------------------*/
10187 static void dtmf_parameter_write(PLCI *plci)
10190 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10192 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10193 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10194 (char *)(FILE_), __LINE__));
10196 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10197 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10198 for (i = 0; i < plci->dtmf_parameter_length; i++)
10199 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10200 add_p(plci, FTY, parameter_buffer);
10201 sig_req(plci, TEL_CTRL, 0);
10206 static void dtmf_parameter_clear_config(PLCI *plci)
10209 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10210 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10211 (char *)(FILE_), __LINE__));
10213 plci->dtmf_parameter_length = 0;
10217 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10220 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10221 UnMapId(Id), (char *)(FILE_), __LINE__));
10226 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10229 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10230 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10236 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10240 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10241 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10244 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10245 && (plci->dtmf_parameter_length != 0))
10247 switch (plci->adjust_b_state)
10249 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10250 plci->internal_command = plci->adjust_b_command;
10253 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10256 dtmf_parameter_write(plci);
10257 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10259 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10260 if ((Rc != OK) && (Rc != OK_FC))
10262 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10263 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10264 Info = _WRONG_STATE;
10274 /*------------------------------------------------------------------*/
10275 /* Line interconnect facilities */
10276 /*------------------------------------------------------------------*/
10279 LI_CONFIG *li_config_table;
10280 word li_total_channels;
10283 /*------------------------------------------------------------------*/
10284 /* translate a CHI information element to a channel number */
10285 /* returns 0xff - any channel */
10286 /* 0xfe - chi wrong coding */
10287 /* 0xfd - D-channel */
10288 /* 0x00 - no channel */
10289 /* else channel number / PRI: timeslot */
10290 /* if channels is provided we accept more than one channel. */
10291 /*------------------------------------------------------------------*/
10293 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10302 if (pchannelmap) *pchannelmap = 0;
10303 if (!chi[0]) return 0xff;
10306 if (chi[1] & 0x20) {
10307 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10308 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10309 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10310 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10311 if (chi[1] & 0x08) excl = 0x40;
10313 /* int. id present */
10314 if (chi[1] & 0x40) {
10316 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10317 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10320 /* coding standard, Number/Map, Channel Type */
10322 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10323 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10324 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10327 if (chi[p] & 0x10) {
10330 if ((chi[0] - p) == 4) ofs = 0;
10331 else if ((chi[0] - p) == 3) ofs = 1;
10335 for (i = 0; i < 4 && p < chi[0]; i++) {
10340 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10351 ch = chi[p] & 0x3f;
10353 if ((byte)(chi[0] - p) > 30) return 0xfe;
10355 for (i = p; i <= chi[0]; i++) {
10356 if ((chi[i] & 0x7f) > 31) return 0xfe;
10357 map |= (1L << (chi[i] & 0x7f));
10361 if (p != chi[0]) return 0xfe;
10362 if (ch > 31) return 0xfe;
10365 if (chi[p] & 0x40) return 0xfe;
10367 if (pchannelmap) *pchannelmap = map;
10368 else if (map != ((dword)(1L << ch))) return 0xfe;
10369 return (byte)(excl | ch);
10371 else { /* not PRI */
10372 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10373 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10374 if (chi[1] & 0x08) excl = 0x40;
10376 switch (chi[1] | 0x98) {
10377 case 0x98: return 0;
10379 if (pchannelmap) *pchannelmap = 2;
10382 if (pchannelmap) *pchannelmap = 4;
10384 case 0x9b: return 0xff;
10385 case 0x9c: return 0xfd; /* d-ch */
10386 default: return 0xfe;
10392 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10394 DIVA_CAPI_ADAPTER *a;
10399 old_id = plci->li_bchannel_id;
10402 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10403 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10404 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10405 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10406 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10410 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10412 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10413 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10414 plci->li_bchannel_id = bchannel_id & 0x03;
10415 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10417 splci = a->AdvSignalPLCI;
10418 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10420 if ((splci->li_bchannel_id != 0)
10421 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10423 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10425 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10426 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10427 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10428 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10429 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10432 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10433 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10436 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10437 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10439 mixer_clear_config(plci);
10441 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10442 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10443 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10447 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10449 DIVA_CAPI_ADAPTER *a;
10454 old_id = plci->li_bchannel_id;
10455 ch = chi_to_channel(chi, NULL);
10460 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10461 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10462 plci->li_bchannel_id = (ch & 0x1f) + 1;
10463 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10464 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10468 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10470 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10471 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10472 plci->li_bchannel_id = ch & 0x1f;
10473 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10475 splci = a->AdvSignalPLCI;
10476 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10478 if ((splci->li_bchannel_id != 0)
10479 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10481 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10483 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10484 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10485 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10486 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10487 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10490 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10491 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10495 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10496 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10498 mixer_clear_config(plci);
10500 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10501 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10502 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10506 #define MIXER_MAX_DUMP_CHANNELS 34
10508 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10510 static char hex_digit_table[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
10513 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10515 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10516 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10518 for (i = 0; i < li_total_channels; i++)
10520 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10521 if (li_config_table[i].chflags != 0)
10522 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10525 for (j = 0; j < li_total_channels; j++)
10527 if (((li_config_table[i].flag_table[j]) != 0)
10528 || ((li_config_table[j].flag_table[i]) != 0))
10530 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10532 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10533 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10535 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10540 for (i = 0; i < li_total_channels; i++)
10542 for (j = 0; j < li_total_channels; j++)
10544 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10545 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10546 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10549 for (n = 0; n < li_total_channels; n++)
10551 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10553 for (i = 0; i < li_total_channels; i++)
10555 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10557 for (j = 0; j < li_total_channels; j++)
10559 li_config_table[i].coef_table[j] |=
10560 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10566 for (i = 0; i < li_total_channels; i++)
10568 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10570 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10571 for (j = 0; j < li_total_channels; j++)
10573 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10574 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10576 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10577 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10580 for (i = 0; i < li_total_channels; i++)
10582 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10584 for (j = 0; j < li_total_channels; j++)
10586 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10588 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10589 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10591 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10592 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10593 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10595 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10597 for (j = 0; j < li_total_channels; j++)
10599 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10601 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10602 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10603 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10607 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10609 for (j = 0; j < li_total_channels; j++)
10611 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10612 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10615 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10617 for (j = 0; j < li_total_channels; j++)
10619 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10621 for (n = 0; n < li_total_channels; n++)
10623 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10625 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10626 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10628 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10629 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10632 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10633 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10641 for (i = 0; i < li_total_channels; i++)
10643 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10645 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10646 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10648 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10650 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651 for (j = 0; j < li_total_channels; j++)
10653 if ((li_config_table[i].flag_table[j] &
10654 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10655 || (li_config_table[j].flag_table[i] &
10656 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10658 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10660 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10661 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10662 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10663 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10665 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10667 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10668 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10672 for (i = 0; i < li_total_channels; i++)
10674 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10677 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10679 if (j < li_total_channels)
10681 for (j = 0; j < li_total_channels; j++)
10683 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10684 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10685 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10690 n = li_total_channels;
10691 if (n > MIXER_MAX_DUMP_CHANNELS)
10692 n = MIXER_MAX_DUMP_CHANNELS;
10694 for (j = 0; j < n; j++)
10696 if ((j & 0x7) == 0)
10698 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10699 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10702 dbug(1, dprintf("[%06lx] CURRENT %s",
10703 (dword)(UnMapController(a->Id)), (char *)hex_line));
10705 for (j = 0; j < n; j++)
10707 if ((j & 0x7) == 0)
10709 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10710 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10713 dbug(1, dprintf("[%06lx] CHANNEL %s",
10714 (dword)(UnMapController(a->Id)), (char *)hex_line));
10716 for (j = 0; j < n; j++)
10718 if ((j & 0x7) == 0)
10720 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10721 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10724 dbug(1, dprintf("[%06lx] CHFLAG %s",
10725 (dword)(UnMapController(a->Id)), (char *)hex_line));
10726 for (i = 0; i < n; i++)
10729 for (j = 0; j < n; j++)
10731 if ((j & 0x7) == 0)
10733 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10734 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10737 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10738 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10740 for (i = 0; i < n; i++)
10743 for (j = 0; j < n; j++)
10745 if ((j & 0x7) == 0)
10747 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10748 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10751 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10752 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10761 } mixer_write_prog_pri[] =
10763 { LI_COEF_CH_CH, 0 },
10764 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10765 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10766 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10774 byte xconnect_override;
10775 } mixer_write_prog_bri[] =
10777 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10778 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10779 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10780 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10781 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10782 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10783 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10784 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10785 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10786 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10787 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10788 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10789 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10790 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10791 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10792 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10793 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10794 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10795 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10796 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10797 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10798 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10799 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10800 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10801 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10802 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10803 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10804 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10805 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10806 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10807 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10808 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10809 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10810 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10811 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10812 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10815 static byte mixer_swapped_index_bri[] =
10818 19, /* Alt B to B */
10820 21, /* Alt PC to B */
10822 23, /* Alt IC to B */
10824 25, /* Alt B to PC */
10826 27, /* Alt PC to PC */
10828 29, /* Alt IC to PC */
10830 31, /* Alt B to IC */
10832 33, /* Alt PC to IC */
10834 35, /* Alt IC to IC */
10835 0, /* Alt B to Alt B */
10836 1, /* B to Alt B */
10837 2, /* Alt PC to Alt B */
10838 3, /* PC to Alt B */
10839 4, /* Alt IC to Alt B */
10840 5, /* IC to Alt B */
10841 6, /* Alt B to Alt PC */
10842 7, /* B to Alt PC */
10843 8, /* Alt PC to Alt PC */
10844 9, /* PC to Alt PC */
10845 10, /* Alt IC to Alt PC */
10846 11, /* IC to Alt PC */
10847 12, /* Alt B to Alt IC */
10848 13, /* B to Alt IC */
10849 14, /* Alt PC to Alt IC */
10850 15, /* PC to Alt IC */
10851 16, /* Alt IC to Alt IC */
10852 17 /* IC to Alt IC */
10860 } xconnect_write_prog[] =
10862 { LI_COEF_CH_CH, false, false },
10863 { LI_COEF_CH_PC, false, true },
10864 { LI_COEF_PC_CH, true, false },
10865 { LI_COEF_PC_PC, true, true }
10869 static void xconnect_query_addresses(PLCI *plci)
10871 DIVA_CAPI_ADAPTER *a;
10875 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10876 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10877 (char *)(FILE_), __LINE__));
10880 if (a->li_pri && ((plci->li_bchannel_id == 0)
10881 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10883 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10884 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10885 (char *)(FILE_), __LINE__));
10888 p = plci->internal_req_buffer;
10889 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10890 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10893 *(p++) = (byte)(w >> 8);
10894 w = ch | XCONNECT_CHANNEL_PORT_PC;
10896 *(p++) = (byte)(w >> 8);
10897 plci->NData[0].P = plci->internal_req_buffer;
10898 plci->NData[0].PLength = p - plci->internal_req_buffer;
10899 plci->NL.X = plci->NData;
10900 plci->NL.ReqCh = 0;
10901 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10902 plci->adapter->request(&plci->NL);
10906 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10909 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10910 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10911 (char *)(FILE_), __LINE__, internal_command));
10913 plci->li_write_command = internal_command;
10914 plci->li_write_channel = 0;
10918 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10920 DIVA_CAPI_ADAPTER *a;
10921 word w, n, i, j, r, s, to_ch;
10924 struct xconnect_transfer_address_s *transfer_address;
10925 byte ch_map[MIXER_CHANNELS_BRI];
10927 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10928 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10931 if ((plci->li_bchannel_id == 0)
10932 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10934 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10935 UnMapId(Id), (char *)(FILE_), __LINE__));
10938 i = a->li_base + (plci->li_bchannel_id - 1);
10939 j = plci->li_write_channel;
10940 p = plci->internal_req_buffer;
10943 if ((Rc != OK) && (Rc != OK_FC))
10945 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10946 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10950 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10954 if (j < li_total_channels)
10956 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10958 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10959 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10960 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10961 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10963 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964 while ((j < li_total_channels)
10966 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10967 || (!li_config_table[j].adapter->li_pri
10968 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10969 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10970 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10971 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10972 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10973 || ((li_config_table[j].adapter->li_base != a->li_base)
10975 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10976 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10977 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10978 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10981 if (j < li_total_channels)
10982 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10985 if (j < li_total_channels)
10987 plci->internal_command = plci->li_write_command;
10988 if (plci_nl_busy(plci))
10990 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10991 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10994 if (li_config_table[j].adapter->li_base != a->li_base)
10997 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10998 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10999 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11000 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11005 if (r & xconnect_write_prog[n].mask)
11007 if (xconnect_write_prog[n].from_pc)
11008 transfer_address = &(li_config_table[j].send_pc);
11010 transfer_address = &(li_config_table[j].send_b);
11011 d = transfer_address->card_address.low;
11013 *(p++) = (byte)(d >> 8);
11014 *(p++) = (byte)(d >> 16);
11015 *(p++) = (byte)(d >> 24);
11016 d = transfer_address->card_address.high;
11018 *(p++) = (byte)(d >> 8);
11019 *(p++) = (byte)(d >> 16);
11020 *(p++) = (byte)(d >> 24);
11021 d = transfer_address->offset;
11023 *(p++) = (byte)(d >> 8);
11024 *(p++) = (byte)(d >> 16);
11025 *(p++) = (byte)(d >> 24);
11026 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11028 *(p++) = (byte)(w >> 8);
11029 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11030 (li_config_table[i].adapter->u_law ?
11031 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11032 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11035 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11038 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11039 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11040 if (n == ARRAY_SIZE(xconnect_write_prog))
11045 if (j < li_total_channels)
11046 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11047 } while ((j < li_total_channels)
11049 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11050 || (!li_config_table[j].adapter->li_pri
11051 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11052 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11053 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11054 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11055 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11056 || ((li_config_table[j].adapter->li_base != a->li_base)
11058 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11059 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11060 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11061 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11063 } while ((j < li_total_channels)
11064 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11066 else if (j == li_total_channels)
11068 plci->internal_command = plci->li_write_command;
11069 if (plci_nl_busy(plci))
11073 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11075 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11076 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11077 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11078 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11080 *(p++) = (byte)(w >> 8);
11084 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11086 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11087 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11089 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11091 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11092 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11093 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11094 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11096 *(p++) = (byte)(w >> 8);
11097 for (j = 0; j < sizeof(ch_map); j += 2)
11099 if (plci->li_bchannel_id == 2)
11101 ch_map[j] = (byte)(j + 1);
11102 ch_map[j + 1] = (byte) j;
11106 ch_map[j] = (byte) j;
11107 ch_map[j + 1] = (byte)(j + 1);
11110 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11112 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11113 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11114 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11116 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11117 mixer_write_prog_bri[n].xconnect_override :
11118 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11119 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11121 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11122 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11128 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11130 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11131 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11132 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11138 j = li_total_channels + 1;
11143 if (j <= li_total_channels)
11145 plci->internal_command = plci->li_write_command;
11146 if (plci_nl_busy(plci))
11148 if (j < a->li_base)
11152 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11154 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11155 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11156 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11157 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11159 *(p++) = (byte)(w >> 8);
11160 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11162 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11163 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11165 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11166 if (w & mixer_write_prog_pri[n].mask)
11168 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11174 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11175 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11177 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11178 if (w & mixer_write_prog_pri[n].mask)
11180 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11181 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11190 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11192 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11193 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11195 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11197 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11198 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11199 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11200 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11202 *(p++) = (byte)(w >> 8);
11203 for (j = 0; j < sizeof(ch_map); j += 2)
11205 if (plci->li_bchannel_id == 2)
11207 ch_map[j] = (byte)(j + 1);
11208 ch_map[j + 1] = (byte) j;
11212 ch_map[j] = (byte) j;
11213 ch_map[j + 1] = (byte)(j + 1);
11216 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11218 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11219 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11220 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11222 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11223 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11224 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11229 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11231 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11232 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11233 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11239 j = li_total_channels + 1;
11242 plci->li_write_channel = j;
11243 if (p != plci->internal_req_buffer)
11245 plci->NData[0].P = plci->internal_req_buffer;
11246 plci->NData[0].PLength = p - plci->internal_req_buffer;
11247 plci->NL.X = plci->NData;
11248 plci->NL.ReqCh = 0;
11249 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11250 plci->adapter->request(&plci->NL);
11256 static void mixer_notify_update(PLCI *plci, byte others)
11258 DIVA_CAPI_ADAPTER *a;
11261 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11263 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11264 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11265 (char *)(FILE_), __LINE__, others));
11268 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11271 plci->li_notify_update = true;
11275 notify_plci = NULL;
11278 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11280 if (i < li_total_channels)
11281 notify_plci = li_config_table[i++].plci;
11285 if ((plci->li_bchannel_id != 0)
11286 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11288 notify_plci = plci;
11291 if ((notify_plci != NULL)
11292 && !notify_plci->li_notify_update
11293 && (notify_plci->appl != NULL)
11294 && (notify_plci->State)
11295 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11297 notify_plci->li_notify_update = true;
11298 ((CAPI_MSG *) msg)->header.length = 18;
11299 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11300 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11301 ((CAPI_MSG *) msg)->header.number = 0;
11302 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11303 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11304 ((CAPI_MSG *) msg)->header.ncci = 0;
11305 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11306 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11307 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11308 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11309 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11310 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11311 if (w != _QUEUE_FULL)
11315 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11316 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11317 (char *)(FILE_), __LINE__,
11318 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11320 notify_plci->li_notify_update = false;
11323 } while (others && (notify_plci != NULL));
11325 plci->li_notify_update = false;
11330 static void mixer_clear_config(PLCI *plci)
11332 DIVA_CAPI_ADAPTER *a;
11335 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11336 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11337 (char *)(FILE_), __LINE__));
11339 plci->li_notify_update = false;
11340 plci->li_plci_b_write_pos = 0;
11341 plci->li_plci_b_read_pos = 0;
11342 plci->li_plci_b_req_pos = 0;
11344 if ((plci->li_bchannel_id != 0)
11345 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11347 i = a->li_base + (plci->li_bchannel_id - 1);
11348 li_config_table[i].curchnl = 0;
11349 li_config_table[i].channel = 0;
11350 li_config_table[i].chflags = 0;
11351 for (j = 0; j < li_total_channels; j++)
11353 li_config_table[j].flag_table[i] = 0;
11354 li_config_table[i].flag_table[j] = 0;
11355 li_config_table[i].coef_table[j] = 0;
11356 li_config_table[j].coef_table[i] = 0;
11360 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11361 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11363 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11364 li_config_table[i].curchnl = 0;
11365 li_config_table[i].channel = 0;
11366 li_config_table[i].chflags = 0;
11367 for (j = 0; j < li_total_channels; j++)
11369 li_config_table[i].flag_table[j] = 0;
11370 li_config_table[j].flag_table[i] = 0;
11371 li_config_table[i].coef_table[j] = 0;
11372 li_config_table[j].coef_table[i] = 0;
11374 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11376 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11377 li_config_table[i].curchnl = 0;
11378 li_config_table[i].channel = 0;
11379 li_config_table[i].chflags = 0;
11380 for (j = 0; j < li_total_channels; j++)
11382 li_config_table[i].flag_table[j] = 0;
11383 li_config_table[j].flag_table[i] = 0;
11384 li_config_table[i].coef_table[j] = 0;
11385 li_config_table[j].coef_table[i] = 0;
11394 static void mixer_prepare_switch(dword Id, PLCI *plci)
11397 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11398 UnMapId(Id), (char *)(FILE_), __LINE__));
11402 mixer_indication_coefs_set(Id, plci);
11403 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11407 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11409 DIVA_CAPI_ADAPTER *a;
11412 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11413 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11416 if ((plci->li_bchannel_id != 0)
11417 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11419 i = a->li_base + (plci->li_bchannel_id - 1);
11420 for (j = 0; j < li_total_channels; j++)
11422 li_config_table[i].coef_table[j] &= 0xf;
11423 li_config_table[j].coef_table[i] &= 0xf;
11426 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11432 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11434 DIVA_CAPI_ADAPTER *a;
11437 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11438 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11442 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11443 && (plci->li_bchannel_id != 0)
11444 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11446 switch (plci->adjust_b_state)
11448 case ADJUST_B_RESTORE_MIXER_1:
11449 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11451 plci->internal_command = plci->adjust_b_command;
11452 if (plci_nl_busy(plci))
11454 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11457 xconnect_query_addresses(plci);
11458 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11461 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11463 case ADJUST_B_RESTORE_MIXER_2:
11464 case ADJUST_B_RESTORE_MIXER_3:
11465 case ADJUST_B_RESTORE_MIXER_4:
11466 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11468 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11469 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11470 Info = _WRONG_STATE;
11475 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11476 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11477 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11478 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11482 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11483 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11484 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11485 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11487 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11489 plci->internal_command = plci->adjust_b_command;
11492 case ADJUST_B_RESTORE_MIXER_5:
11493 xconnect_write_coefs(plci, plci->adjust_b_command);
11494 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11496 case ADJUST_B_RESTORE_MIXER_6:
11497 if (!xconnect_write_coefs_process(Id, plci, Rc))
11499 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11500 UnMapId(Id), (char *)(FILE_), __LINE__));
11501 Info = _FACILITY_NOT_SUPPORTED;
11504 if (plci->internal_command)
11506 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11507 case ADJUST_B_RESTORE_MIXER_7:
11515 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11517 DIVA_CAPI_ADAPTER *a;
11518 word i, internal_command;
11520 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11521 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11525 internal_command = plci->internal_command;
11526 plci->internal_command = 0;
11527 switch (plci->li_cmd)
11529 case LI_REQ_CONNECT:
11530 case LI_REQ_DISCONNECT:
11531 case LI_REQ_SILENT_UPDATE:
11532 switch (internal_command)
11535 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11537 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11538 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11540 case MIXER_COMMAND_1:
11541 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11543 if (adjust_b_process(Id, plci, Rc) != GOOD)
11545 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11546 UnMapId(Id), (char *)(FILE_), __LINE__));
11549 if (plci->internal_command)
11552 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11553 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11554 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11555 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11556 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11558 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11564 mixer_indication_coefs_set(Id, plci);
11565 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11567 case MIXER_COMMAND_2:
11568 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11569 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11570 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11571 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11573 if (!xconnect_write_coefs_process(Id, plci, Rc))
11575 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11576 UnMapId(Id), (char *)(FILE_), __LINE__));
11577 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11581 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11582 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11583 i = (plci->li_plci_b_write_pos == 0) ?
11584 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11585 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11586 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11590 if (plci->internal_command)
11593 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11595 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11596 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11598 case MIXER_COMMAND_3:
11599 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11601 if (adjust_b_process(Id, plci, Rc) != GOOD)
11603 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11604 UnMapId(Id), (char *)(FILE_), __LINE__));
11607 if (plci->internal_command)
11614 if ((plci->li_bchannel_id == 0)
11615 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11617 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11618 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11622 i = a->li_base + (plci->li_bchannel_id - 1);
11623 li_config_table[i].curchnl = plci->li_channel_bits;
11624 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11626 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11627 li_config_table[i].curchnl = plci->li_channel_bits;
11628 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11630 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11631 li_config_table[i].curchnl = plci->li_channel_bits;
11638 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11639 dword plci_b_id, byte connect, dword li_flags)
11641 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11643 DIVA_CAPI_ADAPTER *a_b;
11645 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11646 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11647 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11648 if (!a->li_pri && (plci->tel == ADV_VOICE)
11649 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11651 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11652 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11653 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11660 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11661 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11662 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11664 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11665 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11675 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11676 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11677 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11680 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11681 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11682 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11684 if (ch_a_v == ch_b_v)
11686 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11687 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11691 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11693 for (i = 0; i < li_total_channels; i++)
11696 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11699 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11701 for (i = 0; i < li_total_channels; i++)
11704 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11707 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11709 for (i = 0; i < li_total_channels; i++)
11712 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11715 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11717 for (i = 0; i < li_total_channels; i++)
11720 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11724 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11726 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11728 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11731 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11733 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11734 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11735 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11736 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11738 if (li_flags & LI_FLAG_MONITOR_A)
11740 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11741 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11743 if (li_flags & LI_FLAG_MONITOR_B)
11745 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11746 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11748 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11750 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11753 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11755 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11758 if (li_flags & LI_FLAG_MIX_A)
11760 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11761 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11763 if (li_flags & LI_FLAG_MIX_B)
11765 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11766 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11768 if (ch_a_v != ch_a_s)
11770 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11771 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11773 if (ch_b_v != ch_b_s)
11775 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11776 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11781 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11782 dword plci_b_id, byte connect, dword li_flags)
11784 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11786 DIVA_CAPI_ADAPTER *a_b;
11788 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11789 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11790 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11791 if (!a->li_pri && (plci->tel == ADV_VOICE)
11792 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11794 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11795 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11796 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11803 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11804 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11805 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11807 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11808 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11809 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11818 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11819 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11820 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11822 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11823 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11825 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11833 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11835 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11837 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11840 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11842 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11843 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11844 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11845 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11847 if (li_flags & LI2_FLAG_MONITOR_B)
11849 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11850 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11852 if (li_flags & LI2_FLAG_MIX_B)
11854 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11855 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11857 if (li_flags & LI2_FLAG_MONITOR_X)
11858 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11859 if (li_flags & LI2_FLAG_MIX_X)
11860 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11861 if (li_flags & LI2_FLAG_LOOP_B)
11863 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11865 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11868 if (li_flags & LI2_FLAG_LOOP_PC)
11869 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11870 if (li_flags & LI2_FLAG_LOOP_X)
11871 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11872 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11873 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11874 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11875 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11876 if (ch_a_v != ch_a_s)
11878 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11879 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11881 if (ch_b_v != ch_b_s)
11883 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11884 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11889 static word li_check_main_plci(dword Id, PLCI *plci)
11893 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11894 UnMapId(Id), (char *)(FILE_), __LINE__));
11895 return (_WRONG_IDENTIFIER);
11898 || !plci->NL.Id || plci->nl_remove_id
11899 || (plci->li_bchannel_id == 0))
11901 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11902 UnMapId(Id), (char *)(FILE_), __LINE__));
11903 return (_WRONG_STATE);
11905 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11910 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11911 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11916 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11917 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11919 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11920 UnMapId(Id), (char *)(FILE_), __LINE__));
11921 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11925 if ((plci_b_id & 0x7f) != 0)
11927 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11928 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11932 || (((plci_b_id >> 8) & 0xff) == 0)
11933 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11935 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11936 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11937 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11940 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11942 || !plci_b->NL.Id || plci_b->nl_remove_id
11943 || (plci_b->li_bchannel_id == 0))
11945 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11946 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11947 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11950 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11951 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11952 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11953 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11956 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11957 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11958 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11961 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11962 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11964 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11965 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11966 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11973 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11974 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11979 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11980 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11982 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11983 UnMapId(Id), (char *)(FILE_), __LINE__));
11984 PUT_WORD(p_result, _WRONG_STATE);
11988 if ((plci_b_id & 0x7f) != 0)
11990 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11991 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11995 || (((plci_b_id >> 8) & 0xff) == 0)
11996 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11998 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11999 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12000 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12003 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12005 || !plci_b->NL.Id || plci_b->nl_remove_id
12006 || (plci_b->li_bchannel_id == 0)
12007 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12009 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12010 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12011 PUT_WORD(p_result, _WRONG_STATE);
12014 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12015 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12016 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12017 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12019 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12020 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12021 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12024 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12025 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12027 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12028 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12029 PUT_WORD(p_result, _WRONG_STATE);
12036 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12040 dword d, li_flags, plci_b_id;
12042 API_PARSE li_parms[3];
12043 API_PARSE li_req_parms[3];
12044 API_PARSE li_participant_struct[2];
12045 API_PARSE li_participant_parms[3];
12046 word participant_parms_pos;
12047 byte result_buffer[32];
12050 word plci_b_write_pos;
12052 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12053 UnMapId(Id), (char *)(FILE_), __LINE__));
12056 result = result_buffer;
12057 result_buffer[0] = 0;
12058 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12060 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12061 UnMapId(Id), (char *)(FILE_), __LINE__));
12062 Info = _FACILITY_NOT_SUPPORTED;
12064 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12066 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12067 UnMapId(Id), (char *)(FILE_), __LINE__));
12068 Info = _WRONG_MESSAGE_FORMAT;
12072 result_buffer[0] = 3;
12073 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12074 result_buffer[3] = 0;
12075 switch (GET_WORD(li_parms[0].info))
12077 case LI_GET_SUPPORTED_SERVICES:
12078 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12080 result_buffer[0] = 17;
12081 result_buffer[3] = 14;
12082 PUT_WORD(&result_buffer[4], GOOD);
12084 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12085 d |= LI_CONFERENCING_SUPPORTED;
12086 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12087 d |= LI_MONITORING_SUPPORTED;
12088 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12089 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12090 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12092 PUT_DWORD(&result_buffer[6], d);
12093 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12096 for (i = 0; i < li_total_channels; i++)
12098 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12099 && (li_config_table[i].adapter->li_pri
12100 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12108 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12110 PUT_DWORD(&result_buffer[10], d / 2);
12111 PUT_DWORD(&result_buffer[14], d);
12115 result_buffer[0] = 25;
12116 result_buffer[3] = 22;
12117 PUT_WORD(&result_buffer[4], GOOD);
12118 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12119 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12120 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12121 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12122 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12123 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12124 d |= LI2_PC_LOOPING_SUPPORTED;
12125 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12126 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12127 PUT_DWORD(&result_buffer[6], d);
12128 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12129 PUT_DWORD(&result_buffer[10], d / 2);
12130 PUT_DWORD(&result_buffer[14], d - 1);
12131 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12134 for (i = 0; i < li_total_channels; i++)
12136 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12137 && (li_config_table[i].adapter->li_pri
12138 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12144 PUT_DWORD(&result_buffer[18], d / 2);
12145 PUT_DWORD(&result_buffer[22], d - 1);
12149 case LI_REQ_CONNECT:
12150 if (li_parms[1].length == 8)
12152 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12153 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12155 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12156 UnMapId(Id), (char *)(FILE_), __LINE__));
12157 Info = _WRONG_MESSAGE_FORMAT;
12160 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12161 li_flags = GET_DWORD(li_req_parms[1].info);
12162 Info = li_check_main_plci(Id, plci);
12163 result_buffer[0] = 9;
12164 result_buffer[3] = 6;
12165 PUT_DWORD(&result_buffer[4], plci_b_id);
12166 PUT_WORD(&result_buffer[8], GOOD);
12169 result = plci->saved_msg.info;
12170 for (i = 0; i <= result_buffer[0]; i++)
12171 result[i] = result_buffer[i];
12172 plci_b_write_pos = plci->li_plci_b_write_pos;
12173 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12174 if (plci_b == NULL)
12176 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12177 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12178 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12179 plci->li_plci_b_write_pos = plci_b_write_pos;
12183 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12184 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12186 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12187 UnMapId(Id), (char *)(FILE_), __LINE__));
12188 Info = _WRONG_MESSAGE_FORMAT;
12191 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12192 Info = li_check_main_plci(Id, plci);
12193 result_buffer[0] = 7;
12194 result_buffer[3] = 4;
12195 PUT_WORD(&result_buffer[4], Info);
12196 result_buffer[6] = 0;
12199 result = plci->saved_msg.info;
12200 for (i = 0; i <= result_buffer[0]; i++)
12201 result[i] = result_buffer[i];
12202 plci_b_write_pos = plci->li_plci_b_write_pos;
12203 participant_parms_pos = 0;
12205 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12206 while (participant_parms_pos < li_req_parms[1].length)
12208 result[result_pos] = 6;
12210 PUT_DWORD(&result[result_pos - 6], 0);
12211 PUT_WORD(&result[result_pos - 2], GOOD);
12212 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12213 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12215 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 UnMapId(Id), (char *)(FILE_), __LINE__));
12217 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12220 if (api_parse(&li_participant_struct[0].info[1],
12221 li_participant_struct[0].length, "dd", li_participant_parms))
12223 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12224 UnMapId(Id), (char *)(FILE_), __LINE__));
12225 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12228 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12229 li_flags = GET_DWORD(li_participant_parms[1].info);
12230 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12231 if (sizeof(result) - result_pos < 7)
12233 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12234 UnMapId(Id), (char *)(FILE_), __LINE__));
12235 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12238 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12239 if (plci_b != NULL)
12241 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12242 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12243 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12244 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12245 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12247 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12248 (&li_req_parms[1].info[1]));
12250 result[0] = (byte)(result_pos - 1);
12251 result[3] = (byte)(result_pos - 4);
12252 result[6] = (byte)(result_pos - 7);
12253 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12254 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12255 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12257 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12258 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12261 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12262 plci->li_plci_b_write_pos = plci_b_write_pos;
12264 mixer_calculate_coefs(a);
12265 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12266 mixer_notify_update(plci, true);
12267 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12268 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12270 plci->li_cmd = GET_WORD(li_parms[0].info);
12271 start_internal_command(Id, plci, mixer_command);
12274 case LI_REQ_DISCONNECT:
12275 if (li_parms[1].length == 4)
12277 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12278 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12280 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12281 UnMapId(Id), (char *)(FILE_), __LINE__));
12282 Info = _WRONG_MESSAGE_FORMAT;
12285 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12286 Info = li_check_main_plci(Id, plci);
12287 result_buffer[0] = 9;
12288 result_buffer[3] = 6;
12289 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12290 PUT_WORD(&result_buffer[8], GOOD);
12293 result = plci->saved_msg.info;
12294 for (i = 0; i <= result_buffer[0]; i++)
12295 result[i] = result_buffer[i];
12296 plci_b_write_pos = plci->li_plci_b_write_pos;
12297 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12298 if (plci_b == NULL)
12300 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12301 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12302 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12303 plci->li_plci_b_write_pos = plci_b_write_pos;
12307 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12308 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12310 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12311 UnMapId(Id), (char *)(FILE_), __LINE__));
12312 Info = _WRONG_MESSAGE_FORMAT;
12315 Info = li_check_main_plci(Id, plci);
12316 result_buffer[0] = 7;
12317 result_buffer[3] = 4;
12318 PUT_WORD(&result_buffer[4], Info);
12319 result_buffer[6] = 0;
12322 result = plci->saved_msg.info;
12323 for (i = 0; i <= result_buffer[0]; i++)
12324 result[i] = result_buffer[i];
12325 plci_b_write_pos = plci->li_plci_b_write_pos;
12326 participant_parms_pos = 0;
12328 while (participant_parms_pos < li_req_parms[0].length)
12330 result[result_pos] = 6;
12332 PUT_DWORD(&result[result_pos - 6], 0);
12333 PUT_WORD(&result[result_pos - 2], GOOD);
12334 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12335 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12337 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12338 UnMapId(Id), (char *)(FILE_), __LINE__));
12339 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12342 if (api_parse(&li_participant_struct[0].info[1],
12343 li_participant_struct[0].length, "d", li_participant_parms))
12345 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12346 UnMapId(Id), (char *)(FILE_), __LINE__));
12347 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12350 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12351 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12352 if (sizeof(result) - result_pos < 7)
12354 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12355 UnMapId(Id), (char *)(FILE_), __LINE__));
12356 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12359 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12360 if (plci_b != NULL)
12362 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12363 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12364 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12366 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12367 (&li_req_parms[0].info[1]));
12369 result[0] = (byte)(result_pos - 1);
12370 result[3] = (byte)(result_pos - 4);
12371 result[6] = (byte)(result_pos - 7);
12372 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12373 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12374 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12376 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12377 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12380 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12381 plci->li_plci_b_write_pos = plci_b_write_pos;
12383 mixer_calculate_coefs(a);
12384 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12385 mixer_notify_update(plci, true);
12386 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12387 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12389 plci->li_cmd = GET_WORD(li_parms[0].info);
12390 start_internal_command(Id, plci, mixer_command);
12393 case LI_REQ_SILENT_UPDATE:
12394 if (!plci || !plci->State
12395 || !plci->NL.Id || plci->nl_remove_id
12396 || (plci->li_bchannel_id == 0)
12397 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12399 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12400 UnMapId(Id), (char *)(FILE_), __LINE__));
12403 plci_b_write_pos = plci->li_plci_b_write_pos;
12404 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12405 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12407 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12408 UnMapId(Id), (char *)(FILE_), __LINE__));
12411 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12412 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12413 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12415 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12416 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12419 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12420 plci->li_plci_b_write_pos = plci_b_write_pos;
12421 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12423 plci->li_cmd = GET_WORD(li_parms[0].info);
12424 start_internal_command(Id, plci, mixer_command);
12428 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12429 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12430 Info = _FACILITY_NOT_SUPPORTED;
12433 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12434 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12439 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12444 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12445 UnMapId(Id), (char *)(FILE_), __LINE__));
12447 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12451 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12452 if (!(d & LI_PLCI_B_SKIP_FLAG))
12454 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12456 if (d & LI_PLCI_B_DISC_FLAG)
12459 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12461 PUT_WORD(&result[4], _LI_USER_INITIATED);
12466 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12468 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12473 if (d & LI_PLCI_B_DISC_FLAG)
12476 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12478 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12479 PUT_WORD(&result[8], _LI_USER_INITIATED);
12484 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12486 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12489 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12490 "ws", SELECTOR_LINE_INTERCONNECT, result);
12492 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12493 0 : plci->li_plci_b_read_pos + 1;
12494 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12499 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12502 struct xconnect_transfer_address_s s, *p;
12503 DIVA_CAPI_ADAPTER *a;
12505 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12506 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12510 for (i = 1; i < length; i += 16)
12512 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12513 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12514 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12515 ch = msg[i + 12] | (msg[i + 13] << 8);
12516 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12517 if (!a->li_pri && (plci->li_bchannel_id == 2))
12520 if (ch & XCONNECT_CHANNEL_PORT_PC)
12521 p = &(li_config_table[j].send_pc);
12523 p = &(li_config_table[j].send_b);
12524 p->card_address.low = s.card_address.low;
12525 p->card_address.high = s.card_address.high;
12526 p->offset = s.offset;
12527 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12529 if (plci->internal_command_queue[0]
12530 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12531 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12532 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12534 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12535 if (!plci->internal_command)
12536 next_internal_command(Id, plci);
12538 mixer_notify_update(plci, true);
12542 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12545 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12546 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12551 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12553 word plci_b_write_pos;
12555 plci_b_write_pos = plci->li_plci_b_write_pos;
12556 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12557 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12559 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12560 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12561 (char *)(FILE_), __LINE__));
12564 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12565 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12566 plci->li_plci_b_write_pos = plci_b_write_pos;
12571 static void mixer_remove(PLCI *plci)
12573 DIVA_CAPI_ADAPTER *a;
12578 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12579 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12580 (char *)(FILE_), __LINE__));
12583 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12584 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12586 if ((plci->li_bchannel_id != 0)
12587 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12589 i = a->li_base + (plci->li_bchannel_id - 1);
12590 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12592 for (j = 0; j < li_total_channels; j++)
12594 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12595 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12597 notify_plci = li_config_table[j].plci;
12598 if ((notify_plci != NULL)
12599 && (notify_plci != plci)
12600 && (notify_plci->appl != NULL)
12601 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12602 && (notify_plci->State)
12603 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12605 mixer_notify_source_removed(notify_plci, plci_b_id);
12609 mixer_clear_config(plci);
12610 mixer_calculate_coefs(a);
12611 mixer_notify_update(plci, true);
12613 li_config_table[i].plci = NULL;
12614 plci->li_bchannel_id = 0;
12620 /*------------------------------------------------------------------*/
12621 /* Echo canceller facilities */
12622 /*------------------------------------------------------------------*/
12625 static void ec_write_parameters(PLCI *plci)
12628 byte parameter_buffer[6];
12630 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12631 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12632 (char *)(FILE_), __LINE__));
12634 parameter_buffer[0] = 5;
12635 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12636 PUT_WORD(¶meter_buffer[2], plci->ec_idi_options);
12637 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12638 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12639 PUT_WORD(¶meter_buffer[4], w);
12640 add_p(plci, FTY, parameter_buffer);
12641 sig_req(plci, TEL_CTRL, 0);
12646 static void ec_clear_config(PLCI *plci)
12649 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12650 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12651 (char *)(FILE_), __LINE__));
12653 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12654 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12655 plci->ec_tail_length = 0;
12659 static void ec_prepare_switch(dword Id, PLCI *plci)
12662 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12663 UnMapId(Id), (char *)(FILE_), __LINE__));
12668 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12671 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12672 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12678 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12682 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12683 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12686 if (plci->B1_facilities & B1_FACILITY_EC)
12688 switch (plci->adjust_b_state)
12690 case ADJUST_B_RESTORE_EC_1:
12691 plci->internal_command = plci->adjust_b_command;
12694 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12697 ec_write_parameters(plci);
12698 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12700 case ADJUST_B_RESTORE_EC_2:
12701 if ((Rc != OK) && (Rc != OK_FC))
12703 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12704 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12705 Info = _WRONG_STATE;
12715 static void ec_command(dword Id, PLCI *plci, byte Rc)
12717 word internal_command, Info;
12720 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12721 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12722 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12725 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12728 PUT_WORD(&result[1], EC_SUCCESS);
12733 PUT_WORD(&result[1], plci->ec_cmd);
12735 PUT_WORD(&result[4], GOOD);
12737 internal_command = plci->internal_command;
12738 plci->internal_command = 0;
12739 switch (plci->ec_cmd)
12741 case EC_ENABLE_OPERATION:
12742 case EC_FREEZE_COEFFICIENTS:
12743 case EC_RESUME_COEFFICIENT_UPDATE:
12744 case EC_RESET_COEFFICIENTS:
12745 switch (internal_command)
12748 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12749 B1_FACILITY_EC), EC_COMMAND_1);
12751 if (adjust_b_process(Id, plci, Rc) != GOOD)
12753 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12754 UnMapId(Id), (char *)(FILE_), __LINE__));
12755 Info = _FACILITY_NOT_SUPPORTED;
12758 if (plci->internal_command)
12763 plci->internal_command = EC_COMMAND_2;
12766 plci->internal_command = EC_COMMAND_3;
12767 ec_write_parameters(plci);
12770 if ((Rc != OK) && (Rc != OK_FC))
12772 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12773 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12774 Info = _FACILITY_NOT_SUPPORTED;
12781 case EC_DISABLE_OPERATION:
12782 switch (internal_command)
12786 if (plci->B1_facilities & B1_FACILITY_EC)
12790 plci->internal_command = EC_COMMAND_1;
12793 plci->internal_command = EC_COMMAND_2;
12794 ec_write_parameters(plci);
12799 if ((Rc != OK) && (Rc != OK_FC))
12801 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12802 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12803 Info = _FACILITY_NOT_SUPPORTED;
12806 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12807 ~B1_FACILITY_EC), EC_COMMAND_3);
12809 if (adjust_b_process(Id, plci, Rc) != GOOD)
12811 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12812 UnMapId(Id), (char *)(FILE_), __LINE__));
12813 Info = _FACILITY_NOT_SUPPORTED;
12816 if (plci->internal_command)
12822 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12823 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12824 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12828 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12832 API_PARSE ec_parms[3];
12835 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12836 UnMapId(Id), (char *)(FILE_), __LINE__));
12840 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12842 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12843 UnMapId(Id), (char *)(FILE_), __LINE__));
12844 Info = _FACILITY_NOT_SUPPORTED;
12848 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12850 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12852 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12853 UnMapId(Id), (char *)(FILE_), __LINE__));
12854 Info = _WRONG_MESSAGE_FORMAT;
12860 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12861 UnMapId(Id), (char *)(FILE_), __LINE__));
12862 Info = _WRONG_IDENTIFIER;
12864 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12866 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12867 UnMapId(Id), (char *)(FILE_), __LINE__));
12868 Info = _WRONG_STATE;
12873 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12874 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12876 PUT_WORD(&result[1], EC_SUCCESS);
12877 if (msg[1].length >= 4)
12879 opt = GET_WORD(&ec_parms[0].info[2]);
12880 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12881 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12882 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12883 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12884 if (opt & EC_DETECT_DISABLE_TONE)
12885 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12886 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12887 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12888 if (msg[1].length >= 6)
12890 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12893 switch (plci->ec_cmd)
12895 case EC_ENABLE_OPERATION:
12896 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12897 start_internal_command(Id, plci, ec_command);
12900 case EC_DISABLE_OPERATION:
12901 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12902 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12903 LEC_RESET_COEFFICIENTS;
12904 start_internal_command(Id, plci, ec_command);
12907 case EC_FREEZE_COEFFICIENTS:
12908 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12909 start_internal_command(Id, plci, ec_command);
12912 case EC_RESUME_COEFFICIENT_UPDATE:
12913 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12914 start_internal_command(Id, plci, ec_command);
12917 case EC_RESET_COEFFICIENTS:
12918 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12919 start_internal_command(Id, plci, ec_command);
12923 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12924 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12925 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12932 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12934 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12935 UnMapId(Id), (char *)(FILE_), __LINE__));
12936 Info = _WRONG_MESSAGE_FORMAT;
12940 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12943 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12945 PUT_WORD(&result[4], GOOD);
12946 PUT_WORD(&result[6], 0x0007);
12947 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12948 PUT_WORD(&result[10], 0);
12950 else if (plci == NULL)
12952 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12953 UnMapId(Id), (char *)(FILE_), __LINE__));
12954 Info = _WRONG_IDENTIFIER;
12956 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12958 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12959 UnMapId(Id), (char *)(FILE_), __LINE__));
12960 Info = _WRONG_STATE;
12965 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12966 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12968 PUT_WORD(&result[1], plci->ec_cmd);
12970 PUT_WORD(&result[4], GOOD);
12971 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12972 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12973 plci->ec_tail_length = 0;
12974 if (ec_parms[1].length >= 2)
12976 opt = GET_WORD(&ec_parms[1].info[1]);
12977 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12978 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12979 if (opt & EC_DETECT_DISABLE_TONE)
12980 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12981 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12982 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12983 if (ec_parms[1].length >= 4)
12985 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12988 switch (plci->ec_cmd)
12990 case EC_ENABLE_OPERATION:
12991 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12992 start_internal_command(Id, plci, ec_command);
12995 case EC_DISABLE_OPERATION:
12996 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12997 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12998 LEC_RESET_COEFFICIENTS;
12999 start_internal_command(Id, plci, ec_command);
13003 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13004 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13005 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13011 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13012 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13013 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13018 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13022 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13023 UnMapId(Id), (char *)(FILE_), __LINE__));
13025 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13027 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13030 PUT_WORD(&result[1], 0);
13033 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13034 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13036 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13037 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13039 case LEC_DISABLE_RELEASED:
13040 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13047 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13049 PUT_WORD(&result[4], 0);
13052 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13053 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13055 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13056 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13058 case LEC_DISABLE_RELEASED:
13059 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13063 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13064 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13070 /*------------------------------------------------------------------*/
13071 /* Advanced voice */
13072 /*------------------------------------------------------------------*/
13074 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13076 DIVA_CAPI_ADAPTER *a;
13081 byte ch_map[MIXER_CHANNELS_BRI];
13083 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13085 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13086 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13087 (char *)(FILE_), __LINE__, write_command));
13090 p = coef_buffer + 1;
13091 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13093 while (i + sizeof(word) <= a->adv_voice_coef_length)
13095 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13099 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13101 PUT_WORD(p, 0x8000);
13106 if (!a->li_pri && (plci->li_bchannel_id == 0))
13108 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13110 plci->li_bchannel_id = 1;
13111 li_config_table[a->li_base].plci = plci;
13112 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13114 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13116 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13118 plci->li_bchannel_id = 2;
13119 li_config_table[a->li_base + 1].plci = plci;
13120 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13121 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13122 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13125 if (!a->li_pri && (plci->li_bchannel_id != 0)
13126 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13128 i = a->li_base + (plci->li_bchannel_id - 1);
13129 switch (write_command)
13131 case ADV_VOICE_WRITE_ACTIVATION:
13132 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13133 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13134 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13136 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13137 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13139 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13141 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13142 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13143 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13144 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13146 mixer_calculate_coefs(a);
13147 li_config_table[i].curchnl = li_config_table[i].channel;
13148 li_config_table[j].curchnl = li_config_table[j].channel;
13149 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13150 li_config_table[k].curchnl = li_config_table[k].channel;
13153 case ADV_VOICE_WRITE_DEACTIVATION:
13154 for (j = 0; j < li_total_channels; j++)
13156 li_config_table[i].flag_table[j] = 0;
13157 li_config_table[j].flag_table[i] = 0;
13159 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13160 for (j = 0; j < li_total_channels; j++)
13162 li_config_table[k].flag_table[j] = 0;
13163 li_config_table[j].flag_table[k] = 0;
13165 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13167 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13168 for (j = 0; j < li_total_channels; j++)
13170 li_config_table[k].flag_table[j] = 0;
13171 li_config_table[j].flag_table[k] = 0;
13174 mixer_calculate_coefs(a);
13177 if (plci->B1_facilities & B1_FACILITY_MIXER)
13180 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13181 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13182 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13183 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13184 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13185 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13187 *(p++) = (byte)(w >> 8);
13188 for (j = 0; j < sizeof(ch_map); j += 2)
13190 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13191 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13193 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13195 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13196 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13197 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13199 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13200 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13201 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13205 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13206 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13212 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213 *(p++) = a->adv_voice_coef_buffer[i];
13219 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13220 *(p++) = a->adv_voice_coef_buffer[i];
13222 coef_buffer[0] = (p - coef_buffer) - 1;
13223 add_p(plci, FTY, coef_buffer);
13224 sig_req(plci, TEL_CTRL, 0);
13229 static void adv_voice_clear_config(PLCI *plci)
13231 DIVA_CAPI_ADAPTER *a;
13236 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13237 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13238 (char *)(FILE_), __LINE__));
13241 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13243 a->adv_voice_coef_length = 0;
13245 if (!a->li_pri && (plci->li_bchannel_id != 0)
13246 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13248 i = a->li_base + (plci->li_bchannel_id - 1);
13249 li_config_table[i].curchnl = 0;
13250 li_config_table[i].channel = 0;
13251 li_config_table[i].chflags = 0;
13252 for (j = 0; j < li_total_channels; j++)
13254 li_config_table[i].flag_table[j] = 0;
13255 li_config_table[j].flag_table[i] = 0;
13256 li_config_table[i].coef_table[j] = 0;
13257 li_config_table[j].coef_table[i] = 0;
13259 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13260 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13261 li_config_table[i].curchnl = 0;
13262 li_config_table[i].channel = 0;
13263 li_config_table[i].chflags = 0;
13264 for (j = 0; j < li_total_channels; j++)
13266 li_config_table[i].flag_table[j] = 0;
13267 li_config_table[j].flag_table[i] = 0;
13268 li_config_table[i].coef_table[j] = 0;
13269 li_config_table[j].coef_table[i] = 0;
13271 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13273 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13274 li_config_table[i].curchnl = 0;
13275 li_config_table[i].channel = 0;
13276 li_config_table[i].chflags = 0;
13277 for (j = 0; j < li_total_channels; j++)
13279 li_config_table[i].flag_table[j] = 0;
13280 li_config_table[j].flag_table[i] = 0;
13281 li_config_table[i].coef_table[j] = 0;
13282 li_config_table[j].coef_table[i] = 0;
13291 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13294 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13295 UnMapId(Id), (char *)(FILE_), __LINE__));
13300 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13303 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13304 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13310 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13312 DIVA_CAPI_ADAPTER *a;
13315 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13316 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13320 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13321 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13323 switch (plci->adjust_b_state)
13325 case ADJUST_B_RESTORE_VOICE_1:
13326 plci->internal_command = plci->adjust_b_command;
13329 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13332 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13333 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13335 case ADJUST_B_RESTORE_VOICE_2:
13336 if ((Rc != OK) && (Rc != OK_FC))
13338 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13339 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13340 Info = _WRONG_STATE;
13352 /*------------------------------------------------------------------*/
13353 /* B1 resource switching */
13354 /*------------------------------------------------------------------*/
13356 static byte b1_facilities_table[] =
13358 0x00, /* 0 No bchannel resources */
13359 0x00, /* 1 Codec (automatic law) */
13360 0x00, /* 2 Codec (A-law) */
13361 0x00, /* 3 Codec (y-law) */
13362 0x00, /* 4 HDLC for X.21 */
13364 0x00, /* 6 External Device 0 */
13365 0x00, /* 7 External Device 1 */
13366 0x00, /* 8 HDLC 56k */
13367 0x00, /* 9 Transparent */
13368 0x00, /* 10 Loopback to network */
13369 0x00, /* 11 Test pattern to net */
13370 0x00, /* 12 Rate adaptation sync */
13371 0x00, /* 13 Rate adaptation async */
13372 0x00, /* 14 R-Interface */
13373 0x00, /* 15 HDLC 128k leased line */
13375 0x00, /* 17 Modem async */
13376 0x00, /* 18 Modem sync HDLC */
13377 0x00, /* 19 V.110 async HDLC */
13378 0x12, /* 20 Adv voice (Trans,mixer) */
13379 0x00, /* 21 Codec connected to IC */
13380 0x0c, /* 22 Trans,DTMF */
13381 0x1e, /* 23 Trans,DTMF+mixer */
13382 0x1f, /* 24 Trans,DTMF+mixer+local */
13383 0x13, /* 25 Trans,mixer+local */
13384 0x12, /* 26 HDLC,mixer */
13385 0x12, /* 27 HDLC 56k,mixer */
13386 0x2c, /* 28 Trans,LEC+DTMF */
13387 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13388 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13389 0x2c, /* 31 RTP,LEC+DTMF */
13390 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13391 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13392 0x00, /* 34 Signaling task */
13393 0x00, /* 35 PIAFS */
13394 0x0c, /* 36 Trans,DTMF+TONE */
13395 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13396 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13400 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13402 word b1_facilities;
13404 b1_facilities = b1_facilities_table[b1_resource];
13405 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13408 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13409 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13412 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13413 b1_facilities |= B1_FACILITY_DTMFX;
13414 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13415 b1_facilities |= B1_FACILITY_DTMFR;
13418 if ((b1_resource == 17) || (b1_resource == 18))
13420 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13421 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13424 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13425 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13426 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13428 return (b1_facilities);
13432 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13436 switch (b1_resource)
13440 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13448 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13466 if (b1_facilities & B1_FACILITY_EC)
13468 if (b1_facilities & B1_FACILITY_LOCAL)
13470 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13476 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13477 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13478 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13480 if (b1_facilities & B1_FACILITY_LOCAL)
13482 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13488 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13489 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13490 || ((b1_facilities & B1_FACILITY_DTMFR)
13491 && ((b1_facilities & B1_FACILITY_MIXER)
13492 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13493 || ((b1_facilities & B1_FACILITY_DTMFX)
13494 && ((b1_facilities & B1_FACILITY_MIXER)
13495 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13497 if (b1_facilities & B1_FACILITY_LOCAL)
13499 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13506 if (b1_facilities & B1_FACILITY_LOCAL)
13508 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13518 if (b1_facilities & B1_FACILITY_LOCAL)
13520 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13529 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13530 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13531 (char *)(FILE_), __LINE__,
13532 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13537 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13539 word removed_facilities;
13541 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13542 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13543 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13544 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13546 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13547 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13549 if (removed_facilities & B1_FACILITY_EC)
13550 ec_clear_config(plci);
13553 if (removed_facilities & B1_FACILITY_DTMFR)
13555 dtmf_rec_clear_config(plci);
13556 dtmf_parameter_clear_config(plci);
13558 if (removed_facilities & B1_FACILITY_DTMFX)
13559 dtmf_send_clear_config(plci);
13562 if (removed_facilities & B1_FACILITY_MIXER)
13563 mixer_clear_config(plci);
13565 if (removed_facilities & B1_FACILITY_VOICE)
13566 adv_voice_clear_config(plci);
13567 plci->B1_facilities = new_b1_facilities;
13571 static void adjust_b_clear(PLCI *plci)
13574 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13575 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13576 (char *)(FILE_), __LINE__));
13578 plci->adjust_b_restore = false;
13582 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13589 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13590 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13593 switch (plci->adjust_b_state)
13595 case ADJUST_B_START:
13596 if ((plci->adjust_b_parms_msg == NULL)
13597 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13598 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13599 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13601 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13602 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13603 if (b1_resource == plci->B1_resource)
13605 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13608 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13610 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13611 UnMapId(Id), (char *)(FILE_), __LINE__,
13612 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13613 Info = _WRONG_STATE;
13617 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13620 mixer_prepare_switch(Id, plci);
13623 dtmf_prepare_switch(Id, plci);
13624 dtmf_parameter_prepare_switch(Id, plci);
13627 ec_prepare_switch(Id, plci);
13629 adv_voice_prepare_switch(Id, plci);
13631 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13633 case ADJUST_B_SAVE_MIXER_1:
13634 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13637 Info = mixer_save_config(Id, plci, Rc);
13638 if ((Info != GOOD) || plci->internal_command)
13642 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13644 case ADJUST_B_SAVE_DTMF_1:
13645 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13648 Info = dtmf_save_config(Id, plci, Rc);
13649 if ((Info != GOOD) || plci->internal_command)
13653 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13654 case ADJUST_B_REMOVE_L23_1:
13655 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13656 && plci->NL.Id && !plci->nl_remove_id)
13658 plci->internal_command = plci->adjust_b_command;
13659 if (plci->adjust_b_ncci != 0)
13661 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13662 while (ncci_ptr->data_pending)
13664 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13665 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13667 while (ncci_ptr->data_ack_pending)
13668 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13670 nl_req_ncci(plci, REMOVE,
13671 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13673 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13676 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13678 case ADJUST_B_REMOVE_L23_2:
13679 if ((Rc != OK) && (Rc != OK_FC))
13681 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13682 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13683 Info = _WRONG_STATE;
13686 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13688 if (plci_nl_busy(plci))
13690 plci->internal_command = plci->adjust_b_command;
13694 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13696 case ADJUST_B_SAVE_EC_1:
13697 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13700 Info = ec_save_config(Id, plci, Rc);
13701 if ((Info != GOOD) || plci->internal_command)
13705 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13707 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13708 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13711 Info = dtmf_parameter_save_config(Id, plci, Rc);
13712 if ((Info != GOOD) || plci->internal_command)
13716 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13718 case ADJUST_B_SAVE_VOICE_1:
13719 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13721 Info = adv_voice_save_config(Id, plci, Rc);
13722 if ((Info != GOOD) || plci->internal_command)
13725 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13726 case ADJUST_B_SWITCH_L1_1:
13727 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13731 plci->internal_command = plci->adjust_b_command;
13734 if (plci->adjust_b_parms_msg != NULL)
13735 api_load_msg(plci->adjust_b_parms_msg, bp);
13737 api_load_msg(&plci->B_protocol, bp);
13738 Info = add_b1(plci, bp,
13739 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13740 plci->adjust_b_facilities);
13743 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13744 UnMapId(Id), (char *)(FILE_), __LINE__,
13745 plci->B1_resource, plci->adjust_b_facilities));
13748 plci->internal_command = plci->adjust_b_command;
13749 sig_req(plci, RESOURCES, 0);
13751 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13754 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13756 case ADJUST_B_SWITCH_L1_2:
13757 if ((Rc != OK) && (Rc != OK_FC))
13759 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13760 UnMapId(Id), (char *)(FILE_), __LINE__,
13761 Rc, plci->B1_resource, plci->adjust_b_facilities));
13762 Info = _WRONG_STATE;
13765 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13767 case ADJUST_B_RESTORE_VOICE_1:
13768 case ADJUST_B_RESTORE_VOICE_2:
13769 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13771 Info = adv_voice_restore_config(Id, plci, Rc);
13772 if ((Info != GOOD) || plci->internal_command)
13775 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13777 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13778 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13779 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13782 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13783 if ((Info != GOOD) || plci->internal_command)
13787 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13789 case ADJUST_B_RESTORE_EC_1:
13790 case ADJUST_B_RESTORE_EC_2:
13791 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13794 Info = ec_restore_config(Id, plci, Rc);
13795 if ((Info != GOOD) || plci->internal_command)
13799 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13800 case ADJUST_B_ASSIGN_L23_1:
13801 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13803 if (plci_nl_busy(plci))
13805 plci->internal_command = plci->adjust_b_command;
13808 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13809 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13810 if (plci->adjust_b_parms_msg != NULL)
13811 api_load_msg(plci->adjust_b_parms_msg, bp);
13813 api_load_msg(&plci->B_protocol, bp);
13814 Info = add_b23(plci, bp);
13817 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13818 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13821 plci->internal_command = plci->adjust_b_command;
13822 nl_req_ncci(plci, ASSIGN, 0);
13824 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13827 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13829 case ADJUST_B_ASSIGN_L23_2:
13830 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13832 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13833 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13834 Info = _WRONG_STATE;
13837 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13839 if (Rc != ASSIGN_OK)
13841 plci->internal_command = plci->adjust_b_command;
13845 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13847 plci->adjust_b_restore = true;
13850 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13851 case ADJUST_B_CONNECT_1:
13852 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13854 plci->internal_command = plci->adjust_b_command;
13855 if (plci_nl_busy(plci))
13857 nl_req_ncci(plci, N_CONNECT, 0);
13859 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13862 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13864 case ADJUST_B_CONNECT_2:
13865 case ADJUST_B_CONNECT_3:
13866 case ADJUST_B_CONNECT_4:
13867 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13869 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13870 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13871 Info = _WRONG_STATE;
13876 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13878 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13879 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13881 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13883 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13884 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13888 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13889 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13890 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13891 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13893 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13895 plci->internal_command = plci->adjust_b_command;
13899 case ADJUST_B_RESTORE_DTMF_1:
13900 case ADJUST_B_RESTORE_DTMF_2:
13901 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13904 Info = dtmf_restore_config(Id, plci, Rc);
13905 if ((Info != GOOD) || plci->internal_command)
13909 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13911 case ADJUST_B_RESTORE_MIXER_1:
13912 case ADJUST_B_RESTORE_MIXER_2:
13913 case ADJUST_B_RESTORE_MIXER_3:
13914 case ADJUST_B_RESTORE_MIXER_4:
13915 case ADJUST_B_RESTORE_MIXER_5:
13916 case ADJUST_B_RESTORE_MIXER_6:
13917 case ADJUST_B_RESTORE_MIXER_7:
13918 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13921 Info = mixer_restore_config(Id, plci, Rc);
13922 if ((Info != GOOD) || plci->internal_command)
13926 plci->adjust_b_state = ADJUST_B_END;
13934 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13937 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13938 UnMapId(Id), (char *)(FILE_), __LINE__,
13939 plci->B1_resource, b1_facilities));
13941 plci->adjust_b_parms_msg = bp_msg;
13942 plci->adjust_b_facilities = b1_facilities;
13943 plci->adjust_b_command = internal_command;
13944 plci->adjust_b_ncci = (word)(Id >> 16);
13945 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13946 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13948 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13949 plci->adjust_b_state = ADJUST_B_START;
13950 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13951 UnMapId(Id), (char *)(FILE_), __LINE__,
13952 plci->B1_resource, b1_facilities));
13956 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13958 word internal_command;
13960 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13961 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13963 internal_command = plci->internal_command;
13964 plci->internal_command = 0;
13965 switch (internal_command)
13969 if (plci->req_in != 0)
13971 plci->internal_command = ADJUST_B_RESTORE_1;
13975 case ADJUST_B_RESTORE_1:
13976 if ((Rc != OK) && (Rc != OK_FC))
13978 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13979 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13981 plci->adjust_b_parms_msg = NULL;
13982 plci->adjust_b_facilities = plci->B1_facilities;
13983 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13984 plci->adjust_b_ncci = (word)(Id >> 16);
13985 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13986 plci->adjust_b_state = ADJUST_B_START;
13987 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13988 UnMapId(Id), (char *)(FILE_), __LINE__));
13989 case ADJUST_B_RESTORE_2:
13990 if (adjust_b_process(Id, plci, Rc) != GOOD)
13992 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13993 UnMapId(Id), (char *)(FILE_), __LINE__));
13995 if (plci->internal_command)
14002 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14005 word internal_command;
14007 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14008 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14011 internal_command = plci->internal_command;
14012 plci->internal_command = 0;
14013 switch (internal_command)
14017 plci->adjust_b_parms_msg = NULL;
14018 plci->adjust_b_facilities = plci->B1_facilities;
14019 plci->adjust_b_command = RESET_B3_COMMAND_1;
14020 plci->adjust_b_ncci = (word)(Id >> 16);
14021 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14022 plci->adjust_b_state = ADJUST_B_START;
14023 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14024 UnMapId(Id), (char *)(FILE_), __LINE__));
14025 case RESET_B3_COMMAND_1:
14026 Info = adjust_b_process(Id, plci, Rc);
14029 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14030 UnMapId(Id), (char *)(FILE_), __LINE__));
14033 if (plci->internal_command)
14037 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14038 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14042 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14045 word internal_command;
14048 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14049 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14052 internal_command = plci->internal_command;
14053 plci->internal_command = 0;
14054 switch (internal_command)
14058 plci->adjust_b_parms_msg = &plci->saved_msg;
14059 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14060 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14062 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14063 plci->adjust_b_command = SELECT_B_COMMAND_1;
14064 plci->adjust_b_ncci = (word)(Id >> 16);
14065 if (plci->saved_msg.parms[0].length == 0)
14067 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14068 ADJUST_B_MODE_NO_RESOURCE;
14072 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14073 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14075 plci->adjust_b_state = ADJUST_B_START;
14076 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14077 UnMapId(Id), (char *)(FILE_), __LINE__));
14078 case SELECT_B_COMMAND_1:
14079 Info = adjust_b_process(Id, plci, Rc);
14082 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14083 UnMapId(Id), (char *)(FILE_), __LINE__));
14086 if (plci->internal_command)
14088 if (plci->tel == ADV_VOICE)
14092 esc_chi[2] = plci->b_channel;
14093 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14097 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14101 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14103 word internal_command;
14105 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14106 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14108 internal_command = plci->internal_command;
14109 plci->internal_command = 0;
14110 switch (internal_command)
14114 case FAX_CONNECT_ACK_COMMAND_1:
14115 if (plci_nl_busy(plci))
14117 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14120 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14121 plci->NData[0].P = plci->fax_connect_info_buffer;
14122 plci->NData[0].PLength = plci->fax_connect_info_length;
14123 plci->NL.X = plci->NData;
14124 plci->NL.ReqCh = 0;
14125 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14126 plci->adapter->request(&plci->NL);
14128 case FAX_CONNECT_ACK_COMMAND_2:
14129 if ((Rc != OK) && (Rc != OK_FC))
14131 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14132 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14136 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14137 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14139 if (plci->B3_prot == 4)
14140 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14142 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14143 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14148 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14150 word internal_command;
14152 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14153 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14155 internal_command = plci->internal_command;
14156 plci->internal_command = 0;
14157 switch (internal_command)
14161 case FAX_EDATA_ACK_COMMAND_1:
14162 if (plci_nl_busy(plci))
14164 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14167 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14168 plci->NData[0].P = plci->fax_connect_info_buffer;
14169 plci->NData[0].PLength = plci->fax_edata_ack_length;
14170 plci->NL.X = plci->NData;
14171 plci->NL.ReqCh = 0;
14172 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14173 plci->adapter->request(&plci->NL);
14175 case FAX_EDATA_ACK_COMMAND_2:
14176 if ((Rc != OK) && (Rc != OK_FC))
14178 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14179 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14186 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14189 word internal_command;
14191 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14192 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14195 internal_command = plci->internal_command;
14196 plci->internal_command = 0;
14197 switch (internal_command)
14201 case FAX_CONNECT_INFO_COMMAND_1:
14202 if (plci_nl_busy(plci))
14204 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14207 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14208 plci->NData[0].P = plci->fax_connect_info_buffer;
14209 plci->NData[0].PLength = plci->fax_connect_info_length;
14210 plci->NL.X = plci->NData;
14211 plci->NL.ReqCh = 0;
14212 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14213 plci->adapter->request(&plci->NL);
14215 case FAX_CONNECT_INFO_COMMAND_2:
14216 if ((Rc != OK) && (Rc != OK_FC))
14218 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14219 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14220 Info = _WRONG_STATE;
14223 if (plci_nl_busy(plci))
14225 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14228 plci->command = _CONNECT_B3_R;
14229 nl_req_ncci(plci, N_CONNECT, 0);
14233 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14237 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14240 word internal_command;
14242 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14243 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14246 internal_command = plci->internal_command;
14247 plci->internal_command = 0;
14248 switch (internal_command)
14252 plci->adjust_b_parms_msg = NULL;
14253 plci->adjust_b_facilities = plci->B1_facilities;
14254 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14255 plci->adjust_b_ncci = (word)(Id >> 16);
14256 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14257 plci->adjust_b_state = ADJUST_B_START;
14258 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14259 UnMapId(Id), (char *)(FILE_), __LINE__));
14260 case FAX_ADJUST_B23_COMMAND_1:
14261 Info = adjust_b_process(Id, plci, Rc);
14264 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14265 UnMapId(Id), (char *)(FILE_), __LINE__));
14268 if (plci->internal_command)
14270 case FAX_ADJUST_B23_COMMAND_2:
14271 if (plci_nl_busy(plci))
14273 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14276 plci->command = _CONNECT_B3_R;
14277 nl_req_ncci(plci, N_CONNECT, 0);
14281 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14285 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14287 word internal_command;
14289 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14290 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14292 internal_command = plci->internal_command;
14293 plci->internal_command = 0;
14294 switch (internal_command)
14298 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14300 case FAX_DISCONNECT_COMMAND_1:
14301 case FAX_DISCONNECT_COMMAND_2:
14302 case FAX_DISCONNECT_COMMAND_3:
14303 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14305 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14306 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14311 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14312 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14314 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14319 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14320 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14328 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14331 word internal_command;
14333 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14334 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14337 internal_command = plci->internal_command;
14338 plci->internal_command = 0;
14339 switch (internal_command)
14343 case RTP_CONNECT_B3_REQ_COMMAND_1:
14344 if (plci_nl_busy(plci))
14346 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14349 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14350 nl_req_ncci(plci, N_CONNECT, 0);
14353 case RTP_CONNECT_B3_REQ_COMMAND_2:
14354 if ((Rc != OK) && (Rc != OK_FC))
14356 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14357 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14358 Info = _WRONG_STATE;
14361 if (plci_nl_busy(plci))
14363 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14366 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14367 plci->NData[0].PLength = plci->internal_req_buffer[0];
14368 plci->NData[0].P = plci->internal_req_buffer + 1;
14369 plci->NL.X = plci->NData;
14370 plci->NL.ReqCh = 0;
14371 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14372 plci->adapter->request(&plci->NL);
14374 case RTP_CONNECT_B3_REQ_COMMAND_3:
14377 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14381 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14383 word internal_command;
14385 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14386 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14388 internal_command = plci->internal_command;
14389 plci->internal_command = 0;
14390 switch (internal_command)
14394 case RTP_CONNECT_B3_RES_COMMAND_1:
14395 if (plci_nl_busy(plci))
14397 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14400 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14401 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14404 case RTP_CONNECT_B3_RES_COMMAND_2:
14405 if ((Rc != OK) && (Rc != OK_FC))
14407 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14408 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14411 if (plci_nl_busy(plci))
14413 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14416 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14417 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14418 plci->NData[0].PLength = plci->internal_req_buffer[0];
14419 plci->NData[0].P = plci->internal_req_buffer + 1;
14420 plci->NL.X = plci->NData;
14421 plci->NL.ReqCh = 0;
14422 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14423 plci->adapter->request(&plci->NL);
14425 case RTP_CONNECT_B3_RES_COMMAND_3:
14432 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14434 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14436 word internal_command;
14438 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14439 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14442 internal_command = plci->internal_command;
14443 plci->internal_command = 0;
14444 switch (internal_command)
14450 plci->adjust_b_parms_msg = NULL;
14451 plci->adjust_b_facilities = plci->B1_facilities;
14452 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14453 plci->adjust_b_ncci = (word)(Id >> 16);
14454 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14455 plci->adjust_b_state = ADJUST_B_START;
14456 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14457 UnMapId(Id), (char *)(FILE_), __LINE__));
14458 case HOLD_SAVE_COMMAND_1:
14459 Info = adjust_b_process(Id, plci, Rc);
14462 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14463 UnMapId(Id), (char *)(FILE_), __LINE__));
14466 if (plci->internal_command)
14469 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14473 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14475 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14477 word internal_command;
14479 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14480 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14483 internal_command = plci->internal_command;
14484 plci->internal_command = 0;
14485 switch (internal_command)
14489 plci->adjust_b_parms_msg = NULL;
14490 plci->adjust_b_facilities = plci->B1_facilities;
14491 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14492 plci->adjust_b_ncci = (word)(Id >> 16);
14493 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14494 plci->adjust_b_state = ADJUST_B_START;
14495 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14496 UnMapId(Id), (char *)(FILE_), __LINE__));
14497 case RETRIEVE_RESTORE_COMMAND_1:
14498 Info = adjust_b_process(Id, plci, Rc);
14501 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14502 UnMapId(Id), (char *)(FILE_), __LINE__));
14505 if (plci->internal_command)
14508 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14512 static void init_b1_config(PLCI *plci)
14515 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14516 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14517 (char *)(FILE_), __LINE__));
14519 plci->B1_resource = 0;
14520 plci->B1_facilities = 0;
14522 plci->li_bchannel_id = 0;
14523 mixer_clear_config(plci);
14526 ec_clear_config(plci);
14529 dtmf_rec_clear_config(plci);
14530 dtmf_send_clear_config(plci);
14531 dtmf_parameter_clear_config(plci);
14533 adv_voice_clear_config(plci);
14534 adjust_b_clear(plci);
14538 static void clear_b1_config(PLCI *plci)
14541 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14542 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14543 (char *)(FILE_), __LINE__));
14545 adv_voice_clear_config(plci);
14546 adjust_b_clear(plci);
14548 ec_clear_config(plci);
14551 dtmf_rec_clear_config(plci);
14552 dtmf_send_clear_config(plci);
14553 dtmf_parameter_clear_config(plci);
14556 if ((plci->li_bchannel_id != 0)
14557 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14559 mixer_clear_config(plci);
14560 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14561 plci->li_bchannel_id = 0;
14564 plci->B1_resource = 0;
14565 plci->B1_facilities = 0;
14569 /* -----------------------------------------------------------------
14570 XON protocol local helpers
14571 ----------------------------------------------------------------- */
14572 static void channel_flow_control_remove(PLCI *plci) {
14573 DIVA_CAPI_ADAPTER *a = plci->adapter;
14575 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14576 if (a->ch_flow_plci[i] == plci->Id) {
14577 a->ch_flow_plci[i] = 0;
14578 a->ch_flow_control[i] = 0;
14583 static void channel_x_on(PLCI *plci, byte ch) {
14584 DIVA_CAPI_ADAPTER *a = plci->adapter;
14585 if (a->ch_flow_control[ch] & N_XON_SENT) {
14586 a->ch_flow_control[ch] &= ~N_XON_SENT;
14590 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14591 DIVA_CAPI_ADAPTER *a = plci->adapter;
14592 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14593 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14594 a->ch_flow_plci[ch] = plci->Id;
14595 a->ch_flow_control_pending++;
14599 static void channel_request_xon(PLCI *plci, byte ch) {
14600 DIVA_CAPI_ADAPTER *a = plci->adapter;
14602 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14603 a->ch_flow_control[ch] |= N_XON_REQ;
14604 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14605 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14609 static void channel_xmit_extended_xon(PLCI *plci) {
14610 DIVA_CAPI_ADAPTER *a;
14611 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14612 int i, one_requested = 0;
14614 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14618 for (i = 0; i < max_ch; i++) {
14619 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14620 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14621 (plci->Id == a->ch_flow_plci[i])) {
14622 channel_request_xon(plci, (byte)i);
14627 if (one_requested) {
14628 channel_xmit_xon(plci);
14633 Try to xmit next X_ON
14635 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14636 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14639 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14643 if (a->last_flow_control_ch >= max_ch) {
14644 a->last_flow_control_ch = 1;
14646 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14647 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14648 (plci->Id == a->ch_flow_plci[i])) {
14649 a->last_flow_control_ch = i + 1;
14654 for (i = 1; i < a->last_flow_control_ch; i++) {
14655 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14656 (plci->Id == a->ch_flow_plci[i])) {
14657 a->last_flow_control_ch = i + 1;
14665 static void channel_xmit_xon(PLCI *plci) {
14666 DIVA_CAPI_ADAPTER *a = plci->adapter;
14669 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14672 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14675 a->ch_flow_control[ch] &= ~N_XON_REQ;
14676 a->ch_flow_control[ch] |= N_XON_SENT;
14678 plci->NL.Req = plci->nl_req = (byte)N_XON;
14679 plci->NL.ReqCh = ch;
14680 plci->NL.X = plci->NData;
14682 plci->NData[0].P = &plci->RBuffer[0];
14683 plci->NData[0].PLength = 0;
14685 plci->adapter->request(&plci->NL);
14688 static int channel_can_xon(PLCI *plci, byte ch) {
14690 DIVA_CAPI_ADAPTER *a;
14696 APPLptr = plci->appl;
14702 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14704 /* count all buffers within the Application pool */
14705 /* belonging to the same NCCI. XON if a first is */
14709 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14710 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14711 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14713 if ((count > 2) || (Num == 0xffff)) {
14720 /*------------------------------------------------------------------*/
14722 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14729 /**********************************************************************************/
14730 /* function groups the listening applications according to the CIP mask and the */
14731 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14732 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14733 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14734 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14735 /* OS specific part (per adapter). */
14736 /**********************************************************************************/
14737 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14739 word i, j, k, busy, group_found;
14740 dword info_mask_group[MAX_CIP_TYPES];
14741 dword cip_mask_group[MAX_CIP_TYPES];
14742 word appl_number_group_type[MAX_APPL];
14745 set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14747 if (!a->group_optimization_enabled)
14749 dbug(1, dprintf("No group optimization"));
14753 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14755 for (i = 0; i < MAX_CIP_TYPES; i++)
14757 info_mask_group[i] = 0;
14758 cip_mask_group[i] = 0;
14760 for (i = 0; i < MAX_APPL; i++)
14762 appl_number_group_type[i] = 0;
14764 for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14765 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14766 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14768 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14769 return; /* allow good application unfiltered access */
14772 for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14774 if (application[i].Id && a->CIP_Mask[i])
14776 for (k = 0, busy = false; k < a->max_plci; k++)
14780 auxplci = &a->plci[k];
14781 if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14784 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14786 else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14789 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14794 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14796 if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14797 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14798 appl_number_group_type[i] = MAX_CIP_TYPES;
14799 group_found = true;
14800 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14802 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14803 { /* is group already present ? */
14804 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14805 group_found = true;
14806 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]));
14808 else if (!info_mask_group[j])
14809 { /* establish a new group */
14810 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14811 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14812 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14813 group_found = true;
14814 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]));
14820 for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14822 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14824 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14826 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14830 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14831 for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14833 if (appl_number_group_type[i] == appl_number_group_type[j])
14835 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14836 clear_group_ind_mask_bit(plci, j); /* disable call on other group members */
14837 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14842 else /* application should not get a call */
14844 clear_group_ind_mask_bit(plci, i);
14852 /* OS notifies the driver about a application Capi_Register */
14853 word CapiRegister(word id)
14855 word i, j, appls_found;
14858 DIVA_CAPI_ADAPTER *a;
14860 for (i = 0, appls_found = 0; i < max_appl; i++)
14862 if (application[i].Id && (application[i].Id != id))
14864 appls_found++; /* an application has been found */
14868 if (appls_found) return true;
14869 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14874 if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14876 if (!appls_found) /* first application does a capi register */
14878 if ((j = get_plci(a))) /* activate L1 of all adapters */
14880 plci = &a->plci[j - 1];
14882 add_p(plci, OAD, "\x01\xfd");
14883 add_p(plci, CAI, "\x01\x80");
14884 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14885 add_p(plci, SHIFT | 6, NULL);
14886 add_p(plci, SIN, "\x02\x00\x00");
14887 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14888 sig_req(plci, ASSIGN, DSIG_ID);
14889 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14890 sig_req(plci, SIG_CTRL, 0);
14900 /*------------------------------------------------------------------*/
14902 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14904 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14907 /* Format of vswitch_t:
14910 2 byte VSWITCH_REQ/VSWITCH_IND
14912 4 word VSwitchcommand
14919 plci->Sig.Ind == NCR_FACILITY
14923 for (i = 0; i < MAX_MULTI_IE; i++)
14925 if (!parms[i][0]) continue;
14926 if (parms[i][0] < 7)
14928 parms[i][0] = 0; /* kill it */
14931 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14932 switch (parms[i][4])
14935 if (!plci->relatedPTYPLCI ||
14936 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14940 /* remember all necessary informations */
14941 if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14945 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14946 { /* first indication after ECT-Request on Consultation Call */
14947 plci->vswitchstate = parms[i][9];
14948 parms[i][9] = 2; /* State */
14949 /* now ask first Call to join */
14951 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14952 { /* Answer of VSWITCH_REQ from first Call */
14953 plci->vswitchstate = parms[i][9];
14954 /* tell consultation call to join
14955 and the protocol capabilities of the first call */
14961 plci->vsprot = parms[i][10]; /* protocol */
14962 plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14963 /* send join request to related PLCI */
14964 parms[i][1] = VSWITCHIE;
14965 parms[i][2] = VSWITCH_REQ;
14967 plci->relatedPTYPLCI->command = 0;
14968 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14969 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14970 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14971 send_req(plci->relatedPTYPLCI);
14975 if (plci->relatedPTYPLCI &&
14976 plci->vswitchstate == 3 &&
14977 plci->relatedPTYPLCI->vswitchstate == 3)
14979 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14980 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14981 send_req(plci->relatedPTYPLCI);
14985 parms[i][0] = 0; /* kill it */
14990 /*------------------------------------------------------------------*/
14992 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14994 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14996 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15000 pReq->xdi_dma_descriptor_operation.Req = 0;
15001 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15003 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15004 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15005 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15006 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15008 e.user[0] = plci->adapter->Id - 1;
15009 plci->adapter->request((ENTITY *)pReq);
15011 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15012 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15013 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15014 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15015 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15017 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15019 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15021 dbug(1, dprintf("dma_alloc failed"));
15026 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15028 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15034 pReq->xdi_dma_descriptor_operation.Req = 0;
15035 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15037 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15038 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15039 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15040 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15042 e.user[0] = plci->adapter->Id - 1;
15043 plci->adapter->request((ENTITY *)pReq);
15045 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15046 dbug(1, dprintf("dma_free(%d)", nr));
15048 dbug(1, dprintf("dma_free failed (%d)", nr));
15052 /*------------------------------------------------------------------*/