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.
26 #include <linux/bitmap.h>
36 #define FILE_ "MESSAGE.C"
39 /*------------------------------------------------------------------*/
40 /* This is options supported for all adapters that are server by */
41 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
42 /* and it is not necessary to save it separate for every adapter */
43 /* Macrose defined here have only local meaning */
44 /*------------------------------------------------------------------*/
45 static dword diva_xdi_extended_features = 0;
47 #define DIVA_CAPI_USE_CMA 0x00000001
48 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
49 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
50 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
53 CAPI can request to process all return codes self only if:
54 protocol code supports this && xdi supports this
56 #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))
58 /*------------------------------------------------------------------*/
59 /* local function prototypes */
60 /*------------------------------------------------------------------*/
62 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
63 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
64 word CapiRelease(word);
65 word CapiRegister(word);
66 word api_put(APPL *, CAPI_MSG *);
67 static word api_parse(byte *, word, byte *, API_PARSE *);
68 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
69 static void api_load_msg(API_SAVE *in, API_PARSE *out);
71 word api_remove_start(void);
72 void api_remove_complete(void);
74 static void plci_remove(PLCI *);
75 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
76 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
78 void callback(ENTITY *);
80 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
81 static void data_rc(PLCI *, byte);
82 static void data_ack(PLCI *, byte);
83 static void sig_ind(PLCI *);
84 static void SendInfo(PLCI *, dword, byte **, byte);
85 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
86 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
88 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
90 static void nl_ind(PLCI *);
92 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
93 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
94 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
95 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
96 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
97 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
98 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
99 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
100 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
101 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
102 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
103 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
104 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
105 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
106 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
107 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static word get_plci(DIVA_CAPI_ADAPTER *);
118 static void add_p(PLCI *, byte, byte *);
119 static void add_s(PLCI *plci, byte code, API_PARSE *p);
120 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
121 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
122 static void add_d(PLCI *, word, byte *);
123 static void add_ai(PLCI *, API_PARSE *);
124 static word add_b1(PLCI *, API_PARSE *, word, word);
125 static word add_b23(PLCI *, API_PARSE *);
126 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
127 static void sig_req(PLCI *, byte, byte);
128 static void nl_req_ncci(PLCI *, byte, byte);
129 static void send_req(PLCI *);
130 static void send_data(PLCI *);
131 static word plci_remove_check(PLCI *);
132 static void listen_check(DIVA_CAPI_ADAPTER *);
133 static byte AddInfo(byte **, byte **, byte *, byte *);
134 static byte getChannel(API_PARSE *);
135 static void IndParse(PLCI *, const word *, byte **, byte);
136 static byte ie_compare(byte *, byte *);
137 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
138 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
143 static void channel_flow_control_remove(PLCI *plci);
144 static void channel_x_off(PLCI *plci, byte ch, byte flag);
145 static void channel_x_on(PLCI *plci, byte ch);
146 static void channel_request_xon(PLCI *plci, byte ch);
147 static void channel_xmit_xon(PLCI *plci);
148 static int channel_can_xon(PLCI *plci, byte ch);
149 static void channel_xmit_extended_xon(PLCI *plci);
151 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
152 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
153 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
154 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
155 static void VoiceChannelOff(PLCI *plci);
156 static void adv_voice_write_coefs(PLCI *plci, word write_command);
157 static void adv_voice_clear_config(PLCI *plci);
159 static word get_b1_facilities(PLCI *plci, byte b1_resource);
160 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
161 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
162 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
163 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
164 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
165 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
166 static void select_b_command(dword Id, PLCI *plci, byte Rc);
167 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
168 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
169 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
170 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
171 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
172 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
173 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
174 static void init_b1_config(PLCI *plci);
175 static void clear_b1_config(PLCI *plci);
177 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
178 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
179 static void dtmf_confirmation(dword Id, PLCI *plci);
180 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
181 static void dtmf_parameter_write(PLCI *plci);
184 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
185 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
186 static void mixer_clear_config(PLCI *plci);
187 static void mixer_notify_update(PLCI *plci, byte others);
188 static void mixer_command(dword Id, PLCI *plci, byte Rc);
189 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
190 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
191 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
192 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
193 static void mixer_remove(PLCI *plci);
196 static void ec_command(dword Id, PLCI *plci, byte Rc);
197 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
198 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
201 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
202 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
205 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
206 static void diva_free_dma_descriptor(PLCI *plci, int nr);
208 /*------------------------------------------------------------------*/
209 /* external function prototypes */
210 /*------------------------------------------------------------------*/
212 extern byte MapController(byte);
213 extern byte UnMapController(byte);
214 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
215 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
217 void sendf(APPL *, word, dword, word, byte *, ...);
218 void *TransmitBufferSet(APPL *appl, dword ref);
219 void *TransmitBufferGet(APPL *appl, void *p);
220 void TransmitBufferFree(APPL *appl, void *p);
221 void *ReceiveBufferGet(APPL *appl, int Num);
223 int fax_head_line_time(char *buffer);
226 /*------------------------------------------------------------------*/
227 /* Global data definitions */
228 /*------------------------------------------------------------------*/
229 extern byte max_adapter;
230 extern byte max_appl;
231 extern DIVA_CAPI_ADAPTER *adapter;
232 extern APPL *application;
240 static byte remove_started = false;
241 static PLCI dummy_plci;
244 static struct _ftable {
247 byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
249 {_DATA_B3_R, "dwww", data_b3_req},
250 {_DATA_B3_I | RESPONSE, "w", data_b3_res},
251 {_INFO_R, "ss", info_req},
252 {_INFO_I | RESPONSE, "", info_res},
253 {_CONNECT_R, "wsssssssss", connect_req},
254 {_CONNECT_I | RESPONSE, "wsssss", connect_res},
255 {_CONNECT_ACTIVE_I | RESPONSE, "", connect_a_res},
256 {_DISCONNECT_R, "s", disconnect_req},
257 {_DISCONNECT_I | RESPONSE, "", disconnect_res},
258 {_LISTEN_R, "dddss", listen_req},
259 {_ALERT_R, "s", alert_req},
260 {_FACILITY_R, "ws", facility_req},
261 {_FACILITY_I | RESPONSE, "ws", facility_res},
262 {_CONNECT_B3_R, "s", connect_b3_req},
263 {_CONNECT_B3_I | RESPONSE, "ws", connect_b3_res},
264 {_CONNECT_B3_ACTIVE_I | RESPONSE, "", connect_b3_a_res},
265 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
266 {_DISCONNECT_B3_I | RESPONSE, "", disconnect_b3_res},
267 {_RESET_B3_R, "s", reset_b3_req},
268 {_RESET_B3_I | RESPONSE, "", reset_b3_res},
269 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws", connect_b3_t90_a_res},
270 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "", connect_b3_t90_a_res},
271 {_SELECT_B_REQ, "s", select_b_req},
272 {_MANUFACTURER_R, "dws", manufacturer_req},
273 {_MANUFACTURER_I | RESPONSE, "dws", manufacturer_res},
274 {_MANUFACTURER_I | RESPONSE, "", manufacturer_res}
277 static byte *cip_bc[29][2] = {
279 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
280 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
281 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
282 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
283 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
284 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
285 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
286 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
287 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
295 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
296 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
297 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
298 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
299 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
300 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
301 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
302 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
303 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
304 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
305 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
306 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
307 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
310 static byte *cip_hlc[29] = {
328 "\x02\x91\x81", /* 16 */
329 "\x02\x91\x84", /* 17 */
330 "\x02\x91\xa1", /* 18 */
331 "\x02\x91\xa4", /* 19 */
332 "\x02\x91\xa8", /* 20 */
333 "\x02\x91\xb1", /* 21 */
334 "\x02\x91\xb2", /* 22 */
335 "\x02\x91\xb5", /* 23 */
336 "\x02\x91\xb8", /* 24 */
337 "\x02\x91\xc1", /* 25 */
338 "\x02\x91\x81", /* 26 */
339 "\x03\x91\xe0\x01", /* 27 */
340 "\x03\x91\xe0\x02" /* 28 */
343 /*------------------------------------------------------------------*/
345 #define V120_HEADER_LENGTH 1
346 #define V120_HEADER_EXTEND_BIT 0x80
347 #define V120_HEADER_BREAK_BIT 0x40
348 #define V120_HEADER_C1_BIT 0x04
349 #define V120_HEADER_C2_BIT 0x08
350 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
352 static byte v120_default_header[] =
355 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
359 static byte v120_break_header[] =
362 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
367 /*------------------------------------------------------------------*/
368 /* API_PUT function */
369 /*------------------------------------------------------------------*/
371 word api_put(APPL *appl, CAPI_MSG *msg)
377 DIVA_CAPI_ADAPTER *a;
382 API_PARSE msg_parms[MAX_MSG_PARMS + 1];
384 if (msg->header.length < sizeof(msg->header) ||
385 msg->header.length > MAX_MSG_SIZE) {
386 dbug(1, dprintf("bad len"));
390 controller = (byte)((msg->header.controller & 0x7f) - 1);
392 /* controller starts with 0 up to (max_adapter - 1) */
393 if (controller >= max_adapter)
395 dbug(1, dprintf("invalid ctrl"));
399 a = &adapter[controller];
401 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
403 dbug(1, dprintf("plci=%x", msg->header.plci));
404 plci = &a->plci[msg->header.plci - 1];
405 ncci = GET_WORD(&msg->header.ncci);
408 || (plci->State == INC_CON_PENDING)
409 || (plci->State == INC_CON_ALERT)
410 || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
412 || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
413 || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
415 i = plci->msg_in_read_pos;
416 j = plci->msg_in_write_pos;
419 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
420 i += MSG_IN_QUEUE_SIZE - j;
427 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
429 if (i > MSG_IN_QUEUE_SIZE - n)
430 i = MSG_IN_QUEUE_SIZE - n + 1;
434 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
437 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
438 msg->header.length, plci->msg_in_write_pos,
439 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
444 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
445 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
447 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
450 if (msg->header.command == _DATA_B3_R)
452 if (msg->header.length < 20)
454 dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
457 ncci_ptr = &(a->ncci[ncci]);
458 n = ncci_ptr->data_pending;
459 l = ncci_ptr->data_ack_pending;
460 k = plci->msg_in_read_pos;
461 while (k != plci->msg_in_write_pos)
463 if (k == plci->msg_in_wrap_pos)
465 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
466 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
469 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
473 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
474 MSG_IN_OVERHEAD + 3) & 0xfffc;
477 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
479 dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
480 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
484 if (plci->req_in || plci->internal_command)
486 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
487 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
489 dbug(0, dprintf("Q-FULL3(requeue)"));
498 if (plci->req_in || plci->internal_command)
502 plci->command = msg->header.command;
503 plci->number = msg->header.number;
508 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
509 msg->header.command, plci->req_in, plci->internal_command,
510 msg->header.length, plci->msg_in_write_pos,
511 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
513 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
514 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
515 for (i = 0; i < msg->header.length; i++)
516 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
517 if (m->header.command == _DATA_B3_R)
520 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
524 j = (j + 3) & 0xfffc;
526 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
527 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
536 dbug(1, dprintf("com=%x", msg->header.command));
538 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
539 for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
541 if (ftable[i].command == msg->header.command) {
542 /* break loop if the message is correct, otherwise continue scan */
543 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
544 if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
548 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
552 dbug(1, dprintf("BAD_MSG"));
553 if (plci) plci->command = 0;
558 c = ftable[i].function(GET_DWORD(&msg->header.controller),
565 channel_xmit_extended_xon(plci);
567 if (c == 1) send_req(plci);
568 if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
569 if (plci && !plci->req_in) plci->command = 0;
574 /*------------------------------------------------------------------*/
575 /* api_parse function, check the format of api messages */
576 /*------------------------------------------------------------------*/
578 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
583 for (i = 0, p = 0; format[i]; i++) {
586 parms[i].info = &msg[p];
599 if (msg[p] == 0xff) {
601 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
602 p += (parms[i].length + 3);
605 parms[i].length = msg[p];
606 p += (parms[i].length + 1);
611 if (p > length) return true;
613 if (parms) parms[i].info = NULL;
617 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
623 for (i = 0; format[i] != '\0'; i++)
625 out->parms[i].info = p;
626 out->parms[i].length = in[i].length;
639 n = in[i].length + 1;
642 for (j = 0; j < n; j++)
643 *(p++) = in[i].info[j];
645 out->parms[i].info = NULL;
646 out->parms[i].length = 0;
649 static void api_load_msg(API_SAVE *in, API_PARSE *out)
656 out[i].info = in->parms[i].info;
657 out[i].length = in->parms[i].length;
658 } while (in->parms[i++].info);
662 /*------------------------------------------------------------------*/
663 /* CAPI remove function */
664 /*------------------------------------------------------------------*/
666 word api_remove_start(void)
671 if (!remove_started) {
672 remove_started = true;
673 for (i = 0; i < max_adapter; i++) {
674 if (adapter[i].request) {
675 for (j = 0; j < adapter[i].max_plci; j++) {
676 if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
683 for (i = 0; i < max_adapter; i++) {
684 if (adapter[i].request) {
685 for (j = 0; j < adapter[i].max_plci; j++) {
686 if (adapter[i].plci[j].Sig.Id) return 1;
691 api_remove_complete();
696 /*------------------------------------------------------------------*/
697 /* internal command queue */
698 /*------------------------------------------------------------------*/
700 static void init_internal_command_queue(PLCI *plci)
704 dbug(1, dprintf("%s,%d: init_internal_command_queue",
705 (char *)(FILE_), __LINE__));
707 plci->internal_command = 0;
708 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
709 plci->internal_command_queue[i] = NULL;
713 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
717 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
718 UnMapId(Id), (char *)(FILE_), __LINE__));
720 if (plci->internal_command == 0)
722 plci->internal_command_queue[0] = command_function;
723 (*command_function)(Id, plci, OK);
728 while (plci->internal_command_queue[i] != NULL)
730 plci->internal_command_queue[i] = command_function;
735 static void next_internal_command(dword Id, PLCI *plci)
739 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
740 UnMapId(Id), (char *)(FILE_), __LINE__));
742 plci->internal_command = 0;
743 plci->internal_command_queue[0] = NULL;
744 while (plci->internal_command_queue[1] != NULL)
746 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
747 plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
748 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
749 (*(plci->internal_command_queue[0]))(Id, plci, OK);
750 if (plci->internal_command != 0)
752 plci->internal_command_queue[0] = NULL;
757 /*------------------------------------------------------------------*/
758 /* NCCI allocate/remove function */
759 /*------------------------------------------------------------------*/
761 static dword ncci_mapping_bug = 0;
763 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
765 DIVA_CAPI_ADAPTER *a;
769 if (!ch || a->ch_ncci[ch])
772 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
773 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
782 if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
787 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
789 if (ncci == MAX_NCCI + 1)
796 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
799 if (j < MAX_NCCI + 1)
804 } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
806 } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
807 if (i < MAX_NL_CHANNEL + 1)
809 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
810 ncci_mapping_bug, ch, force_ncci, i, k, j));
814 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
815 ncci_mapping_bug, ch, force_ncci));
820 a->ncci_plci[ncci] = plci->Id;
821 a->ncci_state[ncci] = IDLE;
822 if (!plci->ncci_ring_list)
823 plci->ncci_ring_list = ncci;
825 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
826 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
828 a->ncci_ch[ncci] = ch;
829 a->ch_ncci[ch] = (byte) ncci;
830 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
831 ncci_mapping_bug, ch, force_ncci, ch, ncci));
837 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
839 DIVA_CAPI_ADAPTER *a;
845 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
848 if (a->ncci_plci[ncci] == plci->Id)
853 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
854 ncci_mapping_bug, Id));
859 ncci_code = ncci | (((word) a->Id) << 8);
860 for (i = 0; i < appl->MaxBuffer; i++)
862 if ((appl->DataNCCI[i] == ncci_code)
863 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
865 appl->DataNCCI[i] = 0;
873 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
875 if (a->ncci_plci[ncci] == plci->Id)
880 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
881 ncci_mapping_bug, Id));
886 ncci_code = ncci | (((word) a->Id) << 8);
887 for (i = 0; i < appl->MaxBuffer; i++)
889 if ((appl->DataNCCI[i] == ncci_code)
890 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
892 appl->DataNCCI[i] = 0;
902 static void cleanup_ncci_data(PLCI *plci, word ncci)
906 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
908 ncci_ptr = &(plci->adapter->ncci[ncci]);
911 while (ncci_ptr->data_pending != 0)
913 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
914 TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
915 (ncci_ptr->data_out)++;
916 if (ncci_ptr->data_out == MAX_DATA_B3)
917 ncci_ptr->data_out = 0;
918 (ncci_ptr->data_pending)--;
921 ncci_ptr->data_out = 0;
922 ncci_ptr->data_pending = 0;
923 ncci_ptr->data_ack_out = 0;
924 ncci_ptr->data_ack_pending = 0;
929 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
931 DIVA_CAPI_ADAPTER *a;
936 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
938 ncci_free_receive_buffers(plci, ncci);
941 if (a->ncci_plci[ncci] != plci->Id)
944 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
945 ncci_mapping_bug, Id, preserve_ncci));
949 cleanup_ncci_data(plci, ncci);
950 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
951 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
952 a->ch_ncci[a->ncci_ch[ncci]] = 0;
955 a->ncci_ch[ncci] = 0;
956 a->ncci_plci[ncci] = 0;
957 a->ncci_state[ncci] = IDLE;
958 i = plci->ncci_ring_list;
959 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
961 if ((i != 0) && (a->ncci_next[i] == ncci))
964 plci->ncci_ring_list = 0;
965 else if (plci->ncci_ring_list == ncci)
966 plci->ncci_ring_list = i;
967 a->ncci_next[i] = a->ncci_next[ncci];
969 a->ncci_next[ncci] = 0;
975 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
977 if (a->ncci_plci[ncci] == plci->Id)
979 cleanup_ncci_data(plci, ncci);
980 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
981 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
982 a->ch_ncci[a->ncci_ch[ncci]] = 0;
985 a->ncci_ch[ncci] = 0;
986 a->ncci_plci[ncci] = 0;
987 a->ncci_state[ncci] = IDLE;
988 a->ncci_next[ncci] = 0;
993 plci->ncci_ring_list = 0;
998 /*------------------------------------------------------------------*/
999 /* PLCI remove function */
1000 /*------------------------------------------------------------------*/
1002 static void plci_free_msg_in_queue(PLCI *plci)
1008 i = plci->msg_in_read_pos;
1009 while (i != plci->msg_in_write_pos)
1011 if (i == plci->msg_in_wrap_pos)
1013 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1016 TransmitBufferFree(plci->appl,
1017 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1021 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1022 MSG_IN_OVERHEAD + 3) & 0xfffc;
1026 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1027 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1028 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1032 static void plci_remove(PLCI *plci)
1036 dbug(1, dprintf("plci_remove(no plci)"));
1039 init_internal_command_queue(plci);
1040 dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1041 if (plci_remove_check(plci))
1045 if (plci->Sig.Id == 0xff)
1047 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1048 if (plci->NL.Id && !plci->nl_remove_id)
1050 nl_req_ncci(plci, REMOVE, 0);
1056 if (!plci->sig_remove_id
1058 || (plci->req_in != plci->req_out)
1059 || (plci->nl_req || plci->sig_req)))
1061 sig_req(plci, HANGUP, 0);
1065 ncci_remove(plci, 0, false);
1066 plci_free_msg_in_queue(plci);
1070 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1071 plci->State = OUTG_DIS_PENDING;
1074 /*------------------------------------------------------------------*/
1075 /* translation function for each message */
1076 /*------------------------------------------------------------------*/
1078 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1079 PLCI *plci, APPL *appl, API_PARSE *parms)
1087 API_PARSE ai_parms[5];
1091 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1092 static byte lli[2] = {0x01, 0x00};
1097 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1099 dbug(1, dprintf("connect_req(%d)", parms->length));
1100 Info = _WRONG_IDENTIFIER;
1103 if (a->adapter_disabled)
1105 dbug(1, dprintf("adapter disabled"));
1106 Id = ((word)1 << 8) | a->Id;
1107 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1108 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1111 Info = _OUT_OF_PLCI;
1112 if ((i = get_plci(a)))
1115 plci = &a->plci[i - 1];
1117 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1118 /* check 'external controller' bit for codec support */
1119 if (Id & EXT_CONTROLLER)
1121 if (AdvCodecSupport(a, plci, appl, 0))
1124 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1131 if (bp->length)LinkLayer = bp->info[3];
1136 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1139 if (ai_parms[0].length)
1141 ch = GET_WORD(ai_parms[0].info + 1);
1142 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1143 if (ch == 4) /* explizit CHI in message */
1145 /* check length of B-CH struct */
1146 if ((ai_parms[0].info)[3] >= 1)
1148 if ((ai_parms[0].info)[4] == CHI)
1150 p_chi = &((ai_parms[0].info)[5]);
1154 p_chi = &((ai_parms[0].info)[3]);
1156 if (p_chi[0] > 35) /* check length of channel ID */
1158 Info = _WRONG_MESSAGE_FORMAT;
1161 else Info = _WRONG_MESSAGE_FORMAT;
1164 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1166 dir = GET_WORD(ai_parms[0].info + 3);
1169 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1171 if (ai_parms[0].info[i + 5] != 0)
1173 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1174 Info = _WRONG_MESSAGE_FORMAT;
1185 Info = _WRONG_MESSAGE_FORMAT;
1188 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1190 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1191 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1192 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1196 esc_chi[2] = (byte)channel;
1197 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1198 add_p(plci, LLI, lli);
1199 add_p(plci, ESC, esc_chi);
1200 plci->State = LOCAL_CONNECT;
1201 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1206 else Info = _WRONG_MESSAGE_FORMAT;
1209 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1210 plci->command = _CONNECT_R;
1211 plci->number = Number;
1212 /* x.31 or D-ch free SAPI in LinkLayer? */
1213 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1214 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1216 /* B-channel used for B3 connections (ch==0), or no B channel */
1217 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1218 if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1219 else Info = add_b1(plci, &parms[5], ch, 0);
1220 add_s(plci, OAD, &parms[2]);
1221 add_s(plci, OSA, &parms[4]);
1222 add_s(plci, BC, &parms[6]);
1223 add_s(plci, LLC, &parms[7]);
1224 add_s(plci, HLC, &parms[8]);
1225 if (a->Info_Mask[appl->Id - 1] & 0x200)
1227 /* early B3 connect (CIP mask bit 9) no release after a disc */
1228 add_p(plci, LLI, "\x01\x01");
1230 if (GET_WORD(parms[0].info) < 29) {
1231 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1232 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1234 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1235 sig_req(plci, ASSIGN, DSIG_ID);
1239 /* D-Channel used for B3 connections */
1240 plci->Sig.Id = 0xff;
1244 if (!Info && ch != 2 && !noCh) {
1245 Info = add_b23(plci, &parms[5]);
1247 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1253 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1255 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1257 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1258 plci->spoofed_msg = CALL_REQ;
1259 plci->internal_command = BLOCK_PLCI;
1261 dbug(1, dprintf("Spoof"));
1265 if (ch == 4)add_p(plci, CHI, p_chi);
1266 add_s(plci, CPN, &parms[1]);
1267 add_s(plci, DSA, &parms[3]);
1268 if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1269 add_ai(plci, &parms[9]);
1270 if (!dir)sig_req(plci, CALL_REQ, 0);
1273 plci->command = PERM_LIST_REQ;
1275 sig_req(plci, LISTEN_REQ, 0);
1287 _CONNECT_R | CONFIRM,
1294 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1295 PLCI *plci, APPL *appl, API_PARSE *parms)
1299 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1300 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1302 API_PARSE ai_parms[5];
1306 dbug(1, dprintf("connect_res(no plci)"));
1307 return 0; /* no plci, no send */
1310 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1311 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1313 dbug(1, dprintf("ai->length=%d", ai->length));
1317 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1319 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1321 if (ai_parms[0].length)
1323 ch = GET_WORD(ai_parms[0].info + 1);
1324 dbug(1, dprintf("BCH-I=0x%x", ch));
1329 if (plci->State == INC_CON_CONNECTED_ALERT)
1331 dbug(1, dprintf("Connected Alert Call_Res"));
1332 if (a->Info_Mask[appl->Id - 1] & 0x200)
1334 /* early B3 connect (CIP mask bit 9) no release after a disc */
1335 add_p(plci, LLI, "\x01\x01");
1337 add_s(plci, CONN_NR, &parms[2]);
1338 add_s(plci, LLC, &parms[4]);
1339 add_ai(plci, &parms[5]);
1340 plci->State = INC_CON_ACCEPT;
1341 sig_req(plci, CALL_RES, 0);
1344 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1345 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1346 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
1347 Reject = GET_WORD(parms[0].info);
1348 dbug(1, dprintf("Reject=0x%x", Reject));
1351 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
1353 if ((Reject & 0xff00) == 0x3400)
1355 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1356 add_p(plci, ESC, esc_t);
1357 add_ai(plci, &parms[5]);
1358 sig_req(plci, REJECT, 0);
1360 else if (Reject == 1 || Reject >= 9)
1362 add_ai(plci, &parms[5]);
1363 sig_req(plci, HANGUP, 0);
1367 esc_t[2] = cau_t[(Reject&0x000f)];
1368 add_p(plci, ESC, esc_t);
1369 add_ai(plci, &parms[5]);
1370 sig_req(plci, REJECT, 0);
1376 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1381 if (Id & EXT_CONTROLLER) {
1382 if (AdvCodecSupport(a, plci, appl, 0)) {
1383 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1384 sig_req(plci, HANGUP, 0);
1387 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1389 Info = add_b23(plci, &parms[1]);
1392 dbug(1, dprintf("connect_res(error from add_b23)"));
1393 sig_req(plci, HANGUP, 0);
1398 nl_req_ncci(plci, ASSIGN, 0);
1407 Info = add_b23(plci, &parms[1]);
1410 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1411 sig_req(plci, HANGUP, 0);
1415 nl_req_ncci(plci, ASSIGN, 0);
1418 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1420 api_save_msg(parms, "wsssss", &plci->saved_msg);
1421 plci->spoofed_msg = CALL_RES;
1422 plci->internal_command = BLOCK_PLCI;
1424 dbug(1, dprintf("Spoof"));
1428 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1429 if (a->Info_Mask[appl->Id - 1] & 0x200)
1431 /* early B3 connect (CIP mask bit 9) no release after a disc */
1432 add_p(plci, LLI, "\x01\x01");
1434 add_s(plci, CONN_NR, &parms[2]);
1435 add_s(plci, LLC, &parms[4]);
1436 add_ai(plci, &parms[5]);
1437 plci->State = INC_CON_ACCEPT;
1438 sig_req(plci, CALL_RES, 0);
1441 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1442 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1448 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1449 PLCI *plci, APPL *appl, API_PARSE *msg)
1451 dbug(1, dprintf("connect_a_res"));
1455 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1456 PLCI *plci, APPL *appl, API_PARSE *msg)
1461 dbug(1, dprintf("disconnect_req"));
1463 Info = _WRONG_IDENTIFIER;
1467 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1469 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1471 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1472 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1473 plci->State = OUTG_DIS_PENDING;
1475 if (plci->Sig.Id && plci->appl)
1478 if (plci->Sig.Id != 0xff)
1480 if (plci->State != INC_DIS_PENDING)
1482 add_ai(plci, &msg[0]);
1483 sig_req(plci, HANGUP, 0);
1484 plci->State = OUTG_DIS_PENDING;
1490 if (plci->NL.Id && !plci->nl_remove_id)
1493 nl_req_ncci(plci, REMOVE, 0);
1494 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1496 plci->State = INC_DIS_PENDING;
1503 if (!appl) return false;
1504 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1508 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1509 PLCI *plci, APPL *appl, API_PARSE *msg)
1511 dbug(1, dprintf("disconnect_res"));
1514 /* clear ind mask bit, just in case of collsion of */
1515 /* DISCONNECT_IND and CONNECT_RES */
1516 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1517 ncci_free_receive_buffers(plci, 0);
1518 if (plci_remove_check(plci))
1522 if (plci->State == INC_DIS_PENDING
1523 || plci->State == SUSPENDING) {
1524 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
1525 if (plci->State != SUSPENDING) plci->State = IDLE;
1526 dbug(1, dprintf("chs=%d", plci->channels));
1527 if (!plci->channels) {
1536 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1537 PLCI *plci, APPL *appl, API_PARSE *parms)
1542 dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1544 Info = _WRONG_IDENTIFIER;
1547 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1548 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1549 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1550 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1551 a->Info_Mask[appl->Id - 1] |= 0x10; /* call progression infos */
1554 /* check if external controller listen and switch listen on or off*/
1555 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1556 if (a->profile.Global_Options & ON_BOARD_CODEC) {
1557 dummy_plci.State = IDLE;
1558 a->codec_listen[appl->Id - 1] = &dummy_plci;
1559 a->TelOAD[0] = (byte)(parms[3].length);
1560 for (i = 1; parms[3].length >= i && i < 22; i++) {
1561 a->TelOAD[i] = parms[3].info[i];
1564 a->TelOSA[0] = (byte)(parms[4].length);
1565 for (i = 1; parms[4].length >= i && i < 22; i++) {
1566 a->TelOSA[i] = parms[4].info[i];
1570 else Info = 0x2002; /* wrong controller, codec not supported */
1572 else{ /* clear listen */
1573 a->codec_listen[appl->Id - 1] = (PLCI *)0;
1577 _LISTEN_R | CONFIRM,
1582 if (a) listen_check(a);
1586 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1587 PLCI *plci, APPL *appl, API_PARSE *msg)
1591 PLCI *rc_plci = NULL;
1592 API_PARSE ai_parms[5];
1595 dbug(1, dprintf("info_req"));
1596 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1602 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1604 dbug(1, dprintf("AddInfo wrong"));
1605 Info = _WRONG_MESSAGE_FORMAT;
1608 if (!a) Info = _WRONG_STATE;
1611 { /* no fac, with CPN, or KEY */
1613 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1615 /* overlap sending option */
1616 dbug(1, dprintf("OvlSnd"));
1617 add_s(plci, CPN, &msg[0]);
1618 add_s(plci, KEY, &ai_parms[1]);
1619 sig_req(plci, INFO_REQ, 0);
1624 if (plci->State && ai_parms[2].length)
1626 /* User_Info option */
1627 dbug(1, dprintf("UUI"));
1628 add_s(plci, UUI, &ai_parms[2]);
1629 sig_req(plci, USER_DATA, 0);
1631 else if (plci->State && ai_parms[3].length)
1633 /* Facility option */
1634 dbug(1, dprintf("FAC"));
1635 add_s(plci, CPN, &msg[0]);
1636 add_ai(plci, &msg[1]);
1637 sig_req(plci, FACILITY_REQ, 0);
1641 Info = _WRONG_STATE;
1644 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1646 /* NCR_Facility option -> send UUI and Keypad too */
1647 dbug(1, dprintf("NCR_FAC"));
1648 if ((i = get_plci(a)))
1650 rc_plci = &a->plci[i - 1];
1651 appl->NullCREnable = true;
1652 rc_plci->internal_command = C_NCR_FAC_REQ;
1653 rc_plci->appl = appl;
1654 add_p(rc_plci, CAI, "\x01\x80");
1655 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1656 sig_req(rc_plci, ASSIGN, DSIG_ID);
1661 Info = _OUT_OF_PLCI;
1666 add_s(rc_plci, CPN, &msg[0]);
1667 add_ai(rc_plci, &msg[1]);
1668 sig_req(rc_plci, NCR_FACILITY, 0);
1671 /* for application controlled supplementary services */
1677 Info = _WRONG_MESSAGE_FORMAT;
1685 { /* appl is not assigned to a PLCI or error condition */
1686 dbug(1, dprintf("localInfoCon"));
1696 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1697 PLCI *plci, APPL *appl, API_PARSE *msg)
1699 dbug(1, dprintf("info_res"));
1703 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1704 PLCI *plci, APPL *appl, API_PARSE *msg)
1709 dbug(1, dprintf("alert_req"));
1711 Info = _WRONG_IDENTIFIER;
1714 Info = _ALERT_IGNORED;
1715 if (plci->State != INC_CON_ALERT) {
1716 Info = _WRONG_STATE;
1717 if (plci->State == INC_CON_PENDING) {
1719 plci->State = INC_CON_ALERT;
1720 add_ai(plci, &msg[0]);
1721 sig_req(plci, CALL_ALERT, 0);
1734 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1735 PLCI *plci, APPL *appl, API_PARSE *msg)
1742 long relatedPLCIvalue;
1743 DIVA_CAPI_ADAPTER *relatedadapter;
1745 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1746 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1748 API_PARSE ss_parms[11];
1754 dbug(1, dprintf("facility_req"));
1755 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1761 dbug(1, dprintf("wrong Ctrl"));
1762 Info = _WRONG_IDENTIFIER;
1765 selector = GET_WORD(msg[0].info);
1771 case SELECTOR_HANDSET:
1772 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1775 case SELECTOR_SU_SERV:
1778 Info = _WRONG_MESSAGE_FORMAT;
1781 SSreq = GET_WORD(&(msg[1].info[1]));
1782 PUT_WORD(&RCparms[1], SSreq);
1786 case S_GET_SUPPORTED_SERVICES:
1787 if ((i = get_plci(a)))
1789 rplci = &a->plci[i - 1];
1791 add_p(rplci, CAI, "\x01\x80");
1792 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1793 sig_req(rplci, ASSIGN, DSIG_ID);
1798 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1799 SSparms = (byte *)SSstruct;
1802 rplci->internal_command = GETSERV_REQ_PEND;
1803 rplci->number = Number;
1805 sig_req(rplci, S_SUPPORTED, 0);
1811 if (parms->length == 7)
1813 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1815 dbug(1, dprintf("format wrong"));
1816 Info = _WRONG_MESSAGE_FORMAT;
1822 Info = _WRONG_MESSAGE_FORMAT;
1825 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1826 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1828 if ((i = get_plci(a)))
1830 rplci = &a->plci[i - 1];
1832 add_p(rplci, CAI, "\x01\x80");
1833 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1834 sig_req(rplci, ASSIGN, DSIG_ID);
1841 rplci->internal_command = GET_MWI_STATE;
1842 rplci->number = Number;
1843 sig_req(rplci, MWI_POLL, 0);
1849 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1850 if (plci && plci->State && plci->SuppState == IDLE)
1852 plci->SuppState = HOLD_REQUEST;
1853 plci->command = C_HOLD_REQ;
1854 add_s(plci, CAI, &ss_parms[1]);
1855 sig_req(plci, CALL_HOLD, 0);
1859 else Info = 0x3010; /* wrong state */
1862 if (plci && plci->State && plci->SuppState == CALL_HELD)
1864 if (Id & EXT_CONTROLLER)
1866 if (AdvCodecSupport(a, plci, appl, 0))
1868 Info = 0x3010; /* wrong state */
1874 plci->SuppState = RETRIEVE_REQUEST;
1875 plci->command = C_RETRIEVE_REQ;
1876 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1878 plci->spoofed_msg = CALL_RETRIEVE;
1879 plci->internal_command = BLOCK_PLCI;
1881 dbug(1, dprintf("Spoof"));
1886 sig_req(plci, CALL_RETRIEVE, 0);
1891 else Info = 0x3010; /* wrong state */
1896 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1898 dbug(1, dprintf("format wrong"));
1899 Info = _WRONG_MESSAGE_FORMAT;
1903 if (plci && plci->State)
1905 add_s(plci, CAI, &ss_parms[2]);
1906 plci->command = SUSPEND_REQ;
1907 sig_req(plci, SUSPEND, 0);
1908 plci->State = SUSPENDING;
1911 else Info = 0x3010; /* wrong state */
1915 if (!(i = get_plci(a)))
1917 Info = _OUT_OF_PLCI;
1920 rplci = &a->plci[i - 1];
1922 rplci->number = Number;
1924 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1925 /* check 'external controller' bit for codec support */
1926 if (Id & EXT_CONTROLLER)
1928 if (AdvCodecSupport(a, rplci, appl, 0))
1937 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1939 dbug(1, dprintf("format wrong"));
1941 Info = _WRONG_MESSAGE_FORMAT;
1946 dummy.info = "\x00";
1947 add_b1(rplci, &dummy, 0, 0);
1948 if (a->Info_Mask[appl->Id - 1] & 0x200)
1950 /* early B3 connect (CIP mask bit 9) no release after a disc */
1951 add_p(rplci, LLI, "\x01\x01");
1953 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1954 sig_req(rplci, ASSIGN, DSIG_ID);
1956 add_s(rplci, CAI, &ss_parms[2]);
1957 rplci->command = RESUME_REQ;
1958 sig_req(rplci, RESUME, 0);
1959 rplci->State = RESUMING;
1963 case S_CONF_BEGIN: /* Request */
1965 case S_CONF_ISOLATE:
1966 case S_CONF_REATTACH:
1967 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1969 dbug(1, dprintf("format wrong"));
1970 Info = _WRONG_MESSAGE_FORMAT;
1973 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
1975 d = GET_DWORD(ss_parms[2].info);
1978 dbug(1, dprintf("format wrong"));
1979 Info = _WRONG_MESSAGE_FORMAT;
1982 plci->ptyState = (byte)SSreq;
1988 cai[1] = CONF_BEGIN;
1989 plci->internal_command = CONF_BEGIN_REQ_PEND;
1993 plci->internal_command = CONF_DROP_REQ_PEND;
1995 case S_CONF_ISOLATE:
1996 cai[1] = CONF_ISOLATE;
1997 plci->internal_command = CONF_ISOLATE_REQ_PEND;
1999 case S_CONF_REATTACH:
2000 cai[1] = CONF_REATTACH;
2001 plci->internal_command = CONF_REATTACH_REQ_PEND;
2004 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2005 add_p(plci, CAI, cai);
2006 sig_req(plci, S_SERVICE, 0);
2010 else Info = 0x3010; /* wrong state */
2017 if (parms->length == 7)
2019 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2021 dbug(1, dprintf("format wrong"));
2022 Info = _WRONG_MESSAGE_FORMAT;
2026 else if (parms->length == 8) /* workaround for the T-View-S */
2028 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2030 dbug(1, dprintf("format wrong"));
2031 Info = _WRONG_MESSAGE_FORMAT;
2037 Info = _WRONG_MESSAGE_FORMAT;
2042 Info = _WRONG_MESSAGE_FORMAT;
2047 Info = _WRONG_IDENTIFIER;
2050 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2051 relatedPLCIvalue &= 0x0000FFFF;
2052 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2053 /* controller starts with 0 up to (max_adapter - 1) */
2054 if (((relatedPLCIvalue & 0x7f) == 0)
2055 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2056 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2058 if (SSreq == S_3PTY_END)
2060 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2065 Info = 0x3010; /* wrong state */
2071 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2072 relatedPLCIvalue >>= 8;
2074 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2076 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2078 rplci = &relatedadapter->plci[i];
2081 if (!rplci || !relatedPLCIvalue)
2083 if (SSreq == S_3PTY_END)
2085 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2090 Info = 0x3010; /* wrong state */
2096 dbug(1, dprintf("rplci:%x", rplci));
2097 dbug(1, dprintf("plci:%x", plci));
2098 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2099 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2100 dbug(1, dprintf("SSreq:%x", SSreq));
2101 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2102 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2103 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2105 /* send PTY/ECT req, cannot check all states because of US stuff */
2106 if (!rplci->internal_command && rplci->appl)
2109 rplci->relatedPTYPLCI = plci;
2110 plci->relatedPTYPLCI = rplci;
2111 rplci->ptyState = (byte)SSreq;
2114 rplci->internal_command = ECT_REQ_PEND;
2115 cai[1] = ECT_EXECUTE;
2117 rplci->vswitchstate = 0;
2119 rplci->vsprotdialect = 0;
2120 plci->vswitchstate = 0;
2122 plci->vsprotdialect = 0;
2125 else if (SSreq == S_CONF_ADD)
2127 rplci->internal_command = CONF_ADD_REQ_PEND;
2132 rplci->internal_command = PTY_REQ_PEND;
2133 cai[1] = (byte)(SSreq - 3);
2135 rplci->number = Number;
2136 if (plci != rplci) /* explicit invocation */
2139 cai[2] = plci->Sig.Id;
2140 dbug(1, dprintf("explicit invocation"));
2144 dbug(1, dprintf("implicit invocation"));
2147 add_p(rplci, CAI, cai);
2148 sig_req(rplci, S_SERVICE, 0);
2154 dbug(0, dprintf("Wrong line"));
2155 Info = 0x3010; /* wrong state */
2160 case S_CALL_DEFLECTION:
2161 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2163 dbug(1, dprintf("format wrong"));
2164 Info = _WRONG_MESSAGE_FORMAT;
2169 Info = _WRONG_IDENTIFIER;
2172 /* reuse unused screening indicator */
2173 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2175 plci->internal_command = CD_REQ_PEND;
2176 appl->CDEnable = true;
2178 cai[1] = CALL_DEFLECTION;
2179 add_p(plci, CAI, cai);
2180 add_p(plci, CPN, ss_parms[3].info);
2181 sig_req(plci, S_SERVICE, 0);
2186 case S_CALL_FORWARDING_START:
2187 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2189 dbug(1, dprintf("format wrong"));
2190 Info = _WRONG_MESSAGE_FORMAT;
2194 if ((i = get_plci(a)))
2196 rplci = &a->plci[i - 1];
2198 add_p(rplci, CAI, "\x01\x80");
2199 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2200 sig_req(rplci, ASSIGN, DSIG_ID);
2205 Info = _OUT_OF_PLCI;
2209 /* reuse unused screening indicator */
2210 rplci->internal_command = CF_START_PEND;
2212 rplci->number = Number;
2213 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2215 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2216 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2217 add_p(rplci, CAI, cai);
2218 add_p(rplci, OAD, ss_parms[5].info);
2219 add_p(rplci, CPN, ss_parms[6].info);
2220 sig_req(rplci, S_SERVICE, 0);
2225 case S_INTERROGATE_DIVERSION:
2226 case S_INTERROGATE_NUMBERS:
2227 case S_CALL_FORWARDING_STOP:
2228 case S_CCBS_REQUEST:
2229 case S_CCBS_DEACTIVATE:
2230 case S_CCBS_INTERROGATE:
2233 case S_INTERROGATE_NUMBERS:
2234 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2236 dbug(0, dprintf("format wrong"));
2237 Info = _WRONG_MESSAGE_FORMAT;
2240 case S_CCBS_REQUEST:
2241 case S_CCBS_DEACTIVATE:
2242 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2244 dbug(0, dprintf("format wrong"));
2245 Info = _WRONG_MESSAGE_FORMAT;
2248 case S_CCBS_INTERROGATE:
2249 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2251 dbug(0, dprintf("format wrong"));
2252 Info = _WRONG_MESSAGE_FORMAT;
2256 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2258 dbug(0, dprintf("format wrong"));
2259 Info = _WRONG_MESSAGE_FORMAT;
2266 if ((i = get_plci(a)))
2268 rplci = &a->plci[i - 1];
2271 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2272 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2273 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2275 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2276 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2277 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2279 case S_CALL_FORWARDING_STOP:
2280 rplci->internal_command = CF_STOP_PEND;
2281 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2283 case S_CCBS_REQUEST:
2284 cai[1] = CCBS_REQUEST;
2285 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2287 case S_CCBS_DEACTIVATE:
2288 cai[1] = CCBS_DEACTIVATE;
2289 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2291 case S_CCBS_INTERROGATE:
2292 cai[1] = CCBS_INTERROGATE;
2293 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2300 rplci->number = Number;
2301 add_p(rplci, CAI, "\x01\x80");
2302 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2303 sig_req(rplci, ASSIGN, DSIG_ID);
2308 Info = _OUT_OF_PLCI;
2312 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2315 case S_INTERROGATE_NUMBERS:
2317 add_p(rplci, CAI, cai);
2319 case S_CCBS_REQUEST:
2320 case S_CCBS_DEACTIVATE:
2322 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2323 add_p(rplci, CAI, cai);
2325 case S_CCBS_INTERROGATE:
2327 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2328 add_p(rplci, CAI, cai);
2329 add_p(rplci, OAD, ss_parms[4].info);
2333 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334 add_p(rplci, CAI, cai);
2335 add_p(rplci, OAD, ss_parms[5].info);
2339 sig_req(rplci, S_SERVICE, 0);
2344 case S_MWI_ACTIVATE:
2345 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2347 dbug(1, dprintf("format wrong"));
2348 Info = _WRONG_MESSAGE_FORMAT;
2353 if ((i = get_plci(a)))
2355 rplci = &a->plci[i - 1];
2357 rplci->cr_enquiry = true;
2358 add_p(rplci, CAI, "\x01\x80");
2359 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2360 sig_req(rplci, ASSIGN, DSIG_ID);
2365 Info = _OUT_OF_PLCI;
2372 rplci->cr_enquiry = false;
2376 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2378 rplci->number = Number;
2381 cai[1] = ACTIVATION_MWI; /* Function */
2382 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2383 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2384 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2385 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2386 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2387 add_p(rplci, CAI, cai);
2388 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2389 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2390 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2391 add_p(rplci, UID, ss_parms[10].info); /* Time */
2392 sig_req(rplci, S_SERVICE, 0);
2396 case S_MWI_DEACTIVATE:
2397 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2399 dbug(1, dprintf("format wrong"));
2400 Info = _WRONG_MESSAGE_FORMAT;
2405 if ((i = get_plci(a)))
2407 rplci = &a->plci[i - 1];
2409 rplci->cr_enquiry = true;
2410 add_p(rplci, CAI, "\x01\x80");
2411 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2412 sig_req(rplci, ASSIGN, DSIG_ID);
2417 Info = _OUT_OF_PLCI;
2424 rplci->cr_enquiry = false;
2428 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2430 rplci->number = Number;
2433 cai[1] = DEACTIVATION_MWI; /* Function */
2434 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2435 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2436 add_p(rplci, CAI, cai);
2437 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2438 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2439 sig_req(rplci, S_SERVICE, 0);
2444 Info = 0x300E; /* not supported */
2447 break; /* case SELECTOR_SU_SERV: end */
2451 return (dtmf_request(Id, Number, a, plci, appl, msg));
2455 case SELECTOR_LINE_INTERCONNECT:
2456 return (mixer_request(Id, Number, a, plci, appl, msg));
2460 case PRIV_SELECTOR_ECHO_CANCELLER:
2461 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2462 return (ec_request(Id, Number, a, plci, appl, msg));
2464 case SELECTOR_ECHO_CANCELLER:
2465 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2466 return (ec_request(Id, Number, a, plci, appl, msg));
2469 case SELECTOR_V42BIS:
2471 Info = _FACILITY_NOT_SUPPORTED;
2473 } /* end of switch (selector) */
2476 dbug(1, dprintf("SendFacRc"));
2478 _FACILITY_R | CONFIRM,
2481 "wws", Info, selector, SSparms);
2485 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2486 PLCI *plci, APPL *appl, API_PARSE *msg)
2488 dbug(1, dprintf("facility_res"));
2492 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2493 PLCI *plci, APPL *appl, API_PARSE *parms)
2499 word fax_control_bits, fax_feature_bits, fax_info_change;
2503 API_PARSE fax_parms[9];
2507 dbug(1, dprintf("connect_b3_req"));
2510 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2511 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2513 Info = _WRONG_STATE;
2517 /* local reply if assign unsuccessful
2518 or B3 protocol allows only one layer 3 connection
2519 and already connected
2520 or B2 protocol not any LAPD
2521 and connect_b3_req contradicts originate/answer direction */
2523 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2524 && ((plci->channels != 0)
2525 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2526 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2528 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2529 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2530 Info = _WRONG_STATE;
2532 _CONNECT_B3_R | CONFIRM,
2538 plci->requested_options_conn = 0;
2542 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2544 if (ncpi->length > 2)
2547 if (ncpi->info[2] || ncpi->info[3])
2549 pvc[0] = ncpi->info[3];
2550 pvc[1] = ncpi->info[2];
2551 add_d(plci, 2, pvc);
2556 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2557 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2561 else if (plci->B3_prot == 5)
2563 if (plci->NL.Id && !plci->nl_remove_id)
2565 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2566 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2567 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2568 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2570 len = offsetof(T30_INFO, universal_6);
2571 fax_info_change = false;
2572 if (ncpi->length >= 4)
2574 w = GET_WORD(&ncpi->info[3]);
2575 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2577 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2578 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2579 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2580 fax_info_change = true;
2582 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2583 if (w & 0x0002) /* Fax-polling request */
2584 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2585 if ((w & 0x0004) /* Request to send / poll another document */
2586 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2588 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2590 if (ncpi->length >= 6)
2592 w = GET_WORD(&ncpi->info[5]);
2593 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2595 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2596 fax_info_change = true;
2599 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2600 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2602 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2604 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2605 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2607 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2609 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2610 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2611 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2612 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2614 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2615 Info = _WRONG_MESSAGE_FORMAT;
2618 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2619 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2621 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2622 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2623 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2625 w = fax_parms[4].length;
2628 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2629 for (i = 0; i < w; i++)
2630 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2631 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2632 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2633 w = fax_parms[5].length;
2636 plci->fax_connect_info_buffer[len++] = (byte) w;
2637 for (i = 0; i < w; i++)
2638 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2639 w = fax_parms[6].length;
2642 plci->fax_connect_info_buffer[len++] = (byte) w;
2643 for (i = 0; i < w; i++)
2644 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2645 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2646 & (1L << PRIVATE_FAX_NONSTANDARD))
2648 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2650 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2651 plci->fax_connect_info_buffer[len++] = 0;
2655 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2656 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2657 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2658 for (i = 0; i < fax_parms[7].length; i++)
2659 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2666 len = offsetof(T30_INFO, universal_6);
2668 fax_info_change = true;
2671 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2673 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2674 fax_info_change = true;
2679 plci->fax_connect_info_length = len;
2680 if (fax_info_change)
2682 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2684 start_internal_command(Id, plci, fax_connect_info_command);
2689 start_internal_command(Id, plci, fax_adjust_b23_command);
2695 else Info = _WRONG_STATE;
2697 else Info = _WRONG_STATE;
2700 else if (plci->B3_prot == B3_RTP)
2702 plci->internal_req_buffer[0] = ncpi->length + 1;
2703 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2704 for (w = 0; w < ncpi->length; w++)
2705 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2706 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2712 nl_req_ncci(plci, req, 0);
2717 else Info = _WRONG_IDENTIFIER;
2720 _CONNECT_B3_R | CONFIRM,
2727 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2728 PLCI *plci, APPL *appl, API_PARSE *parms)
2737 API_PARSE fax_parms[9];
2742 dbug(1, dprintf("connect_b3_res"));
2744 ncci = (word)(Id >> 16);
2746 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2747 if (GET_WORD(&parms[0].info[0]) != 0)
2749 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2750 channel_request_xon(plci, a->ncci_ch[ncci]);
2751 channel_xmit_xon(plci);
2752 cleanup_ncci_data(plci, ncci);
2753 nl_req_ncci(plci, N_DISC, (byte)ncci);
2756 a->ncci_state[ncci] = INC_ACT_PENDING;
2758 req = N_CONNECT_ACK;
2760 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2763 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2764 & (1L << PRIVATE_FAX_NONSTANDARD))
2766 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2767 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2768 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2770 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2771 if (plci->fax_connect_info_length < len)
2773 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2774 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2776 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2778 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2782 if (plci->fax_connect_info_length <= len)
2783 plci->fax_connect_info_buffer[len] = 0;
2784 len += 1 + plci->fax_connect_info_buffer[len];
2785 if (plci->fax_connect_info_length <= len)
2786 plci->fax_connect_info_buffer[len] = 0;
2787 len += 1 + plci->fax_connect_info_buffer[len];
2788 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2789 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2790 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2791 for (i = 0; i < fax_parms[7].length; i++)
2792 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2794 plci->fax_connect_info_length = len;
2795 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2796 start_internal_command(Id, plci, fax_connect_ack_command);
2801 nl_req_ncci(plci, req, (byte)ncci);
2802 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2803 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2805 if (plci->B3_prot == 4)
2806 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2808 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2809 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2813 else if (plci->B3_prot == B3_RTP)
2815 plci->internal_req_buffer[0] = ncpi->length + 1;
2816 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2817 for (w = 0; w < ncpi->length; w++)
2818 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2819 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2825 if (ncpi->length > 2) {
2826 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2827 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2829 nl_req_ncci(plci, req, (byte)ncci);
2830 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2831 if (plci->adjust_b_restore)
2833 plci->adjust_b_restore = false;
2834 start_internal_command(Id, plci, adjust_b_restore);
2843 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2844 PLCI *plci, APPL *appl, API_PARSE *parms)
2848 ncci = (word)(Id >> 16);
2849 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2851 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2852 && (plci->State != OUTG_DIS_PENDING))
2854 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2855 a->ncci_state[ncci] = CONNECTED;
2856 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2857 channel_request_xon(plci, a->ncci_ch[ncci]);
2858 channel_xmit_xon(plci);
2864 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2865 PLCI *plci, APPL *appl, API_PARSE *parms)
2871 dbug(1, dprintf("disconnect_b3_req"));
2873 Info = _WRONG_IDENTIFIER;
2874 ncci = (word)(Id >> 16);
2877 Info = _WRONG_STATE;
2878 if ((a->ncci_state[ncci] == CONNECTED)
2879 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2880 || (a->ncci_state[ncci] == INC_CON_PENDING)
2881 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2883 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2884 channel_request_xon(plci, a->ncci_ch[ncci]);
2885 channel_xmit_xon(plci);
2887 if (a->ncci[ncci].data_pending
2888 && ((plci->B3_prot == B3_TRANSPARENT)
2889 || (plci->B3_prot == B3_T30)
2890 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
2892 plci->send_disc = (byte)ncci;
2898 cleanup_ncci_data(plci, ncci);
2900 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2903 if (ncpi->length > 3)
2905 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
2908 nl_req_ncci(plci, N_DISC, (byte)ncci);
2914 _DISCONNECT_B3_R | CONFIRM,
2921 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2922 PLCI *plci, APPL *appl, API_PARSE *parms)
2927 ncci = (word)(Id >> 16);
2928 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
2930 plci->requested_options_conn = 0;
2931 plci->fax_connect_info_length = 0;
2932 plci->ncpi_state = 0x00;
2933 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2934 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
2936 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
2938 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
2939 if (i < MAX_CHANNELS_PER_PLCI) {
2940 if (plci->channels)plci->channels--;
2941 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
2942 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
2944 ncci_free_receive_buffers(plci, ncci);
2946 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
2947 if (plci->State == SUSPENDING) {
2952 "ws", (word)3, "\x03\x04\x00\x00");
2953 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
2961 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
2962 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
2963 && (a->ncci_state[ncci] == INC_DIS_PENDING))
2965 ncci_free_receive_buffers(plci, ncci);
2967 nl_req_ncci(plci, N_EDATA, (byte)ncci);
2969 plci->adapter->ncci_state[ncci] = IDLE;
2970 start_internal_command(Id, plci, fax_disconnect_command);
2978 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2979 PLCI *plci, APPL *appl, API_PARSE *parms)
2987 dbug(1, dprintf("data_b3_req"));
2989 Info = _WRONG_IDENTIFIER;
2990 ncci = (word)(Id >> 16);
2991 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
2995 Info = _WRONG_STATE;
2996 if ((a->ncci_state[ncci] == CONNECTED)
2997 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3000 ncci_ptr = &(a->ncci[ncci]);
3001 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3002 if (i >= MAX_DATA_B3)
3004 data = &(ncci_ptr->DBuffer[i]);
3005 data->Number = Number;
3006 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3007 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3010 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3014 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3015 data->Length = GET_WORD(parms[1].info);
3016 data->Handle = GET_WORD(parms[2].info);
3017 data->Flags = GET_WORD(parms[3].info);
3018 (ncci_ptr->data_pending)++;
3020 /* check for delivery confirmation */
3021 if (data->Flags & 0x0004)
3023 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3024 if (i >= MAX_DATA_ACK)
3026 ncci_ptr->DataAck[i].Number = data->Number;
3027 ncci_ptr->DataAck[i].Handle = data->Handle;
3028 (ncci_ptr->data_ack_pending)++;
3039 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3040 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3043 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3048 _DATA_B3_R | CONFIRM,
3051 "ww", GET_WORD(parms[2].info), Info);
3056 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3057 PLCI *plci, APPL *appl, API_PARSE *parms)
3063 dbug(1, dprintf("data_b3_res"));
3065 ncci = (word)(Id >> 16);
3067 n = GET_WORD(parms[0].info);
3068 dbug(1, dprintf("free(%d)", n));
3069 NCCIcode = ncci | (((word) a->Id) << 8);
3070 if (n < appl->MaxBuffer &&
3071 appl->DataNCCI[n] == NCCIcode &&
3072 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3073 dbug(1, dprintf("found"));
3074 appl->DataNCCI[n] = 0;
3076 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3077 channel_request_xon(plci, a->ncci_ch[ncci]);
3079 channel_xmit_xon(plci);
3081 if (appl->DataFlags[n] & 4) {
3082 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3090 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3091 PLCI *plci, APPL *appl, API_PARSE *parms)
3096 dbug(1, dprintf("reset_b3_req"));
3098 Info = _WRONG_IDENTIFIER;
3099 ncci = (word)(Id >> 16);
3102 Info = _WRONG_STATE;
3103 switch (plci->B3_prot)
3107 if (a->ncci_state[ncci] == CONNECTED)
3109 nl_req_ncci(plci, N_RESET, (byte)ncci);
3114 case B3_TRANSPARENT:
3115 if (a->ncci_state[ncci] == CONNECTED)
3117 start_internal_command(Id, plci, reset_b3_command);
3123 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3125 _RESET_B3_R | CONFIRM,
3132 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3133 PLCI *plci, APPL *appl, API_PARSE *parms)
3137 dbug(1, dprintf("reset_b3_res"));
3139 ncci = (word)(Id >> 16);
3141 switch (plci->B3_prot)
3145 if (a->ncci_state[ncci] == INC_RES_PENDING)
3147 a->ncci_state[ncci] = CONNECTED;
3148 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3157 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3158 PLCI *plci, APPL *appl, API_PARSE *parms)
3164 dbug(1, dprintf("connect_b3_t90_a_res"));
3166 ncci = (word)(Id >> 16);
3168 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3169 a->ncci_state[ncci] = CONNECTED;
3171 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3172 a->ncci_state[ncci] = CONNECTED;
3174 req = N_CONNECT_ACK;
3176 /* parms[0]==0 for CAPI original message definition! */
3177 if (parms[0].info) {
3179 if (ncpi->length > 2) {
3180 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3181 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3184 nl_req_ncci(plci, req, (byte)ncci);
3192 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3193 PLCI *plci, APPL *appl, API_PARSE *msg)
3198 API_PARSE bp_parms[7];
3202 Info = _WRONG_IDENTIFIER;
3206 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3207 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3208 dbug(1, dprintf("PlciState=0x%x", plci->State));
3209 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3211 /* check if no channel is open, no B3 connected only */
3212 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3213 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3215 Info = _WRONG_STATE;
3217 /* check message format and fill bp_parms pointer */
3218 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3220 Info = _WRONG_MESSAGE_FORMAT;
3224 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3225 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3226 if (Id & EXT_CONTROLLER)
3228 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3231 plci->State = INC_CON_CONNECTED_ALERT;
3233 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
3234 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
3235 /* disconnect the other appls its quasi a connect */
3236 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
3237 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3240 api_save_msg(msg, "s", &plci->saved_msg);
3242 if (Id & EXT_CONTROLLER)
3244 if (tel) /* external controller in use by this PLCI */
3246 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3248 dbug(1, dprintf("Ext_Ctrl in use 1"));
3249 Info = _WRONG_STATE;
3252 else /* external controller NOT in use by this PLCI ? */
3254 if (a->AdvSignalPLCI)
3256 dbug(1, dprintf("Ext_Ctrl in use 2"));
3257 Info = _WRONG_STATE;
3259 else /* activate the codec */
3261 dbug(1, dprintf("Ext_Ctrl start"));
3262 if (AdvCodecSupport(a, plci, appl, 0))
3264 dbug(1, dprintf("Error in codec procedures"));
3265 Info = _WRONG_STATE;
3267 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3269 plci->spoofed_msg = AWAITING_SELECT_B;
3270 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3272 dbug(1, dprintf("continue if codec loaded"));
3278 else /* external controller bit is OFF */
3280 if (tel) /* external controller in use, need to switch off */
3282 if (a->AdvSignalAppl == appl)
3284 CodecIdCheck(a, plci);
3287 dbug(1, dprintf("Ext_Ctrl disable"));
3291 dbug(1, dprintf("Ext_Ctrl not requested"));
3297 if (plci->call_dir & CALL_DIR_OUT)
3298 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3299 else if (plci->call_dir & CALL_DIR_IN)
3300 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3301 start_internal_command(Id, plci, select_b_command);
3306 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3310 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3311 PLCI *plci, APPL *appl, API_PARSE *parms)
3317 API_PARSE m_parms[5];
3322 static byte chi[2] = {0x01, 0x00};
3323 static byte lli[2] = {0x01, 0x00};
3324 static byte codec_cai[2] = {0x01, 0x01};
3325 static byte null_msg = {0};
3326 static API_PARSE null_parms = { 0, &null_msg };
3330 dbug(1, dprintf("manufacturer_req"));
3331 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3333 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3334 Info = _WRONG_MESSAGE_FORMAT;
3336 command = GET_WORD(parms[1].info);
3341 case _DI_ASSIGN_PLCI:
3342 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3343 Info = _WRONG_MESSAGE_FORMAT;
3346 codec = GET_WORD(m_parms[0].info);
3347 ch = m_parms[1].info[0];
3348 dir = m_parms[2].info[0];
3349 if ((i = get_plci(a))) {
3350 plci = &a->plci[i - 1];
3352 plci->command = _MANUFACTURER_R;
3353 plci->m_command = command;
3354 plci->number = Number;
3355 plci->State = LOCAL_CONNECT;
3356 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3357 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3359 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3360 chi[1] = (byte)(0x80 | ch);
3362 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3366 Info = add_b1(plci, &m_parms[3], 0, 0);
3369 add_p(plci, CAI, codec_cai);
3371 /* manual 'swich on' to the codec support without signalling */
3372 /* first 'assign plci' with this function, then use */
3374 if (AdvCodecSupport(a, plci, appl, 0)) {
3375 Info = _RESOURCE_ERROR;
3378 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3379 lli[1] = 0x10; /* local call codec stream */
3384 plci->State = LOCAL_CONNECT;
3385 plci->manufacturer = true;
3386 plci->command = _MANUFACTURER_R;
3387 plci->m_command = command;
3388 plci->number = Number;
3392 add_p(plci, LLI, lli);
3393 add_p(plci, CHI, chi);
3394 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3395 sig_req(plci, ASSIGN, DSIG_ID);
3399 Info = add_b23(plci, &m_parms[3]);
3402 nl_req_ncci(plci, ASSIGN, 0);
3408 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3409 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3411 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3412 plci->spoofed_msg = AWAITING_MANUF_CON;
3413 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3419 sig_req(plci, CALL_REQ, 0);
3422 sig_req(plci, LISTEN_REQ, 0);
3429 _MANUFACTURER_R | CONFIRM,
3432 "dww", _DI_MANU_ID, command, Info);
3438 else Info = _OUT_OF_PLCI;
3444 Info = _WRONG_IDENTIFIER;
3447 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3448 Info = _WRONG_MESSAGE_FORMAT;
3451 req = m_parms[0].info[0];
3452 plci->command = _MANUFACTURER_R;
3453 plci->m_command = command;
3454 plci->number = Number;
3455 if (req == CALL_REQ)
3457 plci->b_channel = getChannel(&m_parms[1]);
3458 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3459 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3461 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3462 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3467 else if (req == LAW_REQ)
3469 plci->cr_enquiry = true;
3471 add_ss(plci, FTY, &m_parms[1]);
3472 sig_req(plci, req, 0);
3476 if (plci->NL.Id && !plci->nl_remove_id)
3480 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3482 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3484 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3485 cleanup_ncci_data(plci, ncci);
3486 nl_req_ncci(plci, N_DISC, (byte)ncci);
3491 nl_req_ncci(plci, REMOVE, 0);
3498 /* signalling control for loop activation B-channel */
3501 Info = _WRONG_IDENTIFIER;
3505 plci->command = _MANUFACTURER_R;
3506 plci->number = Number;
3507 add_ss(plci, FTY, m);
3508 sig_req(plci, SIG_CTRL, 0);
3511 else Info = _WRONG_MESSAGE_FORMAT;
3515 /* activation control for receiver/transmitter B-channel */
3518 Info = _WRONG_IDENTIFIER;
3522 plci->command = _MANUFACTURER_R;
3523 plci->number = Number;
3524 add_ss(plci, FTY, m);
3525 sig_req(plci, DSP_CTRL, 0);
3528 else Info = _WRONG_MESSAGE_FORMAT;
3533 /* TEL_CTRL commands to support non standard adjustments: */
3534 /* Ring on/off, Handset micro volume, external micro vol. */
3535 /* handset+external speaker volume, receiver+transm. gain,*/
3536 /* handsfree on (hookinfo off), set mixer command */
3538 if (command == _DI_ADV_CODEC)
3540 if (!a->AdvCodecPLCI) {
3541 Info = _WRONG_STATE;
3544 v_plci = a->AdvCodecPLCI;
3550 && (m->info[1] == 0x1c)
3551 && (m->info[2] >= 1))
3553 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3555 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3557 Info = _WRONG_STATE;
3560 a->adv_voice_coef_length = m->info[2] - 1;
3561 if (a->adv_voice_coef_length > m->length - 3)
3562 a->adv_voice_coef_length = (byte)(m->length - 3);
3563 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3564 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3565 for (i = 0; i < a->adv_voice_coef_length; i++)
3566 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3567 if (plci->B1_facilities & B1_FACILITY_VOICE)
3568 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3571 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3573 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3575 Info = _FACILITY_NOT_SUPPORTED;
3579 plci->dtmf_parameter_length = m->info[2] - 1;
3580 if (plci->dtmf_parameter_length > m->length - 3)
3581 plci->dtmf_parameter_length = (byte)(m->length - 3);
3582 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3583 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3584 for (i = 0; i < plci->dtmf_parameter_length; i++)
3585 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3586 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3587 dtmf_parameter_write(plci);
3597 Info = _WRONG_IDENTIFIER;
3601 add_ss(v_plci, FTY, m);
3602 sig_req(v_plci, TEL_CTRL, 0);
3605 else Info = _WRONG_MESSAGE_FORMAT;
3609 case _DI_OPTIONS_REQUEST:
3610 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3611 Info = _WRONG_MESSAGE_FORMAT;
3614 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3616 Info = _FACILITY_NOT_SUPPORTED;
3619 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3625 Info = _WRONG_MESSAGE_FORMAT;
3631 _MANUFACTURER_R | CONFIRM,
3634 "dww", _DI_MANU_ID, command, Info);
3639 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3640 PLCI *plci, APPL *appl, API_PARSE *msg)
3644 API_PARSE m_parms[3];
3646 API_PARSE fax_parms[9];
3651 dbug(1, dprintf("manufacturer_res"));
3653 if ((msg[0].length == 0)
3654 || (msg[1].length == 0)
3655 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3659 indication = GET_WORD(msg[1].info);
3663 case _DI_NEGOTIATE_B3:
3666 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3667 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3669 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3672 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3674 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3678 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3679 if (plci->fax_connect_info_length < len)
3681 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3682 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3684 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3686 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3690 if (plci->fax_connect_info_length <= len)
3691 plci->fax_connect_info_buffer[len] = 0;
3692 len += 1 + plci->fax_connect_info_buffer[len];
3693 if (plci->fax_connect_info_length <= len)
3694 plci->fax_connect_info_buffer[len] = 0;
3695 len += 1 + plci->fax_connect_info_buffer[len];
3696 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3697 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3698 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3699 for (i = 0; i < fax_parms[7].length; i++)
3700 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3702 plci->fax_connect_info_length = len;
3703 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3704 start_internal_command(Id, plci, fax_edata_ack_command);
3711 /*------------------------------------------------------------------*/
3712 /* IDI callback function */
3713 /*------------------------------------------------------------------*/
3715 void callback(ENTITY *e)
3717 DIVA_CAPI_ADAPTER *a;
3728 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3729 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3731 a = &(adapter[(byte)e->user[0]]);
3732 plci = &(a->plci[e->user[1]]);
3733 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3736 If new protocol code and new XDI is used then CAPI should work
3737 fully in accordance with IDI cpec an look on callback field instead
3738 of Rc field for return codes.
3740 if (((e->complete == 0xff) && no_cancel_rc) ||
3741 (e->Rc && !no_cancel_rc)) {
3747 if (e->user[0] & 0x8000)
3750 If REMOVE request was sent then we have to wait until
3751 return code with Id set to zero arrives.
3752 All other return codes should be ignored.
3758 dbug(1, dprintf("cancel RC in REMOVE state"));
3761 channel_flow_control_remove(plci);
3762 for (i = 0; i < 256; i++)
3764 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3765 a->FlowControlIdTable[i] = 0;
3767 plci->nl_remove_id = 0;
3768 if (plci->rx_dma_descriptor > 0) {
3769 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3770 plci->rx_dma_descriptor = 0;
3775 a->FlowControlIdTable[ch] = e->Id;
3776 a->FlowControlSkipTable[ch] = 0;
3778 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3779 a->ch_flow_plci[ch] = plci->Id;
3785 Cancel return codes self, if feature was requested
3787 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3788 a->FlowControlIdTable[ch] = 0;
3789 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3790 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3795 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3797 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3805 control_rc(plci, 0, rc, ch, 0, true);
3810 channel_x_on(plci, ch);
3811 if (plci->internal_command)
3812 control_rc(plci, req, rc, ch, 0, true);
3816 if (plci->nl_global_req)
3818 global_req = plci->nl_global_req;
3819 plci->nl_global_req = 0;
3820 if (rc != ASSIGN_OK) {
3822 if (plci->rx_dma_descriptor > 0) {
3823 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3824 plci->rx_dma_descriptor = 0;
3827 channel_xmit_xon(plci);
3828 control_rc(plci, 0, rc, ch, global_req, true);
3830 else if (plci->data_sent)
3832 channel_xmit_xon(plci);
3833 plci->data_sent = false;
3836 if (plci->internal_command)
3837 control_rc(plci, req, rc, ch, 0, true);
3841 channel_xmit_xon(plci);
3842 control_rc(plci, req, rc, ch, 0, true);
3850 If REMOVE request was sent then we have to wait until
3851 return code with Id set to zero arrives.
3852 All other return codes should be ignored.
3858 dbug(1, dprintf("cancel RC in REMOVE state"));
3861 plci->sig_remove_id = 0;
3864 if (plci->sig_global_req)
3866 global_req = plci->sig_global_req;
3867 plci->sig_global_req = 0;
3868 if (rc != ASSIGN_OK)
3870 channel_xmit_xon(plci);
3871 control_rc(plci, 0, rc, ch, global_req, false);
3875 channel_xmit_xon(plci);
3876 control_rc(plci, req, rc, ch, 0, false);
3880 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3881 same callback. Also if new XDI and protocol code used then jump
3885 channel_xmit_xon(plci);
3886 goto capi_callback_suffix;
3890 channel_xmit_xon(plci);
3893 if (e->user[0] & 0x8000) {
3894 byte Ind = e->Ind & 0x0f;
3896 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
3897 (a->ch_flow_plci[Ch] == plci->Id)) {
3898 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
3899 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
3901 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3904 if ((e->RNR != 1) &&
3905 (a->ch_flow_plci[Ch] == plci->Id) &&
3906 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
3907 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3908 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
3916 capi_callback_suffix:
3918 while (!plci->req_in
3919 && !plci->internal_command
3920 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
3922 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
3924 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
3926 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
3927 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
3928 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
3929 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
3930 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3932 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3933 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
3937 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
3939 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
3941 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
3942 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3944 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3946 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3947 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3949 i = api_put(appl, m);
3952 if (m->header.command == _DATA_B3_R)
3954 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
3956 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
3960 if (plci->li_notify_update)
3962 plci->li_notify_update = false;
3963 mixer_notify_update(plci, false);
3972 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
3981 DIVA_CAPI_ADAPTER *a;
3984 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
3985 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
3988 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
3991 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
3992 if (plci->req_in != plci->req_out)
3994 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
3996 dbug(1, dprintf("req_1return"));
3999 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4001 plci->req_in = plci->req_in_start = plci->req_out = 0;
4002 dbug(1, dprintf("control_rc"));
4006 ncci = a->ch_ncci[ch];
4009 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4010 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4011 Number = plci->number;
4012 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));
4013 dbug(1, dprintf("channels=0x%x", plci->channels));
4014 if (plci_remove_check(plci))
4016 if (req == REMOVE && rc == ASSIGN_OK)
4018 sig_req(plci, HANGUP, 0);
4019 sig_req(plci, REMOVE, 0);
4024 switch (plci->command)
4027 dbug(1, dprintf("HoldRC=0x%x", rc));
4028 SSparms[1] = (byte)S_HOLD;
4031 plci->SuppState = IDLE;
4034 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4037 case C_RETRIEVE_REQ:
4038 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4039 SSparms[1] = (byte)S_RETRIEVE;
4042 plci->SuppState = CALL_HELD;
4045 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4049 dbug(1, dprintf("InfoRC=0x%x", rc));
4050 if (rc != OK) Info = _WRONG_STATE;
4051 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4055 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4056 if (plci->State == INC_DIS_PENDING)
4058 if (plci->Sig.Id != 0xff)
4060 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4061 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4063 dbug(1, dprintf("No more IDs/Call_Req failed"));
4064 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4069 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4070 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4072 else /* D-ch activation */
4074 if (rc != ASSIGN_OK)
4076 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4077 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4082 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4083 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4084 plci->State = INC_ACT_PENDING;
4088 case _CONNECT_I | RESPONSE:
4089 if (plci->State != INC_DIS_PENDING)
4090 plci->State = INC_CON_ACCEPT;
4094 if (plci->State == INC_DIS_PENDING)
4096 if (plci->Sig.Id != 0xff)
4098 plci->State = OUTG_DIS_PENDING;
4099 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4112 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4115 ncci = get_ncci(plci, ch, 0);
4116 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4120 a->ncci_state[ncci] = INC_ACT_PENDING;
4121 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4122 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4126 a->ncci_state[ncci] = OUTG_CON_PENDING;
4127 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4131 case _CONNECT_B3_I | RESPONSE:
4135 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4138 case _DISCONNECT_B3_R:
4139 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4142 case _MANUFACTURER_R:
4148 Info = _WRONG_IDENTIFIER;
4149 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4153 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4161 else if (plci->internal_command)
4163 switch (plci->internal_command)
4169 if (rc == OK) /* command supported, wait for indication */
4176 /* Get Supported Services */
4177 case GETSERV_REQ_PEND:
4178 if (rc == OK) /* command supported, wait for indication */
4182 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4183 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4187 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4188 case INTERR_NUMBERS_REQ_PEND:
4189 case CF_START_PEND: /* Call Forwarding Start pending */
4190 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4191 case CCBS_REQUEST_REQ_PEND:
4192 case CCBS_DEACTIVATE_REQ_PEND:
4193 case CCBS_INTERROGATE_REQ_PEND:
4194 switch (plci->internal_command)
4196 case INTERR_DIVERSION_REQ_PEND:
4197 SSparms[1] = S_INTERROGATE_DIVERSION;
4199 case INTERR_NUMBERS_REQ_PEND:
4200 SSparms[1] = S_INTERROGATE_NUMBERS;
4203 SSparms[1] = S_CALL_FORWARDING_START;
4206 SSparms[1] = S_CALL_FORWARDING_STOP;
4208 case CCBS_REQUEST_REQ_PEND:
4209 SSparms[1] = S_CCBS_REQUEST;
4211 case CCBS_DEACTIVATE_REQ_PEND:
4212 SSparms[1] = S_CCBS_DEACTIVATE;
4214 case CCBS_INTERROGATE_REQ_PEND:
4215 SSparms[1] = S_CCBS_INTERROGATE;
4218 if (global_req == ASSIGN)
4220 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4223 if (!plci->appl) break;
4224 if (rc == ISDN_GUARD_REJ)
4226 Info = _CAPI_GUARD_ERROR;
4230 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4232 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4233 plci->number, "wws", Info, (word)3, SSparms);
4234 if (Info) plci_remove(plci);
4237 /* 3pty conference pending */
4239 if (!plci->relatedPTYPLCI) break;
4240 rplci = plci->relatedPTYPLCI;
4241 SSparms[1] = plci->ptyState;
4242 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4243 if (rplci->tel) rId |= EXT_CONTROLLER;
4246 Info = 0x300E; /* not supported */
4247 plci->relatedPTYPLCI = NULL;
4251 _FACILITY_R | CONFIRM,
4254 "wws", Info, (word)3, SSparms);
4257 /* Explicit Call Transfer pending */
4259 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4260 if (!plci->relatedPTYPLCI) break;
4261 rplci = plci->relatedPTYPLCI;
4263 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4264 if (rplci->tel) rId |= EXT_CONTROLLER;
4267 Info = 0x300E; /* not supported */
4268 plci->relatedPTYPLCI = NULL;
4272 _FACILITY_R | CONFIRM,
4275 "wws", Info, (word)3, SSparms);
4278 case _MANUFACTURER_R:
4279 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4280 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4282 dbug(1, dprintf("No more IDs"));
4283 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4284 plci_remove(plci); /* after codec init, internal codec commands pending */
4289 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4290 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4292 dbug(1, dprintf("No more IDs"));
4293 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4294 plci_remove(plci); /* after codec init, internal codec commands pending */
4298 case PERM_COD_HOOK: /* finished with Hook_Ind */
4302 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4303 plci->internal_command = PERM_COD_CONN_PEND;
4306 case PERM_COD_ASSIGN:
4307 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4308 if (rc != ASSIGN_OK) break;
4309 sig_req(plci, CALL_REQ, 0);
4311 plci->internal_command = PERM_COD_CALL;
4314 /* Null Call Reference Request pending */
4316 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4317 if (global_req == ASSIGN)
4319 if (rc == ASSIGN_OK)
4325 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4326 appl->NullCREnable = false;
4330 else if (req == NCR_FACILITY)
4334 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4338 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4339 appl->NullCREnable = false;
4348 if (a->ncci_state[ncci] == CONNECTED)
4350 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4351 cleanup_ncci_data(plci, ncci);
4352 nl_req_ncci(plci, N_DISC, (byte)ncci);
4359 if (plci->State == INC_DIS_PENDING)
4361 sig_req(plci, CALL_REQ, 0);
4363 plci->State = OUTG_CON_PENDING;
4367 case MWI_ACTIVATE_REQ_PEND:
4368 case MWI_DEACTIVATE_REQ_PEND:
4369 if (global_req == ASSIGN && rc == ASSIGN_OK)
4371 dbug(1, dprintf("MWI_REQ assigned"));
4378 Info = 0x2007; /* Illegal message parameter coding */
4379 dbug(1, dprintf("MWI_REQ invalid parameter"));
4383 Info = 0x300B; /* not supported */
4384 dbug(1, dprintf("MWI_REQ not supported"));
4386 /* 0x3010: Request not allowed in this state */
4387 PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4390 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4392 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4394 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4396 if (plci->cr_enquiry)
4399 _FACILITY_R | CONFIRM,
4402 "wws", Info, (word)3, SSparms);
4403 if (rc != OK) plci_remove(plci);
4408 _FACILITY_R | CONFIRM,
4411 "wws", Info, (word)3, SSparms);
4415 case CONF_BEGIN_REQ_PEND:
4416 case CONF_ADD_REQ_PEND:
4417 case CONF_SPLIT_REQ_PEND:
4418 case CONF_DROP_REQ_PEND:
4419 case CONF_ISOLATE_REQ_PEND:
4420 case CONF_REATTACH_REQ_PEND:
4421 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4422 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4425 switch (plci->internal_command)
4427 case CONF_BEGIN_REQ_PEND:
4428 SSparms[1] = S_CONF_BEGIN;
4430 case CONF_ADD_REQ_PEND:
4431 SSparms[1] = S_CONF_ADD;
4432 rplci = plci->relatedPTYPLCI;
4433 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4435 case CONF_SPLIT_REQ_PEND:
4436 SSparms[1] = S_CONF_SPLIT;
4438 case CONF_DROP_REQ_PEND:
4439 SSparms[1] = S_CONF_DROP;
4441 case CONF_ISOLATE_REQ_PEND:
4442 SSparms[1] = S_CONF_ISOLATE;
4444 case CONF_REATTACH_REQ_PEND:
4445 SSparms[1] = S_CONF_REATTACH;
4451 Info = 0x300E; /* not supported */
4452 plci->relatedPTYPLCI = NULL;
4456 _FACILITY_R | CONFIRM,
4459 "wws", Info, (word)3, SSparms);
4462 case VSWITCH_REQ_PEND:
4465 if (plci->relatedPTYPLCI)
4467 plci->relatedPTYPLCI->vswitchstate = 0;
4468 plci->relatedPTYPLCI->vsprot = 0;
4469 plci->relatedPTYPLCI->vsprotdialect = 0;
4471 plci->vswitchstate = 0;
4473 plci->vsprotdialect = 0;
4477 if (plci->relatedPTYPLCI &&
4478 plci->vswitchstate == 1 &&
4479 plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4480 plci->vswitchstate = 3;
4484 /* Call Deflection Request pending (SSCT) */
4486 SSparms[1] = S_CALL_DEFLECTION;
4489 Info = 0x300E; /* not supported */
4490 plci->appl->CDEnable = 0;
4492 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4493 plci->number, "wws", Info, (word)3, SSparms);
4496 case RTP_CONNECT_B3_REQ_COMMAND_2:
4499 ncci = get_ncci(plci, ch, 0);
4500 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4502 a->ncci_state[ncci] = OUTG_CON_PENDING;
4506 if (plci->internal_command_queue[0])
4508 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4509 if (plci->internal_command)
4514 next_internal_command(Id, plci);
4519 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4520 if (plci->tel) Id |= EXT_CONTROLLER;
4522 switch (plci->internal_command)
4527 case START_L1_SIG_ASSIGN_PEND:
4528 case REM_L1_SIG_ASSIGN_PEND:
4529 if (global_req == ASSIGN)
4535 dbug(1, dprintf("***L1 Req rem PLCI"));
4536 plci->internal_command = 0;
4537 sig_req(plci, REMOVE, 0);
4542 /* Call Deflection Request pending, just no appl ptr assigned */
4544 SSparms[1] = S_CALL_DEFLECTION;
4547 Info = 0x300E; /* not supported */
4549 for (i = 0; i < max_appl; i++)
4551 if (application[i].CDEnable)
4553 if (!application[i].Id) application[i].CDEnable = 0;
4556 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4557 plci->number, "wws", Info, (word)3, SSparms);
4558 if (Info) application[i].CDEnable = 0;
4562 plci->internal_command = 0;
4565 case PERM_COD_HOOK: /* finished with Hook_Ind */
4569 plci->internal_command = PERM_COD_CONN_PEND;
4570 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4573 case PERM_COD_ASSIGN:
4574 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4575 plci->internal_command = 0;
4576 if (rc != ASSIGN_OK) break;
4577 plci->internal_command = PERM_COD_CALL;
4578 sig_req(plci, CALL_REQ, 0);
4582 case LISTEN_SIG_ASSIGN_PEND:
4583 if (rc == ASSIGN_OK)
4585 plci->internal_command = 0;
4586 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4587 add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4588 sig_req(plci, INDICATE_REQ, 0);
4593 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4601 if (global_req == ASSIGN)
4603 if (rc == ASSIGN_OK)
4605 sig_req(plci, LAW_REQ, 0);
4607 dbug(1, dprintf("Auto-Law assigned"));
4611 dbug(1, dprintf("Auto-Law assign failed"));
4612 a->automatic_law = 3;
4613 plci->internal_command = 0;
4614 a->automatic_lawPLCI = NULL;
4618 else if (req == LAW_REQ && rc == OK)
4620 dbug(1, dprintf("Auto-Law initiated"));
4621 a->automatic_law = 2;
4622 plci->internal_command = 0;
4626 dbug(1, dprintf("Auto-Law not supported"));
4627 a->automatic_law = 3;
4628 plci->internal_command = 0;
4629 sig_req(plci, REMOVE, 0);
4631 a->automatic_lawPLCI = NULL;
4635 plci_remove_check(plci);
4639 static void data_rc(PLCI *plci, byte ch)
4642 DIVA_CAPI_ADAPTER *a;
4649 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4651 ncci = a->ch_ncci[ch];
4652 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4654 ncci_ptr = &(a->ncci[ncci]);
4655 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4656 if (ncci_ptr->data_pending)
4658 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4659 if (!(data->Flags & 4) && a->ncci_state[ncci])
4661 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4662 if (plci->tel) Id |= EXT_CONTROLLER;
4663 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4664 "ww", data->Handle, 0);
4666 (ncci_ptr->data_out)++;
4667 if (ncci_ptr->data_out == MAX_DATA_B3)
4668 ncci_ptr->data_out = 0;
4669 (ncci_ptr->data_pending)--;
4675 static void data_ack(PLCI *plci, byte ch)
4678 DIVA_CAPI_ADAPTER *a;
4683 ncci = a->ch_ncci[ch];
4684 ncci_ptr = &(a->ncci[ncci]);
4685 if (ncci_ptr->data_ack_pending)
4687 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4689 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4690 if (plci->tel) Id |= EXT_CONTROLLER;
4691 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4692 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4694 (ncci_ptr->data_ack_out)++;
4695 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4696 ncci_ptr->data_ack_out = 0;
4697 (ncci_ptr->data_ack_pending)--;
4701 static void sig_ind(PLCI *plci)
4710 DIVA_CAPI_ADAPTER *a;
4711 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4712 #define MAXPARMSIDS 31
4713 byte *parms[MAXPARMSIDS];
4715 byte *multi_fac_parms[MAX_MULTI_IE];
4716 byte *multi_pi_parms[MAX_MULTI_IE];
4717 byte *multi_ssext_parms[MAX_MULTI_IE];
4718 byte *multi_CiPN_parms[MAX_MULTI_IE];
4720 byte *multi_vswitch_parms[MAX_MULTI_IE];
4727 byte *esc_profile = "";
4731 byte chi[] = "\x02\x18\x01";
4732 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4733 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4734 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4735 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4736 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4737 /* (see Info_Mask Bit 4, first IE. then the message type) */
4738 static const word parms_id[] =
4739 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4740 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4741 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4742 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4743 /* 14 FTY repl by ESC_CHI */
4744 /* 18 PI repl by ESC_LAW */
4745 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4746 static const word multi_fac_id[] = {1, FTY};
4747 static const word multi_pi_id[] = {1, PI};
4748 static const word multi_CiPN_id[] = {1, OAD};
4749 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4751 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4755 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4756 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4757 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4758 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4759 byte force_mt_info = false;
4765 Id = ((word)plci->Id << 8) | a->Id;
4766 PUT_WORD(&SS_Ind[4], 0x0000);
4768 if (plci->sig_remove_id)
4770 plci->Sig.RNR = 2; /* discard */
4771 dbug(1, dprintf("SIG discard while remove pending"));
4774 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4775 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4776 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4777 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4782 if (plci->Sig.Ind == HANGUP && plci->channels)
4785 plci->hangup_flow_ctrl_timer++;
4786 /* recover the network layer after timeout */
4787 if (plci->hangup_flow_ctrl_timer == 100)
4789 dbug(1, dprintf("Exceptional disc"));
4791 plci->hangup_flow_ctrl_timer = 0;
4792 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4794 if (a->ncci_plci[ncci] == plci->Id)
4796 cleanup_ncci_data(plci, ncci);
4797 if (plci->channels)plci->channels--;
4799 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4803 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4810 /* do first parse the info with no OAD in, because OAD will be converted */
4811 /* first the multiple facility IE, then mult. progress ind. */
4812 /* then the parameters for the info_ind + conn_ind */
4813 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4814 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4815 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4817 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4819 IndParse(plci, parms_id, parms, 0);
4820 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4821 esc_chi = parms[14];
4822 esc_law = parms[18];
4823 pty_cai = parms[24];
4825 esc_profile = parms[27];
4826 if (esc_cr[0] && plci)
4828 if (plci->cr_enquiry && plci->appl)
4830 plci->cr_enquiry = false;
4833 /* b = total length */
4834 /* b = indication type */
4835 /* b = length of all IEs */
4837 /* S = IE1 length + cont. */
4839 /* S = IE2 length + cont. */
4844 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4845 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);
4848 /* create the additional info structure */
4849 add_i[1] = parms[15]; /* KEY of additional info */
4850 add_i[2] = parms[11]; /* UUI of additional info */
4851 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4853 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4854 /* indication returns by the card if requested by the function */
4855 /* AutomaticLaw() after driver init */
4856 if (a->automatic_law < 4)
4860 dbug(0, dprintf("u-Law selected"));
4864 dbug(0, dprintf("a-Law selected"));
4867 a->automatic_law = 4;
4868 if (plci == a->automatic_lawPLCI) {
4869 plci->internal_command = 0;
4870 sig_req(plci, REMOVE, 0);
4872 a->automatic_lawPLCI = NULL;
4877 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4878 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4879 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4880 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4882 a->profile.Global_Options &= 0x000000ffL;
4883 a->profile.B1_Protocols &= 0x000003ffL;
4884 a->profile.B2_Protocols &= 0x00001fdfL;
4885 a->profile.B3_Protocols &= 0x000000b7L;
4887 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4888 GL_BCHANNEL_OPERATION_SUPPORTED;
4889 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4890 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4891 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4892 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4893 a->man_profile.private_options = 0;
4895 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4897 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4898 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4902 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4903 a->man_profile.private_options |= 1L << PRIVATE_RTP;
4904 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4905 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4908 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4909 a->man_profile.private_options |= 1L << PRIVATE_T38;
4912 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4913 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4916 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4917 a->man_profile.private_options |= 1L << PRIVATE_V18;
4920 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4921 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4924 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4925 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4928 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4929 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4932 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4933 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4936 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4937 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4942 a->profile.Global_Options &= 0x0000007fL;
4943 a->profile.B1_Protocols &= 0x000003dfL;
4944 a->profile.B2_Protocols &= 0x00001adfL;
4945 a->profile.B3_Protocols &= 0x000000b7L;
4946 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4948 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4949 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4951 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4953 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4954 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4955 UnMapController(a->Id), a->profile.Global_Options,
4956 a->profile.B1_Protocols, a->profile.B2_Protocols,
4957 a->profile.B3_Protocols, a->manufacturer_features));
4959 /* codec plci for the handset/hook state support is just an internal id */
4960 if (plci != a->AdvCodecPLCI)
4962 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4963 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4964 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4965 SendInfo(plci, Id, parms, force_mt_info);
4967 VSwitchReqInd(plci, Id, multi_vswitch_parms);
4971 /* switch the codec to the b-channel */
4972 if (esc_chi[0] && plci && !plci->SuppState) {
4973 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4974 mixer_set_bchannel_id_esc(plci, plci->b_channel);
4975 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4976 if (plci->tel == ADV_VOICE && plci->appl) {
4977 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4981 if (plci->appl) plci->appl->Number++;
4983 switch (plci->Sig.Ind) {
4984 /* Response to Get_Supported_Services request */
4986 dbug(1, dprintf("S_Supported"));
4987 if (!plci->appl) break;
4988 if (pty_cai[0] == 4)
4990 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4994 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4996 PUT_WORD(&CF_Ind[1], 0);
4997 PUT_WORD(&CF_Ind[4], 0);
4998 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5002 /* Supplementary Service rejected */
5004 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5005 if (!pty_cai[0]) break;
5010 case THREE_PTY_BEGIN:
5011 if (!plci->relatedPTYPLCI) break;
5012 tplci = plci->relatedPTYPLCI;
5013 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5014 if (tplci->tel) rId |= EXT_CONTROLLER;
5015 if (pty_cai[5] == ECT_EXECUTE)
5017 PUT_WORD(&SS_Ind[1], S_ECT);
5019 plci->vswitchstate = 0;
5020 plci->relatedPTYPLCI->vswitchstate = 0;
5025 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5027 if (pty_cai[2] != 0xff)
5029 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5033 PUT_WORD(&SS_Ind[4], 0x300E);
5035 plci->relatedPTYPLCI = NULL;
5037 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5040 case CALL_DEFLECTION:
5041 if (pty_cai[2] != 0xff)
5043 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5047 PUT_WORD(&SS_Ind[4], 0x300E);
5049 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5050 for (i = 0; i < max_appl; i++)
5052 if (application[i].CDEnable)
5054 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5055 application[i].CDEnable = false;
5060 case DEACTIVATION_DIVERSION:
5061 case ACTIVATION_DIVERSION:
5062 case DIVERSION_INTERROGATE_CFU:
5063 case DIVERSION_INTERROGATE_CFB:
5064 case DIVERSION_INTERROGATE_CFNR:
5065 case DIVERSION_INTERROGATE_NUM:
5067 case CCBS_DEACTIVATE:
5068 case CCBS_INTERROGATE:
5069 if (!plci->appl) break;
5070 if (pty_cai[2] != 0xff)
5072 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5076 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5080 case DEACTIVATION_DIVERSION:
5081 dbug(1, dprintf("Deact_Div"));
5082 Interr_Err_Ind[0] = 0x9;
5083 Interr_Err_Ind[3] = 0x6;
5084 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5086 case ACTIVATION_DIVERSION:
5087 dbug(1, dprintf("Act_Div"));
5088 Interr_Err_Ind[0] = 0x9;
5089 Interr_Err_Ind[3] = 0x6;
5090 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5092 case DIVERSION_INTERROGATE_CFU:
5093 case DIVERSION_INTERROGATE_CFB:
5094 case DIVERSION_INTERROGATE_CFNR:
5095 dbug(1, dprintf("Interr_Div"));
5096 Interr_Err_Ind[0] = 0xa;
5097 Interr_Err_Ind[3] = 0x7;
5098 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5100 case DIVERSION_INTERROGATE_NUM:
5101 dbug(1, dprintf("Interr_Num"));
5102 Interr_Err_Ind[0] = 0xa;
5103 Interr_Err_Ind[3] = 0x7;
5104 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5107 dbug(1, dprintf("CCBS Request"));
5108 Interr_Err_Ind[0] = 0xd;
5109 Interr_Err_Ind[3] = 0xa;
5110 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5112 case CCBS_DEACTIVATE:
5113 dbug(1, dprintf("CCBS Deactivate"));
5114 Interr_Err_Ind[0] = 0x9;
5115 Interr_Err_Ind[3] = 0x6;
5116 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5118 case CCBS_INTERROGATE:
5119 dbug(1, dprintf("CCBS Interrogate"));
5120 Interr_Err_Ind[0] = 0xb;
5121 Interr_Err_Ind[3] = 0x8;
5122 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5125 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5126 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5129 case ACTIVATION_MWI:
5130 case DEACTIVATION_MWI:
5131 if (pty_cai[5] == ACTIVATION_MWI)
5133 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5135 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5137 if (pty_cai[2] != 0xff)
5139 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5143 PUT_WORD(&SS_Ind[4], 0x300E);
5146 if (plci->cr_enquiry)
5148 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5153 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5156 case CONF_ADD: /* ERROR */
5166 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5172 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5173 plci->ptyState = CONNECTED;
5178 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5179 plci->ptyState = CONNECTED;
5184 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5185 plci->ptyState = CONNECTED;
5188 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5189 plci->relatedPTYPLCI = NULL;
5190 tplci = plci->relatedPTYPLCI;
5191 if (tplci) tplci->ptyState = CONNECTED;
5192 plci->ptyState = CONNECTED;
5196 if (pty_cai[2] != 0xff)
5198 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5202 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5203 within the required time */
5206 PUT_DWORD(&CONF_Ind[6], 0x0);
5207 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5212 /* Supplementary Service indicates success */
5214 dbug(1, dprintf("Service_Ind"));
5215 PUT_WORD(&CF_Ind[4], 0);
5219 case THREE_PTY_BEGIN:
5221 if (!plci->relatedPTYPLCI) break;
5222 tplci = plci->relatedPTYPLCI;
5223 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5224 if (tplci->tel) rId |= EXT_CONTROLLER;
5225 if (pty_cai[5] == ECT_EXECUTE)
5227 PUT_WORD(&SS_Ind[1], S_ECT);
5229 if (plci->vswitchstate != 3)
5232 plci->ptyState = IDLE;
5233 plci->relatedPTYPLCI = NULL;
5238 dbug(1, dprintf("ECT OK"));
5239 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5246 switch (plci->ptyState)
5249 plci->ptyState = CONNECTED;
5250 dbug(1, dprintf("3PTY ON"));
5254 plci->ptyState = IDLE;
5255 plci->relatedPTYPLCI = NULL;
5257 dbug(1, dprintf("3PTY OFF"));
5260 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5261 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5265 case CALL_DEFLECTION:
5266 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5267 for (i = 0; i < max_appl; i++)
5269 if (application[i].CDEnable)
5271 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5272 application[i].CDEnable = false;
5277 case DEACTIVATION_DIVERSION:
5278 case ACTIVATION_DIVERSION:
5279 if (!plci->appl) break;
5280 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5281 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5282 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5286 case DIVERSION_INTERROGATE_CFU:
5287 case DIVERSION_INTERROGATE_CFB:
5288 case DIVERSION_INTERROGATE_CFNR:
5289 case DIVERSION_INTERROGATE_NUM:
5291 case CCBS_DEACTIVATE:
5292 case CCBS_INTERROGATE:
5293 if (!plci->appl) break;
5296 case DIVERSION_INTERROGATE_CFU:
5297 case DIVERSION_INTERROGATE_CFB:
5298 case DIVERSION_INTERROGATE_CFNR:
5299 dbug(1, dprintf("Interr_Div"));
5300 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5301 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5303 case DIVERSION_INTERROGATE_NUM:
5304 dbug(1, dprintf("Interr_Num"));
5305 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5306 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5309 dbug(1, dprintf("CCBS Request"));
5310 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5311 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5313 case CCBS_DEACTIVATE:
5314 dbug(1, dprintf("CCBS Deactivate"));
5315 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5316 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5318 case CCBS_INTERROGATE:
5319 dbug(1, dprintf("CCBS Interrogate"));
5320 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5321 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5324 PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5325 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5326 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5330 case ACTIVATION_MWI:
5331 case DEACTIVATION_MWI:
5332 if (pty_cai[5] == ACTIVATION_MWI)
5334 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5336 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5337 if (plci->cr_enquiry)
5339 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5344 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5347 case MWI_INDICATION:
5348 if (pty_cai[0] >= 0x12)
5350 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5351 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5352 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5353 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5355 if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5357 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5361 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5366 for (i = 0; i < max_appl; i++)
5368 if (a->Notification_Mask[i]&SMASK_MWI)
5370 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5378 facility[2] = 0; /* returncode */
5380 else facility[2] = 0xff;
5385 facility[2] = 0xff; /* returncode */
5388 facility[1] = MWI_RESPONSE; /* Function */
5389 add_p(plci, CAI, facility);
5390 add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5391 sig_req(plci, S_SERVICE, 0);
5394 next_internal_command(Id, plci);
5396 case CONF_ADD: /* OK */
5401 case CONF_PARTYDISC:
5407 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5408 if (pty_cai[0] == 6)
5411 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5415 PUT_DWORD(&CONF_Ind[6], 0x0);
5419 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5424 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5429 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5434 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5436 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5437 tplci = plci->relatedPTYPLCI;
5438 if (tplci) tplci->ptyState = CONNECTED;
5440 case CONF_PARTYDISC:
5443 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5445 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5448 plci->ptyState = CONNECTED;
5449 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5451 case CCBS_INFO_RETAIN:
5452 case CCBS_ERASECALLLINKAGEID:
5453 case CCBS_STOP_ALERTING:
5458 case CCBS_INFO_RETAIN:
5459 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5461 case CCBS_STOP_ALERTING:
5462 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5464 case CCBS_ERASECALLLINKAGEID:
5465 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5473 PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5475 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5477 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5481 for (i = 0; i < max_appl; i++)
5482 if (a->Notification_Mask[i] & SMASK_CCBS)
5483 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5492 i = _L3_CAUSE | cau[2];
5493 if (cau[2] == 0) i = 0x3603;
5499 PUT_WORD(&SS_Ind[1], S_HOLD);
5500 PUT_WORD(&SS_Ind[4], i);
5501 if (plci->SuppState == HOLD_REQUEST)
5503 plci->SuppState = IDLE;
5504 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5509 if (plci->SuppState == HOLD_REQUEST)
5511 plci->SuppState = CALL_HELD;
5512 CodecIdCheck(a, plci);
5513 start_internal_command(Id, plci, hold_save_command);
5517 case CALL_RETRIEVE_REJ:
5521 i = _L3_CAUSE | cau[2];
5522 if (cau[2] == 0) i = 0x3603;
5528 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5529 PUT_WORD(&SS_Ind[4], i);
5530 if (plci->SuppState == RETRIEVE_REQUEST)
5532 plci->SuppState = CALL_HELD;
5533 CodecIdCheck(a, plci);
5534 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5538 case CALL_RETRIEVE_ACK:
5539 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5540 if (plci->SuppState == RETRIEVE_REQUEST)
5542 plci->SuppState = IDLE;
5543 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5544 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5547 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5548 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5549 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5550 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5552 dbug(1, dprintf("Get B-ch"));
5553 start_internal_command(Id, plci, retrieve_restore_command);
5556 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5559 start_internal_command(Id, plci, retrieve_restore_command);
5564 if (plci->State != LISTENING) {
5565 sig_req(plci, HANGUP, 0);
5569 cip = find_cip(a, parms[4], parms[6]);
5570 cip_mask = 1L << cip;
5571 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5572 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5573 if (!remove_started && !a->adapter_disabled)
5575 group_optimization(a, plci);
5576 for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5577 if (application[i].Id
5578 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5579 && CPN_filter_ok(parms[0], a, i)) {
5580 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5581 __set_bit(i, plci->c_ind_mask_table);
5582 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5583 plci->State = INC_CON_PENDING;
5584 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5585 CALL_DIR_IN | CALL_DIR_ANSWER;
5587 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5588 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5590 /* if a listen on the ext controller is done, check if hook states */
5591 /* are supported or if just a on board codec must be activated */
5592 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5593 if (a->profile.Global_Options & HANDSET)
5594 plci->tel = ADV_VOICE;
5595 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5597 if (plci->tel) Id |= EXT_CONTROLLER;
5598 a->codec_listen[i] = plci;
5601 sendf(&application[i], _CONNECT_I, Id, 0,
5602 "wSSSSSSSbSSSSS", cip, /* CIP */
5603 parms[0], /* CalledPartyNumber */
5604 multi_CiPN_parms[0], /* CallingPartyNumber */
5605 parms[2], /* CalledPartySubad */
5606 parms[3], /* CallingPartySubad */
5607 parms[4], /* BearerCapability */
5608 parms[5], /* LowLC */
5609 parms[6], /* HighLC */
5610 ai_len, /* nested struct add_i */
5611 add_i[0], /* B channel info */
5612 add_i[1], /* keypad facility */
5613 add_i[2], /* user user data */
5614 add_i[3], /* nested facility */
5615 multi_CiPN_parms[1] /* second CiPN(SCR) */
5617 SendSSExtInd(&application[i],
5621 SendSetupInfo(&application[i],
5625 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5628 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5630 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5631 sig_req(plci, HANGUP, 0);
5635 plci->notifiedcall = 0;
5640 case CALL_PEND_NOTIFY:
5641 plci->notifiedcall = 1;
5647 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5649 if (plci->internal_command == PERM_COD_CONN_PEND)
5651 if (plci->State == ADVANCED_VOICE_NOSIG)
5653 dbug(1, dprintf("***Codec OK"));
5654 if (a->AdvSignalPLCI)
5656 tplci = a->AdvSignalPLCI;
5657 if (tplci->spoofed_msg)
5659 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5661 tplci->internal_command = 0;
5662 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5663 switch (tplci->spoofed_msg)
5666 tplci->command = _CONNECT_I | RESPONSE;
5667 api_load_msg(&tplci->saved_msg, saved_parms);
5668 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5669 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5671 /* early B3 connect (CIP mask bit 9) no release after a disc */
5672 add_p(tplci, LLI, "\x01\x01");
5674 add_s(tplci, CONN_NR, &saved_parms[2]);
5675 add_s(tplci, LLC, &saved_parms[4]);
5676 add_ai(tplci, &saved_parms[5]);
5677 tplci->State = INC_CON_ACCEPT;
5678 sig_req(tplci, CALL_RES, 0);
5682 case AWAITING_SELECT_B:
5683 dbug(1, dprintf("Select_B continue"));
5684 start_internal_command(x_Id, tplci, select_b_command);
5687 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5690 dbug(1, dprintf("No SigID!"));
5691 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5695 tplci->command = _MANUFACTURER_R;
5696 api_load_msg(&tplci->saved_msg, saved_parms);
5697 dir = saved_parms[2].info[0];
5699 sig_req(tplci, CALL_REQ, 0);
5702 sig_req(tplci, LISTEN_REQ, 0);
5705 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5708 case (CALL_REQ | AWAITING_MANUF_CON):
5709 sig_req(tplci, CALL_REQ, 0);
5716 dbug(1, dprintf("No SigID!"));
5717 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5721 tplci->command = _CONNECT_R;
5722 api_load_msg(&tplci->saved_msg, saved_parms);
5723 add_s(tplci, CPN, &saved_parms[1]);
5724 add_s(tplci, DSA, &saved_parms[3]);
5725 add_ai(tplci, &saved_parms[9]);
5726 sig_req(tplci, CALL_REQ, 0);
5731 tplci->command = C_RETRIEVE_REQ;
5732 sig_req(tplci, CALL_RETRIEVE, 0);
5736 tplci->spoofed_msg = 0;
5737 if (tplci->internal_command == 0)
5738 next_internal_command(x_Id, tplci);
5741 next_internal_command(Id, plci);
5744 dbug(1, dprintf("***Codec Hook Init Req"));
5745 plci->internal_command = PERM_COD_HOOK;
5746 add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5747 sig_req(plci, TEL_CTRL, 0);
5751 else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5752 && plci->State != INC_ACT_PENDING)
5754 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5755 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5757 chi[2] = plci->b_channel;
5758 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5760 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5761 plci->State = INC_ACT_PENDING;
5766 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5767 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5768 switch (ie[1] & 0x91) {
5769 case 0x80: /* hook off */
5771 if (plci->internal_command == PERM_COD_HOOK)
5773 dbug(1, dprintf("init:hook_off"));
5774 plci->hook_state = ie[1];
5775 next_internal_command(Id, plci);
5778 else /* ignore doubled hook indications */
5780 if (((plci->hook_state) & 0xf0) == 0x80)
5782 dbug(1, dprintf("ignore hook"));
5785 plci->hook_state = ie[1]&0x91;
5787 /* check for incoming call pending */
5788 /* and signal '+'.Appl must decide */
5789 /* with connect_res if call must */
5790 /* accepted or not */
5791 for (i = 0, tplci = NULL; i < max_appl; i++) {
5792 if (a->codec_listen[i]
5793 && (a->codec_listen[i]->State == INC_CON_PENDING
5794 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5795 tplci = a->codec_listen[i];
5796 tplci->appl = &application[i];
5799 /* no incoming call, do outgoing call */
5800 /* and signal '+' if outg. setup */
5801 if (!a->AdvSignalPLCI && !tplci) {
5802 if ((i = get_plci(a))) {
5803 a->AdvSignalPLCI = &a->plci[i - 1];
5804 tplci = a->AdvSignalPLCI;
5805 tplci->tel = ADV_VOICE;
5806 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5807 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5808 /* early B3 connect (CIP mask bit 9) no release after a disc */
5809 add_p(tplci, LLI, "\x01\x01");
5811 add_p(tplci, CAI, voice_cai);
5812 add_p(tplci, OAD, a->TelOAD);
5813 add_p(tplci, OSA, a->TelOSA);
5814 add_p(tplci, SHIFT | 6, NULL);
5815 add_p(tplci, SIN, "\x02\x01\x00");
5816 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5817 sig_req(tplci, ASSIGN, DSIG_ID);
5818 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5819 a->AdvSignalPLCI->command = 0;
5820 tplci->appl = a->AdvSignalAppl;
5821 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5828 Id = ((word)tplci->Id << 8) | a->Id;
5829 Id |= EXT_CONTROLLER;
5834 "ws", (word)0, "\x01+");
5837 case 0x90: /* hook on */
5839 if (plci->internal_command == PERM_COD_HOOK)
5841 dbug(1, dprintf("init:hook_on"));
5842 plci->hook_state = ie[1] & 0x91;
5843 next_internal_command(Id, plci);
5846 else /* ignore doubled hook indications */
5848 if (((plci->hook_state) & 0xf0) == 0x90) break;
5849 plci->hook_state = ie[1] & 0x91;
5851 /* hangup the adv. voice call and signal '-' to the appl */
5852 if (a->AdvSignalPLCI) {
5853 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5854 if (plci->tel) Id |= EXT_CONTROLLER;
5855 sendf(a->AdvSignalAppl,
5859 "ws", (word)0, "\x01-");
5860 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5861 a->AdvSignalPLCI->command = 0;
5862 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5863 send_req(a->AdvSignalPLCI);
5871 __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5872 PUT_WORD(&resume_cau[4], GOOD);
5873 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5877 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5879 if (plci->NL.Id && !plci->nl_remove_id) {
5881 nl_req_ncci(plci, REMOVE, 0);
5883 if (!plci->sig_remove_id) {
5884 plci->internal_command = 0;
5885 sig_req(plci, REMOVE, 0);
5888 if (!plci->channels) {
5889 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5890 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5898 plci->hangup_flow_ctrl_timer = 0;
5899 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5902 i = _L3_CAUSE | cau[2];
5903 if (cau[2] == 0) i = 0;
5904 else if (cau[2] == 8) i = _L1_ERROR;
5905 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5906 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5912 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5914 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5915 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5919 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5923 if (plci->State == LISTENING)
5925 plci->notifiedcall = 0;
5928 plci->State = INC_DIS_PENDING;
5929 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5932 if (plci->NL.Id && !plci->nl_remove_id)
5935 nl_req_ncci(plci, REMOVE, 0);
5937 if (!plci->sig_remove_id)
5939 plci->internal_command = 0;
5940 sig_req(plci, REMOVE, 0);
5947 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
5948 /* result in a second HANGUP! Don't generate another */
5950 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5952 if (plci->State == RESUMING)
5954 PUT_WORD(&resume_cau[4], i);
5955 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5957 plci->State = INC_DIS_PENDING;
5958 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5964 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5968 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5971 if (plci->relatedPTYPLCI &&
5972 plci->vswitchstate == 3 &&
5973 plci->relatedPTYPLCI->vswitchstate == 3 &&
5974 parms[MAXPARMSIDS - 1][0])
5976 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5977 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5978 send_req(plci->relatedPTYPLCI);
5980 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5987 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5995 dbug(1, dprintf("SetupInfo"));
5997 for (i = 0; i < MAXPARMSIDS; i++) {
6004 dbug(1, dprintf("CPN "));
6005 Info_Number = 0x0070;
6007 Info_Sent_Flag = true;
6009 case 8: /* display */
6010 dbug(1, dprintf("display(%d)", i));
6011 Info_Number = 0x0028;
6013 Info_Sent_Flag = true;
6015 case 16: /* Channel Id */
6016 dbug(1, dprintf("CHI"));
6017 Info_Number = 0x0018;
6019 Info_Sent_Flag = true;
6020 mixer_set_bchannel_id(plci, Info_Element);
6022 case 19: /* Redirected Number */
6023 dbug(1, dprintf("RDN"));
6024 Info_Number = 0x0074;
6026 Info_Sent_Flag = true;
6028 case 20: /* Redirected Number extended */
6029 dbug(1, dprintf("RDX"));
6030 Info_Number = 0x0073;
6032 Info_Sent_Flag = true;
6034 case 22: /* Redirecing Number */
6035 dbug(1, dprintf("RIN"));
6036 Info_Number = 0x0076;
6038 Info_Sent_Flag = true;
6046 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6047 Info_Number = 0x8000 | 5;
6052 if (Info_Sent_Flag && Info_Number) {
6053 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6054 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6061 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6070 static byte charges[5] = {4, 0, 0, 0, 0};
6071 static byte cause[] = {0x02, 0x80, 0x00};
6074 dbug(1, dprintf("InfoParse "));
6079 && plci->Sig.Ind != NCR_FACILITY
6082 dbug(1, dprintf("NoParse "));
6086 for (i = 0; i < MAXPARMSIDS; i++) {
6093 dbug(1, dprintf("CPN "));
6094 Info_Number = 0x0070;
6097 case 7: /* ESC_CAU */
6098 dbug(1, dprintf("cau(0x%x)", ie[2]));
6099 Info_Number = 0x0008;
6102 Info_Element = NULL;
6104 case 8: /* display */
6105 dbug(1, dprintf("display(%d)", i));
6106 Info_Number = 0x0028;
6109 case 9: /* Date display */
6110 dbug(1, dprintf("date(%d)", i));
6111 Info_Number = 0x0029;
6114 case 10: /* charges */
6115 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6116 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6117 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6118 Info_Number = 0x4000;
6120 Info_Element = charges;
6122 case 11: /* user user info */
6123 dbug(1, dprintf("uui"));
6124 Info_Number = 0x007E;
6127 case 12: /* congestion receiver ready */
6128 dbug(1, dprintf("clRDY"));
6129 Info_Number = 0x00B0;
6133 case 13: /* congestion receiver not ready */
6134 dbug(1, dprintf("clNRDY"));
6135 Info_Number = 0x00BF;
6139 case 15: /* Keypad Facility */
6140 dbug(1, dprintf("KEY"));
6141 Info_Number = 0x002C;
6144 case 16: /* Channel Id */
6145 dbug(1, dprintf("CHI"));
6146 Info_Number = 0x0018;
6148 mixer_set_bchannel_id(plci, Info_Element);
6150 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6151 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6152 if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6153 Info_Number = 0x0008;
6155 if (cause[2] != ie[2]) Info_Element = cause;
6157 case 19: /* Redirected Number */
6158 dbug(1, dprintf("RDN"));
6159 Info_Number = 0x0074;
6162 case 22: /* Redirecing Number */
6163 dbug(1, dprintf("RIN"));
6164 Info_Number = 0x0076;
6167 case 23: /* Notification Indicator */
6168 dbug(1, dprintf("NI"));
6169 Info_Number = (word)NI;
6172 case 26: /* Call State */
6173 dbug(1, dprintf("CST"));
6174 Info_Number = (word)CST;
6175 Info_Mask = 0x01; /* do with cause i.e. for now */
6177 case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6178 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6179 Info_Number = 0x8000 | ie[3];
6180 if (iesent) Info_Mask = 0xffff;
6181 else Info_Mask = 0x10;
6192 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6194 for (j = 0; j < max_appl; j++)
6196 appl = &application[j];
6199 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6201 dbug(1, dprintf("NCR_Ind"));
6203 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6207 else if (!plci->appl)
6208 { /* overlap receiving broadcast */
6209 if (Info_Number == CPN
6210 || Info_Number == KEY
6211 || Info_Number == NI
6212 || Info_Number == DSP
6213 || Info_Number == UUI)
6215 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6216 dbug(1, dprintf("Ovl_Ind"));
6218 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6221 } /* all other signalling states */
6222 else if (Info_Number
6223 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6225 dbug(1, dprintf("Std_Ind"));
6227 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6233 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6234 dword info_mask, byte setupParse)
6248 && plci->Sig.Ind != NCR_FACILITY
6252 dbug(1, dprintf("NoM-IEParse "));
6255 dbug(1, dprintf("M-IEParse "));
6257 for (i = 0; i < MAX_MULTI_IE; i++)
6264 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6265 Info_Number = (word)ie_type;
6266 Info_Mask = (word)info_mask;
6269 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6271 for (j = 0; j < max_appl; j++)
6273 appl = &application[j];
6276 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6279 dbug(1, dprintf("Mlt_NCR_Ind"));
6280 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6284 else if (!plci->appl && Info_Number)
6285 { /* overlap receiving broadcast */
6286 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6288 dbug(1, dprintf("Mlt_Ovl_Ind"));
6289 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6291 } /* all other signalling states */
6292 else if (Info_Number
6293 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6296 dbug(1, dprintf("Mlt_Std_Ind"));
6297 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6303 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6306 /* Format of multi_ssext_parms[i][]:
6309 2 byte SSEXT_REQ/SSEXT_IND
6317 && plci->Sig.Ind != NCR_FACILITY
6319 for (i = 0; i < MAX_MULTI_IE; i++)
6321 if (parms[i][0] < 6) continue;
6322 if (parms[i][2] == SSEXT_REQ) continue;
6326 parms[i][0] = 0; /* kill it */
6327 sendf(appl, _MANUFACTURER_I,
6335 else if (plci->appl)
6337 parms[i][0] = 0; /* kill it */
6338 sendf(plci->appl, _MANUFACTURER_I,
6349 static void nl_ind(PLCI *plci)
6354 DIVA_CAPI_ADAPTER *a;
6360 byte len, ncci_state;
6363 word fax_feature_bits;
6364 byte fax_send_edata_ack;
6365 static byte v120_header_buffer[2 + 3];
6366 static word fax_info[] = {
6367 0, /* T30_SUCCESS */
6368 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6369 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6370 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6371 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6372 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6373 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6374 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6375 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6376 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6377 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6378 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6379 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6380 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6381 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6382 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6383 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6384 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6385 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6386 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6387 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6388 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6389 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6390 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6391 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6392 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6393 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6394 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6395 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6396 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6397 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6398 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6399 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6400 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6401 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6402 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6403 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6404 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6405 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6406 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6407 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6408 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6409 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6410 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6411 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6412 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6413 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6416 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6419 static word rtp_info[] = {
6420 GOOD, /* RTP_SUCCESS */
6421 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6424 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6426 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6427 0x00000000, 0x00000000, 0x00000000, 0x00000000
6430 ch = plci->NL.IndCh;
6432 ncci = a->ch_ncci[ch];
6433 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6434 if (plci->tel) Id |= EXT_CONTROLLER;
6435 APPLptr = plci->appl;
6436 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",
6437 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6439 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6441 if (plci->nl_remove_id)
6443 plci->NL.RNR = 2; /* discard */
6444 dbug(1, dprintf("NL discard while remove pending"));
6447 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6449 if (plci->State == INC_DIS_PENDING
6450 || plci->State == OUTG_DIS_PENDING
6451 || plci->State == IDLE)
6453 plci->NL.RNR = 2; /* discard */
6454 dbug(1, dprintf("discard n_connect"));
6457 if (plci->State < INC_ACT_PENDING)
6459 plci->NL.RNR = 1; /* flow control */
6460 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6465 if (!APPLptr) /* no application or invalid data */
6466 { /* while reloading the DSP */
6467 dbug(1, dprintf("discard1"));
6472 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6473 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6474 || (plci->B2_prot == 7)
6475 || (plci->B3_prot == 7)))
6477 plci->ncpi_buffer[0] = 0;
6479 ncpi_state = plci->ncpi_state;
6480 if (plci->NL.complete == 1)
6482 byte *data = &plci->NL.RBuffer->P[0];
6484 if ((plci->NL.RBuffer->length >= 12)
6485 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6486 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6488 word conn_opt, ncpi_opt = 0x00;
6489 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6491 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6492 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6493 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6494 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6496 data++; /* indication code */
6497 data += 2; /* timestamp */
6498 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6499 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6500 data++; /* connected norm */
6501 conn_opt = GET_WORD(data);
6502 data += 2; /* connected options */
6504 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6506 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6508 ncpi_opt |= MDM_NCPI_ECM_V42;
6510 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6512 ncpi_opt |= MDM_NCPI_ECM_MNP;
6516 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6518 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6520 ncpi_opt |= MDM_NCPI_COMPRESSED;
6522 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6523 plci->ncpi_buffer[0] = 4;
6525 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6528 if (plci->B3_prot == 7)
6530 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6531 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6532 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6534 a->ncci_state[ncci] = INC_ACT_PENDING;
6535 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6536 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6540 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6541 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6542 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6543 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6551 if (plci->NL.complete == 2)
6553 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6554 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6556 switch (plci->RData[0].P[0])
6559 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6560 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6561 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6563 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6564 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6565 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6567 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6568 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6570 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6571 dtmf_confirmation(Id, plci);
6575 case UDATA_INDICATION_MIXER_TAP_DATA:
6576 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6577 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6580 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6581 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6586 case UDATA_INDICATION_MIXER_COEFS_SET:
6587 mixer_indication_coefs_set(Id, plci);
6589 case UDATA_INDICATION_XCONNECT_FROM:
6590 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6592 case UDATA_INDICATION_XCONNECT_TO:
6593 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6597 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6598 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6609 if ((plci->RData[0].PLength != 0)
6610 && ((plci->B2_prot == B2_V120_ASYNC)
6611 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6612 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6615 sendf(plci->appl, _DATA_B3_I, Id, 0,
6618 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6626 sendf(plci->appl, _DATA_B3_I, Id, 0,
6629 plci->RData[0].PLength,
6638 fax_feature_bits = 0;
6639 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6640 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6641 (plci->NL.Ind & 0x0f) == N_DISC ||
6642 (plci->NL.Ind & 0x0f) == N_EDATA ||
6643 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6646 plci->ncpi_buffer[0] = 0;
6647 switch (plci->B3_prot) {
6650 break; /* no network control protocol info - jfr */
6653 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6654 plci->ncpi_buffer[0] = (byte)(i + 3);
6655 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6656 plci->ncpi_buffer[2] = 0;
6657 plci->ncpi_buffer[3] = 0;
6659 case 4: /*T.30 - FAX*/
6660 case 5: /*T.30 - FAX*/
6661 if (plci->NL.RLength >= sizeof(T30_INFO))
6663 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6665 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6666 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6667 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6668 if (plci->B3_prot == 5)
6670 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6671 i |= 0x8000; /* This is not an ECM connection */
6672 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6673 i |= 0x4000; /* This is a connection with MMR compression */
6674 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6675 i |= 0x2000; /* This is a connection with MR compression */
6676 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6677 i |= 0x0004; /* More documents */
6678 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6679 i |= 0x0002; /* Fax-polling indication */
6681 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6682 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6683 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6684 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6685 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6686 plci->ncpi_buffer[len] = 0;
6687 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6689 plci->ncpi_buffer[len] = 20;
6690 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6691 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6693 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6695 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6696 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6698 info = _FAX_PROTOCOL_ERROR;
6701 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6702 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6704 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6705 while (i < plci->NL.RBuffer->length)
6706 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6709 plci->ncpi_buffer[0] = len;
6710 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6711 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6713 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6714 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6715 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6716 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6717 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6718 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6719 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6720 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6722 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6724 if (((plci->NL.Ind & 0x0f) == N_DISC)
6725 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6726 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6727 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6729 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6735 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6737 if (plci->NL.RLength != 0)
6739 info = rtp_info[plci->NL.RBuffer->P[0]];
6740 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6741 for (i = 1; i < plci->NL.RLength; i++)
6742 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6750 switch (plci->NL.Ind & 0x0f) {
6752 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6754 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6755 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6756 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6758 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6759 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6760 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6761 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6762 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6763 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6765 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6766 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6767 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6768 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6769 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6770 fax_send_edata_ack = false;
6773 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6775 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6778 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6779 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6780 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6781 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6783 a->ncci_state[ncci] = INC_ACT_PENDING;
6784 if (plci->B3_prot == 4)
6785 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6787 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6788 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6792 case EDATA_T30_TRAIN_OK:
6793 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6794 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6795 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6797 if (plci->B3_prot == 4)
6798 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6800 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6801 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6805 case EDATA_T30_EOP_CAPI:
6806 if (a->ncci_state[ncci] == CONNECTED)
6808 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6809 a->ncci_state[ncci] = INC_DIS_PENDING;
6810 plci->ncpi_state = 0;
6811 fax_send_edata_ack = false;
6818 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6820 case EDATA_T30_TRAIN_OK:
6821 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6822 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6823 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6825 if (plci->B3_prot == 4)
6826 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6828 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6829 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6834 if (fax_send_edata_ack)
6836 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6837 plci->fax_edata_ack_length = 1;
6838 start_internal_command(Id, plci, fax_edata_ack_command);
6843 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6847 if (!a->ch_ncci[ch])
6849 ncci = get_ncci(plci, ch, 0);
6850 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6852 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6853 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6855 msg = _CONNECT_B3_I;
6856 if (a->ncci_state[ncci] == IDLE)
6858 else if (plci->B3_prot == 1)
6859 msg = _CONNECT_B3_T90_ACTIVE_I;
6861 a->ncci_state[ncci] = INC_CON_PENDING;
6862 if (plci->B3_prot == 4)
6863 sendf(plci->appl, msg, Id, 0, "s", "");
6865 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6868 dbug(1, dprintf("N_connect_Ack"));
6869 if (plci->internal_command_queue[0]
6870 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6871 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6872 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6874 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6875 if (!plci->internal_command)
6876 next_internal_command(Id, plci);
6879 msg = _CONNECT_B3_ACTIVE_I;
6880 if (plci->B3_prot == 1)
6882 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6883 msg = _CONNECT_B3_T90_ACTIVE_I;
6884 a->ncci_state[ncci] = INC_ACT_PENDING;
6885 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6887 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6889 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6890 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6891 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6893 a->ncci_state[ncci] = INC_ACT_PENDING;
6894 if (plci->B3_prot == 4)
6895 sendf(plci->appl, msg, Id, 0, "s", "");
6897 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6898 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6903 a->ncci_state[ncci] = INC_ACT_PENDING;
6904 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6906 if (plci->adjust_b_restore)
6908 plci->adjust_b_restore = false;
6909 start_internal_command(Id, plci, adjust_b_restore);
6914 if (plci->internal_command_queue[0]
6915 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6916 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6917 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6919 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6920 if (!plci->internal_command)
6921 next_internal_command(Id, plci);
6923 ncci_state = a->ncci_state[ncci];
6924 ncci_remove(plci, ncci, false);
6926 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
6927 /* channel, so we cannot store the state in ncci_state! The */
6928 /* information which channel we received a N_DISC is thus */
6929 /* stored in the inc_dis_ncci_table buffer. */
6930 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6931 plci->inc_dis_ncci_table[i] = (byte) ncci;
6933 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6935 && (plci->B1_resource == 16)
6936 && (plci->State <= CONNECTED))
6939 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6940 PUT_WORD(&plci->ncpi_buffer[1], i);
6941 PUT_WORD(&plci->ncpi_buffer[3], 0);
6942 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6943 PUT_WORD(&plci->ncpi_buffer[5], i);
6944 PUT_WORD(&plci->ncpi_buffer[7], 0);
6945 plci->ncpi_buffer[len] = 0;
6946 plci->ncpi_buffer[0] = len;
6947 if (plci->B3_prot == 4)
6948 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6952 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6953 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6955 plci->ncpi_buffer[++len] = 0;
6956 plci->ncpi_buffer[++len] = 0;
6957 plci->ncpi_buffer[++len] = 0;
6958 plci->ncpi_buffer[0] = len;
6961 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6963 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6964 plci->ncpi_state = 0;
6965 sig_req(plci, HANGUP, 0);
6967 plci->State = OUTG_DIS_PENDING;
6970 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6971 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6972 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6974 if (ncci_state == IDLE)
6978 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6979 if (plci->State == SUSPENDING) {
6984 "ws", (word)3, "\x03\x04\x00\x00");
6985 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6992 else if (plci->channels)
6994 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6995 plci->ncpi_state = 0;
6996 if ((ncci_state == OUTG_REJ_PENDING)
6997 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6999 sig_req(plci, HANGUP, 0);
7001 plci->State = OUTG_DIS_PENDING;
7006 a->ncci_state[ncci] = INC_RES_PENDING;
7007 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7010 a->ncci_state[ncci] = CONNECTED;
7011 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7015 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7017 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7018 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7019 plci->NL.R = plci->RData;
7025 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7026 || (a->ncci_state[ncci] == IDLE)
7027 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7032 if ((a->ncci_state[ncci] != CONNECTED)
7033 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7034 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7036 dbug(1, dprintf("flow control"));
7037 plci->NL.RNR = 1; /* flow control */
7038 channel_x_off(plci, ch, 0);
7042 NCCIcode = ncci | (((word)a->Id) << 8);
7044 /* count all buffers within the Application pool */
7045 /* belonging to the same NCCI. If this is below the */
7046 /* number of buffers available per NCCI we accept */
7047 /* this packet, otherwise we reject it */
7050 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7051 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7052 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7055 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7057 dbug(3, dprintf("Flow-Control"));
7059 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7060 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7063 dbug(3, dprintf("DiscardData"));
7065 channel_x_off(plci, ch, 0);
7071 APPLptr->NCCIDataFlowCtrlTimer = 0;
7074 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7075 if (!plci->RData[0].P) {
7077 channel_x_off(plci, ch, 0);
7081 APPLptr->DataNCCI[Num] = NCCIcode;
7082 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7083 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7086 plci->RFlags = plci->NL.Ind >> 4;
7087 plci->RData[0].PLength = APPLptr->MaxDataLength;
7088 plci->NL.R = plci->RData;
7089 if ((plci->NL.RLength != 0)
7090 && ((plci->B2_prot == B2_V120_ASYNC)
7091 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7092 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7094 plci->RData[1].P = plci->RData[0].P;
7095 plci->RData[1].PLength = plci->RData[0].PLength;
7096 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7097 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7098 plci->RData[0].PLength = 1;
7100 plci->RData[0].PLength = 2;
7101 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7102 plci->RFlags |= 0x0010;
7103 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7104 plci->RFlags |= 0x8000;
7109 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7110 plci->RFlags |= 0x0010;
7112 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7113 plci->RFlags |= 0x0001;
7127 /*------------------------------------------------------------------*/
7128 /* find a free PLCI */
7129 /*------------------------------------------------------------------*/
7131 static word get_plci(DIVA_CAPI_ADAPTER *a)
7136 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7137 if (i == a->max_plci) {
7138 dbug(1, dprintf("get_plci: out of PLCIs"));
7142 plci->Id = (byte)(i + 1);
7150 plci->relatedPTYPLCI = NULL;
7152 plci->SuppState = IDLE;
7155 plci->B1_resource = 0;
7160 plci->m_command = 0;
7161 init_internal_command_queue(plci);
7163 plci->req_in_start = 0;
7166 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7167 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7168 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7170 plci->data_sent = false;
7171 plci->send_disc = 0;
7172 plci->sig_global_req = 0;
7173 plci->sig_remove_id = 0;
7174 plci->nl_global_req = 0;
7175 plci->nl_remove_id = 0;
7177 plci->manufacturer = false;
7178 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7179 plci->spoofed_msg = 0;
7181 plci->cr_enquiry = false;
7182 plci->hangup_flow_ctrl_timer = 0;
7184 plci->ncci_ring_list = 0;
7185 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7186 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7187 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7188 plci->fax_connect_info_length = 0;
7189 plci->nsf_control_bits = 0;
7190 plci->ncpi_state = 0x00;
7191 plci->ncpi_buffer[0] = 0;
7193 plci->requested_options_conn = 0;
7194 plci->requested_options = 0;
7195 plci->notifiedcall = 0;
7196 plci->vswitchstate = 0;
7198 plci->vsprotdialect = 0;
7199 init_b1_config(plci);
7200 dbug(1, dprintf("get_plci(%x)", plci->Id));
7204 /*------------------------------------------------------------------*/
7205 /* put a parameter in the parameter buffer */
7206 /*------------------------------------------------------------------*/
7208 static void add_p(PLCI *plci, byte code, byte *p)
7213 if (p) p_length = p[0];
7214 add_ie(plci, code, p, p_length);
7217 /*------------------------------------------------------------------*/
7218 /* put a structure in the parameter buffer */
7219 /*------------------------------------------------------------------*/
7220 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7222 if (p) add_ie(plci, code, p->info, (word)p->length);
7225 /*------------------------------------------------------------------*/
7226 /* put multiple structures in the parameter buffer */
7227 /*------------------------------------------------------------------*/
7228 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7233 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7234 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7235 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7236 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7241 /*------------------------------------------------------------------*/
7242 /* return the channel number sent by the application in a esc_chi */
7243 /*------------------------------------------------------------------*/
7244 static byte getChannel(API_PARSE *p)
7249 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7250 if (p->info[i] == 2) {
7251 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7259 /*------------------------------------------------------------------*/
7260 /* put an information element in the parameter buffer */
7261 /*------------------------------------------------------------------*/
7263 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7267 if (!(code & 0x80) && !p_length) return;
7269 if (plci->req_in == plci->req_in_start) {
7275 plci->RBuffer[plci->req_in++] = code;
7278 plci->RBuffer[plci->req_in++] = (byte)p_length;
7279 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7282 plci->RBuffer[plci->req_in++] = 0;
7285 /*------------------------------------------------------------------*/
7286 /* put a unstructured data into the buffer */
7287 /*------------------------------------------------------------------*/
7289 static void add_d(PLCI *plci, word length, byte *p)
7293 if (plci->req_in == plci->req_in_start) {
7299 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7302 /*------------------------------------------------------------------*/
7303 /* put parameters from the Additional Info parameter in the */
7304 /* parameter buffer */
7305 /*------------------------------------------------------------------*/
7307 static void add_ai(PLCI *plci, API_PARSE *ai)
7310 API_PARSE ai_parms[5];
7312 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7316 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7319 add_s(plci, KEY, &ai_parms[1]);
7320 add_s(plci, UUI, &ai_parms[2]);
7321 add_ss(plci, FTY, &ai_parms[3]);
7324 /*------------------------------------------------------------------*/
7325 /* put parameter for b1 protocol in the parameter buffer */
7326 /*------------------------------------------------------------------*/
7328 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7331 API_PARSE bp_parms[8];
7332 API_PARSE mdm_cfg[9];
7333 API_PARSE global_config[2];
7335 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7336 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7339 API_PARSE mdm_cfg_v18[4];
7344 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7345 for (i = 0; i < 2; i++) global_config[i].length = 0;
7347 dbug(1, dprintf("add_b1"));
7348 api_save_msg(bp, "s", &plci->B_protocol);
7350 if (b_channel_info == 2) {
7351 plci->B1_resource = 0;
7352 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7353 add_p(plci, CAI, "\x01\x00");
7354 dbug(1, dprintf("Cai=1,0 (no resource)"));
7358 if (plci->tel == CODEC_PERMANENT) return 0;
7359 else if (plci->tel == CODEC) {
7360 plci->B1_resource = 1;
7361 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7362 add_p(plci, CAI, "\x01\x01");
7363 dbug(1, dprintf("Cai=1,1 (Codec)"));
7366 else if (plci->tel == ADV_VOICE) {
7367 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7368 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7369 voice_cai[1] = plci->B1_resource;
7370 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7371 add_p(plci, CAI, voice_cai);
7372 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7375 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7376 if (plci->call_dir & CALL_DIR_OUT)
7377 plci->call_dir |= CALL_DIR_ORIGINATE;
7378 else if (plci->call_dir & CALL_DIR_IN)
7379 plci->call_dir |= CALL_DIR_ANSWER;
7382 plci->B1_resource = 0x5;
7383 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7384 add_p(plci, CAI, "\x01\x05");
7388 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7389 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7390 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7392 bp_parms[6].length = 0;
7393 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7395 dbug(1, dprintf("b-form.!"));
7396 return _WRONG_MESSAGE_FORMAT;
7399 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7401 dbug(1, dprintf("b-form.!"));
7402 return _WRONG_MESSAGE_FORMAT;
7405 if (bp_parms[6].length)
7407 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7409 return _WRONG_MESSAGE_FORMAT;
7411 switch (GET_WORD(global_config[0].info))
7414 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7417 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7421 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7424 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7425 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7427 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7428 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7429 cai[1] = plci->B1_resource;
7433 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7434 for (i = 0; i < bp_parms[3].length; i++)
7435 cai[7 + i] = bp_parms[3].info[1 + i];
7436 cai[0] = 6 + bp_parms[3].length;
7437 add_p(plci, CAI, cai);
7442 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7443 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7445 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7446 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7447 cai[1] = plci->B1_resource;
7451 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7453 add_p(plci, CAI, cai);
7458 if ((GET_WORD(bp_parms[0].info) >= 32)
7459 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7460 && ((GET_WORD(bp_parms[0].info) != 3)
7461 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7462 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7464 return _B1_NOT_SUPPORTED;
7466 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7467 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7468 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7470 cai[1] = plci->B1_resource;
7471 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7473 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7474 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7475 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7477 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7479 if (bp_parms[3].length)
7481 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7483 return (_WRONG_MESSAGE_FORMAT);
7486 cai[2] = 0; /* Bit rate for adaptation */
7488 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7490 PUT_WORD(&cai[13], 0); /* Min Tx speed */
7491 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7492 PUT_WORD(&cai[17], 0); /* Min Rx speed */
7493 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7495 cai[3] = 0; /* Async framing parameters */
7496 switch (GET_WORD(mdm_cfg[2].info))
7498 case 1: /* odd parity */
7499 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7500 dbug(1, dprintf("MDM: odd parity"));
7503 case 2: /* even parity */
7504 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7505 dbug(1, dprintf("MDM: even parity"));
7509 dbug(1, dprintf("MDM: no parity"));
7513 switch (GET_WORD(mdm_cfg[3].info))
7515 case 1: /* 2 stop bits */
7516 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7517 dbug(1, dprintf("MDM: 2 stop bits"));
7521 dbug(1, dprintf("MDM: 1 stop bit"));
7525 switch (GET_WORD(mdm_cfg[1].info))
7528 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7529 dbug(1, dprintf("MDM: 5 bits"));
7533 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7534 dbug(1, dprintf("MDM: 6 bits"));
7538 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7539 dbug(1, dprintf("MDM: 7 bits"));
7543 dbug(1, dprintf("MDM: 8 bits"));
7547 cai[7] = 0; /* Line taking options */
7548 cai[8] = 0; /* Modulation negotiation options */
7549 cai[9] = 0; /* Modulation options */
7551 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7553 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7554 dbug(1, dprintf("MDM: Reverse direction"));
7557 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7559 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7560 dbug(1, dprintf("MDM: Disable retrain"));
7563 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7565 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7566 dbug(1, dprintf("MDM: Disable ring tone"));
7569 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7571 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7572 dbug(1, dprintf("MDM: 1800 guard tone"));
7574 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7576 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7577 dbug(1, dprintf("MDM: 550 guard tone"));
7580 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7582 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7583 dbug(1, dprintf("MDM: V100"));
7585 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7587 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7588 dbug(1, dprintf("MDM: IN CLASS"));
7590 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7592 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7593 dbug(1, dprintf("MDM: DISABLED"));
7597 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7598 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7600 plci->requested_options |= 1L << PRIVATE_V18;
7602 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7603 plci->requested_options |= 1L << PRIVATE_VOWN;
7605 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7606 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7608 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7611 if (mdm_cfg[6].length >= 4)
7613 d = GET_DWORD(&mdm_cfg[6].info[1]);
7614 cai[7] |= (byte) d; /* line taking options */
7615 cai[9] |= (byte)(d >> 8); /* modulation options */
7616 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7617 cai[++i] = (byte)(d >> 24);
7618 if (mdm_cfg[6].length >= 8)
7620 d = GET_DWORD(&mdm_cfg[6].info[5]);
7621 cai[10] |= (byte) d; /* disabled modulations mask */
7622 cai[11] |= (byte)(d >> 8);
7623 if (mdm_cfg[6].length >= 12)
7625 d = GET_DWORD(&mdm_cfg[6].info[9]);
7626 cai[12] = (byte) d; /* enabled modulations mask */
7627 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7628 cai[++i] = (byte)(d >> 16);
7629 cai[++i] = (byte)(d >> 24);
7631 if (mdm_cfg[6].length >= 14)
7633 w = GET_WORD(&mdm_cfg[6].info[13]);
7635 PUT_WORD(&cai[13], w); /* min tx speed */
7636 if (mdm_cfg[6].length >= 16)
7638 w = GET_WORD(&mdm_cfg[6].info[15]);
7640 PUT_WORD(&cai[15], w); /* max tx speed */
7641 if (mdm_cfg[6].length >= 18)
7643 w = GET_WORD(&mdm_cfg[6].info[17]);
7645 PUT_WORD(&cai[17], w); /* min rx speed */
7646 if (mdm_cfg[6].length >= 20)
7648 w = GET_WORD(&mdm_cfg[6].info[19]);
7650 PUT_WORD(&cai[19], w); /* max rx speed */
7651 if (mdm_cfg[6].length >= 22)
7653 w = GET_WORD(&mdm_cfg[6].info[21]);
7654 cai[23] = (byte)(-((short) w)); /* transmit level */
7655 if (mdm_cfg[6].length >= 24)
7657 w = GET_WORD(&mdm_cfg[6].info[23]);
7658 cai[22] |= (byte) w; /* info options mask */
7659 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7671 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7673 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7675 for (n = 0; n < 3; n++)
7677 cai[i] = (byte)(mdm_cfg_v18[n].length);
7678 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7679 cai[i + j] = mdm_cfg_v18[n].info[j];
7684 cai[0] = (byte)(i - 1);
7690 if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7691 GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7693 if (bp_parms[3].length) {
7694 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7695 switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7698 if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7699 dbug(1, dprintf("56k sync HSCX"));
7704 else if (GET_WORD(bp_parms[0].info) == 2) {
7705 dbug(1, dprintf("56k async DSP"));
7709 case 50: cai[2] = 1; break;
7710 case 75: cai[2] = 1; break;
7711 case 110: cai[2] = 1; break;
7712 case 150: cai[2] = 1; break;
7713 case 200: cai[2] = 1; break;
7714 case 300: cai[2] = 1; break;
7715 case 600: cai[2] = 1; break;
7716 case 1200: cai[2] = 2; break;
7717 case 2400: cai[2] = 3; break;
7718 case 4800: cai[2] = 4; break;
7719 case 7200: cai[2] = 10; break;
7720 case 9600: cai[2] = 5; break;
7721 case 12000: cai[2] = 13; break;
7722 case 24000: cai[2] = 0; break;
7723 case 14400: cai[2] = 11; break;
7724 case 19200: cai[2] = 6; break;
7725 case 28800: cai[2] = 12; break;
7726 case 38400: cai[2] = 7; break;
7727 case 48000: cai[2] = 8; break;
7728 case 76: cai[2] = 15; break; /* 75/1200 */
7729 case 1201: cai[2] = 14; break; /* 1200/75 */
7730 case 56001: cai[2] = 9; break; /* V.110 56000 */
7733 return _B1_PARM_NOT_SUPPORTED;
7736 if (cai[1] == 13) /* v.110 async */
7738 if (bp_parms[3].length >= 8)
7740 switch (GET_WORD(&bp_parms[3].info[3]))
7743 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7746 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7749 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7752 switch (GET_WORD(&bp_parms[3].info[5]))
7754 case 1: /* odd parity */
7755 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7757 case 2: /* even parity */
7758 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7761 switch (GET_WORD(&bp_parms[3].info[7]))
7763 case 1: /* 2 stop bits */
7764 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7770 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7771 dbug(1, dprintf("V.110 default 56k sync"));
7777 dbug(1, dprintf("V.110 default 9600 async"));
7781 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7782 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]));
7783 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7785 add_p(plci, CAI, cai);
7789 /*------------------------------------------------------------------*/
7790 /* put parameter for b2 and B3 protocol in the parameter buffer */
7791 /*------------------------------------------------------------------*/
7793 static word add_b23(PLCI *plci, API_PARSE *bp)
7795 word i, fax_control_bits;
7797 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7798 API_PARSE bp_parms[8];
7799 API_PARSE *b1_config;
7800 API_PARSE *b2_config;
7801 API_PARSE b2_config_parms[8];
7802 API_PARSE *b3_config;
7803 API_PARSE b3_config_parms[6];
7804 API_PARSE global_config[2];
7806 static byte llc[3] = {2,0,0};
7807 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7808 static byte nlc[256];
7809 static byte lli[12] = {1,1};
7811 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7812 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7814 const byte llc3[] = {4,3,2,2,6,6,0};
7815 const byte header[] = {0,2,3,3,0,0,0};
7817 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7818 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7819 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7823 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7825 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7828 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7830 if (plci->rx_dma_descriptor <= 0) {
7831 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7832 if (plci->rx_dma_descriptor >= 0)
7833 plci->rx_dma_descriptor++;
7835 if (plci->rx_dma_descriptor > 0) {
7838 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7839 lli[3] = (byte)plci->rx_dma_magic;
7840 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7841 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7842 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7846 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7850 dbug(1, dprintf("add_b23"));
7851 api_save_msg(bp, "s", &plci->B_protocol);
7853 if (!bp->length && plci->tel)
7855 plci->adv_nl = true;
7856 dbug(1, dprintf("Default adv.Nl"));
7857 add_p(plci, LLI, lli);
7858 plci->B2_prot = 1 /*XPARENT*/;
7859 plci->B3_prot = 0 /*XPARENT*/;
7862 add_p(plci, LLC, llc);
7864 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7865 add_p(plci, DLC, dlc);
7869 if (!bp->length) /*default*/
7871 dbug(1, dprintf("ret default"));
7872 add_p(plci, LLI, lli);
7873 plci->B2_prot = 0 /*X.75 */;
7874 plci->B3_prot = 0 /*XPARENT*/;
7877 add_p(plci, LLC, llc);
7879 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7880 add_p(plci, DLC, dlc);
7883 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7884 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7886 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7888 bp_parms[6].length = 0;
7889 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7891 dbug(1, dprintf("b-form.!"));
7892 return _WRONG_MESSAGE_FORMAT;
7895 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7897 dbug(1, dprintf("b-form.!"));
7898 return _WRONG_MESSAGE_FORMAT;
7901 if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7903 if (GET_WORD(bp_parms[1].info) != 1
7904 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7905 plci->adv_nl = true;
7907 else if (plci->tel) return _B2_NOT_SUPPORTED;
7910 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7911 && (GET_WORD(bp_parms[2].info) == B3_RTP)
7912 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7914 add_p(plci, LLI, lli);
7915 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7916 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7917 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7919 add_p(plci, LLC, llc);
7921 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7922 dlc[3] = 3; /* Addr A */
7923 dlc[4] = 1; /* Addr B */
7924 dlc[5] = 7; /* modulo mode */
7925 dlc[6] = 7; /* window size */
7926 dlc[7] = 0; /* XID len Lo */
7927 dlc[8] = 0; /* XID len Hi */
7928 for (i = 0; i < bp_parms[4].length; i++)
7929 dlc[9 + i] = bp_parms[4].info[1 + i];
7930 dlc[0] = (byte)(8 + bp_parms[4].length);
7931 add_p(plci, DLC, dlc);
7932 for (i = 0; i < bp_parms[5].length; i++)
7933 nlc[1 + i] = bp_parms[5].info[1 + i];
7934 nlc[0] = (byte)(bp_parms[5].length);
7935 add_p(plci, NLC, nlc);
7941 if ((GET_WORD(bp_parms[1].info) >= 32)
7942 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7943 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7944 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7947 return _B2_NOT_SUPPORTED;
7949 if ((GET_WORD(bp_parms[2].info) >= 32)
7950 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7952 return _B3_NOT_SUPPORTED;
7954 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7955 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7956 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7957 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7959 return (add_modem_b23(plci, bp_parms));
7962 add_p(plci, LLI, lli);
7964 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7965 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7966 if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7968 if (bp_parms[6].length)
7970 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7972 return _WRONG_MESSAGE_FORMAT;
7974 switch (GET_WORD(global_config[0].info))
7977 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7980 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7984 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7987 if (plci->B2_prot == B2_PIAFS)
7990 /* IMPLEMENT_PIAFS */
7992 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7993 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7995 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7997 add_p(plci, LLC, llc);
8000 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8001 header[GET_WORD(bp_parms[2].info)]);
8003 b1_config = &bp_parms[3];
8005 if (plci->B3_prot == 4
8006 || plci->B3_prot == 5)
8008 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8009 nlc[0] = sizeof(T30_INFO);
8010 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8011 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8012 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8013 if (b1_config->length >= 2)
8015 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8018 b2_config = &bp_parms[4];
8021 if (llc[1] == PIAFS_CRC)
8023 if (plci->B3_prot != B3_TRANSPARENT)
8025 return _B_STACK_NOT_SUPPORTED;
8027 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8028 return _WRONG_MESSAGE_FORMAT;
8030 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8031 dlc[3] = 0; /* Addr A */
8032 dlc[4] = 0; /* Addr B */
8033 dlc[5] = 0; /* modulo mode */
8034 dlc[6] = 0; /* window size */
8035 if (b2_config->length >= 7) {
8038 dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8039 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8040 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8041 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8042 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8043 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8044 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8046 if (b2_config->length >= 8) { /* PIAFS control abilities */
8048 dlc[16] = 2; /* Length of PIAFS extension */
8049 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8050 dlc[18] = b2_config_parms[4].info[0]; /* value */
8054 else /* default values, 64K, variable, no compression */
8058 dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8059 dlc[10] = 0x03; /* V.42bis P0 */
8060 dlc[11] = 0; /* V.42bis P0 */
8061 dlc[12] = 0; /* V.42bis P1 */
8062 dlc[13] = 0; /* V.42bis P1 */
8063 dlc[14] = 0; /* V.42bis P2 */
8064 dlc[15] = 0; /* V.42bis P2 */
8067 add_p(plci, DLC, dlc);
8071 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8073 if (plci->B3_prot != B3_TRANSPARENT)
8074 return _B_STACK_NOT_SUPPORTED;
8077 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8082 if (b2_config->length != 0)
8084 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8085 return _WRONG_MESSAGE_FORMAT;
8087 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8088 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8089 if (b2_config->info[3] != 128)
8091 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8092 return _B2_PARM_NOT_SUPPORTED;
8094 dlc[5] = (byte)(b2_config->info[3] - 1);
8095 dlc[6] = b2_config->info[4];
8096 if (llc[1] == V120_V42BIS) {
8097 if (b2_config->length >= 10) {
8100 dlc[9] = b2_config_parms[4].info[0];
8101 dlc[10] = b2_config_parms[4].info[1];
8102 dlc[11] = b2_config_parms[5].info[0];
8103 dlc[12] = b2_config_parms[5].info[1];
8104 dlc[13] = b2_config_parms[6].info[0];
8105 dlc[14] = b2_config_parms[6].info[1];
8107 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8108 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8109 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8119 if (b2_config->length)
8121 dbug(1, dprintf("B2-Config"));
8122 if (llc[1] == X75_V42BIS) {
8123 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8125 return _WRONG_MESSAGE_FORMAT;
8129 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8131 return _WRONG_MESSAGE_FORMAT;
8134 /* if B2 Protocol is LAPD, b2_config structure is different */
8138 if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8140 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8142 SAPI = b2_config->info[2]; /* SAPI */
8145 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8147 dlc[3] = 127; /* Mode */
8151 dlc[3] = 7; /* Mode */
8154 if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8156 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8157 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8161 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8162 dlc[3] = b2_config->info[1];
8163 dlc[4] = b2_config->info[2];
8164 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8165 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8166 return _B2_PARM_NOT_SUPPORTED;
8169 dlc[5] = (byte)(b2_config->info[3] - 1);
8170 dlc[6] = b2_config->info[4];
8171 if (dlc[6] > dlc[5]) {
8172 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]));
8173 return _B2_PARM_NOT_SUPPORTED;
8176 if (llc[1] == X75_V42BIS) {
8177 if (b2_config->length >= 10) {
8180 dlc[9] = b2_config_parms[4].info[0];
8181 dlc[10] = b2_config_parms[4].info[1];
8182 dlc[11] = b2_config_parms[5].info[0];
8183 dlc[12] = b2_config_parms[5].info[1];
8184 dlc[13] = b2_config_parms[6].info[0];
8185 dlc[14] = b2_config_parms[6].info[1];
8187 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8188 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8189 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8197 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8198 for (i = 0; i < b2_config_parms[4].length; i++)
8199 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8204 add_p(plci, DLC, dlc);
8206 b3_config = &bp_parms[5];
8207 if (b3_config->length)
8209 if (plci->B3_prot == 4
8210 || plci->B3_prot == 5)
8212 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8214 return _WRONG_MESSAGE_FORMAT;
8216 i = GET_WORD((byte *)(b3_config_parms[0].info));
8217 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8218 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8219 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8220 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8221 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8222 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8223 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8226 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8227 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8229 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8230 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8231 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8234 ((T30_INFO *)&nlc[1])->recording_properties =
8235 T30_RECORDING_WIDTH_ISO_A3 |
8236 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8237 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8239 if (plci->B3_prot == 5)
8241 if (i & 0x0002) /* Accept incoming fax-polling requests */
8242 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8243 if (i & 0x2000) /* Do not use MR compression */
8244 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8245 if (i & 0x4000) /* Do not use MMR compression */
8246 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8247 if (i & 0x8000) /* Do not use ECM */
8248 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8249 if (plci->fax_connect_info_length != 0)
8251 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8252 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8253 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8254 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8255 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8258 /* copy station id to NLC */
8259 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8261 if (i < b3_config_parms[2].length)
8263 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8267 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8270 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8271 /* copy head line to NLC */
8272 if (b3_config_parms[3].length)
8275 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8278 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8282 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8283 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8284 len = (byte)b3_config_parms[2].length;
8287 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8289 for (i = 0; i < len; i++)
8290 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8291 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8292 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8297 len = (byte)b3_config_parms[3].length;
8298 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8299 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8300 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8301 nlc[0] += (byte)(pos + len);
8302 for (i = 0; i < len; i++)
8303 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8305 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8307 plci->nsf_control_bits = 0;
8308 if (plci->B3_prot == 5)
8310 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8311 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8313 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8315 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8316 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8318 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8320 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8321 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8323 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8324 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8326 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8327 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8328 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8331 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8332 if (pos < plci->fax_connect_info_length)
8334 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8335 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8339 if (pos < plci->fax_connect_info_length)
8341 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8342 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8346 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8347 & (1L << PRIVATE_FAX_NONSTANDARD))
8349 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8351 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8352 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8353 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8354 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8358 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8360 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8365 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8366 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8367 nlc[++len] = (byte)(b3_config_parms[4].length);
8368 for (i = 0; i < b3_config_parms[4].length; i++)
8369 nlc[++len] = b3_config_parms[4].info[1 + i];
8374 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8375 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8377 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8382 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8383 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8384 for (i = 0; i < len; i++)
8385 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8386 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8387 i += ((T30_INFO *)&nlc[1])->head_line_len;
8389 plci->fax_connect_info_buffer[len++] = nlc[++i];
8390 plci->fax_connect_info_length = len;
8395 if (b3_config->length != 16)
8396 return _B3_PARM_NOT_SUPPORTED;
8397 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8398 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8399 return _B3_PARM_NOT_SUPPORTED;
8400 nlc[13] = b3_config->info[13];
8401 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8402 return _B3_PARM_NOT_SUPPORTED;
8403 nlc[14] = b3_config->info[15];
8408 if (plci->B3_prot == 4
8409 || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8411 add_p(plci, NLC, nlc);
8415 /*----------------------------------------------------------------*/
8416 /* make the same as add_b23, but only for the modem related */
8417 /* L2 and L3 B-Chan protocol. */
8419 /* Enabled L2 and L3 Configurations: */
8420 /* If L1 == Modem all negotiation */
8421 /* only L2 == Modem with full negotiation is allowed */
8422 /* If L1 == Modem async or sync */
8423 /* only L2 == Transparent is allowed */
8424 /* L3 == Modem or L3 == Transparent are allowed */
8425 /* B2 Configuration for modem: */
8426 /* word : enable/disable compression, bitoptions */
8427 /* B3 Configuration for modem: */
8429 /*----------------------------------------------------------------*/
8430 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8432 static byte lli[12] = {1,1};
8433 static byte llc[3] = {2,0,0};
8434 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8435 API_PARSE mdm_config[2];
8439 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8440 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8442 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8443 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8444 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8445 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8447 return (_B_STACK_NOT_SUPPORTED);
8449 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8450 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8452 return (_B_STACK_NOT_SUPPORTED);
8455 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8456 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8458 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8460 if (api_parse(&bp_parms[4].info[1],
8461 (word)bp_parms[4].length, "w",
8464 return (_WRONG_MESSAGE_FORMAT);
8466 b2_config = GET_WORD(mdm_config[0].info);
8469 /* OK, L2 is modem */
8473 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8475 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8478 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8480 if (plci->rx_dma_descriptor <= 0) {
8481 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8482 if (plci->rx_dma_descriptor >= 0)
8483 plci->rx_dma_descriptor++;
8485 if (plci->rx_dma_descriptor > 0) {
8488 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8489 lli[3] = (byte)plci->rx_dma_magic;
8490 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8491 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8492 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8496 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8500 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8501 /*V42*/ 10 : /*V42_IN*/ 9;
8502 llc[2] = 4; /* pass L3 always transparent */
8503 add_p(plci, LLI, lli);
8504 add_p(plci, LLC, llc);
8506 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8508 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8510 if (bp_parms[4].length)
8512 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8513 dlc[i++] = 3; /* Addr A */
8514 dlc[i++] = 1; /* Addr B */
8515 dlc[i++] = 7; /* modulo mode */
8516 dlc[i++] = 7; /* window size */
8517 dlc[i++] = 0; /* XID len Lo */
8518 dlc[i++] = 0; /* XID len Hi */
8520 if (b2_config & MDM_B2_DISABLE_V42bis)
8522 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8524 if (b2_config & MDM_B2_DISABLE_MNP)
8526 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8528 if (b2_config & MDM_B2_DISABLE_TRANS)
8530 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8532 if (b2_config & MDM_B2_DISABLE_V42)
8534 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8536 if (b2_config & MDM_B2_DISABLE_COMP)
8538 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8545 dlc[i++] = 3; /* Addr A */
8546 dlc[i++] = 1; /* Addr B */
8547 dlc[i++] = 7; /* modulo mode */
8548 dlc[i++] = 7; /* window size */
8549 dlc[i++] = 0; /* XID len Lo */
8550 dlc[i++] = 0; /* XID len Hi */
8551 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8552 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8553 DLC_MODEMPROT_DISABLE_V42_DETECT |
8554 DLC_MODEMPROT_DISABLE_COMPRESSION;
8556 dlc[0] = (byte)(i - 1);
8557 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8558 add_p(plci, DLC, dlc);
8563 /*------------------------------------------------------------------*/
8564 /* send a request for the signaling entity */
8565 /*------------------------------------------------------------------*/
8567 static void sig_req(PLCI *plci, byte req, byte Id)
8570 if (plci->adapter->adapter_disabled) return;
8571 dbug(1, dprintf("sig_req(%x)", req));
8573 plci->sig_remove_id = plci->Sig.Id;
8574 if (plci->req_in == plci->req_in_start) {
8576 plci->RBuffer[plci->req_in++] = 0;
8578 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8579 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8580 plci->RBuffer[plci->req_in++] = req; /* request */
8581 plci->RBuffer[plci->req_in++] = 0; /* channel */
8582 plci->req_in_start = plci->req_in;
8585 /*------------------------------------------------------------------*/
8586 /* send a request for the network layer entity */
8587 /*------------------------------------------------------------------*/
8589 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8592 if (plci->adapter->adapter_disabled) return;
8593 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8596 plci->nl_remove_id = plci->NL.Id;
8597 ncci_remove(plci, 0, (byte)(ncci != 0));
8600 if (plci->req_in == plci->req_in_start) {
8602 plci->RBuffer[plci->req_in++] = 0;
8604 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8605 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8606 plci->RBuffer[plci->req_in++] = req; /* request */
8607 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8608 plci->req_in_start = plci->req_in;
8611 static void send_req(PLCI *plci)
8618 if (plci->adapter->adapter_disabled) return;
8619 channel_xmit_xon(plci);
8621 /* if nothing to do, return */
8622 if (plci->req_in == plci->req_out) return;
8623 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8625 if (plci->nl_req || plci->sig_req) return;
8627 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8629 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8631 if (plci->RBuffer[plci->req_out] == 1)
8635 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8636 e->ReqCh = plci->RBuffer[plci->req_out++];
8637 if (!(e->Id & 0x1f))
8640 plci->RBuffer[plci->req_out - 4] = CAI;
8641 plci->RBuffer[plci->req_out - 3] = 1;
8642 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8643 plci->RBuffer[plci->req_out - 1] = 0;
8645 plci->nl_global_req = plci->nl_req;
8647 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8652 if (plci->RBuffer[plci->req_out])
8653 e->Id = plci->RBuffer[plci->req_out];
8655 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8656 e->ReqCh = plci->RBuffer[plci->req_out++];
8657 if (!(e->Id & 0x1f))
8658 plci->sig_global_req = plci->sig_req;
8659 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8661 plci->XData[0].PLength = l;
8663 plci->adapter->request(e);
8664 dbug(1, dprintf("send_ok"));
8667 static void send_data(PLCI *plci)
8669 DIVA_CAPI_ADAPTER *a;
8674 if (!plci->nl_req && plci->ncci_ring_list)
8677 ncci = plci->ncci_ring_list;
8680 ncci = a->ncci_next[ncci];
8681 ncci_ptr = &(a->ncci[ncci]);
8682 if (!(a->ncci_ch[ncci]
8683 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8685 if (ncci_ptr->data_pending)
8687 if ((a->ncci_state[ncci] == CONNECTED)
8688 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8689 || (plci->send_disc == ncci))
8691 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8692 if ((plci->B2_prot == B2_V120_ASYNC)
8693 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8694 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8696 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8697 plci->NData[1].PLength = data->Length;
8698 if (data->Flags & 0x10)
8699 plci->NData[0].P = v120_break_header;
8701 plci->NData[0].P = v120_default_header;
8702 plci->NData[0].PLength = 1;
8704 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8708 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8709 plci->NData[0].PLength = data->Length;
8710 if (data->Flags & 0x10)
8711 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8713 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8714 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8717 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8719 plci->NL.X = plci->NData;
8720 plci->NL.ReqCh = a->ncci_ch[ncci];
8721 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8722 plci->data_sent = true;
8723 plci->data_sent_ptr = data->P;
8724 a->request(&plci->NL);
8727 cleanup_ncci_data(plci, ncci);
8730 else if (plci->send_disc == ncci)
8732 /* dprintf("N_DISC"); */
8733 plci->NData[0].PLength = 0;
8734 plci->NL.ReqCh = a->ncci_ch[ncci];
8735 plci->NL.Req = plci->nl_req = N_DISC;
8736 a->request(&plci->NL);
8737 plci->command = _DISCONNECT_B3_R;
8738 plci->send_disc = 0;
8741 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8742 plci->ncci_ring_list = ncci;
8746 static void listen_check(DIVA_CAPI_ADAPTER *a)
8750 byte activnotifiedcalls = 0;
8752 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8753 if (!remove_started && !a->adapter_disabled)
8755 for (i = 0; i < a->max_plci; i++)
8757 plci = &(a->plci[i]);
8758 if (plci->notifiedcall) activnotifiedcalls++;
8760 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8762 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8763 if ((j = get_plci(a))) {
8765 plci = &a->plci[j - 1];
8766 plci->State = LISTENING;
8768 add_p(plci, OAD, "\x01\xfd");
8770 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8772 add_p(plci, CAI, "\x01\xc0");
8773 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8774 add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8775 add_p(plci, SHIFT | 6, NULL);
8776 add_p(plci, SIN, "\x02\x00\x00");
8777 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8778 sig_req(plci, ASSIGN, DSIG_ID);
8785 /*------------------------------------------------------------------*/
8786 /* functions for all parameters sent in INDs */
8787 /*------------------------------------------------------------------*/
8789 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8791 word ploc; /* points to current location within packet */
8803 in = plci->Sig.RBuffer->P;
8804 for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8805 { /* element but parms array is larger */
8806 parms[i] = (byte *)"";
8808 for (i = 0; i < multiIEsize; i++)
8810 parms[i] = (byte *)"";
8813 while (ploc < plci->Sig.RBuffer->length - 1) {
8815 /* read information element id and length */
8819 /* w &=0xf0; removed, cannot detect congestion levels */
8820 /* upper 4 bit masked with w==SHIFT now */
8824 wlen = (byte)(in[ploc + 1] + 1);
8826 /* check if length valid (not exceeding end of packet) */
8827 if ((ploc + wlen) > 270) return;
8828 if (lock & 0x80) lock &= 0x7f;
8829 else codeset = lock;
8831 if ((w & 0xf0) == SHIFT) {
8833 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8838 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8840 code |= (codeset << 8);
8842 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8844 if (i < parms_id[0] + 1) {
8845 if (!multiIEsize) { /* with multiIEs use next field index, */
8846 mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8849 parms[mIEindex] = &in[ploc + 1];
8850 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8851 if (parms_id[i] == OAD
8852 || parms_id[i] == CONN_NR
8853 || parms_id[i] == CAD) {
8854 if (in[ploc + 2] & 0x80) {
8855 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8856 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8857 in[ploc + 2] = 0x80;
8858 parms[mIEindex] = &in[ploc];
8861 mIEindex++; /* effects multiIEs only */
8870 /*------------------------------------------------------------------*/
8871 /* try to match a cip from received BC and HLC */
8872 /*------------------------------------------------------------------*/
8874 static byte ie_compare(byte *ie1, byte *ie2)
8877 if (!ie1 || !ie2) return false;
8878 if (!ie1[0]) return false;
8879 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8883 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8888 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8890 for (j = 16; j < 29 &&
8891 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8892 if (j == 29) return i;
8897 static byte AddInfo(byte **add_i,
8907 /* facility is a nested structure */
8908 /* FTY can be more than once */
8910 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8912 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8917 add_i[0] = (byte *)"";
8921 add_i[3] = (byte *)"";
8924 { /* facility array found */
8925 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8927 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8931 facility[j++] = 0x1c; /* copy fac IE */
8932 for (k = 0; k <= flen; k++, j++)
8934 facility[j] = fty_i[i][k];
8935 /* dbug(1, dprintf("%x ",facility[j])); */
8939 add_i[3] = facility;
8941 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
8942 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8943 len += 4; /* calculate length of all */
8947 /*------------------------------------------------------------------*/
8948 /* voice and codec features */
8949 /*------------------------------------------------------------------*/
8951 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8953 byte voice_chi[] = "\x02\x18\x01";
8956 channel = chi[chi[0]] & 0x3;
8957 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8958 voice_chi[2] = (channel) ? channel : 1;
8959 add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
8960 add_p(plci, ESC, voice_chi); /* Channel */
8961 sig_req(plci, TEL_CTRL, 0);
8963 if (a->AdvSignalPLCI)
8965 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8969 static void VoiceChannelOff(PLCI *plci)
8971 dbug(1, dprintf("ExtDevOFF"));
8972 add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
8973 sig_req(plci, TEL_CTRL, 0);
8975 if (plci->adapter->AdvSignalPLCI)
8977 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8982 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8988 /* check if hardware supports handset with hook states (adv.codec) */
8989 /* or if just a on board codec is supported */
8990 /* the advanced codec plci is just for internal use */
8992 /* diva Pro with on-board codec: */
8993 if (a->profile.Global_Options & HANDSET)
8995 /* new call, but hook states are already signalled */
8996 if (a->AdvCodecFLAG)
8998 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9000 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9001 return 0x2001; /* codec in use by another application */
9005 a->AdvSignalPLCI = plci;
9006 plci->tel = ADV_VOICE;
9008 return 0; /* adv codec still used */
9010 if ((j = get_plci(a)))
9012 splci = &a->plci[j - 1];
9013 splci->tel = CODEC_PERMANENT;
9014 /* hook_listen indicates if a facility_req with handset/hook support */
9015 /* was sent. Otherwise if just a call on an external device was made */
9016 /* the codec will be used but the hook info will be discarded (just */
9017 /* the external controller is in use */
9018 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9021 splci->State = ADVANCED_VOICE_NOSIG;
9024 plci->spoofed_msg = SPOOFING_REQUIRED;
9026 /* indicate D-ch connect if */
9027 } /* codec is connected OK */
9030 a->AdvSignalPLCI = plci;
9031 plci->tel = ADV_VOICE;
9033 a->AdvSignalAppl = appl;
9034 a->AdvCodecFLAG = true;
9035 a->AdvCodecPLCI = splci;
9036 add_p(splci, CAI, "\x01\x15");
9037 add_p(splci, LLI, "\x01\x00");
9038 add_p(splci, ESC, "\x02\x18\x00");
9039 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9040 splci->internal_command = PERM_COD_ASSIGN;
9041 dbug(1, dprintf("Codec Assign"));
9042 sig_req(splci, ASSIGN, DSIG_ID);
9047 return 0x2001; /* wrong state, no more plcis */
9050 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9052 if (hook_listen) return 0x300B; /* Facility not supported */
9053 /* no hook with SCOM */
9054 if (plci != NULL) plci->tel = CODEC;
9055 dbug(1, dprintf("S/SCOM codec"));
9056 /* first time we use the scom-s codec we must shut down the internal */
9057 /* handset application of the card. This can be done by an assign with */
9058 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9059 if (!a->scom_appl_disable) {
9060 if ((j = get_plci(a))) {
9061 splci = &a->plci[j - 1];
9062 add_p(splci, CAI, "\x01\x80");
9063 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9064 sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9066 a->scom_appl_disable = true;
9069 return 0x2001; /* wrong state, no more plcis */
9073 else return 0x300B; /* Facility not supported */
9079 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9082 dbug(1, dprintf("CodecIdCheck"));
9084 if (a->AdvSignalPLCI == plci)
9086 dbug(1, dprintf("PLCI owns codec"));
9087 VoiceChannelOff(a->AdvCodecPLCI);
9088 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9090 dbug(1, dprintf("remove temp codec PLCI"));
9091 plci_remove(a->AdvCodecPLCI);
9092 a->AdvCodecFLAG = 0;
9093 a->AdvCodecPLCI = NULL;
9094 a->AdvSignalAppl = NULL;
9096 a->AdvSignalPLCI = NULL;
9100 /* -------------------------------------------------------------------
9101 Ask for physical address of card on PCI bus
9102 ------------------------------------------------------------------- */
9103 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9104 IDI_SYNC_REQ *preq) {
9106 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9107 ENTITY *e = (ENTITY *)preq;
9109 e->user[0] = a->Id - 1;
9110 preq->xdi_sdram_bar.info.bar = 0;
9111 preq->xdi_sdram_bar.Req = 0;
9112 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9116 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9117 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9121 /* -------------------------------------------------------------------
9122 Ask XDI about extended features
9123 ------------------------------------------------------------------- */
9124 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9126 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9129 preq = (IDI_SYNC_REQ *)&buffer[0];
9131 if (!diva_xdi_extended_features) {
9132 ENTITY *e = (ENTITY *)preq;
9133 diva_xdi_extended_features |= 0x80000000;
9135 e->user[0] = a->Id - 1;
9136 preq->xdi_extended_features.Req = 0;
9137 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9138 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9139 preq->xdi_extended_features.info.features = &features[0];
9143 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9145 Check features located in the byte '0'
9147 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9148 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9150 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9151 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9152 dbug(1, dprintf("XDI provides RxDMA"));
9154 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9155 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9157 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9158 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9159 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9165 diva_ask_for_xdi_sdram_bar(a, preq);
9168 /*------------------------------------------------------------------*/
9170 /*------------------------------------------------------------------*/
9171 /* called from OS specific part after init time to get the Law */
9172 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9173 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9178 if (a->automatic_law) {
9181 if ((j = get_plci(a))) {
9182 diva_get_extended_adapter_features(a);
9183 splci = &a->plci[j - 1];
9184 a->automatic_lawPLCI = splci;
9185 a->automatic_law = 1;
9186 add_p(splci, CAI, "\x01\x80");
9187 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9188 splci->internal_command = USELAW_REQ;
9191 sig_req(splci, ASSIGN, DSIG_ID);
9196 /* called from OS specific part if an application sends an Capi20Release */
9197 word CapiRelease(word Id)
9199 word i, j, appls_found;
9202 DIVA_CAPI_ADAPTER *a;
9206 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9207 return (_WRONG_APPL_ID);
9210 this = &application[Id - 1]; /* get application pointer */
9212 for (i = 0, appls_found = 0; i < max_appl; i++)
9214 if (application[i].Id) /* an application has been found */
9220 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9225 a->Info_Mask[Id - 1] = 0;
9226 a->CIP_Mask[Id - 1] = 0;
9227 a->Notification_Mask[Id - 1] = 0;
9228 a->codec_listen[Id - 1] = NULL;
9229 a->requested_options_table[Id - 1] = 0;
9230 for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9231 { /* with this application */
9233 if (plci->Id) /* if plci owns no application */
9234 { /* it may be not jet connected */
9235 if (plci->State == INC_CON_PENDING
9236 || plci->State == INC_CON_ALERT)
9238 if (test_bit(Id - 1, plci->c_ind_mask_table))
9240 __clear_bit(Id - 1, plci->c_ind_mask_table);
9241 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9243 sig_req(plci, HANGUP, 0);
9245 plci->State = OUTG_DIS_PENDING;
9249 if (test_bit(Id - 1, plci->c_ind_mask_table))
9251 __clear_bit(Id - 1, plci->c_ind_mask_table);
9252 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9261 if (plci->appl == this)
9271 if (a->flag_dynamic_l1_down)
9273 if (appls_found == 1) /* last application does a capi release */
9275 if ((j = get_plci(a)))
9277 plci = &a->plci[j - 1];
9279 add_p(plci, OAD, "\x01\xfd");
9280 add_p(plci, CAI, "\x01\x80");
9281 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9282 add_p(plci, SHIFT | 6, NULL);
9283 add_p(plci, SIN, "\x02\x00\x00");
9284 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9285 sig_req(plci, ASSIGN, DSIG_ID);
9286 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9287 sig_req(plci, SIG_CTRL, 0);
9292 if (a->AdvSignalAppl == this)
9294 this->NullCREnable = false;
9295 if (a->AdvCodecPLCI)
9297 plci_remove(a->AdvCodecPLCI);
9298 a->AdvCodecPLCI->tel = 0;
9299 a->AdvCodecPLCI->adv_nl = 0;
9301 a->AdvSignalAppl = NULL;
9302 a->AdvSignalPLCI = NULL;
9303 a->AdvCodecFLAG = 0;
9304 a->AdvCodecPLCI = NULL;
9314 static word plci_remove_check(PLCI *plci)
9316 if (!plci) return true;
9317 if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9319 if (plci->Sig.Id == 0xff)
9323 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9324 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9327 CodecIdCheck(plci->adapter, plci);
9328 clear_b1_config(plci);
9329 ncci_remove(plci, 0, false);
9330 plci_free_msg_in_queue(plci);
9331 channel_flow_control_remove(plci);
9336 plci->notifiedcall = 0;
9338 listen_check(plci->adapter);
9346 /*------------------------------------------------------------------*/
9348 static byte plci_nl_busy(PLCI *plci)
9350 /* only applicable for non-multiplexed protocols */
9351 return (plci->nl_req
9352 || (plci->ncci_ring_list
9353 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9354 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9358 /*------------------------------------------------------------------*/
9359 /* DTMF facilities */
9360 /*------------------------------------------------------------------*/
9369 } dtmf_digit_map[] =
9371 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9372 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9373 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9374 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9375 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9376 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9377 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9378 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9379 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9380 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9381 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9382 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9383 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9384 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9385 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9386 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9387 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9388 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9389 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9390 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9392 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9393 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9394 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9395 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9396 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9397 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9398 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9399 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9400 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9401 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9402 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9403 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9404 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9405 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9406 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9407 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9408 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9409 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9410 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9411 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9412 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9413 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9414 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9415 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9416 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9417 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9418 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9419 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9420 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9421 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9422 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9423 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9424 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9425 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9426 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9427 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9428 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9429 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9430 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9431 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9432 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9433 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9434 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9435 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9436 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9437 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9438 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9439 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9440 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9441 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9442 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9443 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9447 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9450 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9452 word min_digit_duration, min_gap_duration;
9454 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9455 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9456 (char *)(FILE_), __LINE__, enable_mask));
9458 if (enable_mask != 0)
9460 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9461 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9462 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9463 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9464 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9465 plci->NData[0].PLength = 5;
9467 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9468 plci->NData[0].PLength += 2;
9469 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9474 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9475 plci->NData[0].PLength = 1;
9477 capidtmf_recv_disable(&(plci->capidtmf_state));
9480 plci->NData[0].P = plci->internal_req_buffer;
9481 plci->NL.X = plci->NData;
9483 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9484 plci->adapter->request(&plci->NL);
9488 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9492 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9493 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9494 (char *)(FILE_), __LINE__, digit_count));
9496 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9497 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9498 PUT_WORD(&plci->internal_req_buffer[1], w);
9499 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9500 PUT_WORD(&plci->internal_req_buffer[3], w);
9501 for (i = 0; i < digit_count; i++)
9504 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9505 && (digit_buffer[i] != dtmf_digit_map[w].character))
9509 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9510 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9512 plci->NData[0].PLength = 5 + digit_count;
9513 plci->NData[0].P = plci->internal_req_buffer;
9514 plci->NL.X = plci->NData;
9516 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9517 plci->adapter->request(&plci->NL);
9521 static void dtmf_rec_clear_config(PLCI *plci)
9524 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9525 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9526 (char *)(FILE_), __LINE__));
9528 plci->dtmf_rec_active = 0;
9529 plci->dtmf_rec_pulse_ms = 0;
9530 plci->dtmf_rec_pause_ms = 0;
9532 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9537 static void dtmf_send_clear_config(PLCI *plci)
9540 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9541 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9542 (char *)(FILE_), __LINE__));
9544 plci->dtmf_send_requests = 0;
9545 plci->dtmf_send_pulse_ms = 0;
9546 plci->dtmf_send_pause_ms = 0;
9550 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9553 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9554 UnMapId(Id), (char *)(FILE_), __LINE__));
9556 while (plci->dtmf_send_requests != 0)
9557 dtmf_confirmation(Id, plci);
9561 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9564 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9565 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9571 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9575 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9576 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9579 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9581 switch (plci->adjust_b_state)
9583 case ADJUST_B_RESTORE_DTMF_1:
9584 plci->internal_command = plci->adjust_b_command;
9585 if (plci_nl_busy(plci))
9587 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9590 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9591 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9593 case ADJUST_B_RESTORE_DTMF_2:
9594 if ((Rc != OK) && (Rc != OK_FC))
9596 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9597 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9598 Info = _WRONG_STATE;
9608 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9610 word internal_command, Info;
9614 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9615 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9616 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9617 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9621 PUT_WORD(&result[1], DTMF_SUCCESS);
9622 internal_command = plci->internal_command;
9623 plci->internal_command = 0;
9625 switch (plci->dtmf_cmd)
9628 case DTMF_LISTEN_TONE_START:
9630 case DTMF_LISTEN_MF_START:
9633 case DTMF_LISTEN_START:
9634 switch (internal_command)
9637 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9638 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9639 case DTMF_COMMAND_1:
9640 if (adjust_b_process(Id, plci, Rc) != GOOD)
9642 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9643 UnMapId(Id), (char *)(FILE_), __LINE__));
9644 Info = _FACILITY_NOT_SUPPORTED;
9647 if (plci->internal_command)
9649 case DTMF_COMMAND_2:
9650 if (plci_nl_busy(plci))
9652 plci->internal_command = DTMF_COMMAND_2;
9655 plci->internal_command = DTMF_COMMAND_3;
9656 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9658 case DTMF_COMMAND_3:
9659 if ((Rc != OK) && (Rc != OK_FC))
9661 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9662 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9663 Info = _FACILITY_NOT_SUPPORTED;
9667 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9669 plci->dtmf_rec_active |= mask;
9675 case DTMF_LISTEN_TONE_STOP:
9677 case DTMF_LISTEN_MF_STOP:
9680 case DTMF_LISTEN_STOP:
9681 switch (internal_command)
9684 plci->dtmf_rec_active &= ~mask;
9685 if (plci->dtmf_rec_active)
9688 case DTMF_COMMAND_1:
9689 if (plci->dtmf_rec_active)
9691 if (plci_nl_busy (plci))
9693 plci->internal_command = DTMF_COMMAND_1;
9696 plci->dtmf_rec_active &= ~mask;
9697 plci->internal_command = DTMF_COMMAND_2;
9698 dtmf_enable_receiver (plci, false);
9702 case DTMF_COMMAND_2:
9703 if ((Rc != OK) && (Rc != OK_FC))
9705 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9706 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9707 Info = _FACILITY_NOT_SUPPORTED;
9711 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9712 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9713 case DTMF_COMMAND_3:
9714 if (adjust_b_process(Id, plci, Rc) != GOOD)
9716 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9717 UnMapId(Id), (char *)(FILE_), __LINE__));
9718 Info = _FACILITY_NOT_SUPPORTED;
9721 if (plci->internal_command)
9728 case DTMF_SEND_TONE:
9733 case DTMF_DIGITS_SEND:
9734 switch (internal_command)
9737 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9738 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9740 case DTMF_COMMAND_1:
9741 if (adjust_b_process(Id, plci, Rc) != GOOD)
9743 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9744 UnMapId(Id), (char *)(FILE_), __LINE__));
9745 Info = _FACILITY_NOT_SUPPORTED;
9748 if (plci->internal_command)
9750 case DTMF_COMMAND_2:
9751 if (plci_nl_busy(plci))
9753 plci->internal_command = DTMF_COMMAND_2;
9756 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9757 plci->internal_command = DTMF_COMMAND_3;
9758 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9760 case DTMF_COMMAND_3:
9761 if ((Rc != OK) && (Rc != OK_FC))
9763 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9764 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9765 if (plci->dtmf_send_requests != 0)
9766 (plci->dtmf_send_requests)--;
9767 Info = _FACILITY_NOT_SUPPORTED;
9774 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9775 "wws", Info, SELECTOR_DTMF, result);
9779 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9784 API_PARSE dtmf_parms[5];
9787 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9788 UnMapId(Id), (char *)(FILE_), __LINE__));
9792 PUT_WORD(&result[1], DTMF_SUCCESS);
9793 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9795 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9796 UnMapId(Id), (char *)(FILE_), __LINE__));
9797 Info = _FACILITY_NOT_SUPPORTED;
9799 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9801 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9802 UnMapId(Id), (char *)(FILE_), __LINE__));
9803 Info = _WRONG_MESSAGE_FORMAT;
9806 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9807 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9809 if (!((a->requested_options_table[appl->Id - 1])
9810 & (1L << PRIVATE_DTMF_TONE)))
9812 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9813 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9814 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9818 for (i = 0; i < 32; i++)
9820 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9822 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9824 if (dtmf_digit_map[i].listen_mask != 0)
9825 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9830 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9832 if (dtmf_digit_map[i].send_mask != 0)
9833 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9841 else if (plci == NULL)
9843 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9844 UnMapId(Id), (char *)(FILE_), __LINE__));
9845 Info = _WRONG_IDENTIFIER;
9850 || !plci->NL.Id || plci->nl_remove_id)
9852 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9853 UnMapId(Id), (char *)(FILE_), __LINE__));
9854 Info = _WRONG_STATE;
9859 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9861 switch (plci->dtmf_cmd)
9864 case DTMF_LISTEN_TONE_START:
9865 case DTMF_LISTEN_TONE_STOP:
9867 case DTMF_LISTEN_MF_START:
9868 case DTMF_LISTEN_MF_STOP:
9870 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9871 & (1L << PRIVATE_DTMF_TONE)))
9873 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9874 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9875 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9879 case DTMF_LISTEN_START:
9880 case DTMF_LISTEN_STOP:
9881 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9882 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9884 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9885 UnMapId(Id), (char *)(FILE_), __LINE__));
9886 Info = _FACILITY_NOT_SUPPORTED;
9889 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9891 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9893 plci->dtmf_rec_pulse_ms = 0;
9894 plci->dtmf_rec_pause_ms = 0;
9898 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9899 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9902 start_internal_command(Id, plci, dtmf_command);
9906 case DTMF_SEND_TONE:
9910 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9911 & (1L << PRIVATE_DTMF_TONE)))
9913 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9914 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9915 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9919 case DTMF_DIGITS_SEND:
9920 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9922 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9923 UnMapId(Id), (char *)(FILE_), __LINE__));
9924 Info = _WRONG_MESSAGE_FORMAT;
9927 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9929 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9930 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9934 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9937 while ((j < DTMF_DIGIT_MAP_ENTRIES)
9938 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9939 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9945 if (j == DTMF_DIGIT_MAP_ENTRIES)
9947 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9948 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9949 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9952 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9954 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9955 UnMapId(Id), (char *)(FILE_), __LINE__));
9956 Info = _WRONG_STATE;
9959 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9960 start_internal_command(Id, plci, dtmf_command);
9964 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9965 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9966 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9970 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9971 "wws", Info, SELECTOR_DTMF, result);
9976 static void dtmf_confirmation(dword Id, PLCI *plci)
9981 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9982 UnMapId(Id), (char *)(FILE_), __LINE__));
9985 PUT_WORD(&result[1], DTMF_SUCCESS);
9986 if (plci->dtmf_send_requests != 0)
9988 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9989 "wws", GOOD, SELECTOR_DTMF, result);
9990 (plci->dtmf_send_requests)--;
9991 for (i = 0; i < plci->dtmf_send_requests; i++)
9992 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
9997 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10001 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10002 UnMapId(Id), (char *)(FILE_), __LINE__));
10005 for (i = 1; i < length; i++)
10008 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10009 && ((msg[i] != dtmf_digit_map[j].code)
10010 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10014 if (j < DTMF_DIGIT_MAP_ENTRIES)
10017 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10018 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10019 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10023 for (i = length; i > n + 1; i--)
10024 msg[i] = msg[i - 1];
10028 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10030 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10032 msg[++n] = dtmf_digit_map[j].character;
10038 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10043 /*------------------------------------------------------------------*/
10044 /* DTMF parameters */
10045 /*------------------------------------------------------------------*/
10047 static void dtmf_parameter_write(PLCI *plci)
10050 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10052 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10053 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10054 (char *)(FILE_), __LINE__));
10056 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10057 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10058 for (i = 0; i < plci->dtmf_parameter_length; i++)
10059 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10060 add_p(plci, FTY, parameter_buffer);
10061 sig_req(plci, TEL_CTRL, 0);
10066 static void dtmf_parameter_clear_config(PLCI *plci)
10069 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10070 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10071 (char *)(FILE_), __LINE__));
10073 plci->dtmf_parameter_length = 0;
10077 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10080 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10081 UnMapId(Id), (char *)(FILE_), __LINE__));
10086 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10089 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10090 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10096 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10100 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10101 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10104 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10105 && (plci->dtmf_parameter_length != 0))
10107 switch (plci->adjust_b_state)
10109 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10110 plci->internal_command = plci->adjust_b_command;
10113 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10116 dtmf_parameter_write(plci);
10117 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10119 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10120 if ((Rc != OK) && (Rc != OK_FC))
10122 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10123 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10124 Info = _WRONG_STATE;
10134 /*------------------------------------------------------------------*/
10135 /* Line interconnect facilities */
10136 /*------------------------------------------------------------------*/
10139 LI_CONFIG *li_config_table;
10140 word li_total_channels;
10143 /*------------------------------------------------------------------*/
10144 /* translate a CHI information element to a channel number */
10145 /* returns 0xff - any channel */
10146 /* 0xfe - chi wrong coding */
10147 /* 0xfd - D-channel */
10148 /* 0x00 - no channel */
10149 /* else channel number / PRI: timeslot */
10150 /* if channels is provided we accept more than one channel. */
10151 /*------------------------------------------------------------------*/
10153 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10162 if (pchannelmap) *pchannelmap = 0;
10163 if (!chi[0]) return 0xff;
10166 if (chi[1] & 0x20) {
10167 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10168 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10169 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10170 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10171 if (chi[1] & 0x08) excl = 0x40;
10173 /* int. id present */
10174 if (chi[1] & 0x40) {
10176 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10177 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10180 /* coding standard, Number/Map, Channel Type */
10182 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10183 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10184 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10187 if (chi[p] & 0x10) {
10190 if ((chi[0] - p) == 4) ofs = 0;
10191 else if ((chi[0] - p) == 3) ofs = 1;
10195 for (i = 0; i < 4 && p < chi[0]; i++) {
10200 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10211 ch = chi[p] & 0x3f;
10213 if ((byte)(chi[0] - p) > 30) return 0xfe;
10215 for (i = p; i <= chi[0]; i++) {
10216 if ((chi[i] & 0x7f) > 31) return 0xfe;
10217 map |= (1L << (chi[i] & 0x7f));
10221 if (p != chi[0]) return 0xfe;
10222 if (ch > 31) return 0xfe;
10225 if (chi[p] & 0x40) return 0xfe;
10227 if (pchannelmap) *pchannelmap = map;
10228 else if (map != ((dword)(1L << ch))) return 0xfe;
10229 return (byte)(excl | ch);
10231 else { /* not PRI */
10232 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10233 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10234 if (chi[1] & 0x08) excl = 0x40;
10236 switch (chi[1] | 0x98) {
10237 case 0x98: return 0;
10239 if (pchannelmap) *pchannelmap = 2;
10242 if (pchannelmap) *pchannelmap = 4;
10244 case 0x9b: return 0xff;
10245 case 0x9c: return 0xfd; /* d-ch */
10246 default: return 0xfe;
10252 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10254 DIVA_CAPI_ADAPTER *a;
10259 old_id = plci->li_bchannel_id;
10262 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10263 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10264 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10265 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10266 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10270 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10272 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10273 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10274 plci->li_bchannel_id = bchannel_id & 0x03;
10275 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10277 splci = a->AdvSignalPLCI;
10278 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10280 if ((splci->li_bchannel_id != 0)
10281 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10283 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10285 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10286 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10287 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10288 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10289 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10292 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10293 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10296 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10297 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10299 mixer_clear_config(plci);
10301 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10302 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10303 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10307 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10309 DIVA_CAPI_ADAPTER *a;
10314 old_id = plci->li_bchannel_id;
10315 ch = chi_to_channel(chi, NULL);
10320 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10321 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10322 plci->li_bchannel_id = (ch & 0x1f) + 1;
10323 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10324 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10328 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10330 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10331 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10332 plci->li_bchannel_id = ch & 0x1f;
10333 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10335 splci = a->AdvSignalPLCI;
10336 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10338 if ((splci->li_bchannel_id != 0)
10339 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10341 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10343 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10344 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10345 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10346 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10347 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10350 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10351 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10355 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10356 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10358 mixer_clear_config(plci);
10360 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10361 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10362 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10366 #define MIXER_MAX_DUMP_CHANNELS 34
10368 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10372 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10374 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10375 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10377 for (i = 0; i < li_total_channels; i++)
10379 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10380 if (li_config_table[i].chflags != 0)
10381 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10384 for (j = 0; j < li_total_channels; j++)
10386 if (((li_config_table[i].flag_table[j]) != 0)
10387 || ((li_config_table[j].flag_table[i]) != 0))
10389 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10391 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10392 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10394 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10399 for (i = 0; i < li_total_channels; i++)
10401 for (j = 0; j < li_total_channels; j++)
10403 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10404 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10405 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10408 for (n = 0; n < li_total_channels; n++)
10410 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10412 for (i = 0; i < li_total_channels; i++)
10414 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10416 for (j = 0; j < li_total_channels; j++)
10418 li_config_table[i].coef_table[j] |=
10419 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10425 for (i = 0; i < li_total_channels; i++)
10427 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10429 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10430 for (j = 0; j < li_total_channels; j++)
10432 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10433 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10435 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10436 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10439 for (i = 0; i < li_total_channels; i++)
10441 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10443 for (j = 0; j < li_total_channels; j++)
10445 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10446 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10447 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10448 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10449 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10450 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10451 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10452 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10454 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10456 for (j = 0; j < li_total_channels; j++)
10458 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10460 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10461 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10462 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10466 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10468 for (j = 0; j < li_total_channels; j++)
10470 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10471 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10474 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10476 for (j = 0; j < li_total_channels; j++)
10478 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10480 for (n = 0; n < li_total_channels; n++)
10482 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10484 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10485 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10487 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10488 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10489 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10491 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10492 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10500 for (i = 0; i < li_total_channels; i++)
10502 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10504 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10505 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10506 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10507 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10508 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10509 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10510 for (j = 0; j < li_total_channels; j++)
10512 if ((li_config_table[i].flag_table[j] &
10513 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10514 || (li_config_table[j].flag_table[i] &
10515 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10517 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10519 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10520 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10521 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10522 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10524 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10526 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10527 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10531 for (i = 0; i < li_total_channels; i++)
10533 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10536 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10538 if (j < li_total_channels)
10540 for (j = 0; j < li_total_channels; j++)
10542 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10543 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10544 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10549 n = li_total_channels;
10550 if (n > MIXER_MAX_DUMP_CHANNELS)
10551 n = MIXER_MAX_DUMP_CHANNELS;
10554 for (j = 0; j < n; j++)
10556 if ((j & 0x7) == 0)
10558 p = hex_byte_pack(p, li_config_table[j].curchnl);
10561 dbug(1, dprintf("[%06lx] CURRENT %s",
10562 (dword)(UnMapController(a->Id)), (char *)hex_line));
10564 for (j = 0; j < n; j++)
10566 if ((j & 0x7) == 0)
10568 p = hex_byte_pack(p, li_config_table[j].channel);
10571 dbug(1, dprintf("[%06lx] CHANNEL %s",
10572 (dword)(UnMapController(a->Id)), (char *)hex_line));
10574 for (j = 0; j < n; j++)
10576 if ((j & 0x7) == 0)
10578 p = hex_byte_pack(p, li_config_table[j].chflags);
10581 dbug(1, dprintf("[%06lx] CHFLAG %s",
10582 (dword)(UnMapController(a->Id)), (char *)hex_line));
10583 for (i = 0; i < n; i++)
10586 for (j = 0; j < n; j++)
10588 if ((j & 0x7) == 0)
10590 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10593 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10594 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10596 for (i = 0; i < n; i++)
10599 for (j = 0; j < n; j++)
10601 if ((j & 0x7) == 0)
10603 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10606 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10607 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10616 } mixer_write_prog_pri[] =
10618 { LI_COEF_CH_CH, 0 },
10619 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10620 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10621 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10629 byte xconnect_override;
10630 } mixer_write_prog_bri[] =
10632 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10633 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10634 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10635 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10636 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10637 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10638 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10639 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10640 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10641 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10642 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10643 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10644 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10645 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10646 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10647 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10648 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10649 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10650 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10651 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10652 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10653 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10654 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10655 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10656 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10657 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10658 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10659 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10660 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10661 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10662 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10663 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10664 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10665 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10666 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10667 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10670 static byte mixer_swapped_index_bri[] =
10673 19, /* Alt B to B */
10675 21, /* Alt PC to B */
10677 23, /* Alt IC to B */
10679 25, /* Alt B to PC */
10681 27, /* Alt PC to PC */
10683 29, /* Alt IC to PC */
10685 31, /* Alt B to IC */
10687 33, /* Alt PC to IC */
10689 35, /* Alt IC to IC */
10690 0, /* Alt B to Alt B */
10691 1, /* B to Alt B */
10692 2, /* Alt PC to Alt B */
10693 3, /* PC to Alt B */
10694 4, /* Alt IC to Alt B */
10695 5, /* IC to Alt B */
10696 6, /* Alt B to Alt PC */
10697 7, /* B to Alt PC */
10698 8, /* Alt PC to Alt PC */
10699 9, /* PC to Alt PC */
10700 10, /* Alt IC to Alt PC */
10701 11, /* IC to Alt PC */
10702 12, /* Alt B to Alt IC */
10703 13, /* B to Alt IC */
10704 14, /* Alt PC to Alt IC */
10705 15, /* PC to Alt IC */
10706 16, /* Alt IC to Alt IC */
10707 17 /* IC to Alt IC */
10715 } xconnect_write_prog[] =
10717 { LI_COEF_CH_CH, false, false },
10718 { LI_COEF_CH_PC, false, true },
10719 { LI_COEF_PC_CH, true, false },
10720 { LI_COEF_PC_PC, true, true }
10724 static void xconnect_query_addresses(PLCI *plci)
10726 DIVA_CAPI_ADAPTER *a;
10730 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10731 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10732 (char *)(FILE_), __LINE__));
10735 if (a->li_pri && ((plci->li_bchannel_id == 0)
10736 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10738 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10739 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10740 (char *)(FILE_), __LINE__));
10743 p = plci->internal_req_buffer;
10744 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10745 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10748 *(p++) = (byte)(w >> 8);
10749 w = ch | XCONNECT_CHANNEL_PORT_PC;
10751 *(p++) = (byte)(w >> 8);
10752 plci->NData[0].P = plci->internal_req_buffer;
10753 plci->NData[0].PLength = p - plci->internal_req_buffer;
10754 plci->NL.X = plci->NData;
10755 plci->NL.ReqCh = 0;
10756 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10757 plci->adapter->request(&plci->NL);
10761 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10764 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10765 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10766 (char *)(FILE_), __LINE__, internal_command));
10768 plci->li_write_command = internal_command;
10769 plci->li_write_channel = 0;
10773 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10775 DIVA_CAPI_ADAPTER *a;
10776 word w, n, i, j, r, s, to_ch;
10779 struct xconnect_transfer_address_s *transfer_address;
10780 byte ch_map[MIXER_CHANNELS_BRI];
10782 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10783 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10786 if ((plci->li_bchannel_id == 0)
10787 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10789 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10790 UnMapId(Id), (char *)(FILE_), __LINE__));
10793 i = a->li_base + (plci->li_bchannel_id - 1);
10794 j = plci->li_write_channel;
10795 p = plci->internal_req_buffer;
10798 if ((Rc != OK) && (Rc != OK_FC))
10800 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10801 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10805 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10809 if (j < li_total_channels)
10811 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10813 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10814 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10815 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10816 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10818 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10819 while ((j < li_total_channels)
10821 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10822 || (!li_config_table[j].adapter->li_pri
10823 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10824 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10825 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10826 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10827 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10828 || ((li_config_table[j].adapter->li_base != a->li_base)
10830 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10831 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10832 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10833 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10836 if (j < li_total_channels)
10837 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10840 if (j < li_total_channels)
10842 plci->internal_command = plci->li_write_command;
10843 if (plci_nl_busy(plci))
10845 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10846 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10849 if (li_config_table[j].adapter->li_base != a->li_base)
10852 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10853 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10854 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10855 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10860 if (r & xconnect_write_prog[n].mask)
10862 if (xconnect_write_prog[n].from_pc)
10863 transfer_address = &(li_config_table[j].send_pc);
10865 transfer_address = &(li_config_table[j].send_b);
10866 d = transfer_address->card_address.low;
10868 *(p++) = (byte)(d >> 8);
10869 *(p++) = (byte)(d >> 16);
10870 *(p++) = (byte)(d >> 24);
10871 d = transfer_address->card_address.high;
10873 *(p++) = (byte)(d >> 8);
10874 *(p++) = (byte)(d >> 16);
10875 *(p++) = (byte)(d >> 24);
10876 d = transfer_address->offset;
10878 *(p++) = (byte)(d >> 8);
10879 *(p++) = (byte)(d >> 16);
10880 *(p++) = (byte)(d >> 24);
10881 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10883 *(p++) = (byte)(w >> 8);
10884 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10885 (li_config_table[i].adapter->u_law ?
10886 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10887 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10890 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10893 } while ((n < ARRAY_SIZE(xconnect_write_prog))
10894 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10895 if (n == ARRAY_SIZE(xconnect_write_prog))
10900 if (j < li_total_channels)
10901 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10902 } while ((j < li_total_channels)
10904 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10905 || (!li_config_table[j].adapter->li_pri
10906 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10907 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10908 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10909 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10910 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10911 || ((li_config_table[j].adapter->li_base != a->li_base)
10913 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10914 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10915 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10916 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10918 } while ((j < li_total_channels)
10919 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10921 else if (j == li_total_channels)
10923 plci->internal_command = plci->li_write_command;
10924 if (plci_nl_busy(plci))
10928 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10930 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10931 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10932 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10933 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10935 *(p++) = (byte)(w >> 8);
10939 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10941 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10942 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10944 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10946 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10947 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10948 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10949 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10951 *(p++) = (byte)(w >> 8);
10952 for (j = 0; j < sizeof(ch_map); j += 2)
10954 if (plci->li_bchannel_id == 2)
10956 ch_map[j] = (byte)(j + 1);
10957 ch_map[j + 1] = (byte) j;
10961 ch_map[j] = (byte) j;
10962 ch_map[j + 1] = (byte)(j + 1);
10965 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10967 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10968 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10969 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10971 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10972 mixer_write_prog_bri[n].xconnect_override :
10973 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10974 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10976 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10977 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10983 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10985 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10986 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10987 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10993 j = li_total_channels + 1;
10998 if (j <= li_total_channels)
11000 plci->internal_command = plci->li_write_command;
11001 if (plci_nl_busy(plci))
11003 if (j < a->li_base)
11007 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11009 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11010 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11011 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11012 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11014 *(p++) = (byte)(w >> 8);
11015 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11017 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11018 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11020 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11021 if (w & mixer_write_prog_pri[n].mask)
11023 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11024 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11029 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11030 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11032 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11033 if (w & mixer_write_prog_pri[n].mask)
11035 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11036 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11045 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11047 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11048 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11050 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11052 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11053 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11054 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11055 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11057 *(p++) = (byte)(w >> 8);
11058 for (j = 0; j < sizeof(ch_map); j += 2)
11060 if (plci->li_bchannel_id == 2)
11062 ch_map[j] = (byte)(j + 1);
11063 ch_map[j + 1] = (byte) j;
11067 ch_map[j] = (byte) j;
11068 ch_map[j + 1] = (byte)(j + 1);
11071 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11073 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11074 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11075 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11077 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11078 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11079 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11084 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11086 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11087 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11088 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11094 j = li_total_channels + 1;
11097 plci->li_write_channel = j;
11098 if (p != plci->internal_req_buffer)
11100 plci->NData[0].P = plci->internal_req_buffer;
11101 plci->NData[0].PLength = p - plci->internal_req_buffer;
11102 plci->NL.X = plci->NData;
11103 plci->NL.ReqCh = 0;
11104 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11105 plci->adapter->request(&plci->NL);
11111 static void mixer_notify_update(PLCI *plci, byte others)
11113 DIVA_CAPI_ADAPTER *a;
11116 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11118 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11119 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11120 (char *)(FILE_), __LINE__, others));
11123 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11126 plci->li_notify_update = true;
11130 notify_plci = NULL;
11133 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11135 if (i < li_total_channels)
11136 notify_plci = li_config_table[i++].plci;
11140 if ((plci->li_bchannel_id != 0)
11141 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11143 notify_plci = plci;
11146 if ((notify_plci != NULL)
11147 && !notify_plci->li_notify_update
11148 && (notify_plci->appl != NULL)
11149 && (notify_plci->State)
11150 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11152 notify_plci->li_notify_update = true;
11153 ((CAPI_MSG *) msg)->header.length = 18;
11154 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11155 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11156 ((CAPI_MSG *) msg)->header.number = 0;
11157 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11158 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11159 ((CAPI_MSG *) msg)->header.ncci = 0;
11160 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11161 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11162 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11163 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11164 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11165 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11166 if (w != _QUEUE_FULL)
11170 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11171 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11172 (char *)(FILE_), __LINE__,
11173 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11175 notify_plci->li_notify_update = false;
11178 } while (others && (notify_plci != NULL));
11180 plci->li_notify_update = false;
11185 static void mixer_clear_config(PLCI *plci)
11187 DIVA_CAPI_ADAPTER *a;
11190 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11191 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11192 (char *)(FILE_), __LINE__));
11194 plci->li_notify_update = false;
11195 plci->li_plci_b_write_pos = 0;
11196 plci->li_plci_b_read_pos = 0;
11197 plci->li_plci_b_req_pos = 0;
11199 if ((plci->li_bchannel_id != 0)
11200 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11202 i = a->li_base + (plci->li_bchannel_id - 1);
11203 li_config_table[i].curchnl = 0;
11204 li_config_table[i].channel = 0;
11205 li_config_table[i].chflags = 0;
11206 for (j = 0; j < li_total_channels; j++)
11208 li_config_table[j].flag_table[i] = 0;
11209 li_config_table[i].flag_table[j] = 0;
11210 li_config_table[i].coef_table[j] = 0;
11211 li_config_table[j].coef_table[i] = 0;
11215 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11216 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11218 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11219 li_config_table[i].curchnl = 0;
11220 li_config_table[i].channel = 0;
11221 li_config_table[i].chflags = 0;
11222 for (j = 0; j < li_total_channels; j++)
11224 li_config_table[i].flag_table[j] = 0;
11225 li_config_table[j].flag_table[i] = 0;
11226 li_config_table[i].coef_table[j] = 0;
11227 li_config_table[j].coef_table[i] = 0;
11229 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11231 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11232 li_config_table[i].curchnl = 0;
11233 li_config_table[i].channel = 0;
11234 li_config_table[i].chflags = 0;
11235 for (j = 0; j < li_total_channels; j++)
11237 li_config_table[i].flag_table[j] = 0;
11238 li_config_table[j].flag_table[i] = 0;
11239 li_config_table[i].coef_table[j] = 0;
11240 li_config_table[j].coef_table[i] = 0;
11249 static void mixer_prepare_switch(dword Id, PLCI *plci)
11252 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11253 UnMapId(Id), (char *)(FILE_), __LINE__));
11257 mixer_indication_coefs_set(Id, plci);
11258 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11262 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11264 DIVA_CAPI_ADAPTER *a;
11267 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11268 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11271 if ((plci->li_bchannel_id != 0)
11272 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11274 i = a->li_base + (plci->li_bchannel_id - 1);
11275 for (j = 0; j < li_total_channels; j++)
11277 li_config_table[i].coef_table[j] &= 0xf;
11278 li_config_table[j].coef_table[i] &= 0xf;
11281 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11287 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11289 DIVA_CAPI_ADAPTER *a;
11292 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11293 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11297 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11298 && (plci->li_bchannel_id != 0)
11299 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11301 switch (plci->adjust_b_state)
11303 case ADJUST_B_RESTORE_MIXER_1:
11304 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11306 plci->internal_command = plci->adjust_b_command;
11307 if (plci_nl_busy(plci))
11309 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11312 xconnect_query_addresses(plci);
11313 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11316 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11318 case ADJUST_B_RESTORE_MIXER_2:
11319 case ADJUST_B_RESTORE_MIXER_3:
11320 case ADJUST_B_RESTORE_MIXER_4:
11321 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11323 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11324 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11325 Info = _WRONG_STATE;
11330 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11331 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11332 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11333 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11337 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11338 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11339 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11340 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11342 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11344 plci->internal_command = plci->adjust_b_command;
11347 case ADJUST_B_RESTORE_MIXER_5:
11348 xconnect_write_coefs(plci, plci->adjust_b_command);
11349 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11351 case ADJUST_B_RESTORE_MIXER_6:
11352 if (!xconnect_write_coefs_process(Id, plci, Rc))
11354 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11355 UnMapId(Id), (char *)(FILE_), __LINE__));
11356 Info = _FACILITY_NOT_SUPPORTED;
11359 if (plci->internal_command)
11361 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11362 case ADJUST_B_RESTORE_MIXER_7:
11370 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11372 DIVA_CAPI_ADAPTER *a;
11373 word i, internal_command;
11375 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11376 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11380 internal_command = plci->internal_command;
11381 plci->internal_command = 0;
11382 switch (plci->li_cmd)
11384 case LI_REQ_CONNECT:
11385 case LI_REQ_DISCONNECT:
11386 case LI_REQ_SILENT_UPDATE:
11387 switch (internal_command)
11390 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11392 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11393 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11395 case MIXER_COMMAND_1:
11396 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11398 if (adjust_b_process(Id, plci, Rc) != GOOD)
11400 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11401 UnMapId(Id), (char *)(FILE_), __LINE__));
11404 if (plci->internal_command)
11407 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11408 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11409 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11410 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11411 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11413 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11419 mixer_indication_coefs_set(Id, plci);
11420 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11422 case MIXER_COMMAND_2:
11423 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11424 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11425 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11426 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11428 if (!xconnect_write_coefs_process(Id, plci, Rc))
11430 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11431 UnMapId(Id), (char *)(FILE_), __LINE__));
11432 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11436 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11437 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11438 i = (plci->li_plci_b_write_pos == 0) ?
11439 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11440 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11441 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11445 if (plci->internal_command)
11448 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11450 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11451 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11453 case MIXER_COMMAND_3:
11454 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11456 if (adjust_b_process(Id, plci, Rc) != GOOD)
11458 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11459 UnMapId(Id), (char *)(FILE_), __LINE__));
11462 if (plci->internal_command)
11469 if ((plci->li_bchannel_id == 0)
11470 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11472 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11473 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11477 i = a->li_base + (plci->li_bchannel_id - 1);
11478 li_config_table[i].curchnl = plci->li_channel_bits;
11479 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11481 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11482 li_config_table[i].curchnl = plci->li_channel_bits;
11483 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11485 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11486 li_config_table[i].curchnl = plci->li_channel_bits;
11493 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11494 dword plci_b_id, byte connect, dword li_flags)
11496 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11498 DIVA_CAPI_ADAPTER *a_b;
11500 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11501 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11502 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11503 if (!a->li_pri && (plci->tel == ADV_VOICE)
11504 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11506 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11507 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11508 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11515 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11516 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11517 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11519 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11520 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11521 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11530 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11531 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11532 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11533 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11535 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11536 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11537 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11538 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11539 if (ch_a_v == ch_b_v)
11541 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11542 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11546 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11548 for (i = 0; i < li_total_channels; i++)
11551 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11554 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11556 for (i = 0; i < li_total_channels; i++)
11559 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11562 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11564 for (i = 0; i < li_total_channels; i++)
11567 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11570 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11572 for (i = 0; i < li_total_channels; i++)
11575 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11579 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11581 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11582 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11583 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11584 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11586 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11588 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11589 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11590 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11591 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11593 if (li_flags & LI_FLAG_MONITOR_A)
11595 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11596 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11598 if (li_flags & LI_FLAG_MONITOR_B)
11600 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11601 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11603 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11605 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11606 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11608 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11610 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11611 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11613 if (li_flags & LI_FLAG_MIX_A)
11615 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11616 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11618 if (li_flags & LI_FLAG_MIX_B)
11620 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11621 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11623 if (ch_a_v != ch_a_s)
11625 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11626 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11628 if (ch_b_v != ch_b_s)
11630 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11631 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11636 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11637 dword plci_b_id, byte connect, dword li_flags)
11639 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11641 DIVA_CAPI_ADAPTER *a_b;
11643 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11644 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11645 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11646 if (!a->li_pri && (plci->tel == ADV_VOICE)
11647 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11649 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11650 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11651 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11658 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11659 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11660 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11662 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11663 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11664 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11673 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11676 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11677 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11678 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11680 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11681 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11682 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11683 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11684 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11685 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11686 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11687 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11688 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11690 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11691 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11692 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11693 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11695 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11697 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11698 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11699 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11700 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11702 if (li_flags & LI2_FLAG_MONITOR_B)
11704 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11705 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11707 if (li_flags & LI2_FLAG_MIX_B)
11709 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11710 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11712 if (li_flags & LI2_FLAG_MONITOR_X)
11713 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11714 if (li_flags & LI2_FLAG_MIX_X)
11715 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11716 if (li_flags & LI2_FLAG_LOOP_B)
11718 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11719 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11720 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11721 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11723 if (li_flags & LI2_FLAG_LOOP_PC)
11724 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11725 if (li_flags & LI2_FLAG_LOOP_X)
11726 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11727 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11728 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11729 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11730 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11731 if (ch_a_v != ch_a_s)
11733 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11734 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11736 if (ch_b_v != ch_b_s)
11738 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11739 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11744 static word li_check_main_plci(dword Id, PLCI *plci)
11748 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11749 UnMapId(Id), (char *)(FILE_), __LINE__));
11750 return (_WRONG_IDENTIFIER);
11753 || !plci->NL.Id || plci->nl_remove_id
11754 || (plci->li_bchannel_id == 0))
11756 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11757 UnMapId(Id), (char *)(FILE_), __LINE__));
11758 return (_WRONG_STATE);
11760 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11765 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11766 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11771 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11772 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11774 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11775 UnMapId(Id), (char *)(FILE_), __LINE__));
11776 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11780 if ((plci_b_id & 0x7f) != 0)
11782 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11783 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11787 || (((plci_b_id >> 8) & 0xff) == 0)
11788 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11790 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11791 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11792 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11795 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11797 || !plci_b->NL.Id || plci_b->nl_remove_id
11798 || (plci_b->li_bchannel_id == 0))
11800 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11801 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11802 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11805 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11806 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11807 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11808 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11809 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11811 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11812 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11813 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11816 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11817 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11819 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11820 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11821 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11828 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11829 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11834 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11835 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11837 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11838 UnMapId(Id), (char *)(FILE_), __LINE__));
11839 PUT_WORD(p_result, _WRONG_STATE);
11843 if ((plci_b_id & 0x7f) != 0)
11845 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11846 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11850 || (((plci_b_id >> 8) & 0xff) == 0)
11851 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11853 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11854 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11855 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11858 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11860 || !plci_b->NL.Id || plci_b->nl_remove_id
11861 || (plci_b->li_bchannel_id == 0)
11862 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11864 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11865 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11866 PUT_WORD(p_result, _WRONG_STATE);
11869 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11870 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11871 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11872 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11874 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11875 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11876 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11879 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11880 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11882 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11883 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11884 PUT_WORD(p_result, _WRONG_STATE);
11891 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
11895 dword d, li_flags, plci_b_id;
11897 API_PARSE li_parms[3];
11898 API_PARSE li_req_parms[3];
11899 API_PARSE li_participant_struct[2];
11900 API_PARSE li_participant_parms[3];
11901 word participant_parms_pos;
11902 byte result_buffer[32];
11905 word plci_b_write_pos;
11907 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11908 UnMapId(Id), (char *)(FILE_), __LINE__));
11911 result = result_buffer;
11912 result_buffer[0] = 0;
11913 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11915 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11916 UnMapId(Id), (char *)(FILE_), __LINE__));
11917 Info = _FACILITY_NOT_SUPPORTED;
11919 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11921 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11922 UnMapId(Id), (char *)(FILE_), __LINE__));
11923 Info = _WRONG_MESSAGE_FORMAT;
11927 result_buffer[0] = 3;
11928 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11929 result_buffer[3] = 0;
11930 switch (GET_WORD(li_parms[0].info))
11932 case LI_GET_SUPPORTED_SERVICES:
11933 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11935 result_buffer[0] = 17;
11936 result_buffer[3] = 14;
11937 PUT_WORD(&result_buffer[4], GOOD);
11939 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11940 d |= LI_CONFERENCING_SUPPORTED;
11941 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11942 d |= LI_MONITORING_SUPPORTED;
11943 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11944 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11945 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946 d |= LI_CROSS_CONTROLLER_SUPPORTED;
11947 PUT_DWORD(&result_buffer[6], d);
11948 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11951 for (i = 0; i < li_total_channels; i++)
11953 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954 && (li_config_table[i].adapter->li_pri
11955 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11963 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11965 PUT_DWORD(&result_buffer[10], d / 2);
11966 PUT_DWORD(&result_buffer[14], d);
11970 result_buffer[0] = 25;
11971 result_buffer[3] = 22;
11972 PUT_WORD(&result_buffer[4], GOOD);
11973 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11974 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11975 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11976 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11977 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11978 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11979 d |= LI2_PC_LOOPING_SUPPORTED;
11980 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11981 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11982 PUT_DWORD(&result_buffer[6], d);
11983 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11984 PUT_DWORD(&result_buffer[10], d / 2);
11985 PUT_DWORD(&result_buffer[14], d - 1);
11986 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11989 for (i = 0; i < li_total_channels; i++)
11991 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11992 && (li_config_table[i].adapter->li_pri
11993 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11999 PUT_DWORD(&result_buffer[18], d / 2);
12000 PUT_DWORD(&result_buffer[22], d - 1);
12004 case LI_REQ_CONNECT:
12005 if (li_parms[1].length == 8)
12007 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12008 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12010 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12011 UnMapId(Id), (char *)(FILE_), __LINE__));
12012 Info = _WRONG_MESSAGE_FORMAT;
12015 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12016 li_flags = GET_DWORD(li_req_parms[1].info);
12017 Info = li_check_main_plci(Id, plci);
12018 result_buffer[0] = 9;
12019 result_buffer[3] = 6;
12020 PUT_DWORD(&result_buffer[4], plci_b_id);
12021 PUT_WORD(&result_buffer[8], GOOD);
12024 result = plci->saved_msg.info;
12025 for (i = 0; i <= result_buffer[0]; i++)
12026 result[i] = result_buffer[i];
12027 plci_b_write_pos = plci->li_plci_b_write_pos;
12028 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12029 if (plci_b == NULL)
12031 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12032 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12033 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12034 plci->li_plci_b_write_pos = plci_b_write_pos;
12038 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12039 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12041 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12042 UnMapId(Id), (char *)(FILE_), __LINE__));
12043 Info = _WRONG_MESSAGE_FORMAT;
12046 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12047 Info = li_check_main_plci(Id, plci);
12048 result_buffer[0] = 7;
12049 result_buffer[3] = 4;
12050 PUT_WORD(&result_buffer[4], Info);
12051 result_buffer[6] = 0;
12054 result = plci->saved_msg.info;
12055 for (i = 0; i <= result_buffer[0]; i++)
12056 result[i] = result_buffer[i];
12057 plci_b_write_pos = plci->li_plci_b_write_pos;
12058 participant_parms_pos = 0;
12060 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12061 while (participant_parms_pos < li_req_parms[1].length)
12063 result[result_pos] = 6;
12065 PUT_DWORD(&result[result_pos - 6], 0);
12066 PUT_WORD(&result[result_pos - 2], GOOD);
12067 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12068 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12070 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12071 UnMapId(Id), (char *)(FILE_), __LINE__));
12072 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12075 if (api_parse(&li_participant_struct[0].info[1],
12076 li_participant_struct[0].length, "dd", li_participant_parms))
12078 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12079 UnMapId(Id), (char *)(FILE_), __LINE__));
12080 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12083 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12084 li_flags = GET_DWORD(li_participant_parms[1].info);
12085 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12086 if (sizeof(result) - result_pos < 7)
12088 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12089 UnMapId(Id), (char *)(FILE_), __LINE__));
12090 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12093 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12094 if (plci_b != NULL)
12096 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12097 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12098 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12099 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12100 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12102 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12103 (&li_req_parms[1].info[1]));
12105 result[0] = (byte)(result_pos - 1);
12106 result[3] = (byte)(result_pos - 4);
12107 result[6] = (byte)(result_pos - 7);
12108 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12109 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12110 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12112 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12113 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12116 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12117 plci->li_plci_b_write_pos = plci_b_write_pos;
12119 mixer_calculate_coefs(a);
12120 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12121 mixer_notify_update(plci, true);
12122 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12123 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12125 plci->li_cmd = GET_WORD(li_parms[0].info);
12126 start_internal_command(Id, plci, mixer_command);
12129 case LI_REQ_DISCONNECT:
12130 if (li_parms[1].length == 4)
12132 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12133 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12135 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12136 UnMapId(Id), (char *)(FILE_), __LINE__));
12137 Info = _WRONG_MESSAGE_FORMAT;
12140 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12141 Info = li_check_main_plci(Id, plci);
12142 result_buffer[0] = 9;
12143 result_buffer[3] = 6;
12144 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12145 PUT_WORD(&result_buffer[8], GOOD);
12148 result = plci->saved_msg.info;
12149 for (i = 0; i <= result_buffer[0]; i++)
12150 result[i] = result_buffer[i];
12151 plci_b_write_pos = plci->li_plci_b_write_pos;
12152 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12153 if (plci_b == NULL)
12155 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12156 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12157 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12158 plci->li_plci_b_write_pos = plci_b_write_pos;
12162 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12163 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12165 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12166 UnMapId(Id), (char *)(FILE_), __LINE__));
12167 Info = _WRONG_MESSAGE_FORMAT;
12170 Info = li_check_main_plci(Id, plci);
12171 result_buffer[0] = 7;
12172 result_buffer[3] = 4;
12173 PUT_WORD(&result_buffer[4], Info);
12174 result_buffer[6] = 0;
12177 result = plci->saved_msg.info;
12178 for (i = 0; i <= result_buffer[0]; i++)
12179 result[i] = result_buffer[i];
12180 plci_b_write_pos = plci->li_plci_b_write_pos;
12181 participant_parms_pos = 0;
12183 while (participant_parms_pos < li_req_parms[0].length)
12185 result[result_pos] = 6;
12187 PUT_DWORD(&result[result_pos - 6], 0);
12188 PUT_WORD(&result[result_pos - 2], GOOD);
12189 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12190 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12192 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12193 UnMapId(Id), (char *)(FILE_), __LINE__));
12194 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12197 if (api_parse(&li_participant_struct[0].info[1],
12198 li_participant_struct[0].length, "d", li_participant_parms))
12200 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12201 UnMapId(Id), (char *)(FILE_), __LINE__));
12202 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12205 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12206 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12207 if (sizeof(result) - result_pos < 7)
12209 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12210 UnMapId(Id), (char *)(FILE_), __LINE__));
12211 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12214 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12215 if (plci_b != NULL)
12217 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12218 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12219 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12221 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12222 (&li_req_parms[0].info[1]));
12224 result[0] = (byte)(result_pos - 1);
12225 result[3] = (byte)(result_pos - 4);
12226 result[6] = (byte)(result_pos - 7);
12227 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12228 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12229 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12231 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12232 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12235 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12236 plci->li_plci_b_write_pos = plci_b_write_pos;
12238 mixer_calculate_coefs(a);
12239 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12240 mixer_notify_update(plci, true);
12241 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12242 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12244 plci->li_cmd = GET_WORD(li_parms[0].info);
12245 start_internal_command(Id, plci, mixer_command);
12248 case LI_REQ_SILENT_UPDATE:
12249 if (!plci || !plci->State
12250 || !plci->NL.Id || plci->nl_remove_id
12251 || (plci->li_bchannel_id == 0)
12252 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12254 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12255 UnMapId(Id), (char *)(FILE_), __LINE__));
12258 plci_b_write_pos = plci->li_plci_b_write_pos;
12259 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12260 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12262 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12263 UnMapId(Id), (char *)(FILE_), __LINE__));
12266 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12267 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12268 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12270 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12271 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12274 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12275 plci->li_plci_b_write_pos = plci_b_write_pos;
12276 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12278 plci->li_cmd = GET_WORD(li_parms[0].info);
12279 start_internal_command(Id, plci, mixer_command);
12283 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12284 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12285 Info = _FACILITY_NOT_SUPPORTED;
12288 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12289 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12294 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12299 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12300 UnMapId(Id), (char *)(FILE_), __LINE__));
12302 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12306 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12307 if (!(d & LI_PLCI_B_SKIP_FLAG))
12309 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12311 if (d & LI_PLCI_B_DISC_FLAG)
12314 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12316 PUT_WORD(&result[4], _LI_USER_INITIATED);
12321 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12323 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12328 if (d & LI_PLCI_B_DISC_FLAG)
12331 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12333 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12334 PUT_WORD(&result[8], _LI_USER_INITIATED);
12339 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12341 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12344 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12345 "ws", SELECTOR_LINE_INTERCONNECT, result);
12347 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12348 0 : plci->li_plci_b_read_pos + 1;
12349 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12354 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12357 struct xconnect_transfer_address_s s, *p;
12358 DIVA_CAPI_ADAPTER *a;
12360 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12361 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12365 for (i = 1; i < length; i += 16)
12367 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12368 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12369 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12370 ch = msg[i + 12] | (msg[i + 13] << 8);
12371 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12372 if (!a->li_pri && (plci->li_bchannel_id == 2))
12375 if (ch & XCONNECT_CHANNEL_PORT_PC)
12376 p = &(li_config_table[j].send_pc);
12378 p = &(li_config_table[j].send_b);
12379 p->card_address.low = s.card_address.low;
12380 p->card_address.high = s.card_address.high;
12381 p->offset = s.offset;
12382 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12384 if (plci->internal_command_queue[0]
12385 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12386 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12387 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12389 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12390 if (!plci->internal_command)
12391 next_internal_command(Id, plci);
12393 mixer_notify_update(plci, true);
12397 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12400 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12401 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12406 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12408 word plci_b_write_pos;
12410 plci_b_write_pos = plci->li_plci_b_write_pos;
12411 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12412 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12414 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12415 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12416 (char *)(FILE_), __LINE__));
12419 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12420 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12421 plci->li_plci_b_write_pos = plci_b_write_pos;
12426 static void mixer_remove(PLCI *plci)
12428 DIVA_CAPI_ADAPTER *a;
12433 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12434 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12435 (char *)(FILE_), __LINE__));
12438 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12439 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12441 if ((plci->li_bchannel_id != 0)
12442 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12444 i = a->li_base + (plci->li_bchannel_id - 1);
12445 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12447 for (j = 0; j < li_total_channels; j++)
12449 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12450 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12452 notify_plci = li_config_table[j].plci;
12453 if ((notify_plci != NULL)
12454 && (notify_plci != plci)
12455 && (notify_plci->appl != NULL)
12456 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12457 && (notify_plci->State)
12458 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12460 mixer_notify_source_removed(notify_plci, plci_b_id);
12464 mixer_clear_config(plci);
12465 mixer_calculate_coefs(a);
12466 mixer_notify_update(plci, true);
12468 li_config_table[i].plci = NULL;
12469 plci->li_bchannel_id = 0;
12475 /*------------------------------------------------------------------*/
12476 /* Echo canceller facilities */
12477 /*------------------------------------------------------------------*/
12480 static void ec_write_parameters(PLCI *plci)
12483 byte parameter_buffer[6];
12485 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12486 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12487 (char *)(FILE_), __LINE__));
12489 parameter_buffer[0] = 5;
12490 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12491 PUT_WORD(¶meter_buffer[2], plci->ec_idi_options);
12492 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12493 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12494 PUT_WORD(¶meter_buffer[4], w);
12495 add_p(plci, FTY, parameter_buffer);
12496 sig_req(plci, TEL_CTRL, 0);
12501 static void ec_clear_config(PLCI *plci)
12504 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12505 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12506 (char *)(FILE_), __LINE__));
12508 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12509 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12510 plci->ec_tail_length = 0;
12514 static void ec_prepare_switch(dword Id, PLCI *plci)
12517 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12518 UnMapId(Id), (char *)(FILE_), __LINE__));
12523 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12526 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12527 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12533 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12537 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12538 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12541 if (plci->B1_facilities & B1_FACILITY_EC)
12543 switch (plci->adjust_b_state)
12545 case ADJUST_B_RESTORE_EC_1:
12546 plci->internal_command = plci->adjust_b_command;
12549 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12552 ec_write_parameters(plci);
12553 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12555 case ADJUST_B_RESTORE_EC_2:
12556 if ((Rc != OK) && (Rc != OK_FC))
12558 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12559 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12560 Info = _WRONG_STATE;
12570 static void ec_command(dword Id, PLCI *plci, byte Rc)
12572 word internal_command, Info;
12575 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12576 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12577 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12580 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12583 PUT_WORD(&result[1], EC_SUCCESS);
12588 PUT_WORD(&result[1], plci->ec_cmd);
12590 PUT_WORD(&result[4], GOOD);
12592 internal_command = plci->internal_command;
12593 plci->internal_command = 0;
12594 switch (plci->ec_cmd)
12596 case EC_ENABLE_OPERATION:
12597 case EC_FREEZE_COEFFICIENTS:
12598 case EC_RESUME_COEFFICIENT_UPDATE:
12599 case EC_RESET_COEFFICIENTS:
12600 switch (internal_command)
12603 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12604 B1_FACILITY_EC), EC_COMMAND_1);
12606 if (adjust_b_process(Id, plci, Rc) != GOOD)
12608 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12609 UnMapId(Id), (char *)(FILE_), __LINE__));
12610 Info = _FACILITY_NOT_SUPPORTED;
12613 if (plci->internal_command)
12618 plci->internal_command = EC_COMMAND_2;
12621 plci->internal_command = EC_COMMAND_3;
12622 ec_write_parameters(plci);
12625 if ((Rc != OK) && (Rc != OK_FC))
12627 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12628 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12629 Info = _FACILITY_NOT_SUPPORTED;
12636 case EC_DISABLE_OPERATION:
12637 switch (internal_command)
12641 if (plci->B1_facilities & B1_FACILITY_EC)
12645 plci->internal_command = EC_COMMAND_1;
12648 plci->internal_command = EC_COMMAND_2;
12649 ec_write_parameters(plci);
12654 if ((Rc != OK) && (Rc != OK_FC))
12656 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12657 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12658 Info = _FACILITY_NOT_SUPPORTED;
12661 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12662 ~B1_FACILITY_EC), EC_COMMAND_3);
12664 if (adjust_b_process(Id, plci, Rc) != GOOD)
12666 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12667 UnMapId(Id), (char *)(FILE_), __LINE__));
12668 Info = _FACILITY_NOT_SUPPORTED;
12671 if (plci->internal_command)
12677 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12678 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12679 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12683 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12687 API_PARSE ec_parms[3];
12690 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12691 UnMapId(Id), (char *)(FILE_), __LINE__));
12695 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12697 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12698 UnMapId(Id), (char *)(FILE_), __LINE__));
12699 Info = _FACILITY_NOT_SUPPORTED;
12703 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12705 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12707 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12708 UnMapId(Id), (char *)(FILE_), __LINE__));
12709 Info = _WRONG_MESSAGE_FORMAT;
12715 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12716 UnMapId(Id), (char *)(FILE_), __LINE__));
12717 Info = _WRONG_IDENTIFIER;
12719 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12721 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12722 UnMapId(Id), (char *)(FILE_), __LINE__));
12723 Info = _WRONG_STATE;
12728 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12729 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12731 PUT_WORD(&result[1], EC_SUCCESS);
12732 if (msg[1].length >= 4)
12734 opt = GET_WORD(&ec_parms[0].info[2]);
12735 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12736 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12737 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12738 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12739 if (opt & EC_DETECT_DISABLE_TONE)
12740 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12741 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12742 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12743 if (msg[1].length >= 6)
12745 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12748 switch (plci->ec_cmd)
12750 case EC_ENABLE_OPERATION:
12751 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12752 start_internal_command(Id, plci, ec_command);
12755 case EC_DISABLE_OPERATION:
12756 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12757 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12758 LEC_RESET_COEFFICIENTS;
12759 start_internal_command(Id, plci, ec_command);
12762 case EC_FREEZE_COEFFICIENTS:
12763 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12764 start_internal_command(Id, plci, ec_command);
12767 case EC_RESUME_COEFFICIENT_UPDATE:
12768 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12769 start_internal_command(Id, plci, ec_command);
12772 case EC_RESET_COEFFICIENTS:
12773 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12774 start_internal_command(Id, plci, ec_command);
12778 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12779 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12780 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12787 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12789 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12790 UnMapId(Id), (char *)(FILE_), __LINE__));
12791 Info = _WRONG_MESSAGE_FORMAT;
12795 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12798 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12800 PUT_WORD(&result[4], GOOD);
12801 PUT_WORD(&result[6], 0x0007);
12802 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12803 PUT_WORD(&result[10], 0);
12805 else if (plci == NULL)
12807 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12808 UnMapId(Id), (char *)(FILE_), __LINE__));
12809 Info = _WRONG_IDENTIFIER;
12811 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12813 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12814 UnMapId(Id), (char *)(FILE_), __LINE__));
12815 Info = _WRONG_STATE;
12820 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12821 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12823 PUT_WORD(&result[1], plci->ec_cmd);
12825 PUT_WORD(&result[4], GOOD);
12826 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12827 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12828 plci->ec_tail_length = 0;
12829 if (ec_parms[1].length >= 2)
12831 opt = GET_WORD(&ec_parms[1].info[1]);
12832 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12833 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12834 if (opt & EC_DETECT_DISABLE_TONE)
12835 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12836 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12837 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12838 if (ec_parms[1].length >= 4)
12840 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12843 switch (plci->ec_cmd)
12845 case EC_ENABLE_OPERATION:
12846 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12847 start_internal_command(Id, plci, ec_command);
12850 case EC_DISABLE_OPERATION:
12851 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12852 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12853 LEC_RESET_COEFFICIENTS;
12854 start_internal_command(Id, plci, ec_command);
12858 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12859 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12860 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12866 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12867 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12868 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12873 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12877 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12878 UnMapId(Id), (char *)(FILE_), __LINE__));
12880 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12882 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12885 PUT_WORD(&result[1], 0);
12888 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12889 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12891 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12892 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12894 case LEC_DISABLE_RELEASED:
12895 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12902 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12904 PUT_WORD(&result[4], 0);
12907 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12910 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12913 case LEC_DISABLE_RELEASED:
12914 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12918 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12919 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12925 /*------------------------------------------------------------------*/
12926 /* Advanced voice */
12927 /*------------------------------------------------------------------*/
12929 static void adv_voice_write_coefs(PLCI *plci, word write_command)
12931 DIVA_CAPI_ADAPTER *a;
12936 byte ch_map[MIXER_CHANNELS_BRI];
12938 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12940 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12941 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12942 (char *)(FILE_), __LINE__, write_command));
12945 p = coef_buffer + 1;
12946 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12948 while (i + sizeof(word) <= a->adv_voice_coef_length)
12950 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12954 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12956 PUT_WORD(p, 0x8000);
12961 if (!a->li_pri && (plci->li_bchannel_id == 0))
12963 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12965 plci->li_bchannel_id = 1;
12966 li_config_table[a->li_base].plci = plci;
12967 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12968 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12969 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12971 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12973 plci->li_bchannel_id = 2;
12974 li_config_table[a->li_base + 1].plci = plci;
12975 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12976 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12977 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12980 if (!a->li_pri && (plci->li_bchannel_id != 0)
12981 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12983 i = a->li_base + (plci->li_bchannel_id - 1);
12984 switch (write_command)
12986 case ADV_VOICE_WRITE_ACTIVATION:
12987 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
12988 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
12989 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
12991 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12992 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12994 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
12996 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12997 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12998 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
12999 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13001 mixer_calculate_coefs(a);
13002 li_config_table[i].curchnl = li_config_table[i].channel;
13003 li_config_table[j].curchnl = li_config_table[j].channel;
13004 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13005 li_config_table[k].curchnl = li_config_table[k].channel;
13008 case ADV_VOICE_WRITE_DEACTIVATION:
13009 for (j = 0; j < li_total_channels; j++)
13011 li_config_table[i].flag_table[j] = 0;
13012 li_config_table[j].flag_table[i] = 0;
13014 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13015 for (j = 0; j < li_total_channels; j++)
13017 li_config_table[k].flag_table[j] = 0;
13018 li_config_table[j].flag_table[k] = 0;
13020 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13022 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13023 for (j = 0; j < li_total_channels; j++)
13025 li_config_table[k].flag_table[j] = 0;
13026 li_config_table[j].flag_table[k] = 0;
13029 mixer_calculate_coefs(a);
13032 if (plci->B1_facilities & B1_FACILITY_MIXER)
13035 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13036 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13037 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13038 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13039 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13040 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13042 *(p++) = (byte)(w >> 8);
13043 for (j = 0; j < sizeof(ch_map); j += 2)
13045 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13046 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13048 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13050 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13051 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13052 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13054 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13055 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13056 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13060 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13061 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13067 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13068 *(p++) = a->adv_voice_coef_buffer[i];
13074 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13075 *(p++) = a->adv_voice_coef_buffer[i];
13077 coef_buffer[0] = (p - coef_buffer) - 1;
13078 add_p(plci, FTY, coef_buffer);
13079 sig_req(plci, TEL_CTRL, 0);
13084 static void adv_voice_clear_config(PLCI *plci)
13086 DIVA_CAPI_ADAPTER *a;
13091 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13092 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13093 (char *)(FILE_), __LINE__));
13096 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13098 a->adv_voice_coef_length = 0;
13100 if (!a->li_pri && (plci->li_bchannel_id != 0)
13101 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13103 i = a->li_base + (plci->li_bchannel_id - 1);
13104 li_config_table[i].curchnl = 0;
13105 li_config_table[i].channel = 0;
13106 li_config_table[i].chflags = 0;
13107 for (j = 0; j < li_total_channels; j++)
13109 li_config_table[i].flag_table[j] = 0;
13110 li_config_table[j].flag_table[i] = 0;
13111 li_config_table[i].coef_table[j] = 0;
13112 li_config_table[j].coef_table[i] = 0;
13114 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13115 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13116 li_config_table[i].curchnl = 0;
13117 li_config_table[i].channel = 0;
13118 li_config_table[i].chflags = 0;
13119 for (j = 0; j < li_total_channels; j++)
13121 li_config_table[i].flag_table[j] = 0;
13122 li_config_table[j].flag_table[i] = 0;
13123 li_config_table[i].coef_table[j] = 0;
13124 li_config_table[j].coef_table[i] = 0;
13126 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13128 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13129 li_config_table[i].curchnl = 0;
13130 li_config_table[i].channel = 0;
13131 li_config_table[i].chflags = 0;
13132 for (j = 0; j < li_total_channels; j++)
13134 li_config_table[i].flag_table[j] = 0;
13135 li_config_table[j].flag_table[i] = 0;
13136 li_config_table[i].coef_table[j] = 0;
13137 li_config_table[j].coef_table[i] = 0;
13146 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13149 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13150 UnMapId(Id), (char *)(FILE_), __LINE__));
13155 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13158 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13159 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13165 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13167 DIVA_CAPI_ADAPTER *a;
13170 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13171 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13175 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13176 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13178 switch (plci->adjust_b_state)
13180 case ADJUST_B_RESTORE_VOICE_1:
13181 plci->internal_command = plci->adjust_b_command;
13184 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13187 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13188 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13190 case ADJUST_B_RESTORE_VOICE_2:
13191 if ((Rc != OK) && (Rc != OK_FC))
13193 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13194 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13195 Info = _WRONG_STATE;
13207 /*------------------------------------------------------------------*/
13208 /* B1 resource switching */
13209 /*------------------------------------------------------------------*/
13211 static byte b1_facilities_table[] =
13213 0x00, /* 0 No bchannel resources */
13214 0x00, /* 1 Codec (automatic law) */
13215 0x00, /* 2 Codec (A-law) */
13216 0x00, /* 3 Codec (y-law) */
13217 0x00, /* 4 HDLC for X.21 */
13219 0x00, /* 6 External Device 0 */
13220 0x00, /* 7 External Device 1 */
13221 0x00, /* 8 HDLC 56k */
13222 0x00, /* 9 Transparent */
13223 0x00, /* 10 Loopback to network */
13224 0x00, /* 11 Test pattern to net */
13225 0x00, /* 12 Rate adaptation sync */
13226 0x00, /* 13 Rate adaptation async */
13227 0x00, /* 14 R-Interface */
13228 0x00, /* 15 HDLC 128k leased line */
13230 0x00, /* 17 Modem async */
13231 0x00, /* 18 Modem sync HDLC */
13232 0x00, /* 19 V.110 async HDLC */
13233 0x12, /* 20 Adv voice (Trans,mixer) */
13234 0x00, /* 21 Codec connected to IC */
13235 0x0c, /* 22 Trans,DTMF */
13236 0x1e, /* 23 Trans,DTMF+mixer */
13237 0x1f, /* 24 Trans,DTMF+mixer+local */
13238 0x13, /* 25 Trans,mixer+local */
13239 0x12, /* 26 HDLC,mixer */
13240 0x12, /* 27 HDLC 56k,mixer */
13241 0x2c, /* 28 Trans,LEC+DTMF */
13242 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13243 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13244 0x2c, /* 31 RTP,LEC+DTMF */
13245 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13246 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13247 0x00, /* 34 Signaling task */
13248 0x00, /* 35 PIAFS */
13249 0x0c, /* 36 Trans,DTMF+TONE */
13250 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13251 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13255 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13257 word b1_facilities;
13259 b1_facilities = b1_facilities_table[b1_resource];
13260 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13263 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13264 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13267 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13268 b1_facilities |= B1_FACILITY_DTMFX;
13269 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13270 b1_facilities |= B1_FACILITY_DTMFR;
13273 if ((b1_resource == 17) || (b1_resource == 18))
13275 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13276 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13279 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13280 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13281 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13283 return (b1_facilities);
13287 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13291 switch (b1_resource)
13295 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13303 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13321 if (b1_facilities & B1_FACILITY_EC)
13323 if (b1_facilities & B1_FACILITY_LOCAL)
13325 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13331 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13332 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13333 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13335 if (b1_facilities & B1_FACILITY_LOCAL)
13337 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13343 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13344 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13345 || ((b1_facilities & B1_FACILITY_DTMFR)
13346 && ((b1_facilities & B1_FACILITY_MIXER)
13347 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13348 || ((b1_facilities & B1_FACILITY_DTMFX)
13349 && ((b1_facilities & B1_FACILITY_MIXER)
13350 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13352 if (b1_facilities & B1_FACILITY_LOCAL)
13354 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13361 if (b1_facilities & B1_FACILITY_LOCAL)
13363 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13373 if (b1_facilities & B1_FACILITY_LOCAL)
13375 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13384 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13385 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13386 (char *)(FILE_), __LINE__,
13387 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13392 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13394 word removed_facilities;
13396 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13397 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13398 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13399 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13401 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13402 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13404 if (removed_facilities & B1_FACILITY_EC)
13405 ec_clear_config(plci);
13408 if (removed_facilities & B1_FACILITY_DTMFR)
13410 dtmf_rec_clear_config(plci);
13411 dtmf_parameter_clear_config(plci);
13413 if (removed_facilities & B1_FACILITY_DTMFX)
13414 dtmf_send_clear_config(plci);
13417 if (removed_facilities & B1_FACILITY_MIXER)
13418 mixer_clear_config(plci);
13420 if (removed_facilities & B1_FACILITY_VOICE)
13421 adv_voice_clear_config(plci);
13422 plci->B1_facilities = new_b1_facilities;
13426 static void adjust_b_clear(PLCI *plci)
13429 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13430 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13431 (char *)(FILE_), __LINE__));
13433 plci->adjust_b_restore = false;
13437 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13444 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13445 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13448 switch (plci->adjust_b_state)
13450 case ADJUST_B_START:
13451 if ((plci->adjust_b_parms_msg == NULL)
13452 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13453 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13454 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13456 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13457 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13458 if (b1_resource == plci->B1_resource)
13460 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13463 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13465 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13466 UnMapId(Id), (char *)(FILE_), __LINE__,
13467 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13468 Info = _WRONG_STATE;
13472 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13475 mixer_prepare_switch(Id, plci);
13478 dtmf_prepare_switch(Id, plci);
13479 dtmf_parameter_prepare_switch(Id, plci);
13482 ec_prepare_switch(Id, plci);
13484 adv_voice_prepare_switch(Id, plci);
13486 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13488 case ADJUST_B_SAVE_MIXER_1:
13489 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13492 Info = mixer_save_config(Id, plci, Rc);
13493 if ((Info != GOOD) || plci->internal_command)
13497 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13499 case ADJUST_B_SAVE_DTMF_1:
13500 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13503 Info = dtmf_save_config(Id, plci, Rc);
13504 if ((Info != GOOD) || plci->internal_command)
13508 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13509 case ADJUST_B_REMOVE_L23_1:
13510 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13511 && plci->NL.Id && !plci->nl_remove_id)
13513 plci->internal_command = plci->adjust_b_command;
13514 if (plci->adjust_b_ncci != 0)
13516 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13517 while (ncci_ptr->data_pending)
13519 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13520 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13522 while (ncci_ptr->data_ack_pending)
13523 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13525 nl_req_ncci(plci, REMOVE,
13526 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13528 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13531 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13533 case ADJUST_B_REMOVE_L23_2:
13534 if ((Rc != OK) && (Rc != OK_FC))
13536 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13537 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13538 Info = _WRONG_STATE;
13541 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13543 if (plci_nl_busy(plci))
13545 plci->internal_command = plci->adjust_b_command;
13549 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13551 case ADJUST_B_SAVE_EC_1:
13552 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13555 Info = ec_save_config(Id, plci, Rc);
13556 if ((Info != GOOD) || plci->internal_command)
13560 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13562 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13563 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13566 Info = dtmf_parameter_save_config(Id, plci, Rc);
13567 if ((Info != GOOD) || plci->internal_command)
13571 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13573 case ADJUST_B_SAVE_VOICE_1:
13574 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13576 Info = adv_voice_save_config(Id, plci, Rc);
13577 if ((Info != GOOD) || plci->internal_command)
13580 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13581 case ADJUST_B_SWITCH_L1_1:
13582 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13586 plci->internal_command = plci->adjust_b_command;
13589 if (plci->adjust_b_parms_msg != NULL)
13590 api_load_msg(plci->adjust_b_parms_msg, bp);
13592 api_load_msg(&plci->B_protocol, bp);
13593 Info = add_b1(plci, bp,
13594 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13595 plci->adjust_b_facilities);
13598 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13599 UnMapId(Id), (char *)(FILE_), __LINE__,
13600 plci->B1_resource, plci->adjust_b_facilities));
13603 plci->internal_command = plci->adjust_b_command;
13604 sig_req(plci, RESOURCES, 0);
13606 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13609 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13611 case ADJUST_B_SWITCH_L1_2:
13612 if ((Rc != OK) && (Rc != OK_FC))
13614 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13615 UnMapId(Id), (char *)(FILE_), __LINE__,
13616 Rc, plci->B1_resource, plci->adjust_b_facilities));
13617 Info = _WRONG_STATE;
13620 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13622 case ADJUST_B_RESTORE_VOICE_1:
13623 case ADJUST_B_RESTORE_VOICE_2:
13624 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13626 Info = adv_voice_restore_config(Id, plci, Rc);
13627 if ((Info != GOOD) || plci->internal_command)
13630 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13632 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13633 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13634 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13637 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13638 if ((Info != GOOD) || plci->internal_command)
13642 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13644 case ADJUST_B_RESTORE_EC_1:
13645 case ADJUST_B_RESTORE_EC_2:
13646 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13649 Info = ec_restore_config(Id, plci, Rc);
13650 if ((Info != GOOD) || plci->internal_command)
13654 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13655 case ADJUST_B_ASSIGN_L23_1:
13656 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13658 if (plci_nl_busy(plci))
13660 plci->internal_command = plci->adjust_b_command;
13663 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13664 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13665 if (plci->adjust_b_parms_msg != NULL)
13666 api_load_msg(plci->adjust_b_parms_msg, bp);
13668 api_load_msg(&plci->B_protocol, bp);
13669 Info = add_b23(plci, bp);
13672 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13673 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13676 plci->internal_command = plci->adjust_b_command;
13677 nl_req_ncci(plci, ASSIGN, 0);
13679 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13682 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13684 case ADJUST_B_ASSIGN_L23_2:
13685 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13687 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13688 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13689 Info = _WRONG_STATE;
13692 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13694 if (Rc != ASSIGN_OK)
13696 plci->internal_command = plci->adjust_b_command;
13700 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13702 plci->adjust_b_restore = true;
13705 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13706 case ADJUST_B_CONNECT_1:
13707 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13709 plci->internal_command = plci->adjust_b_command;
13710 if (plci_nl_busy(plci))
13712 nl_req_ncci(plci, N_CONNECT, 0);
13714 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13717 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13719 case ADJUST_B_CONNECT_2:
13720 case ADJUST_B_CONNECT_3:
13721 case ADJUST_B_CONNECT_4:
13722 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13724 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13725 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13726 Info = _WRONG_STATE;
13731 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13733 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13734 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13736 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13737 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13738 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13739 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13743 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13744 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13745 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13746 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13748 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13750 plci->internal_command = plci->adjust_b_command;
13754 case ADJUST_B_RESTORE_DTMF_1:
13755 case ADJUST_B_RESTORE_DTMF_2:
13756 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13759 Info = dtmf_restore_config(Id, plci, Rc);
13760 if ((Info != GOOD) || plci->internal_command)
13764 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13766 case ADJUST_B_RESTORE_MIXER_1:
13767 case ADJUST_B_RESTORE_MIXER_2:
13768 case ADJUST_B_RESTORE_MIXER_3:
13769 case ADJUST_B_RESTORE_MIXER_4:
13770 case ADJUST_B_RESTORE_MIXER_5:
13771 case ADJUST_B_RESTORE_MIXER_6:
13772 case ADJUST_B_RESTORE_MIXER_7:
13773 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13776 Info = mixer_restore_config(Id, plci, Rc);
13777 if ((Info != GOOD) || plci->internal_command)
13781 plci->adjust_b_state = ADJUST_B_END;
13789 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13792 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13793 UnMapId(Id), (char *)(FILE_), __LINE__,
13794 plci->B1_resource, b1_facilities));
13796 plci->adjust_b_parms_msg = bp_msg;
13797 plci->adjust_b_facilities = b1_facilities;
13798 plci->adjust_b_command = internal_command;
13799 plci->adjust_b_ncci = (word)(Id >> 16);
13800 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13801 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13803 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13804 plci->adjust_b_state = ADJUST_B_START;
13805 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13806 UnMapId(Id), (char *)(FILE_), __LINE__,
13807 plci->B1_resource, b1_facilities));
13811 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13813 word internal_command;
13815 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13816 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13818 internal_command = plci->internal_command;
13819 plci->internal_command = 0;
13820 switch (internal_command)
13824 if (plci->req_in != 0)
13826 plci->internal_command = ADJUST_B_RESTORE_1;
13830 case ADJUST_B_RESTORE_1:
13831 if ((Rc != OK) && (Rc != OK_FC))
13833 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13834 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13836 plci->adjust_b_parms_msg = NULL;
13837 plci->adjust_b_facilities = plci->B1_facilities;
13838 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13839 plci->adjust_b_ncci = (word)(Id >> 16);
13840 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13841 plci->adjust_b_state = ADJUST_B_START;
13842 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13843 UnMapId(Id), (char *)(FILE_), __LINE__));
13844 case ADJUST_B_RESTORE_2:
13845 if (adjust_b_process(Id, plci, Rc) != GOOD)
13847 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13848 UnMapId(Id), (char *)(FILE_), __LINE__));
13850 if (plci->internal_command)
13857 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13860 word internal_command;
13862 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13863 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13866 internal_command = plci->internal_command;
13867 plci->internal_command = 0;
13868 switch (internal_command)
13872 plci->adjust_b_parms_msg = NULL;
13873 plci->adjust_b_facilities = plci->B1_facilities;
13874 plci->adjust_b_command = RESET_B3_COMMAND_1;
13875 plci->adjust_b_ncci = (word)(Id >> 16);
13876 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13877 plci->adjust_b_state = ADJUST_B_START;
13878 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13879 UnMapId(Id), (char *)(FILE_), __LINE__));
13880 case RESET_B3_COMMAND_1:
13881 Info = adjust_b_process(Id, plci, Rc);
13884 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13885 UnMapId(Id), (char *)(FILE_), __LINE__));
13888 if (plci->internal_command)
13892 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13893 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13897 static void select_b_command(dword Id, PLCI *plci, byte Rc)
13900 word internal_command;
13903 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13904 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13907 internal_command = plci->internal_command;
13908 plci->internal_command = 0;
13909 switch (internal_command)
13913 plci->adjust_b_parms_msg = &plci->saved_msg;
13914 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13915 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13917 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13918 plci->adjust_b_command = SELECT_B_COMMAND_1;
13919 plci->adjust_b_ncci = (word)(Id >> 16);
13920 if (plci->saved_msg.parms[0].length == 0)
13922 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13923 ADJUST_B_MODE_NO_RESOURCE;
13927 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13928 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13930 plci->adjust_b_state = ADJUST_B_START;
13931 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13932 UnMapId(Id), (char *)(FILE_), __LINE__));
13933 case SELECT_B_COMMAND_1:
13934 Info = adjust_b_process(Id, plci, Rc);
13937 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13938 UnMapId(Id), (char *)(FILE_), __LINE__));
13941 if (plci->internal_command)
13943 if (plci->tel == ADV_VOICE)
13947 esc_chi[2] = plci->b_channel;
13948 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13952 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13956 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13958 word internal_command;
13960 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %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 case FAX_CONNECT_ACK_COMMAND_1:
13970 if (plci_nl_busy(plci))
13972 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
13975 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
13976 plci->NData[0].P = plci->fax_connect_info_buffer;
13977 plci->NData[0].PLength = plci->fax_connect_info_length;
13978 plci->NL.X = plci->NData;
13979 plci->NL.ReqCh = 0;
13980 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
13981 plci->adapter->request(&plci->NL);
13983 case FAX_CONNECT_ACK_COMMAND_2:
13984 if ((Rc != OK) && (Rc != OK_FC))
13986 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
13987 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13991 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
13992 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
13994 if (plci->B3_prot == 4)
13995 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
13997 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
13998 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14003 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14005 word internal_command;
14007 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14008 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14010 internal_command = plci->internal_command;
14011 plci->internal_command = 0;
14012 switch (internal_command)
14016 case FAX_EDATA_ACK_COMMAND_1:
14017 if (plci_nl_busy(plci))
14019 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14022 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14023 plci->NData[0].P = plci->fax_connect_info_buffer;
14024 plci->NData[0].PLength = plci->fax_edata_ack_length;
14025 plci->NL.X = plci->NData;
14026 plci->NL.ReqCh = 0;
14027 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14028 plci->adapter->request(&plci->NL);
14030 case FAX_EDATA_ACK_COMMAND_2:
14031 if ((Rc != OK) && (Rc != OK_FC))
14033 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14034 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14041 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14044 word internal_command;
14046 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14047 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050 internal_command = plci->internal_command;
14051 plci->internal_command = 0;
14052 switch (internal_command)
14056 case FAX_CONNECT_INFO_COMMAND_1:
14057 if (plci_nl_busy(plci))
14059 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14062 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14063 plci->NData[0].P = plci->fax_connect_info_buffer;
14064 plci->NData[0].PLength = plci->fax_connect_info_length;
14065 plci->NL.X = plci->NData;
14066 plci->NL.ReqCh = 0;
14067 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14068 plci->adapter->request(&plci->NL);
14070 case FAX_CONNECT_INFO_COMMAND_2:
14071 if ((Rc != OK) && (Rc != OK_FC))
14073 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14074 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14075 Info = _WRONG_STATE;
14078 if (plci_nl_busy(plci))
14080 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14083 plci->command = _CONNECT_B3_R;
14084 nl_req_ncci(plci, N_CONNECT, 0);
14088 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14092 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14095 word internal_command;
14097 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14098 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14101 internal_command = plci->internal_command;
14102 plci->internal_command = 0;
14103 switch (internal_command)
14107 plci->adjust_b_parms_msg = NULL;
14108 plci->adjust_b_facilities = plci->B1_facilities;
14109 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14110 plci->adjust_b_ncci = (word)(Id >> 16);
14111 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14112 plci->adjust_b_state = ADJUST_B_START;
14113 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14114 UnMapId(Id), (char *)(FILE_), __LINE__));
14115 case FAX_ADJUST_B23_COMMAND_1:
14116 Info = adjust_b_process(Id, plci, Rc);
14119 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14120 UnMapId(Id), (char *)(FILE_), __LINE__));
14123 if (plci->internal_command)
14125 case FAX_ADJUST_B23_COMMAND_2:
14126 if (plci_nl_busy(plci))
14128 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14131 plci->command = _CONNECT_B3_R;
14132 nl_req_ncci(plci, N_CONNECT, 0);
14136 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14140 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14142 word internal_command;
14144 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14145 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14147 internal_command = plci->internal_command;
14148 plci->internal_command = 0;
14149 switch (internal_command)
14153 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14155 case FAX_DISCONNECT_COMMAND_1:
14156 case FAX_DISCONNECT_COMMAND_2:
14157 case FAX_DISCONNECT_COMMAND_3:
14158 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14160 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14161 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14166 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14167 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14169 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14174 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14175 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14183 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14186 word internal_command;
14188 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14189 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14192 internal_command = plci->internal_command;
14193 plci->internal_command = 0;
14194 switch (internal_command)
14198 case RTP_CONNECT_B3_REQ_COMMAND_1:
14199 if (plci_nl_busy(plci))
14201 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14204 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14205 nl_req_ncci(plci, N_CONNECT, 0);
14208 case RTP_CONNECT_B3_REQ_COMMAND_2:
14209 if ((Rc != OK) && (Rc != OK_FC))
14211 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14212 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213 Info = _WRONG_STATE;
14216 if (plci_nl_busy(plci))
14218 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14221 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14222 plci->NData[0].PLength = plci->internal_req_buffer[0];
14223 plci->NData[0].P = plci->internal_req_buffer + 1;
14224 plci->NL.X = plci->NData;
14225 plci->NL.ReqCh = 0;
14226 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14227 plci->adapter->request(&plci->NL);
14229 case RTP_CONNECT_B3_REQ_COMMAND_3:
14232 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14236 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14238 word internal_command;
14240 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14241 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14243 internal_command = plci->internal_command;
14244 plci->internal_command = 0;
14245 switch (internal_command)
14249 case RTP_CONNECT_B3_RES_COMMAND_1:
14250 if (plci_nl_busy(plci))
14252 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14255 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14256 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14259 case RTP_CONNECT_B3_RES_COMMAND_2:
14260 if ((Rc != OK) && (Rc != OK_FC))
14262 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14263 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14266 if (plci_nl_busy(plci))
14268 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14271 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14272 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14273 plci->NData[0].PLength = plci->internal_req_buffer[0];
14274 plci->NData[0].P = plci->internal_req_buffer + 1;
14275 plci->NL.X = plci->NData;
14276 plci->NL.ReqCh = 0;
14277 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14278 plci->adapter->request(&plci->NL);
14280 case RTP_CONNECT_B3_RES_COMMAND_3:
14287 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14289 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14291 word internal_command;
14293 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14294 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14297 internal_command = plci->internal_command;
14298 plci->internal_command = 0;
14299 switch (internal_command)
14305 plci->adjust_b_parms_msg = NULL;
14306 plci->adjust_b_facilities = plci->B1_facilities;
14307 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14308 plci->adjust_b_ncci = (word)(Id >> 16);
14309 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14310 plci->adjust_b_state = ADJUST_B_START;
14311 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14312 UnMapId(Id), (char *)(FILE_), __LINE__));
14313 case HOLD_SAVE_COMMAND_1:
14314 Info = adjust_b_process(Id, plci, Rc);
14317 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14318 UnMapId(Id), (char *)(FILE_), __LINE__));
14321 if (plci->internal_command)
14324 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14328 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14330 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14332 word internal_command;
14334 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14335 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14338 internal_command = plci->internal_command;
14339 plci->internal_command = 0;
14340 switch (internal_command)
14344 plci->adjust_b_parms_msg = NULL;
14345 plci->adjust_b_facilities = plci->B1_facilities;
14346 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14347 plci->adjust_b_ncci = (word)(Id >> 16);
14348 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14349 plci->adjust_b_state = ADJUST_B_START;
14350 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14351 UnMapId(Id), (char *)(FILE_), __LINE__));
14352 case RETRIEVE_RESTORE_COMMAND_1:
14353 Info = adjust_b_process(Id, plci, Rc);
14356 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14357 UnMapId(Id), (char *)(FILE_), __LINE__));
14360 if (plci->internal_command)
14363 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14367 static void init_b1_config(PLCI *plci)
14370 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14371 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14372 (char *)(FILE_), __LINE__));
14374 plci->B1_resource = 0;
14375 plci->B1_facilities = 0;
14377 plci->li_bchannel_id = 0;
14378 mixer_clear_config(plci);
14381 ec_clear_config(plci);
14384 dtmf_rec_clear_config(plci);
14385 dtmf_send_clear_config(plci);
14386 dtmf_parameter_clear_config(plci);
14388 adv_voice_clear_config(plci);
14389 adjust_b_clear(plci);
14393 static void clear_b1_config(PLCI *plci)
14396 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14397 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14398 (char *)(FILE_), __LINE__));
14400 adv_voice_clear_config(plci);
14401 adjust_b_clear(plci);
14403 ec_clear_config(plci);
14406 dtmf_rec_clear_config(plci);
14407 dtmf_send_clear_config(plci);
14408 dtmf_parameter_clear_config(plci);
14411 if ((plci->li_bchannel_id != 0)
14412 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14414 mixer_clear_config(plci);
14415 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14416 plci->li_bchannel_id = 0;
14419 plci->B1_resource = 0;
14420 plci->B1_facilities = 0;
14424 /* -----------------------------------------------------------------
14425 XON protocol local helpers
14426 ----------------------------------------------------------------- */
14427 static void channel_flow_control_remove(PLCI *plci) {
14428 DIVA_CAPI_ADAPTER *a = plci->adapter;
14430 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14431 if (a->ch_flow_plci[i] == plci->Id) {
14432 a->ch_flow_plci[i] = 0;
14433 a->ch_flow_control[i] = 0;
14438 static void channel_x_on(PLCI *plci, byte ch) {
14439 DIVA_CAPI_ADAPTER *a = plci->adapter;
14440 if (a->ch_flow_control[ch] & N_XON_SENT) {
14441 a->ch_flow_control[ch] &= ~N_XON_SENT;
14445 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14446 DIVA_CAPI_ADAPTER *a = plci->adapter;
14447 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14448 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14449 a->ch_flow_plci[ch] = plci->Id;
14450 a->ch_flow_control_pending++;
14454 static void channel_request_xon(PLCI *plci, byte ch) {
14455 DIVA_CAPI_ADAPTER *a = plci->adapter;
14457 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14458 a->ch_flow_control[ch] |= N_XON_REQ;
14459 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14460 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14464 static void channel_xmit_extended_xon(PLCI *plci) {
14465 DIVA_CAPI_ADAPTER *a;
14466 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14467 int i, one_requested = 0;
14469 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14473 for (i = 0; i < max_ch; i++) {
14474 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14475 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14476 (plci->Id == a->ch_flow_plci[i])) {
14477 channel_request_xon(plci, (byte)i);
14482 if (one_requested) {
14483 channel_xmit_xon(plci);
14488 Try to xmit next X_ON
14490 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14491 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14494 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14498 if (a->last_flow_control_ch >= max_ch) {
14499 a->last_flow_control_ch = 1;
14501 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14502 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14503 (plci->Id == a->ch_flow_plci[i])) {
14504 a->last_flow_control_ch = i + 1;
14509 for (i = 1; i < a->last_flow_control_ch; i++) {
14510 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14511 (plci->Id == a->ch_flow_plci[i])) {
14512 a->last_flow_control_ch = i + 1;
14520 static void channel_xmit_xon(PLCI *plci) {
14521 DIVA_CAPI_ADAPTER *a = plci->adapter;
14524 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14527 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14530 a->ch_flow_control[ch] &= ~N_XON_REQ;
14531 a->ch_flow_control[ch] |= N_XON_SENT;
14533 plci->NL.Req = plci->nl_req = (byte)N_XON;
14534 plci->NL.ReqCh = ch;
14535 plci->NL.X = plci->NData;
14537 plci->NData[0].P = &plci->RBuffer[0];
14538 plci->NData[0].PLength = 0;
14540 plci->adapter->request(&plci->NL);
14543 static int channel_can_xon(PLCI *plci, byte ch) {
14545 DIVA_CAPI_ADAPTER *a;
14551 APPLptr = plci->appl;
14557 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14559 /* count all buffers within the Application pool */
14560 /* belonging to the same NCCI. XON if a first is */
14564 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14565 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14566 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14568 if ((count > 2) || (Num == 0xffff)) {
14575 /*------------------------------------------------------------------*/
14577 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14584 /**********************************************************************************/
14585 /* function groups the listening applications according to the CIP mask and the */
14586 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14587 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14588 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14589 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14590 /* OS specific part (per adapter). */
14591 /**********************************************************************************/
14592 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14594 word i, j, k, busy, group_found;
14595 dword info_mask_group[MAX_CIP_TYPES];
14596 dword cip_mask_group[MAX_CIP_TYPES];
14597 word appl_number_group_type[MAX_APPL];
14600 /* all APPLs within this inc. call are allowed to dial in */
14601 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14603 if (!a->group_optimization_enabled)
14605 dbug(1, dprintf("No group optimization"));
14609 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14611 for (i = 0; i < MAX_CIP_TYPES; i++)
14613 info_mask_group[i] = 0;
14614 cip_mask_group[i] = 0;
14616 for (i = 0; i < MAX_APPL; i++)
14618 appl_number_group_type[i] = 0;
14620 for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14621 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14622 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14624 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14625 return; /* allow good application unfiltered access */
14628 for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14630 if (application[i].Id && a->CIP_Mask[i])
14632 for (k = 0, busy = false; k < a->max_plci; k++)
14636 auxplci = &a->plci[k];
14637 if (auxplci->appl == &application[i]) {
14638 /* application has a busy PLCI */
14640 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14641 } else if (test_bit(i, plci->c_ind_mask_table)) {
14642 /* application has an incoming call pending */
14644 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14649 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14651 if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14652 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14653 appl_number_group_type[i] = MAX_CIP_TYPES;
14654 group_found = true;
14655 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14657 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14658 { /* is group already present ? */
14659 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14660 group_found = true;
14661 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]));
14663 else if (!info_mask_group[j])
14664 { /* establish a new group */
14665 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14666 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14667 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14668 group_found = true;
14669 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]));
14675 for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14677 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14679 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14681 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14685 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14686 for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14688 if (appl_number_group_type[i] == appl_number_group_type[j])
14690 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14691 /* disable call on other group members */
14692 __clear_bit(j, plci->group_optimization_mask_table);
14693 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14698 else /* application should not get a call */
14700 __clear_bit(i, plci->group_optimization_mask_table);
14708 /* OS notifies the driver about a application Capi_Register */
14709 word CapiRegister(word id)
14711 word i, j, appls_found;
14714 DIVA_CAPI_ADAPTER *a;
14716 for (i = 0, appls_found = 0; i < max_appl; i++)
14718 if (application[i].Id && (application[i].Id != id))
14720 appls_found++; /* an application has been found */
14724 if (appls_found) return true;
14725 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14730 if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14732 if (!appls_found) /* first application does a capi register */
14734 if ((j = get_plci(a))) /* activate L1 of all adapters */
14736 plci = &a->plci[j - 1];
14738 add_p(plci, OAD, "\x01\xfd");
14739 add_p(plci, CAI, "\x01\x80");
14740 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14741 add_p(plci, SHIFT | 6, NULL);
14742 add_p(plci, SIN, "\x02\x00\x00");
14743 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14744 sig_req(plci, ASSIGN, DSIG_ID);
14745 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14746 sig_req(plci, SIG_CTRL, 0);
14756 /*------------------------------------------------------------------*/
14758 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14760 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14763 /* Format of vswitch_t:
14766 2 byte VSWITCH_REQ/VSWITCH_IND
14768 4 word VSwitchcommand
14775 plci->Sig.Ind == NCR_FACILITY
14779 for (i = 0; i < MAX_MULTI_IE; i++)
14781 if (!parms[i][0]) continue;
14782 if (parms[i][0] < 7)
14784 parms[i][0] = 0; /* kill it */
14787 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14788 switch (parms[i][4])
14791 if (!plci->relatedPTYPLCI ||
14792 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14796 /* remember all necessary informations */
14797 if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14801 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14802 { /* first indication after ECT-Request on Consultation Call */
14803 plci->vswitchstate = parms[i][9];
14804 parms[i][9] = 2; /* State */
14805 /* now ask first Call to join */
14807 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14808 { /* Answer of VSWITCH_REQ from first Call */
14809 plci->vswitchstate = parms[i][9];
14810 /* tell consultation call to join
14811 and the protocol capabilities of the first call */
14817 plci->vsprot = parms[i][10]; /* protocol */
14818 plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14819 /* send join request to related PLCI */
14820 parms[i][1] = VSWITCHIE;
14821 parms[i][2] = VSWITCH_REQ;
14823 plci->relatedPTYPLCI->command = 0;
14824 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14825 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14826 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14827 send_req(plci->relatedPTYPLCI);
14831 if (plci->relatedPTYPLCI &&
14832 plci->vswitchstate == 3 &&
14833 plci->relatedPTYPLCI->vswitchstate == 3)
14835 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14836 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14837 send_req(plci->relatedPTYPLCI);
14841 parms[i][0] = 0; /* kill it */
14846 /*------------------------------------------------------------------*/
14848 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14850 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14852 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14856 pReq->xdi_dma_descriptor_operation.Req = 0;
14857 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14859 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14860 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14861 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14862 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14864 e.user[0] = plci->adapter->Id - 1;
14865 plci->adapter->request((ENTITY *)pReq);
14867 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14868 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14869 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14870 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14871 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14873 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14875 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14877 dbug(1, dprintf("dma_alloc failed"));
14882 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14884 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14890 pReq->xdi_dma_descriptor_operation.Req = 0;
14891 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14893 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14894 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
14895 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14896 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14898 e.user[0] = plci->adapter->Id - 1;
14899 plci->adapter->request((ENTITY *)pReq);
14901 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14902 dbug(1, dprintf("dma_free(%d)", nr));
14904 dbug(1, dprintf("dma_free failed (%d)", nr));
14908 /*------------------------------------------------------------------*/