sh_eth: fix EESIPR values for SH77{34|63}
[linux/fpc-iii.git] / drivers / isdn / hardware / eicon / message.c
blob1a1d99704fe694ad2f0c19933fdfc7df89803da9
1 /*
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)
13 any later version.
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.
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter */
55 /* Macrose defined here have only local meaning */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
59 #define DIVA_CAPI_USE_CMA 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
65 CAPI can request to process all return codes self only if:
66 protocol code supports this && xdi supports this
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
70 /*------------------------------------------------------------------*/
71 /* local function prototypes */
72 /*------------------------------------------------------------------*/
74 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
75 static void set_group_ind_mask(PLCI *plci);
76 static void clear_group_ind_mask_bit(PLCI *plci, word b);
77 static byte test_group_ind_mask_bit(PLCI *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL *, CAPI_MSG *);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
86 word api_remove_start(void);
87 void api_remove_complete(void);
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
93 void callback(ENTITY *);
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte **, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
101 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
105 static void nl_ind(PLCI *);
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI *plci, byte code, API_PARSE *p);
135 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
136 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
156 XON protocol helpers
158 static void channel_flow_control_remove(PLCI *plci);
159 static void channel_x_off(PLCI *plci, byte ch, byte flag);
160 static void channel_x_on(PLCI *plci, byte ch);
161 static void channel_request_xon(PLCI *plci, byte ch);
162 static void channel_xmit_xon(PLCI *plci);
163 static int channel_can_xon(PLCI *plci, byte ch);
164 static void channel_xmit_extended_xon(PLCI *plci);
166 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs(PLCI *plci, word write_command);
172 static void adv_voice_clear_config(PLCI *plci);
174 static word get_b1_facilities(PLCI *plci, byte b1_resource);
175 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
181 static void select_b_command(dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config(PLCI *plci);
190 static void clear_b1_config(PLCI *plci);
192 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation(dword Id, PLCI *plci);
195 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write(PLCI *plci);
199 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
201 static void mixer_clear_config(PLCI *plci);
202 static void mixer_notify_update(PLCI *plci, byte others);
203 static void mixer_command(dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove(PLCI *plci);
211 static void ec_command(dword Id, PLCI *plci, byte Rc);
212 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
216 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
220 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor(PLCI *plci, int nr);
223 /*------------------------------------------------------------------*/
224 /* external function prototypes */
225 /*------------------------------------------------------------------*/
227 extern byte MapController(byte);
228 extern byte UnMapController(byte);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void *TransmitBufferSet(APPL *appl, dword ref);
234 void *TransmitBufferGet(APPL *appl, void *p);
235 void TransmitBufferFree(APPL *appl, void *p);
236 void *ReceiveBufferGet(APPL *appl, int Num);
238 int fax_head_line_time(char *buffer);
241 /*------------------------------------------------------------------*/
242 /* Global data definitions */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER *adapter;
247 extern APPL *application;
255 static byte remove_started = false;
256 static PLCI dummy_plci;
259 static struct _ftable {
260 word command;
261 byte *format;
262 byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263 } ftable[] = {
264 {_DATA_B3_R, "dwww", data_b3_req},
265 {_DATA_B3_I | RESPONSE, "w", data_b3_res},
266 {_INFO_R, "ss", info_req},
267 {_INFO_I | RESPONSE, "", info_res},
268 {_CONNECT_R, "wsssssssss", connect_req},
269 {_CONNECT_I | RESPONSE, "wsssss", connect_res},
270 {_CONNECT_ACTIVE_I | RESPONSE, "", connect_a_res},
271 {_DISCONNECT_R, "s", disconnect_req},
272 {_DISCONNECT_I | RESPONSE, "", disconnect_res},
273 {_LISTEN_R, "dddss", listen_req},
274 {_ALERT_R, "s", alert_req},
275 {_FACILITY_R, "ws", facility_req},
276 {_FACILITY_I | RESPONSE, "ws", facility_res},
277 {_CONNECT_B3_R, "s", connect_b3_req},
278 {_CONNECT_B3_I | RESPONSE, "ws", connect_b3_res},
279 {_CONNECT_B3_ACTIVE_I | RESPONSE, "", connect_b3_a_res},
280 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
281 {_DISCONNECT_B3_I | RESPONSE, "", disconnect_b3_res},
282 {_RESET_B3_R, "s", reset_b3_req},
283 {_RESET_B3_I | RESPONSE, "", reset_b3_res},
284 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws", connect_b3_t90_a_res},
285 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "", connect_b3_t90_a_res},
286 {_SELECT_B_REQ, "s", select_b_req},
287 {_MANUFACTURER_R, "dws", manufacturer_req},
288 {_MANUFACTURER_I | RESPONSE, "dws", manufacturer_res},
289 {_MANUFACTURER_I | RESPONSE, "", manufacturer_res}
292 static byte *cip_bc[29][2] = {
293 { "", "" }, /* 0 */
294 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
295 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
296 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
297 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
298 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
299 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
300 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
303 { "", "" }, /* 10 */
304 { "", "" }, /* 11 */
305 { "", "" }, /* 12 */
306 { "", "" }, /* 13 */
307 { "", "" }, /* 14 */
308 { "", "" }, /* 15 */
310 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
311 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
312 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
320 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
322 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
325 static byte *cip_hlc[29] = {
326 "", /* 0 */
327 "", /* 1 */
328 "", /* 2 */
329 "", /* 3 */
330 "", /* 4 */
331 "", /* 5 */
332 "", /* 6 */
333 "", /* 7 */
334 "", /* 8 */
335 "", /* 9 */
336 "", /* 10 */
337 "", /* 11 */
338 "", /* 12 */
339 "", /* 13 */
340 "", /* 14 */
341 "", /* 15 */
343 "\x02\x91\x81", /* 16 */
344 "\x02\x91\x84", /* 17 */
345 "\x02\x91\xa1", /* 18 */
346 "\x02\x91\xa4", /* 19 */
347 "\x02\x91\xa8", /* 20 */
348 "\x02\x91\xb1", /* 21 */
349 "\x02\x91\xb2", /* 22 */
350 "\x02\x91\xb5", /* 23 */
351 "\x02\x91\xb8", /* 24 */
352 "\x02\x91\xc1", /* 25 */
353 "\x02\x91\x81", /* 26 */
354 "\x03\x91\xe0\x01", /* 27 */
355 "\x03\x91\xe0\x02" /* 28 */
358 /*------------------------------------------------------------------*/
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT 0x80
362 #define V120_HEADER_BREAK_BIT 0x40
363 #define V120_HEADER_C1_BIT 0x04
364 #define V120_HEADER_C2_BIT 0x08
365 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
367 static byte v120_default_header[] =
370 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
374 static byte v120_break_header[] =
377 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
382 /*------------------------------------------------------------------*/
383 /* API_PUT function */
384 /*------------------------------------------------------------------*/
386 word api_put(APPL *appl, CAPI_MSG *msg)
388 word i, j, k, l, n;
389 word ret;
390 byte c;
391 byte controller;
392 DIVA_CAPI_ADAPTER *a;
393 PLCI *plci;
394 NCCI *ncci_ptr;
395 word ncci;
396 CAPI_MSG *m;
397 API_PARSE msg_parms[MAX_MSG_PARMS + 1];
399 if (msg->header.length < sizeof(msg->header) ||
400 msg->header.length > MAX_MSG_SIZE) {
401 dbug(1, dprintf("bad len"));
402 return _BAD_MSG;
405 controller = (byte)((msg->header.controller & 0x7f) - 1);
407 /* controller starts with 0 up to (max_adapter - 1) */
408 if (controller >= max_adapter)
410 dbug(1, dprintf("invalid ctrl"));
411 return _BAD_MSG;
414 a = &adapter[controller];
415 plci = NULL;
416 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
418 dbug(1, dprintf("plci=%x", msg->header.plci));
419 plci = &a->plci[msg->header.plci - 1];
420 ncci = GET_WORD(&msg->header.ncci);
421 if (plci->Id
422 && (plci->appl
423 || (plci->State == INC_CON_PENDING)
424 || (plci->State == INC_CON_ALERT)
425 || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
426 && ((ncci == 0)
427 || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
428 || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
430 i = plci->msg_in_read_pos;
431 j = plci->msg_in_write_pos;
432 if (j >= i)
434 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435 i += MSG_IN_QUEUE_SIZE - j;
436 else
437 j = 0;
439 else
442 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444 if (i > MSG_IN_QUEUE_SIZE - n)
445 i = MSG_IN_QUEUE_SIZE - n + 1;
446 i -= j;
449 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
452 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453 msg->header.length, plci->msg_in_write_pos,
454 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
456 return _QUEUE_FULL;
458 c = false;
459 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
462 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463 c = true;
465 if (msg->header.command == _DATA_B3_R)
467 if (msg->header.length < 20)
469 dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470 return _BAD_MSG;
472 ncci_ptr = &(a->ncci[ncci]);
473 n = ncci_ptr->data_pending;
474 l = ncci_ptr->data_ack_pending;
475 k = plci->msg_in_read_pos;
476 while (k != plci->msg_in_write_pos)
478 if (k == plci->msg_in_wrap_pos)
479 k = 0;
480 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
483 n++;
484 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485 l++;
488 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489 MSG_IN_OVERHEAD + 3) & 0xfffc;
492 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
494 dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
497 return _QUEUE_FULL;
499 if (plci->req_in || plci->internal_command)
501 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504 dbug(0, dprintf("Q-FULL3(requeue)"));
506 return _QUEUE_FULL;
508 c = true;
511 else
513 if (plci->req_in || plci->internal_command)
514 c = true;
515 else
517 plci->command = msg->header.command;
518 plci->number = msg->header.number;
521 if (c)
523 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524 msg->header.command, plci->req_in, plci->internal_command,
525 msg->header.length, plci->msg_in_write_pos,
526 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527 if (j == 0)
528 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530 for (i = 0; i < msg->header.length; i++)
531 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532 if (m->header.command == _DATA_B3_R)
535 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
539 j = (j + 3) & 0xfffc;
541 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543 return 0;
546 else
548 plci = NULL;
551 dbug(1, dprintf("com=%x", msg->header.command));
553 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
554 for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
556 if (ftable[i].command == msg->header.command) {
557 /* break loop if the message is correct, otherwise continue scan */
558 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
559 if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
560 ret = 0;
561 break;
563 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
566 if (ret) {
567 dbug(1, dprintf("BAD_MSG"));
568 if (plci) plci->command = 0;
569 return ret;
573 c = ftable[i].function(GET_DWORD(&msg->header.controller),
574 msg->header.number,
576 plci,
577 appl,
578 msg_parms);
580 channel_xmit_extended_xon(plci);
582 if (c == 1) send_req(plci);
583 if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584 if (plci && !plci->req_in) plci->command = 0;
585 return 0;
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages */
591 /*------------------------------------------------------------------*/
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
595 word i;
596 word p;
598 for (i = 0, p = 0; format[i]; i++) {
599 if (parms)
601 parms[i].info = &msg[p];
603 switch (format[i]) {
604 case 'b':
605 p += 1;
606 break;
607 case 'w':
608 p += 2;
609 break;
610 case 'd':
611 p += 4;
612 break;
613 case 's':
614 if (msg[p] == 0xff) {
615 parms[i].info += 2;
616 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617 p += (parms[i].length + 3);
619 else {
620 parms[i].length = msg[p];
621 p += (parms[i].length + 1);
623 break;
626 if (p > length) return true;
628 if (parms) parms[i].info = NULL;
629 return false;
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
634 word i, j, n = 0;
635 byte *p;
637 p = out->info;
638 for (i = 0; format[i] != '\0'; i++)
640 out->parms[i].info = p;
641 out->parms[i].length = in[i].length;
642 switch (format[i])
644 case 'b':
645 n = 1;
646 break;
647 case 'w':
648 n = 2;
649 break;
650 case 'd':
651 n = 4;
652 break;
653 case 's':
654 n = in[i].length + 1;
655 break;
657 for (j = 0; j < n; j++)
658 *(p++) = in[i].info[j];
660 out->parms[i].info = NULL;
661 out->parms[i].length = 0;
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
666 word i;
668 i = 0;
671 out[i].info = in->parms[i].info;
672 out[i].length = in->parms[i].length;
673 } while (in->parms[i++].info);
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function */
679 /*------------------------------------------------------------------*/
681 word api_remove_start(void)
683 word i;
684 word j;
686 if (!remove_started) {
687 remove_started = true;
688 for (i = 0; i < max_adapter; i++) {
689 if (adapter[i].request) {
690 for (j = 0; j < adapter[i].max_plci; j++) {
691 if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
695 return 1;
697 else {
698 for (i = 0; i < max_adapter; i++) {
699 if (adapter[i].request) {
700 for (j = 0; j < adapter[i].max_plci; j++) {
701 if (adapter[i].plci[j].Sig.Id) return 1;
706 api_remove_complete();
707 return 0;
711 /*------------------------------------------------------------------*/
712 /* internal command queue */
713 /*------------------------------------------------------------------*/
715 static void init_internal_command_queue(PLCI *plci)
717 word i;
719 dbug(1, dprintf("%s,%d: init_internal_command_queue",
720 (char *)(FILE_), __LINE__));
722 plci->internal_command = 0;
723 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724 plci->internal_command_queue[i] = NULL;
728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
730 word i;
732 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733 UnMapId(Id), (char *)(FILE_), __LINE__));
735 if (plci->internal_command == 0)
737 plci->internal_command_queue[0] = command_function;
738 (*command_function)(Id, plci, OK);
740 else
742 i = 1;
743 while (plci->internal_command_queue[i] != NULL)
744 i++;
745 plci->internal_command_queue[i] = command_function;
750 static void next_internal_command(dword Id, PLCI *plci)
752 word i;
754 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755 UnMapId(Id), (char *)(FILE_), __LINE__));
757 plci->internal_command = 0;
758 plci->internal_command_queue[0] = NULL;
759 while (plci->internal_command_queue[1] != NULL)
761 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762 plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765 if (plci->internal_command != 0)
766 return;
767 plci->internal_command_queue[0] = NULL;
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function */
774 /*------------------------------------------------------------------*/
776 static dword ncci_mapping_bug = 0;
778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
780 DIVA_CAPI_ADAPTER *a;
781 word ncci, i, j, k;
783 a = plci->adapter;
784 if (!ch || a->ch_ncci[ch])
786 ncci_mapping_bug++;
787 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789 ncci = ch;
791 else
793 if (force_ncci)
794 ncci = force_ncci;
795 else
797 if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
798 ncci = ch;
799 else
801 ncci = 1;
802 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
803 ncci++;
804 if (ncci == MAX_NCCI + 1)
806 ncci_mapping_bug++;
807 i = 1;
810 j = 1;
811 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
812 j++;
813 k = j;
814 if (j < MAX_NCCI + 1)
818 j++;
819 } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
821 } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822 if (i < MAX_NL_CHANNEL + 1)
824 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 ncci_mapping_bug, ch, force_ncci, i, k, j));
827 else
829 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830 ncci_mapping_bug, ch, force_ncci));
832 ncci = ch;
835 a->ncci_plci[ncci] = plci->Id;
836 a->ncci_state[ncci] = IDLE;
837 if (!plci->ncci_ring_list)
838 plci->ncci_ring_list = ncci;
839 else
840 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
843 a->ncci_ch[ncci] = ch;
844 a->ch_ncci[ch] = (byte) ncci;
845 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846 ncci_mapping_bug, ch, force_ncci, ch, ncci));
848 return (ncci);
852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
854 DIVA_CAPI_ADAPTER *a;
855 APPL *appl;
856 word i, ncci_code;
857 dword Id;
859 a = plci->adapter;
860 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861 if (ncci)
863 if (a->ncci_plci[ncci] == plci->Id)
865 if (!plci->appl)
867 ncci_mapping_bug++;
868 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869 ncci_mapping_bug, Id));
871 else
873 appl = plci->appl;
874 ncci_code = ncci | (((word) a->Id) << 8);
875 for (i = 0; i < appl->MaxBuffer; i++)
877 if ((appl->DataNCCI[i] == ncci_code)
878 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
880 appl->DataNCCI[i] = 0;
886 else
888 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
890 if (a->ncci_plci[ncci] == plci->Id)
892 if (!plci->appl)
894 ncci_mapping_bug++;
895 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896 ncci_mapping_bug, Id));
898 else
900 appl = plci->appl;
901 ncci_code = ncci | (((word) a->Id) << 8);
902 for (i = 0; i < appl->MaxBuffer; i++)
904 if ((appl->DataNCCI[i] == ncci_code)
905 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
907 appl->DataNCCI[i] = 0;
917 static void cleanup_ncci_data(PLCI *plci, word ncci)
919 NCCI *ncci_ptr;
921 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
923 ncci_ptr = &(plci->adapter->ncci[ncci]);
924 if (plci->appl)
926 while (ncci_ptr->data_pending != 0)
928 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929 TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930 (ncci_ptr->data_out)++;
931 if (ncci_ptr->data_out == MAX_DATA_B3)
932 ncci_ptr->data_out = 0;
933 (ncci_ptr->data_pending)--;
936 ncci_ptr->data_out = 0;
937 ncci_ptr->data_pending = 0;
938 ncci_ptr->data_ack_out = 0;
939 ncci_ptr->data_ack_pending = 0;
944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
946 DIVA_CAPI_ADAPTER *a;
947 dword Id;
948 word i;
950 a = plci->adapter;
951 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952 if (!preserve_ncci)
953 ncci_free_receive_buffers(plci, ncci);
954 if (ncci)
956 if (a->ncci_plci[ncci] != plci->Id)
958 ncci_mapping_bug++;
959 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 ncci_mapping_bug, Id, preserve_ncci));
962 else
964 cleanup_ncci_data(plci, ncci);
965 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967 a->ch_ncci[a->ncci_ch[ncci]] = 0;
968 if (!preserve_ncci)
970 a->ncci_ch[ncci] = 0;
971 a->ncci_plci[ncci] = 0;
972 a->ncci_state[ncci] = IDLE;
973 i = plci->ncci_ring_list;
974 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975 i = a->ncci_next[i];
976 if ((i != 0) && (a->ncci_next[i] == ncci))
978 if (i == ncci)
979 plci->ncci_ring_list = 0;
980 else if (plci->ncci_ring_list == ncci)
981 plci->ncci_ring_list = i;
982 a->ncci_next[i] = a->ncci_next[ncci];
984 a->ncci_next[ncci] = 0;
988 else
990 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
992 if (a->ncci_plci[ncci] == plci->Id)
994 cleanup_ncci_data(plci, ncci);
995 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997 a->ch_ncci[a->ncci_ch[ncci]] = 0;
998 if (!preserve_ncci)
1000 a->ncci_ch[ncci] = 0;
1001 a->ncci_plci[ncci] = 0;
1002 a->ncci_state[ncci] = IDLE;
1003 a->ncci_next[ncci] = 0;
1007 if (!preserve_ncci)
1008 plci->ncci_ring_list = 0;
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function */
1015 /*------------------------------------------------------------------*/
1017 static void plci_free_msg_in_queue(PLCI *plci)
1019 word i;
1021 if (plci->appl)
1023 i = plci->msg_in_read_pos;
1024 while (i != plci->msg_in_write_pos)
1026 if (i == plci->msg_in_wrap_pos)
1027 i = 0;
1028 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031 TransmitBufferFree(plci->appl,
1032 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037 MSG_IN_OVERHEAD + 3) & 0xfffc;
1041 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047 static void plci_remove(PLCI *plci)
1050 if (!plci) {
1051 dbug(1, dprintf("plci_remove(no plci)"));
1052 return;
1054 init_internal_command_queue(plci);
1055 dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056 if (plci_remove_check(plci))
1058 return;
1060 if (plci->Sig.Id == 0xff)
1062 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063 if (plci->NL.Id && !plci->nl_remove_id)
1065 nl_req_ncci(plci, REMOVE, 0);
1066 send_req(plci);
1069 else
1071 if (!plci->sig_remove_id
1072 && (plci->Sig.Id
1073 || (plci->req_in != plci->req_out)
1074 || (plci->nl_req || plci->sig_req)))
1076 sig_req(plci, HANGUP, 0);
1077 send_req(plci);
1080 ncci_remove(plci, 0, false);
1081 plci_free_msg_in_queue(plci);
1083 plci->channels = 0;
1084 plci->appl = NULL;
1085 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086 plci->State = OUTG_DIS_PENDING;
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers */
1091 /*------------------------------------------------------------------*/
1093 static void set_group_ind_mask(PLCI *plci)
1095 word i;
1097 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098 plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1103 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1108 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL */
1113 /*------------------------------------------------------------------*/
1115 static void clear_c_ind_mask(PLCI *plci)
1117 word i;
1119 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120 plci->c_ind_mask_table[i] = 0;
1123 static byte c_ind_mask_empty(PLCI *plci)
1125 word i;
1127 i = 0;
1128 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129 i++;
1130 return (i == C_IND_MASK_DWORDS);
1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1135 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1140 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1145 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 static void dump_c_ind_mask(PLCI *plci)
1150 word i, j, k;
1151 dword d;
1152 char *p;
1153 char buf[40];
1155 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1157 p = buf + 36;
1158 *p = '\0';
1159 for (j = 0; j < 4; j++)
1161 if (i + j < C_IND_MASK_DWORDS)
1163 d = plci->c_ind_mask_table[i + j];
1164 for (k = 0; k < 8; k++)
1166 *(--p) = hex_asc_lo(d);
1167 d >>= 4;
1170 else if (i != 0)
1172 for (k = 0; k < 8; k++)
1173 *(--p) = ' ';
1175 *(--p) = ' ';
1177 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1185 #define dump_plcis(a)
1189 /*------------------------------------------------------------------*/
1190 /* translation function for each message */
1191 /*------------------------------------------------------------------*/
1193 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1194 PLCI *plci, APPL *appl, API_PARSE *parms)
1196 word ch;
1197 word i;
1198 word Info;
1199 byte LinkLayer;
1200 API_PARSE *ai;
1201 API_PARSE *bp;
1202 API_PARSE ai_parms[5];
1203 word channel = 0;
1204 dword ch_mask;
1205 byte m;
1206 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1207 static byte lli[2] = {0x01, 0x00};
1208 byte noCh = 0;
1209 word dir = 0;
1210 byte *p_chi = "";
1212 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1214 dbug(1, dprintf("connect_req(%d)", parms->length));
1215 Info = _WRONG_IDENTIFIER;
1216 if (a)
1218 if (a->adapter_disabled)
1220 dbug(1, dprintf("adapter disabled"));
1221 Id = ((word)1 << 8) | a->Id;
1222 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1223 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1224 return false;
1226 Info = _OUT_OF_PLCI;
1227 if ((i = get_plci(a)))
1229 Info = 0;
1230 plci = &a->plci[i - 1];
1231 plci->appl = appl;
1232 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1233 /* check 'external controller' bit for codec support */
1234 if (Id & EXT_CONTROLLER)
1236 if (AdvCodecSupport(a, plci, appl, 0))
1238 plci->Id = 0;
1239 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1240 return 2;
1243 ai = &parms[9];
1244 bp = &parms[5];
1245 ch = 0;
1246 if (bp->length)LinkLayer = bp->info[3];
1247 else LinkLayer = 0;
1248 if (ai->length)
1250 ch = 0xffff;
1251 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1253 ch = 0;
1254 if (ai_parms[0].length)
1256 ch = GET_WORD(ai_parms[0].info + 1);
1257 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1258 if (ch == 4) /* explizit CHI in message */
1260 /* check length of B-CH struct */
1261 if ((ai_parms[0].info)[3] >= 1)
1263 if ((ai_parms[0].info)[4] == CHI)
1265 p_chi = &((ai_parms[0].info)[5]);
1267 else
1269 p_chi = &((ai_parms[0].info)[3]);
1271 if (p_chi[0] > 35) /* check length of channel ID */
1273 Info = _WRONG_MESSAGE_FORMAT;
1276 else Info = _WRONG_MESSAGE_FORMAT;
1279 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1281 dir = GET_WORD(ai_parms[0].info + 3);
1282 ch_mask = 0;
1283 m = 0x3f;
1284 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1286 if (ai_parms[0].info[i + 5] != 0)
1288 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1289 Info = _WRONG_MESSAGE_FORMAT;
1290 else
1292 if (ch_mask == 0)
1293 channel = i;
1294 ch_mask |= 1L << i;
1297 m = 0;
1299 if (ch_mask == 0)
1300 Info = _WRONG_MESSAGE_FORMAT;
1301 if (!Info)
1303 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1305 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1306 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1307 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1309 else
1310 esc_chi[0] = 2;
1311 esc_chi[2] = (byte)channel;
1312 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1313 add_p(plci, LLI, lli);
1314 add_p(plci, ESC, esc_chi);
1315 plci->State = LOCAL_CONNECT;
1316 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1321 else Info = _WRONG_MESSAGE_FORMAT;
1324 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1325 plci->command = _CONNECT_R;
1326 plci->number = Number;
1327 /* x.31 or D-ch free SAPI in LinkLayer? */
1328 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1329 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1331 /* B-channel used for B3 connections (ch==0), or no B channel */
1332 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1333 if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1334 else Info = add_b1(plci, &parms[5], ch, 0);
1335 add_s(plci, OAD, &parms[2]);
1336 add_s(plci, OSA, &parms[4]);
1337 add_s(plci, BC, &parms[6]);
1338 add_s(plci, LLC, &parms[7]);
1339 add_s(plci, HLC, &parms[8]);
1340 if (a->Info_Mask[appl->Id - 1] & 0x200)
1342 /* early B3 connect (CIP mask bit 9) no release after a disc */
1343 add_p(plci, LLI, "\x01\x01");
1345 if (GET_WORD(parms[0].info) < 29) {
1346 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1347 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1349 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1350 sig_req(plci, ASSIGN, DSIG_ID);
1352 else if (ch == 1) {
1354 /* D-Channel used for B3 connections */
1355 plci->Sig.Id = 0xff;
1356 Info = 0;
1359 if (!Info && ch != 2 && !noCh) {
1360 Info = add_b23(plci, &parms[5]);
1361 if (!Info) {
1362 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1366 if (!Info)
1368 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1370 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1372 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1373 plci->spoofed_msg = CALL_REQ;
1374 plci->internal_command = BLOCK_PLCI;
1375 plci->command = 0;
1376 dbug(1, dprintf("Spoof"));
1377 send_req(plci);
1378 return false;
1380 if (ch == 4)add_p(plci, CHI, p_chi);
1381 add_s(plci, CPN, &parms[1]);
1382 add_s(plci, DSA, &parms[3]);
1383 if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1384 add_ai(plci, &parms[9]);
1385 if (!dir)sig_req(plci, CALL_REQ, 0);
1386 else
1388 plci->command = PERM_LIST_REQ;
1389 plci->appl = appl;
1390 sig_req(plci, LISTEN_REQ, 0);
1391 send_req(plci);
1392 return false;
1395 send_req(plci);
1396 return false;
1398 plci->Id = 0;
1401 sendf(appl,
1402 _CONNECT_R | CONFIRM,
1404 Number,
1405 "w", Info);
1406 return 2;
1409 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1410 PLCI *plci, APPL *appl, API_PARSE *parms)
1412 word i, Info;
1413 word Reject;
1414 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1415 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1416 API_PARSE *ai;
1417 API_PARSE ai_parms[5];
1418 word ch = 0;
1420 if (!plci) {
1421 dbug(1, dprintf("connect_res(no plci)"));
1422 return 0; /* no plci, no send */
1425 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1426 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1427 ai = &parms[5];
1428 dbug(1, dprintf("ai->length=%d", ai->length));
1430 if (ai->length)
1432 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1434 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1435 ch = 0;
1436 if (ai_parms[0].length)
1438 ch = GET_WORD(ai_parms[0].info + 1);
1439 dbug(1, dprintf("BCH-I=0x%x", ch));
1444 if (plci->State == INC_CON_CONNECTED_ALERT)
1446 dbug(1, dprintf("Connected Alert Call_Res"));
1447 if (a->Info_Mask[appl->Id - 1] & 0x200)
1449 /* early B3 connect (CIP mask bit 9) no release after a disc */
1450 add_p(plci, LLI, "\x01\x01");
1452 add_s(plci, CONN_NR, &parms[2]);
1453 add_s(plci, LLC, &parms[4]);
1454 add_ai(plci, &parms[5]);
1455 plci->State = INC_CON_ACCEPT;
1456 sig_req(plci, CALL_RES, 0);
1457 return 1;
1459 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1460 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1461 dump_c_ind_mask(plci);
1462 Reject = GET_WORD(parms[0].info);
1463 dbug(1, dprintf("Reject=0x%x", Reject));
1464 if (Reject)
1466 if (c_ind_mask_empty(plci))
1468 if ((Reject & 0xff00) == 0x3400)
1470 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1471 add_p(plci, ESC, esc_t);
1472 add_ai(plci, &parms[5]);
1473 sig_req(plci, REJECT, 0);
1475 else if (Reject == 1 || Reject >= 9)
1477 add_ai(plci, &parms[5]);
1478 sig_req(plci, HANGUP, 0);
1480 else
1482 esc_t[2] = cau_t[(Reject&0x000f)];
1483 add_p(plci, ESC, esc_t);
1484 add_ai(plci, &parms[5]);
1485 sig_req(plci, REJECT, 0);
1487 plci->appl = appl;
1489 else
1491 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1494 else {
1495 plci->appl = appl;
1496 if (Id & EXT_CONTROLLER) {
1497 if (AdvCodecSupport(a, plci, appl, 0)) {
1498 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1499 sig_req(plci, HANGUP, 0);
1500 return 1;
1502 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1504 Info = add_b23(plci, &parms[1]);
1505 if (Info)
1507 dbug(1, dprintf("connect_res(error from add_b23)"));
1508 sig_req(plci, HANGUP, 0);
1509 return 1;
1511 if (plci->adv_nl)
1513 nl_req_ncci(plci, ASSIGN, 0);
1517 else
1519 plci->tel = 0;
1520 if (ch != 2)
1522 Info = add_b23(plci, &parms[1]);
1523 if (Info)
1525 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1526 sig_req(plci, HANGUP, 0);
1527 return 1;
1530 nl_req_ncci(plci, ASSIGN, 0);
1533 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1535 api_save_msg(parms, "wsssss", &plci->saved_msg);
1536 plci->spoofed_msg = CALL_RES;
1537 plci->internal_command = BLOCK_PLCI;
1538 plci->command = 0;
1539 dbug(1, dprintf("Spoof"));
1541 else
1543 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1544 if (a->Info_Mask[appl->Id - 1] & 0x200)
1546 /* early B3 connect (CIP mask bit 9) no release after a disc */
1547 add_p(plci, LLI, "\x01\x01");
1549 add_s(plci, CONN_NR, &parms[2]);
1550 add_s(plci, LLC, &parms[4]);
1551 add_ai(plci, &parms[5]);
1552 plci->State = INC_CON_ACCEPT;
1553 sig_req(plci, CALL_RES, 0);
1556 for (i = 0; i < max_appl; i++) {
1557 if (test_c_ind_mask_bit(plci, i)) {
1558 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563 return 1;
1566 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1567 PLCI *plci, APPL *appl, API_PARSE *msg)
1569 dbug(1, dprintf("connect_a_res"));
1570 return false;
1573 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1574 PLCI *plci, APPL *appl, API_PARSE *msg)
1576 word Info;
1577 word i;
1579 dbug(1, dprintf("disconnect_req"));
1581 Info = _WRONG_IDENTIFIER;
1583 if (plci)
1585 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1587 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1588 plci->appl = appl;
1589 for (i = 0; i < max_appl; i++)
1591 if (test_c_ind_mask_bit(plci, i))
1592 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1594 plci->State = OUTG_DIS_PENDING;
1596 if (plci->Sig.Id && plci->appl)
1598 Info = 0;
1599 if (plci->Sig.Id != 0xff)
1601 if (plci->State != INC_DIS_PENDING)
1603 add_ai(plci, &msg[0]);
1604 sig_req(plci, HANGUP, 0);
1605 plci->State = OUTG_DIS_PENDING;
1606 return 1;
1609 else
1611 if (plci->NL.Id && !plci->nl_remove_id)
1613 mixer_remove(plci);
1614 nl_req_ncci(plci, REMOVE, 0);
1615 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1616 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1617 plci->State = INC_DIS_PENDING;
1619 return 1;
1624 if (!appl) return false;
1625 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1626 return false;
1629 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1630 PLCI *plci, APPL *appl, API_PARSE *msg)
1632 dbug(1, dprintf("disconnect_res"));
1633 if (plci)
1635 /* clear ind mask bit, just in case of collsion of */
1636 /* DISCONNECT_IND and CONNECT_RES */
1637 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1638 ncci_free_receive_buffers(plci, 0);
1639 if (plci_remove_check(plci))
1641 return 0;
1643 if (plci->State == INC_DIS_PENDING
1644 || plci->State == SUSPENDING) {
1645 if (c_ind_mask_empty(plci)) {
1646 if (plci->State != SUSPENDING) plci->State = IDLE;
1647 dbug(1, dprintf("chs=%d", plci->channels));
1648 if (!plci->channels) {
1649 plci_remove(plci);
1654 return 0;
1657 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1658 PLCI *plci, APPL *appl, API_PARSE *parms)
1660 word Info;
1661 byte i;
1663 dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1665 Info = _WRONG_IDENTIFIER;
1666 if (a) {
1667 Info = 0;
1668 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1669 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1670 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1671 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1672 a->Info_Mask[appl->Id - 1] |= 0x10; /* call progression infos */
1675 /* check if external controller listen and switch listen on or off*/
1676 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1677 if (a->profile.Global_Options & ON_BOARD_CODEC) {
1678 dummy_plci.State = IDLE;
1679 a->codec_listen[appl->Id - 1] = &dummy_plci;
1680 a->TelOAD[0] = (byte)(parms[3].length);
1681 for (i = 1; parms[3].length >= i && i < 22; i++) {
1682 a->TelOAD[i] = parms[3].info[i];
1684 a->TelOAD[i] = 0;
1685 a->TelOSA[0] = (byte)(parms[4].length);
1686 for (i = 1; parms[4].length >= i && i < 22; i++) {
1687 a->TelOSA[i] = parms[4].info[i];
1689 a->TelOSA[i] = 0;
1691 else Info = 0x2002; /* wrong controller, codec not supported */
1693 else{ /* clear listen */
1694 a->codec_listen[appl->Id - 1] = (PLCI *)0;
1697 sendf(appl,
1698 _LISTEN_R | CONFIRM,
1700 Number,
1701 "w", Info);
1703 if (a) listen_check(a);
1704 return false;
1707 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1708 PLCI *plci, APPL *appl, API_PARSE *msg)
1710 word i;
1711 API_PARSE *ai;
1712 PLCI *rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1714 word Info = 0;
1716 dbug(1, dprintf("info_req"));
1717 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1719 ai = &msg[1];
1721 if (ai->length)
1723 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1725 dbug(1, dprintf("AddInfo wrong"));
1726 Info = _WRONG_MESSAGE_FORMAT;
1729 if (!a) Info = _WRONG_STATE;
1731 if (!Info && plci)
1732 { /* no fac, with CPN, or KEY */
1733 rc_plci = plci;
1734 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1736 /* overlap sending option */
1737 dbug(1, dprintf("OvlSnd"));
1738 add_s(plci, CPN, &msg[0]);
1739 add_s(plci, KEY, &ai_parms[1]);
1740 sig_req(plci, INFO_REQ, 0);
1741 send_req(plci);
1742 return false;
1745 if (plci->State && ai_parms[2].length)
1747 /* User_Info option */
1748 dbug(1, dprintf("UUI"));
1749 add_s(plci, UUI, &ai_parms[2]);
1750 sig_req(plci, USER_DATA, 0);
1752 else if (plci->State && ai_parms[3].length)
1754 /* Facility option */
1755 dbug(1, dprintf("FAC"));
1756 add_s(plci, CPN, &msg[0]);
1757 add_ai(plci, &msg[1]);
1758 sig_req(plci, FACILITY_REQ, 0);
1760 else
1762 Info = _WRONG_STATE;
1765 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1, dprintf("NCR_FAC"));
1769 if ((i = get_plci(a)))
1771 rc_plci = &a->plci[i - 1];
1772 appl->NullCREnable = true;
1773 rc_plci->internal_command = C_NCR_FAC_REQ;
1774 rc_plci->appl = appl;
1775 add_p(rc_plci, CAI, "\x01\x80");
1776 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci, ASSIGN, DSIG_ID);
1778 send_req(rc_plci);
1780 else
1782 Info = _OUT_OF_PLCI;
1785 if (!Info)
1787 add_s(rc_plci, CPN, &msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci, NCR_FACILITY, 0);
1790 send_req(rc_plci);
1791 return false;
1792 /* for application controlled supplementary services */
1796 if (!rc_plci)
1798 Info = _WRONG_MESSAGE_FORMAT;
1801 if (!Info)
1803 send_req(rc_plci);
1805 else
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1, dprintf("localInfoCon"));
1808 sendf(appl,
1809 _INFO_R | CONFIRM,
1811 Number,
1812 "w", Info);
1814 return false;
1817 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1818 PLCI *plci, APPL *appl, API_PARSE *msg)
1820 dbug(1, dprintf("info_res"));
1821 return false;
1824 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1825 PLCI *plci, APPL *appl, API_PARSE *msg)
1827 word Info;
1828 byte ret;
1830 dbug(1, dprintf("alert_req"));
1832 Info = _WRONG_IDENTIFIER;
1833 ret = false;
1834 if (plci) {
1835 Info = _ALERT_IGNORED;
1836 if (plci->State != INC_CON_ALERT) {
1837 Info = _WRONG_STATE;
1838 if (plci->State == INC_CON_PENDING) {
1839 Info = 0;
1840 plci->State = INC_CON_ALERT;
1841 add_ai(plci, &msg[0]);
1842 sig_req(plci, CALL_ALERT, 0);
1843 ret = 1;
1847 sendf(appl,
1848 _ALERT_R | CONFIRM,
1850 Number,
1851 "w", Info);
1852 return ret;
1855 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1856 PLCI *plci, APPL *appl, API_PARSE *msg)
1858 word Info = 0;
1859 word i = 0;
1861 word selector;
1862 word SSreq;
1863 long relatedPLCIvalue;
1864 DIVA_CAPI_ADAPTER *relatedadapter;
1865 byte *SSparms = "";
1866 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1867 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1868 API_PARSE *parms;
1869 API_PARSE ss_parms[11];
1870 PLCI *rplci;
1871 byte cai[15];
1872 dword d;
1873 API_PARSE dummy;
1875 dbug(1, dprintf("facility_req"));
1876 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1878 parms = &msg[1];
1880 if (!a)
1882 dbug(1, dprintf("wrong Ctrl"));
1883 Info = _WRONG_IDENTIFIER;
1886 selector = GET_WORD(msg[0].info);
1888 if (!Info)
1890 switch (selector)
1892 case SELECTOR_HANDSET:
1893 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1894 break;
1896 case SELECTOR_SU_SERV:
1897 if (!msg[1].length)
1899 Info = _WRONG_MESSAGE_FORMAT;
1900 break;
1902 SSreq = GET_WORD(&(msg[1].info[1]));
1903 PUT_WORD(&RCparms[1], SSreq);
1904 SSparms = RCparms;
1905 switch (SSreq)
1907 case S_GET_SUPPORTED_SERVICES:
1908 if ((i = get_plci(a)))
1910 rplci = &a->plci[i - 1];
1911 rplci->appl = appl;
1912 add_p(rplci, CAI, "\x01\x80");
1913 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1914 sig_req(rplci, ASSIGN, DSIG_ID);
1915 send_req(rplci);
1917 else
1919 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1920 SSparms = (byte *)SSstruct;
1921 break;
1923 rplci->internal_command = GETSERV_REQ_PEND;
1924 rplci->number = Number;
1925 rplci->appl = appl;
1926 sig_req(rplci, S_SUPPORTED, 0);
1927 send_req(rplci);
1928 return false;
1929 break;
1931 case S_LISTEN:
1932 if (parms->length == 7)
1934 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1936 dbug(1, dprintf("format wrong"));
1937 Info = _WRONG_MESSAGE_FORMAT;
1938 break;
1941 else
1943 Info = _WRONG_MESSAGE_FORMAT;
1944 break;
1946 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1947 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1949 if ((i = get_plci(a)))
1951 rplci = &a->plci[i - 1];
1952 rplci->appl = appl;
1953 add_p(rplci, CAI, "\x01\x80");
1954 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1955 sig_req(rplci, ASSIGN, DSIG_ID);
1956 send_req(rplci);
1958 else
1960 break;
1962 rplci->internal_command = GET_MWI_STATE;
1963 rplci->number = Number;
1964 sig_req(rplci, MWI_POLL, 0);
1965 send_req(rplci);
1967 break;
1969 case S_HOLD:
1970 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1971 if (plci && plci->State && plci->SuppState == IDLE)
1973 plci->SuppState = HOLD_REQUEST;
1974 plci->command = C_HOLD_REQ;
1975 add_s(plci, CAI, &ss_parms[1]);
1976 sig_req(plci, CALL_HOLD, 0);
1977 send_req(plci);
1978 return false;
1980 else Info = 0x3010; /* wrong state */
1981 break;
1982 case S_RETRIEVE:
1983 if (plci && plci->State && plci->SuppState == CALL_HELD)
1985 if (Id & EXT_CONTROLLER)
1987 if (AdvCodecSupport(a, plci, appl, 0))
1989 Info = 0x3010; /* wrong state */
1990 break;
1993 else plci->tel = 0;
1995 plci->SuppState = RETRIEVE_REQUEST;
1996 plci->command = C_RETRIEVE_REQ;
1997 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1999 plci->spoofed_msg = CALL_RETRIEVE;
2000 plci->internal_command = BLOCK_PLCI;
2001 plci->command = 0;
2002 dbug(1, dprintf("Spoof"));
2003 return false;
2005 else
2007 sig_req(plci, CALL_RETRIEVE, 0);
2008 send_req(plci);
2009 return false;
2012 else Info = 0x3010; /* wrong state */
2013 break;
2014 case S_SUSPEND:
2015 if (parms->length)
2017 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2019 dbug(1, dprintf("format wrong"));
2020 Info = _WRONG_MESSAGE_FORMAT;
2021 break;
2024 if (plci && plci->State)
2026 add_s(plci, CAI, &ss_parms[2]);
2027 plci->command = SUSPEND_REQ;
2028 sig_req(plci, SUSPEND, 0);
2029 plci->State = SUSPENDING;
2030 send_req(plci);
2032 else Info = 0x3010; /* wrong state */
2033 break;
2035 case S_RESUME:
2036 if (!(i = get_plci(a)))
2038 Info = _OUT_OF_PLCI;
2039 break;
2041 rplci = &a->plci[i - 1];
2042 rplci->appl = appl;
2043 rplci->number = Number;
2044 rplci->tel = 0;
2045 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2046 /* check 'external controller' bit for codec support */
2047 if (Id & EXT_CONTROLLER)
2049 if (AdvCodecSupport(a, rplci, appl, 0))
2051 rplci->Id = 0;
2052 Info = 0x300A;
2053 break;
2056 if (parms->length)
2058 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2060 dbug(1, dprintf("format wrong"));
2061 rplci->Id = 0;
2062 Info = _WRONG_MESSAGE_FORMAT;
2063 break;
2066 dummy.length = 0;
2067 dummy.info = "\x00";
2068 add_b1(rplci, &dummy, 0, 0);
2069 if (a->Info_Mask[appl->Id - 1] & 0x200)
2071 /* early B3 connect (CIP mask bit 9) no release after a disc */
2072 add_p(rplci, LLI, "\x01\x01");
2074 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2075 sig_req(rplci, ASSIGN, DSIG_ID);
2076 send_req(rplci);
2077 add_s(rplci, CAI, &ss_parms[2]);
2078 rplci->command = RESUME_REQ;
2079 sig_req(rplci, RESUME, 0);
2080 rplci->State = RESUMING;
2081 send_req(rplci);
2082 break;
2084 case S_CONF_BEGIN: /* Request */
2085 case S_CONF_DROP:
2086 case S_CONF_ISOLATE:
2087 case S_CONF_REATTACH:
2088 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2090 dbug(1, dprintf("format wrong"));
2091 Info = _WRONG_MESSAGE_FORMAT;
2092 break;
2094 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2096 d = GET_DWORD(ss_parms[2].info);
2097 if (d >= 0x80)
2099 dbug(1, dprintf("format wrong"));
2100 Info = _WRONG_MESSAGE_FORMAT;
2101 break;
2103 plci->ptyState = (byte)SSreq;
2104 plci->command = 0;
2105 cai[0] = 2;
2106 switch (SSreq)
2108 case S_CONF_BEGIN:
2109 cai[1] = CONF_BEGIN;
2110 plci->internal_command = CONF_BEGIN_REQ_PEND;
2111 break;
2112 case S_CONF_DROP:
2113 cai[1] = CONF_DROP;
2114 plci->internal_command = CONF_DROP_REQ_PEND;
2115 break;
2116 case S_CONF_ISOLATE:
2117 cai[1] = CONF_ISOLATE;
2118 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2119 break;
2120 case S_CONF_REATTACH:
2121 cai[1] = CONF_REATTACH;
2122 plci->internal_command = CONF_REATTACH_REQ_PEND;
2123 break;
2125 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2126 add_p(plci, CAI, cai);
2127 sig_req(plci, S_SERVICE, 0);
2128 send_req(plci);
2129 return false;
2131 else Info = 0x3010; /* wrong state */
2132 break;
2134 case S_ECT:
2135 case S_3PTY_BEGIN:
2136 case S_3PTY_END:
2137 case S_CONF_ADD:
2138 if (parms->length == 7)
2140 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2142 dbug(1, dprintf("format wrong"));
2143 Info = _WRONG_MESSAGE_FORMAT;
2144 break;
2147 else if (parms->length == 8) /* workaround for the T-View-S */
2149 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2151 dbug(1, dprintf("format wrong"));
2152 Info = _WRONG_MESSAGE_FORMAT;
2153 break;
2156 else
2158 Info = _WRONG_MESSAGE_FORMAT;
2159 break;
2161 if (!msg[1].length)
2163 Info = _WRONG_MESSAGE_FORMAT;
2164 break;
2166 if (!plci)
2168 Info = _WRONG_IDENTIFIER;
2169 break;
2171 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2172 relatedPLCIvalue &= 0x0000FFFF;
2173 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2174 /* controller starts with 0 up to (max_adapter - 1) */
2175 if (((relatedPLCIvalue & 0x7f) == 0)
2176 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2177 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2179 if (SSreq == S_3PTY_END)
2181 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2182 rplci = plci;
2184 else
2186 Info = 0x3010; /* wrong state */
2187 break;
2190 else
2192 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2193 relatedPLCIvalue >>= 8;
2194 /* find PLCI PTR*/
2195 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2197 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2199 rplci = &relatedadapter->plci[i];
2202 if (!rplci || !relatedPLCIvalue)
2204 if (SSreq == S_3PTY_END)
2206 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2207 rplci = plci;
2209 else
2211 Info = 0x3010; /* wrong state */
2212 break;
2217 dbug(1, dprintf("rplci:%x", rplci));
2218 dbug(1, dprintf("plci:%x", plci));
2219 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2220 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2221 dbug(1, dprintf("SSreq:%x", SSreq));
2222 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2223 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2224 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2226 /* send PTY/ECT req, cannot check all states because of US stuff */
2227 if (!rplci->internal_command && rplci->appl)
2229 plci->command = 0;
2230 rplci->relatedPTYPLCI = plci;
2231 plci->relatedPTYPLCI = rplci;
2232 rplci->ptyState = (byte)SSreq;
2233 if (SSreq == S_ECT)
2235 rplci->internal_command = ECT_REQ_PEND;
2236 cai[1] = ECT_EXECUTE;
2238 rplci->vswitchstate = 0;
2239 rplci->vsprot = 0;
2240 rplci->vsprotdialect = 0;
2241 plci->vswitchstate = 0;
2242 plci->vsprot = 0;
2243 plci->vsprotdialect = 0;
2246 else if (SSreq == S_CONF_ADD)
2248 rplci->internal_command = CONF_ADD_REQ_PEND;
2249 cai[1] = CONF_ADD;
2251 else
2253 rplci->internal_command = PTY_REQ_PEND;
2254 cai[1] = (byte)(SSreq - 3);
2256 rplci->number = Number;
2257 if (plci != rplci) /* explicit invocation */
2259 cai[0] = 2;
2260 cai[2] = plci->Sig.Id;
2261 dbug(1, dprintf("explicit invocation"));
2263 else
2265 dbug(1, dprintf("implicit invocation"));
2266 cai[0] = 1;
2268 add_p(rplci, CAI, cai);
2269 sig_req(rplci, S_SERVICE, 0);
2270 send_req(rplci);
2271 return false;
2273 else
2275 dbug(0, dprintf("Wrong line"));
2276 Info = 0x3010; /* wrong state */
2277 break;
2279 break;
2281 case S_CALL_DEFLECTION:
2282 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2284 dbug(1, dprintf("format wrong"));
2285 Info = _WRONG_MESSAGE_FORMAT;
2286 break;
2288 if (!plci)
2290 Info = _WRONG_IDENTIFIER;
2291 break;
2293 /* reuse unused screening indicator */
2294 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2295 plci->command = 0;
2296 plci->internal_command = CD_REQ_PEND;
2297 appl->CDEnable = true;
2298 cai[0] = 1;
2299 cai[1] = CALL_DEFLECTION;
2300 add_p(plci, CAI, cai);
2301 add_p(plci, CPN, ss_parms[3].info);
2302 sig_req(plci, S_SERVICE, 0);
2303 send_req(plci);
2304 return false;
2305 break;
2307 case S_CALL_FORWARDING_START:
2308 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2310 dbug(1, dprintf("format wrong"));
2311 Info = _WRONG_MESSAGE_FORMAT;
2312 break;
2315 if ((i = get_plci(a)))
2317 rplci = &a->plci[i - 1];
2318 rplci->appl = appl;
2319 add_p(rplci, CAI, "\x01\x80");
2320 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2321 sig_req(rplci, ASSIGN, DSIG_ID);
2322 send_req(rplci);
2324 else
2326 Info = _OUT_OF_PLCI;
2327 break;
2330 /* reuse unused screening indicator */
2331 rplci->internal_command = CF_START_PEND;
2332 rplci->appl = appl;
2333 rplci->number = Number;
2334 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2335 cai[0] = 2;
2336 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2337 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2338 add_p(rplci, CAI, cai);
2339 add_p(rplci, OAD, ss_parms[5].info);
2340 add_p(rplci, CPN, ss_parms[6].info);
2341 sig_req(rplci, S_SERVICE, 0);
2342 send_req(rplci);
2343 return false;
2344 break;
2346 case S_INTERROGATE_DIVERSION:
2347 case S_INTERROGATE_NUMBERS:
2348 case S_CALL_FORWARDING_STOP:
2349 case S_CCBS_REQUEST:
2350 case S_CCBS_DEACTIVATE:
2351 case S_CCBS_INTERROGATE:
2352 switch (SSreq)
2354 case S_INTERROGATE_NUMBERS:
2355 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2357 dbug(0, dprintf("format wrong"));
2358 Info = _WRONG_MESSAGE_FORMAT;
2360 break;
2361 case S_CCBS_REQUEST:
2362 case S_CCBS_DEACTIVATE:
2363 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2365 dbug(0, dprintf("format wrong"));
2366 Info = _WRONG_MESSAGE_FORMAT;
2368 break;
2369 case S_CCBS_INTERROGATE:
2370 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2372 dbug(0, dprintf("format wrong"));
2373 Info = _WRONG_MESSAGE_FORMAT;
2375 break;
2376 default:
2377 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2379 dbug(0, dprintf("format wrong"));
2380 Info = _WRONG_MESSAGE_FORMAT;
2381 break;
2383 break;
2386 if (Info) break;
2387 if ((i = get_plci(a)))
2389 rplci = &a->plci[i - 1];
2390 switch (SSreq)
2392 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2393 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2394 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2395 break;
2396 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2397 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2398 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2399 break;
2400 case S_CALL_FORWARDING_STOP:
2401 rplci->internal_command = CF_STOP_PEND;
2402 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2403 break;
2404 case S_CCBS_REQUEST:
2405 cai[1] = CCBS_REQUEST;
2406 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2407 break;
2408 case S_CCBS_DEACTIVATE:
2409 cai[1] = CCBS_DEACTIVATE;
2410 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2411 break;
2412 case S_CCBS_INTERROGATE:
2413 cai[1] = CCBS_INTERROGATE;
2414 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2415 break;
2416 default:
2417 cai[1] = 0;
2418 break;
2420 rplci->appl = appl;
2421 rplci->number = Number;
2422 add_p(rplci, CAI, "\x01\x80");
2423 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2424 sig_req(rplci, ASSIGN, DSIG_ID);
2425 send_req(rplci);
2427 else
2429 Info = _OUT_OF_PLCI;
2430 break;
2433 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2434 switch (SSreq)
2436 case S_INTERROGATE_NUMBERS:
2437 cai[0] = 1;
2438 add_p(rplci, CAI, cai);
2439 break;
2440 case S_CCBS_REQUEST:
2441 case S_CCBS_DEACTIVATE:
2442 cai[0] = 3;
2443 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2444 add_p(rplci, CAI, cai);
2445 break;
2446 case S_CCBS_INTERROGATE:
2447 cai[0] = 3;
2448 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2449 add_p(rplci, CAI, cai);
2450 add_p(rplci, OAD, ss_parms[4].info);
2451 break;
2452 default:
2453 cai[0] = 2;
2454 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2455 add_p(rplci, CAI, cai);
2456 add_p(rplci, OAD, ss_parms[5].info);
2457 break;
2460 sig_req(rplci, S_SERVICE, 0);
2461 send_req(rplci);
2462 return false;
2463 break;
2465 case S_MWI_ACTIVATE:
2466 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2468 dbug(1, dprintf("format wrong"));
2469 Info = _WRONG_MESSAGE_FORMAT;
2470 break;
2472 if (!plci)
2474 if ((i = get_plci(a)))
2476 rplci = &a->plci[i - 1];
2477 rplci->appl = appl;
2478 rplci->cr_enquiry = true;
2479 add_p(rplci, CAI, "\x01\x80");
2480 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2481 sig_req(rplci, ASSIGN, DSIG_ID);
2482 send_req(rplci);
2484 else
2486 Info = _OUT_OF_PLCI;
2487 break;
2490 else
2492 rplci = plci;
2493 rplci->cr_enquiry = false;
2496 rplci->command = 0;
2497 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2498 rplci->appl = appl;
2499 rplci->number = Number;
2501 cai[0] = 13;
2502 cai[1] = ACTIVATION_MWI; /* Function */
2503 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2504 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2505 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2506 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2507 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2508 add_p(rplci, CAI, cai);
2509 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2510 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2511 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2512 add_p(rplci, UID, ss_parms[10].info); /* Time */
2513 sig_req(rplci, S_SERVICE, 0);
2514 send_req(rplci);
2515 return false;
2517 case S_MWI_DEACTIVATE:
2518 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2520 dbug(1, dprintf("format wrong"));
2521 Info = _WRONG_MESSAGE_FORMAT;
2522 break;
2524 if (!plci)
2526 if ((i = get_plci(a)))
2528 rplci = &a->plci[i - 1];
2529 rplci->appl = appl;
2530 rplci->cr_enquiry = true;
2531 add_p(rplci, CAI, "\x01\x80");
2532 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2533 sig_req(rplci, ASSIGN, DSIG_ID);
2534 send_req(rplci);
2536 else
2538 Info = _OUT_OF_PLCI;
2539 break;
2542 else
2544 rplci = plci;
2545 rplci->cr_enquiry = false;
2548 rplci->command = 0;
2549 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2550 rplci->appl = appl;
2551 rplci->number = Number;
2553 cai[0] = 5;
2554 cai[1] = DEACTIVATION_MWI; /* Function */
2555 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2556 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2557 add_p(rplci, CAI, cai);
2558 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2559 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2560 sig_req(rplci, S_SERVICE, 0);
2561 send_req(rplci);
2562 return false;
2564 default:
2565 Info = 0x300E; /* not supported */
2566 break;
2568 break; /* case SELECTOR_SU_SERV: end */
2571 case SELECTOR_DTMF:
2572 return (dtmf_request(Id, Number, a, plci, appl, msg));
2576 case SELECTOR_LINE_INTERCONNECT:
2577 return (mixer_request(Id, Number, a, plci, appl, msg));
2581 case PRIV_SELECTOR_ECHO_CANCELLER:
2582 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2583 return (ec_request(Id, Number, a, plci, appl, msg));
2585 case SELECTOR_ECHO_CANCELLER:
2586 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2587 return (ec_request(Id, Number, a, plci, appl, msg));
2590 case SELECTOR_V42BIS:
2591 default:
2592 Info = _FACILITY_NOT_SUPPORTED;
2593 break;
2594 } /* end of switch (selector) */
2597 dbug(1, dprintf("SendFacRc"));
2598 sendf(appl,
2599 _FACILITY_R | CONFIRM,
2601 Number,
2602 "wws", Info, selector, SSparms);
2603 return false;
2606 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2607 PLCI *plci, APPL *appl, API_PARSE *msg)
2609 dbug(1, dprintf("facility_res"));
2610 return false;
2613 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2614 PLCI *plci, APPL *appl, API_PARSE *parms)
2616 word Info = 0;
2617 byte req;
2618 byte len;
2619 word w;
2620 word fax_control_bits, fax_feature_bits, fax_info_change;
2621 API_PARSE *ncpi;
2622 byte pvc[2];
2624 API_PARSE fax_parms[9];
2625 word i;
2628 dbug(1, dprintf("connect_b3_req"));
2629 if (plci)
2631 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2632 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2634 Info = _WRONG_STATE;
2636 else
2638 /* local reply if assign unsuccessful
2639 or B3 protocol allows only one layer 3 connection
2640 and already connected
2641 or B2 protocol not any LAPD
2642 and connect_b3_req contradicts originate/answer direction */
2643 if (!plci->NL.Id
2644 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2645 && ((plci->channels != 0)
2646 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2647 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2649 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2650 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2651 Info = _WRONG_STATE;
2652 sendf(appl,
2653 _CONNECT_B3_R | CONFIRM,
2655 Number,
2656 "w", Info);
2657 return false;
2659 plci->requested_options_conn = 0;
2661 req = N_CONNECT;
2662 ncpi = &parms[0];
2663 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2665 if (ncpi->length > 2)
2667 /* check for PVC */
2668 if (ncpi->info[2] || ncpi->info[3])
2670 pvc[0] = ncpi->info[3];
2671 pvc[1] = ncpi->info[2];
2672 add_d(plci, 2, pvc);
2673 req = N_RESET;
2675 else
2677 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2678 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2682 else if (plci->B3_prot == 5)
2684 if (plci->NL.Id && !plci->nl_remove_id)
2686 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2687 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2688 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2689 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2691 len = offsetof(T30_INFO, universal_6);
2692 fax_info_change = false;
2693 if (ncpi->length >= 4)
2695 w = GET_WORD(&ncpi->info[3]);
2696 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2698 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2699 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2700 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2701 fax_info_change = true;
2703 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2704 if (w & 0x0002) /* Fax-polling request */
2705 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2706 if ((w & 0x0004) /* Request to send / poll another document */
2707 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2709 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2711 if (ncpi->length >= 6)
2713 w = GET_WORD(&ncpi->info[5]);
2714 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2716 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2717 fax_info_change = true;
2720 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2721 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2723 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2725 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2726 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2728 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2730 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2731 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2732 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2733 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2735 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2736 Info = _WRONG_MESSAGE_FORMAT;
2737 else
2739 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2740 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2742 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2743 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2744 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2746 w = fax_parms[4].length;
2747 if (w > 20)
2748 w = 20;
2749 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2750 for (i = 0; i < w; i++)
2751 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2752 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2753 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2754 w = fax_parms[5].length;
2755 if (w > 20)
2756 w = 20;
2757 plci->fax_connect_info_buffer[len++] = (byte) w;
2758 for (i = 0; i < w; i++)
2759 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2760 w = fax_parms[6].length;
2761 if (w > 20)
2762 w = 20;
2763 plci->fax_connect_info_buffer[len++] = (byte) w;
2764 for (i = 0; i < w; i++)
2765 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2766 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2767 & (1L << PRIVATE_FAX_NONSTANDARD))
2769 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2771 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2772 plci->fax_connect_info_buffer[len++] = 0;
2774 else
2776 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2777 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2778 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2779 for (i = 0; i < fax_parms[7].length; i++)
2780 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2785 else
2787 len = offsetof(T30_INFO, universal_6);
2789 fax_info_change = true;
2792 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2794 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2795 fax_info_change = true;
2798 if (Info == GOOD)
2800 plci->fax_connect_info_length = len;
2801 if (fax_info_change)
2803 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2805 start_internal_command(Id, plci, fax_connect_info_command);
2806 return false;
2808 else
2810 start_internal_command(Id, plci, fax_adjust_b23_command);
2811 return false;
2816 else Info = _WRONG_STATE;
2818 else Info = _WRONG_STATE;
2821 else if (plci->B3_prot == B3_RTP)
2823 plci->internal_req_buffer[0] = ncpi->length + 1;
2824 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2825 for (w = 0; w < ncpi->length; w++)
2826 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2827 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2828 return false;
2831 if (!Info)
2833 nl_req_ncci(plci, req, 0);
2834 return 1;
2838 else Info = _WRONG_IDENTIFIER;
2840 sendf(appl,
2841 _CONNECT_B3_R | CONFIRM,
2843 Number,
2844 "w", Info);
2845 return false;
2848 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2849 PLCI *plci, APPL *appl, API_PARSE *parms)
2851 word ncci;
2852 API_PARSE *ncpi;
2853 byte req;
2855 word w;
2858 API_PARSE fax_parms[9];
2859 word i;
2860 byte len;
2863 dbug(1, dprintf("connect_b3_res"));
2865 ncci = (word)(Id >> 16);
2866 if (plci && ncci) {
2867 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2868 if (GET_WORD(&parms[0].info[0]) != 0)
2870 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2871 channel_request_xon(plci, a->ncci_ch[ncci]);
2872 channel_xmit_xon(plci);
2873 cleanup_ncci_data(plci, ncci);
2874 nl_req_ncci(plci, N_DISC, (byte)ncci);
2875 return 1;
2877 a->ncci_state[ncci] = INC_ACT_PENDING;
2879 req = N_CONNECT_ACK;
2880 ncpi = &parms[1];
2881 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2885 & (1L << PRIVATE_FAX_NONSTANDARD))
2887 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2888 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2889 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2891 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2892 if (plci->fax_connect_info_length < len)
2894 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2895 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2897 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2899 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2901 else
2903 if (plci->fax_connect_info_length <= len)
2904 plci->fax_connect_info_buffer[len] = 0;
2905 len += 1 + plci->fax_connect_info_buffer[len];
2906 if (plci->fax_connect_info_length <= len)
2907 plci->fax_connect_info_buffer[len] = 0;
2908 len += 1 + plci->fax_connect_info_buffer[len];
2909 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2910 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2911 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2912 for (i = 0; i < fax_parms[7].length; i++)
2913 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2915 plci->fax_connect_info_length = len;
2916 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2917 start_internal_command(Id, plci, fax_connect_ack_command);
2918 return false;
2922 nl_req_ncci(plci, req, (byte)ncci);
2923 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2924 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2926 if (plci->B3_prot == 4)
2927 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2928 else
2929 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2930 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2934 else if (plci->B3_prot == B3_RTP)
2936 plci->internal_req_buffer[0] = ncpi->length + 1;
2937 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2938 for (w = 0; w < ncpi->length; w++)
2939 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2940 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2941 return false;
2944 else
2946 if (ncpi->length > 2) {
2947 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2948 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2950 nl_req_ncci(plci, req, (byte)ncci);
2951 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2952 if (plci->adjust_b_restore)
2954 plci->adjust_b_restore = false;
2955 start_internal_command(Id, plci, adjust_b_restore);
2958 return 1;
2961 return false;
2964 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2965 PLCI *plci, APPL *appl, API_PARSE *parms)
2967 word ncci;
2969 ncci = (word)(Id >> 16);
2970 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2972 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2973 && (plci->State != OUTG_DIS_PENDING))
2975 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2976 a->ncci_state[ncci] = CONNECTED;
2977 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2978 channel_request_xon(plci, a->ncci_ch[ncci]);
2979 channel_xmit_xon(plci);
2982 return false;
2985 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2986 PLCI *plci, APPL *appl, API_PARSE *parms)
2988 word Info;
2989 word ncci;
2990 API_PARSE *ncpi;
2992 dbug(1, dprintf("disconnect_b3_req"));
2994 Info = _WRONG_IDENTIFIER;
2995 ncci = (word)(Id >> 16);
2996 if (plci && ncci)
2998 Info = _WRONG_STATE;
2999 if ((a->ncci_state[ncci] == CONNECTED)
3000 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3001 || (a->ncci_state[ncci] == INC_CON_PENDING)
3002 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3004 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3005 channel_request_xon(plci, a->ncci_ch[ncci]);
3006 channel_xmit_xon(plci);
3008 if (a->ncci[ncci].data_pending
3009 && ((plci->B3_prot == B3_TRANSPARENT)
3010 || (plci->B3_prot == B3_T30)
3011 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3013 plci->send_disc = (byte)ncci;
3014 plci->command = 0;
3015 return false;
3017 else
3019 cleanup_ncci_data(plci, ncci);
3021 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3023 ncpi = &parms[0];
3024 if (ncpi->length > 3)
3026 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029 nl_req_ncci(plci, N_DISC, (byte)ncci);
3031 return 1;
3034 sendf(appl,
3035 _DISCONNECT_B3_R | CONFIRM,
3037 Number,
3038 "w", Info);
3039 return false;
3042 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3043 PLCI *plci, APPL *appl, API_PARSE *parms)
3045 word ncci;
3046 word i;
3048 ncci = (word)(Id >> 16);
3049 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3050 if (plci && ncci) {
3051 plci->requested_options_conn = 0;
3052 plci->fax_connect_info_length = 0;
3053 plci->ncpi_state = 0x00;
3054 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3055 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3057 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3059 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3060 if (i < MAX_CHANNELS_PER_PLCI) {
3061 if (plci->channels)plci->channels--;
3062 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3063 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3065 ncci_free_receive_buffers(plci, ncci);
3067 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3068 if (plci->State == SUSPENDING) {
3069 sendf(plci->appl,
3070 _FACILITY_I,
3071 Id & 0xffffL,
3073 "ws", (word)3, "\x03\x04\x00\x00");
3074 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3076 plci_remove(plci);
3077 plci->State = IDLE;
3080 else
3082 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3083 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3084 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3086 ncci_free_receive_buffers(plci, ncci);
3088 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3090 plci->adapter->ncci_state[ncci] = IDLE;
3091 start_internal_command(Id, plci, fax_disconnect_command);
3092 return 1;
3096 return false;
3099 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3100 PLCI *plci, APPL *appl, API_PARSE *parms)
3102 NCCI *ncci_ptr;
3103 DATA_B3_DESC *data;
3104 word Info;
3105 word ncci;
3106 word i;
3108 dbug(1, dprintf("data_b3_req"));
3110 Info = _WRONG_IDENTIFIER;
3111 ncci = (word)(Id >> 16);
3112 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3114 if (plci && ncci)
3116 Info = _WRONG_STATE;
3117 if ((a->ncci_state[ncci] == CONNECTED)
3118 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3120 /* queue data */
3121 ncci_ptr = &(a->ncci[ncci]);
3122 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3123 if (i >= MAX_DATA_B3)
3124 i -= MAX_DATA_B3;
3125 data = &(ncci_ptr->DBuffer[i]);
3126 data->Number = Number;
3127 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3128 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3134 else
3135 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3136 data->Length = GET_WORD(parms[1].info);
3137 data->Handle = GET_WORD(parms[2].info);
3138 data->Flags = GET_WORD(parms[3].info);
3139 (ncci_ptr->data_pending)++;
3141 /* check for delivery confirmation */
3142 if (data->Flags & 0x0004)
3144 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3145 if (i >= MAX_DATA_ACK)
3146 i -= MAX_DATA_ACK;
3147 ncci_ptr->DataAck[i].Number = data->Number;
3148 ncci_ptr->DataAck[i].Handle = data->Handle;
3149 (ncci_ptr->data_ack_pending)++;
3152 send_data(plci);
3153 return false;
3156 if (appl)
3158 if (plci)
3160 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3161 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3168 sendf(appl,
3169 _DATA_B3_R | CONFIRM,
3171 Number,
3172 "ww", GET_WORD(parms[2].info), Info);
3174 return false;
3177 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3178 PLCI *plci, APPL *appl, API_PARSE *parms)
3180 word n;
3181 word ncci;
3182 word NCCIcode;
3184 dbug(1, dprintf("data_b3_res"));
3186 ncci = (word)(Id >> 16);
3187 if (plci && ncci) {
3188 n = GET_WORD(parms[0].info);
3189 dbug(1, dprintf("free(%d)", n));
3190 NCCIcode = ncci | (((word) a->Id) << 8);
3191 if (n < appl->MaxBuffer &&
3192 appl->DataNCCI[n] == NCCIcode &&
3193 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3194 dbug(1, dprintf("found"));
3195 appl->DataNCCI[n] = 0;
3197 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3198 channel_request_xon(plci, a->ncci_ch[ncci]);
3200 channel_xmit_xon(plci);
3202 if (appl->DataFlags[n] & 4) {
3203 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3204 return 1;
3208 return false;
3211 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3212 PLCI *plci, APPL *appl, API_PARSE *parms)
3214 word Info;
3215 word ncci;
3217 dbug(1, dprintf("reset_b3_req"));
3219 Info = _WRONG_IDENTIFIER;
3220 ncci = (word)(Id >> 16);
3221 if (plci && ncci)
3223 Info = _WRONG_STATE;
3224 switch (plci->B3_prot)
3226 case B3_ISO8208:
3227 case B3_X25_DCE:
3228 if (a->ncci_state[ncci] == CONNECTED)
3230 nl_req_ncci(plci, N_RESET, (byte)ncci);
3231 send_req(plci);
3232 Info = GOOD;
3234 break;
3235 case B3_TRANSPARENT:
3236 if (a->ncci_state[ncci] == CONNECTED)
3238 start_internal_command(Id, plci, reset_b3_command);
3239 Info = GOOD;
3241 break;
3244 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3245 sendf(appl,
3246 _RESET_B3_R | CONFIRM,
3248 Number,
3249 "w", Info);
3250 return false;
3253 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3254 PLCI *plci, APPL *appl, API_PARSE *parms)
3256 word ncci;
3258 dbug(1, dprintf("reset_b3_res"));
3260 ncci = (word)(Id >> 16);
3261 if (plci && ncci) {
3262 switch (plci->B3_prot)
3264 case B3_ISO8208:
3265 case B3_X25_DCE:
3266 if (a->ncci_state[ncci] == INC_RES_PENDING)
3268 a->ncci_state[ncci] = CONNECTED;
3269 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3270 return true;
3272 break;
3275 return false;
3278 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3279 PLCI *plci, APPL *appl, API_PARSE *parms)
3281 word ncci;
3282 API_PARSE *ncpi;
3283 byte req;
3285 dbug(1, dprintf("connect_b3_t90_a_res"));
3287 ncci = (word)(Id >> 16);
3288 if (plci && ncci) {
3289 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3290 a->ncci_state[ncci] = CONNECTED;
3292 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3293 a->ncci_state[ncci] = CONNECTED;
3295 req = N_CONNECT_ACK;
3297 /* parms[0]==0 for CAPI original message definition! */
3298 if (parms[0].info) {
3299 ncpi = &parms[1];
3300 if (ncpi->length > 2) {
3301 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3302 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305 nl_req_ncci(plci, req, (byte)ncci);
3306 return 1;
3309 return false;
3313 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3314 PLCI *plci, APPL *appl, API_PARSE *msg)
3316 word Info = 0;
3317 word i;
3318 byte tel;
3319 API_PARSE bp_parms[7];
3321 if (!plci || !msg)
3323 Info = _WRONG_IDENTIFIER;
3325 else
3327 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3328 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3329 dbug(1, dprintf("PlciState=0x%x", plci->State));
3330 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3332 /* check if no channel is open, no B3 connected only */
3333 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3334 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3336 Info = _WRONG_STATE;
3338 /* check message format and fill bp_parms pointer */
3339 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3341 Info = _WRONG_MESSAGE_FORMAT;
3343 else
3345 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3346 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3347 if (Id & EXT_CONTROLLER)
3349 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3350 return 0;
3352 plci->State = INC_CON_CONNECTED_ALERT;
3353 plci->appl = appl;
3354 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3355 dump_c_ind_mask(plci);
3356 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3357 { /* its quasi a connect */
3358 if (test_c_ind_mask_bit(plci, i))
3359 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3363 api_save_msg(msg, "s", &plci->saved_msg);
3364 tel = plci->tel;
3365 if (Id & EXT_CONTROLLER)
3367 if (tel) /* external controller in use by this PLCI */
3369 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3371 dbug(1, dprintf("Ext_Ctrl in use 1"));
3372 Info = _WRONG_STATE;
3375 else /* external controller NOT in use by this PLCI ? */
3377 if (a->AdvSignalPLCI)
3379 dbug(1, dprintf("Ext_Ctrl in use 2"));
3380 Info = _WRONG_STATE;
3382 else /* activate the codec */
3384 dbug(1, dprintf("Ext_Ctrl start"));
3385 if (AdvCodecSupport(a, plci, appl, 0))
3387 dbug(1, dprintf("Error in codec procedures"));
3388 Info = _WRONG_STATE;
3390 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3392 plci->spoofed_msg = AWAITING_SELECT_B;
3393 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3394 plci->command = 0;
3395 dbug(1, dprintf("continue if codec loaded"));
3396 return false;
3401 else /* external controller bit is OFF */
3403 if (tel) /* external controller in use, need to switch off */
3405 if (a->AdvSignalAppl == appl)
3407 CodecIdCheck(a, plci);
3408 plci->tel = 0;
3409 plci->adv_nl = 0;
3410 dbug(1, dprintf("Ext_Ctrl disable"));
3412 else
3414 dbug(1, dprintf("Ext_Ctrl not requested"));
3418 if (!Info)
3420 if (plci->call_dir & CALL_DIR_OUT)
3421 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3422 else if (plci->call_dir & CALL_DIR_IN)
3423 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3424 start_internal_command(Id, plci, select_b_command);
3425 return false;
3429 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3430 return false;
3433 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3434 PLCI *plci, APPL *appl, API_PARSE *parms)
3436 word command;
3437 word i;
3438 word ncci;
3439 API_PARSE *m;
3440 API_PARSE m_parms[5];
3441 word codec;
3442 byte req;
3443 byte ch;
3444 byte dir;
3445 static byte chi[2] = {0x01, 0x00};
3446 static byte lli[2] = {0x01, 0x00};
3447 static byte codec_cai[2] = {0x01, 0x01};
3448 static byte null_msg = {0};
3449 static API_PARSE null_parms = { 0, &null_msg };
3450 PLCI *v_plci;
3451 word Info = 0;
3453 dbug(1, dprintf("manufacturer_req"));
3454 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3456 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3457 Info = _WRONG_MESSAGE_FORMAT;
3459 command = GET_WORD(parms[1].info);
3460 m = &parms[2];
3461 if (!Info)
3463 switch (command) {
3464 case _DI_ASSIGN_PLCI:
3465 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3466 Info = _WRONG_MESSAGE_FORMAT;
3467 break;
3469 codec = GET_WORD(m_parms[0].info);
3470 ch = m_parms[1].info[0];
3471 dir = m_parms[2].info[0];
3472 if ((i = get_plci(a))) {
3473 plci = &a->plci[i - 1];
3474 plci->appl = appl;
3475 plci->command = _MANUFACTURER_R;
3476 plci->m_command = command;
3477 plci->number = Number;
3478 plci->State = LOCAL_CONNECT;
3479 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3480 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3482 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3483 chi[1] = (byte)(0x80 | ch);
3484 lli[1] = 0;
3485 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3486 switch (codec)
3488 case 0:
3489 Info = add_b1(plci, &m_parms[3], 0, 0);
3490 break;
3491 case 1:
3492 add_p(plci, CAI, codec_cai);
3493 break;
3494 /* manual 'swich on' to the codec support without signalling */
3495 /* first 'assign plci' with this function, then use */
3496 case 2:
3497 if (AdvCodecSupport(a, plci, appl, 0)) {
3498 Info = _RESOURCE_ERROR;
3500 else {
3501 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3502 lli[1] = 0x10; /* local call codec stream */
3504 break;
3507 plci->State = LOCAL_CONNECT;
3508 plci->manufacturer = true;
3509 plci->command = _MANUFACTURER_R;
3510 plci->m_command = command;
3511 plci->number = Number;
3513 if (!Info)
3515 add_p(plci, LLI, lli);
3516 add_p(plci, CHI, chi);
3517 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3518 sig_req(plci, ASSIGN, DSIG_ID);
3520 if (!codec)
3522 Info = add_b23(plci, &m_parms[3]);
3523 if (!Info)
3525 nl_req_ncci(plci, ASSIGN, 0);
3526 send_req(plci);
3529 if (!Info)
3531 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3532 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3534 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3535 plci->spoofed_msg = AWAITING_MANUF_CON;
3536 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3537 plci->command = 0;
3538 send_req(plci);
3539 return false;
3541 if (dir == 1) {
3542 sig_req(plci, CALL_REQ, 0);
3544 else if (!dir) {
3545 sig_req(plci, LISTEN_REQ, 0);
3547 send_req(plci);
3549 else
3551 sendf(appl,
3552 _MANUFACTURER_R | CONFIRM,
3554 Number,
3555 "dww", _DI_MANU_ID, command, Info);
3556 return 2;
3561 else Info = _OUT_OF_PLCI;
3562 break;
3564 case _DI_IDI_CTRL:
3565 if (!plci)
3567 Info = _WRONG_IDENTIFIER;
3568 break;
3570 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3571 Info = _WRONG_MESSAGE_FORMAT;
3572 break;
3574 req = m_parms[0].info[0];
3575 plci->command = _MANUFACTURER_R;
3576 plci->m_command = command;
3577 plci->number = Number;
3578 if (req == CALL_REQ)
3580 plci->b_channel = getChannel(&m_parms[1]);
3581 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3582 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3584 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3585 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3586 plci->command = 0;
3587 break;
3590 else if (req == LAW_REQ)
3592 plci->cr_enquiry = true;
3594 add_ss(plci, FTY, &m_parms[1]);
3595 sig_req(plci, req, 0);
3596 send_req(plci);
3597 if (req == HANGUP)
3599 if (plci->NL.Id && !plci->nl_remove_id)
3601 if (plci->channels)
3603 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3605 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3607 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3608 cleanup_ncci_data(plci, ncci);
3609 nl_req_ncci(plci, N_DISC, (byte)ncci);
3613 mixer_remove(plci);
3614 nl_req_ncci(plci, REMOVE, 0);
3615 send_req(plci);
3618 break;
3620 case _DI_SIG_CTRL:
3621 /* signalling control for loop activation B-channel */
3622 if (!plci)
3624 Info = _WRONG_IDENTIFIER;
3625 break;
3627 if (m->length) {
3628 plci->command = _MANUFACTURER_R;
3629 plci->number = Number;
3630 add_ss(plci, FTY, m);
3631 sig_req(plci, SIG_CTRL, 0);
3632 send_req(plci);
3634 else Info = _WRONG_MESSAGE_FORMAT;
3635 break;
3637 case _DI_RXT_CTRL:
3638 /* activation control for receiver/transmitter B-channel */
3639 if (!plci)
3641 Info = _WRONG_IDENTIFIER;
3642 break;
3644 if (m->length) {
3645 plci->command = _MANUFACTURER_R;
3646 plci->number = Number;
3647 add_ss(plci, FTY, m);
3648 sig_req(plci, DSP_CTRL, 0);
3649 send_req(plci);
3651 else Info = _WRONG_MESSAGE_FORMAT;
3652 break;
3654 case _DI_ADV_CODEC:
3655 case _DI_DSP_CTRL:
3656 /* TEL_CTRL commands to support non standard adjustments: */
3657 /* Ring on/off, Handset micro volume, external micro vol. */
3658 /* handset+external speaker volume, receiver+transm. gain,*/
3659 /* handsfree on (hookinfo off), set mixer command */
3661 if (command == _DI_ADV_CODEC)
3663 if (!a->AdvCodecPLCI) {
3664 Info = _WRONG_STATE;
3665 break;
3667 v_plci = a->AdvCodecPLCI;
3669 else
3671 if (plci
3672 && (m->length >= 3)
3673 && (m->info[1] == 0x1c)
3674 && (m->info[2] >= 1))
3676 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3678 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3680 Info = _WRONG_STATE;
3681 break;
3683 a->adv_voice_coef_length = m->info[2] - 1;
3684 if (a->adv_voice_coef_length > m->length - 3)
3685 a->adv_voice_coef_length = (byte)(m->length - 3);
3686 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3687 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3688 for (i = 0; i < a->adv_voice_coef_length; i++)
3689 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3690 if (plci->B1_facilities & B1_FACILITY_VOICE)
3691 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3692 break;
3694 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3696 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3698 Info = _FACILITY_NOT_SUPPORTED;
3699 break;
3702 plci->dtmf_parameter_length = m->info[2] - 1;
3703 if (plci->dtmf_parameter_length > m->length - 3)
3704 plci->dtmf_parameter_length = (byte)(m->length - 3);
3705 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3706 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3707 for (i = 0; i < plci->dtmf_parameter_length; i++)
3708 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3709 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3710 dtmf_parameter_write(plci);
3711 break;
3715 v_plci = plci;
3718 if (!v_plci)
3720 Info = _WRONG_IDENTIFIER;
3721 break;
3723 if (m->length) {
3724 add_ss(v_plci, FTY, m);
3725 sig_req(v_plci, TEL_CTRL, 0);
3726 send_req(v_plci);
3728 else Info = _WRONG_MESSAGE_FORMAT;
3730 break;
3732 case _DI_OPTIONS_REQUEST:
3733 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3734 Info = _WRONG_MESSAGE_FORMAT;
3735 break;
3737 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3739 Info = _FACILITY_NOT_SUPPORTED;
3740 break;
3742 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3743 break;
3747 default:
3748 Info = _WRONG_MESSAGE_FORMAT;
3749 break;
3753 sendf(appl,
3754 _MANUFACTURER_R | CONFIRM,
3756 Number,
3757 "dww", _DI_MANU_ID, command, Info);
3758 return false;
3762 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3763 PLCI *plci, APPL *appl, API_PARSE *msg)
3765 word indication;
3767 API_PARSE m_parms[3];
3768 API_PARSE *ncpi;
3769 API_PARSE fax_parms[9];
3770 word i;
3771 byte len;
3774 dbug(1, dprintf("manufacturer_res"));
3776 if ((msg[0].length == 0)
3777 || (msg[1].length == 0)
3778 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3780 return false;
3782 indication = GET_WORD(msg[1].info);
3783 switch (indication)
3786 case _DI_NEGOTIATE_B3:
3787 if (!plci)
3788 break;
3789 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3790 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3792 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3793 break;
3795 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3797 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3798 break;
3800 ncpi = &m_parms[1];
3801 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3802 if (plci->fax_connect_info_length < len)
3804 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3805 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3807 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3809 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3811 else
3813 if (plci->fax_connect_info_length <= len)
3814 plci->fax_connect_info_buffer[len] = 0;
3815 len += 1 + plci->fax_connect_info_buffer[len];
3816 if (plci->fax_connect_info_length <= len)
3817 plci->fax_connect_info_buffer[len] = 0;
3818 len += 1 + plci->fax_connect_info_buffer[len];
3819 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3820 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3821 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3822 for (i = 0; i < fax_parms[7].length; i++)
3823 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3825 plci->fax_connect_info_length = len;
3826 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3827 start_internal_command(Id, plci, fax_edata_ack_command);
3828 break;
3831 return false;
3834 /*------------------------------------------------------------------*/
3835 /* IDI callback function */
3836 /*------------------------------------------------------------------*/
3838 void callback(ENTITY *e)
3840 DIVA_CAPI_ADAPTER *a;
3841 APPL *appl;
3842 PLCI *plci;
3843 CAPI_MSG *m;
3844 word i, j;
3845 byte rc;
3846 byte ch;
3847 byte req;
3848 byte global_req;
3849 int no_cancel_rc;
3851 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3852 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3854 a = &(adapter[(byte)e->user[0]]);
3855 plci = &(a->plci[e->user[1]]);
3856 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859 If new protocol code and new XDI is used then CAPI should work
3860 fully in accordance with IDI cpec an look on callback field instead
3861 of Rc field for return codes.
3863 if (((e->complete == 0xff) && no_cancel_rc) ||
3864 (e->Rc && !no_cancel_rc)) {
3865 rc = e->Rc;
3866 ch = e->RcCh;
3867 req = e->Req;
3868 e->Rc = 0;
3870 if (e->user[0] & 0x8000)
3873 If REMOVE request was sent then we have to wait until
3874 return code with Id set to zero arrives.
3875 All other return codes should be ignored.
3877 if (req == REMOVE)
3879 if (e->Id)
3881 dbug(1, dprintf("cancel RC in REMOVE state"));
3882 return;
3884 channel_flow_control_remove(plci);
3885 for (i = 0; i < 256; i++)
3887 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3888 a->FlowControlIdTable[i] = 0;
3890 plci->nl_remove_id = 0;
3891 if (plci->rx_dma_descriptor > 0) {
3892 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3893 plci->rx_dma_descriptor = 0;
3896 if (rc == OK_FC)
3898 a->FlowControlIdTable[ch] = e->Id;
3899 a->FlowControlSkipTable[ch] = 0;
3901 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3902 a->ch_flow_plci[ch] = plci->Id;
3903 plci->nl_req = 0;
3905 else
3908 Cancel return codes self, if feature was requested
3910 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3911 a->FlowControlIdTable[ch] = 0;
3912 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3913 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3914 return;
3918 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3920 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3921 if (ch == e->ReqCh)
3922 plci->nl_req = 0;
3924 else
3925 plci->nl_req = 0;
3927 if (plci->nl_req)
3928 control_rc(plci, 0, rc, ch, 0, true);
3929 else
3931 if (req == N_XON)
3933 channel_x_on(plci, ch);
3934 if (plci->internal_command)
3935 control_rc(plci, req, rc, ch, 0, true);
3937 else
3939 if (plci->nl_global_req)
3941 global_req = plci->nl_global_req;
3942 plci->nl_global_req = 0;
3943 if (rc != ASSIGN_OK) {
3944 e->Id = 0;
3945 if (plci->rx_dma_descriptor > 0) {
3946 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3947 plci->rx_dma_descriptor = 0;
3950 channel_xmit_xon(plci);
3951 control_rc(plci, 0, rc, ch, global_req, true);
3953 else if (plci->data_sent)
3955 channel_xmit_xon(plci);
3956 plci->data_sent = false;
3957 plci->NL.XNum = 1;
3958 data_rc(plci, ch);
3959 if (plci->internal_command)
3960 control_rc(plci, req, rc, ch, 0, true);
3962 else
3964 channel_xmit_xon(plci);
3965 control_rc(plci, req, rc, ch, 0, true);
3970 else
3973 If REMOVE request was sent then we have to wait until
3974 return code with Id set to zero arrives.
3975 All other return codes should be ignored.
3977 if (req == REMOVE)
3979 if (e->Id)
3981 dbug(1, dprintf("cancel RC in REMOVE state"));
3982 return;
3984 plci->sig_remove_id = 0;
3986 plci->sig_req = 0;
3987 if (plci->sig_global_req)
3989 global_req = plci->sig_global_req;
3990 plci->sig_global_req = 0;
3991 if (rc != ASSIGN_OK)
3992 e->Id = 0;
3993 channel_xmit_xon(plci);
3994 control_rc(plci, 0, rc, ch, global_req, false);
3996 else
3998 channel_xmit_xon(plci);
3999 control_rc(plci, req, rc, ch, 0, false);
4003 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4004 same callback. Also if new XDI and protocol code used then jump
4005 direct to finish.
4007 if (no_cancel_rc) {
4008 channel_xmit_xon(plci);
4009 goto capi_callback_suffix;
4013 channel_xmit_xon(plci);
4015 if (e->Ind) {
4016 if (e->user[0] & 0x8000) {
4017 byte Ind = e->Ind & 0x0f;
4018 byte Ch = e->IndCh;
4019 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4020 (a->ch_flow_plci[Ch] == plci->Id)) {
4021 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4022 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4024 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4026 nl_ind(plci);
4027 if ((e->RNR != 1) &&
4028 (a->ch_flow_plci[Ch] == plci->Id) &&
4029 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4030 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4031 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4033 } else {
4034 sig_ind(plci);
4036 e->Ind = 0;
4039 capi_callback_suffix:
4041 while (!plci->req_in
4042 && !plci->internal_command
4043 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4045 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4047 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4049 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4050 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4051 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4052 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4053 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4055 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4056 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4058 else
4060 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4062 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4064 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4065 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4067 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4069 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4072 i = api_put(appl, m);
4073 if (i != 0)
4075 if (m->header.command == _DATA_B3_R)
4077 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4079 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4080 break;
4083 if (plci->li_notify_update)
4085 plci->li_notify_update = false;
4086 mixer_notify_update(plci, false);
4090 send_data(plci);
4091 send_req(plci);
4095 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4096 byte nl_rc)
4098 dword Id;
4099 dword rId;
4100 word Number;
4101 word Info = 0;
4102 word i;
4103 word ncci;
4104 DIVA_CAPI_ADAPTER *a;
4105 APPL *appl;
4106 PLCI *rplci;
4107 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4108 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4110 if (!plci) {
4111 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4112 return;
4114 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4115 if (plci->req_in != plci->req_out)
4117 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4119 dbug(1, dprintf("req_1return"));
4120 return;
4122 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4124 plci->req_in = plci->req_in_start = plci->req_out = 0;
4125 dbug(1, dprintf("control_rc"));
4127 appl = plci->appl;
4128 a = plci->adapter;
4129 ncci = a->ch_ncci[ch];
4130 if (appl)
4132 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4133 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4134 Number = plci->number;
4135 dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4136 dbug(1, dprintf("channels=0x%x", plci->channels));
4137 if (plci_remove_check(plci))
4138 return;
4139 if (req == REMOVE && rc == ASSIGN_OK)
4141 sig_req(plci, HANGUP, 0);
4142 sig_req(plci, REMOVE, 0);
4143 send_req(plci);
4145 if (plci->command)
4147 switch (plci->command)
4149 case C_HOLD_REQ:
4150 dbug(1, dprintf("HoldRC=0x%x", rc));
4151 SSparms[1] = (byte)S_HOLD;
4152 if (rc != OK)
4154 plci->SuppState = IDLE;
4155 Info = 0x2001;
4157 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4158 break;
4160 case C_RETRIEVE_REQ:
4161 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4162 SSparms[1] = (byte)S_RETRIEVE;
4163 if (rc != OK)
4165 plci->SuppState = CALL_HELD;
4166 Info = 0x2001;
4168 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4169 break;
4171 case _INFO_R:
4172 dbug(1, dprintf("InfoRC=0x%x", rc));
4173 if (rc != OK) Info = _WRONG_STATE;
4174 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4175 break;
4177 case _CONNECT_R:
4178 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4179 if (plci->State == INC_DIS_PENDING)
4180 break;
4181 if (plci->Sig.Id != 0xff)
4183 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4184 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4186 dbug(1, dprintf("No more IDs/Call_Req failed"));
4187 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4188 plci_remove(plci);
4189 plci->State = IDLE;
4190 break;
4192 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4193 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4195 else /* D-ch activation */
4197 if (rc != ASSIGN_OK)
4199 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4200 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4201 plci_remove(plci);
4202 plci->State = IDLE;
4203 break;
4205 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4206 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4207 plci->State = INC_ACT_PENDING;
4209 break;
4211 case _CONNECT_I | RESPONSE:
4212 if (plci->State != INC_DIS_PENDING)
4213 plci->State = INC_CON_ACCEPT;
4214 break;
4216 case _DISCONNECT_R:
4217 if (plci->State == INC_DIS_PENDING)
4218 break;
4219 if (plci->Sig.Id != 0xff)
4221 plci->State = OUTG_DIS_PENDING;
4222 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4224 break;
4226 case SUSPEND_REQ:
4227 break;
4229 case RESUME_REQ:
4230 break;
4232 case _CONNECT_B3_R:
4233 if (rc != OK)
4235 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4236 break;
4238 ncci = get_ncci(plci, ch, 0);
4239 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4240 plci->channels++;
4241 if (req == N_RESET)
4243 a->ncci_state[ncci] = INC_ACT_PENDING;
4244 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4245 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4247 else
4249 a->ncci_state[ncci] = OUTG_CON_PENDING;
4250 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4252 break;
4254 case _CONNECT_B3_I | RESPONSE:
4255 break;
4257 case _RESET_B3_R:
4258 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4259 break;
4261 case _DISCONNECT_B3_R:
4262 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4263 break;
4265 case _MANUFACTURER_R:
4266 break;
4268 case PERM_LIST_REQ:
4269 if (rc != OK)
4271 Info = _WRONG_IDENTIFIER;
4272 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4273 plci_remove(plci);
4275 else
4276 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4277 break;
4279 default:
4280 break;
4282 plci->command = 0;
4284 else if (plci->internal_command)
4286 switch (plci->internal_command)
4288 case BLOCK_PLCI:
4289 return;
4291 case GET_MWI_STATE:
4292 if (rc == OK) /* command supported, wait for indication */
4294 return;
4296 plci_remove(plci);
4297 break;
4299 /* Get Supported Services */
4300 case GETSERV_REQ_PEND:
4301 if (rc == OK) /* command supported, wait for indication */
4303 break;
4305 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4306 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4307 plci_remove(plci);
4308 break;
4310 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4311 case INTERR_NUMBERS_REQ_PEND:
4312 case CF_START_PEND: /* Call Forwarding Start pending */
4313 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4314 case CCBS_REQUEST_REQ_PEND:
4315 case CCBS_DEACTIVATE_REQ_PEND:
4316 case CCBS_INTERROGATE_REQ_PEND:
4317 switch (plci->internal_command)
4319 case INTERR_DIVERSION_REQ_PEND:
4320 SSparms[1] = S_INTERROGATE_DIVERSION;
4321 break;
4322 case INTERR_NUMBERS_REQ_PEND:
4323 SSparms[1] = S_INTERROGATE_NUMBERS;
4324 break;
4325 case CF_START_PEND:
4326 SSparms[1] = S_CALL_FORWARDING_START;
4327 break;
4328 case CF_STOP_PEND:
4329 SSparms[1] = S_CALL_FORWARDING_STOP;
4330 break;
4331 case CCBS_REQUEST_REQ_PEND:
4332 SSparms[1] = S_CCBS_REQUEST;
4333 break;
4334 case CCBS_DEACTIVATE_REQ_PEND:
4335 SSparms[1] = S_CCBS_DEACTIVATE;
4336 break;
4337 case CCBS_INTERROGATE_REQ_PEND:
4338 SSparms[1] = S_CCBS_INTERROGATE;
4339 break;
4341 if (global_req == ASSIGN)
4343 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4344 return;
4346 if (!plci->appl) break;
4347 if (rc == ISDN_GUARD_REJ)
4349 Info = _CAPI_GUARD_ERROR;
4351 else if (rc != OK)
4353 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4355 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4356 plci->number, "wws", Info, (word)3, SSparms);
4357 if (Info) plci_remove(plci);
4358 break;
4360 /* 3pty conference pending */
4361 case PTY_REQ_PEND:
4362 if (!plci->relatedPTYPLCI) break;
4363 rplci = plci->relatedPTYPLCI;
4364 SSparms[1] = plci->ptyState;
4365 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4366 if (rplci->tel) rId |= EXT_CONTROLLER;
4367 if (rc != OK)
4369 Info = 0x300E; /* not supported */
4370 plci->relatedPTYPLCI = NULL;
4371 plci->ptyState = 0;
4373 sendf(rplci->appl,
4374 _FACILITY_R | CONFIRM,
4375 rId,
4376 plci->number,
4377 "wws", Info, (word)3, SSparms);
4378 break;
4380 /* Explicit Call Transfer pending */
4381 case ECT_REQ_PEND:
4382 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4383 if (!plci->relatedPTYPLCI) break;
4384 rplci = plci->relatedPTYPLCI;
4385 SSparms[1] = S_ECT;
4386 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4387 if (rplci->tel) rId |= EXT_CONTROLLER;
4388 if (rc != OK)
4390 Info = 0x300E; /* not supported */
4391 plci->relatedPTYPLCI = NULL;
4392 plci->ptyState = 0;
4394 sendf(rplci->appl,
4395 _FACILITY_R | CONFIRM,
4396 rId,
4397 plci->number,
4398 "wws", Info, (word)3, SSparms);
4399 break;
4401 case _MANUFACTURER_R:
4402 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4403 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4405 dbug(1, dprintf("No more IDs"));
4406 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4407 plci_remove(plci); /* after codec init, internal codec commands pending */
4409 break;
4411 case _CONNECT_R:
4412 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4413 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4415 dbug(1, dprintf("No more IDs"));
4416 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4417 plci_remove(plci); /* after codec init, internal codec commands pending */
4419 break;
4421 case PERM_COD_HOOK: /* finished with Hook_Ind */
4422 return;
4424 case PERM_COD_CALL:
4425 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4426 plci->internal_command = PERM_COD_CONN_PEND;
4427 return;
4429 case PERM_COD_ASSIGN:
4430 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4431 if (rc != ASSIGN_OK) break;
4432 sig_req(plci, CALL_REQ, 0);
4433 send_req(plci);
4434 plci->internal_command = PERM_COD_CALL;
4435 return;
4437 /* Null Call Reference Request pending */
4438 case C_NCR_FAC_REQ:
4439 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4440 if (global_req == ASSIGN)
4442 if (rc == ASSIGN_OK)
4444 return;
4446 else
4448 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4449 appl->NullCREnable = false;
4450 plci_remove(plci);
4453 else if (req == NCR_FACILITY)
4455 if (rc == OK)
4457 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4459 else
4461 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4462 appl->NullCREnable = false;
4464 plci_remove(plci);
4466 break;
4468 case HOOK_ON_REQ:
4469 if (plci->channels)
4471 if (a->ncci_state[ncci] == CONNECTED)
4473 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4474 cleanup_ncci_data(plci, ncci);
4475 nl_req_ncci(plci, N_DISC, (byte)ncci);
4477 break;
4479 break;
4481 case HOOK_OFF_REQ:
4482 if (plci->State == INC_DIS_PENDING)
4483 break;
4484 sig_req(plci, CALL_REQ, 0);
4485 send_req(plci);
4486 plci->State = OUTG_CON_PENDING;
4487 break;
4490 case MWI_ACTIVATE_REQ_PEND:
4491 case MWI_DEACTIVATE_REQ_PEND:
4492 if (global_req == ASSIGN && rc == ASSIGN_OK)
4494 dbug(1, dprintf("MWI_REQ assigned"));
4495 return;
4497 else if (rc != OK)
4499 if (rc == WRONG_IE)
4501 Info = 0x2007; /* Illegal message parameter coding */
4502 dbug(1, dprintf("MWI_REQ invalid parameter"));
4504 else
4506 Info = 0x300B; /* not supported */
4507 dbug(1, dprintf("MWI_REQ not supported"));
4509 /* 0x3010: Request not allowed in this state */
4510 PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4515 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4517 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4519 if (plci->cr_enquiry)
4521 sendf(plci->appl,
4522 _FACILITY_R | CONFIRM,
4523 Id & 0xf,
4524 plci->number,
4525 "wws", Info, (word)3, SSparms);
4526 if (rc != OK) plci_remove(plci);
4528 else
4530 sendf(plci->appl,
4531 _FACILITY_R | CONFIRM,
4533 plci->number,
4534 "wws", Info, (word)3, SSparms);
4536 break;
4538 case CONF_BEGIN_REQ_PEND:
4539 case CONF_ADD_REQ_PEND:
4540 case CONF_SPLIT_REQ_PEND:
4541 case CONF_DROP_REQ_PEND:
4542 case CONF_ISOLATE_REQ_PEND:
4543 case CONF_REATTACH_REQ_PEND:
4544 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4545 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4546 rplci = plci;
4547 rId = Id;
4548 switch (plci->internal_command)
4550 case CONF_BEGIN_REQ_PEND:
4551 SSparms[1] = S_CONF_BEGIN;
4552 break;
4553 case CONF_ADD_REQ_PEND:
4554 SSparms[1] = S_CONF_ADD;
4555 rplci = plci->relatedPTYPLCI;
4556 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4557 break;
4558 case CONF_SPLIT_REQ_PEND:
4559 SSparms[1] = S_CONF_SPLIT;
4560 break;
4561 case CONF_DROP_REQ_PEND:
4562 SSparms[1] = S_CONF_DROP;
4563 break;
4564 case CONF_ISOLATE_REQ_PEND:
4565 SSparms[1] = S_CONF_ISOLATE;
4566 break;
4567 case CONF_REATTACH_REQ_PEND:
4568 SSparms[1] = S_CONF_REATTACH;
4569 break;
4572 if (rc != OK)
4574 Info = 0x300E; /* not supported */
4575 plci->relatedPTYPLCI = NULL;
4576 plci->ptyState = 0;
4578 sendf(rplci->appl,
4579 _FACILITY_R | CONFIRM,
4580 rId,
4581 plci->number,
4582 "wws", Info, (word)3, SSparms);
4583 break;
4585 case VSWITCH_REQ_PEND:
4586 if (rc != OK)
4588 if (plci->relatedPTYPLCI)
4590 plci->relatedPTYPLCI->vswitchstate = 0;
4591 plci->relatedPTYPLCI->vsprot = 0;
4592 plci->relatedPTYPLCI->vsprotdialect = 0;
4594 plci->vswitchstate = 0;
4595 plci->vsprot = 0;
4596 plci->vsprotdialect = 0;
4598 else
4600 if (plci->relatedPTYPLCI &&
4601 plci->vswitchstate == 1 &&
4602 plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4603 plci->vswitchstate = 3;
4605 break;
4607 /* Call Deflection Request pending (SSCT) */
4608 case CD_REQ_PEND:
4609 SSparms[1] = S_CALL_DEFLECTION;
4610 if (rc != OK)
4612 Info = 0x300E; /* not supported */
4613 plci->appl->CDEnable = 0;
4615 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4616 plci->number, "wws", Info, (word)3, SSparms);
4617 break;
4619 case RTP_CONNECT_B3_REQ_COMMAND_2:
4620 if (rc == OK)
4622 ncci = get_ncci(plci, ch, 0);
4623 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4624 plci->channels++;
4625 a->ncci_state[ncci] = OUTG_CON_PENDING;
4628 default:
4629 if (plci->internal_command_queue[0])
4631 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4632 if (plci->internal_command)
4633 return;
4635 break;
4637 next_internal_command(Id, plci);
4640 else /* appl==0 */
4642 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4643 if (plci->tel) Id |= EXT_CONTROLLER;
4645 switch (plci->internal_command)
4647 case BLOCK_PLCI:
4648 return;
4650 case START_L1_SIG_ASSIGN_PEND:
4651 case REM_L1_SIG_ASSIGN_PEND:
4652 if (global_req == ASSIGN)
4654 break;
4656 else
4658 dbug(1, dprintf("***L1 Req rem PLCI"));
4659 plci->internal_command = 0;
4660 sig_req(plci, REMOVE, 0);
4661 send_req(plci);
4663 break;
4665 /* Call Deflection Request pending, just no appl ptr assigned */
4666 case CD_REQ_PEND:
4667 SSparms[1] = S_CALL_DEFLECTION;
4668 if (rc != OK)
4670 Info = 0x300E; /* not supported */
4672 for (i = 0; i < max_appl; i++)
4674 if (application[i].CDEnable)
4676 if (!application[i].Id) application[i].CDEnable = 0;
4677 else
4679 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4680 plci->number, "wws", Info, (word)3, SSparms);
4681 if (Info) application[i].CDEnable = 0;
4685 plci->internal_command = 0;
4686 break;
4688 case PERM_COD_HOOK: /* finished with Hook_Ind */
4689 return;
4691 case PERM_COD_CALL:
4692 plci->internal_command = PERM_COD_CONN_PEND;
4693 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4694 return;
4696 case PERM_COD_ASSIGN:
4697 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4698 plci->internal_command = 0;
4699 if (rc != ASSIGN_OK) break;
4700 plci->internal_command = PERM_COD_CALL;
4701 sig_req(plci, CALL_REQ, 0);
4702 send_req(plci);
4703 return;
4705 case LISTEN_SIG_ASSIGN_PEND:
4706 if (rc == ASSIGN_OK)
4708 plci->internal_command = 0;
4709 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4710 add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4711 sig_req(plci, INDICATE_REQ, 0);
4712 send_req(plci);
4714 else
4716 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4717 a->listen_active--;
4718 plci_remove(plci);
4719 plci->State = IDLE;
4721 break;
4723 case USELAW_REQ:
4724 if (global_req == ASSIGN)
4726 if (rc == ASSIGN_OK)
4728 sig_req(plci, LAW_REQ, 0);
4729 send_req(plci);
4730 dbug(1, dprintf("Auto-Law assigned"));
4732 else
4734 dbug(1, dprintf("Auto-Law assign failed"));
4735 a->automatic_law = 3;
4736 plci->internal_command = 0;
4737 a->automatic_lawPLCI = NULL;
4739 break;
4741 else if (req == LAW_REQ && rc == OK)
4743 dbug(1, dprintf("Auto-Law initiated"));
4744 a->automatic_law = 2;
4745 plci->internal_command = 0;
4747 else
4749 dbug(1, dprintf("Auto-Law not supported"));
4750 a->automatic_law = 3;
4751 plci->internal_command = 0;
4752 sig_req(plci, REMOVE, 0);
4753 send_req(plci);
4754 a->automatic_lawPLCI = NULL;
4756 break;
4758 plci_remove_check(plci);
4762 static void data_rc(PLCI *plci, byte ch)
4764 dword Id;
4765 DIVA_CAPI_ADAPTER *a;
4766 NCCI *ncci_ptr;
4767 DATA_B3_DESC *data;
4768 word ncci;
4770 if (plci->appl)
4772 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4773 a = plci->adapter;
4774 ncci = a->ch_ncci[ch];
4775 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4777 ncci_ptr = &(a->ncci[ncci]);
4778 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4779 if (ncci_ptr->data_pending)
4781 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4782 if (!(data->Flags & 4) && a->ncci_state[ncci])
4784 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4785 if (plci->tel) Id |= EXT_CONTROLLER;
4786 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4787 "ww", data->Handle, 0);
4789 (ncci_ptr->data_out)++;
4790 if (ncci_ptr->data_out == MAX_DATA_B3)
4791 ncci_ptr->data_out = 0;
4792 (ncci_ptr->data_pending)--;
4798 static void data_ack(PLCI *plci, byte ch)
4800 dword Id;
4801 DIVA_CAPI_ADAPTER *a;
4802 NCCI *ncci_ptr;
4803 word ncci;
4805 a = plci->adapter;
4806 ncci = a->ch_ncci[ch];
4807 ncci_ptr = &(a->ncci[ncci]);
4808 if (ncci_ptr->data_ack_pending)
4810 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4812 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4813 if (plci->tel) Id |= EXT_CONTROLLER;
4814 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4815 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4817 (ncci_ptr->data_ack_out)++;
4818 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4819 ncci_ptr->data_ack_out = 0;
4820 (ncci_ptr->data_ack_pending)--;
4824 static void sig_ind(PLCI *plci)
4826 dword x_Id;
4827 dword Id;
4828 dword rId;
4829 word i;
4830 word cip;
4831 dword cip_mask;
4832 byte *ie;
4833 DIVA_CAPI_ADAPTER *a;
4834 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4835 #define MAXPARMSIDS 31
4836 byte *parms[MAXPARMSIDS];
4837 byte *add_i[4];
4838 byte *multi_fac_parms[MAX_MULTI_IE];
4839 byte *multi_pi_parms[MAX_MULTI_IE];
4840 byte *multi_ssext_parms[MAX_MULTI_IE];
4841 byte *multi_CiPN_parms[MAX_MULTI_IE];
4843 byte *multi_vswitch_parms[MAX_MULTI_IE];
4845 byte ai_len;
4846 byte *esc_chi = "";
4847 byte *esc_law = "";
4848 byte *pty_cai = "";
4849 byte *esc_cr = "";
4850 byte *esc_profile = "";
4852 byte facility[256];
4853 PLCI *tplci = NULL;
4854 byte chi[] = "\x02\x18\x01";
4855 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4856 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4857 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4858 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4859 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4860 /* (see Info_Mask Bit 4, first IE. then the message type) */
4861 word parms_id[] =
4862 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4863 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4864 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4865 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4866 /* 14 FTY repl by ESC_CHI */
4867 /* 18 PI repl by ESC_LAW */
4868 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4869 word multi_fac_id[] = {1, FTY};
4870 word multi_pi_id[] = {1, PI};
4871 word multi_CiPN_id[] = {1, OAD};
4872 word multi_ssext_id[] = {1, ESC_SSEXT};
4874 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4876 byte *cau;
4877 word ncci;
4878 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4879 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4880 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4881 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4882 byte force_mt_info = false;
4883 byte dir;
4884 dword d;
4885 word w;
4887 a = plci->adapter;
4888 Id = ((word)plci->Id << 8) | a->Id;
4889 PUT_WORD(&SS_Ind[4], 0x0000);
4891 if (plci->sig_remove_id)
4893 plci->Sig.RNR = 2; /* discard */
4894 dbug(1, dprintf("SIG discard while remove pending"));
4895 return;
4897 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4898 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4899 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4900 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4902 plci->Sig.RNR = 1;
4903 return;
4905 if (plci->Sig.Ind == HANGUP && plci->channels)
4907 plci->Sig.RNR = 1;
4908 plci->hangup_flow_ctrl_timer++;
4909 /* recover the network layer after timeout */
4910 if (plci->hangup_flow_ctrl_timer == 100)
4912 dbug(1, dprintf("Exceptional disc"));
4913 plci->Sig.RNR = 0;
4914 plci->hangup_flow_ctrl_timer = 0;
4915 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4917 if (a->ncci_plci[ncci] == plci->Id)
4919 cleanup_ncci_data(plci, ncci);
4920 if (plci->channels)plci->channels--;
4921 if (plci->appl)
4922 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925 if (plci->appl)
4926 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4927 plci_remove(plci);
4928 plci->State = IDLE;
4930 return;
4933 /* do first parse the info with no OAD in, because OAD will be converted */
4934 /* first the multiple facility IE, then mult. progress ind. */
4935 /* then the parameters for the info_ind + conn_ind */
4936 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4937 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4938 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4940 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4942 IndParse(plci, parms_id, parms, 0);
4943 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4944 esc_chi = parms[14];
4945 esc_law = parms[18];
4946 pty_cai = parms[24];
4947 esc_cr = parms[25];
4948 esc_profile = parms[27];
4949 if (esc_cr[0] && plci)
4951 if (plci->cr_enquiry && plci->appl)
4953 plci->cr_enquiry = false;
4954 /* d = MANU_ID */
4955 /* w = m_command */
4956 /* b = total length */
4957 /* b = indication type */
4958 /* b = length of all IEs */
4959 /* b = IE1 */
4960 /* S = IE1 length + cont. */
4961 /* b = IE2 */
4962 /* S = IE2 length + cont. */
4963 sendf(plci->appl,
4964 _MANUFACTURER_I,
4967 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4968 2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4971 /* create the additional info structure */
4972 add_i[1] = parms[15]; /* KEY of additional info */
4973 add_i[2] = parms[11]; /* UUI of additional info */
4974 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4976 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4977 /* indication returns by the card if requested by the function */
4978 /* AutomaticLaw() after driver init */
4979 if (a->automatic_law < 4)
4981 if (esc_law[0]) {
4982 if (esc_law[2]) {
4983 dbug(0, dprintf("u-Law selected"));
4984 a->u_law = 1;
4986 else {
4987 dbug(0, dprintf("a-Law selected"));
4988 a->u_law = 0;
4990 a->automatic_law = 4;
4991 if (plci == a->automatic_lawPLCI) {
4992 plci->internal_command = 0;
4993 sig_req(plci, REMOVE, 0);
4994 send_req(plci);
4995 a->automatic_lawPLCI = NULL;
4998 if (esc_profile[0])
5000 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5001 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5002 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5003 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5005 a->profile.Global_Options &= 0x000000ffL;
5006 a->profile.B1_Protocols &= 0x000003ffL;
5007 a->profile.B2_Protocols &= 0x00001fdfL;
5008 a->profile.B3_Protocols &= 0x000000b7L;
5010 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5011 GL_BCHANNEL_OPERATION_SUPPORTED;
5012 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5013 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5014 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5015 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5016 a->man_profile.private_options = 0;
5018 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5020 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5021 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5025 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5026 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5027 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5028 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5032 a->man_profile.private_options |= 1L << PRIVATE_T38;
5035 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5036 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5040 a->man_profile.private_options |= 1L << PRIVATE_V18;
5043 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5044 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5048 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5052 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5056 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5060 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5063 else
5065 a->profile.Global_Options &= 0x0000007fL;
5066 a->profile.B1_Protocols &= 0x000003dfL;
5067 a->profile.B2_Protocols &= 0x00001adfL;
5068 a->profile.B3_Protocols &= 0x000000b7L;
5069 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5071 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5072 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5074 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5076 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5077 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5078 UnMapController(a->Id), a->profile.Global_Options,
5079 a->profile.B1_Protocols, a->profile.B2_Protocols,
5080 a->profile.B3_Protocols, a->manufacturer_features));
5082 /* codec plci for the handset/hook state support is just an internal id */
5083 if (plci != a->AdvCodecPLCI)
5085 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5086 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5087 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5088 SendInfo(plci, Id, parms, force_mt_info);
5090 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5094 /* switch the codec to the b-channel */
5095 if (esc_chi[0] && plci && !plci->SuppState) {
5096 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5097 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5098 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5099 if (plci->tel == ADV_VOICE && plci->appl) {
5100 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5104 if (plci->appl) plci->appl->Number++;
5106 switch (plci->Sig.Ind) {
5107 /* Response to Get_Supported_Services request */
5108 case S_SUPPORTED:
5109 dbug(1, dprintf("S_Supported"));
5110 if (!plci->appl) break;
5111 if (pty_cai[0] == 4)
5113 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5115 else
5117 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5119 PUT_WORD(&CF_Ind[1], 0);
5120 PUT_WORD(&CF_Ind[4], 0);
5121 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5122 plci_remove(plci);
5123 break;
5125 /* Supplementary Service rejected */
5126 case S_SERVICE_REJ:
5127 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5128 if (!pty_cai[0]) break;
5129 switch (pty_cai[5])
5131 case ECT_EXECUTE:
5132 case THREE_PTY_END:
5133 case THREE_PTY_BEGIN:
5134 if (!plci->relatedPTYPLCI) break;
5135 tplci = plci->relatedPTYPLCI;
5136 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5137 if (tplci->tel) rId |= EXT_CONTROLLER;
5138 if (pty_cai[5] == ECT_EXECUTE)
5140 PUT_WORD(&SS_Ind[1], S_ECT);
5142 plci->vswitchstate = 0;
5143 plci->relatedPTYPLCI->vswitchstate = 0;
5146 else
5148 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5150 if (pty_cai[2] != 0xff)
5152 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5154 else
5156 PUT_WORD(&SS_Ind[4], 0x300E);
5158 plci->relatedPTYPLCI = NULL;
5159 plci->ptyState = 0;
5160 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5161 break;
5163 case CALL_DEFLECTION:
5164 if (pty_cai[2] != 0xff)
5166 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5168 else
5170 PUT_WORD(&SS_Ind[4], 0x300E);
5172 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5173 for (i = 0; i < max_appl; i++)
5175 if (application[i].CDEnable)
5177 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5178 application[i].CDEnable = false;
5181 break;
5183 case DEACTIVATION_DIVERSION:
5184 case ACTIVATION_DIVERSION:
5185 case DIVERSION_INTERROGATE_CFU:
5186 case DIVERSION_INTERROGATE_CFB:
5187 case DIVERSION_INTERROGATE_CFNR:
5188 case DIVERSION_INTERROGATE_NUM:
5189 case CCBS_REQUEST:
5190 case CCBS_DEACTIVATE:
5191 case CCBS_INTERROGATE:
5192 if (!plci->appl) break;
5193 if (pty_cai[2] != 0xff)
5195 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5197 else
5199 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5201 switch (pty_cai[5])
5203 case DEACTIVATION_DIVERSION:
5204 dbug(1, dprintf("Deact_Div"));
5205 Interr_Err_Ind[0] = 0x9;
5206 Interr_Err_Ind[3] = 0x6;
5207 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5208 break;
5209 case ACTIVATION_DIVERSION:
5210 dbug(1, dprintf("Act_Div"));
5211 Interr_Err_Ind[0] = 0x9;
5212 Interr_Err_Ind[3] = 0x6;
5213 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5214 break;
5215 case DIVERSION_INTERROGATE_CFU:
5216 case DIVERSION_INTERROGATE_CFB:
5217 case DIVERSION_INTERROGATE_CFNR:
5218 dbug(1, dprintf("Interr_Div"));
5219 Interr_Err_Ind[0] = 0xa;
5220 Interr_Err_Ind[3] = 0x7;
5221 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5222 break;
5223 case DIVERSION_INTERROGATE_NUM:
5224 dbug(1, dprintf("Interr_Num"));
5225 Interr_Err_Ind[0] = 0xa;
5226 Interr_Err_Ind[3] = 0x7;
5227 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5228 break;
5229 case CCBS_REQUEST:
5230 dbug(1, dprintf("CCBS Request"));
5231 Interr_Err_Ind[0] = 0xd;
5232 Interr_Err_Ind[3] = 0xa;
5233 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5234 break;
5235 case CCBS_DEACTIVATE:
5236 dbug(1, dprintf("CCBS Deactivate"));
5237 Interr_Err_Ind[0] = 0x9;
5238 Interr_Err_Ind[3] = 0x6;
5239 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5240 break;
5241 case CCBS_INTERROGATE:
5242 dbug(1, dprintf("CCBS Interrogate"));
5243 Interr_Err_Ind[0] = 0xb;
5244 Interr_Err_Ind[3] = 0x8;
5245 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5246 break;
5248 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5249 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5250 plci_remove(plci);
5251 break;
5252 case ACTIVATION_MWI:
5253 case DEACTIVATION_MWI:
5254 if (pty_cai[5] == ACTIVATION_MWI)
5256 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5258 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5260 if (pty_cai[2] != 0xff)
5262 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5264 else
5266 PUT_WORD(&SS_Ind[4], 0x300E);
5269 if (plci->cr_enquiry)
5271 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5272 plci_remove(plci);
5274 else
5276 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5278 break;
5279 case CONF_ADD: /* ERROR */
5280 case CONF_BEGIN:
5281 case CONF_DROP:
5282 case CONF_ISOLATE:
5283 case CONF_REATTACH:
5284 CONF_Ind[0] = 9;
5285 CONF_Ind[3] = 6;
5286 switch (pty_cai[5])
5288 case CONF_BEGIN:
5289 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5290 plci->ptyState = 0;
5291 break;
5292 case CONF_DROP:
5293 CONF_Ind[0] = 5;
5294 CONF_Ind[3] = 2;
5295 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5296 plci->ptyState = CONNECTED;
5297 break;
5298 case CONF_ISOLATE:
5299 CONF_Ind[0] = 5;
5300 CONF_Ind[3] = 2;
5301 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5302 plci->ptyState = CONNECTED;
5303 break;
5304 case CONF_REATTACH:
5305 CONF_Ind[0] = 5;
5306 CONF_Ind[3] = 2;
5307 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5308 plci->ptyState = CONNECTED;
5309 break;
5310 case CONF_ADD:
5311 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5312 plci->relatedPTYPLCI = NULL;
5313 tplci = plci->relatedPTYPLCI;
5314 if (tplci) tplci->ptyState = CONNECTED;
5315 plci->ptyState = CONNECTED;
5316 break;
5319 if (pty_cai[2] != 0xff)
5321 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5323 else
5325 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5326 within the required time */
5329 PUT_DWORD(&CONF_Ind[6], 0x0);
5330 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5331 break;
5333 break;
5335 /* Supplementary Service indicates success */
5336 case S_SERVICE:
5337 dbug(1, dprintf("Service_Ind"));
5338 PUT_WORD(&CF_Ind[4], 0);
5339 switch (pty_cai[5])
5341 case THREE_PTY_END:
5342 case THREE_PTY_BEGIN:
5343 case ECT_EXECUTE:
5344 if (!plci->relatedPTYPLCI) break;
5345 tplci = plci->relatedPTYPLCI;
5346 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5347 if (tplci->tel) rId |= EXT_CONTROLLER;
5348 if (pty_cai[5] == ECT_EXECUTE)
5350 PUT_WORD(&SS_Ind[1], S_ECT);
5352 if (plci->vswitchstate != 3)
5355 plci->ptyState = IDLE;
5356 plci->relatedPTYPLCI = NULL;
5357 plci->ptyState = 0;
5361 dbug(1, dprintf("ECT OK"));
5362 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5367 else
5369 switch (plci->ptyState)
5371 case S_3PTY_BEGIN:
5372 plci->ptyState = CONNECTED;
5373 dbug(1, dprintf("3PTY ON"));
5374 break;
5376 case S_3PTY_END:
5377 plci->ptyState = IDLE;
5378 plci->relatedPTYPLCI = NULL;
5379 plci->ptyState = 0;
5380 dbug(1, dprintf("3PTY OFF"));
5381 break;
5383 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5384 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5386 break;
5388 case CALL_DEFLECTION:
5389 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5390 for (i = 0; i < max_appl; i++)
5392 if (application[i].CDEnable)
5394 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5395 application[i].CDEnable = false;
5398 break;
5400 case DEACTIVATION_DIVERSION:
5401 case ACTIVATION_DIVERSION:
5402 if (!plci->appl) break;
5403 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5404 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5405 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5406 plci_remove(plci);
5407 break;
5409 case DIVERSION_INTERROGATE_CFU:
5410 case DIVERSION_INTERROGATE_CFB:
5411 case DIVERSION_INTERROGATE_CFNR:
5412 case DIVERSION_INTERROGATE_NUM:
5413 case CCBS_REQUEST:
5414 case CCBS_DEACTIVATE:
5415 case CCBS_INTERROGATE:
5416 if (!plci->appl) break;
5417 switch (pty_cai[5])
5419 case DIVERSION_INTERROGATE_CFU:
5420 case DIVERSION_INTERROGATE_CFB:
5421 case DIVERSION_INTERROGATE_CFNR:
5422 dbug(1, dprintf("Interr_Div"));
5423 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5424 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5425 break;
5426 case DIVERSION_INTERROGATE_NUM:
5427 dbug(1, dprintf("Interr_Num"));
5428 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5429 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5430 break;
5431 case CCBS_REQUEST:
5432 dbug(1, dprintf("CCBS Request"));
5433 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5434 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5435 break;
5436 case CCBS_DEACTIVATE:
5437 dbug(1, dprintf("CCBS Deactivate"));
5438 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5439 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5440 break;
5441 case CCBS_INTERROGATE:
5442 dbug(1, dprintf("CCBS Interrogate"));
5443 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5444 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5445 break;
5447 PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5448 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5449 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5450 plci_remove(plci);
5451 break;
5453 case ACTIVATION_MWI:
5454 case DEACTIVATION_MWI:
5455 if (pty_cai[5] == ACTIVATION_MWI)
5457 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5459 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5460 if (plci->cr_enquiry)
5462 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5463 plci_remove(plci);
5465 else
5467 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5469 break;
5470 case MWI_INDICATION:
5471 if (pty_cai[0] >= 0x12)
5473 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5474 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5475 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5476 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5478 if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5480 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5481 plci_remove(plci);
5482 return;
5484 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5485 pty_cai[0] = 0;
5487 else
5489 for (i = 0; i < max_appl; i++)
5491 if (a->Notification_Mask[i]&SMASK_MWI)
5493 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5494 pty_cai[0] = 0;
5499 if (!pty_cai[0])
5500 { /* acknowledge */
5501 facility[2] = 0; /* returncode */
5503 else facility[2] = 0xff;
5505 else
5507 /* reject */
5508 facility[2] = 0xff; /* returncode */
5510 facility[0] = 2;
5511 facility[1] = MWI_RESPONSE; /* Function */
5512 add_p(plci, CAI, facility);
5513 add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5514 sig_req(plci, S_SERVICE, 0);
5515 send_req(plci);
5516 plci->command = 0;
5517 next_internal_command(Id, plci);
5518 break;
5519 case CONF_ADD: /* OK */
5520 case CONF_BEGIN:
5521 case CONF_DROP:
5522 case CONF_ISOLATE:
5523 case CONF_REATTACH:
5524 case CONF_PARTYDISC:
5525 CONF_Ind[0] = 9;
5526 CONF_Ind[3] = 6;
5527 switch (pty_cai[5])
5529 case CONF_BEGIN:
5530 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5531 if (pty_cai[0] == 6)
5533 d = pty_cai[6];
5534 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5536 else
5538 PUT_DWORD(&CONF_Ind[6], 0x0);
5540 break;
5541 case CONF_ISOLATE:
5542 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5543 CONF_Ind[0] = 5;
5544 CONF_Ind[3] = 2;
5545 break;
5546 case CONF_REATTACH:
5547 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5548 CONF_Ind[0] = 5;
5549 CONF_Ind[3] = 2;
5550 break;
5551 case CONF_DROP:
5552 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5553 CONF_Ind[0] = 5;
5554 CONF_Ind[3] = 2;
5555 break;
5556 case CONF_ADD:
5557 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5558 d = pty_cai[6];
5559 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5560 tplci = plci->relatedPTYPLCI;
5561 if (tplci) tplci->ptyState = CONNECTED;
5562 break;
5563 case CONF_PARTYDISC:
5564 CONF_Ind[0] = 7;
5565 CONF_Ind[3] = 4;
5566 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5567 d = pty_cai[6];
5568 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5569 break;
5571 plci->ptyState = CONNECTED;
5572 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5573 break;
5574 case CCBS_INFO_RETAIN:
5575 case CCBS_ERASECALLLINKAGEID:
5576 case CCBS_STOP_ALERTING:
5577 CONF_Ind[0] = 5;
5578 CONF_Ind[3] = 2;
5579 switch (pty_cai[5])
5581 case CCBS_INFO_RETAIN:
5582 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5583 break;
5584 case CCBS_STOP_ALERTING:
5585 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5586 break;
5587 case CCBS_ERASECALLLINKAGEID:
5588 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5589 CONF_Ind[0] = 7;
5590 CONF_Ind[3] = 4;
5591 CONF_Ind[6] = 0;
5592 CONF_Ind[7] = 0;
5593 break;
5595 w = pty_cai[6];
5596 PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5598 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5600 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5602 else
5604 for (i = 0; i < max_appl; i++)
5605 if (a->Notification_Mask[i] & SMASK_CCBS)
5606 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5608 break;
5610 break;
5611 case CALL_HOLD_REJ:
5612 cau = parms[7];
5613 if (cau)
5615 i = _L3_CAUSE | cau[2];
5616 if (cau[2] == 0) i = 0x3603;
5618 else
5620 i = 0x3603;
5622 PUT_WORD(&SS_Ind[1], S_HOLD);
5623 PUT_WORD(&SS_Ind[4], i);
5624 if (plci->SuppState == HOLD_REQUEST)
5626 plci->SuppState = IDLE;
5627 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5629 break;
5631 case CALL_HOLD_ACK:
5632 if (plci->SuppState == HOLD_REQUEST)
5634 plci->SuppState = CALL_HELD;
5635 CodecIdCheck(a, plci);
5636 start_internal_command(Id, plci, hold_save_command);
5638 break;
5640 case CALL_RETRIEVE_REJ:
5641 cau = parms[7];
5642 if (cau)
5644 i = _L3_CAUSE | cau[2];
5645 if (cau[2] == 0) i = 0x3603;
5647 else
5649 i = 0x3603;
5651 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5652 PUT_WORD(&SS_Ind[4], i);
5653 if (plci->SuppState == RETRIEVE_REQUEST)
5655 plci->SuppState = CALL_HELD;
5656 CodecIdCheck(a, plci);
5657 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5659 break;
5661 case CALL_RETRIEVE_ACK:
5662 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5663 if (plci->SuppState == RETRIEVE_REQUEST)
5665 plci->SuppState = IDLE;
5666 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5667 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5668 if (plci->tel)
5670 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5671 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5672 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5673 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5675 dbug(1, dprintf("Get B-ch"));
5676 start_internal_command(Id, plci, retrieve_restore_command);
5678 else
5679 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5681 else
5682 start_internal_command(Id, plci, retrieve_restore_command);
5684 break;
5686 case INDICATE_IND:
5687 if (plci->State != LISTENING) {
5688 sig_req(plci, HANGUP, 0);
5689 send_req(plci);
5690 break;
5692 cip = find_cip(a, parms[4], parms[6]);
5693 cip_mask = 1L << cip;
5694 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5695 clear_c_ind_mask(plci);
5696 if (!remove_started && !a->adapter_disabled)
5698 set_c_ind_mask_bit(plci, MAX_APPL);
5699 group_optimization(a, plci);
5700 for (i = 0; i < max_appl; i++) {
5701 if (application[i].Id
5702 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5703 && CPN_filter_ok(parms[0], a, i)
5704 && test_group_ind_mask_bit(plci, i)) {
5705 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5706 set_c_ind_mask_bit(plci, i);
5707 dump_c_ind_mask(plci);
5708 plci->State = INC_CON_PENDING;
5709 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5710 CALL_DIR_IN | CALL_DIR_ANSWER;
5711 if (esc_chi[0]) {
5712 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5713 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5715 /* if a listen on the ext controller is done, check if hook states */
5716 /* are supported or if just a on board codec must be activated */
5717 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5718 if (a->profile.Global_Options & HANDSET)
5719 plci->tel = ADV_VOICE;
5720 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5721 plci->tel = CODEC;
5722 if (plci->tel) Id |= EXT_CONTROLLER;
5723 a->codec_listen[i] = plci;
5726 sendf(&application[i], _CONNECT_I, Id, 0,
5727 "wSSSSSSSbSSSSS", cip, /* CIP */
5728 parms[0], /* CalledPartyNumber */
5729 multi_CiPN_parms[0], /* CallingPartyNumber */
5730 parms[2], /* CalledPartySubad */
5731 parms[3], /* CallingPartySubad */
5732 parms[4], /* BearerCapability */
5733 parms[5], /* LowLC */
5734 parms[6], /* HighLC */
5735 ai_len, /* nested struct add_i */
5736 add_i[0], /* B channel info */
5737 add_i[1], /* keypad facility */
5738 add_i[2], /* user user data */
5739 add_i[3], /* nested facility */
5740 multi_CiPN_parms[1] /* second CiPN(SCR) */
5742 SendSSExtInd(&application[i],
5743 plci,
5745 multi_ssext_parms);
5746 SendSetupInfo(&application[i],
5747 plci,
5749 parms,
5750 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753 clear_c_ind_mask_bit(plci, MAX_APPL);
5754 dump_c_ind_mask(plci);
5756 if (c_ind_mask_empty(plci)) {
5757 sig_req(plci, HANGUP, 0);
5758 send_req(plci);
5759 plci->State = IDLE;
5761 plci->notifiedcall = 0;
5762 a->listen_active--;
5763 listen_check(a);
5764 break;
5766 case CALL_PEND_NOTIFY:
5767 plci->notifiedcall = 1;
5768 listen_check(a);
5769 break;
5771 case CALL_IND:
5772 case CALL_CON:
5773 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5775 if (plci->internal_command == PERM_COD_CONN_PEND)
5777 if (plci->State == ADVANCED_VOICE_NOSIG)
5779 dbug(1, dprintf("***Codec OK"));
5780 if (a->AdvSignalPLCI)
5782 tplci = a->AdvSignalPLCI;
5783 if (tplci->spoofed_msg)
5785 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5786 tplci->command = 0;
5787 tplci->internal_command = 0;
5788 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5789 switch (tplci->spoofed_msg)
5791 case CALL_RES:
5792 tplci->command = _CONNECT_I | RESPONSE;
5793 api_load_msg(&tplci->saved_msg, saved_parms);
5794 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5795 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5797 /* early B3 connect (CIP mask bit 9) no release after a disc */
5798 add_p(tplci, LLI, "\x01\x01");
5800 add_s(tplci, CONN_NR, &saved_parms[2]);
5801 add_s(tplci, LLC, &saved_parms[4]);
5802 add_ai(tplci, &saved_parms[5]);
5803 tplci->State = INC_CON_ACCEPT;
5804 sig_req(tplci, CALL_RES, 0);
5805 send_req(tplci);
5806 break;
5808 case AWAITING_SELECT_B:
5809 dbug(1, dprintf("Select_B continue"));
5810 start_internal_command(x_Id, tplci, select_b_command);
5811 break;
5813 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5814 if (!tplci->Sig.Id)
5816 dbug(1, dprintf("No SigID!"));
5817 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5818 plci_remove(tplci);
5819 break;
5821 tplci->command = _MANUFACTURER_R;
5822 api_load_msg(&tplci->saved_msg, saved_parms);
5823 dir = saved_parms[2].info[0];
5824 if (dir == 1) {
5825 sig_req(tplci, CALL_REQ, 0);
5827 else if (!dir) {
5828 sig_req(tplci, LISTEN_REQ, 0);
5830 send_req(tplci);
5831 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5832 break;
5834 case (CALL_REQ | AWAITING_MANUF_CON):
5835 sig_req(tplci, CALL_REQ, 0);
5836 send_req(tplci);
5837 break;
5839 case CALL_REQ:
5840 if (!tplci->Sig.Id)
5842 dbug(1, dprintf("No SigID!"));
5843 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5844 plci_remove(tplci);
5845 break;
5847 tplci->command = _CONNECT_R;
5848 api_load_msg(&tplci->saved_msg, saved_parms);
5849 add_s(tplci, CPN, &saved_parms[1]);
5850 add_s(tplci, DSA, &saved_parms[3]);
5851 add_ai(tplci, &saved_parms[9]);
5852 sig_req(tplci, CALL_REQ, 0);
5853 send_req(tplci);
5854 break;
5856 case CALL_RETRIEVE:
5857 tplci->command = C_RETRIEVE_REQ;
5858 sig_req(tplci, CALL_RETRIEVE, 0);
5859 send_req(tplci);
5860 break;
5862 tplci->spoofed_msg = 0;
5863 if (tplci->internal_command == 0)
5864 next_internal_command(x_Id, tplci);
5867 next_internal_command(Id, plci);
5868 break;
5870 dbug(1, dprintf("***Codec Hook Init Req"));
5871 plci->internal_command = PERM_COD_HOOK;
5872 add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5873 sig_req(plci, TEL_CTRL, 0);
5874 send_req(plci);
5877 else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5878 && plci->State != INC_ACT_PENDING)
5880 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5881 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5883 chi[2] = plci->b_channel;
5884 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5886 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5887 plci->State = INC_ACT_PENDING;
5889 break;
5891 case TEL_CTRL:
5892 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5893 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5894 switch (ie[1] & 0x91) {
5895 case 0x80: /* hook off */
5896 case 0x81:
5897 if (plci->internal_command == PERM_COD_HOOK)
5899 dbug(1, dprintf("init:hook_off"));
5900 plci->hook_state = ie[1];
5901 next_internal_command(Id, plci);
5902 break;
5904 else /* ignore doubled hook indications */
5906 if (((plci->hook_state) & 0xf0) == 0x80)
5908 dbug(1, dprintf("ignore hook"));
5909 break;
5911 plci->hook_state = ie[1]&0x91;
5913 /* check for incoming call pending */
5914 /* and signal '+'.Appl must decide */
5915 /* with connect_res if call must */
5916 /* accepted or not */
5917 for (i = 0, tplci = NULL; i < max_appl; i++) {
5918 if (a->codec_listen[i]
5919 && (a->codec_listen[i]->State == INC_CON_PENDING
5920 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5921 tplci = a->codec_listen[i];
5922 tplci->appl = &application[i];
5925 /* no incoming call, do outgoing call */
5926 /* and signal '+' if outg. setup */
5927 if (!a->AdvSignalPLCI && !tplci) {
5928 if ((i = get_plci(a))) {
5929 a->AdvSignalPLCI = &a->plci[i - 1];
5930 tplci = a->AdvSignalPLCI;
5931 tplci->tel = ADV_VOICE;
5932 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5933 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5934 /* early B3 connect (CIP mask bit 9) no release after a disc */
5935 add_p(tplci, LLI, "\x01\x01");
5937 add_p(tplci, CAI, voice_cai);
5938 add_p(tplci, OAD, a->TelOAD);
5939 add_p(tplci, OSA, a->TelOSA);
5940 add_p(tplci, SHIFT | 6, NULL);
5941 add_p(tplci, SIN, "\x02\x01\x00");
5942 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5943 sig_req(tplci, ASSIGN, DSIG_ID);
5944 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5945 a->AdvSignalPLCI->command = 0;
5946 tplci->appl = a->AdvSignalAppl;
5947 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5948 send_req(tplci);
5953 if (!tplci) break;
5954 Id = ((word)tplci->Id << 8) | a->Id;
5955 Id |= EXT_CONTROLLER;
5956 sendf(tplci->appl,
5957 _FACILITY_I,
5960 "ws", (word)0, "\x01+");
5961 break;
5963 case 0x90: /* hook on */
5964 case 0x91:
5965 if (plci->internal_command == PERM_COD_HOOK)
5967 dbug(1, dprintf("init:hook_on"));
5968 plci->hook_state = ie[1] & 0x91;
5969 next_internal_command(Id, plci);
5970 break;
5972 else /* ignore doubled hook indications */
5974 if (((plci->hook_state) & 0xf0) == 0x90) break;
5975 plci->hook_state = ie[1] & 0x91;
5977 /* hangup the adv. voice call and signal '-' to the appl */
5978 if (a->AdvSignalPLCI) {
5979 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5980 if (plci->tel) Id |= EXT_CONTROLLER;
5981 sendf(a->AdvSignalAppl,
5982 _FACILITY_I,
5985 "ws", (word)0, "\x01-");
5986 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5987 a->AdvSignalPLCI->command = 0;
5988 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5989 send_req(a->AdvSignalPLCI);
5991 break;
5994 break;
5996 case RESUME:
5997 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
5998 PUT_WORD(&resume_cau[4], GOOD);
5999 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6000 break;
6002 case SUSPEND:
6003 clear_c_ind_mask(plci);
6005 if (plci->NL.Id && !plci->nl_remove_id) {
6006 mixer_remove(plci);
6007 nl_req_ncci(plci, REMOVE, 0);
6009 if (!plci->sig_remove_id) {
6010 plci->internal_command = 0;
6011 sig_req(plci, REMOVE, 0);
6013 send_req(plci);
6014 if (!plci->channels) {
6015 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6016 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6018 break;
6020 case SUSPEND_REJ:
6021 break;
6023 case HANGUP:
6024 plci->hangup_flow_ctrl_timer = 0;
6025 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6026 cau = parms[7];
6027 if (cau) {
6028 i = _L3_CAUSE | cau[2];
6029 if (cau[2] == 0) i = 0;
6030 else if (cau[2] == 8) i = _L1_ERROR;
6031 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6032 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6034 else {
6035 i = _L3_ERROR;
6038 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6040 for (i = 0; i < max_appl; i++)
6042 if (test_c_ind_mask_bit(plci, i))
6043 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046 else
6048 clear_c_ind_mask(plci);
6050 if (!plci->appl)
6052 if (plci->State == LISTENING)
6054 plci->notifiedcall = 0;
6055 a->listen_active--;
6057 plci->State = INC_DIS_PENDING;
6058 if (c_ind_mask_empty(plci))
6060 plci->State = IDLE;
6061 if (plci->NL.Id && !plci->nl_remove_id)
6063 mixer_remove(plci);
6064 nl_req_ncci(plci, REMOVE, 0);
6066 if (!plci->sig_remove_id)
6068 plci->internal_command = 0;
6069 sig_req(plci, REMOVE, 0);
6071 send_req(plci);
6074 else
6076 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6077 /* result in a second HANGUP! Don't generate another */
6078 /* DISCONNECT */
6079 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6081 if (plci->State == RESUMING)
6083 PUT_WORD(&resume_cau[4], i);
6084 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6086 plci->State = INC_DIS_PENDING;
6087 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090 break;
6092 case SSEXT_IND:
6093 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6094 break;
6096 case VSWITCH_REQ:
6097 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6098 break;
6099 case VSWITCH_IND:
6100 if (plci->relatedPTYPLCI &&
6101 plci->vswitchstate == 3 &&
6102 plci->relatedPTYPLCI->vswitchstate == 3 &&
6103 parms[MAXPARMSIDS - 1][0])
6105 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6106 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6107 send_req(plci->relatedPTYPLCI);
6109 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6110 break;
6116 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6118 word i;
6119 byte *ie;
6120 word Info_Number;
6121 byte *Info_Element;
6122 word Info_Mask = 0;
6124 dbug(1, dprintf("SetupInfo"));
6126 for (i = 0; i < MAXPARMSIDS; i++) {
6127 ie = parms[i];
6128 Info_Number = 0;
6129 Info_Element = ie;
6130 if (ie[0]) {
6131 switch (i) {
6132 case 0:
6133 dbug(1, dprintf("CPN "));
6134 Info_Number = 0x0070;
6135 Info_Mask = 0x80;
6136 Info_Sent_Flag = true;
6137 break;
6138 case 8: /* display */
6139 dbug(1, dprintf("display(%d)", i));
6140 Info_Number = 0x0028;
6141 Info_Mask = 0x04;
6142 Info_Sent_Flag = true;
6143 break;
6144 case 16: /* Channel Id */
6145 dbug(1, dprintf("CHI"));
6146 Info_Number = 0x0018;
6147 Info_Mask = 0x100;
6148 Info_Sent_Flag = true;
6149 mixer_set_bchannel_id(plci, Info_Element);
6150 break;
6151 case 19: /* Redirected Number */
6152 dbug(1, dprintf("RDN"));
6153 Info_Number = 0x0074;
6154 Info_Mask = 0x400;
6155 Info_Sent_Flag = true;
6156 break;
6157 case 20: /* Redirected Number extended */
6158 dbug(1, dprintf("RDX"));
6159 Info_Number = 0x0073;
6160 Info_Mask = 0x400;
6161 Info_Sent_Flag = true;
6162 break;
6163 case 22: /* Redirecing Number */
6164 dbug(1, dprintf("RIN"));
6165 Info_Number = 0x0076;
6166 Info_Mask = 0x400;
6167 Info_Sent_Flag = true;
6168 break;
6169 default:
6170 Info_Number = 0;
6171 break;
6175 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6176 Info_Number = 0x8000 | 5;
6177 Info_Mask = 0x10;
6178 Info_Element = "";
6181 if (Info_Sent_Flag && Info_Number) {
6182 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6183 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6190 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6192 word i;
6193 word j;
6194 word k;
6195 byte *ie;
6196 word Info_Number;
6197 byte *Info_Element;
6198 word Info_Mask = 0;
6199 static byte charges[5] = {4, 0, 0, 0, 0};
6200 static byte cause[] = {0x02, 0x80, 0x00};
6201 APPL *appl;
6203 dbug(1, dprintf("InfoParse "));
6205 if (
6206 !plci->appl
6207 && !plci->State
6208 && plci->Sig.Ind != NCR_FACILITY
6211 dbug(1, dprintf("NoParse "));
6212 return;
6214 cause[2] = 0;
6215 for (i = 0; i < MAXPARMSIDS; i++) {
6216 ie = parms[i];
6217 Info_Number = 0;
6218 Info_Element = ie;
6219 if (ie[0]) {
6220 switch (i) {
6221 case 0:
6222 dbug(1, dprintf("CPN "));
6223 Info_Number = 0x0070;
6224 Info_Mask = 0x80;
6225 break;
6226 case 7: /* ESC_CAU */
6227 dbug(1, dprintf("cau(0x%x)", ie[2]));
6228 Info_Number = 0x0008;
6229 Info_Mask = 0x00;
6230 cause[2] = ie[2];
6231 Info_Element = NULL;
6232 break;
6233 case 8: /* display */
6234 dbug(1, dprintf("display(%d)", i));
6235 Info_Number = 0x0028;
6236 Info_Mask = 0x04;
6237 break;
6238 case 9: /* Date display */
6239 dbug(1, dprintf("date(%d)", i));
6240 Info_Number = 0x0029;
6241 Info_Mask = 0x02;
6242 break;
6243 case 10: /* charges */
6244 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6245 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6246 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6247 Info_Number = 0x4000;
6248 Info_Mask = 0x40;
6249 Info_Element = charges;
6250 break;
6251 case 11: /* user user info */
6252 dbug(1, dprintf("uui"));
6253 Info_Number = 0x007E;
6254 Info_Mask = 0x08;
6255 break;
6256 case 12: /* congestion receiver ready */
6257 dbug(1, dprintf("clRDY"));
6258 Info_Number = 0x00B0;
6259 Info_Mask = 0x08;
6260 Info_Element = "";
6261 break;
6262 case 13: /* congestion receiver not ready */
6263 dbug(1, dprintf("clNRDY"));
6264 Info_Number = 0x00BF;
6265 Info_Mask = 0x08;
6266 Info_Element = "";
6267 break;
6268 case 15: /* Keypad Facility */
6269 dbug(1, dprintf("KEY"));
6270 Info_Number = 0x002C;
6271 Info_Mask = 0x20;
6272 break;
6273 case 16: /* Channel Id */
6274 dbug(1, dprintf("CHI"));
6275 Info_Number = 0x0018;
6276 Info_Mask = 0x100;
6277 mixer_set_bchannel_id(plci, Info_Element);
6278 break;
6279 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6280 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6281 if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6282 Info_Number = 0x0008;
6283 Info_Mask = 0x01;
6284 if (cause[2] != ie[2]) Info_Element = cause;
6285 break;
6286 case 19: /* Redirected Number */
6287 dbug(1, dprintf("RDN"));
6288 Info_Number = 0x0074;
6289 Info_Mask = 0x400;
6290 break;
6291 case 22: /* Redirecing Number */
6292 dbug(1, dprintf("RIN"));
6293 Info_Number = 0x0076;
6294 Info_Mask = 0x400;
6295 break;
6296 case 23: /* Notification Indicator */
6297 dbug(1, dprintf("NI"));
6298 Info_Number = (word)NI;
6299 Info_Mask = 0x210;
6300 break;
6301 case 26: /* Call State */
6302 dbug(1, dprintf("CST"));
6303 Info_Number = (word)CST;
6304 Info_Mask = 0x01; /* do with cause i.e. for now */
6305 break;
6306 case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6307 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6308 Info_Number = 0x8000 | ie[3];
6309 if (iesent) Info_Mask = 0xffff;
6310 else Info_Mask = 0x10;
6311 Info_Element = "";
6312 break;
6313 default:
6314 Info_Number = 0;
6315 Info_Mask = 0;
6316 Info_Element = "";
6317 break;
6321 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6323 for (j = 0; j < max_appl; j++)
6325 appl = &application[j];
6326 if (Info_Number
6327 && appl->Id
6328 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6330 dbug(1, dprintf("NCR_Ind"));
6331 iesent = true;
6332 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6336 else if (!plci->appl)
6337 { /* overlap receiving broadcast */
6338 if (Info_Number == CPN
6339 || Info_Number == KEY
6340 || Info_Number == NI
6341 || Info_Number == DSP
6342 || Info_Number == UUI)
6344 for (j = 0; j < max_appl; j++)
6346 if (test_c_ind_mask_bit(plci, j))
6348 dbug(1, dprintf("Ovl_Ind"));
6349 iesent = true;
6350 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6354 } /* all other signalling states */
6355 else if (Info_Number
6356 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6358 dbug(1, dprintf("Std_Ind"));
6359 iesent = true;
6360 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6366 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6367 dword info_mask, byte setupParse)
6369 word i;
6370 word j;
6371 byte *ie;
6372 word Info_Number;
6373 byte *Info_Element;
6374 APPL *appl;
6375 word Info_Mask = 0;
6376 byte iesent = 0;
6378 if (
6379 !plci->appl
6380 && !plci->State
6381 && plci->Sig.Ind != NCR_FACILITY
6382 && !setupParse
6385 dbug(1, dprintf("NoM-IEParse "));
6386 return 0;
6388 dbug(1, dprintf("M-IEParse "));
6390 for (i = 0; i < MAX_MULTI_IE; i++)
6392 ie = parms[i];
6393 Info_Number = 0;
6394 Info_Element = ie;
6395 if (ie[0])
6397 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6398 Info_Number = (word)ie_type;
6399 Info_Mask = (word)info_mask;
6402 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6404 for (j = 0; j < max_appl; j++)
6406 appl = &application[j];
6407 if (Info_Number
6408 && appl->Id
6409 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6411 iesent = true;
6412 dbug(1, dprintf("Mlt_NCR_Ind"));
6413 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6417 else if (!plci->appl && Info_Number)
6418 { /* overlap receiving broadcast */
6419 for (j = 0; j < max_appl; j++)
6421 if (test_c_ind_mask_bit(plci, j))
6423 iesent = true;
6424 dbug(1, dprintf("Mlt_Ovl_Ind"));
6425 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428 } /* all other signalling states */
6429 else if (Info_Number
6430 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6432 iesent = true;
6433 dbug(1, dprintf("Mlt_Std_Ind"));
6434 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6437 return iesent;
6440 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6442 word i;
6443 /* Format of multi_ssext_parms[i][]:
6444 0 byte length
6445 1 byte SSEXTIE
6446 2 byte SSEXT_REQ/SSEXT_IND
6447 3 byte length
6448 4 word SSExtCommand
6449 6... Params
6451 if (
6452 plci
6453 && plci->State
6454 && plci->Sig.Ind != NCR_FACILITY
6456 for (i = 0; i < MAX_MULTI_IE; i++)
6458 if (parms[i][0] < 6) continue;
6459 if (parms[i][2] == SSEXT_REQ) continue;
6461 if (appl)
6463 parms[i][0] = 0; /* kill it */
6464 sendf(appl, _MANUFACTURER_I,
6467 "dwS",
6468 _DI_MANU_ID,
6469 _DI_SSEXT_CTRL,
6470 &parms[i][3]);
6472 else if (plci->appl)
6474 parms[i][0] = 0; /* kill it */
6475 sendf(plci->appl, _MANUFACTURER_I,
6478 "dwS",
6479 _DI_MANU_ID,
6480 _DI_SSEXT_CTRL,
6481 &parms[i][3]);
6486 static void nl_ind(PLCI *plci)
6488 byte ch;
6489 word ncci;
6490 dword Id;
6491 DIVA_CAPI_ADAPTER *a;
6492 word NCCIcode;
6493 APPL *APPLptr;
6494 word count;
6495 word Num;
6496 word i, ncpi_state;
6497 byte len, ncci_state;
6498 word msg;
6499 word info = 0;
6500 word fax_feature_bits;
6501 byte fax_send_edata_ack;
6502 static byte v120_header_buffer[2 + 3];
6503 static word fax_info[] = {
6504 0, /* T30_SUCCESS */
6505 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6510 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6511 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6512 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6513 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6514 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6515 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6516 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6517 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6518 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6523 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6524 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6525 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6537 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6538 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6539 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6540 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6541 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6542 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6543 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6544 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6545 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6546 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6547 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6548 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6549 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6550 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6553 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556 static word rtp_info[] = {
6557 GOOD, /* RTP_SUCCESS */
6558 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6561 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6563 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6564 0x00000000, 0x00000000, 0x00000000, 0x00000000
6567 ch = plci->NL.IndCh;
6568 a = plci->adapter;
6569 ncci = a->ch_ncci[ch];
6570 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6571 if (plci->tel) Id |= EXT_CONTROLLER;
6572 APPLptr = plci->appl;
6573 dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6574 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6576 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6578 if (plci->nl_remove_id)
6580 plci->NL.RNR = 2; /* discard */
6581 dbug(1, dprintf("NL discard while remove pending"));
6582 return;
6584 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6586 if (plci->State == INC_DIS_PENDING
6587 || plci->State == OUTG_DIS_PENDING
6588 || plci->State == IDLE)
6590 plci->NL.RNR = 2; /* discard */
6591 dbug(1, dprintf("discard n_connect"));
6592 return;
6594 if (plci->State < INC_ACT_PENDING)
6596 plci->NL.RNR = 1; /* flow control */
6597 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6598 return;
6602 if (!APPLptr) /* no application or invalid data */
6603 { /* while reloading the DSP */
6604 dbug(1, dprintf("discard1"));
6605 plci->NL.RNR = 2;
6606 return;
6609 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6610 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6611 || (plci->B2_prot == 7)
6612 || (plci->B3_prot == 7)))
6614 plci->ncpi_buffer[0] = 0;
6616 ncpi_state = plci->ncpi_state;
6617 if (plci->NL.complete == 1)
6619 byte *data = &plci->NL.RBuffer->P[0];
6621 if ((plci->NL.RBuffer->length >= 12)
6622 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6623 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6625 word conn_opt, ncpi_opt = 0x00;
6626 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6628 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6629 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6630 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6631 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6633 data++; /* indication code */
6634 data += 2; /* timestamp */
6635 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6636 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6637 data++; /* connected norm */
6638 conn_opt = GET_WORD(data);
6639 data += 2; /* connected options */
6641 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6643 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6645 ncpi_opt |= MDM_NCPI_ECM_V42;
6647 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6649 ncpi_opt |= MDM_NCPI_ECM_MNP;
6651 else
6653 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6655 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6657 ncpi_opt |= MDM_NCPI_COMPRESSED;
6659 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6660 plci->ncpi_buffer[0] = 4;
6662 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6665 if (plci->B3_prot == 7)
6667 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6668 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6669 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6671 a->ncci_state[ncci] = INC_ACT_PENDING;
6672 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6673 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6677 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6678 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6679 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6680 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6683 plci->NL.RNR = 2;
6684 return;
6688 if (plci->NL.complete == 2)
6690 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6691 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6693 switch (plci->RData[0].P[0])
6696 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6697 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6698 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6699 break;
6700 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6701 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6702 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6703 break;
6704 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6705 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6706 break;
6707 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6708 dtmf_confirmation(Id, plci);
6709 break;
6712 case UDATA_INDICATION_MIXER_TAP_DATA:
6713 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6714 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6715 if (i != 0)
6717 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6718 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6720 break;
6723 case UDATA_INDICATION_MIXER_COEFS_SET:
6724 mixer_indication_coefs_set(Id, plci);
6725 break;
6726 case UDATA_INDICATION_XCONNECT_FROM:
6727 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6728 break;
6729 case UDATA_INDICATION_XCONNECT_TO:
6730 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6731 break;
6734 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6735 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6736 break;
6740 default:
6741 break;
6744 else
6746 if ((plci->RData[0].PLength != 0)
6747 && ((plci->B2_prot == B2_V120_ASYNC)
6748 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6749 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752 sendf(plci->appl, _DATA_B3_I, Id, 0,
6753 "dwww",
6754 plci->RData[1].P,
6755 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6756 plci->RNum,
6757 plci->RFlags);
6760 else
6763 sendf(plci->appl, _DATA_B3_I, Id, 0,
6764 "dwww",
6765 plci->RData[0].P,
6766 plci->RData[0].PLength,
6767 plci->RNum,
6768 plci->RFlags);
6772 return;
6775 fax_feature_bits = 0;
6776 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6777 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6778 (plci->NL.Ind & 0x0f) == N_DISC ||
6779 (plci->NL.Ind & 0x0f) == N_EDATA ||
6780 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6782 info = 0;
6783 plci->ncpi_buffer[0] = 0;
6784 switch (plci->B3_prot) {
6785 case 0: /*XPARENT*/
6786 case 1: /*T.90 NL*/
6787 break; /* no network control protocol info - jfr */
6788 case 2: /*ISO8202*/
6789 case 3: /*X25 DCE*/
6790 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6791 plci->ncpi_buffer[0] = (byte)(i + 3);
6792 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6793 plci->ncpi_buffer[2] = 0;
6794 plci->ncpi_buffer[3] = 0;
6795 break;
6796 case 4: /*T.30 - FAX*/
6797 case 5: /*T.30 - FAX*/
6798 if (plci->NL.RLength >= sizeof(T30_INFO))
6800 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6801 len = 9;
6802 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6803 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6804 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6805 if (plci->B3_prot == 5)
6807 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6808 i |= 0x8000; /* This is not an ECM connection */
6809 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6810 i |= 0x4000; /* This is a connection with MMR compression */
6811 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6812 i |= 0x2000; /* This is a connection with MR compression */
6813 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6814 i |= 0x0004; /* More documents */
6815 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6816 i |= 0x0002; /* Fax-polling indication */
6818 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6819 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6820 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6821 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6822 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6823 plci->ncpi_buffer[len] = 0;
6824 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6826 plci->ncpi_buffer[len] = 20;
6827 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6828 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6830 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6832 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6833 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6834 else
6835 info = _FAX_PROTOCOL_ERROR;
6838 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6839 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6841 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6842 while (i < plci->NL.RBuffer->length)
6843 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846 plci->ncpi_buffer[0] = len;
6847 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6848 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6850 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6851 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6852 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6853 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6854 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6855 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6856 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6857 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6859 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6861 if (((plci->NL.Ind & 0x0f) == N_DISC)
6862 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6863 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6864 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6866 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6869 break;
6871 case B3_RTP:
6872 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6874 if (plci->NL.RLength != 0)
6876 info = rtp_info[plci->NL.RBuffer->P[0]];
6877 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6878 for (i = 1; i < plci->NL.RLength; i++)
6879 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6882 break;
6885 plci->NL.RNR = 2;
6887 switch (plci->NL.Ind & 0x0f) {
6888 case N_EDATA:
6889 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6891 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6892 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6893 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6895 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6896 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6897 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6898 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6899 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6900 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6902 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6903 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6904 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6905 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6906 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6907 fax_send_edata_ack = false;
6910 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6912 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6914 case EDATA_T30_DIS:
6915 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6916 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6917 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6920 a->ncci_state[ncci] = INC_ACT_PENDING;
6921 if (plci->B3_prot == 4)
6922 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6923 else
6924 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6925 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6927 break;
6929 case EDATA_T30_TRAIN_OK:
6930 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6931 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6932 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6934 if (plci->B3_prot == 4)
6935 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6936 else
6937 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6938 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6940 break;
6942 case EDATA_T30_EOP_CAPI:
6943 if (a->ncci_state[ncci] == CONNECTED)
6945 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6946 a->ncci_state[ncci] = INC_DIS_PENDING;
6947 plci->ncpi_state = 0;
6948 fax_send_edata_ack = false;
6950 break;
6953 else
6955 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6957 case EDATA_T30_TRAIN_OK:
6958 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6959 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6960 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6962 if (plci->B3_prot == 4)
6963 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6964 else
6965 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6966 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6968 break;
6971 if (fax_send_edata_ack)
6973 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6974 plci->fax_edata_ack_length = 1;
6975 start_internal_command(Id, plci, fax_edata_ack_command);
6978 else
6980 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6982 break;
6983 case N_CONNECT:
6984 if (!a->ch_ncci[ch])
6986 ncci = get_ncci(plci, ch, 0);
6987 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6989 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6990 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6992 msg = _CONNECT_B3_I;
6993 if (a->ncci_state[ncci] == IDLE)
6994 plci->channels++;
6995 else if (plci->B3_prot == 1)
6996 msg = _CONNECT_B3_T90_ACTIVE_I;
6998 a->ncci_state[ncci] = INC_CON_PENDING;
6999 if (plci->B3_prot == 4)
7000 sendf(plci->appl, msg, Id, 0, "s", "");
7001 else
7002 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7003 break;
7004 case N_CONNECT_ACK:
7005 dbug(1, dprintf("N_connect_Ack"));
7006 if (plci->internal_command_queue[0]
7007 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7008 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7009 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7011 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7012 if (!plci->internal_command)
7013 next_internal_command(Id, plci);
7014 break;
7016 msg = _CONNECT_B3_ACTIVE_I;
7017 if (plci->B3_prot == 1)
7019 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7020 msg = _CONNECT_B3_T90_ACTIVE_I;
7021 a->ncci_state[ncci] = INC_ACT_PENDING;
7022 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7024 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7026 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7027 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7028 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7030 a->ncci_state[ncci] = INC_ACT_PENDING;
7031 if (plci->B3_prot == 4)
7032 sendf(plci->appl, msg, Id, 0, "s", "");
7033 else
7034 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7035 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7038 else
7040 a->ncci_state[ncci] = INC_ACT_PENDING;
7041 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7043 if (plci->adjust_b_restore)
7045 plci->adjust_b_restore = false;
7046 start_internal_command(Id, plci, adjust_b_restore);
7048 break;
7049 case N_DISC:
7050 case N_DISC_ACK:
7051 if (plci->internal_command_queue[0]
7052 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7053 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7054 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7056 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7057 if (!plci->internal_command)
7058 next_internal_command(Id, plci);
7060 ncci_state = a->ncci_state[ncci];
7061 ncci_remove(plci, ncci, false);
7063 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7064 /* channel, so we cannot store the state in ncci_state! The */
7065 /* information which channel we received a N_DISC is thus */
7066 /* stored in the inc_dis_ncci_table buffer. */
7067 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7068 plci->inc_dis_ncci_table[i] = (byte) ncci;
7070 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7071 if (!plci->channels
7072 && (plci->B1_resource == 16)
7073 && (plci->State <= CONNECTED))
7075 len = 9;
7076 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7077 PUT_WORD(&plci->ncpi_buffer[1], i);
7078 PUT_WORD(&plci->ncpi_buffer[3], 0);
7079 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7080 PUT_WORD(&plci->ncpi_buffer[5], i);
7081 PUT_WORD(&plci->ncpi_buffer[7], 0);
7082 plci->ncpi_buffer[len] = 0;
7083 plci->ncpi_buffer[0] = len;
7084 if (plci->B3_prot == 4)
7085 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7086 else
7089 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7090 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7092 plci->ncpi_buffer[++len] = 0;
7093 plci->ncpi_buffer[++len] = 0;
7094 plci->ncpi_buffer[++len] = 0;
7095 plci->ncpi_buffer[0] = len;
7098 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7100 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7101 plci->ncpi_state = 0;
7102 sig_req(plci, HANGUP, 0);
7103 send_req(plci);
7104 plci->State = OUTG_DIS_PENDING;
7105 /* disc here */
7107 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7108 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7109 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7111 if (ncci_state == IDLE)
7113 if (plci->channels)
7114 plci->channels--;
7115 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7116 if (plci->State == SUSPENDING) {
7117 sendf(plci->appl,
7118 _FACILITY_I,
7119 Id & 0xffffL,
7121 "ws", (word)3, "\x03\x04\x00\x00");
7122 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7124 plci_remove(plci);
7125 plci->State = IDLE;
7129 else if (plci->channels)
7131 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7132 plci->ncpi_state = 0;
7133 if ((ncci_state == OUTG_REJ_PENDING)
7134 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7136 sig_req(plci, HANGUP, 0);
7137 send_req(plci);
7138 plci->State = OUTG_DIS_PENDING;
7141 break;
7142 case N_RESET:
7143 a->ncci_state[ncci] = INC_RES_PENDING;
7144 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7145 break;
7146 case N_RESET_ACK:
7147 a->ncci_state[ncci] = CONNECTED;
7148 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7149 break;
7151 case N_UDATA:
7152 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7154 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7155 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7156 plci->NL.R = plci->RData;
7157 plci->NL.RNum = 1;
7158 return;
7160 case N_BDATA:
7161 case N_DATA:
7162 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7163 || (a->ncci_state[ncci] == IDLE)
7164 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7166 plci->NL.RNR = 2;
7167 break;
7169 if ((a->ncci_state[ncci] != CONNECTED)
7170 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7171 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7173 dbug(1, dprintf("flow control"));
7174 plci->NL.RNR = 1; /* flow control */
7175 channel_x_off(plci, ch, 0);
7176 break;
7179 NCCIcode = ncci | (((word)a->Id) << 8);
7181 /* count all buffers within the Application pool */
7182 /* belonging to the same NCCI. If this is below the */
7183 /* number of buffers available per NCCI we accept */
7184 /* this packet, otherwise we reject it */
7185 count = 0;
7186 Num = 0xffff;
7187 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7188 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7189 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7194 dbug(3, dprintf("Flow-Control"));
7195 plci->NL.RNR = 1;
7196 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7197 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7199 plci->NL.RNR = 2;
7200 dbug(3, dprintf("DiscardData"));
7201 } else {
7202 channel_x_off(plci, ch, 0);
7204 break;
7206 else
7208 APPLptr->NCCIDataFlowCtrlTimer = 0;
7211 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7212 if (!plci->RData[0].P) {
7213 plci->NL.RNR = 1;
7214 channel_x_off(plci, ch, 0);
7215 break;
7218 APPLptr->DataNCCI[Num] = NCCIcode;
7219 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7220 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7222 plci->RNum = Num;
7223 plci->RFlags = plci->NL.Ind >> 4;
7224 plci->RData[0].PLength = APPLptr->MaxDataLength;
7225 plci->NL.R = plci->RData;
7226 if ((plci->NL.RLength != 0)
7227 && ((plci->B2_prot == B2_V120_ASYNC)
7228 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7229 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7231 plci->RData[1].P = plci->RData[0].P;
7232 plci->RData[1].PLength = plci->RData[0].PLength;
7233 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7234 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7235 plci->RData[0].PLength = 1;
7236 else
7237 plci->RData[0].PLength = 2;
7238 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7239 plci->RFlags |= 0x0010;
7240 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7241 plci->RFlags |= 0x8000;
7242 plci->NL.RNum = 2;
7244 else
7246 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7247 plci->RFlags |= 0x0010;
7249 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7250 plci->RFlags |= 0x0001;
7252 plci->NL.RNum = 1;
7254 break;
7255 case N_DATA_ACK:
7256 data_ack(plci, ch);
7257 break;
7258 default:
7259 plci->NL.RNR = 2;
7260 break;
7264 /*------------------------------------------------------------------*/
7265 /* find a free PLCI */
7266 /*------------------------------------------------------------------*/
7268 static word get_plci(DIVA_CAPI_ADAPTER *a)
7270 word i, j;
7271 PLCI *plci;
7273 dump_plcis(a);
7274 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7275 if (i == a->max_plci) {
7276 dbug(1, dprintf("get_plci: out of PLCIs"));
7277 return 0;
7279 plci = &a->plci[i];
7280 plci->Id = (byte)(i + 1);
7282 plci->Sig.Id = 0;
7283 plci->NL.Id = 0;
7284 plci->sig_req = 0;
7285 plci->nl_req = 0;
7287 plci->appl = NULL;
7288 plci->relatedPTYPLCI = NULL;
7289 plci->State = IDLE;
7290 plci->SuppState = IDLE;
7291 plci->channels = 0;
7292 plci->tel = 0;
7293 plci->B1_resource = 0;
7294 plci->B2_prot = 0;
7295 plci->B3_prot = 0;
7297 plci->command = 0;
7298 plci->m_command = 0;
7299 init_internal_command_queue(plci);
7300 plci->number = 0;
7301 plci->req_in_start = 0;
7302 plci->req_in = 0;
7303 plci->req_out = 0;
7304 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7305 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7306 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7308 plci->data_sent = false;
7309 plci->send_disc = 0;
7310 plci->sig_global_req = 0;
7311 plci->sig_remove_id = 0;
7312 plci->nl_global_req = 0;
7313 plci->nl_remove_id = 0;
7314 plci->adv_nl = 0;
7315 plci->manufacturer = false;
7316 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7317 plci->spoofed_msg = 0;
7318 plci->ptyState = 0;
7319 plci->cr_enquiry = false;
7320 plci->hangup_flow_ctrl_timer = 0;
7322 plci->ncci_ring_list = 0;
7323 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7324 clear_c_ind_mask(plci);
7325 set_group_ind_mask(plci);
7326 plci->fax_connect_info_length = 0;
7327 plci->nsf_control_bits = 0;
7328 plci->ncpi_state = 0x00;
7329 plci->ncpi_buffer[0] = 0;
7331 plci->requested_options_conn = 0;
7332 plci->requested_options = 0;
7333 plci->notifiedcall = 0;
7334 plci->vswitchstate = 0;
7335 plci->vsprot = 0;
7336 plci->vsprotdialect = 0;
7337 init_b1_config(plci);
7338 dbug(1, dprintf("get_plci(%x)", plci->Id));
7339 return i + 1;
7342 /*------------------------------------------------------------------*/
7343 /* put a parameter in the parameter buffer */
7344 /*------------------------------------------------------------------*/
7346 static void add_p(PLCI *plci, byte code, byte *p)
7348 word p_length;
7350 p_length = 0;
7351 if (p) p_length = p[0];
7352 add_ie(plci, code, p, p_length);
7355 /*------------------------------------------------------------------*/
7356 /* put a structure in the parameter buffer */
7357 /*------------------------------------------------------------------*/
7358 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7360 if (p) add_ie(plci, code, p->info, (word)p->length);
7363 /*------------------------------------------------------------------*/
7364 /* put multiple structures in the parameter buffer */
7365 /*------------------------------------------------------------------*/
7366 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7368 byte i;
7370 if (p) {
7371 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7372 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7373 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7374 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7379 /*------------------------------------------------------------------*/
7380 /* return the channel number sent by the application in a esc_chi */
7381 /*------------------------------------------------------------------*/
7382 static byte getChannel(API_PARSE *p)
7384 byte i;
7386 if (p) {
7387 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7388 if (p->info[i] == 2) {
7389 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7393 return 0;
7397 /*------------------------------------------------------------------*/
7398 /* put an information element in the parameter buffer */
7399 /*------------------------------------------------------------------*/
7401 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7403 word i;
7405 if (!(code & 0x80) && !p_length) return;
7407 if (plci->req_in == plci->req_in_start) {
7408 plci->req_in += 2;
7410 else {
7411 plci->req_in--;
7413 plci->RBuffer[plci->req_in++] = code;
7415 if (p) {
7416 plci->RBuffer[plci->req_in++] = (byte)p_length;
7417 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420 plci->RBuffer[plci->req_in++] = 0;
7423 /*------------------------------------------------------------------*/
7424 /* put a unstructured data into the buffer */
7425 /*------------------------------------------------------------------*/
7427 static void add_d(PLCI *plci, word length, byte *p)
7429 word i;
7431 if (plci->req_in == plci->req_in_start) {
7432 plci->req_in += 2;
7434 else {
7435 plci->req_in--;
7437 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440 /*------------------------------------------------------------------*/
7441 /* put parameters from the Additional Info parameter in the */
7442 /* parameter buffer */
7443 /*------------------------------------------------------------------*/
7445 static void add_ai(PLCI *plci, API_PARSE *ai)
7447 word i;
7448 API_PARSE ai_parms[5];
7450 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7452 if (!ai->length)
7453 return;
7454 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7455 return;
7457 add_s(plci, KEY, &ai_parms[1]);
7458 add_s(plci, UUI, &ai_parms[2]);
7459 add_ss(plci, FTY, &ai_parms[3]);
7462 /*------------------------------------------------------------------*/
7463 /* put parameter for b1 protocol in the parameter buffer */
7464 /*------------------------------------------------------------------*/
7466 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7467 word b1_facilities)
7469 API_PARSE bp_parms[8];
7470 API_PARSE mdm_cfg[9];
7471 API_PARSE global_config[2];
7472 byte cai[256];
7473 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7474 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7475 word i;
7477 API_PARSE mdm_cfg_v18[4];
7478 word j, n, w;
7479 dword d;
7482 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7483 for (i = 0; i < 2; i++) global_config[i].length = 0;
7485 dbug(1, dprintf("add_b1"));
7486 api_save_msg(bp, "s", &plci->B_protocol);
7488 if (b_channel_info == 2) {
7489 plci->B1_resource = 0;
7490 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7491 add_p(plci, CAI, "\x01\x00");
7492 dbug(1, dprintf("Cai=1,0 (no resource)"));
7493 return 0;
7496 if (plci->tel == CODEC_PERMANENT) return 0;
7497 else if (plci->tel == CODEC) {
7498 plci->B1_resource = 1;
7499 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7500 add_p(plci, CAI, "\x01\x01");
7501 dbug(1, dprintf("Cai=1,1 (Codec)"));
7502 return 0;
7504 else if (plci->tel == ADV_VOICE) {
7505 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7506 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7507 voice_cai[1] = plci->B1_resource;
7508 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7509 add_p(plci, CAI, voice_cai);
7510 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7511 return 0;
7513 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7514 if (plci->call_dir & CALL_DIR_OUT)
7515 plci->call_dir |= CALL_DIR_ORIGINATE;
7516 else if (plci->call_dir & CALL_DIR_IN)
7517 plci->call_dir |= CALL_DIR_ANSWER;
7519 if (!bp->length) {
7520 plci->B1_resource = 0x5;
7521 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7522 add_p(plci, CAI, "\x01\x05");
7523 return 0;
7526 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7527 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7528 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7530 bp_parms[6].length = 0;
7531 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7533 dbug(1, dprintf("b-form.!"));
7534 return _WRONG_MESSAGE_FORMAT;
7537 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7539 dbug(1, dprintf("b-form.!"));
7540 return _WRONG_MESSAGE_FORMAT;
7543 if (bp_parms[6].length)
7545 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7547 return _WRONG_MESSAGE_FORMAT;
7549 switch (GET_WORD(global_config[0].info))
7551 case 1:
7552 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7553 break;
7554 case 2:
7555 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7556 break;
7559 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7563 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7565 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567 cai[1] = plci->B1_resource;
7568 cai[2] = 0;
7569 cai[3] = 0;
7570 cai[4] = 0;
7571 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7572 for (i = 0; i < bp_parms[3].length; i++)
7573 cai[7 + i] = bp_parms[3].info[1 + i];
7574 cai[0] = 6 + bp_parms[3].length;
7575 add_p(plci, CAI, cai);
7576 return 0;
7580 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7581 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7583 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7584 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7585 cai[1] = plci->B1_resource;
7586 cai[2] = 0;
7587 cai[3] = 0;
7588 cai[4] = 0;
7589 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7590 cai[0] = 6;
7591 add_p(plci, CAI, cai);
7592 return 0;
7596 if ((GET_WORD(bp_parms[0].info) >= 32)
7597 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7598 && ((GET_WORD(bp_parms[0].info) != 3)
7599 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7600 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7602 return _B1_NOT_SUPPORTED;
7604 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7605 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7606 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7607 cai[0] = 6;
7608 cai[1] = plci->B1_resource;
7609 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7611 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7612 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7613 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7614 { /* B1 - modem */
7615 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7617 if (bp_parms[3].length)
7619 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7621 return (_WRONG_MESSAGE_FORMAT);
7624 cai[2] = 0; /* Bit rate for adaptation */
7626 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7628 PUT_WORD(&cai[13], 0); /* Min Tx speed */
7629 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7630 PUT_WORD(&cai[17], 0); /* Min Rx speed */
7631 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7633 cai[3] = 0; /* Async framing parameters */
7634 switch (GET_WORD(mdm_cfg[2].info))
7635 { /* Parity */
7636 case 1: /* odd parity */
7637 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7638 dbug(1, dprintf("MDM: odd parity"));
7639 break;
7641 case 2: /* even parity */
7642 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7643 dbug(1, dprintf("MDM: even parity"));
7644 break;
7646 default:
7647 dbug(1, dprintf("MDM: no parity"));
7648 break;
7651 switch (GET_WORD(mdm_cfg[3].info))
7652 { /* stop bits */
7653 case 1: /* 2 stop bits */
7654 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7655 dbug(1, dprintf("MDM: 2 stop bits"));
7656 break;
7658 default:
7659 dbug(1, dprintf("MDM: 1 stop bit"));
7660 break;
7663 switch (GET_WORD(mdm_cfg[1].info))
7664 { /* char length */
7665 case 5:
7666 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7667 dbug(1, dprintf("MDM: 5 bits"));
7668 break;
7670 case 6:
7671 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7672 dbug(1, dprintf("MDM: 6 bits"));
7673 break;
7675 case 7:
7676 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7677 dbug(1, dprintf("MDM: 7 bits"));
7678 break;
7680 default:
7681 dbug(1, dprintf("MDM: 8 bits"));
7682 break;
7685 cai[7] = 0; /* Line taking options */
7686 cai[8] = 0; /* Modulation negotiation options */
7687 cai[9] = 0; /* Modulation options */
7689 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7691 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7692 dbug(1, dprintf("MDM: Reverse direction"));
7695 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7697 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7698 dbug(1, dprintf("MDM: Disable retrain"));
7701 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7703 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7704 dbug(1, dprintf("MDM: Disable ring tone"));
7707 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7709 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7710 dbug(1, dprintf("MDM: 1800 guard tone"));
7712 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7714 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7715 dbug(1, dprintf("MDM: 550 guard tone"));
7718 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7720 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7721 dbug(1, dprintf("MDM: V100"));
7723 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7725 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7726 dbug(1, dprintf("MDM: IN CLASS"));
7728 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7730 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7731 dbug(1, dprintf("MDM: DISABLED"));
7733 cai[0] = 20;
7735 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7736 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7738 plci->requested_options |= 1L << PRIVATE_V18;
7740 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7741 plci->requested_options |= 1L << PRIVATE_VOWN;
7743 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7744 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7746 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7748 i = 27;
7749 if (mdm_cfg[6].length >= 4)
7751 d = GET_DWORD(&mdm_cfg[6].info[1]);
7752 cai[7] |= (byte) d; /* line taking options */
7753 cai[9] |= (byte)(d >> 8); /* modulation options */
7754 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7755 cai[++i] = (byte)(d >> 24);
7756 if (mdm_cfg[6].length >= 8)
7758 d = GET_DWORD(&mdm_cfg[6].info[5]);
7759 cai[10] |= (byte) d; /* disabled modulations mask */
7760 cai[11] |= (byte)(d >> 8);
7761 if (mdm_cfg[6].length >= 12)
7763 d = GET_DWORD(&mdm_cfg[6].info[9]);
7764 cai[12] = (byte) d; /* enabled modulations mask */
7765 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7766 cai[++i] = (byte)(d >> 16);
7767 cai[++i] = (byte)(d >> 24);
7768 cai[++i] = 0;
7769 if (mdm_cfg[6].length >= 14)
7771 w = GET_WORD(&mdm_cfg[6].info[13]);
7772 if (w != 0)
7773 PUT_WORD(&cai[13], w); /* min tx speed */
7774 if (mdm_cfg[6].length >= 16)
7776 w = GET_WORD(&mdm_cfg[6].info[15]);
7777 if (w != 0)
7778 PUT_WORD(&cai[15], w); /* max tx speed */
7779 if (mdm_cfg[6].length >= 18)
7781 w = GET_WORD(&mdm_cfg[6].info[17]);
7782 if (w != 0)
7783 PUT_WORD(&cai[17], w); /* min rx speed */
7784 if (mdm_cfg[6].length >= 20)
7786 w = GET_WORD(&mdm_cfg[6].info[19]);
7787 if (w != 0)
7788 PUT_WORD(&cai[19], w); /* max rx speed */
7789 if (mdm_cfg[6].length >= 22)
7791 w = GET_WORD(&mdm_cfg[6].info[21]);
7792 cai[23] = (byte)(-((short) w)); /* transmit level */
7793 if (mdm_cfg[6].length >= 24)
7795 w = GET_WORD(&mdm_cfg[6].info[23]);
7796 cai[22] |= (byte) w; /* info options mask */
7797 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7807 cai[27] = i - 27;
7808 i++;
7809 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7811 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7813 for (n = 0; n < 3; n++)
7815 cai[i] = (byte)(mdm_cfg_v18[n].length);
7816 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7817 cai[i + j] = mdm_cfg_v18[n].info[j];
7818 i += cai[i] + 1;
7822 cai[0] = (byte)(i - 1);
7828 if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7829 GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7831 if (bp_parms[3].length) {
7832 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7833 switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7834 case 0:
7835 case 56000:
7836 if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7837 dbug(1, dprintf("56k sync HSCX"));
7838 cai[1] = 8;
7839 cai[2] = 0;
7840 cai[3] = 0;
7842 else if (GET_WORD(bp_parms[0].info) == 2) {
7843 dbug(1, dprintf("56k async DSP"));
7844 cai[2] = 9;
7846 break;
7847 case 50: cai[2] = 1; break;
7848 case 75: cai[2] = 1; break;
7849 case 110: cai[2] = 1; break;
7850 case 150: cai[2] = 1; break;
7851 case 200: cai[2] = 1; break;
7852 case 300: cai[2] = 1; break;
7853 case 600: cai[2] = 1; break;
7854 case 1200: cai[2] = 2; break;
7855 case 2400: cai[2] = 3; break;
7856 case 4800: cai[2] = 4; break;
7857 case 7200: cai[2] = 10; break;
7858 case 9600: cai[2] = 5; break;
7859 case 12000: cai[2] = 13; break;
7860 case 24000: cai[2] = 0; break;
7861 case 14400: cai[2] = 11; break;
7862 case 19200: cai[2] = 6; break;
7863 case 28800: cai[2] = 12; break;
7864 case 38400: cai[2] = 7; break;
7865 case 48000: cai[2] = 8; break;
7866 case 76: cai[2] = 15; break; /* 75/1200 */
7867 case 1201: cai[2] = 14; break; /* 1200/75 */
7868 case 56001: cai[2] = 9; break; /* V.110 56000 */
7870 default:
7871 return _B1_PARM_NOT_SUPPORTED;
7873 cai[3] = 0;
7874 if (cai[1] == 13) /* v.110 async */
7876 if (bp_parms[3].length >= 8)
7878 switch (GET_WORD(&bp_parms[3].info[3]))
7879 { /* char length */
7880 case 5:
7881 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7882 break;
7883 case 6:
7884 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7885 break;
7886 case 7:
7887 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7888 break;
7890 switch (GET_WORD(&bp_parms[3].info[5]))
7891 { /* Parity */
7892 case 1: /* odd parity */
7893 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7894 break;
7895 case 2: /* even parity */
7896 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7897 break;
7899 switch (GET_WORD(&bp_parms[3].info[7]))
7900 { /* stop bits */
7901 case 1: /* 2 stop bits */
7902 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7903 break;
7908 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7909 dbug(1, dprintf("V.110 default 56k sync"));
7910 cai[1] = 8;
7911 cai[2] = 0;
7912 cai[3] = 0;
7914 else {
7915 dbug(1, dprintf("V.110 default 9600 async"));
7916 cai[2] = 5;
7919 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7920 dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7921 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7923 add_p(plci, CAI, cai);
7924 return 0;
7927 /*------------------------------------------------------------------*/
7928 /* put parameter for b2 and B3 protocol in the parameter buffer */
7929 /*------------------------------------------------------------------*/
7931 static word add_b23(PLCI *plci, API_PARSE *bp)
7933 word i, fax_control_bits;
7934 byte pos, len;
7935 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7936 API_PARSE bp_parms[8];
7937 API_PARSE *b1_config;
7938 API_PARSE *b2_config;
7939 API_PARSE b2_config_parms[8];
7940 API_PARSE *b3_config;
7941 API_PARSE b3_config_parms[6];
7942 API_PARSE global_config[2];
7944 static byte llc[3] = {2,0,0};
7945 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7946 static byte nlc[256];
7947 static byte lli[12] = {1,1};
7949 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7950 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952 const byte llc3[] = {4,3,2,2,6,6,0};
7953 const byte header[] = {0,2,3,3,0,0,0};
7955 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7956 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7957 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7959 lli[0] = 1;
7960 lli[1] = 1;
7961 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7962 lli[1] |= 2;
7963 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7964 lli[1] |= 4;
7966 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7967 lli[1] |= 0x10;
7968 if (plci->rx_dma_descriptor <= 0) {
7969 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7970 if (plci->rx_dma_descriptor >= 0)
7971 plci->rx_dma_descriptor++;
7973 if (plci->rx_dma_descriptor > 0) {
7974 lli[0] = 6;
7975 lli[1] |= 0x40;
7976 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7977 lli[3] = (byte)plci->rx_dma_magic;
7978 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7979 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7980 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7984 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7985 lli[1] |= 0x20;
7988 dbug(1, dprintf("add_b23"));
7989 api_save_msg(bp, "s", &plci->B_protocol);
7991 if (!bp->length && plci->tel)
7993 plci->adv_nl = true;
7994 dbug(1, dprintf("Default adv.Nl"));
7995 add_p(plci, LLI, lli);
7996 plci->B2_prot = 1 /*XPARENT*/;
7997 plci->B3_prot = 0 /*XPARENT*/;
7998 llc[1] = 2;
7999 llc[2] = 4;
8000 add_p(plci, LLC, llc);
8001 dlc[0] = 2;
8002 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8003 add_p(plci, DLC, dlc);
8004 return 0;
8007 if (!bp->length) /*default*/
8009 dbug(1, dprintf("ret default"));
8010 add_p(plci, LLI, lli);
8011 plci->B2_prot = 0 /*X.75 */;
8012 plci->B3_prot = 0 /*XPARENT*/;
8013 llc[1] = 1;
8014 llc[2] = 4;
8015 add_p(plci, LLC, llc);
8016 dlc[0] = 2;
8017 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8018 add_p(plci, DLC, dlc);
8019 return 0;
8021 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8022 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8024 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8026 bp_parms[6].length = 0;
8027 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8029 dbug(1, dprintf("b-form.!"));
8030 return _WRONG_MESSAGE_FORMAT;
8033 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8035 dbug(1, dprintf("b-form.!"));
8036 return _WRONG_MESSAGE_FORMAT;
8039 if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8041 if (GET_WORD(bp_parms[1].info) != 1
8042 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8043 plci->adv_nl = true;
8045 else if (plci->tel) return _B2_NOT_SUPPORTED;
8048 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8049 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8050 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8052 add_p(plci, LLI, lli);
8053 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8054 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8055 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8056 llc[2] = 4;
8057 add_p(plci, LLC, llc);
8058 dlc[0] = 2;
8059 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8060 dlc[3] = 3; /* Addr A */
8061 dlc[4] = 1; /* Addr B */
8062 dlc[5] = 7; /* modulo mode */
8063 dlc[6] = 7; /* window size */
8064 dlc[7] = 0; /* XID len Lo */
8065 dlc[8] = 0; /* XID len Hi */
8066 for (i = 0; i < bp_parms[4].length; i++)
8067 dlc[9 + i] = bp_parms[4].info[1 + i];
8068 dlc[0] = (byte)(8 + bp_parms[4].length);
8069 add_p(plci, DLC, dlc);
8070 for (i = 0; i < bp_parms[5].length; i++)
8071 nlc[1 + i] = bp_parms[5].info[1 + i];
8072 nlc[0] = (byte)(bp_parms[5].length);
8073 add_p(plci, NLC, nlc);
8074 return 0;
8079 if ((GET_WORD(bp_parms[1].info) >= 32)
8080 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8081 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8082 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085 return _B2_NOT_SUPPORTED;
8087 if ((GET_WORD(bp_parms[2].info) >= 32)
8088 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8090 return _B3_NOT_SUPPORTED;
8092 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8093 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8094 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8095 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8097 return (add_modem_b23(plci, bp_parms));
8100 add_p(plci, LLI, lli);
8102 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8103 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8104 if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8106 if (bp_parms[6].length)
8108 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8110 return _WRONG_MESSAGE_FORMAT;
8112 switch (GET_WORD(global_config[0].info))
8114 case 1:
8115 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8116 break;
8117 case 2:
8118 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8119 break;
8122 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125 if (plci->B2_prot == B2_PIAFS)
8126 llc[1] = PIAFS_CRC;
8127 else
8128 /* IMPLEMENT_PIAFS */
8130 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8131 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8133 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8135 add_p(plci, LLC, llc);
8137 dlc[0] = 2;
8138 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8139 header[GET_WORD(bp_parms[2].info)]);
8141 b1_config = &bp_parms[3];
8142 nlc[0] = 0;
8143 if (plci->B3_prot == 4
8144 || plci->B3_prot == 5)
8146 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8147 nlc[0] = sizeof(T30_INFO);
8148 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8149 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8150 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8151 if (b1_config->length >= 2)
8153 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156 b2_config = &bp_parms[4];
8159 if (llc[1] == PIAFS_CRC)
8161 if (plci->B3_prot != B3_TRANSPARENT)
8163 return _B_STACK_NOT_SUPPORTED;
8165 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8166 return _WRONG_MESSAGE_FORMAT;
8168 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8169 dlc[3] = 0; /* Addr A */
8170 dlc[4] = 0; /* Addr B */
8171 dlc[5] = 0; /* modulo mode */
8172 dlc[6] = 0; /* window size */
8173 if (b2_config->length >= 7) {
8174 dlc[7] = 7;
8175 dlc[8] = 0;
8176 dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8177 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8178 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8179 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8180 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8181 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8182 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8183 dlc[0] = 15;
8184 if (b2_config->length >= 8) { /* PIAFS control abilities */
8185 dlc[7] = 10;
8186 dlc[16] = 2; /* Length of PIAFS extension */
8187 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8188 dlc[18] = b2_config_parms[4].info[0]; /* value */
8189 dlc[0] = 18;
8192 else /* default values, 64K, variable, no compression */
8194 dlc[7] = 7;
8195 dlc[8] = 0;
8196 dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8197 dlc[10] = 0x03; /* V.42bis P0 */
8198 dlc[11] = 0; /* V.42bis P0 */
8199 dlc[12] = 0; /* V.42bis P1 */
8200 dlc[13] = 0; /* V.42bis P1 */
8201 dlc[14] = 0; /* V.42bis P2 */
8202 dlc[15] = 0; /* V.42bis P2 */
8203 dlc[0] = 15;
8205 add_p(plci, DLC, dlc);
8207 else
8209 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8211 if (plci->B3_prot != B3_TRANSPARENT)
8212 return _B_STACK_NOT_SUPPORTED;
8214 dlc[0] = 6;
8215 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8216 dlc[3] = 0x08;
8217 dlc[4] = 0x01;
8218 dlc[5] = 127;
8219 dlc[6] = 7;
8220 if (b2_config->length != 0)
8222 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8223 return _WRONG_MESSAGE_FORMAT;
8225 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8226 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8227 if (b2_config->info[3] != 128)
8229 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8230 return _B2_PARM_NOT_SUPPORTED;
8232 dlc[5] = (byte)(b2_config->info[3] - 1);
8233 dlc[6] = b2_config->info[4];
8234 if (llc[1] == V120_V42BIS) {
8235 if (b2_config->length >= 10) {
8236 dlc[7] = 6;
8237 dlc[8] = 0;
8238 dlc[9] = b2_config_parms[4].info[0];
8239 dlc[10] = b2_config_parms[4].info[1];
8240 dlc[11] = b2_config_parms[5].info[0];
8241 dlc[12] = b2_config_parms[5].info[1];
8242 dlc[13] = b2_config_parms[6].info[0];
8243 dlc[14] = b2_config_parms[6].info[1];
8244 dlc[0] = 14;
8245 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8246 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8247 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8249 else {
8250 dlc[6] = 14;
8255 else
8257 if (b2_config->length)
8259 dbug(1, dprintf("B2-Config"));
8260 if (llc[1] == X75_V42BIS) {
8261 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8263 return _WRONG_MESSAGE_FORMAT;
8266 else {
8267 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8269 return _WRONG_MESSAGE_FORMAT;
8272 /* if B2 Protocol is LAPD, b2_config structure is different */
8273 if (llc[1] == 6)
8275 dlc[0] = 4;
8276 if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8277 else dlc[2] = 0x01;
8278 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8280 SAPI = b2_config->info[2]; /* SAPI */
8282 dlc[1] = SAPI;
8283 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8285 dlc[3] = 127; /* Mode */
8287 else
8289 dlc[3] = 7; /* Mode */
8292 if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8293 else dlc[4] = 1;
8294 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8295 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8297 else
8299 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8300 dlc[3] = b2_config->info[1];
8301 dlc[4] = b2_config->info[2];
8302 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8303 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8304 return _B2_PARM_NOT_SUPPORTED;
8307 dlc[5] = (byte)(b2_config->info[3] - 1);
8308 dlc[6] = b2_config->info[4];
8309 if (dlc[6] > dlc[5]) {
8310 dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8311 return _B2_PARM_NOT_SUPPORTED;
8314 if (llc[1] == X75_V42BIS) {
8315 if (b2_config->length >= 10) {
8316 dlc[7] = 6;
8317 dlc[8] = 0;
8318 dlc[9] = b2_config_parms[4].info[0];
8319 dlc[10] = b2_config_parms[4].info[1];
8320 dlc[11] = b2_config_parms[5].info[0];
8321 dlc[12] = b2_config_parms[5].info[1];
8322 dlc[13] = b2_config_parms[6].info[0];
8323 dlc[14] = b2_config_parms[6].info[1];
8324 dlc[0] = 14;
8325 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8326 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8327 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8329 else {
8330 dlc[6] = 14;
8334 else {
8335 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8336 for (i = 0; i < b2_config_parms[4].length; i++)
8337 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8342 add_p(plci, DLC, dlc);
8344 b3_config = &bp_parms[5];
8345 if (b3_config->length)
8347 if (plci->B3_prot == 4
8348 || plci->B3_prot == 5)
8350 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8352 return _WRONG_MESSAGE_FORMAT;
8354 i = GET_WORD((byte *)(b3_config_parms[0].info));
8355 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8356 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8357 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8358 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8359 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8360 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8361 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8364 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8365 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8367 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8368 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8369 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8372 ((T30_INFO *)&nlc[1])->recording_properties =
8373 T30_RECORDING_WIDTH_ISO_A3 |
8374 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8375 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8377 if (plci->B3_prot == 5)
8379 if (i & 0x0002) /* Accept incoming fax-polling requests */
8380 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8381 if (i & 0x2000) /* Do not use MR compression */
8382 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8383 if (i & 0x4000) /* Do not use MMR compression */
8384 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8385 if (i & 0x8000) /* Do not use ECM */
8386 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8387 if (plci->fax_connect_info_length != 0)
8389 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8390 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8391 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8392 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8393 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8396 /* copy station id to NLC */
8397 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8399 if (i < b3_config_parms[2].length)
8401 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8403 else
8405 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8409 /* copy head line to NLC */
8410 if (b3_config_parms[3].length)
8413 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8414 if (pos != 0)
8416 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8417 pos = 0;
8418 else
8420 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8421 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8422 len = (byte)b3_config_parms[2].length;
8423 if (len > 20)
8424 len = 20;
8425 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8427 for (i = 0; i < len; i++)
8428 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8429 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8430 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8435 len = (byte)b3_config_parms[3].length;
8436 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8437 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8438 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8439 nlc[0] += (byte)(pos + len);
8440 for (i = 0; i < len; i++)
8441 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8442 } else
8443 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8445 plci->nsf_control_bits = 0;
8446 if (plci->B3_prot == 5)
8448 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8449 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8451 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8453 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8454 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8456 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8458 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8459 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8461 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8462 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8464 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8465 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8466 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8468 len = nlc[0];
8469 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8470 if (pos < plci->fax_connect_info_length)
8472 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8473 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8475 else
8476 nlc[++len] = 0;
8477 if (pos < plci->fax_connect_info_length)
8479 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8482 else
8483 nlc[++len] = 0;
8484 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8485 & (1L << PRIVATE_FAX_NONSTANDARD))
8487 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8489 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8490 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8491 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8492 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8494 else
8496 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8498 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8499 nlc[++len] = 0;
8501 else
8503 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8504 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8505 nlc[++len] = (byte)(b3_config_parms[4].length);
8506 for (i = 0; i < b3_config_parms[4].length; i++)
8507 nlc[++len] = b3_config_parms[4].info[1 + i];
8511 nlc[0] = len;
8512 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8513 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8515 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8520 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8521 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8522 for (i = 0; i < len; i++)
8523 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8524 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8525 i += ((T30_INFO *)&nlc[1])->head_line_len;
8526 while (i < nlc[0])
8527 plci->fax_connect_info_buffer[len++] = nlc[++i];
8528 plci->fax_connect_info_length = len;
8530 else
8532 nlc[0] = 14;
8533 if (b3_config->length != 16)
8534 return _B3_PARM_NOT_SUPPORTED;
8535 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8536 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8537 return _B3_PARM_NOT_SUPPORTED;
8538 nlc[13] = b3_config->info[13];
8539 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8540 return _B3_PARM_NOT_SUPPORTED;
8541 nlc[14] = b3_config->info[15];
8544 else
8546 if (plci->B3_prot == 4
8547 || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8549 add_p(plci, NLC, nlc);
8550 return 0;
8553 /*----------------------------------------------------------------*/
8554 /* make the same as add_b23, but only for the modem related */
8555 /* L2 and L3 B-Chan protocol. */
8556 /* */
8557 /* Enabled L2 and L3 Configurations: */
8558 /* If L1 == Modem all negotiation */
8559 /* only L2 == Modem with full negotiation is allowed */
8560 /* If L1 == Modem async or sync */
8561 /* only L2 == Transparent is allowed */
8562 /* L3 == Modem or L3 == Transparent are allowed */
8563 /* B2 Configuration for modem: */
8564 /* word : enable/disable compression, bitoptions */
8565 /* B3 Configuration for modem: */
8566 /* empty */
8567 /*----------------------------------------------------------------*/
8568 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8570 static byte lli[12] = {1,1};
8571 static byte llc[3] = {2,0,0};
8572 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8573 API_PARSE mdm_config[2];
8574 word i;
8575 word b2_config = 0;
8577 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8578 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8580 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8581 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8582 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8583 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8585 return (_B_STACK_NOT_SUPPORTED);
8587 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8588 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8590 return (_B_STACK_NOT_SUPPORTED);
8593 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8594 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8596 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8598 if (api_parse(&bp_parms[4].info[1],
8599 (word)bp_parms[4].length, "w",
8600 mdm_config))
8602 return (_WRONG_MESSAGE_FORMAT);
8604 b2_config = GET_WORD(mdm_config[0].info);
8607 /* OK, L2 is modem */
8609 lli[0] = 1;
8610 lli[1] = 1;
8611 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8612 lli[1] |= 2;
8613 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8614 lli[1] |= 4;
8616 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8617 lli[1] |= 0x10;
8618 if (plci->rx_dma_descriptor <= 0) {
8619 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8620 if (plci->rx_dma_descriptor >= 0)
8621 plci->rx_dma_descriptor++;
8623 if (plci->rx_dma_descriptor > 0) {
8624 lli[1] |= 0x40;
8625 lli[0] = 6;
8626 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8627 lli[3] = (byte)plci->rx_dma_magic;
8628 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8629 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8630 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8634 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8635 lli[1] |= 0x20;
8638 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8639 /*V42*/ 10 : /*V42_IN*/ 9;
8640 llc[2] = 4; /* pass L3 always transparent */
8641 add_p(plci, LLI, lli);
8642 add_p(plci, LLC, llc);
8643 i = 1;
8644 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8645 i += 2;
8646 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8648 if (bp_parms[4].length)
8650 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8651 dlc[i++] = 3; /* Addr A */
8652 dlc[i++] = 1; /* Addr B */
8653 dlc[i++] = 7; /* modulo mode */
8654 dlc[i++] = 7; /* window size */
8655 dlc[i++] = 0; /* XID len Lo */
8656 dlc[i++] = 0; /* XID len Hi */
8658 if (b2_config & MDM_B2_DISABLE_V42bis)
8660 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8662 if (b2_config & MDM_B2_DISABLE_MNP)
8664 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8666 if (b2_config & MDM_B2_DISABLE_TRANS)
8668 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8670 if (b2_config & MDM_B2_DISABLE_V42)
8672 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8674 if (b2_config & MDM_B2_DISABLE_COMP)
8676 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8678 i++;
8681 else
8683 dlc[i++] = 3; /* Addr A */
8684 dlc[i++] = 1; /* Addr B */
8685 dlc[i++] = 7; /* modulo mode */
8686 dlc[i++] = 7; /* window size */
8687 dlc[i++] = 0; /* XID len Lo */
8688 dlc[i++] = 0; /* XID len Hi */
8689 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8690 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8691 DLC_MODEMPROT_DISABLE_V42_DETECT |
8692 DLC_MODEMPROT_DISABLE_COMPRESSION;
8694 dlc[0] = (byte)(i - 1);
8695 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8696 add_p(plci, DLC, dlc);
8697 return (0);
8701 /*------------------------------------------------------------------*/
8702 /* send a request for the signaling entity */
8703 /*------------------------------------------------------------------*/
8705 static void sig_req(PLCI *plci, byte req, byte Id)
8707 if (!plci) return;
8708 if (plci->adapter->adapter_disabled) return;
8709 dbug(1, dprintf("sig_req(%x)", req));
8710 if (req == REMOVE)
8711 plci->sig_remove_id = plci->Sig.Id;
8712 if (plci->req_in == plci->req_in_start) {
8713 plci->req_in += 2;
8714 plci->RBuffer[plci->req_in++] = 0;
8716 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8717 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8718 plci->RBuffer[plci->req_in++] = req; /* request */
8719 plci->RBuffer[plci->req_in++] = 0; /* channel */
8720 plci->req_in_start = plci->req_in;
8723 /*------------------------------------------------------------------*/
8724 /* send a request for the network layer entity */
8725 /*------------------------------------------------------------------*/
8727 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8729 if (!plci) return;
8730 if (plci->adapter->adapter_disabled) return;
8731 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8732 if (req == REMOVE)
8734 plci->nl_remove_id = plci->NL.Id;
8735 ncci_remove(plci, 0, (byte)(ncci != 0));
8736 ncci = 0;
8738 if (plci->req_in == plci->req_in_start) {
8739 plci->req_in += 2;
8740 plci->RBuffer[plci->req_in++] = 0;
8742 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8743 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8744 plci->RBuffer[plci->req_in++] = req; /* request */
8745 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8746 plci->req_in_start = plci->req_in;
8749 static void send_req(PLCI *plci)
8751 ENTITY *e;
8752 word l;
8753 /* word i; */
8755 if (!plci) return;
8756 if (plci->adapter->adapter_disabled) return;
8757 channel_xmit_xon(plci);
8759 /* if nothing to do, return */
8760 if (plci->req_in == plci->req_out) return;
8761 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8763 if (plci->nl_req || plci->sig_req) return;
8765 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8766 plci->req_out += 2;
8767 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8768 plci->req_out += l;
8769 if (plci->RBuffer[plci->req_out] == 1)
8771 e = &plci->NL;
8772 plci->req_out++;
8773 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8774 e->ReqCh = plci->RBuffer[plci->req_out++];
8775 if (!(e->Id & 0x1f))
8777 e->Id = NL_ID;
8778 plci->RBuffer[plci->req_out - 4] = CAI;
8779 plci->RBuffer[plci->req_out - 3] = 1;
8780 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8781 plci->RBuffer[plci->req_out - 1] = 0;
8782 l += 3;
8783 plci->nl_global_req = plci->nl_req;
8785 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8787 else
8789 e = &plci->Sig;
8790 if (plci->RBuffer[plci->req_out])
8791 e->Id = plci->RBuffer[plci->req_out];
8792 plci->req_out++;
8793 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8794 e->ReqCh = plci->RBuffer[plci->req_out++];
8795 if (!(e->Id & 0x1f))
8796 plci->sig_global_req = plci->sig_req;
8797 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8799 plci->XData[0].PLength = l;
8800 e->X = plci->XData;
8801 plci->adapter->request(e);
8802 dbug(1, dprintf("send_ok"));
8805 static void send_data(PLCI *plci)
8807 DIVA_CAPI_ADAPTER *a;
8808 DATA_B3_DESC *data;
8809 NCCI *ncci_ptr;
8810 word ncci;
8812 if (!plci->nl_req && plci->ncci_ring_list)
8814 a = plci->adapter;
8815 ncci = plci->ncci_ring_list;
8818 ncci = a->ncci_next[ncci];
8819 ncci_ptr = &(a->ncci[ncci]);
8820 if (!(a->ncci_ch[ncci]
8821 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8823 if (ncci_ptr->data_pending)
8825 if ((a->ncci_state[ncci] == CONNECTED)
8826 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8827 || (plci->send_disc == ncci))
8829 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8830 if ((plci->B2_prot == B2_V120_ASYNC)
8831 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8832 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8834 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8835 plci->NData[1].PLength = data->Length;
8836 if (data->Flags & 0x10)
8837 plci->NData[0].P = v120_break_header;
8838 else
8839 plci->NData[0].P = v120_default_header;
8840 plci->NData[0].PLength = 1;
8841 plci->NL.XNum = 2;
8842 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8844 else
8846 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8847 plci->NData[0].PLength = data->Length;
8848 if (data->Flags & 0x10)
8849 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8851 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8852 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8854 else
8855 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8857 plci->NL.X = plci->NData;
8858 plci->NL.ReqCh = a->ncci_ch[ncci];
8859 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8860 plci->data_sent = true;
8861 plci->data_sent_ptr = data->P;
8862 a->request(&plci->NL);
8864 else {
8865 cleanup_ncci_data(plci, ncci);
8868 else if (plci->send_disc == ncci)
8870 /* dprintf("N_DISC"); */
8871 plci->NData[0].PLength = 0;
8872 plci->NL.ReqCh = a->ncci_ch[ncci];
8873 plci->NL.Req = plci->nl_req = N_DISC;
8874 a->request(&plci->NL);
8875 plci->command = _DISCONNECT_B3_R;
8876 plci->send_disc = 0;
8879 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8880 plci->ncci_ring_list = ncci;
8884 static void listen_check(DIVA_CAPI_ADAPTER *a)
8886 word i, j;
8887 PLCI *plci;
8888 byte activnotifiedcalls = 0;
8890 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8891 if (!remove_started && !a->adapter_disabled)
8893 for (i = 0; i < a->max_plci; i++)
8895 plci = &(a->plci[i]);
8896 if (plci->notifiedcall) activnotifiedcalls++;
8898 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8900 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8901 if ((j = get_plci(a))) {
8902 a->listen_active++;
8903 plci = &a->plci[j - 1];
8904 plci->State = LISTENING;
8906 add_p(plci, OAD, "\x01\xfd");
8908 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8910 add_p(plci, CAI, "\x01\xc0");
8911 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8912 add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8913 add_p(plci, SHIFT | 6, NULL);
8914 add_p(plci, SIN, "\x02\x00\x00");
8915 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8916 sig_req(plci, ASSIGN, DSIG_ID);
8917 send_req(plci);
8923 /*------------------------------------------------------------------*/
8924 /* functions for all parameters sent in INDs */
8925 /*------------------------------------------------------------------*/
8927 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8929 word ploc; /* points to current location within packet */
8930 byte w;
8931 byte wlen;
8932 byte codeset, lock;
8933 byte *in;
8934 word i;
8935 word code;
8936 word mIEindex = 0;
8937 ploc = 0;
8938 codeset = 0;
8939 lock = 0;
8941 in = plci->Sig.RBuffer->P;
8942 for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8943 { /* element but parms array is larger */
8944 parms[i] = (byte *)"";
8946 for (i = 0; i < multiIEsize; i++)
8948 parms[i] = (byte *)"";
8951 while (ploc < plci->Sig.RBuffer->length - 1) {
8953 /* read information element id and length */
8954 w = in[ploc];
8956 if (w & 0x80) {
8957 /* w &=0xf0; removed, cannot detect congestion levels */
8958 /* upper 4 bit masked with w==SHIFT now */
8959 wlen = 0;
8961 else {
8962 wlen = (byte)(in[ploc + 1] + 1);
8964 /* check if length valid (not exceeding end of packet) */
8965 if ((ploc + wlen) > 270) return;
8966 if (lock & 0x80) lock &= 0x7f;
8967 else codeset = lock;
8969 if ((w & 0xf0) == SHIFT) {
8970 codeset = in[ploc];
8971 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8972 codeset &= 7;
8973 lock |= 0x80;
8975 else {
8976 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8977 else code = w;
8978 code |= (codeset << 8);
8980 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8982 if (i < parms_id[0] + 1) {
8983 if (!multiIEsize) { /* with multiIEs use next field index, */
8984 mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8987 parms[mIEindex] = &in[ploc + 1];
8988 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8989 if (parms_id[i] == OAD
8990 || parms_id[i] == CONN_NR
8991 || parms_id[i] == CAD) {
8992 if (in[ploc + 2] & 0x80) {
8993 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8994 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8995 in[ploc + 2] = 0x80;
8996 parms[mIEindex] = &in[ploc];
8999 mIEindex++; /* effects multiIEs only */
9003 ploc += (wlen + 1);
9005 return;
9008 /*------------------------------------------------------------------*/
9009 /* try to match a cip from received BC and HLC */
9010 /*------------------------------------------------------------------*/
9012 static byte ie_compare(byte *ie1, byte *ie2)
9014 word i;
9015 if (!ie1 || !ie2) return false;
9016 if (!ie1[0]) return false;
9017 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9018 return true;
9021 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9023 word i;
9024 word j;
9026 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9028 for (j = 16; j < 29 &&
9029 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9030 if (j == 29) return i;
9031 return j;
9035 static byte AddInfo(byte **add_i,
9036 byte **fty_i,
9037 byte *esc_chi,
9038 byte *facility)
9040 byte i;
9041 byte j;
9042 byte k;
9043 byte flen;
9044 byte len = 0;
9045 /* facility is a nested structure */
9046 /* FTY can be more than once */
9048 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9050 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9053 else
9055 add_i[0] = (byte *)"";
9057 if (!fty_i[0][0])
9059 add_i[3] = (byte *)"";
9061 else
9062 { /* facility array found */
9063 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9065 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9066 len += fty_i[i][0];
9067 len += 2;
9068 flen = fty_i[i][0];
9069 facility[j++] = 0x1c; /* copy fac IE */
9070 for (k = 0; k <= flen; k++, j++)
9072 facility[j] = fty_i[i][k];
9073 /* dbug(1, dprintf("%x ",facility[j])); */
9076 facility[0] = len;
9077 add_i[3] = facility;
9079 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
9080 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9081 len += 4; /* calculate length of all */
9082 return (len);
9085 /*------------------------------------------------------------------*/
9086 /* voice and codec features */
9087 /*------------------------------------------------------------------*/
9089 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9091 byte voice_chi[] = "\x02\x18\x01";
9092 byte channel;
9094 channel = chi[chi[0]] & 0x3;
9095 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9096 voice_chi[2] = (channel) ? channel : 1;
9097 add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
9098 add_p(plci, ESC, voice_chi); /* Channel */
9099 sig_req(plci, TEL_CTRL, 0);
9100 send_req(plci);
9101 if (a->AdvSignalPLCI)
9103 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9107 static void VoiceChannelOff(PLCI *plci)
9109 dbug(1, dprintf("ExtDevOFF"));
9110 add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
9111 sig_req(plci, TEL_CTRL, 0);
9112 send_req(plci);
9113 if (plci->adapter->AdvSignalPLCI)
9115 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9120 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9121 byte hook_listen)
9123 word j;
9124 PLCI *splci;
9126 /* check if hardware supports handset with hook states (adv.codec) */
9127 /* or if just a on board codec is supported */
9128 /* the advanced codec plci is just for internal use */
9130 /* diva Pro with on-board codec: */
9131 if (a->profile.Global_Options & HANDSET)
9133 /* new call, but hook states are already signalled */
9134 if (a->AdvCodecFLAG)
9136 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9138 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9139 return 0x2001; /* codec in use by another application */
9141 if (plci != NULL)
9143 a->AdvSignalPLCI = plci;
9144 plci->tel = ADV_VOICE;
9146 return 0; /* adv codec still used */
9148 if ((j = get_plci(a)))
9150 splci = &a->plci[j - 1];
9151 splci->tel = CODEC_PERMANENT;
9152 /* hook_listen indicates if a facility_req with handset/hook support */
9153 /* was sent. Otherwise if just a call on an external device was made */
9154 /* the codec will be used but the hook info will be discarded (just */
9155 /* the external controller is in use */
9156 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9157 else
9159 splci->State = ADVANCED_VOICE_NOSIG;
9160 if (plci)
9162 plci->spoofed_msg = SPOOFING_REQUIRED;
9164 /* indicate D-ch connect if */
9165 } /* codec is connected OK */
9166 if (plci != NULL)
9168 a->AdvSignalPLCI = plci;
9169 plci->tel = ADV_VOICE;
9171 a->AdvSignalAppl = appl;
9172 a->AdvCodecFLAG = true;
9173 a->AdvCodecPLCI = splci;
9174 add_p(splci, CAI, "\x01\x15");
9175 add_p(splci, LLI, "\x01\x00");
9176 add_p(splci, ESC, "\x02\x18\x00");
9177 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9178 splci->internal_command = PERM_COD_ASSIGN;
9179 dbug(1, dprintf("Codec Assign"));
9180 sig_req(splci, ASSIGN, DSIG_ID);
9181 send_req(splci);
9183 else
9185 return 0x2001; /* wrong state, no more plcis */
9188 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9190 if (hook_listen) return 0x300B; /* Facility not supported */
9191 /* no hook with SCOM */
9192 if (plci != NULL) plci->tel = CODEC;
9193 dbug(1, dprintf("S/SCOM codec"));
9194 /* first time we use the scom-s codec we must shut down the internal */
9195 /* handset application of the card. This can be done by an assign with */
9196 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9197 if (!a->scom_appl_disable) {
9198 if ((j = get_plci(a))) {
9199 splci = &a->plci[j - 1];
9200 add_p(splci, CAI, "\x01\x80");
9201 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9202 sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9203 send_req(splci);
9204 a->scom_appl_disable = true;
9206 else{
9207 return 0x2001; /* wrong state, no more plcis */
9211 else return 0x300B; /* Facility not supported */
9213 return 0;
9217 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220 dbug(1, dprintf("CodecIdCheck"));
9222 if (a->AdvSignalPLCI == plci)
9224 dbug(1, dprintf("PLCI owns codec"));
9225 VoiceChannelOff(a->AdvCodecPLCI);
9226 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9228 dbug(1, dprintf("remove temp codec PLCI"));
9229 plci_remove(a->AdvCodecPLCI);
9230 a->AdvCodecFLAG = 0;
9231 a->AdvCodecPLCI = NULL;
9232 a->AdvSignalAppl = NULL;
9234 a->AdvSignalPLCI = NULL;
9238 /* -------------------------------------------------------------------
9239 Ask for physical address of card on PCI bus
9240 ------------------------------------------------------------------- */
9241 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9242 IDI_SYNC_REQ *preq) {
9243 a->sdram_bar = 0;
9244 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9245 ENTITY *e = (ENTITY *)preq;
9247 e->user[0] = a->Id - 1;
9248 preq->xdi_sdram_bar.info.bar = 0;
9249 preq->xdi_sdram_bar.Req = 0;
9250 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9252 (*(a->request))(e);
9254 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9255 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9259 /* -------------------------------------------------------------------
9260 Ask XDI about extended features
9261 ------------------------------------------------------------------- */
9262 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9263 IDI_SYNC_REQ *preq;
9264 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9266 char features[4];
9267 preq = (IDI_SYNC_REQ *)&buffer[0];
9269 if (!diva_xdi_extended_features) {
9270 ENTITY *e = (ENTITY *)preq;
9271 diva_xdi_extended_features |= 0x80000000;
9273 e->user[0] = a->Id - 1;
9274 preq->xdi_extended_features.Req = 0;
9275 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9276 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9277 preq->xdi_extended_features.info.features = &features[0];
9279 (*(a->request))(e);
9281 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9283 Check features located in the byte '0'
9285 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9286 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9288 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9289 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9290 dbug(1, dprintf("XDI provides RxDMA"));
9292 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9293 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9295 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9296 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9297 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9303 diva_ask_for_xdi_sdram_bar(a, preq);
9306 /*------------------------------------------------------------------*/
9307 /* automatic law */
9308 /*------------------------------------------------------------------*/
9309 /* called from OS specific part after init time to get the Law */
9310 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9311 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9313 word j;
9314 PLCI *splci;
9316 if (a->automatic_law) {
9317 return;
9319 if ((j = get_plci(a))) {
9320 diva_get_extended_adapter_features(a);
9321 splci = &a->plci[j - 1];
9322 a->automatic_lawPLCI = splci;
9323 a->automatic_law = 1;
9324 add_p(splci, CAI, "\x01\x80");
9325 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9326 splci->internal_command = USELAW_REQ;
9327 splci->command = 0;
9328 splci->number = 0;
9329 sig_req(splci, ASSIGN, DSIG_ID);
9330 send_req(splci);
9334 /* called from OS specific part if an application sends an Capi20Release */
9335 word CapiRelease(word Id)
9337 word i, j, appls_found;
9338 PLCI *plci;
9339 APPL *this;
9340 DIVA_CAPI_ADAPTER *a;
9342 if (!Id)
9344 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9345 return (_WRONG_APPL_ID);
9348 this = &application[Id - 1]; /* get application pointer */
9350 for (i = 0, appls_found = 0; i < max_appl; i++)
9352 if (application[i].Id) /* an application has been found */
9354 appls_found++;
9358 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9360 a = &adapter[i];
9361 if (a->request)
9363 a->Info_Mask[Id - 1] = 0;
9364 a->CIP_Mask[Id - 1] = 0;
9365 a->Notification_Mask[Id - 1] = 0;
9366 a->codec_listen[Id - 1] = NULL;
9367 a->requested_options_table[Id - 1] = 0;
9368 for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9369 { /* with this application */
9370 plci = &a->plci[j];
9371 if (plci->Id) /* if plci owns no application */
9372 { /* it may be not jet connected */
9373 if (plci->State == INC_CON_PENDING
9374 || plci->State == INC_CON_ALERT)
9376 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9378 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9379 if (c_ind_mask_empty(plci))
9381 sig_req(plci, HANGUP, 0);
9382 send_req(plci);
9383 plci->State = OUTG_DIS_PENDING;
9387 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9389 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9390 if (c_ind_mask_empty(plci))
9392 if (!plci->appl)
9394 plci_remove(plci);
9395 plci->State = IDLE;
9399 if (plci->appl == this)
9401 plci->appl = NULL;
9402 plci_remove(plci);
9403 plci->State = IDLE;
9407 listen_check(a);
9409 if (a->flag_dynamic_l1_down)
9411 if (appls_found == 1) /* last application does a capi release */
9413 if ((j = get_plci(a)))
9415 plci = &a->plci[j - 1];
9416 plci->command = 0;
9417 add_p(plci, OAD, "\x01\xfd");
9418 add_p(plci, CAI, "\x01\x80");
9419 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9420 add_p(plci, SHIFT | 6, NULL);
9421 add_p(plci, SIN, "\x02\x00\x00");
9422 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9423 sig_req(plci, ASSIGN, DSIG_ID);
9424 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9425 sig_req(plci, SIG_CTRL, 0);
9426 send_req(plci);
9430 if (a->AdvSignalAppl == this)
9432 this->NullCREnable = false;
9433 if (a->AdvCodecPLCI)
9435 plci_remove(a->AdvCodecPLCI);
9436 a->AdvCodecPLCI->tel = 0;
9437 a->AdvCodecPLCI->adv_nl = 0;
9439 a->AdvSignalAppl = NULL;
9440 a->AdvSignalPLCI = NULL;
9441 a->AdvCodecFLAG = 0;
9442 a->AdvCodecPLCI = NULL;
9447 this->Id = 0;
9449 return GOOD;
9452 static word plci_remove_check(PLCI *plci)
9454 if (!plci) return true;
9455 if (!plci->NL.Id && c_ind_mask_empty(plci))
9457 if (plci->Sig.Id == 0xff)
9458 plci->Sig.Id = 0;
9459 if (!plci->Sig.Id)
9461 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9462 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9463 if (plci->Id)
9465 CodecIdCheck(plci->adapter, plci);
9466 clear_b1_config(plci);
9467 ncci_remove(plci, 0, false);
9468 plci_free_msg_in_queue(plci);
9469 channel_flow_control_remove(plci);
9470 plci->Id = 0;
9471 plci->State = IDLE;
9472 plci->channels = 0;
9473 plci->appl = NULL;
9474 plci->notifiedcall = 0;
9476 listen_check(plci->adapter);
9477 return true;
9480 return false;
9484 /*------------------------------------------------------------------*/
9486 static byte plci_nl_busy(PLCI *plci)
9488 /* only applicable for non-multiplexed protocols */
9489 return (plci->nl_req
9490 || (plci->ncci_ring_list
9491 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9492 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9496 /*------------------------------------------------------------------*/
9497 /* DTMF facilities */
9498 /*------------------------------------------------------------------*/
9501 static struct
9503 byte send_mask;
9504 byte listen_mask;
9505 byte character;
9506 byte code;
9507 } dtmf_digit_map[] =
9509 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9510 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9511 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9512 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9513 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9514 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9515 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9516 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9517 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9518 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9519 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9520 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9521 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9522 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9523 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9524 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9525 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9526 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9527 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9528 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9530 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9531 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9532 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9533 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9534 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9535 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9536 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9537 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9538 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9539 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9540 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9541 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9542 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9543 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9544 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9545 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9546 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9547 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9548 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9549 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9550 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9551 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9552 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9553 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9554 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9555 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9556 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9557 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9558 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9559 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9560 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9561 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9562 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9563 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9564 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9565 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9566 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9567 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9568 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9569 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9570 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9571 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9572 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9573 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9574 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9575 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9576 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9577 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9578 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9579 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9580 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9581 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9585 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9590 word min_digit_duration, min_gap_duration;
9592 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9593 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9594 (char *)(FILE_), __LINE__, enable_mask));
9596 if (enable_mask != 0)
9598 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9599 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9600 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9601 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9602 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9603 plci->NData[0].PLength = 5;
9605 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9606 plci->NData[0].PLength += 2;
9607 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9610 else
9612 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9613 plci->NData[0].PLength = 1;
9615 capidtmf_recv_disable(&(plci->capidtmf_state));
9618 plci->NData[0].P = plci->internal_req_buffer;
9619 plci->NL.X = plci->NData;
9620 plci->NL.ReqCh = 0;
9621 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9622 plci->adapter->request(&plci->NL);
9626 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9628 word w, i;
9630 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9631 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9632 (char *)(FILE_), __LINE__, digit_count));
9634 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9635 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9636 PUT_WORD(&plci->internal_req_buffer[1], w);
9637 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9638 PUT_WORD(&plci->internal_req_buffer[3], w);
9639 for (i = 0; i < digit_count; i++)
9641 w = 0;
9642 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9643 && (digit_buffer[i] != dtmf_digit_map[w].character))
9645 w++;
9647 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9648 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9650 plci->NData[0].PLength = 5 + digit_count;
9651 plci->NData[0].P = plci->internal_req_buffer;
9652 plci->NL.X = plci->NData;
9653 plci->NL.ReqCh = 0;
9654 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9655 plci->adapter->request(&plci->NL);
9659 static void dtmf_rec_clear_config(PLCI *plci)
9662 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9663 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9664 (char *)(FILE_), __LINE__));
9666 plci->dtmf_rec_active = 0;
9667 plci->dtmf_rec_pulse_ms = 0;
9668 plci->dtmf_rec_pause_ms = 0;
9670 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9675 static void dtmf_send_clear_config(PLCI *plci)
9678 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9679 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9680 (char *)(FILE_), __LINE__));
9682 plci->dtmf_send_requests = 0;
9683 plci->dtmf_send_pulse_ms = 0;
9684 plci->dtmf_send_pause_ms = 0;
9688 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9692 UnMapId(Id), (char *)(FILE_), __LINE__));
9694 while (plci->dtmf_send_requests != 0)
9695 dtmf_confirmation(Id, plci);
9699 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9703 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9705 return (GOOD);
9709 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9711 word Info;
9713 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9714 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9716 Info = GOOD;
9717 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9719 switch (plci->adjust_b_state)
9721 case ADJUST_B_RESTORE_DTMF_1:
9722 plci->internal_command = plci->adjust_b_command;
9723 if (plci_nl_busy(plci))
9725 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9726 break;
9728 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9729 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9730 break;
9731 case ADJUST_B_RESTORE_DTMF_2:
9732 if ((Rc != OK) && (Rc != OK_FC))
9734 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9735 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9736 Info = _WRONG_STATE;
9737 break;
9739 break;
9742 return (Info);
9746 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9748 word internal_command, Info;
9749 byte mask;
9750 byte result[4];
9752 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9753 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9754 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9755 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9757 Info = GOOD;
9758 result[0] = 2;
9759 PUT_WORD(&result[1], DTMF_SUCCESS);
9760 internal_command = plci->internal_command;
9761 plci->internal_command = 0;
9762 mask = 0x01;
9763 switch (plci->dtmf_cmd)
9766 case DTMF_LISTEN_TONE_START:
9767 mask <<= 1;
9768 case DTMF_LISTEN_MF_START:
9769 mask <<= 1;
9771 case DTMF_LISTEN_START:
9772 switch (internal_command)
9774 default:
9775 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9776 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9777 case DTMF_COMMAND_1:
9778 if (adjust_b_process(Id, plci, Rc) != GOOD)
9780 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9781 UnMapId(Id), (char *)(FILE_), __LINE__));
9782 Info = _FACILITY_NOT_SUPPORTED;
9783 break;
9785 if (plci->internal_command)
9786 return;
9787 case DTMF_COMMAND_2:
9788 if (plci_nl_busy(plci))
9790 plci->internal_command = DTMF_COMMAND_2;
9791 return;
9793 plci->internal_command = DTMF_COMMAND_3;
9794 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9795 return;
9796 case DTMF_COMMAND_3:
9797 if ((Rc != OK) && (Rc != OK_FC))
9799 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9800 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9801 Info = _FACILITY_NOT_SUPPORTED;
9802 break;
9805 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9807 plci->dtmf_rec_active |= mask;
9808 break;
9810 break;
9813 case DTMF_LISTEN_TONE_STOP:
9814 mask <<= 1;
9815 case DTMF_LISTEN_MF_STOP:
9816 mask <<= 1;
9818 case DTMF_LISTEN_STOP:
9819 switch (internal_command)
9821 default:
9822 plci->dtmf_rec_active &= ~mask;
9823 if (plci->dtmf_rec_active)
9824 break;
9826 case DTMF_COMMAND_1:
9827 if (plci->dtmf_rec_active)
9829 if (plci_nl_busy (plci))
9831 plci->internal_command = DTMF_COMMAND_1;
9832 return;
9834 plci->dtmf_rec_active &= ~mask;
9835 plci->internal_command = DTMF_COMMAND_2;
9836 dtmf_enable_receiver (plci, false);
9837 return;
9839 Rc = OK;
9840 case DTMF_COMMAND_2:
9841 if ((Rc != OK) && (Rc != OK_FC))
9843 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9844 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9845 Info = _FACILITY_NOT_SUPPORTED;
9846 break;
9849 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9850 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9851 case DTMF_COMMAND_3:
9852 if (adjust_b_process(Id, plci, Rc) != GOOD)
9854 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9855 UnMapId(Id), (char *)(FILE_), __LINE__));
9856 Info = _FACILITY_NOT_SUPPORTED;
9857 break;
9859 if (plci->internal_command)
9860 return;
9861 break;
9863 break;
9866 case DTMF_SEND_TONE:
9867 mask <<= 1;
9868 case DTMF_SEND_MF:
9869 mask <<= 1;
9871 case DTMF_DIGITS_SEND:
9872 switch (internal_command)
9874 default:
9875 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9876 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9877 DTMF_COMMAND_1);
9878 case DTMF_COMMAND_1:
9879 if (adjust_b_process(Id, plci, Rc) != GOOD)
9881 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9882 UnMapId(Id), (char *)(FILE_), __LINE__));
9883 Info = _FACILITY_NOT_SUPPORTED;
9884 break;
9886 if (plci->internal_command)
9887 return;
9888 case DTMF_COMMAND_2:
9889 if (plci_nl_busy(plci))
9891 plci->internal_command = DTMF_COMMAND_2;
9892 return;
9894 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9895 plci->internal_command = DTMF_COMMAND_3;
9896 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9897 return;
9898 case DTMF_COMMAND_3:
9899 if ((Rc != OK) && (Rc != OK_FC))
9901 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9902 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9903 if (plci->dtmf_send_requests != 0)
9904 (plci->dtmf_send_requests)--;
9905 Info = _FACILITY_NOT_SUPPORTED;
9906 break;
9908 return;
9910 break;
9912 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9913 "wws", Info, SELECTOR_DTMF, result);
9917 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9919 word Info;
9920 word i, j;
9921 byte mask;
9922 API_PARSE dtmf_parms[5];
9923 byte result[40];
9925 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9926 UnMapId(Id), (char *)(FILE_), __LINE__));
9928 Info = GOOD;
9929 result[0] = 2;
9930 PUT_WORD(&result[1], DTMF_SUCCESS);
9931 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9933 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9934 UnMapId(Id), (char *)(FILE_), __LINE__));
9935 Info = _FACILITY_NOT_SUPPORTED;
9937 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9939 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9940 UnMapId(Id), (char *)(FILE_), __LINE__));
9941 Info = _WRONG_MESSAGE_FORMAT;
9944 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9945 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9947 if (!((a->requested_options_table[appl->Id - 1])
9948 & (1L << PRIVATE_DTMF_TONE)))
9950 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9951 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9952 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9954 else
9956 for (i = 0; i < 32; i++)
9957 result[4 + i] = 0;
9958 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9960 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9962 if (dtmf_digit_map[i].listen_mask != 0)
9963 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966 else
9968 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9970 if (dtmf_digit_map[i].send_mask != 0)
9971 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9974 result[0] = 3 + 32;
9975 result[3] = 32;
9979 else if (plci == NULL)
9981 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9982 UnMapId(Id), (char *)(FILE_), __LINE__));
9983 Info = _WRONG_IDENTIFIER;
9985 else
9987 if (!plci->State
9988 || !plci->NL.Id || plci->nl_remove_id)
9990 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9991 UnMapId(Id), (char *)(FILE_), __LINE__));
9992 Info = _WRONG_STATE;
9994 else
9996 plci->command = 0;
9997 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9998 mask = 0x01;
9999 switch (plci->dtmf_cmd)
10002 case DTMF_LISTEN_TONE_START:
10003 case DTMF_LISTEN_TONE_STOP:
10004 mask <<= 1;
10005 case DTMF_LISTEN_MF_START:
10006 case DTMF_LISTEN_MF_STOP:
10007 mask <<= 1;
10008 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10009 & (1L << PRIVATE_DTMF_TONE)))
10011 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10012 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10013 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10014 break;
10017 case DTMF_LISTEN_START:
10018 case DTMF_LISTEN_STOP:
10019 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10020 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10022 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10023 UnMapId(Id), (char *)(FILE_), __LINE__));
10024 Info = _FACILITY_NOT_SUPPORTED;
10025 break;
10027 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10029 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10031 plci->dtmf_rec_pulse_ms = 0;
10032 plci->dtmf_rec_pause_ms = 0;
10034 else
10036 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10037 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040 start_internal_command(Id, plci, dtmf_command);
10041 return (false);
10044 case DTMF_SEND_TONE:
10045 mask <<= 1;
10046 case DTMF_SEND_MF:
10047 mask <<= 1;
10048 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10049 & (1L << PRIVATE_DTMF_TONE)))
10051 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10052 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10053 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10054 break;
10057 case DTMF_DIGITS_SEND:
10058 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10060 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10061 UnMapId(Id), (char *)(FILE_), __LINE__));
10062 Info = _WRONG_MESSAGE_FORMAT;
10063 break;
10065 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10067 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10068 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10070 i = 0;
10071 j = 0;
10072 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10074 j = 0;
10075 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10076 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10077 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10079 j++;
10081 i++;
10083 if (j == DTMF_DIGIT_MAP_ENTRIES)
10085 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10086 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10087 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10088 break;
10090 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10092 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10093 UnMapId(Id), (char *)(FILE_), __LINE__));
10094 Info = _WRONG_STATE;
10095 break;
10097 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10098 start_internal_command(Id, plci, dtmf_command);
10099 return (false);
10101 default:
10102 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10103 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10104 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10108 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10109 "wws", Info, SELECTOR_DTMF, result);
10110 return (false);
10114 static void dtmf_confirmation(dword Id, PLCI *plci)
10116 word i;
10117 byte result[4];
10119 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10120 UnMapId(Id), (char *)(FILE_), __LINE__));
10122 result[0] = 2;
10123 PUT_WORD(&result[1], DTMF_SUCCESS);
10124 if (plci->dtmf_send_requests != 0)
10126 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10127 "wws", GOOD, SELECTOR_DTMF, result);
10128 (plci->dtmf_send_requests)--;
10129 for (i = 0; i < plci->dtmf_send_requests; i++)
10130 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10135 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10137 word i, j, n;
10139 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10140 UnMapId(Id), (char *)(FILE_), __LINE__));
10142 n = 0;
10143 for (i = 1; i < length; i++)
10145 j = 0;
10146 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10147 && ((msg[i] != dtmf_digit_map[j].code)
10148 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10150 j++;
10152 if (j < DTMF_DIGIT_MAP_ENTRIES)
10155 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10156 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10157 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10159 if (n + 1 == i)
10161 for (i = length; i > n + 1; i--)
10162 msg[i] = msg[i - 1];
10163 length++;
10164 i++;
10166 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10168 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10170 msg[++n] = dtmf_digit_map[j].character;
10173 if (n != 0)
10175 msg[0] = (byte) n;
10176 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10181 /*------------------------------------------------------------------*/
10182 /* DTMF parameters */
10183 /*------------------------------------------------------------------*/
10185 static void dtmf_parameter_write(PLCI *plci)
10187 word i;
10188 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10190 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10191 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10192 (char *)(FILE_), __LINE__));
10194 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10195 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10196 for (i = 0; i < plci->dtmf_parameter_length; i++)
10197 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10198 add_p(plci, FTY, parameter_buffer);
10199 sig_req(plci, TEL_CTRL, 0);
10200 send_req(plci);
10204 static void dtmf_parameter_clear_config(PLCI *plci)
10207 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10208 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10209 (char *)(FILE_), __LINE__));
10211 plci->dtmf_parameter_length = 0;
10215 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10219 UnMapId(Id), (char *)(FILE_), __LINE__));
10224 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10228 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10230 return (GOOD);
10234 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10236 word Info;
10238 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10239 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10241 Info = GOOD;
10242 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10243 && (plci->dtmf_parameter_length != 0))
10245 switch (plci->adjust_b_state)
10247 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10248 plci->internal_command = plci->adjust_b_command;
10249 if (plci->sig_req)
10251 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10252 break;
10254 dtmf_parameter_write(plci);
10255 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10256 break;
10257 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10258 if ((Rc != OK) && (Rc != OK_FC))
10260 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10261 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10262 Info = _WRONG_STATE;
10263 break;
10265 break;
10268 return (Info);
10272 /*------------------------------------------------------------------*/
10273 /* Line interconnect facilities */
10274 /*------------------------------------------------------------------*/
10277 LI_CONFIG *li_config_table;
10278 word li_total_channels;
10281 /*------------------------------------------------------------------*/
10282 /* translate a CHI information element to a channel number */
10283 /* returns 0xff - any channel */
10284 /* 0xfe - chi wrong coding */
10285 /* 0xfd - D-channel */
10286 /* 0x00 - no channel */
10287 /* else channel number / PRI: timeslot */
10288 /* if channels is provided we accept more than one channel. */
10289 /*------------------------------------------------------------------*/
10291 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10293 int p;
10294 int i;
10295 dword map;
10296 byte excl;
10297 byte ofs;
10298 byte ch;
10300 if (pchannelmap) *pchannelmap = 0;
10301 if (!chi[0]) return 0xff;
10302 excl = 0;
10304 if (chi[1] & 0x20) {
10305 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10306 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10307 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10308 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10309 if (chi[1] & 0x08) excl = 0x40;
10311 /* int. id present */
10312 if (chi[1] & 0x40) {
10313 p = i + 1;
10314 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10315 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318 /* coding standard, Number/Map, Channel Type */
10319 p = i + 1;
10320 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10321 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10322 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10324 /* Number/Map */
10325 if (chi[p] & 0x10) {
10327 /* map */
10328 if ((chi[0] - p) == 4) ofs = 0;
10329 else if ((chi[0] - p) == 3) ofs = 1;
10330 else return 0xfe;
10331 ch = 0;
10332 map = 0;
10333 for (i = 0; i < 4 && p < chi[0]; i++) {
10334 p++;
10335 ch += 8;
10336 map <<= 8;
10337 if (chi[p]) {
10338 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10339 map |= chi[p];
10342 ch += ofs;
10343 map <<= ofs;
10345 else {
10347 /* number */
10348 p = i + 1;
10349 ch = chi[p] & 0x3f;
10350 if (pchannelmap) {
10351 if ((byte)(chi[0] - p) > 30) return 0xfe;
10352 map = 0;
10353 for (i = p; i <= chi[0]; i++) {
10354 if ((chi[i] & 0x7f) > 31) return 0xfe;
10355 map |= (1L << (chi[i] & 0x7f));
10358 else {
10359 if (p != chi[0]) return 0xfe;
10360 if (ch > 31) return 0xfe;
10361 map = (1L << ch);
10363 if (chi[p] & 0x40) return 0xfe;
10365 if (pchannelmap) *pchannelmap = map;
10366 else if (map != ((dword)(1L << ch))) return 0xfe;
10367 return (byte)(excl | ch);
10369 else { /* not PRI */
10370 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10371 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10372 if (chi[1] & 0x08) excl = 0x40;
10374 switch (chi[1] | 0x98) {
10375 case 0x98: return 0;
10376 case 0x99:
10377 if (pchannelmap) *pchannelmap = 2;
10378 return excl | 1;
10379 case 0x9a:
10380 if (pchannelmap) *pchannelmap = 4;
10381 return excl | 2;
10382 case 0x9b: return 0xff;
10383 case 0x9c: return 0xfd; /* d-ch */
10384 default: return 0xfe;
10390 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10392 DIVA_CAPI_ADAPTER *a;
10393 PLCI *splci;
10394 byte old_id;
10396 a = plci->adapter;
10397 old_id = plci->li_bchannel_id;
10398 if (a->li_pri)
10400 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10401 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10402 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10403 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10404 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10406 else
10408 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10410 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10411 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10412 plci->li_bchannel_id = bchannel_id & 0x03;
10413 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10415 splci = a->AdvSignalPLCI;
10416 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10418 if ((splci->li_bchannel_id != 0)
10419 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10421 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10423 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10424 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10425 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10426 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10427 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10431 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10435 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10437 mixer_clear_config(plci);
10439 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10440 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10441 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10445 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10447 DIVA_CAPI_ADAPTER *a;
10448 PLCI *splci;
10449 byte ch, old_id;
10451 a = plci->adapter;
10452 old_id = plci->li_bchannel_id;
10453 ch = chi_to_channel(chi, NULL);
10454 if (!(ch & 0x80))
10456 if (a->li_pri)
10458 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10459 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10460 plci->li_bchannel_id = (ch & 0x1f) + 1;
10461 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10462 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10464 else
10466 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10468 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10469 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10470 plci->li_bchannel_id = ch & 0x1f;
10471 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10473 splci = a->AdvSignalPLCI;
10474 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10476 if ((splci->li_bchannel_id != 0)
10477 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10479 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10481 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10482 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10483 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10484 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10485 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10489 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10493 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10494 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10496 mixer_clear_config(plci);
10498 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10499 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10500 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10504 #define MIXER_MAX_DUMP_CHANNELS 34
10506 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10508 word n, i, j;
10509 char *p;
10510 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10512 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10513 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10515 for (i = 0; i < li_total_channels; i++)
10517 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10518 if (li_config_table[i].chflags != 0)
10519 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10520 else
10522 for (j = 0; j < li_total_channels; j++)
10524 if (((li_config_table[i].flag_table[j]) != 0)
10525 || ((li_config_table[j].flag_table[i]) != 0))
10527 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10529 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10530 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10532 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10537 for (i = 0; i < li_total_channels; i++)
10539 for (j = 0; j < li_total_channels; j++)
10541 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10542 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10543 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10546 for (n = 0; n < li_total_channels; n++)
10548 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10550 for (i = 0; i < li_total_channels; i++)
10552 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10554 for (j = 0; j < li_total_channels; j++)
10556 li_config_table[i].coef_table[j] |=
10557 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10563 for (i = 0; i < li_total_channels; i++)
10565 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10567 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10568 for (j = 0; j < li_total_channels; j++)
10570 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10571 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10573 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10574 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10577 for (i = 0; i < li_total_channels; i++)
10579 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10581 for (j = 0; j < li_total_channels; j++)
10583 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10584 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10585 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10586 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10587 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10588 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10589 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10590 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10592 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10594 for (j = 0; j < li_total_channels; j++)
10596 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10598 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10599 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10600 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10606 for (j = 0; j < li_total_channels; j++)
10608 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10609 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10612 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10614 for (j = 0; j < li_total_channels; j++)
10616 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10618 for (n = 0; n < li_total_channels; n++)
10620 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10622 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10623 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10625 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10626 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10627 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10629 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10638 for (i = 0; i < li_total_channels; i++)
10640 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10642 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10643 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10644 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10645 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10646 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10647 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10648 for (j = 0; j < li_total_channels; j++)
10650 if ((li_config_table[i].flag_table[j] &
10651 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10652 || (li_config_table[j].flag_table[i] &
10653 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10655 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10657 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10658 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10659 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10660 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10662 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10664 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10665 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669 for (i = 0; i < li_total_channels; i++)
10671 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10673 j = 0;
10674 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10675 j++;
10676 if (j < li_total_channels)
10678 for (j = 0; j < li_total_channels; j++)
10680 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10681 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10682 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10687 n = li_total_channels;
10688 if (n > MIXER_MAX_DUMP_CHANNELS)
10689 n = MIXER_MAX_DUMP_CHANNELS;
10691 p = hex_line;
10692 for (j = 0; j < n; j++)
10694 if ((j & 0x7) == 0)
10695 *(p++) = ' ';
10696 p = hex_byte_pack(p, li_config_table[j].curchnl);
10698 *p = '\0';
10699 dbug(1, dprintf("[%06lx] CURRENT %s",
10700 (dword)(UnMapController(a->Id)), (char *)hex_line));
10701 p = hex_line;
10702 for (j = 0; j < n; j++)
10704 if ((j & 0x7) == 0)
10705 *(p++) = ' ';
10706 p = hex_byte_pack(p, li_config_table[j].channel);
10708 *p = '\0';
10709 dbug(1, dprintf("[%06lx] CHANNEL %s",
10710 (dword)(UnMapController(a->Id)), (char *)hex_line));
10711 p = hex_line;
10712 for (j = 0; j < n; j++)
10714 if ((j & 0x7) == 0)
10715 *(p++) = ' ';
10716 p = hex_byte_pack(p, li_config_table[j].chflags);
10718 *p = '\0';
10719 dbug(1, dprintf("[%06lx] CHFLAG %s",
10720 (dword)(UnMapController(a->Id)), (char *)hex_line));
10721 for (i = 0; i < n; i++)
10723 p = hex_line;
10724 for (j = 0; j < n; j++)
10726 if ((j & 0x7) == 0)
10727 *(p++) = ' ';
10728 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10730 *p = '\0';
10731 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10732 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10734 for (i = 0; i < n; i++)
10736 p = hex_line;
10737 for (j = 0; j < n; j++)
10739 if ((j & 0x7) == 0)
10740 *(p++) = ' ';
10741 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10743 *p = '\0';
10744 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10745 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10750 static struct
10752 byte mask;
10753 byte line_flags;
10754 } mixer_write_prog_pri[] =
10756 { LI_COEF_CH_CH, 0 },
10757 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10758 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10759 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10762 static struct
10764 byte from_ch;
10765 byte to_ch;
10766 byte mask;
10767 byte xconnect_override;
10768 } mixer_write_prog_bri[] =
10770 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10771 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10772 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10773 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10774 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10775 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10776 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10777 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10778 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10779 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10780 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10781 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10782 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10783 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10784 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10785 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10786 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10787 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10788 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10789 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10790 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10791 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10792 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10793 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10794 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10795 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10796 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10797 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10798 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10799 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10800 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10801 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10802 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10803 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10804 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10805 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10808 static byte mixer_swapped_index_bri[] =
10810 18, /* B to B */
10811 19, /* Alt B to B */
10812 20, /* PC to B */
10813 21, /* Alt PC to B */
10814 22, /* IC to B */
10815 23, /* Alt IC to B */
10816 24, /* B to PC */
10817 25, /* Alt B to PC */
10818 26, /* PC to PC */
10819 27, /* Alt PC to PC */
10820 28, /* IC to PC */
10821 29, /* Alt IC to PC */
10822 30, /* B to IC */
10823 31, /* Alt B to IC */
10824 32, /* PC to IC */
10825 33, /* Alt PC to IC */
10826 34, /* IC to IC */
10827 35, /* Alt IC to IC */
10828 0, /* Alt B to Alt B */
10829 1, /* B to Alt B */
10830 2, /* Alt PC to Alt B */
10831 3, /* PC to Alt B */
10832 4, /* Alt IC to Alt B */
10833 5, /* IC to Alt B */
10834 6, /* Alt B to Alt PC */
10835 7, /* B to Alt PC */
10836 8, /* Alt PC to Alt PC */
10837 9, /* PC to Alt PC */
10838 10, /* Alt IC to Alt PC */
10839 11, /* IC to Alt PC */
10840 12, /* Alt B to Alt IC */
10841 13, /* B to Alt IC */
10842 14, /* Alt PC to Alt IC */
10843 15, /* PC to Alt IC */
10844 16, /* Alt IC to Alt IC */
10845 17 /* IC to Alt IC */
10848 static struct
10850 byte mask;
10851 byte from_pc;
10852 byte to_pc;
10853 } xconnect_write_prog[] =
10855 { LI_COEF_CH_CH, false, false },
10856 { LI_COEF_CH_PC, false, true },
10857 { LI_COEF_PC_CH, true, false },
10858 { LI_COEF_PC_PC, true, true }
10862 static void xconnect_query_addresses(PLCI *plci)
10864 DIVA_CAPI_ADAPTER *a;
10865 word w, ch;
10866 byte *p;
10868 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10869 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10870 (char *)(FILE_), __LINE__));
10872 a = plci->adapter;
10873 if (a->li_pri && ((plci->li_bchannel_id == 0)
10874 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10876 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10877 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10878 (char *)(FILE_), __LINE__));
10879 return;
10881 p = plci->internal_req_buffer;
10882 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10883 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10884 w = ch;
10885 *(p++) = (byte) w;
10886 *(p++) = (byte)(w >> 8);
10887 w = ch | XCONNECT_CHANNEL_PORT_PC;
10888 *(p++) = (byte) w;
10889 *(p++) = (byte)(w >> 8);
10890 plci->NData[0].P = plci->internal_req_buffer;
10891 plci->NData[0].PLength = p - plci->internal_req_buffer;
10892 plci->NL.X = plci->NData;
10893 plci->NL.ReqCh = 0;
10894 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10895 plci->adapter->request(&plci->NL);
10899 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10902 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10903 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10904 (char *)(FILE_), __LINE__, internal_command));
10906 plci->li_write_command = internal_command;
10907 plci->li_write_channel = 0;
10911 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10913 DIVA_CAPI_ADAPTER *a;
10914 word w, n, i, j, r, s, to_ch;
10915 dword d;
10916 byte *p;
10917 struct xconnect_transfer_address_s *transfer_address;
10918 byte ch_map[MIXER_CHANNELS_BRI];
10920 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10921 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10923 a = plci->adapter;
10924 if ((plci->li_bchannel_id == 0)
10925 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10927 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10928 UnMapId(Id), (char *)(FILE_), __LINE__));
10929 return (true);
10931 i = a->li_base + (plci->li_bchannel_id - 1);
10932 j = plci->li_write_channel;
10933 p = plci->internal_req_buffer;
10934 if (j != 0)
10936 if ((Rc != OK) && (Rc != OK_FC))
10938 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10939 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10940 return (false);
10943 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10945 r = 0;
10946 s = 0;
10947 if (j < li_total_channels)
10949 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10951 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10952 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10953 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10954 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10956 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10957 while ((j < li_total_channels)
10958 && ((r == 0)
10959 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10960 || (!li_config_table[j].adapter->li_pri
10961 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10962 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10963 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10964 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10965 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10966 || ((li_config_table[j].adapter->li_base != a->li_base)
10967 && !(r & s &
10968 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10969 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10970 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10971 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10973 j++;
10974 if (j < li_total_channels)
10975 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10978 if (j < li_total_channels)
10980 plci->internal_command = plci->li_write_command;
10981 if (plci_nl_busy(plci))
10982 return (true);
10983 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10984 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10987 if (li_config_table[j].adapter->li_base != a->li_base)
10989 r &= s &
10990 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10991 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10992 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10993 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10995 n = 0;
10998 if (r & xconnect_write_prog[n].mask)
11000 if (xconnect_write_prog[n].from_pc)
11001 transfer_address = &(li_config_table[j].send_pc);
11002 else
11003 transfer_address = &(li_config_table[j].send_b);
11004 d = transfer_address->card_address.low;
11005 *(p++) = (byte) d;
11006 *(p++) = (byte)(d >> 8);
11007 *(p++) = (byte)(d >> 16);
11008 *(p++) = (byte)(d >> 24);
11009 d = transfer_address->card_address.high;
11010 *(p++) = (byte) d;
11011 *(p++) = (byte)(d >> 8);
11012 *(p++) = (byte)(d >> 16);
11013 *(p++) = (byte)(d >> 24);
11014 d = transfer_address->offset;
11015 *(p++) = (byte) d;
11016 *(p++) = (byte)(d >> 8);
11017 *(p++) = (byte)(d >> 16);
11018 *(p++) = (byte)(d >> 24);
11019 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11020 *(p++) = (byte) w;
11021 *(p++) = (byte)(w >> 8);
11022 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11023 (li_config_table[i].adapter->u_law ?
11024 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11025 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11026 *(p++) = (byte) w;
11027 *(p++) = (byte) 0;
11028 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11030 n++;
11031 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11032 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11033 if (n == ARRAY_SIZE(xconnect_write_prog))
11037 j++;
11038 if (j < li_total_channels)
11039 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11040 } while ((j < li_total_channels)
11041 && ((r == 0)
11042 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11043 || (!li_config_table[j].adapter->li_pri
11044 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11045 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11046 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11047 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11048 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11049 || ((li_config_table[j].adapter->li_base != a->li_base)
11050 && !(r & s &
11051 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11052 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11053 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11054 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11056 } while ((j < li_total_channels)
11057 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11059 else if (j == li_total_channels)
11061 plci->internal_command = plci->li_write_command;
11062 if (plci_nl_busy(plci))
11063 return (true);
11064 if (a->li_pri)
11066 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11067 w = 0;
11068 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11069 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11070 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11071 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11072 *(p++) = (byte) w;
11073 *(p++) = (byte)(w >> 8);
11075 else
11077 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11078 w = 0;
11079 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11080 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11082 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11084 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11085 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11086 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11087 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11088 *(p++) = (byte) w;
11089 *(p++) = (byte)(w >> 8);
11090 for (j = 0; j < sizeof(ch_map); j += 2)
11092 if (plci->li_bchannel_id == 2)
11094 ch_map[j] = (byte)(j + 1);
11095 ch_map[j + 1] = (byte) j;
11097 else
11099 ch_map[j] = (byte) j;
11100 ch_map[j + 1] = (byte)(j + 1);
11103 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11105 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11106 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11107 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11109 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11110 mixer_write_prog_bri[n].xconnect_override :
11111 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11112 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11114 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11115 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11118 else
11120 *p = 0x00;
11121 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11123 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11124 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11125 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11128 p++;
11131 j = li_total_channels + 1;
11134 else
11136 if (j <= li_total_channels)
11138 plci->internal_command = plci->li_write_command;
11139 if (plci_nl_busy(plci))
11140 return (true);
11141 if (j < a->li_base)
11142 j = a->li_base;
11143 if (a->li_pri)
11145 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11146 w = 0;
11147 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11148 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11149 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11150 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11151 *(p++) = (byte) w;
11152 *(p++) = (byte)(w >> 8);
11153 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11155 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11156 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11158 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11159 if (w & mixer_write_prog_pri[n].mask)
11161 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11164 else
11165 *(p++) = 0x00;
11167 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11168 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11170 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11171 if (w & mixer_write_prog_pri[n].mask)
11173 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11174 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11176 else
11177 *(p++) = 0x00;
11181 else
11183 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11184 w = 0;
11185 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11186 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11188 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11190 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11191 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11192 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11193 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11194 *(p++) = (byte) w;
11195 *(p++) = (byte)(w >> 8);
11196 for (j = 0; j < sizeof(ch_map); j += 2)
11198 if (plci->li_bchannel_id == 2)
11200 ch_map[j] = (byte)(j + 1);
11201 ch_map[j + 1] = (byte) j;
11203 else
11205 ch_map[j] = (byte) j;
11206 ch_map[j + 1] = (byte)(j + 1);
11209 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11211 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11212 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11213 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11215 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11216 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11217 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11219 else
11221 *p = 0x00;
11222 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11224 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11225 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11226 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11229 p++;
11232 j = li_total_channels + 1;
11235 plci->li_write_channel = j;
11236 if (p != plci->internal_req_buffer)
11238 plci->NData[0].P = plci->internal_req_buffer;
11239 plci->NData[0].PLength = p - plci->internal_req_buffer;
11240 plci->NL.X = plci->NData;
11241 plci->NL.ReqCh = 0;
11242 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11243 plci->adapter->request(&plci->NL);
11245 return (true);
11249 static void mixer_notify_update(PLCI *plci, byte others)
11251 DIVA_CAPI_ADAPTER *a;
11252 word i, w;
11253 PLCI *notify_plci;
11254 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11256 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11257 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11258 (char *)(FILE_), __LINE__, others));
11260 a = plci->adapter;
11261 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11263 if (others)
11264 plci->li_notify_update = true;
11265 i = 0;
11268 notify_plci = NULL;
11269 if (others)
11271 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11272 i++;
11273 if (i < li_total_channels)
11274 notify_plci = li_config_table[i++].plci;
11276 else
11278 if ((plci->li_bchannel_id != 0)
11279 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11281 notify_plci = plci;
11284 if ((notify_plci != NULL)
11285 && !notify_plci->li_notify_update
11286 && (notify_plci->appl != NULL)
11287 && (notify_plci->State)
11288 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11290 notify_plci->li_notify_update = true;
11291 ((CAPI_MSG *) msg)->header.length = 18;
11292 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11293 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11294 ((CAPI_MSG *) msg)->header.number = 0;
11295 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11296 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11297 ((CAPI_MSG *) msg)->header.ncci = 0;
11298 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11299 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11300 PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11301 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11302 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11303 if (w != _QUEUE_FULL)
11305 if (w != 0)
11307 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11308 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11309 (char *)(FILE_), __LINE__,
11310 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11312 notify_plci->li_notify_update = false;
11315 } while (others && (notify_plci != NULL));
11316 if (others)
11317 plci->li_notify_update = false;
11322 static void mixer_clear_config(PLCI *plci)
11324 DIVA_CAPI_ADAPTER *a;
11325 word i, j;
11327 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11328 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11329 (char *)(FILE_), __LINE__));
11331 plci->li_notify_update = false;
11332 plci->li_plci_b_write_pos = 0;
11333 plci->li_plci_b_read_pos = 0;
11334 plci->li_plci_b_req_pos = 0;
11335 a = plci->adapter;
11336 if ((plci->li_bchannel_id != 0)
11337 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11339 i = a->li_base + (plci->li_bchannel_id - 1);
11340 li_config_table[i].curchnl = 0;
11341 li_config_table[i].channel = 0;
11342 li_config_table[i].chflags = 0;
11343 for (j = 0; j < li_total_channels; j++)
11345 li_config_table[j].flag_table[i] = 0;
11346 li_config_table[i].flag_table[j] = 0;
11347 li_config_table[i].coef_table[j] = 0;
11348 li_config_table[j].coef_table[i] = 0;
11350 if (!a->li_pri)
11352 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11353 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11355 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11356 li_config_table[i].curchnl = 0;
11357 li_config_table[i].channel = 0;
11358 li_config_table[i].chflags = 0;
11359 for (j = 0; j < li_total_channels; j++)
11361 li_config_table[i].flag_table[j] = 0;
11362 li_config_table[j].flag_table[i] = 0;
11363 li_config_table[i].coef_table[j] = 0;
11364 li_config_table[j].coef_table[i] = 0;
11366 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11368 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11369 li_config_table[i].curchnl = 0;
11370 li_config_table[i].channel = 0;
11371 li_config_table[i].chflags = 0;
11372 for (j = 0; j < li_total_channels; j++)
11374 li_config_table[i].flag_table[j] = 0;
11375 li_config_table[j].flag_table[i] = 0;
11376 li_config_table[i].coef_table[j] = 0;
11377 li_config_table[j].coef_table[i] = 0;
11386 static void mixer_prepare_switch(dword Id, PLCI *plci)
11389 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11390 UnMapId(Id), (char *)(FILE_), __LINE__));
11394 mixer_indication_coefs_set(Id, plci);
11395 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11399 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11401 DIVA_CAPI_ADAPTER *a;
11402 word i, j;
11404 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11405 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11407 a = plci->adapter;
11408 if ((plci->li_bchannel_id != 0)
11409 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11411 i = a->li_base + (plci->li_bchannel_id - 1);
11412 for (j = 0; j < li_total_channels; j++)
11414 li_config_table[i].coef_table[j] &= 0xf;
11415 li_config_table[j].coef_table[i] &= 0xf;
11417 if (!a->li_pri)
11418 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11420 return (GOOD);
11424 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11426 DIVA_CAPI_ADAPTER *a;
11427 word Info;
11429 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11430 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11432 Info = GOOD;
11433 a = plci->adapter;
11434 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11435 && (plci->li_bchannel_id != 0)
11436 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11438 switch (plci->adjust_b_state)
11440 case ADJUST_B_RESTORE_MIXER_1:
11441 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11443 plci->internal_command = plci->adjust_b_command;
11444 if (plci_nl_busy(plci))
11446 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11447 break;
11449 xconnect_query_addresses(plci);
11450 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11451 break;
11453 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11454 Rc = OK;
11455 case ADJUST_B_RESTORE_MIXER_2:
11456 case ADJUST_B_RESTORE_MIXER_3:
11457 case ADJUST_B_RESTORE_MIXER_4:
11458 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11460 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11461 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11462 Info = _WRONG_STATE;
11463 break;
11465 if (Rc == OK)
11467 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11468 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11469 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11470 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11472 else if (Rc == 0)
11474 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11475 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11476 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11477 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11479 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11481 plci->internal_command = plci->adjust_b_command;
11482 break;
11484 case ADJUST_B_RESTORE_MIXER_5:
11485 xconnect_write_coefs(plci, plci->adjust_b_command);
11486 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11487 Rc = OK;
11488 case ADJUST_B_RESTORE_MIXER_6:
11489 if (!xconnect_write_coefs_process(Id, plci, Rc))
11491 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11492 UnMapId(Id), (char *)(FILE_), __LINE__));
11493 Info = _FACILITY_NOT_SUPPORTED;
11494 break;
11496 if (plci->internal_command)
11497 break;
11498 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11499 case ADJUST_B_RESTORE_MIXER_7:
11500 break;
11503 return (Info);
11507 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11509 DIVA_CAPI_ADAPTER *a;
11510 word i, internal_command;
11512 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11513 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11514 plci->li_cmd));
11516 a = plci->adapter;
11517 internal_command = plci->internal_command;
11518 plci->internal_command = 0;
11519 switch (plci->li_cmd)
11521 case LI_REQ_CONNECT:
11522 case LI_REQ_DISCONNECT:
11523 case LI_REQ_SILENT_UPDATE:
11524 switch (internal_command)
11526 default:
11527 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11529 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11530 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11532 case MIXER_COMMAND_1:
11533 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535 if (adjust_b_process(Id, plci, Rc) != GOOD)
11537 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11538 UnMapId(Id), (char *)(FILE_), __LINE__));
11539 break;
11541 if (plci->internal_command)
11542 return;
11544 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11545 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11546 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11547 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11548 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11550 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11552 else
11556 mixer_indication_coefs_set(Id, plci);
11557 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11559 case MIXER_COMMAND_2:
11560 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11561 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11562 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11563 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11565 if (!xconnect_write_coefs_process(Id, plci, Rc))
11567 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11568 UnMapId(Id), (char *)(FILE_), __LINE__));
11569 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11573 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11574 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11575 i = (plci->li_plci_b_write_pos == 0) ?
11576 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11577 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11578 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11580 break;
11582 if (plci->internal_command)
11583 return;
11585 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11587 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11588 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11590 case MIXER_COMMAND_3:
11591 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593 if (adjust_b_process(Id, plci, Rc) != GOOD)
11595 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11596 UnMapId(Id), (char *)(FILE_), __LINE__));
11597 break;
11599 if (plci->internal_command)
11600 return;
11602 break;
11604 break;
11606 if ((plci->li_bchannel_id == 0)
11607 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11609 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11610 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11612 else
11614 i = a->li_base + (plci->li_bchannel_id - 1);
11615 li_config_table[i].curchnl = plci->li_channel_bits;
11616 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11618 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11619 li_config_table[i].curchnl = plci->li_channel_bits;
11620 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11622 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11623 li_config_table[i].curchnl = plci->li_channel_bits;
11630 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11631 dword plci_b_id, byte connect, dword li_flags)
11633 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11634 PLCI *plci_b;
11635 DIVA_CAPI_ADAPTER *a_b;
11637 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11638 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11639 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11640 if (!a->li_pri && (plci->tel == ADV_VOICE)
11641 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11643 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11644 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11645 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11647 else
11649 ch_a_v = ch_a;
11650 ch_a_s = ch_a;
11652 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11653 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11654 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11656 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11657 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11658 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11660 else
11662 ch_b_v = ch_b;
11663 ch_b_s = ch_b;
11665 if (connect)
11667 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11668 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11669 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11672 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11673 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11674 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11675 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676 if (ch_a_v == ch_b_v)
11678 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11679 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11681 else
11683 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11685 for (i = 0; i < li_total_channels; i++)
11687 if (i != ch_a_v)
11688 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11691 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11693 for (i = 0; i < li_total_channels; i++)
11695 if (i != ch_a_s)
11696 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11699 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11701 for (i = 0; i < li_total_channels; i++)
11703 if (i != ch_a_v)
11704 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11707 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11709 for (i = 0; i < li_total_channels; i++)
11711 if (i != ch_a_s)
11712 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11716 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11718 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11723 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11725 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11727 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11728 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11730 if (li_flags & LI_FLAG_MONITOR_A)
11732 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11733 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11735 if (li_flags & LI_FLAG_MONITOR_B)
11737 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11738 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11740 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11742 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11745 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11747 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11748 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750 if (li_flags & LI_FLAG_MIX_A)
11752 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11753 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11755 if (li_flags & LI_FLAG_MIX_B)
11757 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11758 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11760 if (ch_a_v != ch_a_s)
11762 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11763 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11765 if (ch_b_v != ch_b_s)
11767 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11768 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11773 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11774 dword plci_b_id, byte connect, dword li_flags)
11776 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11777 PLCI *plci_b;
11778 DIVA_CAPI_ADAPTER *a_b;
11780 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11781 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11782 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11783 if (!a->li_pri && (plci->tel == ADV_VOICE)
11784 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11786 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11787 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11788 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11790 else
11792 ch_a_v = ch_a;
11793 ch_a_s = ch_a;
11795 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11796 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11797 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11799 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11800 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11801 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11803 else
11805 ch_b_v = ch_b;
11806 ch_b_s = ch_b;
11808 if (connect)
11810 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11811 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11812 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11813 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11815 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11817 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11827 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11832 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11834 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11836 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11837 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11839 if (li_flags & LI2_FLAG_MONITOR_B)
11841 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11842 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11844 if (li_flags & LI2_FLAG_MIX_B)
11846 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11847 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11849 if (li_flags & LI2_FLAG_MONITOR_X)
11850 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11851 if (li_flags & LI2_FLAG_MIX_X)
11852 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11853 if (li_flags & LI2_FLAG_LOOP_B)
11855 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11856 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11858 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11860 if (li_flags & LI2_FLAG_LOOP_PC)
11861 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11862 if (li_flags & LI2_FLAG_LOOP_X)
11863 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11864 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11865 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11866 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11867 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11868 if (ch_a_v != ch_a_s)
11870 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11871 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11873 if (ch_b_v != ch_b_s)
11875 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11876 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11881 static word li_check_main_plci(dword Id, PLCI *plci)
11883 if (plci == NULL)
11885 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11886 UnMapId(Id), (char *)(FILE_), __LINE__));
11887 return (_WRONG_IDENTIFIER);
11889 if (!plci->State
11890 || !plci->NL.Id || plci->nl_remove_id
11891 || (plci->li_bchannel_id == 0))
11893 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11894 UnMapId(Id), (char *)(FILE_), __LINE__));
11895 return (_WRONG_STATE);
11897 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11898 return (GOOD);
11902 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11903 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11905 byte ctlr_b;
11906 PLCI *plci_b;
11908 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11909 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11911 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11912 UnMapId(Id), (char *)(FILE_), __LINE__));
11913 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11914 return (NULL);
11916 ctlr_b = 0;
11917 if ((plci_b_id & 0x7f) != 0)
11919 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11920 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11921 ctlr_b = 0;
11923 if ((ctlr_b == 0)
11924 || (((plci_b_id >> 8) & 0xff) == 0)
11925 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11927 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11928 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11929 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11930 return (NULL);
11932 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11933 if (!plci_b->State
11934 || !plci_b->NL.Id || plci_b->nl_remove_id
11935 || (plci_b->li_bchannel_id == 0))
11937 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11938 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11939 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11940 return (NULL);
11942 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11943 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11944 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11945 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11948 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11949 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11950 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11951 return (NULL);
11953 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11954 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11956 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11957 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11958 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11959 return (NULL);
11961 return (plci_b);
11965 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11966 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11968 byte ctlr_b;
11969 PLCI *plci_b;
11971 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11972 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11974 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11975 UnMapId(Id), (char *)(FILE_), __LINE__));
11976 PUT_WORD(p_result, _WRONG_STATE);
11977 return (NULL);
11979 ctlr_b = 0;
11980 if ((plci_b_id & 0x7f) != 0)
11982 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11983 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11984 ctlr_b = 0;
11986 if ((ctlr_b == 0)
11987 || (((plci_b_id >> 8) & 0xff) == 0)
11988 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11990 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11991 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11992 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11993 return (NULL);
11995 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11996 if (!plci_b->State
11997 || !plci_b->NL.Id || plci_b->nl_remove_id
11998 || (plci_b->li_bchannel_id == 0)
11999 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12001 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12002 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12003 PUT_WORD(p_result, _WRONG_STATE);
12004 return (NULL);
12006 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12007 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12008 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12009 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12011 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12012 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12013 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12014 return (NULL);
12016 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12017 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12019 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12020 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12021 PUT_WORD(p_result, _WRONG_STATE);
12022 return (NULL);
12024 return (plci_b);
12028 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12030 word Info;
12031 word i;
12032 dword d, li_flags, plci_b_id;
12033 PLCI *plci_b;
12034 API_PARSE li_parms[3];
12035 API_PARSE li_req_parms[3];
12036 API_PARSE li_participant_struct[2];
12037 API_PARSE li_participant_parms[3];
12038 word participant_parms_pos;
12039 byte result_buffer[32];
12040 byte *result;
12041 word result_pos;
12042 word plci_b_write_pos;
12044 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12045 UnMapId(Id), (char *)(FILE_), __LINE__));
12047 Info = GOOD;
12048 result = result_buffer;
12049 result_buffer[0] = 0;
12050 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12052 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12053 UnMapId(Id), (char *)(FILE_), __LINE__));
12054 Info = _FACILITY_NOT_SUPPORTED;
12056 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12058 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12059 UnMapId(Id), (char *)(FILE_), __LINE__));
12060 Info = _WRONG_MESSAGE_FORMAT;
12062 else
12064 result_buffer[0] = 3;
12065 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12066 result_buffer[3] = 0;
12067 switch (GET_WORD(li_parms[0].info))
12069 case LI_GET_SUPPORTED_SERVICES:
12070 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12072 result_buffer[0] = 17;
12073 result_buffer[3] = 14;
12074 PUT_WORD(&result_buffer[4], GOOD);
12075 d = 0;
12076 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12077 d |= LI_CONFERENCING_SUPPORTED;
12078 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12079 d |= LI_MONITORING_SUPPORTED;
12080 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12081 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12082 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12084 PUT_DWORD(&result_buffer[6], d);
12085 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12087 d = 0;
12088 for (i = 0; i < li_total_channels; i++)
12090 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091 && (li_config_table[i].adapter->li_pri
12092 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12094 d++;
12098 else
12100 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12102 PUT_DWORD(&result_buffer[10], d / 2);
12103 PUT_DWORD(&result_buffer[14], d);
12105 else
12107 result_buffer[0] = 25;
12108 result_buffer[3] = 22;
12109 PUT_WORD(&result_buffer[4], GOOD);
12110 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12111 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12112 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12113 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12114 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12115 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12116 d |= LI2_PC_LOOPING_SUPPORTED;
12117 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12119 PUT_DWORD(&result_buffer[6], d);
12120 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12121 PUT_DWORD(&result_buffer[10], d / 2);
12122 PUT_DWORD(&result_buffer[14], d - 1);
12123 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12125 d = 0;
12126 for (i = 0; i < li_total_channels; i++)
12128 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12129 && (li_config_table[i].adapter->li_pri
12130 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12132 d++;
12136 PUT_DWORD(&result_buffer[18], d / 2);
12137 PUT_DWORD(&result_buffer[22], d - 1);
12139 break;
12141 case LI_REQ_CONNECT:
12142 if (li_parms[1].length == 8)
12144 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12145 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12147 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12148 UnMapId(Id), (char *)(FILE_), __LINE__));
12149 Info = _WRONG_MESSAGE_FORMAT;
12150 break;
12152 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12153 li_flags = GET_DWORD(li_req_parms[1].info);
12154 Info = li_check_main_plci(Id, plci);
12155 result_buffer[0] = 9;
12156 result_buffer[3] = 6;
12157 PUT_DWORD(&result_buffer[4], plci_b_id);
12158 PUT_WORD(&result_buffer[8], GOOD);
12159 if (Info != GOOD)
12160 break;
12161 result = plci->saved_msg.info;
12162 for (i = 0; i <= result_buffer[0]; i++)
12163 result[i] = result_buffer[i];
12164 plci_b_write_pos = plci->li_plci_b_write_pos;
12165 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12166 if (plci_b == NULL)
12167 break;
12168 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12169 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12170 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12171 plci->li_plci_b_write_pos = plci_b_write_pos;
12173 else
12175 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12176 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12178 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12179 UnMapId(Id), (char *)(FILE_), __LINE__));
12180 Info = _WRONG_MESSAGE_FORMAT;
12181 break;
12183 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12184 Info = li_check_main_plci(Id, plci);
12185 result_buffer[0] = 7;
12186 result_buffer[3] = 4;
12187 PUT_WORD(&result_buffer[4], Info);
12188 result_buffer[6] = 0;
12189 if (Info != GOOD)
12190 break;
12191 result = plci->saved_msg.info;
12192 for (i = 0; i <= result_buffer[0]; i++)
12193 result[i] = result_buffer[i];
12194 plci_b_write_pos = plci->li_plci_b_write_pos;
12195 participant_parms_pos = 0;
12196 result_pos = 7;
12197 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12198 while (participant_parms_pos < li_req_parms[1].length)
12200 result[result_pos] = 6;
12201 result_pos += 7;
12202 PUT_DWORD(&result[result_pos - 6], 0);
12203 PUT_WORD(&result[result_pos - 2], GOOD);
12204 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12205 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12207 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208 UnMapId(Id), (char *)(FILE_), __LINE__));
12209 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210 break;
12212 if (api_parse(&li_participant_struct[0].info[1],
12213 li_participant_struct[0].length, "dd", li_participant_parms))
12215 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 UnMapId(Id), (char *)(FILE_), __LINE__));
12217 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218 break;
12220 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221 li_flags = GET_DWORD(li_participant_parms[1].info);
12222 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12223 if (sizeof(result) - result_pos < 7)
12225 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12226 UnMapId(Id), (char *)(FILE_), __LINE__));
12227 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12228 break;
12230 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12231 if (plci_b != NULL)
12233 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12234 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12235 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12236 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12237 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12239 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12240 (&li_req_parms[1].info[1]));
12242 result[0] = (byte)(result_pos - 1);
12243 result[3] = (byte)(result_pos - 4);
12244 result[6] = (byte)(result_pos - 7);
12245 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12246 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12247 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12249 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12250 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12252 else
12253 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12254 plci->li_plci_b_write_pos = plci_b_write_pos;
12256 mixer_calculate_coefs(a);
12257 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12258 mixer_notify_update(plci, true);
12259 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12260 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12261 plci->command = 0;
12262 plci->li_cmd = GET_WORD(li_parms[0].info);
12263 start_internal_command(Id, plci, mixer_command);
12264 return (false);
12266 case LI_REQ_DISCONNECT:
12267 if (li_parms[1].length == 4)
12269 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12270 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12272 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12273 UnMapId(Id), (char *)(FILE_), __LINE__));
12274 Info = _WRONG_MESSAGE_FORMAT;
12275 break;
12277 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12278 Info = li_check_main_plci(Id, plci);
12279 result_buffer[0] = 9;
12280 result_buffer[3] = 6;
12281 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12282 PUT_WORD(&result_buffer[8], GOOD);
12283 if (Info != GOOD)
12284 break;
12285 result = plci->saved_msg.info;
12286 for (i = 0; i <= result_buffer[0]; i++)
12287 result[i] = result_buffer[i];
12288 plci_b_write_pos = plci->li_plci_b_write_pos;
12289 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12290 if (plci_b == NULL)
12291 break;
12292 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12293 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12294 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12295 plci->li_plci_b_write_pos = plci_b_write_pos;
12297 else
12299 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12300 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12302 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12303 UnMapId(Id), (char *)(FILE_), __LINE__));
12304 Info = _WRONG_MESSAGE_FORMAT;
12305 break;
12307 Info = li_check_main_plci(Id, plci);
12308 result_buffer[0] = 7;
12309 result_buffer[3] = 4;
12310 PUT_WORD(&result_buffer[4], Info);
12311 result_buffer[6] = 0;
12312 if (Info != GOOD)
12313 break;
12314 result = plci->saved_msg.info;
12315 for (i = 0; i <= result_buffer[0]; i++)
12316 result[i] = result_buffer[i];
12317 plci_b_write_pos = plci->li_plci_b_write_pos;
12318 participant_parms_pos = 0;
12319 result_pos = 7;
12320 while (participant_parms_pos < li_req_parms[0].length)
12322 result[result_pos] = 6;
12323 result_pos += 7;
12324 PUT_DWORD(&result[result_pos - 6], 0);
12325 PUT_WORD(&result[result_pos - 2], GOOD);
12326 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12327 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12329 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12330 UnMapId(Id), (char *)(FILE_), __LINE__));
12331 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332 break;
12334 if (api_parse(&li_participant_struct[0].info[1],
12335 li_participant_struct[0].length, "d", li_participant_parms))
12337 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12338 UnMapId(Id), (char *)(FILE_), __LINE__));
12339 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12340 break;
12342 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12343 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12344 if (sizeof(result) - result_pos < 7)
12346 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12347 UnMapId(Id), (char *)(FILE_), __LINE__));
12348 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12349 break;
12351 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12352 if (plci_b != NULL)
12354 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12355 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12356 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12358 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12359 (&li_req_parms[0].info[1]));
12361 result[0] = (byte)(result_pos - 1);
12362 result[3] = (byte)(result_pos - 4);
12363 result[6] = (byte)(result_pos - 7);
12364 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12365 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12366 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12368 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12369 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12371 else
12372 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12373 plci->li_plci_b_write_pos = plci_b_write_pos;
12375 mixer_calculate_coefs(a);
12376 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12377 mixer_notify_update(plci, true);
12378 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12379 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12380 plci->command = 0;
12381 plci->li_cmd = GET_WORD(li_parms[0].info);
12382 start_internal_command(Id, plci, mixer_command);
12383 return (false);
12385 case LI_REQ_SILENT_UPDATE:
12386 if (!plci || !plci->State
12387 || !plci->NL.Id || plci->nl_remove_id
12388 || (plci->li_bchannel_id == 0)
12389 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12391 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12392 UnMapId(Id), (char *)(FILE_), __LINE__));
12393 return (false);
12395 plci_b_write_pos = plci->li_plci_b_write_pos;
12396 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12397 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12399 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12400 UnMapId(Id), (char *)(FILE_), __LINE__));
12401 return (false);
12403 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12404 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12405 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12407 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12408 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12410 else
12411 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12412 plci->li_plci_b_write_pos = plci_b_write_pos;
12413 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12414 plci->command = 0;
12415 plci->li_cmd = GET_WORD(li_parms[0].info);
12416 start_internal_command(Id, plci, mixer_command);
12417 return (false);
12419 default:
12420 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12421 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12422 Info = _FACILITY_NOT_SUPPORTED;
12425 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12426 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12427 return (false);
12431 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12433 dword d;
12434 byte result[12];
12436 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12437 UnMapId(Id), (char *)(FILE_), __LINE__));
12439 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12443 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12444 if (!(d & LI_PLCI_B_SKIP_FLAG))
12446 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12448 if (d & LI_PLCI_B_DISC_FLAG)
12450 result[0] = 5;
12451 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12452 result[3] = 2;
12453 PUT_WORD(&result[4], _LI_USER_INITIATED);
12455 else
12457 result[0] = 7;
12458 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12459 result[3] = 4;
12460 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12463 else
12465 if (d & LI_PLCI_B_DISC_FLAG)
12467 result[0] = 9;
12468 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12469 result[3] = 6;
12470 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12471 PUT_WORD(&result[8], _LI_USER_INITIATED);
12473 else
12475 result[0] = 7;
12476 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12477 result[3] = 4;
12478 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12481 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12482 "ws", SELECTOR_LINE_INTERCONNECT, result);
12484 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12485 0 : plci->li_plci_b_read_pos + 1;
12486 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12491 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12493 word i, j, ch;
12494 struct xconnect_transfer_address_s s, *p;
12495 DIVA_CAPI_ADAPTER *a;
12497 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12498 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12500 a = plci->adapter;
12501 i = 1;
12502 for (i = 1; i < length; i += 16)
12504 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12505 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12506 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12507 ch = msg[i + 12] | (msg[i + 13] << 8);
12508 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12509 if (!a->li_pri && (plci->li_bchannel_id == 2))
12510 j = 1 - j;
12511 j += a->li_base;
12512 if (ch & XCONNECT_CHANNEL_PORT_PC)
12513 p = &(li_config_table[j].send_pc);
12514 else
12515 p = &(li_config_table[j].send_b);
12516 p->card_address.low = s.card_address.low;
12517 p->card_address.high = s.card_address.high;
12518 p->offset = s.offset;
12519 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12521 if (plci->internal_command_queue[0]
12522 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12523 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12524 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12526 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12527 if (!plci->internal_command)
12528 next_internal_command(Id, plci);
12530 mixer_notify_update(plci, true);
12534 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12537 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12538 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12543 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12545 word plci_b_write_pos;
12547 plci_b_write_pos = plci->li_plci_b_write_pos;
12548 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12549 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12551 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12552 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12553 (char *)(FILE_), __LINE__));
12554 return (false);
12556 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12557 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12558 plci->li_plci_b_write_pos = plci_b_write_pos;
12559 return (true);
12563 static void mixer_remove(PLCI *plci)
12565 DIVA_CAPI_ADAPTER *a;
12566 PLCI *notify_plci;
12567 dword plci_b_id;
12568 word i, j;
12570 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12571 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12572 (char *)(FILE_), __LINE__));
12574 a = plci->adapter;
12575 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12576 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12578 if ((plci->li_bchannel_id != 0)
12579 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12581 i = a->li_base + (plci->li_bchannel_id - 1);
12582 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12584 for (j = 0; j < li_total_channels; j++)
12586 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12587 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12589 notify_plci = li_config_table[j].plci;
12590 if ((notify_plci != NULL)
12591 && (notify_plci != plci)
12592 && (notify_plci->appl != NULL)
12593 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12594 && (notify_plci->State)
12595 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12597 mixer_notify_source_removed(notify_plci, plci_b_id);
12601 mixer_clear_config(plci);
12602 mixer_calculate_coefs(a);
12603 mixer_notify_update(plci, true);
12605 li_config_table[i].plci = NULL;
12606 plci->li_bchannel_id = 0;
12612 /*------------------------------------------------------------------*/
12613 /* Echo canceller facilities */
12614 /*------------------------------------------------------------------*/
12617 static void ec_write_parameters(PLCI *plci)
12619 word w;
12620 byte parameter_buffer[6];
12622 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12623 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12624 (char *)(FILE_), __LINE__));
12626 parameter_buffer[0] = 5;
12627 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12628 PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12629 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12630 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12631 PUT_WORD(&parameter_buffer[4], w);
12632 add_p(plci, FTY, parameter_buffer);
12633 sig_req(plci, TEL_CTRL, 0);
12634 send_req(plci);
12638 static void ec_clear_config(PLCI *plci)
12641 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12642 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12643 (char *)(FILE_), __LINE__));
12645 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12646 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12647 plci->ec_tail_length = 0;
12651 static void ec_prepare_switch(dword Id, PLCI *plci)
12654 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12655 UnMapId(Id), (char *)(FILE_), __LINE__));
12660 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12663 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12664 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12666 return (GOOD);
12670 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12672 word Info;
12674 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12675 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12677 Info = GOOD;
12678 if (plci->B1_facilities & B1_FACILITY_EC)
12680 switch (plci->adjust_b_state)
12682 case ADJUST_B_RESTORE_EC_1:
12683 plci->internal_command = plci->adjust_b_command;
12684 if (plci->sig_req)
12686 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12687 break;
12689 ec_write_parameters(plci);
12690 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12691 break;
12692 case ADJUST_B_RESTORE_EC_2:
12693 if ((Rc != OK) && (Rc != OK_FC))
12695 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12696 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12697 Info = _WRONG_STATE;
12698 break;
12700 break;
12703 return (Info);
12707 static void ec_command(dword Id, PLCI *plci, byte Rc)
12709 word internal_command, Info;
12710 byte result[8];
12712 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12713 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12714 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12716 Info = GOOD;
12717 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12719 result[0] = 2;
12720 PUT_WORD(&result[1], EC_SUCCESS);
12722 else
12724 result[0] = 5;
12725 PUT_WORD(&result[1], plci->ec_cmd);
12726 result[3] = 2;
12727 PUT_WORD(&result[4], GOOD);
12729 internal_command = plci->internal_command;
12730 plci->internal_command = 0;
12731 switch (plci->ec_cmd)
12733 case EC_ENABLE_OPERATION:
12734 case EC_FREEZE_COEFFICIENTS:
12735 case EC_RESUME_COEFFICIENT_UPDATE:
12736 case EC_RESET_COEFFICIENTS:
12737 switch (internal_command)
12739 default:
12740 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12741 B1_FACILITY_EC), EC_COMMAND_1);
12742 case EC_COMMAND_1:
12743 if (adjust_b_process(Id, plci, Rc) != GOOD)
12745 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12746 UnMapId(Id), (char *)(FILE_), __LINE__));
12747 Info = _FACILITY_NOT_SUPPORTED;
12748 break;
12750 if (plci->internal_command)
12751 return;
12752 case EC_COMMAND_2:
12753 if (plci->sig_req)
12755 plci->internal_command = EC_COMMAND_2;
12756 return;
12758 plci->internal_command = EC_COMMAND_3;
12759 ec_write_parameters(plci);
12760 return;
12761 case EC_COMMAND_3:
12762 if ((Rc != OK) && (Rc != OK_FC))
12764 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12765 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12766 Info = _FACILITY_NOT_SUPPORTED;
12767 break;
12769 break;
12771 break;
12773 case EC_DISABLE_OPERATION:
12774 switch (internal_command)
12776 default:
12777 case EC_COMMAND_1:
12778 if (plci->B1_facilities & B1_FACILITY_EC)
12780 if (plci->sig_req)
12782 plci->internal_command = EC_COMMAND_1;
12783 return;
12785 plci->internal_command = EC_COMMAND_2;
12786 ec_write_parameters(plci);
12787 return;
12789 Rc = OK;
12790 case EC_COMMAND_2:
12791 if ((Rc != OK) && (Rc != OK_FC))
12793 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12794 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12795 Info = _FACILITY_NOT_SUPPORTED;
12796 break;
12798 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12799 ~B1_FACILITY_EC), EC_COMMAND_3);
12800 case EC_COMMAND_3:
12801 if (adjust_b_process(Id, plci, Rc) != GOOD)
12803 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12804 UnMapId(Id), (char *)(FILE_), __LINE__));
12805 Info = _FACILITY_NOT_SUPPORTED;
12806 break;
12808 if (plci->internal_command)
12809 return;
12810 break;
12812 break;
12814 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12815 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12816 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12820 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12822 word Info;
12823 word opt;
12824 API_PARSE ec_parms[3];
12825 byte result[16];
12827 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12828 UnMapId(Id), (char *)(FILE_), __LINE__));
12830 Info = GOOD;
12831 result[0] = 0;
12832 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12834 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12835 UnMapId(Id), (char *)(FILE_), __LINE__));
12836 Info = _FACILITY_NOT_SUPPORTED;
12838 else
12840 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12842 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12844 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12845 UnMapId(Id), (char *)(FILE_), __LINE__));
12846 Info = _WRONG_MESSAGE_FORMAT;
12848 else
12850 if (plci == NULL)
12852 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12853 UnMapId(Id), (char *)(FILE_), __LINE__));
12854 Info = _WRONG_IDENTIFIER;
12856 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12858 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12859 UnMapId(Id), (char *)(FILE_), __LINE__));
12860 Info = _WRONG_STATE;
12862 else
12864 plci->command = 0;
12865 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12866 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12867 result[0] = 2;
12868 PUT_WORD(&result[1], EC_SUCCESS);
12869 if (msg[1].length >= 4)
12871 opt = GET_WORD(&ec_parms[0].info[2]);
12872 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12873 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12874 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12875 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12876 if (opt & EC_DETECT_DISABLE_TONE)
12877 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12878 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12879 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12880 if (msg[1].length >= 6)
12882 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12885 switch (plci->ec_cmd)
12887 case EC_ENABLE_OPERATION:
12888 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12889 start_internal_command(Id, plci, ec_command);
12890 return (false);
12892 case EC_DISABLE_OPERATION:
12893 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12894 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12895 LEC_RESET_COEFFICIENTS;
12896 start_internal_command(Id, plci, ec_command);
12897 return (false);
12899 case EC_FREEZE_COEFFICIENTS:
12900 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12901 start_internal_command(Id, plci, ec_command);
12902 return (false);
12904 case EC_RESUME_COEFFICIENT_UPDATE:
12905 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12906 start_internal_command(Id, plci, ec_command);
12907 return (false);
12909 case EC_RESET_COEFFICIENTS:
12910 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12911 start_internal_command(Id, plci, ec_command);
12912 return (false);
12914 default:
12915 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12916 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12917 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12922 else
12924 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12926 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12927 UnMapId(Id), (char *)(FILE_), __LINE__));
12928 Info = _WRONG_MESSAGE_FORMAT;
12930 else
12932 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12934 result[0] = 11;
12935 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12936 result[3] = 8;
12937 PUT_WORD(&result[4], GOOD);
12938 PUT_WORD(&result[6], 0x0007);
12939 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12940 PUT_WORD(&result[10], 0);
12942 else if (plci == NULL)
12944 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12945 UnMapId(Id), (char *)(FILE_), __LINE__));
12946 Info = _WRONG_IDENTIFIER;
12948 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12950 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12951 UnMapId(Id), (char *)(FILE_), __LINE__));
12952 Info = _WRONG_STATE;
12954 else
12956 plci->command = 0;
12957 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12958 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12959 result[0] = 5;
12960 PUT_WORD(&result[1], plci->ec_cmd);
12961 result[3] = 2;
12962 PUT_WORD(&result[4], GOOD);
12963 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12964 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12965 plci->ec_tail_length = 0;
12966 if (ec_parms[1].length >= 2)
12968 opt = GET_WORD(&ec_parms[1].info[1]);
12969 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12970 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12971 if (opt & EC_DETECT_DISABLE_TONE)
12972 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12973 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12974 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12975 if (ec_parms[1].length >= 4)
12977 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12980 switch (plci->ec_cmd)
12982 case EC_ENABLE_OPERATION:
12983 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12984 start_internal_command(Id, plci, ec_command);
12985 return (false);
12987 case EC_DISABLE_OPERATION:
12988 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12989 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12990 LEC_RESET_COEFFICIENTS;
12991 start_internal_command(Id, plci, ec_command);
12992 return (false);
12994 default:
12995 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12996 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12997 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13003 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13004 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13005 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13006 return (false);
13010 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13012 byte result[8];
13014 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13015 UnMapId(Id), (char *)(FILE_), __LINE__));
13017 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13019 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13021 result[0] = 2;
13022 PUT_WORD(&result[1], 0);
13023 switch (msg[1])
13025 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13026 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13027 break;
13028 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13029 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13030 break;
13031 case LEC_DISABLE_RELEASED:
13032 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13033 break;
13036 else
13038 result[0] = 5;
13039 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13040 result[3] = 2;
13041 PUT_WORD(&result[4], 0);
13042 switch (msg[1])
13044 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046 break;
13047 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049 break;
13050 case LEC_DISABLE_RELEASED:
13051 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13052 break;
13055 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13056 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13062 /*------------------------------------------------------------------*/
13063 /* Advanced voice */
13064 /*------------------------------------------------------------------*/
13066 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13068 DIVA_CAPI_ADAPTER *a;
13069 word i;
13070 byte *p;
13072 word w, n, j, k;
13073 byte ch_map[MIXER_CHANNELS_BRI];
13075 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13077 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13078 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13079 (char *)(FILE_), __LINE__, write_command));
13081 a = plci->adapter;
13082 p = coef_buffer + 1;
13083 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13084 i = 0;
13085 while (i + sizeof(word) <= a->adv_voice_coef_length)
13087 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13088 p += 2;
13089 i += 2;
13091 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13093 PUT_WORD(p, 0x8000);
13094 p += 2;
13095 i += 2;
13098 if (!a->li_pri && (plci->li_bchannel_id == 0))
13100 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13102 plci->li_bchannel_id = 1;
13103 li_config_table[a->li_base].plci = plci;
13104 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13105 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13106 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13108 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13110 plci->li_bchannel_id = 2;
13111 li_config_table[a->li_base + 1].plci = plci;
13112 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13114 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13117 if (!a->li_pri && (plci->li_bchannel_id != 0)
13118 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13120 i = a->li_base + (plci->li_bchannel_id - 1);
13121 switch (write_command)
13123 case ADV_VOICE_WRITE_ACTIVATION:
13124 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13125 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13126 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13128 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13133 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13134 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13135 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13136 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13138 mixer_calculate_coefs(a);
13139 li_config_table[i].curchnl = li_config_table[i].channel;
13140 li_config_table[j].curchnl = li_config_table[j].channel;
13141 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13142 li_config_table[k].curchnl = li_config_table[k].channel;
13143 break;
13145 case ADV_VOICE_WRITE_DEACTIVATION:
13146 for (j = 0; j < li_total_channels; j++)
13148 li_config_table[i].flag_table[j] = 0;
13149 li_config_table[j].flag_table[i] = 0;
13151 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13152 for (j = 0; j < li_total_channels; j++)
13154 li_config_table[k].flag_table[j] = 0;
13155 li_config_table[j].flag_table[k] = 0;
13157 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13159 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13160 for (j = 0; j < li_total_channels; j++)
13162 li_config_table[k].flag_table[j] = 0;
13163 li_config_table[j].flag_table[k] = 0;
13166 mixer_calculate_coefs(a);
13167 break;
13169 if (plci->B1_facilities & B1_FACILITY_MIXER)
13171 w = 0;
13172 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13173 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13174 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13175 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13176 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13177 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13178 *(p++) = (byte) w;
13179 *(p++) = (byte)(w >> 8);
13180 for (j = 0; j < sizeof(ch_map); j += 2)
13182 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13183 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13185 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13187 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13188 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13189 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13191 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13192 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13193 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13195 else
13197 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13198 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13202 else
13204 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13205 *(p++) = a->adv_voice_coef_buffer[i];
13208 else
13211 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212 *(p++) = a->adv_voice_coef_buffer[i];
13214 coef_buffer[0] = (p - coef_buffer) - 1;
13215 add_p(plci, FTY, coef_buffer);
13216 sig_req(plci, TEL_CTRL, 0);
13217 send_req(plci);
13221 static void adv_voice_clear_config(PLCI *plci)
13223 DIVA_CAPI_ADAPTER *a;
13225 word i, j;
13228 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13229 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13230 (char *)(FILE_), __LINE__));
13232 a = plci->adapter;
13233 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13235 a->adv_voice_coef_length = 0;
13237 if (!a->li_pri && (plci->li_bchannel_id != 0)
13238 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13240 i = a->li_base + (plci->li_bchannel_id - 1);
13241 li_config_table[i].curchnl = 0;
13242 li_config_table[i].channel = 0;
13243 li_config_table[i].chflags = 0;
13244 for (j = 0; j < li_total_channels; j++)
13246 li_config_table[i].flag_table[j] = 0;
13247 li_config_table[j].flag_table[i] = 0;
13248 li_config_table[i].coef_table[j] = 0;
13249 li_config_table[j].coef_table[i] = 0;
13251 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13252 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13253 li_config_table[i].curchnl = 0;
13254 li_config_table[i].channel = 0;
13255 li_config_table[i].chflags = 0;
13256 for (j = 0; j < li_total_channels; j++)
13258 li_config_table[i].flag_table[j] = 0;
13259 li_config_table[j].flag_table[i] = 0;
13260 li_config_table[i].coef_table[j] = 0;
13261 li_config_table[j].coef_table[i] = 0;
13263 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13265 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13266 li_config_table[i].curchnl = 0;
13267 li_config_table[i].channel = 0;
13268 li_config_table[i].chflags = 0;
13269 for (j = 0; j < li_total_channels; j++)
13271 li_config_table[i].flag_table[j] = 0;
13272 li_config_table[j].flag_table[i] = 0;
13273 li_config_table[i].coef_table[j] = 0;
13274 li_config_table[j].coef_table[i] = 0;
13283 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13286 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13287 UnMapId(Id), (char *)(FILE_), __LINE__));
13292 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13295 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13296 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13298 return (GOOD);
13302 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13304 DIVA_CAPI_ADAPTER *a;
13305 word Info;
13307 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13308 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13310 Info = GOOD;
13311 a = plci->adapter;
13312 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13313 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13315 switch (plci->adjust_b_state)
13317 case ADJUST_B_RESTORE_VOICE_1:
13318 plci->internal_command = plci->adjust_b_command;
13319 if (plci->sig_req)
13321 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13322 break;
13324 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13325 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13326 break;
13327 case ADJUST_B_RESTORE_VOICE_2:
13328 if ((Rc != OK) && (Rc != OK_FC))
13330 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13331 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13332 Info = _WRONG_STATE;
13333 break;
13335 break;
13338 return (Info);
13344 /*------------------------------------------------------------------*/
13345 /* B1 resource switching */
13346 /*------------------------------------------------------------------*/
13348 static byte b1_facilities_table[] =
13350 0x00, /* 0 No bchannel resources */
13351 0x00, /* 1 Codec (automatic law) */
13352 0x00, /* 2 Codec (A-law) */
13353 0x00, /* 3 Codec (y-law) */
13354 0x00, /* 4 HDLC for X.21 */
13355 0x00, /* 5 HDLC */
13356 0x00, /* 6 External Device 0 */
13357 0x00, /* 7 External Device 1 */
13358 0x00, /* 8 HDLC 56k */
13359 0x00, /* 9 Transparent */
13360 0x00, /* 10 Loopback to network */
13361 0x00, /* 11 Test pattern to net */
13362 0x00, /* 12 Rate adaptation sync */
13363 0x00, /* 13 Rate adaptation async */
13364 0x00, /* 14 R-Interface */
13365 0x00, /* 15 HDLC 128k leased line */
13366 0x00, /* 16 FAX */
13367 0x00, /* 17 Modem async */
13368 0x00, /* 18 Modem sync HDLC */
13369 0x00, /* 19 V.110 async HDLC */
13370 0x12, /* 20 Adv voice (Trans,mixer) */
13371 0x00, /* 21 Codec connected to IC */
13372 0x0c, /* 22 Trans,DTMF */
13373 0x1e, /* 23 Trans,DTMF+mixer */
13374 0x1f, /* 24 Trans,DTMF+mixer+local */
13375 0x13, /* 25 Trans,mixer+local */
13376 0x12, /* 26 HDLC,mixer */
13377 0x12, /* 27 HDLC 56k,mixer */
13378 0x2c, /* 28 Trans,LEC+DTMF */
13379 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13380 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13381 0x2c, /* 31 RTP,LEC+DTMF */
13382 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13383 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13384 0x00, /* 34 Signaling task */
13385 0x00, /* 35 PIAFS */
13386 0x0c, /* 36 Trans,DTMF+TONE */
13387 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13388 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13392 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13394 word b1_facilities;
13396 b1_facilities = b1_facilities_table[b1_resource];
13397 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13400 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13401 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13404 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13405 b1_facilities |= B1_FACILITY_DTMFX;
13406 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13407 b1_facilities |= B1_FACILITY_DTMFR;
13410 if ((b1_resource == 17) || (b1_resource == 18))
13412 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13413 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13416 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13417 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13418 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13420 return (b1_facilities);
13424 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13426 byte b;
13428 switch (b1_resource)
13430 case 5:
13431 case 26:
13432 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13433 b = 26;
13434 else
13435 b = 5;
13436 break;
13438 case 8:
13439 case 27:
13440 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441 b = 27;
13442 else
13443 b = 8;
13444 break;
13446 case 9:
13447 case 20:
13448 case 22:
13449 case 23:
13450 case 24:
13451 case 25:
13452 case 28:
13453 case 29:
13454 case 30:
13455 case 36:
13456 case 37:
13457 case 38:
13458 if (b1_facilities & B1_FACILITY_EC)
13460 if (b1_facilities & B1_FACILITY_LOCAL)
13461 b = 30;
13462 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13463 b = 29;
13464 else
13465 b = 28;
13468 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13469 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13470 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13472 if (b1_facilities & B1_FACILITY_LOCAL)
13473 b = 38;
13474 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13475 b = 37;
13476 else
13477 b = 36;
13480 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13481 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13482 || ((b1_facilities & B1_FACILITY_DTMFR)
13483 && ((b1_facilities & B1_FACILITY_MIXER)
13484 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13485 || ((b1_facilities & B1_FACILITY_DTMFX)
13486 && ((b1_facilities & B1_FACILITY_MIXER)
13487 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13489 if (b1_facilities & B1_FACILITY_LOCAL)
13490 b = 24;
13491 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13492 b = 23;
13493 else
13494 b = 22;
13496 else
13498 if (b1_facilities & B1_FACILITY_LOCAL)
13499 b = 25;
13500 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13501 b = 20;
13502 else
13503 b = 9;
13505 break;
13507 case 31:
13508 case 32:
13509 case 33:
13510 if (b1_facilities & B1_FACILITY_LOCAL)
13511 b = 33;
13512 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13513 b = 32;
13514 else
13515 b = 31;
13516 break;
13518 default:
13519 b = b1_resource;
13521 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13522 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13523 (char *)(FILE_), __LINE__,
13524 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13525 return (b);
13529 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13531 word removed_facilities;
13533 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13534 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13535 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13536 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13538 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13539 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13541 if (removed_facilities & B1_FACILITY_EC)
13542 ec_clear_config(plci);
13545 if (removed_facilities & B1_FACILITY_DTMFR)
13547 dtmf_rec_clear_config(plci);
13548 dtmf_parameter_clear_config(plci);
13550 if (removed_facilities & B1_FACILITY_DTMFX)
13551 dtmf_send_clear_config(plci);
13554 if (removed_facilities & B1_FACILITY_MIXER)
13555 mixer_clear_config(plci);
13557 if (removed_facilities & B1_FACILITY_VOICE)
13558 adv_voice_clear_config(plci);
13559 plci->B1_facilities = new_b1_facilities;
13563 static void adjust_b_clear(PLCI *plci)
13566 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13567 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13568 (char *)(FILE_), __LINE__));
13570 plci->adjust_b_restore = false;
13574 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13576 word Info;
13577 byte b1_resource;
13578 NCCI *ncci_ptr;
13579 API_PARSE bp[2];
13581 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13582 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13584 Info = GOOD;
13585 switch (plci->adjust_b_state)
13587 case ADJUST_B_START:
13588 if ((plci->adjust_b_parms_msg == NULL)
13589 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13590 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13591 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13593 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13594 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13595 if (b1_resource == plci->B1_resource)
13597 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13598 break;
13600 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13602 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13603 UnMapId(Id), (char *)(FILE_), __LINE__,
13604 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13605 Info = _WRONG_STATE;
13606 break;
13609 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13612 mixer_prepare_switch(Id, plci);
13615 dtmf_prepare_switch(Id, plci);
13616 dtmf_parameter_prepare_switch(Id, plci);
13619 ec_prepare_switch(Id, plci);
13621 adv_voice_prepare_switch(Id, plci);
13623 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13624 Rc = OK;
13625 case ADJUST_B_SAVE_MIXER_1:
13626 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13629 Info = mixer_save_config(Id, plci, Rc);
13630 if ((Info != GOOD) || plci->internal_command)
13631 break;
13634 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13635 Rc = OK;
13636 case ADJUST_B_SAVE_DTMF_1:
13637 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13640 Info = dtmf_save_config(Id, plci, Rc);
13641 if ((Info != GOOD) || plci->internal_command)
13642 break;
13645 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13646 case ADJUST_B_REMOVE_L23_1:
13647 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13648 && plci->NL.Id && !plci->nl_remove_id)
13650 plci->internal_command = plci->adjust_b_command;
13651 if (plci->adjust_b_ncci != 0)
13653 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13654 while (ncci_ptr->data_pending)
13656 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13657 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13659 while (ncci_ptr->data_ack_pending)
13660 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13662 nl_req_ncci(plci, REMOVE,
13663 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13664 send_req(plci);
13665 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13666 break;
13668 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13669 Rc = OK;
13670 case ADJUST_B_REMOVE_L23_2:
13671 if ((Rc != OK) && (Rc != OK_FC))
13673 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13674 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13675 Info = _WRONG_STATE;
13676 break;
13678 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13680 if (plci_nl_busy(plci))
13682 plci->internal_command = plci->adjust_b_command;
13683 break;
13686 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13687 Rc = OK;
13688 case ADJUST_B_SAVE_EC_1:
13689 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13692 Info = ec_save_config(Id, plci, Rc);
13693 if ((Info != GOOD) || plci->internal_command)
13694 break;
13697 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13698 Rc = OK;
13699 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13700 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13703 Info = dtmf_parameter_save_config(Id, plci, Rc);
13704 if ((Info != GOOD) || plci->internal_command)
13705 break;
13708 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13709 Rc = OK;
13710 case ADJUST_B_SAVE_VOICE_1:
13711 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13713 Info = adv_voice_save_config(Id, plci, Rc);
13714 if ((Info != GOOD) || plci->internal_command)
13715 break;
13717 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13718 case ADJUST_B_SWITCH_L1_1:
13719 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13721 if (plci->sig_req)
13723 plci->internal_command = plci->adjust_b_command;
13724 break;
13726 if (plci->adjust_b_parms_msg != NULL)
13727 api_load_msg(plci->adjust_b_parms_msg, bp);
13728 else
13729 api_load_msg(&plci->B_protocol, bp);
13730 Info = add_b1(plci, bp,
13731 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13732 plci->adjust_b_facilities);
13733 if (Info != GOOD)
13735 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13736 UnMapId(Id), (char *)(FILE_), __LINE__,
13737 plci->B1_resource, plci->adjust_b_facilities));
13738 break;
13740 plci->internal_command = plci->adjust_b_command;
13741 sig_req(plci, RESOURCES, 0);
13742 send_req(plci);
13743 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13744 break;
13746 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13747 Rc = OK;
13748 case ADJUST_B_SWITCH_L1_2:
13749 if ((Rc != OK) && (Rc != OK_FC))
13751 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13752 UnMapId(Id), (char *)(FILE_), __LINE__,
13753 Rc, plci->B1_resource, plci->adjust_b_facilities));
13754 Info = _WRONG_STATE;
13755 break;
13757 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13758 Rc = OK;
13759 case ADJUST_B_RESTORE_VOICE_1:
13760 case ADJUST_B_RESTORE_VOICE_2:
13761 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13763 Info = adv_voice_restore_config(Id, plci, Rc);
13764 if ((Info != GOOD) || plci->internal_command)
13765 break;
13767 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13768 Rc = OK;
13769 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13771 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13774 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13775 if ((Info != GOOD) || plci->internal_command)
13776 break;
13779 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13780 Rc = OK;
13781 case ADJUST_B_RESTORE_EC_1:
13782 case ADJUST_B_RESTORE_EC_2:
13783 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13786 Info = ec_restore_config(Id, plci, Rc);
13787 if ((Info != GOOD) || plci->internal_command)
13788 break;
13791 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13792 case ADJUST_B_ASSIGN_L23_1:
13793 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13795 if (plci_nl_busy(plci))
13797 plci->internal_command = plci->adjust_b_command;
13798 break;
13800 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13801 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13802 if (plci->adjust_b_parms_msg != NULL)
13803 api_load_msg(plci->adjust_b_parms_msg, bp);
13804 else
13805 api_load_msg(&plci->B_protocol, bp);
13806 Info = add_b23(plci, bp);
13807 if (Info != GOOD)
13809 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13810 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13811 break;
13813 plci->internal_command = plci->adjust_b_command;
13814 nl_req_ncci(plci, ASSIGN, 0);
13815 send_req(plci);
13816 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13817 break;
13819 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13820 Rc = ASSIGN_OK;
13821 case ADJUST_B_ASSIGN_L23_2:
13822 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13824 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13825 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13826 Info = _WRONG_STATE;
13827 break;
13829 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13831 if (Rc != ASSIGN_OK)
13833 plci->internal_command = plci->adjust_b_command;
13834 break;
13837 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13839 plci->adjust_b_restore = true;
13840 break;
13842 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13843 case ADJUST_B_CONNECT_1:
13844 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13846 plci->internal_command = plci->adjust_b_command;
13847 if (plci_nl_busy(plci))
13848 break;
13849 nl_req_ncci(plci, N_CONNECT, 0);
13850 send_req(plci);
13851 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13852 break;
13854 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13855 Rc = OK;
13856 case ADJUST_B_CONNECT_2:
13857 case ADJUST_B_CONNECT_3:
13858 case ADJUST_B_CONNECT_4:
13859 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13861 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13862 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13863 Info = _WRONG_STATE;
13864 break;
13866 if (Rc == OK)
13868 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13870 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13871 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13873 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13874 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13875 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13876 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878 else if (Rc == 0)
13880 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13882 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13883 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13885 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13887 plci->internal_command = plci->adjust_b_command;
13888 break;
13890 Rc = OK;
13891 case ADJUST_B_RESTORE_DTMF_1:
13892 case ADJUST_B_RESTORE_DTMF_2:
13893 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13896 Info = dtmf_restore_config(Id, plci, Rc);
13897 if ((Info != GOOD) || plci->internal_command)
13898 break;
13901 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13902 Rc = OK;
13903 case ADJUST_B_RESTORE_MIXER_1:
13904 case ADJUST_B_RESTORE_MIXER_2:
13905 case ADJUST_B_RESTORE_MIXER_3:
13906 case ADJUST_B_RESTORE_MIXER_4:
13907 case ADJUST_B_RESTORE_MIXER_5:
13908 case ADJUST_B_RESTORE_MIXER_6:
13909 case ADJUST_B_RESTORE_MIXER_7:
13910 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13913 Info = mixer_restore_config(Id, plci, Rc);
13914 if ((Info != GOOD) || plci->internal_command)
13915 break;
13918 plci->adjust_b_state = ADJUST_B_END;
13919 case ADJUST_B_END:
13920 break;
13922 return (Info);
13926 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13929 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13930 UnMapId(Id), (char *)(FILE_), __LINE__,
13931 plci->B1_resource, b1_facilities));
13933 plci->adjust_b_parms_msg = bp_msg;
13934 plci->adjust_b_facilities = b1_facilities;
13935 plci->adjust_b_command = internal_command;
13936 plci->adjust_b_ncci = (word)(Id >> 16);
13937 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13938 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13939 else
13940 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13941 plci->adjust_b_state = ADJUST_B_START;
13942 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13943 UnMapId(Id), (char *)(FILE_), __LINE__,
13944 plci->B1_resource, b1_facilities));
13948 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13950 word internal_command;
13952 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13953 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13955 internal_command = plci->internal_command;
13956 plci->internal_command = 0;
13957 switch (internal_command)
13959 default:
13960 plci->command = 0;
13961 if (plci->req_in != 0)
13963 plci->internal_command = ADJUST_B_RESTORE_1;
13964 break;
13966 Rc = OK;
13967 case ADJUST_B_RESTORE_1:
13968 if ((Rc != OK) && (Rc != OK_FC))
13970 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13971 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13973 plci->adjust_b_parms_msg = NULL;
13974 plci->adjust_b_facilities = plci->B1_facilities;
13975 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13976 plci->adjust_b_ncci = (word)(Id >> 16);
13977 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13978 plci->adjust_b_state = ADJUST_B_START;
13979 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13980 UnMapId(Id), (char *)(FILE_), __LINE__));
13981 case ADJUST_B_RESTORE_2:
13982 if (adjust_b_process(Id, plci, Rc) != GOOD)
13984 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13985 UnMapId(Id), (char *)(FILE_), __LINE__));
13987 if (plci->internal_command)
13988 break;
13989 break;
13994 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13996 word Info;
13997 word internal_command;
13999 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14000 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14002 Info = GOOD;
14003 internal_command = plci->internal_command;
14004 plci->internal_command = 0;
14005 switch (internal_command)
14007 default:
14008 plci->command = 0;
14009 plci->adjust_b_parms_msg = NULL;
14010 plci->adjust_b_facilities = plci->B1_facilities;
14011 plci->adjust_b_command = RESET_B3_COMMAND_1;
14012 plci->adjust_b_ncci = (word)(Id >> 16);
14013 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14014 plci->adjust_b_state = ADJUST_B_START;
14015 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14016 UnMapId(Id), (char *)(FILE_), __LINE__));
14017 case RESET_B3_COMMAND_1:
14018 Info = adjust_b_process(Id, plci, Rc);
14019 if (Info != GOOD)
14021 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14022 UnMapId(Id), (char *)(FILE_), __LINE__));
14023 break;
14025 if (plci->internal_command)
14026 return;
14027 break;
14029 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14030 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14034 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14036 word Info;
14037 word internal_command;
14038 byte esc_chi[3];
14040 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14041 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14043 Info = GOOD;
14044 internal_command = plci->internal_command;
14045 plci->internal_command = 0;
14046 switch (internal_command)
14048 default:
14049 plci->command = 0;
14050 plci->adjust_b_parms_msg = &plci->saved_msg;
14051 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14052 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14053 else
14054 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14055 plci->adjust_b_command = SELECT_B_COMMAND_1;
14056 plci->adjust_b_ncci = (word)(Id >> 16);
14057 if (plci->saved_msg.parms[0].length == 0)
14059 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060 ADJUST_B_MODE_NO_RESOURCE;
14062 else
14064 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14065 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14067 plci->adjust_b_state = ADJUST_B_START;
14068 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14069 UnMapId(Id), (char *)(FILE_), __LINE__));
14070 case SELECT_B_COMMAND_1:
14071 Info = adjust_b_process(Id, plci, Rc);
14072 if (Info != GOOD)
14074 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14075 UnMapId(Id), (char *)(FILE_), __LINE__));
14076 break;
14078 if (plci->internal_command)
14079 return;
14080 if (plci->tel == ADV_VOICE)
14082 esc_chi[0] = 0x02;
14083 esc_chi[1] = 0x18;
14084 esc_chi[2] = plci->b_channel;
14085 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14087 break;
14089 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14093 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14095 word internal_command;
14097 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14098 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14100 internal_command = plci->internal_command;
14101 plci->internal_command = 0;
14102 switch (internal_command)
14104 default:
14105 plci->command = 0;
14106 case FAX_CONNECT_ACK_COMMAND_1:
14107 if (plci_nl_busy(plci))
14109 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14110 return;
14112 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14113 plci->NData[0].P = plci->fax_connect_info_buffer;
14114 plci->NData[0].PLength = plci->fax_connect_info_length;
14115 plci->NL.X = plci->NData;
14116 plci->NL.ReqCh = 0;
14117 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14118 plci->adapter->request(&plci->NL);
14119 return;
14120 case FAX_CONNECT_ACK_COMMAND_2:
14121 if ((Rc != OK) && (Rc != OK_FC))
14123 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14124 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14125 break;
14128 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14129 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14131 if (plci->B3_prot == 4)
14132 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14133 else
14134 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14135 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14140 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14142 word internal_command;
14144 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_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)
14151 default:
14152 plci->command = 0;
14153 case FAX_EDATA_ACK_COMMAND_1:
14154 if (plci_nl_busy(plci))
14156 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14157 return;
14159 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14160 plci->NData[0].P = plci->fax_connect_info_buffer;
14161 plci->NData[0].PLength = plci->fax_edata_ack_length;
14162 plci->NL.X = plci->NData;
14163 plci->NL.ReqCh = 0;
14164 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14165 plci->adapter->request(&plci->NL);
14166 return;
14167 case FAX_EDATA_ACK_COMMAND_2:
14168 if ((Rc != OK) && (Rc != OK_FC))
14170 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14171 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14172 break;
14178 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14180 word Info;
14181 word internal_command;
14183 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14184 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14186 Info = GOOD;
14187 internal_command = plci->internal_command;
14188 plci->internal_command = 0;
14189 switch (internal_command)
14191 default:
14192 plci->command = 0;
14193 case FAX_CONNECT_INFO_COMMAND_1:
14194 if (plci_nl_busy(plci))
14196 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14197 return;
14199 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14200 plci->NData[0].P = plci->fax_connect_info_buffer;
14201 plci->NData[0].PLength = plci->fax_connect_info_length;
14202 plci->NL.X = plci->NData;
14203 plci->NL.ReqCh = 0;
14204 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14205 plci->adapter->request(&plci->NL);
14206 return;
14207 case FAX_CONNECT_INFO_COMMAND_2:
14208 if ((Rc != OK) && (Rc != OK_FC))
14210 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14211 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14212 Info = _WRONG_STATE;
14213 break;
14215 if (plci_nl_busy(plci))
14217 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14218 return;
14220 plci->command = _CONNECT_B3_R;
14221 nl_req_ncci(plci, N_CONNECT, 0);
14222 send_req(plci);
14223 return;
14225 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14229 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14231 word Info;
14232 word internal_command;
14234 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14235 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14237 Info = GOOD;
14238 internal_command = plci->internal_command;
14239 plci->internal_command = 0;
14240 switch (internal_command)
14242 default:
14243 plci->command = 0;
14244 plci->adjust_b_parms_msg = NULL;
14245 plci->adjust_b_facilities = plci->B1_facilities;
14246 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14247 plci->adjust_b_ncci = (word)(Id >> 16);
14248 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14249 plci->adjust_b_state = ADJUST_B_START;
14250 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14251 UnMapId(Id), (char *)(FILE_), __LINE__));
14252 case FAX_ADJUST_B23_COMMAND_1:
14253 Info = adjust_b_process(Id, plci, Rc);
14254 if (Info != GOOD)
14256 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14257 UnMapId(Id), (char *)(FILE_), __LINE__));
14258 break;
14260 if (plci->internal_command)
14261 return;
14262 case FAX_ADJUST_B23_COMMAND_2:
14263 if (plci_nl_busy(plci))
14265 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14266 return;
14268 plci->command = _CONNECT_B3_R;
14269 nl_req_ncci(plci, N_CONNECT, 0);
14270 send_req(plci);
14271 return;
14273 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14277 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14279 word internal_command;
14281 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14282 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14284 internal_command = plci->internal_command;
14285 plci->internal_command = 0;
14286 switch (internal_command)
14288 default:
14289 plci->command = 0;
14290 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14291 return;
14292 case FAX_DISCONNECT_COMMAND_1:
14293 case FAX_DISCONNECT_COMMAND_2:
14294 case FAX_DISCONNECT_COMMAND_3:
14295 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14297 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14298 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14299 break;
14301 if (Rc == OK)
14303 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14304 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14306 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14309 else if (Rc == 0)
14311 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14312 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14314 return;
14320 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14322 word Info;
14323 word internal_command;
14325 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14326 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14328 Info = GOOD;
14329 internal_command = plci->internal_command;
14330 plci->internal_command = 0;
14331 switch (internal_command)
14333 default:
14334 plci->command = 0;
14335 case RTP_CONNECT_B3_REQ_COMMAND_1:
14336 if (plci_nl_busy(plci))
14338 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14339 return;
14341 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14342 nl_req_ncci(plci, N_CONNECT, 0);
14343 send_req(plci);
14344 return;
14345 case RTP_CONNECT_B3_REQ_COMMAND_2:
14346 if ((Rc != OK) && (Rc != OK_FC))
14348 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14349 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14350 Info = _WRONG_STATE;
14351 break;
14353 if (plci_nl_busy(plci))
14355 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14356 return;
14358 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14359 plci->NData[0].PLength = plci->internal_req_buffer[0];
14360 plci->NData[0].P = plci->internal_req_buffer + 1;
14361 plci->NL.X = plci->NData;
14362 plci->NL.ReqCh = 0;
14363 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14364 plci->adapter->request(&plci->NL);
14365 break;
14366 case RTP_CONNECT_B3_REQ_COMMAND_3:
14367 return;
14369 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14373 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14375 word internal_command;
14377 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14378 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14380 internal_command = plci->internal_command;
14381 plci->internal_command = 0;
14382 switch (internal_command)
14384 default:
14385 plci->command = 0;
14386 case RTP_CONNECT_B3_RES_COMMAND_1:
14387 if (plci_nl_busy(plci))
14389 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14390 return;
14392 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14393 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14394 send_req(plci);
14395 return;
14396 case RTP_CONNECT_B3_RES_COMMAND_2:
14397 if ((Rc != OK) && (Rc != OK_FC))
14399 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14400 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14401 break;
14403 if (plci_nl_busy(plci))
14405 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14406 return;
14408 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14409 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14410 plci->NData[0].PLength = plci->internal_req_buffer[0];
14411 plci->NData[0].P = plci->internal_req_buffer + 1;
14412 plci->NL.X = plci->NData;
14413 plci->NL.ReqCh = 0;
14414 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14415 plci->adapter->request(&plci->NL);
14416 return;
14417 case RTP_CONNECT_B3_RES_COMMAND_3:
14418 return;
14424 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14426 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14427 word Info;
14428 word internal_command;
14430 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14431 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14433 Info = GOOD;
14434 internal_command = plci->internal_command;
14435 plci->internal_command = 0;
14436 switch (internal_command)
14438 default:
14439 if (!plci->NL.Id)
14440 break;
14441 plci->command = 0;
14442 plci->adjust_b_parms_msg = NULL;
14443 plci->adjust_b_facilities = plci->B1_facilities;
14444 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14445 plci->adjust_b_ncci = (word)(Id >> 16);
14446 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14447 plci->adjust_b_state = ADJUST_B_START;
14448 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14449 UnMapId(Id), (char *)(FILE_), __LINE__));
14450 case HOLD_SAVE_COMMAND_1:
14451 Info = adjust_b_process(Id, plci, Rc);
14452 if (Info != GOOD)
14454 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14455 UnMapId(Id), (char *)(FILE_), __LINE__));
14456 break;
14458 if (plci->internal_command)
14459 return;
14461 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14465 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14467 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14468 word Info;
14469 word internal_command;
14471 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14472 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14474 Info = GOOD;
14475 internal_command = plci->internal_command;
14476 plci->internal_command = 0;
14477 switch (internal_command)
14479 default:
14480 plci->command = 0;
14481 plci->adjust_b_parms_msg = NULL;
14482 plci->adjust_b_facilities = plci->B1_facilities;
14483 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14484 plci->adjust_b_ncci = (word)(Id >> 16);
14485 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14486 plci->adjust_b_state = ADJUST_B_START;
14487 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14488 UnMapId(Id), (char *)(FILE_), __LINE__));
14489 case RETRIEVE_RESTORE_COMMAND_1:
14490 Info = adjust_b_process(Id, plci, Rc);
14491 if (Info != GOOD)
14493 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14494 UnMapId(Id), (char *)(FILE_), __LINE__));
14495 break;
14497 if (plci->internal_command)
14498 return;
14500 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14504 static void init_b1_config(PLCI *plci)
14507 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14508 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14509 (char *)(FILE_), __LINE__));
14511 plci->B1_resource = 0;
14512 plci->B1_facilities = 0;
14514 plci->li_bchannel_id = 0;
14515 mixer_clear_config(plci);
14518 ec_clear_config(plci);
14521 dtmf_rec_clear_config(plci);
14522 dtmf_send_clear_config(plci);
14523 dtmf_parameter_clear_config(plci);
14525 adv_voice_clear_config(plci);
14526 adjust_b_clear(plci);
14530 static void clear_b1_config(PLCI *plci)
14533 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14534 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14535 (char *)(FILE_), __LINE__));
14537 adv_voice_clear_config(plci);
14538 adjust_b_clear(plci);
14540 ec_clear_config(plci);
14543 dtmf_rec_clear_config(plci);
14544 dtmf_send_clear_config(plci);
14545 dtmf_parameter_clear_config(plci);
14548 if ((plci->li_bchannel_id != 0)
14549 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14551 mixer_clear_config(plci);
14552 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14553 plci->li_bchannel_id = 0;
14556 plci->B1_resource = 0;
14557 plci->B1_facilities = 0;
14561 /* -----------------------------------------------------------------
14562 XON protocol local helpers
14563 ----------------------------------------------------------------- */
14564 static void channel_flow_control_remove(PLCI *plci) {
14565 DIVA_CAPI_ADAPTER *a = plci->adapter;
14566 word i;
14567 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14568 if (a->ch_flow_plci[i] == plci->Id) {
14569 a->ch_flow_plci[i] = 0;
14570 a->ch_flow_control[i] = 0;
14575 static void channel_x_on(PLCI *plci, byte ch) {
14576 DIVA_CAPI_ADAPTER *a = plci->adapter;
14577 if (a->ch_flow_control[ch] & N_XON_SENT) {
14578 a->ch_flow_control[ch] &= ~N_XON_SENT;
14582 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14583 DIVA_CAPI_ADAPTER *a = plci->adapter;
14584 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14585 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14586 a->ch_flow_plci[ch] = plci->Id;
14587 a->ch_flow_control_pending++;
14591 static void channel_request_xon(PLCI *plci, byte ch) {
14592 DIVA_CAPI_ADAPTER *a = plci->adapter;
14594 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14595 a->ch_flow_control[ch] |= N_XON_REQ;
14596 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14597 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14601 static void channel_xmit_extended_xon(PLCI *plci) {
14602 DIVA_CAPI_ADAPTER *a;
14603 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14604 int i, one_requested = 0;
14606 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14607 return;
14610 for (i = 0; i < max_ch; i++) {
14611 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14612 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14613 (plci->Id == a->ch_flow_plci[i])) {
14614 channel_request_xon(plci, (byte)i);
14615 one_requested = 1;
14619 if (one_requested) {
14620 channel_xmit_xon(plci);
14625 Try to xmit next X_ON
14627 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14628 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14629 int i;
14631 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14632 return (0);
14635 if (a->last_flow_control_ch >= max_ch) {
14636 a->last_flow_control_ch = 1;
14638 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14639 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14640 (plci->Id == a->ch_flow_plci[i])) {
14641 a->last_flow_control_ch = i + 1;
14642 return (i);
14646 for (i = 1; i < a->last_flow_control_ch; i++) {
14647 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14648 (plci->Id == a->ch_flow_plci[i])) {
14649 a->last_flow_control_ch = i + 1;
14650 return (i);
14654 return (0);
14657 static void channel_xmit_xon(PLCI *plci) {
14658 DIVA_CAPI_ADAPTER *a = plci->adapter;
14659 byte ch;
14661 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14662 return;
14664 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14665 return;
14667 a->ch_flow_control[ch] &= ~N_XON_REQ;
14668 a->ch_flow_control[ch] |= N_XON_SENT;
14670 plci->NL.Req = plci->nl_req = (byte)N_XON;
14671 plci->NL.ReqCh = ch;
14672 plci->NL.X = plci->NData;
14673 plci->NL.XNum = 1;
14674 plci->NData[0].P = &plci->RBuffer[0];
14675 plci->NData[0].PLength = 0;
14677 plci->adapter->request(&plci->NL);
14680 static int channel_can_xon(PLCI *plci, byte ch) {
14681 APPL *APPLptr;
14682 DIVA_CAPI_ADAPTER *a;
14683 word NCCIcode;
14684 dword count;
14685 word Num;
14686 word i;
14688 APPLptr = plci->appl;
14689 a = plci->adapter;
14691 if (!APPLptr)
14692 return (0);
14694 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14696 /* count all buffers within the Application pool */
14697 /* belonging to the same NCCI. XON if a first is */
14698 /* used. */
14699 count = 0;
14700 Num = 0xffff;
14701 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14702 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14703 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14705 if ((count > 2) || (Num == 0xffff)) {
14706 return (0);
14708 return (1);
14712 /*------------------------------------------------------------------*/
14714 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14716 return 1;
14721 /**********************************************************************************/
14722 /* function groups the listening applications according to the CIP mask and the */
14723 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14724 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14725 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14726 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14727 /* OS specific part (per adapter). */
14728 /**********************************************************************************/
14729 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14731 word i, j, k, busy, group_found;
14732 dword info_mask_group[MAX_CIP_TYPES];
14733 dword cip_mask_group[MAX_CIP_TYPES];
14734 word appl_number_group_type[MAX_APPL];
14735 PLCI *auxplci;
14737 set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14739 if (!a->group_optimization_enabled)
14741 dbug(1, dprintf("No group optimization"));
14742 return;
14745 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14747 for (i = 0; i < MAX_CIP_TYPES; i++)
14749 info_mask_group[i] = 0;
14750 cip_mask_group[i] = 0;
14752 for (i = 0; i < MAX_APPL; i++)
14754 appl_number_group_type[i] = 0;
14756 for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14757 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14758 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14760 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14761 return; /* allow good application unfiltered access */
14764 for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14766 if (application[i].Id && a->CIP_Mask[i])
14768 for (k = 0, busy = false; k < a->max_plci; k++)
14770 if (a->plci[k].Id)
14772 auxplci = &a->plci[k];
14773 if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14775 busy = true;
14776 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14778 else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14780 busy = true;
14781 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14786 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14788 if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14789 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14790 appl_number_group_type[i] = MAX_CIP_TYPES;
14791 group_found = true;
14792 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14794 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14795 { /* is group already present ? */
14796 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14797 group_found = true;
14798 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]));
14800 else if (!info_mask_group[j])
14801 { /* establish a new group */
14802 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14803 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14804 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14805 group_found = true;
14806 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]));
14812 for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14814 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14816 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14818 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14820 else
14822 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14823 for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14825 if (appl_number_group_type[i] == appl_number_group_type[j])
14827 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14828 clear_group_ind_mask_bit(plci, j); /* disable call on other group members */
14829 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14834 else /* application should not get a call */
14836 clear_group_ind_mask_bit(plci, i);
14844 /* OS notifies the driver about a application Capi_Register */
14845 word CapiRegister(word id)
14847 word i, j, appls_found;
14849 PLCI *plci;
14850 DIVA_CAPI_ADAPTER *a;
14852 for (i = 0, appls_found = 0; i < max_appl; i++)
14854 if (application[i].Id && (application[i].Id != id))
14856 appls_found++; /* an application has been found */
14860 if (appls_found) return true;
14861 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14863 a = &adapter[i];
14864 if (a->request)
14866 if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14868 if (!appls_found) /* first application does a capi register */
14870 if ((j = get_plci(a))) /* activate L1 of all adapters */
14872 plci = &a->plci[j - 1];
14873 plci->command = 0;
14874 add_p(plci, OAD, "\x01\xfd");
14875 add_p(plci, CAI, "\x01\x80");
14876 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14877 add_p(plci, SHIFT | 6, NULL);
14878 add_p(plci, SIN, "\x02\x00\x00");
14879 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14880 sig_req(plci, ASSIGN, DSIG_ID);
14881 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14882 sig_req(plci, SIG_CTRL, 0);
14883 send_req(plci);
14889 return false;
14892 /*------------------------------------------------------------------*/
14894 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14896 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14898 word i;
14899 /* Format of vswitch_t:
14900 0 byte length
14901 1 byte VSWITCHIE
14902 2 byte VSWITCH_REQ/VSWITCH_IND
14903 3 byte reserved
14904 4 word VSwitchcommand
14905 6 word returnerror
14906 8... Params
14908 if (!plci ||
14909 !plci->appl ||
14910 !plci->State ||
14911 plci->Sig.Ind == NCR_FACILITY
14913 return;
14915 for (i = 0; i < MAX_MULTI_IE; i++)
14917 if (!parms[i][0]) continue;
14918 if (parms[i][0] < 7)
14920 parms[i][0] = 0; /* kill it */
14921 continue;
14923 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14924 switch (parms[i][4])
14926 case VSJOIN:
14927 if (!plci->relatedPTYPLCI ||
14928 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14929 { /* Error */
14930 break;
14932 /* remember all necessary informations */
14933 if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14935 break;
14937 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14938 { /* first indication after ECT-Request on Consultation Call */
14939 plci->vswitchstate = parms[i][9];
14940 parms[i][9] = 2; /* State */
14941 /* now ask first Call to join */
14943 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14944 { /* Answer of VSWITCH_REQ from first Call */
14945 plci->vswitchstate = parms[i][9];
14946 /* tell consultation call to join
14947 and the protocol capabilities of the first call */
14949 else
14950 { /* Error */
14951 break;
14953 plci->vsprot = parms[i][10]; /* protocol */
14954 plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14955 /* send join request to related PLCI */
14956 parms[i][1] = VSWITCHIE;
14957 parms[i][2] = VSWITCH_REQ;
14959 plci->relatedPTYPLCI->command = 0;
14960 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14961 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14962 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14963 send_req(plci->relatedPTYPLCI);
14964 break;
14965 case VSTRANSPORT:
14966 default:
14967 if (plci->relatedPTYPLCI &&
14968 plci->vswitchstate == 3 &&
14969 plci->relatedPTYPLCI->vswitchstate == 3)
14971 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14972 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14973 send_req(plci->relatedPTYPLCI);
14975 break;
14977 parms[i][0] = 0; /* kill it */
14982 /*------------------------------------------------------------------*/
14984 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14985 ENTITY e;
14986 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14988 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14989 return (-1);
14992 pReq->xdi_dma_descriptor_operation.Req = 0;
14993 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14995 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14996 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14997 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14998 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15000 e.user[0] = plci->adapter->Id - 1;
15001 plci->adapter->request((ENTITY *)pReq);
15003 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15004 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15005 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15006 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15007 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15008 plci->adapter->Id,
15009 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15010 *dma_magic));
15011 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15012 } else {
15013 dbug(1, dprintf("dma_alloc failed"));
15014 return (-1);
15018 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15019 ENTITY e;
15020 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15022 if (nr < 0) {
15023 return;
15026 pReq->xdi_dma_descriptor_operation.Req = 0;
15027 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15029 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15030 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15031 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15032 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15034 e.user[0] = plci->adapter->Id - 1;
15035 plci->adapter->request((ENTITY *)pReq);
15037 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15038 dbug(1, dprintf("dma_free(%d)", nr));
15039 } else {
15040 dbug(1, dprintf("dma_free failed (%d)", nr));
15044 /*------------------------------------------------------------------*/