added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / isdn / hardware / eicon / message.c
blob3378c6f040d578eed882dac8ea6afc0c4d99af89
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;
555 i<(sizeof(ftable)/sizeof(struct _ftable));
556 i++) {
558 if(ftable[i].command==msg->header.command) {
559 /* break loop if the message is correct, otherwise continue scan */
560 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
561 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
562 ret = 0;
563 break;
565 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
568 if(ret) {
569 dbug(1,dprintf("BAD_MSG"));
570 if(plci) plci->command = 0;
571 return ret;
575 c = ftable[i].function(GET_DWORD(&msg->header.controller),
576 msg->header.number,
578 plci,
579 appl,
580 msg_parms);
582 channel_xmit_extended_xon (plci);
584 if(c==1) send_req(plci);
585 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586 if(plci && !plci->req_in) plci->command = 0;
587 return 0;
591 /*------------------------------------------------------------------*/
592 /* api_parse function, check the format of api messages */
593 /*------------------------------------------------------------------*/
595 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
597 word i;
598 word p;
600 for(i=0,p=0; format[i]; i++) {
601 if(parms)
603 parms[i].info = &msg[p];
605 switch(format[i]) {
606 case 'b':
607 p +=1;
608 break;
609 case 'w':
610 p +=2;
611 break;
612 case 'd':
613 p +=4;
614 break;
615 case 's':
616 if(msg[p]==0xff) {
617 parms[i].info +=2;
618 parms[i].length = msg[p+1] + (msg[p+2]<<8);
619 p +=(parms[i].length +3);
621 else {
622 parms[i].length = msg[p];
623 p +=(parms[i].length +1);
625 break;
628 if(p>length) return true;
630 if(parms) parms[i].info = NULL;
631 return false;
634 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
636 word i, j, n = 0;
637 byte *p;
639 p = out->info;
640 for (i = 0; format[i] != '\0'; i++)
642 out->parms[i].info = p;
643 out->parms[i].length = in[i].length;
644 switch (format[i])
646 case 'b':
647 n = 1;
648 break;
649 case 'w':
650 n = 2;
651 break;
652 case 'd':
653 n = 4;
654 break;
655 case 's':
656 n = in[i].length + 1;
657 break;
659 for (j = 0; j < n; j++)
660 *(p++) = in[i].info[j];
662 out->parms[i].info = NULL;
663 out->parms[i].length = 0;
666 static void api_load_msg(API_SAVE *in, API_PARSE *out)
668 word i;
670 i = 0;
673 out[i].info = in->parms[i].info;
674 out[i].length = in->parms[i].length;
675 } while (in->parms[i++].info);
679 /*------------------------------------------------------------------*/
680 /* CAPI remove function */
681 /*------------------------------------------------------------------*/
683 word api_remove_start(void)
685 word i;
686 word j;
688 if(!remove_started) {
689 remove_started = true;
690 for(i=0;i<max_adapter;i++) {
691 if(adapter[i].request) {
692 for(j=0;j<adapter[i].max_plci;j++) {
693 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
697 return 1;
699 else {
700 for(i=0;i<max_adapter;i++) {
701 if(adapter[i].request) {
702 for(j=0;j<adapter[i].max_plci;j++) {
703 if(adapter[i].plci[j].Sig.Id) return 1;
708 api_remove_complete();
709 return 0;
713 /*------------------------------------------------------------------*/
714 /* internal command queue */
715 /*------------------------------------------------------------------*/
717 static void init_internal_command_queue (PLCI *plci)
719 word i;
721 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722 (char *)(FILE_), __LINE__));
724 plci->internal_command = 0;
725 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726 plci->internal_command_queue[i] = NULL;
730 static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
732 word i;
734 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735 UnMapId (Id), (char *)(FILE_), __LINE__));
737 if (plci->internal_command == 0)
739 plci->internal_command_queue[0] = command_function;
740 (* command_function)(Id, plci, OK);
742 else
744 i = 1;
745 while (plci->internal_command_queue[i] != NULL)
746 i++;
747 plci->internal_command_queue[i] = command_function;
752 static void next_internal_command (dword Id, PLCI *plci)
754 word i;
756 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757 UnMapId (Id), (char *)(FILE_), __LINE__));
759 plci->internal_command = 0;
760 plci->internal_command_queue[0] = NULL;
761 while (plci->internal_command_queue[1] != NULL)
763 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766 (*(plci->internal_command_queue[0]))(Id, plci, OK);
767 if (plci->internal_command != 0)
768 return;
769 plci->internal_command_queue[0] = NULL;
774 /*------------------------------------------------------------------*/
775 /* NCCI allocate/remove function */
776 /*------------------------------------------------------------------*/
778 static dword ncci_mapping_bug = 0;
780 static word get_ncci (PLCI *plci, byte ch, word force_ncci)
782 DIVA_CAPI_ADAPTER *a;
783 word ncci, i, j, k;
785 a = plci->adapter;
786 if (!ch || a->ch_ncci[ch])
788 ncci_mapping_bug++;
789 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
791 ncci = ch;
793 else
795 if (force_ncci)
796 ncci = force_ncci;
797 else
799 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
800 ncci = ch;
801 else
803 ncci = 1;
804 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
805 ncci++;
806 if (ncci == MAX_NCCI+1)
808 ncci_mapping_bug++;
809 i = 1;
812 j = 1;
813 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
814 j++;
815 k = j;
816 if (j < MAX_NCCI+1)
820 j++;
821 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
823 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824 if (i < MAX_NL_CHANNEL+1)
826 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827 ncci_mapping_bug, ch, force_ncci, i, k, j));
829 else
831 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832 ncci_mapping_bug, ch, force_ncci));
834 ncci = ch;
837 a->ncci_plci[ncci] = plci->Id;
838 a->ncci_state[ncci] = IDLE;
839 if (!plci->ncci_ring_list)
840 plci->ncci_ring_list = ncci;
841 else
842 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
845 a->ncci_ch[ncci] = ch;
846 a->ch_ncci[ch] = (byte) ncci;
847 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848 ncci_mapping_bug, ch, force_ncci, ch, ncci));
850 return (ncci);
854 static void ncci_free_receive_buffers (PLCI *plci, word ncci)
856 DIVA_CAPI_ADAPTER *a;
857 APPL *appl;
858 word i, ncci_code;
859 dword Id;
861 a = plci->adapter;
862 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863 if (ncci)
865 if (a->ncci_plci[ncci] == plci->Id)
867 if (!plci->appl)
869 ncci_mapping_bug++;
870 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871 ncci_mapping_bug, Id));
873 else
875 appl = plci->appl;
876 ncci_code = ncci | (((word) a->Id) << 8);
877 for (i = 0; i < appl->MaxBuffer; i++)
879 if ((appl->DataNCCI[i] == ncci_code)
880 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
882 appl->DataNCCI[i] = 0;
888 else
890 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
892 if (a->ncci_plci[ncci] == plci->Id)
894 if (!plci->appl)
896 ncci_mapping_bug++;
897 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898 ncci_mapping_bug, Id));
900 else
902 appl = plci->appl;
903 ncci_code = ncci | (((word) a->Id) << 8);
904 for (i = 0; i < appl->MaxBuffer; i++)
906 if ((appl->DataNCCI[i] == ncci_code)
907 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
909 appl->DataNCCI[i] = 0;
919 static void cleanup_ncci_data (PLCI *plci, word ncci)
921 NCCI *ncci_ptr;
923 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
925 ncci_ptr = &(plci->adapter->ncci[ncci]);
926 if (plci->appl)
928 while (ncci_ptr->data_pending != 0)
930 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932 (ncci_ptr->data_out)++;
933 if (ncci_ptr->data_out == MAX_DATA_B3)
934 ncci_ptr->data_out = 0;
935 (ncci_ptr->data_pending)--;
938 ncci_ptr->data_out = 0;
939 ncci_ptr->data_pending = 0;
940 ncci_ptr->data_ack_out = 0;
941 ncci_ptr->data_ack_pending = 0;
946 static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
948 DIVA_CAPI_ADAPTER *a;
949 dword Id;
950 word i;
952 a = plci->adapter;
953 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
954 if (!preserve_ncci)
955 ncci_free_receive_buffers (plci, ncci);
956 if (ncci)
958 if (a->ncci_plci[ncci] != plci->Id)
960 ncci_mapping_bug++;
961 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962 ncci_mapping_bug, Id, preserve_ncci));
964 else
966 cleanup_ncci_data (plci, ncci);
967 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969 a->ch_ncci[a->ncci_ch[ncci]] = 0;
970 if (!preserve_ncci)
972 a->ncci_ch[ncci] = 0;
973 a->ncci_plci[ncci] = 0;
974 a->ncci_state[ncci] = IDLE;
975 i = plci->ncci_ring_list;
976 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
977 i = a->ncci_next[i];
978 if ((i != 0) && (a->ncci_next[i] == ncci))
980 if (i == ncci)
981 plci->ncci_ring_list = 0;
982 else if (plci->ncci_ring_list == ncci)
983 plci->ncci_ring_list = i;
984 a->ncci_next[i] = a->ncci_next[ncci];
986 a->ncci_next[ncci] = 0;
990 else
992 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
994 if (a->ncci_plci[ncci] == plci->Id)
996 cleanup_ncci_data (plci, ncci);
997 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000 if (!preserve_ncci)
1002 a->ncci_ch[ncci] = 0;
1003 a->ncci_plci[ncci] = 0;
1004 a->ncci_state[ncci] = IDLE;
1005 a->ncci_next[ncci] = 0;
1009 if (!preserve_ncci)
1010 plci->ncci_ring_list = 0;
1015 /*------------------------------------------------------------------*/
1016 /* PLCI remove function */
1017 /*------------------------------------------------------------------*/
1019 static void plci_free_msg_in_queue (PLCI *plci)
1021 word i;
1023 if (plci->appl)
1025 i = plci->msg_in_read_pos;
1026 while (i != plci->msg_in_write_pos)
1028 if (i == plci->msg_in_wrap_pos)
1029 i = 0;
1030 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1033 TransmitBufferFree (plci->appl,
1034 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1038 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1039 MSG_IN_OVERHEAD + 3) & 0xfffc;
1043 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1049 static void plci_remove(PLCI * plci)
1052 if(!plci) {
1053 dbug(1,dprintf("plci_remove(no plci)"));
1054 return;
1056 init_internal_command_queue (plci);
1057 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058 if(plci_remove_check(plci))
1060 return;
1062 if (plci->Sig.Id == 0xff)
1064 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065 if (plci->NL.Id && !plci->nl_remove_id)
1067 nl_req_ncci(plci,REMOVE,0);
1068 send_req(plci);
1071 else
1073 if (!plci->sig_remove_id
1074 && (plci->Sig.Id
1075 || (plci->req_in!=plci->req_out)
1076 || (plci->nl_req || plci->sig_req)))
1078 sig_req(plci,HANGUP,0);
1079 send_req(plci);
1082 ncci_remove (plci, 0, false);
1083 plci_free_msg_in_queue (plci);
1085 plci->channels = 0;
1086 plci->appl = NULL;
1087 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088 plci->State = OUTG_DIS_PENDING;
1091 /*------------------------------------------------------------------*/
1092 /* Application Group function helpers */
1093 /*------------------------------------------------------------------*/
1095 static void set_group_ind_mask (PLCI *plci)
1097 word i;
1099 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100 plci->group_optimization_mask_table[i] = 0xffffffffL;
1103 static void clear_group_ind_mask_bit (PLCI *plci, word b)
1105 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1108 static byte test_group_ind_mask_bit (PLCI *plci, word b)
1110 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1113 /*------------------------------------------------------------------*/
1114 /* c_ind_mask operations for arbitrary MAX_APPL */
1115 /*------------------------------------------------------------------*/
1117 static void clear_c_ind_mask (PLCI *plci)
1119 word i;
1121 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122 plci->c_ind_mask_table[i] = 0;
1125 static byte c_ind_mask_empty (PLCI *plci)
1127 word i;
1129 i = 0;
1130 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131 i++;
1132 return (i == C_IND_MASK_DWORDS);
1135 static void set_c_ind_mask_bit (PLCI *plci, word b)
1137 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1140 static void clear_c_ind_mask_bit (PLCI *plci, word b)
1142 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1145 static byte test_c_ind_mask_bit (PLCI *plci, word b)
1147 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1150 static void dump_c_ind_mask (PLCI *plci)
1152 static char hex_digit_table[0x10] =
1153 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154 word i, j, k;
1155 dword d;
1156 char *p;
1157 char buf[40];
1159 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1161 p = buf + 36;
1162 *p = '\0';
1163 for (j = 0; j < 4; j++)
1165 if (i+j < C_IND_MASK_DWORDS)
1167 d = plci->c_ind_mask_table[i+j];
1168 for (k = 0; k < 8; k++)
1170 *(--p) = hex_digit_table[d & 0xf];
1171 d >>= 4;
1174 else if (i != 0)
1176 for (k = 0; k < 8; k++)
1177 *(--p) = ' ';
1179 *(--p) = ' ';
1181 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1189 #define dump_plcis(a)
1193 /*------------------------------------------------------------------*/
1194 /* translation function for each message */
1195 /*------------------------------------------------------------------*/
1197 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1199 word ch;
1200 word i;
1201 word Info;
1202 word CIP;
1203 byte LinkLayer;
1204 API_PARSE * ai;
1205 API_PARSE * bp;
1206 API_PARSE ai_parms[5];
1207 word channel = 0;
1208 dword ch_mask;
1209 byte m;
1210 static byte esc_chi[35] = {0x02,0x18,0x01};
1211 static byte lli[2] = {0x01,0x00};
1212 byte noCh = 0;
1213 word dir = 0;
1214 byte *p_chi = "";
1216 for(i=0;i<5;i++) ai_parms[i].length = 0;
1218 dbug(1,dprintf("connect_req(%d)",parms->length));
1219 Info = _WRONG_IDENTIFIER;
1220 if(a)
1222 if(a->adapter_disabled)
1224 dbug(1,dprintf("adapter disabled"));
1225 Id = ((word)1<<8)|a->Id;
1226 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1228 return false;
1230 Info = _OUT_OF_PLCI;
1231 if((i=get_plci(a)))
1233 Info = 0;
1234 plci = &a->plci[i-1];
1235 plci->appl = appl;
1236 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237 /* check 'external controller' bit for codec support */
1238 if(Id & EXT_CONTROLLER)
1240 if(AdvCodecSupport(a, plci, appl, 0) )
1242 plci->Id = 0;
1243 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1244 return 2;
1247 ai = &parms[9];
1248 bp = &parms[5];
1249 ch = 0;
1250 if(bp->length)LinkLayer = bp->info[3];
1251 else LinkLayer = 0;
1252 if(ai->length)
1254 ch=0xffff;
1255 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1257 ch = 0;
1258 if(ai_parms[0].length)
1260 ch = GET_WORD(ai_parms[0].info+1);
1261 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262 if(ch==4) /* explizit CHI in message */
1264 /* check length of B-CH struct */
1265 if((ai_parms[0].info)[3]>=1)
1267 if((ai_parms[0].info)[4]==CHI)
1269 p_chi = &((ai_parms[0].info)[5]);
1271 else
1273 p_chi = &((ai_parms[0].info)[3]);
1275 if(p_chi[0]>35) /* check length of channel ID */
1277 Info = _WRONG_MESSAGE_FORMAT;
1280 else Info = _WRONG_MESSAGE_FORMAT;
1283 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285 dir = GET_WORD(ai_parms[0].info+3);
1286 ch_mask = 0;
1287 m = 0x3f;
1288 for(i=0; i+5<=ai_parms[0].length; i++)
1290 if(ai_parms[0].info[i+5]!=0)
1292 if((ai_parms[0].info[i+5] | m) != 0xff)
1293 Info = _WRONG_MESSAGE_FORMAT;
1294 else
1296 if (ch_mask == 0)
1297 channel = i;
1298 ch_mask |= 1L << i;
1301 m = 0;
1303 if (ch_mask == 0)
1304 Info = _WRONG_MESSAGE_FORMAT;
1305 if (!Info)
1307 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310 for(i=0; i+5<=ai_parms[0].length; i++)
1311 esc_chi[i+3] = ai_parms[0].info[i+5];
1313 else
1314 esc_chi[0] = 2;
1315 esc_chi[2] = (byte)channel;
1316 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317 add_p(plci,LLI,lli);
1318 add_p(plci,ESC,esc_chi);
1319 plci->State = LOCAL_CONNECT;
1320 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1325 else Info = _WRONG_MESSAGE_FORMAT;
1328 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329 plci->command = _CONNECT_R;
1330 plci->number = Number;
1331 /* x.31 or D-ch free SAPI in LinkLayer? */
1332 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1333 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335 /* B-channel used for B3 connections (ch==0), or no B channel */
1336 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1337 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1338 else Info = add_b1(plci,&parms[5],ch,0);
1339 add_s(plci,OAD,&parms[2]);
1340 add_s(plci,OSA,&parms[4]);
1341 add_s(plci,BC,&parms[6]);
1342 add_s(plci,LLC,&parms[7]);
1343 add_s(plci,HLC,&parms[8]);
1344 CIP = GET_WORD(parms[0].info);
1345 if (a->Info_Mask[appl->Id-1] & 0x200)
1347 /* early B3 connect (CIP mask bit 9) no release after a disc */
1348 add_p(plci,LLI,"\x01\x01");
1350 if(GET_WORD(parms[0].info)<29) {
1351 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355 sig_req(plci,ASSIGN,DSIG_ID);
1357 else if(ch==1) {
1359 /* D-Channel used for B3 connections */
1360 plci->Sig.Id = 0xff;
1361 Info = 0;
1364 if(!Info && ch!=2 && !noCh ) {
1365 Info = add_b23(plci,&parms[5]);
1366 if(!Info) {
1367 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1371 if(!Info)
1373 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378 plci->spoofed_msg = CALL_REQ;
1379 plci->internal_command = BLOCK_PLCI;
1380 plci->command = 0;
1381 dbug(1,dprintf("Spoof"));
1382 send_req(plci);
1383 return false;
1385 if(ch==4)add_p(plci,CHI,p_chi);
1386 add_s(plci,CPN,&parms[1]);
1387 add_s(plci,DSA,&parms[3]);
1388 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1389 add_ai(plci,&parms[9]);
1390 if(!dir)sig_req(plci,CALL_REQ,0);
1391 else
1393 plci->command = PERM_LIST_REQ;
1394 plci->appl = appl;
1395 sig_req(plci,LISTEN_REQ,0);
1396 send_req(plci);
1397 return false;
1400 send_req(plci);
1401 return false;
1403 plci->Id = 0;
1406 sendf(appl,
1407 _CONNECT_R|CONFIRM,
1409 Number,
1410 "w",Info);
1411 return 2;
1414 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1416 word i, Info;
1417 word Reject;
1418 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420 API_PARSE * ai;
1421 API_PARSE ai_parms[5];
1422 word ch=0;
1424 if(!plci) {
1425 dbug(1,dprintf("connect_res(no plci)"));
1426 return 0; /* no plci, no send */
1429 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430 for(i=0;i<5;i++) ai_parms[i].length = 0;
1431 ai = &parms[5];
1432 dbug(1,dprintf("ai->length=%d",ai->length));
1434 if(ai->length)
1436 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1438 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439 ch = 0;
1440 if(ai_parms[0].length)
1442 ch = GET_WORD(ai_parms[0].info+1);
1443 dbug(1,dprintf("BCH-I=0x%x",ch));
1448 if(plci->State==INC_CON_CONNECTED_ALERT)
1450 dbug(1,dprintf("Connected Alert Call_Res"));
1451 if (a->Info_Mask[appl->Id-1] & 0x200)
1453 /* early B3 connect (CIP mask bit 9) no release after a disc */
1454 add_p(plci,LLI,"\x01\x01");
1456 add_s(plci, CONN_NR, &parms[2]);
1457 add_s(plci, LLC, &parms[4]);
1458 add_ai(plci, &parms[5]);
1459 plci->State = INC_CON_ACCEPT;
1460 sig_req(plci, CALL_RES,0);
1461 return 1;
1463 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465 dump_c_ind_mask (plci);
1466 Reject = GET_WORD(parms[0].info);
1467 dbug(1,dprintf("Reject=0x%x",Reject));
1468 if(Reject)
1470 if(c_ind_mask_empty (plci))
1472 if((Reject&0xff00)==0x3400)
1474 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475 add_p(plci,ESC,esc_t);
1476 add_ai(plci, &parms[5]);
1477 sig_req(plci,REJECT,0);
1479 else if(Reject==1 || Reject>9)
1481 add_ai(plci, &parms[5]);
1482 sig_req(plci,HANGUP,0);
1484 else
1486 esc_t[2] = cau_t[(Reject&0x000f)];
1487 add_p(plci,ESC,esc_t);
1488 add_ai(plci, &parms[5]);
1489 sig_req(plci,REJECT,0);
1491 plci->appl = appl;
1493 else
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1498 else {
1499 plci->appl = appl;
1500 if(Id & EXT_CONTROLLER){
1501 if(AdvCodecSupport(a, plci, appl, 0)){
1502 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503 sig_req(plci,HANGUP,0);
1504 return 1;
1506 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508 Info = add_b23(plci, &parms[1]);
1509 if (Info)
1511 dbug(1,dprintf("connect_res(error from add_b23)"));
1512 sig_req(plci,HANGUP,0);
1513 return 1;
1515 if(plci->adv_nl)
1517 nl_req_ncci(plci, ASSIGN, 0);
1521 else
1523 plci->tel = 0;
1524 if(ch!=2)
1526 Info = add_b23(plci, &parms[1]);
1527 if (Info)
1529 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530 sig_req(plci,HANGUP,0);
1531 return 1;
1534 nl_req_ncci(plci, ASSIGN, 0);
1537 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1539 api_save_msg(parms, "wsssss", &plci->saved_msg);
1540 plci->spoofed_msg = CALL_RES;
1541 plci->internal_command = BLOCK_PLCI;
1542 plci->command = 0;
1543 dbug(1,dprintf("Spoof"));
1545 else
1547 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548 if (a->Info_Mask[appl->Id-1] & 0x200)
1550 /* early B3 connect (CIP mask bit 9) no release after a disc */
1551 add_p(plci,LLI,"\x01\x01");
1553 add_s(plci, CONN_NR, &parms[2]);
1554 add_s(plci, LLC, &parms[4]);
1555 add_ai(plci, &parms[5]);
1556 plci->State = INC_CON_ACCEPT;
1557 sig_req(plci, CALL_RES,0);
1560 for(i=0; i<max_appl; i++) {
1561 if(test_c_ind_mask_bit (plci, i)) {
1562 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1567 return 1;
1570 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1572 dbug(1,dprintf("connect_a_res"));
1573 return false;
1576 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1578 word Info;
1579 word i;
1581 dbug(1,dprintf("disconnect_req"));
1583 Info = _WRONG_IDENTIFIER;
1585 if(plci)
1587 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1589 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1590 plci->appl = appl;
1591 for(i=0; i<max_appl; i++)
1593 if(test_c_ind_mask_bit (plci, i))
1594 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596 plci->State = OUTG_DIS_PENDING;
1598 if(plci->Sig.Id && plci->appl)
1600 Info = 0;
1601 if(plci->Sig.Id!=0xff)
1603 if(plci->State!=INC_DIS_PENDING)
1605 add_ai(plci, &msg[0]);
1606 sig_req(plci,HANGUP,0);
1607 plci->State = OUTG_DIS_PENDING;
1608 return 1;
1611 else
1613 if (plci->NL.Id && !plci->nl_remove_id)
1615 mixer_remove (plci);
1616 nl_req_ncci(plci,REMOVE,0);
1617 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619 plci->State = INC_DIS_PENDING;
1621 return 1;
1626 if(!appl) return false;
1627 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1628 return false;
1631 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1633 dbug(1,dprintf("disconnect_res"));
1634 if(plci)
1636 /* clear ind mask bit, just in case of collsion of */
1637 /* DISCONNECT_IND and CONNECT_RES */
1638 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639 ncci_free_receive_buffers (plci, 0);
1640 if(plci_remove_check(plci))
1642 return 0;
1644 if(plci->State==INC_DIS_PENDING
1645 || plci->State==SUSPENDING) {
1646 if(c_ind_mask_empty (plci)) {
1647 if(plci->State!=SUSPENDING)plci->State = IDLE;
1648 dbug(1,dprintf("chs=%d",plci->channels));
1649 if(!plci->channels) {
1650 plci_remove(plci);
1655 return 0;
1658 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, 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 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1709 word i;
1710 API_PARSE * ai;
1711 PLCI * rc_plci = NULL;
1712 API_PARSE ai_parms[5];
1713 word Info = 0;
1715 dbug(1,dprintf("info_req"));
1716 for(i=0;i<5;i++) ai_parms[i].length = 0;
1718 ai = &msg[1];
1720 if(ai->length)
1722 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1724 dbug(1,dprintf("AddInfo wrong"));
1725 Info = _WRONG_MESSAGE_FORMAT;
1728 if(!a) Info = _WRONG_STATE;
1730 if(!Info && plci)
1731 { /* no fac, with CPN, or KEY */
1732 rc_plci = plci;
1733 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1735 /* overlap sending option */
1736 dbug(1,dprintf("OvlSnd"));
1737 add_s(plci,CPN,&msg[0]);
1738 add_s(plci,KEY,&ai_parms[1]);
1739 sig_req(plci,INFO_REQ,0);
1740 send_req(plci);
1741 return false;
1744 if(plci->State && ai_parms[2].length)
1746 /* User_Info option */
1747 dbug(1,dprintf("UUI"));
1748 add_s(plci,UUI,&ai_parms[2]);
1749 sig_req(plci,USER_DATA,0);
1751 else if(plci->State && ai_parms[3].length)
1753 /* Facility option */
1754 dbug(1,dprintf("FAC"));
1755 add_s(plci,CPN,&msg[0]);
1756 add_ai(plci, &msg[1]);
1757 sig_req(plci,FACILITY_REQ,0);
1759 else
1761 Info = _WRONG_STATE;
1764 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766 /* NCR_Facility option -> send UUI and Keypad too */
1767 dbug(1,dprintf("NCR_FAC"));
1768 if((i=get_plci(a)))
1770 rc_plci = &a->plci[i-1];
1771 appl->NullCREnable = true;
1772 rc_plci->internal_command = C_NCR_FAC_REQ;
1773 rc_plci->appl = appl;
1774 add_p(rc_plci,CAI,"\x01\x80");
1775 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776 sig_req(rc_plci,ASSIGN,DSIG_ID);
1777 send_req(rc_plci);
1779 else
1781 Info = _OUT_OF_PLCI;
1784 if(!Info)
1786 add_s(rc_plci,CPN,&msg[0]);
1787 add_ai(rc_plci, &msg[1]);
1788 sig_req(rc_plci,NCR_FACILITY,0);
1789 send_req(rc_plci);
1790 return false;
1791 /* for application controlled supplementary services */
1795 if (!rc_plci)
1797 Info = _WRONG_MESSAGE_FORMAT;
1800 if(!Info)
1802 send_req(rc_plci);
1804 else
1805 { /* appl is not assigned to a PLCI or error condition */
1806 dbug(1,dprintf("localInfoCon"));
1807 sendf(appl,
1808 _INFO_R|CONFIRM,
1810 Number,
1811 "w",Info);
1813 return false;
1816 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1818 dbug(1,dprintf("info_res"));
1819 return false;
1822 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1824 word Info;
1825 byte ret;
1827 dbug(1,dprintf("alert_req"));
1829 Info = _WRONG_IDENTIFIER;
1830 ret = false;
1831 if(plci) {
1832 Info = _ALERT_IGNORED;
1833 if(plci->State!=INC_CON_ALERT) {
1834 Info = _WRONG_STATE;
1835 if(plci->State==INC_CON_PENDING) {
1836 Info = 0;
1837 plci->State=INC_CON_ALERT;
1838 add_ai(plci, &msg[0]);
1839 sig_req(plci,CALL_ALERT,0);
1840 ret = 1;
1844 sendf(appl,
1845 _ALERT_R|CONFIRM,
1847 Number,
1848 "w",Info);
1849 return ret;
1852 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1854 word Info = 0;
1855 word i = 0;
1857 word selector;
1858 word SSreq;
1859 long relatedPLCIvalue;
1860 DIVA_CAPI_ADAPTER * relatedadapter;
1861 byte * SSparms = "";
1862 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1863 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1864 API_PARSE * parms;
1865 API_PARSE ss_parms[11];
1866 PLCI *rplci;
1867 byte cai[15];
1868 dword d;
1869 API_PARSE dummy;
1871 dbug(1,dprintf("facility_req"));
1872 for(i=0;i<9;i++) ss_parms[i].length = 0;
1874 parms = &msg[1];
1876 if(!a)
1878 dbug(1,dprintf("wrong Ctrl"));
1879 Info = _WRONG_IDENTIFIER;
1882 selector = GET_WORD(msg[0].info);
1884 if(!Info)
1886 switch(selector)
1888 case SELECTOR_HANDSET:
1889 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1890 break;
1892 case SELECTOR_SU_SERV:
1893 if(!msg[1].length)
1895 Info = _WRONG_MESSAGE_FORMAT;
1896 break;
1898 SSreq = GET_WORD(&(msg[1].info[1]));
1899 PUT_WORD(&RCparms[1],SSreq);
1900 SSparms = RCparms;
1901 switch(SSreq)
1903 case S_GET_SUPPORTED_SERVICES:
1904 if((i=get_plci(a)))
1906 rplci = &a->plci[i-1];
1907 rplci->appl = appl;
1908 add_p(rplci,CAI,"\x01\x80");
1909 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910 sig_req(rplci,ASSIGN,DSIG_ID);
1911 send_req(rplci);
1913 else
1915 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916 SSparms = (byte *)SSstruct;
1917 break;
1919 rplci->internal_command = GETSERV_REQ_PEND;
1920 rplci->number = Number;
1921 rplci->appl = appl;
1922 sig_req(rplci,S_SUPPORTED,0);
1923 send_req(rplci);
1924 return false;
1925 break;
1927 case S_LISTEN:
1928 if(parms->length==7)
1930 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1932 dbug(1,dprintf("format wrong"));
1933 Info = _WRONG_MESSAGE_FORMAT;
1934 break;
1937 else
1939 Info = _WRONG_MESSAGE_FORMAT;
1940 break;
1942 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1945 if((i=get_plci(a)))
1947 rplci = &a->plci[i-1];
1948 rplci->appl = appl;
1949 add_p(rplci,CAI,"\x01\x80");
1950 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951 sig_req(rplci,ASSIGN,DSIG_ID);
1952 send_req(rplci);
1954 else
1956 break;
1958 rplci->internal_command = GET_MWI_STATE;
1959 rplci->number = Number;
1960 sig_req(rplci,MWI_POLL,0);
1961 send_req(rplci);
1963 break;
1965 case S_HOLD:
1966 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967 if(plci && plci->State && plci->SuppState==IDLE)
1969 plci->SuppState = HOLD_REQUEST;
1970 plci->command = C_HOLD_REQ;
1971 add_s(plci,CAI,&ss_parms[1]);
1972 sig_req(plci,CALL_HOLD,0);
1973 send_req(plci);
1974 return false;
1976 else Info = 0x3010; /* wrong state */
1977 break;
1978 case S_RETRIEVE:
1979 if(plci && plci->State && plci->SuppState==CALL_HELD)
1981 if(Id & EXT_CONTROLLER)
1983 if(AdvCodecSupport(a, plci, appl, 0))
1985 Info = 0x3010; /* wrong state */
1986 break;
1989 else plci->tel = 0;
1991 plci->SuppState = RETRIEVE_REQUEST;
1992 plci->command = C_RETRIEVE_REQ;
1993 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1995 plci->spoofed_msg = CALL_RETRIEVE;
1996 plci->internal_command = BLOCK_PLCI;
1997 plci->command = 0;
1998 dbug(1,dprintf("Spoof"));
1999 return false;
2001 else
2003 sig_req(plci,CALL_RETRIEVE,0);
2004 send_req(plci);
2005 return false;
2008 else Info = 0x3010; /* wrong state */
2009 break;
2010 case S_SUSPEND:
2011 if(parms->length)
2013 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2015 dbug(1,dprintf("format wrong"));
2016 Info = _WRONG_MESSAGE_FORMAT;
2017 break;
2020 if(plci && plci->State)
2022 add_s(plci,CAI,&ss_parms[2]);
2023 plci->command = SUSPEND_REQ;
2024 sig_req(plci,SUSPEND,0);
2025 plci->State = SUSPENDING;
2026 send_req(plci);
2028 else Info = 0x3010; /* wrong state */
2029 break;
2031 case S_RESUME:
2032 if(!(i=get_plci(a)) )
2034 Info = _OUT_OF_PLCI;
2035 break;
2037 rplci = &a->plci[i-1];
2038 rplci->appl = appl;
2039 rplci->number = Number;
2040 rplci->tel = 0;
2041 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042 /* check 'external controller' bit for codec support */
2043 if(Id & EXT_CONTROLLER)
2045 if(AdvCodecSupport(a, rplci, appl, 0) )
2047 rplci->Id = 0;
2048 Info = 0x300A;
2049 break;
2052 if(parms->length)
2054 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2056 dbug(1,dprintf("format wrong"));
2057 rplci->Id = 0;
2058 Info = _WRONG_MESSAGE_FORMAT;
2059 break;
2062 dummy.length = 0;
2063 dummy.info = "\x00";
2064 add_b1(rplci, &dummy, 0, 0);
2065 if (a->Info_Mask[appl->Id-1] & 0x200)
2067 /* early B3 connect (CIP mask bit 9) no release after a disc */
2068 add_p(rplci,LLI,"\x01\x01");
2070 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071 sig_req(rplci,ASSIGN,DSIG_ID);
2072 send_req(rplci);
2073 add_s(rplci,CAI,&ss_parms[2]);
2074 rplci->command = RESUME_REQ;
2075 sig_req(rplci,RESUME,0);
2076 rplci->State = RESUMING;
2077 send_req(rplci);
2078 break;
2080 case S_CONF_BEGIN: /* Request */
2081 case S_CONF_DROP:
2082 case S_CONF_ISOLATE:
2083 case S_CONF_REATTACH:
2084 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2086 dbug(1,dprintf("format wrong"));
2087 Info = _WRONG_MESSAGE_FORMAT;
2088 break;
2090 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2092 d = GET_DWORD(ss_parms[2].info);
2093 if(d>=0x80)
2095 dbug(1,dprintf("format wrong"));
2096 Info = _WRONG_MESSAGE_FORMAT;
2097 break;
2099 plci->ptyState = (byte)SSreq;
2100 plci->command = 0;
2101 cai[0] = 2;
2102 switch(SSreq)
2104 case S_CONF_BEGIN:
2105 cai[1] = CONF_BEGIN;
2106 plci->internal_command = CONF_BEGIN_REQ_PEND;
2107 break;
2108 case S_CONF_DROP:
2109 cai[1] = CONF_DROP;
2110 plci->internal_command = CONF_DROP_REQ_PEND;
2111 break;
2112 case S_CONF_ISOLATE:
2113 cai[1] = CONF_ISOLATE;
2114 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2115 break;
2116 case S_CONF_REATTACH:
2117 cai[1] = CONF_REATTACH;
2118 plci->internal_command = CONF_REATTACH_REQ_PEND;
2119 break;
2121 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122 add_p(plci,CAI,cai);
2123 sig_req(plci,S_SERVICE,0);
2124 send_req(plci);
2125 return false;
2127 else Info = 0x3010; /* wrong state */
2128 break;
2130 case S_ECT:
2131 case S_3PTY_BEGIN:
2132 case S_3PTY_END:
2133 case S_CONF_ADD:
2134 if(parms->length==7)
2136 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2138 dbug(1,dprintf("format wrong"));
2139 Info = _WRONG_MESSAGE_FORMAT;
2140 break;
2143 else if(parms->length==8) /* workaround for the T-View-S */
2145 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2147 dbug(1,dprintf("format wrong"));
2148 Info = _WRONG_MESSAGE_FORMAT;
2149 break;
2152 else
2154 Info = _WRONG_MESSAGE_FORMAT;
2155 break;
2157 if(!msg[1].length)
2159 Info = _WRONG_MESSAGE_FORMAT;
2160 break;
2162 if (!plci)
2164 Info = _WRONG_IDENTIFIER;
2165 break;
2167 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168 relatedPLCIvalue &= 0x0000FFFF;
2169 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170 /* controller starts with 0 up to (max_adapter - 1) */
2171 if (((relatedPLCIvalue & 0x7f) == 0)
2172 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2175 if(SSreq==S_3PTY_END)
2177 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2178 rplci = plci;
2180 else
2182 Info = 0x3010; /* wrong state */
2183 break;
2186 else
2188 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189 relatedPLCIvalue >>=8;
2190 /* find PLCI PTR*/
2191 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2193 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2195 rplci = &relatedadapter->plci[i];
2198 if(!rplci || !relatedPLCIvalue)
2200 if(SSreq==S_3PTY_END)
2202 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2203 rplci = plci;
2205 else
2207 Info = 0x3010; /* wrong state */
2208 break;
2213 dbug(1,dprintf("rplci:%x",rplci));
2214 dbug(1,dprintf("plci:%x",plci));
2215 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217 dbug(1,dprintf("SSreq:%x",SSreq));
2218 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2222 /* send PTY/ECT req, cannot check all states because of US stuff */
2223 if( !rplci->internal_command && rplci->appl )
2225 plci->command = 0;
2226 rplci->relatedPTYPLCI = plci;
2227 plci->relatedPTYPLCI = rplci;
2228 rplci->ptyState = (byte)SSreq;
2229 if(SSreq==S_ECT)
2231 rplci->internal_command = ECT_REQ_PEND;
2232 cai[1] = ECT_EXECUTE;
2234 rplci->vswitchstate=0;
2235 rplci->vsprot=0;
2236 rplci->vsprotdialect=0;
2237 plci->vswitchstate=0;
2238 plci->vsprot=0;
2239 plci->vsprotdialect=0;
2242 else if(SSreq==S_CONF_ADD)
2244 rplci->internal_command = CONF_ADD_REQ_PEND;
2245 cai[1] = CONF_ADD;
2247 else
2249 rplci->internal_command = PTY_REQ_PEND;
2250 cai[1] = (byte)(SSreq-3);
2252 rplci->number = Number;
2253 if(plci!=rplci) /* explicit invocation */
2255 cai[0] = 2;
2256 cai[2] = plci->Sig.Id;
2257 dbug(1,dprintf("explicit invocation"));
2259 else
2261 dbug(1,dprintf("implicit invocation"));
2262 cai[0] = 1;
2264 add_p(rplci,CAI,cai);
2265 sig_req(rplci,S_SERVICE,0);
2266 send_req(rplci);
2267 return false;
2269 else
2271 dbug(0,dprintf("Wrong line"));
2272 Info = 0x3010; /* wrong state */
2273 break;
2275 break;
2277 case S_CALL_DEFLECTION:
2278 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2280 dbug(1,dprintf("format wrong"));
2281 Info = _WRONG_MESSAGE_FORMAT;
2282 break;
2284 if (!plci)
2286 Info = _WRONG_IDENTIFIER;
2287 break;
2289 /* reuse unused screening indicator */
2290 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2291 plci->command = 0;
2292 plci->internal_command = CD_REQ_PEND;
2293 appl->CDEnable = true;
2294 cai[0] = 1;
2295 cai[1] = CALL_DEFLECTION;
2296 add_p(plci,CAI,cai);
2297 add_p(plci,CPN,ss_parms[3].info);
2298 sig_req(plci,S_SERVICE,0);
2299 send_req(plci);
2300 return false;
2301 break;
2303 case S_CALL_FORWARDING_START:
2304 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2306 dbug(1,dprintf("format wrong"));
2307 Info = _WRONG_MESSAGE_FORMAT;
2308 break;
2311 if((i=get_plci(a)))
2313 rplci = &a->plci[i-1];
2314 rplci->appl = appl;
2315 add_p(rplci,CAI,"\x01\x80");
2316 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317 sig_req(rplci,ASSIGN,DSIG_ID);
2318 send_req(rplci);
2320 else
2322 Info = _OUT_OF_PLCI;
2323 break;
2326 /* reuse unused screening indicator */
2327 rplci->internal_command = CF_START_PEND;
2328 rplci->appl = appl;
2329 rplci->number = Number;
2330 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2331 cai[0] = 2;
2332 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334 add_p(rplci,CAI,cai);
2335 add_p(rplci,OAD,ss_parms[5].info);
2336 add_p(rplci,CPN,ss_parms[6].info);
2337 sig_req(rplci,S_SERVICE,0);
2338 send_req(rplci);
2339 return false;
2340 break;
2342 case S_INTERROGATE_DIVERSION:
2343 case S_INTERROGATE_NUMBERS:
2344 case S_CALL_FORWARDING_STOP:
2345 case S_CCBS_REQUEST:
2346 case S_CCBS_DEACTIVATE:
2347 case S_CCBS_INTERROGATE:
2348 switch(SSreq)
2350 case S_INTERROGATE_NUMBERS:
2351 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2353 dbug(0,dprintf("format wrong"));
2354 Info = _WRONG_MESSAGE_FORMAT;
2356 break;
2357 case S_CCBS_REQUEST:
2358 case S_CCBS_DEACTIVATE:
2359 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2361 dbug(0,dprintf("format wrong"));
2362 Info = _WRONG_MESSAGE_FORMAT;
2364 break;
2365 case S_CCBS_INTERROGATE:
2366 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2368 dbug(0,dprintf("format wrong"));
2369 Info = _WRONG_MESSAGE_FORMAT;
2371 break;
2372 default:
2373 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2375 dbug(0,dprintf("format wrong"));
2376 Info = _WRONG_MESSAGE_FORMAT;
2377 break;
2379 break;
2382 if(Info) break;
2383 if((i=get_plci(a)))
2385 rplci = &a->plci[i-1];
2386 switch(SSreq)
2388 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2391 break;
2392 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2395 break;
2396 case S_CALL_FORWARDING_STOP:
2397 rplci->internal_command = CF_STOP_PEND;
2398 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2399 break;
2400 case S_CCBS_REQUEST:
2401 cai[1] = CCBS_REQUEST;
2402 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2403 break;
2404 case S_CCBS_DEACTIVATE:
2405 cai[1] = CCBS_DEACTIVATE;
2406 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2407 break;
2408 case S_CCBS_INTERROGATE:
2409 cai[1] = CCBS_INTERROGATE;
2410 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2411 break;
2412 default:
2413 cai[1] = 0;
2414 break;
2416 rplci->appl = appl;
2417 rplci->number = Number;
2418 add_p(rplci,CAI,"\x01\x80");
2419 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420 sig_req(rplci,ASSIGN,DSIG_ID);
2421 send_req(rplci);
2423 else
2425 Info = _OUT_OF_PLCI;
2426 break;
2429 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2430 switch(SSreq)
2432 case S_INTERROGATE_NUMBERS:
2433 cai[0] = 1;
2434 add_p(rplci,CAI,cai);
2435 break;
2436 case S_CCBS_REQUEST:
2437 case S_CCBS_DEACTIVATE:
2438 cai[0] = 3;
2439 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440 add_p(rplci,CAI,cai);
2441 break;
2442 case S_CCBS_INTERROGATE:
2443 cai[0] = 3;
2444 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445 add_p(rplci,CAI,cai);
2446 add_p(rplci,OAD,ss_parms[4].info);
2447 break;
2448 default:
2449 cai[0] = 2;
2450 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451 add_p(rplci,CAI,cai);
2452 add_p(rplci,OAD,ss_parms[5].info);
2453 break;
2456 sig_req(rplci,S_SERVICE,0);
2457 send_req(rplci);
2458 return false;
2459 break;
2461 case S_MWI_ACTIVATE:
2462 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2464 dbug(1,dprintf("format wrong"));
2465 Info = _WRONG_MESSAGE_FORMAT;
2466 break;
2468 if(!plci)
2470 if((i=get_plci(a)))
2472 rplci = &a->plci[i-1];
2473 rplci->appl = appl;
2474 rplci->cr_enquiry=true;
2475 add_p(rplci,CAI,"\x01\x80");
2476 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477 sig_req(rplci,ASSIGN,DSIG_ID);
2478 send_req(rplci);
2480 else
2482 Info = _OUT_OF_PLCI;
2483 break;
2486 else
2488 rplci = plci;
2489 rplci->cr_enquiry=false;
2492 rplci->command = 0;
2493 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2494 rplci->appl = appl;
2495 rplci->number = Number;
2497 cai[0] = 13;
2498 cai[1] = ACTIVATION_MWI; /* Function */
2499 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504 add_p(rplci,CAI,cai);
2505 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508 add_p(rplci,UID,ss_parms[10].info); /* Time */
2509 sig_req(rplci,S_SERVICE,0);
2510 send_req(rplci);
2511 return false;
2513 case S_MWI_DEACTIVATE:
2514 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2516 dbug(1,dprintf("format wrong"));
2517 Info = _WRONG_MESSAGE_FORMAT;
2518 break;
2520 if(!plci)
2522 if((i=get_plci(a)))
2524 rplci = &a->plci[i-1];
2525 rplci->appl = appl;
2526 rplci->cr_enquiry=true;
2527 add_p(rplci,CAI,"\x01\x80");
2528 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529 sig_req(rplci,ASSIGN,DSIG_ID);
2530 send_req(rplci);
2532 else
2534 Info = _OUT_OF_PLCI;
2535 break;
2538 else
2540 rplci = plci;
2541 rplci->cr_enquiry=false;
2544 rplci->command = 0;
2545 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2546 rplci->appl = appl;
2547 rplci->number = Number;
2549 cai[0] = 5;
2550 cai[1] = DEACTIVATION_MWI; /* Function */
2551 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553 add_p(rplci,CAI,cai);
2554 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556 sig_req(rplci,S_SERVICE,0);
2557 send_req(rplci);
2558 return false;
2560 default:
2561 Info = 0x300E; /* not supported */
2562 break;
2564 break; /* case SELECTOR_SU_SERV: end */
2567 case SELECTOR_DTMF:
2568 return (dtmf_request (Id, Number, a, plci, appl, msg));
2572 case SELECTOR_LINE_INTERCONNECT:
2573 return (mixer_request (Id, Number, a, plci, appl, msg));
2577 case PRIV_SELECTOR_ECHO_CANCELLER:
2578 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579 return (ec_request (Id, Number, a, plci, appl, msg));
2581 case SELECTOR_ECHO_CANCELLER:
2582 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583 return (ec_request (Id, Number, a, plci, appl, msg));
2586 case SELECTOR_V42BIS:
2587 default:
2588 Info = _FACILITY_NOT_SUPPORTED;
2589 break;
2590 } /* end of switch(selector) */
2593 dbug(1,dprintf("SendFacRc"));
2594 sendf(appl,
2595 _FACILITY_R|CONFIRM,
2597 Number,
2598 "wws",Info,selector,SSparms);
2599 return false;
2602 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2604 dbug(1,dprintf("facility_res"));
2605 return false;
2608 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2610 word Info = 0;
2611 byte req;
2612 byte len;
2613 word w;
2614 word fax_control_bits, fax_feature_bits, fax_info_change;
2615 API_PARSE * ncpi;
2616 byte pvc[2];
2618 API_PARSE fax_parms[9];
2619 word i;
2622 dbug(1,dprintf("connect_b3_req"));
2623 if(plci)
2625 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2628 Info = _WRONG_STATE;
2630 else
2632 /* local reply if assign unsuccessfull
2633 or B3 protocol allows only one layer 3 connection
2634 and already connected
2635 or B2 protocol not any LAPD
2636 and connect_b3_req contradicts originate/answer direction */
2637 if (!plci->NL.Id
2638 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639 && ((plci->channels != 0)
2640 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2643 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645 Info = _WRONG_STATE;
2646 sendf(appl,
2647 _CONNECT_B3_R|CONFIRM,
2649 Number,
2650 "w",Info);
2651 return false;
2653 plci->requested_options_conn = 0;
2655 req = N_CONNECT;
2656 ncpi = &parms[0];
2657 if(plci->B3_prot==2 || plci->B3_prot==3)
2659 if(ncpi->length>2)
2661 /* check for PVC */
2662 if(ncpi->info[2] || ncpi->info[3])
2664 pvc[0] = ncpi->info[3];
2665 pvc[1] = ncpi->info[2];
2666 add_d(plci,2,pvc);
2667 req = N_RESET;
2669 else
2671 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2676 else if(plci->B3_prot==5)
2678 if (plci->NL.Id && !plci->nl_remove_id)
2680 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2681 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2682 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2685 len = (byte)(offsetof(T30_INFO, universal_6));
2686 fax_info_change = false;
2687 if (ncpi->length >= 4)
2689 w = GET_WORD(&ncpi->info[3]);
2690 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2692 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2693 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2695 fax_info_change = true;
2697 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698 if (w & 0x0002) /* Fax-polling request */
2699 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700 if ((w & 0x0004) /* Request to send / poll another document */
2701 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2703 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2705 if (ncpi->length >= 6)
2707 w = GET_WORD(&ncpi->info[5]);
2708 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2710 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2711 fax_info_change = true;
2714 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2717 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2719 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2722 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2724 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2729 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730 Info = _WRONG_MESSAGE_FORMAT;
2731 else
2733 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2736 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2740 w = fax_parms[4].length;
2741 if (w > 20)
2742 w = 20;
2743 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744 for (i = 0; i < w; i++)
2745 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747 len = (byte)(offsetof(T30_INFO, station_id) + 20);
2748 w = fax_parms[5].length;
2749 if (w > 20)
2750 w = 20;
2751 plci->fax_connect_info_buffer[len++] = (byte) w;
2752 for (i = 0; i < w; i++)
2753 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754 w = fax_parms[6].length;
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[6].info[1+i];
2760 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761 & (1L << PRIVATE_FAX_NONSTANDARD))
2763 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2765 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766 plci->fax_connect_info_buffer[len++] = 0;
2768 else
2770 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773 for (i = 0; i < fax_parms[7].length; i++)
2774 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2779 else
2781 len = (byte)(offsetof(T30_INFO, universal_6));
2783 fax_info_change = true;
2786 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2788 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2789 fax_info_change = true;
2792 if (Info == GOOD)
2794 plci->fax_connect_info_length = len;
2795 if (fax_info_change)
2797 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2799 start_internal_command (Id, plci, fax_connect_info_command);
2800 return false;
2802 else
2804 start_internal_command (Id, plci, fax_adjust_b23_command);
2805 return false;
2810 else Info = _WRONG_STATE;
2812 else Info = _WRONG_STATE;
2815 else if (plci->B3_prot == B3_RTP)
2817 plci->internal_req_buffer[0] = ncpi->length + 1;
2818 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819 for (w = 0; w < ncpi->length; w++)
2820 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2822 return false;
2825 if(!Info)
2827 nl_req_ncci(plci,req,0);
2828 return 1;
2832 else Info = _WRONG_IDENTIFIER;
2834 sendf(appl,
2835 _CONNECT_B3_R|CONFIRM,
2837 Number,
2838 "w",Info);
2839 return false;
2842 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2844 word ncci;
2845 API_PARSE * ncpi;
2846 byte req;
2848 word w;
2851 API_PARSE fax_parms[9];
2852 word i;
2853 byte len;
2856 dbug(1,dprintf("connect_b3_res"));
2858 ncci = (word)(Id>>16);
2859 if(plci && ncci) {
2860 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861 if (GET_WORD (&parms[0].info[0]) != 0)
2863 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864 channel_request_xon (plci, a->ncci_ch[ncci]);
2865 channel_xmit_xon (plci);
2866 cleanup_ncci_data (plci, ncci);
2867 nl_req_ncci(plci,N_DISC,(byte)ncci);
2868 return 1;
2870 a->ncci_state[ncci] = INC_ACT_PENDING;
2872 req = N_CONNECT_ACK;
2873 ncpi = &parms[1];
2874 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2877 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878 & (1L << PRIVATE_FAX_NONSTANDARD))
2880 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2884 len = (byte)(offsetof(T30_INFO, station_id) + 20);
2885 if (plci->fax_connect_info_length < len)
2887 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2890 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2892 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2894 else
2896 if (plci->fax_connect_info_length <= len)
2897 plci->fax_connect_info_buffer[len] = 0;
2898 len += 1 + plci->fax_connect_info_buffer[len];
2899 if (plci->fax_connect_info_length <= len)
2900 plci->fax_connect_info_buffer[len] = 0;
2901 len += 1 + plci->fax_connect_info_buffer[len];
2902 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905 for (i = 0; i < fax_parms[7].length; i++)
2906 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2908 plci->fax_connect_info_length = len;
2909 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910 start_internal_command (Id, plci, fax_connect_ack_command);
2911 return false;
2915 nl_req_ncci(plci,req,(byte)ncci);
2916 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2919 if (plci->B3_prot == 4)
2920 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2921 else
2922 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2927 else if (plci->B3_prot == B3_RTP)
2929 plci->internal_req_buffer[0] = ncpi->length + 1;
2930 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931 for (w = 0; w < ncpi->length; w++)
2932 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2934 return false;
2937 else
2939 if(ncpi->length>2) {
2940 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2943 nl_req_ncci(plci,req,(byte)ncci);
2944 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945 if (plci->adjust_b_restore)
2947 plci->adjust_b_restore = false;
2948 start_internal_command (Id, plci, adjust_b_restore);
2951 return 1;
2954 return false;
2957 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2959 word ncci;
2961 ncci = (word)(Id>>16);
2962 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2964 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965 && (plci->State != OUTG_DIS_PENDING))
2967 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968 a->ncci_state[ncci] = CONNECTED;
2969 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970 channel_request_xon (plci, a->ncci_ch[ncci]);
2971 channel_xmit_xon (plci);
2974 return false;
2977 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2979 word Info;
2980 word ncci;
2981 API_PARSE * ncpi;
2983 dbug(1,dprintf("disconnect_b3_req"));
2985 Info = _WRONG_IDENTIFIER;
2986 ncci = (word)(Id>>16);
2987 if (plci && ncci)
2989 Info = _WRONG_STATE;
2990 if ((a->ncci_state[ncci] == CONNECTED)
2991 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992 || (a->ncci_state[ncci] == INC_CON_PENDING)
2993 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2995 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996 channel_request_xon (plci, a->ncci_ch[ncci]);
2997 channel_xmit_xon (plci);
2999 if (a->ncci[ncci].data_pending
3000 && ((plci->B3_prot == B3_TRANSPARENT)
3001 || (plci->B3_prot == B3_T30)
3002 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3004 plci->send_disc = (byte)ncci;
3005 plci->command = 0;
3006 return false;
3008 else
3010 cleanup_ncci_data (plci, ncci);
3012 if(plci->B3_prot==2 || plci->B3_prot==3)
3014 ncpi = &parms[0];
3015 if(ncpi->length>3)
3017 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3020 nl_req_ncci(plci,N_DISC,(byte)ncci);
3022 return 1;
3025 sendf(appl,
3026 _DISCONNECT_B3_R|CONFIRM,
3028 Number,
3029 "w",Info);
3030 return false;
3033 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3035 word ncci;
3036 word i;
3038 ncci = (word)(Id>>16);
3039 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3040 if(plci && ncci) {
3041 plci->requested_options_conn = 0;
3042 plci->fax_connect_info_length = 0;
3043 plci->ncpi_state = 0x00;
3044 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3047 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3049 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050 if(i<MAX_CHANNELS_PER_PLCI) {
3051 if(plci->channels)plci->channels--;
3052 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3055 ncci_free_receive_buffers (plci, ncci);
3057 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058 if(plci->State == SUSPENDING){
3059 sendf(plci->appl,
3060 _FACILITY_I,
3061 Id & 0xffffL,
3063 "ws", (word)3, "\x03\x04\x00\x00");
3064 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3066 plci_remove(plci);
3067 plci->State=IDLE;
3070 else
3072 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3076 ncci_free_receive_buffers (plci, ncci);
3078 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3080 plci->adapter->ncci_state[ncci] = IDLE;
3081 start_internal_command (Id, plci, fax_disconnect_command);
3082 return 1;
3086 return false;
3089 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3091 NCCI *ncci_ptr;
3092 DATA_B3_DESC *data;
3093 word Info;
3094 word ncci;
3095 word i;
3097 dbug(1,dprintf("data_b3_req"));
3099 Info = _WRONG_IDENTIFIER;
3100 ncci = (word)(Id>>16);
3101 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3103 if (plci && ncci)
3105 Info = _WRONG_STATE;
3106 if ((a->ncci_state[ncci] == CONNECTED)
3107 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3109 /* queue data */
3110 ncci_ptr = &(a->ncci[ncci]);
3111 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112 if (i >= MAX_DATA_B3)
3113 i -= MAX_DATA_B3;
3114 data = &(ncci_ptr->DBuffer[i]);
3115 data->Number = Number;
3116 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3117 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3120 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3123 else
3124 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125 data->Length = GET_WORD(parms[1].info);
3126 data->Handle = GET_WORD(parms[2].info);
3127 data->Flags = GET_WORD(parms[3].info);
3128 (ncci_ptr->data_pending)++;
3130 /* check for delivery confirmation */
3131 if (data->Flags & 0x0004)
3133 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134 if (i >= MAX_DATA_ACK)
3135 i -= MAX_DATA_ACK;
3136 ncci_ptr->DataAck[i].Number = data->Number;
3137 ncci_ptr->DataAck[i].Handle = data->Handle;
3138 (ncci_ptr->data_ack_pending)++;
3141 send_data(plci);
3142 return false;
3145 if (appl)
3147 if (plci)
3149 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3150 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3153 TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3157 sendf(appl,
3158 _DATA_B3_R|CONFIRM,
3160 Number,
3161 "ww",GET_WORD(parms[2].info),Info);
3163 return false;
3166 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3168 word n;
3169 word ncci;
3170 word NCCIcode;
3172 dbug(1,dprintf("data_b3_res"));
3174 ncci = (word)(Id>>16);
3175 if(plci && ncci) {
3176 n = GET_WORD(parms[0].info);
3177 dbug(1,dprintf("free(%d)",n));
3178 NCCIcode = ncci | (((word) a->Id) << 8);
3179 if(n<appl->MaxBuffer &&
3180 appl->DataNCCI[n]==NCCIcode &&
3181 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182 dbug(1,dprintf("found"));
3183 appl->DataNCCI[n] = 0;
3185 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186 channel_request_xon (plci, a->ncci_ch[ncci]);
3188 channel_xmit_xon (plci);
3190 if(appl->DataFlags[n] &4) {
3191 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3192 return 1;
3196 return false;
3199 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3201 word Info;
3202 word ncci;
3204 dbug(1,dprintf("reset_b3_req"));
3206 Info = _WRONG_IDENTIFIER;
3207 ncci = (word)(Id>>16);
3208 if(plci && ncci)
3210 Info = _WRONG_STATE;
3211 switch (plci->B3_prot)
3213 case B3_ISO8208:
3214 case B3_X25_DCE:
3215 if(a->ncci_state[ncci]==CONNECTED)
3217 nl_req_ncci(plci,N_RESET,(byte)ncci);
3218 send_req(plci);
3219 Info = GOOD;
3221 break;
3222 case B3_TRANSPARENT:
3223 if(a->ncci_state[ncci]==CONNECTED)
3225 start_internal_command (Id, plci, reset_b3_command);
3226 Info = GOOD;
3228 break;
3231 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3232 sendf(appl,
3233 _RESET_B3_R|CONFIRM,
3235 Number,
3236 "w",Info);
3237 return false;
3240 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3242 word ncci;
3244 dbug(1,dprintf("reset_b3_res"));
3246 ncci = (word)(Id>>16);
3247 if(plci && ncci) {
3248 switch (plci->B3_prot)
3250 case B3_ISO8208:
3251 case B3_X25_DCE:
3252 if(a->ncci_state[ncci]==INC_RES_PENDING)
3254 a->ncci_state[ncci] = CONNECTED;
3255 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3256 return true;
3258 break;
3261 return false;
3264 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3266 word ncci;
3267 API_PARSE * ncpi;
3268 byte req;
3270 dbug(1,dprintf("connect_b3_t90_a_res"));
3272 ncci = (word)(Id>>16);
3273 if(plci && ncci) {
3274 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275 a->ncci_state[ncci] = CONNECTED;
3277 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278 a->ncci_state[ncci] = CONNECTED;
3280 req = N_CONNECT_ACK;
3282 /* parms[0]==0 for CAPI original message definition! */
3283 if(parms[0].info) {
3284 ncpi = &parms[1];
3285 if(ncpi->length>2) {
3286 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3290 nl_req_ncci(plci,req,(byte)ncci);
3291 return 1;
3294 return false;
3298 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3300 word Info=0;
3301 word i;
3302 byte tel;
3303 API_PARSE bp_parms[7];
3305 if(!plci || !msg)
3307 Info = _WRONG_IDENTIFIER;
3309 else
3311 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313 dbug(1,dprintf("PlciState=0x%x",plci->State));
3314 for(i=0;i<7;i++) bp_parms[i].length = 0;
3316 /* check if no channel is open, no B3 connected only */
3317 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3320 Info = _WRONG_STATE;
3322 /* check message format and fill bp_parms pointer */
3323 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3325 Info = _WRONG_MESSAGE_FORMAT;
3327 else
3329 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331 if(Id & EXT_CONTROLLER)
3333 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3334 return 0;
3336 plci->State=INC_CON_CONNECTED_ALERT;
3337 plci->appl = appl;
3338 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339 dump_c_ind_mask (plci);
3340 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341 { /* its quasi a connect */
3342 if(test_c_ind_mask_bit (plci, i))
3343 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3347 api_save_msg(msg, "s", &plci->saved_msg);
3348 tel = plci->tel;
3349 if(Id & EXT_CONTROLLER)
3351 if(tel) /* external controller in use by this PLCI */
3353 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3355 dbug(1,dprintf("Ext_Ctrl in use 1"));
3356 Info = _WRONG_STATE;
3359 else /* external controller NOT in use by this PLCI ? */
3361 if(a->AdvSignalPLCI)
3363 dbug(1,dprintf("Ext_Ctrl in use 2"));
3364 Info = _WRONG_STATE;
3366 else /* activate the codec */
3368 dbug(1,dprintf("Ext_Ctrl start"));
3369 if(AdvCodecSupport(a, plci, appl, 0) )
3371 dbug(1,dprintf("Error in codec procedures"));
3372 Info = _WRONG_STATE;
3374 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3376 plci->spoofed_msg = AWAITING_SELECT_B;
3377 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3378 plci->command = 0;
3379 dbug(1,dprintf("continue if codec loaded"));
3380 return false;
3385 else /* external controller bit is OFF */
3387 if(tel) /* external controller in use, need to switch off */
3389 if(a->AdvSignalAppl==appl)
3391 CodecIdCheck(a, plci);
3392 plci->tel = 0;
3393 plci->adv_nl = 0;
3394 dbug(1,dprintf("Ext_Ctrl disable"));
3396 else
3398 dbug(1,dprintf("Ext_Ctrl not requested"));
3402 if (!Info)
3404 if (plci->call_dir & CALL_DIR_OUT)
3405 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406 else if (plci->call_dir & CALL_DIR_IN)
3407 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408 start_internal_command (Id, plci, select_b_command);
3409 return false;
3413 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3414 return false;
3417 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3418 PLCI *plci, APPL *appl, API_PARSE *parms)
3420 word command;
3421 word i;
3422 word ncci;
3423 API_PARSE * m;
3424 API_PARSE m_parms[5];
3425 word codec;
3426 byte req;
3427 byte ch;
3428 byte dir;
3429 static byte chi[2] = {0x01,0x00};
3430 static byte lli[2] = {0x01,0x00};
3431 static byte codec_cai[2] = {0x01,0x01};
3432 static byte null_msg = {0};
3433 static API_PARSE null_parms = { 0, &null_msg };
3434 PLCI * v_plci;
3435 word Info=0;
3437 dbug(1,dprintf("manufacturer_req"));
3438 for(i=0;i<5;i++) m_parms[i].length = 0;
3440 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441 Info = _WRONG_MESSAGE_FORMAT;
3443 command = GET_WORD(parms[1].info);
3444 m = &parms[2];
3445 if (!Info)
3447 switch(command) {
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
3451 break;
3453 codec = GET_WORD(m_parms[0].info);
3454 ch = m_parms[1].info[0];
3455 dir = m_parms[2].info[0];
3456 if((i=get_plci(a))) {
3457 plci = &a->plci[i-1];
3458 plci->appl = appl;
3459 plci->command = _MANUFACTURER_R;
3460 plci->m_command = command;
3461 plci->number = Number;
3462 plci->State = LOCAL_CONNECT;
3463 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3466 if((ch==1 || ch==2) && (dir<=2)) {
3467 chi[1] = (byte)(0x80|ch);
3468 lli[1] = 0;
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470 switch(codec)
3472 case 0:
3473 Info = add_b1(plci,&m_parms[3],0,0);
3474 break;
3475 case 1:
3476 add_p(plci,CAI,codec_cai);
3477 break;
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3480 case 2:
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3484 else {
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3488 break;
3491 plci->State = LOCAL_CONNECT;
3492 plci->manufacturer = true;
3493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
3497 if(!Info)
3499 add_p(plci,LLI,lli);
3500 add_p(plci,CHI,chi);
3501 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502 sig_req(plci,ASSIGN,DSIG_ID);
3504 if(!codec)
3506 Info = add_b23(plci,&m_parms[3]);
3507 if(!Info)
3509 nl_req_ncci(plci,ASSIGN,0);
3510 send_req(plci);
3513 if(!Info)
3515 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3518 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519 plci->spoofed_msg = AWAITING_MANUF_CON;
3520 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521 plci->command = 0;
3522 send_req(plci);
3523 return false;
3525 if(dir==1) {
3526 sig_req(plci,CALL_REQ,0);
3528 else if(!dir){
3529 sig_req(plci,LISTEN_REQ,0);
3531 send_req(plci);
3533 else
3535 sendf(appl,
3536 _MANUFACTURER_R|CONFIRM,
3538 Number,
3539 "dww",_DI_MANU_ID,command,Info);
3540 return 2;
3545 else Info = _OUT_OF_PLCI;
3546 break;
3548 case _DI_IDI_CTRL:
3549 if(!plci)
3551 Info = _WRONG_IDENTIFIER;
3552 break;
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3556 break;
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
3562 if(req==CALL_REQ)
3564 plci->b_channel = getChannel(&m_parms[1]);
3565 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3568 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570 plci->command = 0;
3571 break;
3574 else if(req==LAW_REQ)
3576 plci->cr_enquiry = true;
3578 add_ss(plci,FTY,&m_parms[1]);
3579 sig_req(plci,req,0);
3580 send_req(plci);
3581 if(req==HANGUP)
3583 if (plci->NL.Id && !plci->nl_remove_id)
3585 if (plci->channels)
3587 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3589 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3591 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592 cleanup_ncci_data (plci, ncci);
3593 nl_req_ncci(plci,N_DISC,(byte)ncci);
3597 mixer_remove (plci);
3598 nl_req_ncci(plci,REMOVE,0);
3599 send_req(plci);
3602 break;
3604 case _DI_SIG_CTRL:
3605 /* signalling control for loop activation B-channel */
3606 if(!plci)
3608 Info = _WRONG_IDENTIFIER;
3609 break;
3611 if(m->length){
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3614 add_ss(plci,FTY,m);
3615 sig_req(plci,SIG_CTRL,0);
3616 send_req(plci);
3618 else Info = _WRONG_MESSAGE_FORMAT;
3619 break;
3621 case _DI_RXT_CTRL:
3622 /* activation control for receiver/transmitter B-channel */
3623 if(!plci)
3625 Info = _WRONG_IDENTIFIER;
3626 break;
3628 if(m->length){
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3631 add_ss(plci,FTY,m);
3632 sig_req(plci,DSP_CTRL,0);
3633 send_req(plci);
3635 else Info = _WRONG_MESSAGE_FORMAT;
3636 break;
3638 case _DI_ADV_CODEC:
3639 case _DI_DSP_CTRL:
3640 /* TEL_CTRL commands to support non standard adjustments: */
3641 /* Ring on/off, Handset micro volume, external micro vol. */
3642 /* handset+external speaker volume, receiver+transm. gain,*/
3643 /* handsfree on (hookinfo off), set mixer command */
3645 if(command == _DI_ADV_CODEC)
3647 if(!a->AdvCodecPLCI) {
3648 Info = _WRONG_STATE;
3649 break;
3651 v_plci = a->AdvCodecPLCI;
3653 else
3655 if (plci
3656 && (m->length >= 3)
3657 && (m->info[1] == 0x1c)
3658 && (m->info[2] >= 1))
3660 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3662 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3664 Info = _WRONG_STATE;
3665 break;
3667 a->adv_voice_coef_length = m->info[2] - 1;
3668 if (a->adv_voice_coef_length > m->length - 3)
3669 a->adv_voice_coef_length = (byte)(m->length - 3);
3670 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672 for (i = 0; i < a->adv_voice_coef_length; i++)
3673 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674 if (plci->B1_facilities & B1_FACILITY_VOICE)
3675 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676 break;
3678 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3680 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3682 Info = _FACILITY_NOT_SUPPORTED;
3683 break;
3686 plci->dtmf_parameter_length = m->info[2] - 1;
3687 if (plci->dtmf_parameter_length > m->length - 3)
3688 plci->dtmf_parameter_length = (byte)(m->length - 3);
3689 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691 for (i = 0; i < plci->dtmf_parameter_length; i++)
3692 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694 dtmf_parameter_write (plci);
3695 break;
3699 v_plci = plci;
3702 if(!v_plci)
3704 Info = _WRONG_IDENTIFIER;
3705 break;
3707 if(m->length){
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3710 send_req(v_plci);
3712 else Info = _WRONG_MESSAGE_FORMAT;
3714 break;
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3719 break;
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3723 Info = _FACILITY_NOT_SUPPORTED;
3724 break;
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727 break;
3731 default:
3732 Info = _WRONG_MESSAGE_FORMAT;
3733 break;
3737 sendf(appl,
3738 _MANUFACTURER_R|CONFIRM,
3740 Number,
3741 "dww",_DI_MANU_ID,command,Info);
3742 return false;
3746 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3747 PLCI *plci, APPL *appl, API_PARSE *msg)
3749 word indication;
3751 API_PARSE m_parms[3];
3752 API_PARSE *ncpi;
3753 API_PARSE fax_parms[9];
3754 word i;
3755 byte len;
3758 dbug(1,dprintf("manufacturer_res"));
3760 if ((msg[0].length == 0)
3761 || (msg[1].length == 0)
3762 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3764 return false;
3766 indication = GET_WORD(msg[1].info);
3767 switch (indication)
3770 case _DI_NEGOTIATE_B3:
3771 if(!plci)
3772 break;
3773 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3774 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3776 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3777 break;
3779 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3781 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3782 break;
3784 ncpi = &m_parms[1];
3785 len = (byte)(offsetof(T30_INFO, station_id) + 20);
3786 if (plci->fax_connect_info_length < len)
3788 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3789 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3791 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3793 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3795 else
3797 if (plci->fax_connect_info_length <= len)
3798 plci->fax_connect_info_buffer[len] = 0;
3799 len += 1 + plci->fax_connect_info_buffer[len];
3800 if (plci->fax_connect_info_length <= len)
3801 plci->fax_connect_info_buffer[len] = 0;
3802 len += 1 + plci->fax_connect_info_buffer[len];
3803 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3804 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3805 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3806 for (i = 0; i < fax_parms[7].length; i++)
3807 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3809 plci->fax_connect_info_length = len;
3810 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3811 start_internal_command (Id, plci, fax_edata_ack_command);
3812 break;
3815 return false;
3818 /*------------------------------------------------------------------*/
3819 /* IDI callback function */
3820 /*------------------------------------------------------------------*/
3822 void callback(ENTITY * e)
3824 DIVA_CAPI_ADAPTER * a;
3825 APPL * appl;
3826 PLCI * plci;
3827 CAPI_MSG *m;
3828 word i, j;
3829 byte rc;
3830 byte ch;
3831 byte req;
3832 byte global_req;
3833 int no_cancel_rc;
3835 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3836 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3838 a = &(adapter[(byte)e->user[0]]);
3839 plci = &(a->plci[e->user[1]]);
3840 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3843 If new protocol code and new XDI is used then CAPI should work
3844 fully in accordance with IDI cpec an look on callback field instead
3845 of Rc field for return codes.
3847 if (((e->complete == 0xff) && no_cancel_rc) ||
3848 (e->Rc && !no_cancel_rc)) {
3849 rc = e->Rc;
3850 ch = e->RcCh;
3851 req = e->Req;
3852 e->Rc = 0;
3854 if (e->user[0] & 0x8000)
3857 If REMOVE request was sent then we have to wait until
3858 return code with Id set to zero arrives.
3859 All other return codes should be ignored.
3861 if (req == REMOVE)
3863 if (e->Id)
3865 dbug(1,dprintf("cancel RC in REMOVE state"));
3866 return;
3868 channel_flow_control_remove (plci);
3869 for (i = 0; i < 256; i++)
3871 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3872 a->FlowControlIdTable[i] = 0;
3874 plci->nl_remove_id = 0;
3875 if (plci->rx_dma_descriptor > 0) {
3876 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3877 plci->rx_dma_descriptor = 0;
3880 if (rc == OK_FC)
3882 a->FlowControlIdTable[ch] = e->Id;
3883 a->FlowControlSkipTable[ch] = 0;
3885 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3886 a->ch_flow_plci[ch] = plci->Id;
3887 plci->nl_req = 0;
3889 else
3892 Cancel return codes self, if feature was requested
3894 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3895 a->FlowControlIdTable[ch] = 0;
3896 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3897 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3898 return;
3902 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3904 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3905 if (ch == e->ReqCh)
3906 plci->nl_req = 0;
3908 else
3909 plci->nl_req = 0;
3911 if (plci->nl_req)
3912 control_rc (plci, 0, rc, ch, 0, true);
3913 else
3915 if (req == N_XON)
3917 channel_x_on (plci, ch);
3918 if (plci->internal_command)
3919 control_rc (plci, req, rc, ch, 0, true);
3921 else
3923 if (plci->nl_global_req)
3925 global_req = plci->nl_global_req;
3926 plci->nl_global_req = 0;
3927 if (rc != ASSIGN_OK) {
3928 e->Id = 0;
3929 if (plci->rx_dma_descriptor > 0) {
3930 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3931 plci->rx_dma_descriptor = 0;
3934 channel_xmit_xon (plci);
3935 control_rc (plci, 0, rc, ch, global_req, true);
3937 else if (plci->data_sent)
3939 channel_xmit_xon (plci);
3940 plci->data_sent = false;
3941 plci->NL.XNum = 1;
3942 data_rc (plci, ch);
3943 if (plci->internal_command)
3944 control_rc (plci, req, rc, ch, 0, true);
3946 else
3948 channel_xmit_xon (plci);
3949 control_rc (plci, req, rc, ch, 0, true);
3954 else
3957 If REMOVE request was sent then we have to wait until
3958 return code with Id set to zero arrives.
3959 All other return codes should be ignored.
3961 if (req == REMOVE)
3963 if (e->Id)
3965 dbug(1,dprintf("cancel RC in REMOVE state"));
3966 return;
3968 plci->sig_remove_id = 0;
3970 plci->sig_req = 0;
3971 if (plci->sig_global_req)
3973 global_req = plci->sig_global_req;
3974 plci->sig_global_req = 0;
3975 if (rc != ASSIGN_OK)
3976 e->Id = 0;
3977 channel_xmit_xon (plci);
3978 control_rc (plci, 0, rc, ch, global_req, false);
3980 else
3982 channel_xmit_xon (plci);
3983 control_rc (plci, req, rc, ch, 0, false);
3987 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3988 same callback. Also if new XDI and protocol code used then jump
3989 direct to finish.
3991 if (no_cancel_rc) {
3992 channel_xmit_xon(plci);
3993 goto capi_callback_suffix;
3997 channel_xmit_xon(plci);
3999 if (e->Ind) {
4000 if (e->user[0] &0x8000) {
4001 byte Ind = e->Ind & 0x0f;
4002 byte Ch = e->IndCh;
4003 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4004 (a->ch_flow_plci[Ch] == plci->Id)) {
4005 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4006 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4008 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4010 nl_ind(plci);
4011 if ((e->RNR != 1) &&
4012 (a->ch_flow_plci[Ch] == plci->Id) &&
4013 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4014 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4015 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4017 } else {
4018 sig_ind(plci);
4020 e->Ind = 0;
4023 capi_callback_suffix:
4025 while (!plci->req_in
4026 && !plci->internal_command
4027 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4029 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4031 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4033 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4034 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4035 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4036 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4037 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4039 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4040 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4042 else
4044 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4046 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4048 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4049 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4051 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4053 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4054 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4056 i = api_put (appl, m);
4057 if (i != 0)
4059 if (m->header.command == _DATA_B3_R)
4061 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4063 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4064 break;
4067 if (plci->li_notify_update)
4069 plci->li_notify_update = false;
4070 mixer_notify_update (plci, false);
4074 send_data(plci);
4075 send_req(plci);
4079 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4080 byte nl_rc)
4082 dword Id;
4083 dword rId;
4084 word Number;
4085 word Info=0;
4086 word i;
4087 word ncci;
4088 DIVA_CAPI_ADAPTER * a;
4089 APPL * appl;
4090 PLCI * rplci;
4091 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4092 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4094 if (!plci) {
4095 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4096 return;
4098 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4099 if(plci->req_in!=plci->req_out)
4101 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4103 dbug(1,dprintf("req_1return"));
4104 return;
4106 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4108 plci->req_in = plci->req_in_start = plci->req_out = 0;
4109 dbug(1,dprintf("control_rc"));
4111 appl = plci->appl;
4112 a = plci->adapter;
4113 ncci = a->ch_ncci[ch];
4114 if(appl)
4116 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4117 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4118 Number = plci->number;
4119 dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command));
4120 dbug(1,dprintf("channels=0x%x",plci->channels));
4121 if (plci_remove_check(plci))
4122 return;
4123 if(req==REMOVE && rc==ASSIGN_OK)
4125 sig_req(plci,HANGUP,0);
4126 sig_req(plci,REMOVE,0);
4127 send_req(plci);
4129 if(plci->command)
4131 switch(plci->command)
4133 case C_HOLD_REQ:
4134 dbug(1,dprintf("HoldRC=0x%x",rc));
4135 SSparms[1] = (byte)S_HOLD;
4136 if(rc!=OK)
4138 plci->SuppState = IDLE;
4139 Info = 0x2001;
4141 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4142 break;
4144 case C_RETRIEVE_REQ:
4145 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4146 SSparms[1] = (byte)S_RETRIEVE;
4147 if(rc!=OK)
4149 plci->SuppState = CALL_HELD;
4150 Info = 0x2001;
4152 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4153 break;
4155 case _INFO_R:
4156 dbug(1,dprintf("InfoRC=0x%x",rc));
4157 if(rc!=OK) Info=_WRONG_STATE;
4158 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4159 break;
4161 case _CONNECT_R:
4162 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4163 if (plci->State == INC_DIS_PENDING)
4164 break;
4165 if(plci->Sig.Id!=0xff)
4167 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4168 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4170 dbug(1,dprintf("No more IDs/Call_Req failed"));
4171 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4172 plci_remove(plci);
4173 plci->State = IDLE;
4174 break;
4176 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4177 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4179 else /* D-ch activation */
4181 if (rc != ASSIGN_OK)
4183 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4184 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4185 plci_remove(plci);
4186 plci->State = IDLE;
4187 break;
4189 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4190 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4191 plci->State = INC_ACT_PENDING;
4193 break;
4195 case _CONNECT_I|RESPONSE:
4196 if (plci->State != INC_DIS_PENDING)
4197 plci->State = INC_CON_ACCEPT;
4198 break;
4200 case _DISCONNECT_R:
4201 if (plci->State == INC_DIS_PENDING)
4202 break;
4203 if(plci->Sig.Id!=0xff)
4205 plci->State = OUTG_DIS_PENDING;
4206 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4208 break;
4210 case SUSPEND_REQ:
4211 break;
4213 case RESUME_REQ:
4214 break;
4216 case _CONNECT_B3_R:
4217 if(rc!=OK)
4219 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4220 break;
4222 ncci = get_ncci (plci, ch, 0);
4223 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4224 plci->channels++;
4225 if(req==N_RESET)
4227 a->ncci_state[ncci] = INC_ACT_PENDING;
4228 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4229 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4231 else
4233 a->ncci_state[ncci] = OUTG_CON_PENDING;
4234 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4236 break;
4238 case _CONNECT_B3_I|RESPONSE:
4239 break;
4241 case _RESET_B3_R:
4242 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4243 break;
4245 case _DISCONNECT_B3_R:
4246 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4247 break;
4249 case _MANUFACTURER_R:
4250 break;
4252 case PERM_LIST_REQ:
4253 if(rc!=OK)
4255 Info = _WRONG_IDENTIFIER;
4256 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4257 plci_remove(plci);
4259 else
4260 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4261 break;
4263 default:
4264 break;
4266 plci->command = 0;
4268 else if (plci->internal_command)
4270 switch(plci->internal_command)
4272 case BLOCK_PLCI:
4273 return;
4275 case GET_MWI_STATE:
4276 if(rc==OK) /* command supported, wait for indication */
4278 return;
4280 plci_remove(plci);
4281 break;
4283 /* Get Supported Services */
4284 case GETSERV_REQ_PEND:
4285 if(rc==OK) /* command supported, wait for indication */
4287 break;
4289 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4290 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4291 plci_remove(plci);
4292 break;
4294 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4295 case INTERR_NUMBERS_REQ_PEND:
4296 case CF_START_PEND: /* Call Forwarding Start pending */
4297 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4298 case CCBS_REQUEST_REQ_PEND:
4299 case CCBS_DEACTIVATE_REQ_PEND:
4300 case CCBS_INTERROGATE_REQ_PEND:
4301 switch(plci->internal_command)
4303 case INTERR_DIVERSION_REQ_PEND:
4304 SSparms[1] = S_INTERROGATE_DIVERSION;
4305 break;
4306 case INTERR_NUMBERS_REQ_PEND:
4307 SSparms[1] = S_INTERROGATE_NUMBERS;
4308 break;
4309 case CF_START_PEND:
4310 SSparms[1] = S_CALL_FORWARDING_START;
4311 break;
4312 case CF_STOP_PEND:
4313 SSparms[1] = S_CALL_FORWARDING_STOP;
4314 break;
4315 case CCBS_REQUEST_REQ_PEND:
4316 SSparms[1] = S_CCBS_REQUEST;
4317 break;
4318 case CCBS_DEACTIVATE_REQ_PEND:
4319 SSparms[1] = S_CCBS_DEACTIVATE;
4320 break;
4321 case CCBS_INTERROGATE_REQ_PEND:
4322 SSparms[1] = S_CCBS_INTERROGATE;
4323 break;
4325 if(global_req==ASSIGN)
4327 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4328 return;
4330 if(!plci->appl) break;
4331 if(rc==ISDN_GUARD_REJ)
4333 Info = _CAPI_GUARD_ERROR;
4335 else if(rc!=OK)
4337 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4339 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4340 plci->number,"wws",Info,(word)3,SSparms);
4341 if(Info) plci_remove(plci);
4342 break;
4344 /* 3pty conference pending */
4345 case PTY_REQ_PEND:
4346 if(!plci->relatedPTYPLCI) break;
4347 rplci = plci->relatedPTYPLCI;
4348 SSparms[1] = plci->ptyState;
4349 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4350 if(rplci->tel) rId|=EXT_CONTROLLER;
4351 if(rc!=OK)
4353 Info = 0x300E; /* not supported */
4354 plci->relatedPTYPLCI = NULL;
4355 plci->ptyState = 0;
4357 sendf(rplci->appl,
4358 _FACILITY_R|CONFIRM,
4359 rId,
4360 plci->number,
4361 "wws",Info,(word)3,SSparms);
4362 break;
4364 /* Explicit Call Transfer pending */
4365 case ECT_REQ_PEND:
4366 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4367 if(!plci->relatedPTYPLCI) break;
4368 rplci = plci->relatedPTYPLCI;
4369 SSparms[1] = S_ECT;
4370 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4371 if(rplci->tel) rId|=EXT_CONTROLLER;
4372 if(rc!=OK)
4374 Info = 0x300E; /* not supported */
4375 plci->relatedPTYPLCI = NULL;
4376 plci->ptyState = 0;
4378 sendf(rplci->appl,
4379 _FACILITY_R|CONFIRM,
4380 rId,
4381 plci->number,
4382 "wws",Info,(word)3,SSparms);
4383 break;
4385 case _MANUFACTURER_R:
4386 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4387 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4389 dbug(1,dprintf("No more IDs"));
4390 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4391 plci_remove(plci); /* after codec init, internal codec commands pending */
4393 break;
4395 case _CONNECT_R:
4396 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4397 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4399 dbug(1,dprintf("No more IDs"));
4400 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4401 plci_remove(plci); /* after codec init, internal codec commands pending */
4403 break;
4405 case PERM_COD_HOOK: /* finished with Hook_Ind */
4406 return;
4408 case PERM_COD_CALL:
4409 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4410 plci->internal_command = PERM_COD_CONN_PEND;
4411 return;
4413 case PERM_COD_ASSIGN:
4414 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4415 if(rc!=ASSIGN_OK) break;
4416 sig_req(plci,CALL_REQ,0);
4417 send_req(plci);
4418 plci->internal_command = PERM_COD_CALL;
4419 return;
4421 /* Null Call Reference Request pending */
4422 case C_NCR_FAC_REQ:
4423 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4424 if(global_req==ASSIGN)
4426 if(rc==ASSIGN_OK)
4428 return;
4430 else
4432 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4433 appl->NullCREnable = false;
4434 plci_remove(plci);
4437 else if(req==NCR_FACILITY)
4439 if(rc==OK)
4441 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4443 else
4445 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4446 appl->NullCREnable = false;
4448 plci_remove(plci);
4450 break;
4452 case HOOK_ON_REQ:
4453 if(plci->channels)
4455 if(a->ncci_state[ncci]==CONNECTED)
4457 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4458 cleanup_ncci_data (plci, ncci);
4459 nl_req_ncci(plci,N_DISC,(byte)ncci);
4461 break;
4463 break;
4465 case HOOK_OFF_REQ:
4466 if (plci->State == INC_DIS_PENDING)
4467 break;
4468 sig_req(plci,CALL_REQ,0);
4469 send_req(plci);
4470 plci->State=OUTG_CON_PENDING;
4471 break;
4474 case MWI_ACTIVATE_REQ_PEND:
4475 case MWI_DEACTIVATE_REQ_PEND:
4476 if(global_req == ASSIGN && rc==ASSIGN_OK)
4478 dbug(1,dprintf("MWI_REQ assigned"));
4479 return;
4481 else if(rc!=OK)
4483 if(rc==WRONG_IE)
4485 Info = 0x2007; /* Illegal message parameter coding */
4486 dbug(1,dprintf("MWI_REQ invalid parameter"));
4488 else
4490 Info = 0x300B; /* not supported */
4491 dbug(1,dprintf("MWI_REQ not supported"));
4493 /* 0x3010: Request not allowed in this state */
4494 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4497 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4499 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4501 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4503 if(plci->cr_enquiry)
4505 sendf(plci->appl,
4506 _FACILITY_R|CONFIRM,
4507 Id&0xf,
4508 plci->number,
4509 "wws",Info,(word)3,SSparms);
4510 if(rc!=OK) plci_remove(plci);
4512 else
4514 sendf(plci->appl,
4515 _FACILITY_R|CONFIRM,
4517 plci->number,
4518 "wws",Info,(word)3,SSparms);
4520 break;
4522 case CONF_BEGIN_REQ_PEND:
4523 case CONF_ADD_REQ_PEND:
4524 case CONF_SPLIT_REQ_PEND:
4525 case CONF_DROP_REQ_PEND:
4526 case CONF_ISOLATE_REQ_PEND:
4527 case CONF_REATTACH_REQ_PEND:
4528 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4529 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4530 rplci = plci;
4531 rId = Id;
4532 switch(plci->internal_command)
4534 case CONF_BEGIN_REQ_PEND:
4535 SSparms[1] = S_CONF_BEGIN;
4536 break;
4537 case CONF_ADD_REQ_PEND:
4538 SSparms[1] = S_CONF_ADD;
4539 rplci = plci->relatedPTYPLCI;
4540 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4541 break;
4542 case CONF_SPLIT_REQ_PEND:
4543 SSparms[1] = S_CONF_SPLIT;
4544 break;
4545 case CONF_DROP_REQ_PEND:
4546 SSparms[1] = S_CONF_DROP;
4547 break;
4548 case CONF_ISOLATE_REQ_PEND:
4549 SSparms[1] = S_CONF_ISOLATE;
4550 break;
4551 case CONF_REATTACH_REQ_PEND:
4552 SSparms[1] = S_CONF_REATTACH;
4553 break;
4556 if(rc!=OK)
4558 Info = 0x300E; /* not supported */
4559 plci->relatedPTYPLCI = NULL;
4560 plci->ptyState = 0;
4562 sendf(rplci->appl,
4563 _FACILITY_R|CONFIRM,
4564 rId,
4565 plci->number,
4566 "wws",Info,(word)3,SSparms);
4567 break;
4569 case VSWITCH_REQ_PEND:
4570 if(rc!=OK)
4572 if(plci->relatedPTYPLCI)
4574 plci->relatedPTYPLCI->vswitchstate=0;
4575 plci->relatedPTYPLCI->vsprot=0;
4576 plci->relatedPTYPLCI->vsprotdialect=0;
4578 plci->vswitchstate=0;
4579 plci->vsprot=0;
4580 plci->vsprotdialect=0;
4582 else
4584 if(plci->relatedPTYPLCI &&
4585 plci->vswitchstate==1 &&
4586 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4587 plci->vswitchstate=3;
4589 break;
4591 /* Call Deflection Request pending (SSCT) */
4592 case CD_REQ_PEND:
4593 SSparms[1] = S_CALL_DEFLECTION;
4594 if(rc!=OK)
4596 Info = 0x300E; /* not supported */
4597 plci->appl->CDEnable = 0;
4599 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4600 plci->number,"wws",Info,(word)3,SSparms);
4601 break;
4603 case RTP_CONNECT_B3_REQ_COMMAND_2:
4604 if (rc == OK)
4606 ncci = get_ncci (plci, ch, 0);
4607 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4608 plci->channels++;
4609 a->ncci_state[ncci] = OUTG_CON_PENDING;
4612 default:
4613 if (plci->internal_command_queue[0])
4615 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4616 if (plci->internal_command)
4617 return;
4619 break;
4621 next_internal_command (Id, plci);
4624 else /* appl==0 */
4626 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4627 if(plci->tel) Id|=EXT_CONTROLLER;
4629 switch(plci->internal_command)
4631 case BLOCK_PLCI:
4632 return;
4634 case START_L1_SIG_ASSIGN_PEND:
4635 case REM_L1_SIG_ASSIGN_PEND:
4636 if(global_req == ASSIGN)
4638 break;
4640 else
4642 dbug(1,dprintf("***L1 Req rem PLCI"));
4643 plci->internal_command = 0;
4644 sig_req(plci,REMOVE,0);
4645 send_req(plci);
4647 break;
4649 /* Call Deflection Request pending, just no appl ptr assigned */
4650 case CD_REQ_PEND:
4651 SSparms[1] = S_CALL_DEFLECTION;
4652 if(rc!=OK)
4654 Info = 0x300E; /* not supported */
4656 for(i=0; i<max_appl; i++)
4658 if(application[i].CDEnable)
4660 if(!application[i].Id) application[i].CDEnable = 0;
4661 else
4663 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4664 plci->number,"wws",Info,(word)3,SSparms);
4665 if(Info) application[i].CDEnable = 0;
4669 plci->internal_command = 0;
4670 break;
4672 case PERM_COD_HOOK: /* finished with Hook_Ind */
4673 return;
4675 case PERM_COD_CALL:
4676 plci->internal_command = PERM_COD_CONN_PEND;
4677 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4678 return;
4680 case PERM_COD_ASSIGN:
4681 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4682 plci->internal_command = 0;
4683 if(rc!=ASSIGN_OK) break;
4684 plci->internal_command = PERM_COD_CALL;
4685 sig_req(plci,CALL_REQ,0);
4686 send_req(plci);
4687 return;
4689 case LISTEN_SIG_ASSIGN_PEND:
4690 if(rc == ASSIGN_OK)
4692 plci->internal_command = 0;
4693 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4694 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4695 sig_req(plci,INDICATE_REQ,0);
4696 send_req(plci);
4698 else
4700 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4701 a->listen_active--;
4702 plci_remove(plci);
4703 plci->State = IDLE;
4705 break;
4707 case USELAW_REQ:
4708 if(global_req == ASSIGN)
4710 if (rc==ASSIGN_OK)
4712 sig_req(plci,LAW_REQ,0);
4713 send_req(plci);
4714 dbug(1,dprintf("Auto-Law assigned"));
4716 else
4718 dbug(1,dprintf("Auto-Law assign failed"));
4719 a->automatic_law = 3;
4720 plci->internal_command = 0;
4721 a->automatic_lawPLCI = NULL;
4723 break;
4725 else if(req == LAW_REQ && rc==OK)
4727 dbug(1,dprintf("Auto-Law initiated"));
4728 a->automatic_law = 2;
4729 plci->internal_command = 0;
4731 else
4733 dbug(1,dprintf("Auto-Law not supported"));
4734 a->automatic_law = 3;
4735 plci->internal_command = 0;
4736 sig_req(plci,REMOVE,0);
4737 send_req(plci);
4738 a->automatic_lawPLCI = NULL;
4740 break;
4742 plci_remove_check(plci);
4746 static void data_rc(PLCI *plci, byte ch)
4748 dword Id;
4749 DIVA_CAPI_ADAPTER * a;
4750 NCCI *ncci_ptr;
4751 DATA_B3_DESC *data;
4752 word ncci;
4754 if (plci->appl)
4756 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4757 a = plci->adapter;
4758 ncci = a->ch_ncci[ch];
4759 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4761 ncci_ptr = &(a->ncci[ncci]);
4762 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4763 if (ncci_ptr->data_pending)
4765 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4766 if (!(data->Flags &4) && a->ncci_state[ncci])
4768 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4769 if(plci->tel) Id|=EXT_CONTROLLER;
4770 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4771 "ww",data->Handle,0);
4773 (ncci_ptr->data_out)++;
4774 if (ncci_ptr->data_out == MAX_DATA_B3)
4775 ncci_ptr->data_out = 0;
4776 (ncci_ptr->data_pending)--;
4782 static void data_ack(PLCI *plci, byte ch)
4784 dword Id;
4785 DIVA_CAPI_ADAPTER * a;
4786 NCCI *ncci_ptr;
4787 word ncci;
4789 a = plci->adapter;
4790 ncci = a->ch_ncci[ch];
4791 ncci_ptr = &(a->ncci[ncci]);
4792 if (ncci_ptr->data_ack_pending)
4794 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4796 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4797 if(plci->tel) Id|=EXT_CONTROLLER;
4798 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4799 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4801 (ncci_ptr->data_ack_out)++;
4802 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4803 ncci_ptr->data_ack_out = 0;
4804 (ncci_ptr->data_ack_pending)--;
4808 static void sig_ind(PLCI *plci)
4810 dword x_Id;
4811 dword Id;
4812 dword rId;
4813 word Number = 0;
4814 word i;
4815 word cip;
4816 dword cip_mask;
4817 byte *ie;
4818 DIVA_CAPI_ADAPTER * a;
4819 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4820 #define MAXPARMSIDS 31
4821 byte * parms[MAXPARMSIDS];
4822 byte * add_i[4];
4823 byte * multi_fac_parms[MAX_MULTI_IE];
4824 byte * multi_pi_parms [MAX_MULTI_IE];
4825 byte * multi_ssext_parms [MAX_MULTI_IE];
4826 byte * multi_CiPN_parms [MAX_MULTI_IE];
4828 byte * multi_vswitch_parms [MAX_MULTI_IE];
4830 byte ai_len;
4831 byte *esc_chi = "";
4832 byte *esc_law = "";
4833 byte *pty_cai = "";
4834 byte *esc_cr = "";
4835 byte *esc_profile = "";
4837 byte facility[256];
4838 PLCI * tplci = NULL;
4839 byte chi[] = "\x02\x18\x01";
4840 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4841 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4842 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4843 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4844 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4845 /* (see Info_Mask Bit 4, first IE. then the message type) */
4846 word parms_id[] =
4847 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4848 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4849 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4850 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4851 /* 14 FTY repl by ESC_CHI */
4852 /* 18 PI repl by ESC_LAW */
4853 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4854 word multi_fac_id[] = {1, FTY};
4855 word multi_pi_id[] = {1, PI};
4856 word multi_CiPN_id[] = {1, OAD};
4857 word multi_ssext_id[] = {1, ESC_SSEXT};
4859 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4861 byte * cau;
4862 word ncci;
4863 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4864 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4865 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4866 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4867 byte force_mt_info = false;
4868 byte dir;
4869 dword d;
4870 word w;
4872 a = plci->adapter;
4873 Id = ((word)plci->Id<<8)|a->Id;
4874 PUT_WORD(&SS_Ind[4],0x0000);
4876 if (plci->sig_remove_id)
4878 plci->Sig.RNR = 2; /* discard */
4879 dbug(1,dprintf("SIG discard while remove pending"));
4880 return;
4882 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4883 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4884 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4885 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4887 plci->Sig.RNR = 1;
4888 return;
4890 if(plci->Sig.Ind==HANGUP && plci->channels)
4892 plci->Sig.RNR = 1;
4893 plci->hangup_flow_ctrl_timer++;
4894 /* recover the network layer after timeout */
4895 if(plci->hangup_flow_ctrl_timer==100)
4897 dbug(1,dprintf("Exceptional disc"));
4898 plci->Sig.RNR = 0;
4899 plci->hangup_flow_ctrl_timer = 0;
4900 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4902 if (a->ncci_plci[ncci] == plci->Id)
4904 cleanup_ncci_data (plci, ncci);
4905 if(plci->channels)plci->channels--;
4906 if (plci->appl)
4907 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4910 if (plci->appl)
4911 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4912 plci_remove(plci);
4913 plci->State=IDLE;
4915 return;
4918 /* do first parse the info with no OAD in, because OAD will be converted */
4919 /* first the multiple facility IE, then mult. progress ind. */
4920 /* then the parameters for the info_ind + conn_ind */
4921 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4922 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4923 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4925 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4927 IndParse(plci,parms_id,parms,0);
4928 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4929 esc_chi = parms[14];
4930 esc_law = parms[18];
4931 pty_cai = parms[24];
4932 esc_cr = parms[25];
4933 esc_profile = parms[27];
4934 if(esc_cr[0] && plci)
4936 if(plci->cr_enquiry && plci->appl)
4938 plci->cr_enquiry = false;
4939 /* d = MANU_ID */
4940 /* w = m_command */
4941 /* b = total length */
4942 /* b = indication type */
4943 /* b = length of all IEs */
4944 /* b = IE1 */
4945 /* S = IE1 length + cont. */
4946 /* b = IE2 */
4947 /* S = IE2 length + cont. */
4948 sendf(plci->appl,
4949 _MANUFACTURER_I,
4952 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4953 2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law);
4956 /* create the additional info structure */
4957 add_i[1] = parms[15]; /* KEY of additional info */
4958 add_i[2] = parms[11]; /* UUI of additional info */
4959 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4961 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4962 /* indication returns by the card if requested by the function */
4963 /* AutomaticLaw() after driver init */
4964 if (a->automatic_law<4)
4966 if(esc_law[0]){
4967 if(esc_law[2]){
4968 dbug(0,dprintf("u-Law selected"));
4969 a->u_law = 1;
4971 else {
4972 dbug(0,dprintf("a-Law selected"));
4973 a->u_law = 0;
4975 a->automatic_law = 4;
4976 if(plci==a->automatic_lawPLCI) {
4977 plci->internal_command = 0;
4978 sig_req(plci,REMOVE,0);
4979 send_req(plci);
4980 a->automatic_lawPLCI = NULL;
4983 if (esc_profile[0])
4985 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4986 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4987 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4988 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4990 a->profile.Global_Options &= 0x000000ffL;
4991 a->profile.B1_Protocols &= 0x000003ffL;
4992 a->profile.B2_Protocols &= 0x00001fdfL;
4993 a->profile.B3_Protocols &= 0x000000b7L;
4995 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4996 GL_BCHANNEL_OPERATION_SUPPORTED;
4997 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4998 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4999 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5000 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5001 a->man_profile.private_options = 0;
5003 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5005 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5006 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5010 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5011 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5012 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5013 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5016 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5017 a->man_profile.private_options |= 1L << PRIVATE_T38;
5020 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5021 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5024 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5025 a->man_profile.private_options |= 1L << PRIVATE_V18;
5028 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5029 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5032 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5033 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5036 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5037 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5040 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5041 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5044 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5045 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5048 else
5050 a->profile.Global_Options &= 0x0000007fL;
5051 a->profile.B1_Protocols &= 0x000003dfL;
5052 a->profile.B2_Protocols &= 0x00001adfL;
5053 a->profile.B3_Protocols &= 0x000000b7L;
5054 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5056 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5057 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5059 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5061 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5062 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5063 UnMapController (a->Id), a->profile.Global_Options,
5064 a->profile.B1_Protocols, a->profile.B2_Protocols,
5065 a->profile.B3_Protocols, a->manufacturer_features));
5067 /* codec plci for the handset/hook state support is just an internal id */
5068 if(plci!=a->AdvCodecPLCI)
5070 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5071 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5072 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5073 SendInfo(plci,Id, parms, force_mt_info);
5075 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5079 /* switch the codec to the b-channel */
5080 if(esc_chi[0] && plci && !plci->SuppState){
5081 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5082 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5083 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5084 if(plci->tel==ADV_VOICE && plci->appl) {
5085 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5089 if(plci->appl) Number = plci->appl->Number++;
5091 switch(plci->Sig.Ind) {
5092 /* Response to Get_Supported_Services request */
5093 case S_SUPPORTED:
5094 dbug(1,dprintf("S_Supported"));
5095 if(!plci->appl) break;
5096 if(pty_cai[0]==4)
5098 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5100 else
5102 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5104 PUT_WORD (&CF_Ind[1], 0);
5105 PUT_WORD (&CF_Ind[4], 0);
5106 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5107 plci_remove(plci);
5108 break;
5110 /* Supplementary Service rejected */
5111 case S_SERVICE_REJ:
5112 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5113 if(!pty_cai[0]) break;
5114 switch (pty_cai[5])
5116 case ECT_EXECUTE:
5117 case THREE_PTY_END:
5118 case THREE_PTY_BEGIN:
5119 if(!plci->relatedPTYPLCI) break;
5120 tplci = plci->relatedPTYPLCI;
5121 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5122 if(tplci->tel) rId|=EXT_CONTROLLER;
5123 if(pty_cai[5]==ECT_EXECUTE)
5125 PUT_WORD(&SS_Ind[1],S_ECT);
5127 plci->vswitchstate=0;
5128 plci->relatedPTYPLCI->vswitchstate=0;
5131 else
5133 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5135 if(pty_cai[2]!=0xff)
5137 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5139 else
5141 PUT_WORD(&SS_Ind[4],0x300E);
5143 plci->relatedPTYPLCI = NULL;
5144 plci->ptyState = 0;
5145 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5146 break;
5148 case CALL_DEFLECTION:
5149 if(pty_cai[2]!=0xff)
5151 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5153 else
5155 PUT_WORD(&SS_Ind[4],0x300E);
5157 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5158 for(i=0; i<max_appl; i++)
5160 if(application[i].CDEnable)
5162 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5163 application[i].CDEnable = false;
5166 break;
5168 case DEACTIVATION_DIVERSION:
5169 case ACTIVATION_DIVERSION:
5170 case DIVERSION_INTERROGATE_CFU:
5171 case DIVERSION_INTERROGATE_CFB:
5172 case DIVERSION_INTERROGATE_CFNR:
5173 case DIVERSION_INTERROGATE_NUM:
5174 case CCBS_REQUEST:
5175 case CCBS_DEACTIVATE:
5176 case CCBS_INTERROGATE:
5177 if(!plci->appl) break;
5178 if(pty_cai[2]!=0xff)
5180 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5182 else
5184 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5186 switch (pty_cai[5])
5188 case DEACTIVATION_DIVERSION:
5189 dbug(1,dprintf("Deact_Div"));
5190 Interr_Err_Ind[0]=0x9;
5191 Interr_Err_Ind[3]=0x6;
5192 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5193 break;
5194 case ACTIVATION_DIVERSION:
5195 dbug(1,dprintf("Act_Div"));
5196 Interr_Err_Ind[0]=0x9;
5197 Interr_Err_Ind[3]=0x6;
5198 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5199 break;
5200 case DIVERSION_INTERROGATE_CFU:
5201 case DIVERSION_INTERROGATE_CFB:
5202 case DIVERSION_INTERROGATE_CFNR:
5203 dbug(1,dprintf("Interr_Div"));
5204 Interr_Err_Ind[0]=0xa;
5205 Interr_Err_Ind[3]=0x7;
5206 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5207 break;
5208 case DIVERSION_INTERROGATE_NUM:
5209 dbug(1,dprintf("Interr_Num"));
5210 Interr_Err_Ind[0]=0xa;
5211 Interr_Err_Ind[3]=0x7;
5212 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5213 break;
5214 case CCBS_REQUEST:
5215 dbug(1,dprintf("CCBS Request"));
5216 Interr_Err_Ind[0]=0xd;
5217 Interr_Err_Ind[3]=0xa;
5218 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5219 break;
5220 case CCBS_DEACTIVATE:
5221 dbug(1,dprintf("CCBS Deactivate"));
5222 Interr_Err_Ind[0]=0x9;
5223 Interr_Err_Ind[3]=0x6;
5224 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5225 break;
5226 case CCBS_INTERROGATE:
5227 dbug(1,dprintf("CCBS Interrogate"));
5228 Interr_Err_Ind[0]=0xb;
5229 Interr_Err_Ind[3]=0x8;
5230 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5231 break;
5233 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5234 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5235 plci_remove(plci);
5236 break;
5237 case ACTIVATION_MWI:
5238 case DEACTIVATION_MWI:
5239 if(pty_cai[5]==ACTIVATION_MWI)
5241 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5243 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5245 if(pty_cai[2]!=0xff)
5247 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5249 else
5251 PUT_WORD(&SS_Ind[4],0x300E);
5254 if(plci->cr_enquiry)
5256 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5257 plci_remove(plci);
5259 else
5261 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5263 break;
5264 case CONF_ADD: /* ERROR */
5265 case CONF_BEGIN:
5266 case CONF_DROP:
5267 case CONF_ISOLATE:
5268 case CONF_REATTACH:
5269 CONF_Ind[0]=9;
5270 CONF_Ind[3]=6;
5271 switch(pty_cai[5])
5273 case CONF_BEGIN:
5274 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5275 plci->ptyState = 0;
5276 break;
5277 case CONF_DROP:
5278 CONF_Ind[0]=5;
5279 CONF_Ind[3]=2;
5280 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5281 plci->ptyState = CONNECTED;
5282 break;
5283 case CONF_ISOLATE:
5284 CONF_Ind[0]=5;
5285 CONF_Ind[3]=2;
5286 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5287 plci->ptyState = CONNECTED;
5288 break;
5289 case CONF_REATTACH:
5290 CONF_Ind[0]=5;
5291 CONF_Ind[3]=2;
5292 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5293 plci->ptyState = CONNECTED;
5294 break;
5295 case CONF_ADD:
5296 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5297 plci->relatedPTYPLCI = NULL;
5298 tplci=plci->relatedPTYPLCI;
5299 if(tplci) tplci->ptyState = CONNECTED;
5300 plci->ptyState = CONNECTED;
5301 break;
5304 if(pty_cai[2]!=0xff)
5306 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5308 else
5310 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5311 within the required time */
5314 PUT_DWORD(&CONF_Ind[6],0x0);
5315 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5316 break;
5318 break;
5320 /* Supplementary Service indicates success */
5321 case S_SERVICE:
5322 dbug(1,dprintf("Service_Ind"));
5323 PUT_WORD (&CF_Ind[4], 0);
5324 switch (pty_cai[5])
5326 case THREE_PTY_END:
5327 case THREE_PTY_BEGIN:
5328 case ECT_EXECUTE:
5329 if(!plci->relatedPTYPLCI) break;
5330 tplci = plci->relatedPTYPLCI;
5331 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5332 if(tplci->tel) rId|=EXT_CONTROLLER;
5333 if(pty_cai[5]==ECT_EXECUTE)
5335 PUT_WORD(&SS_Ind[1],S_ECT);
5337 if(plci->vswitchstate!=3)
5340 plci->ptyState = IDLE;
5341 plci->relatedPTYPLCI = NULL;
5342 plci->ptyState = 0;
5346 dbug(1,dprintf("ECT OK"));
5347 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5352 else
5354 switch (plci->ptyState)
5356 case S_3PTY_BEGIN:
5357 plci->ptyState = CONNECTED;
5358 dbug(1,dprintf("3PTY ON"));
5359 break;
5361 case S_3PTY_END:
5362 plci->ptyState = IDLE;
5363 plci->relatedPTYPLCI = NULL;
5364 plci->ptyState = 0;
5365 dbug(1,dprintf("3PTY OFF"));
5366 break;
5368 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5369 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5371 break;
5373 case CALL_DEFLECTION:
5374 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5375 for(i=0; i<max_appl; i++)
5377 if(application[i].CDEnable)
5379 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5380 application[i].CDEnable = false;
5383 break;
5385 case DEACTIVATION_DIVERSION:
5386 case ACTIVATION_DIVERSION:
5387 if(!plci->appl) break;
5388 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5389 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5390 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5391 plci_remove(plci);
5392 break;
5394 case DIVERSION_INTERROGATE_CFU:
5395 case DIVERSION_INTERROGATE_CFB:
5396 case DIVERSION_INTERROGATE_CFNR:
5397 case DIVERSION_INTERROGATE_NUM:
5398 case CCBS_REQUEST:
5399 case CCBS_DEACTIVATE:
5400 case CCBS_INTERROGATE:
5401 if(!plci->appl) break;
5402 switch (pty_cai[5])
5404 case DIVERSION_INTERROGATE_CFU:
5405 case DIVERSION_INTERROGATE_CFB:
5406 case DIVERSION_INTERROGATE_CFNR:
5407 dbug(1,dprintf("Interr_Div"));
5408 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5409 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5410 break;
5411 case DIVERSION_INTERROGATE_NUM:
5412 dbug(1,dprintf("Interr_Num"));
5413 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5414 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5415 break;
5416 case CCBS_REQUEST:
5417 dbug(1,dprintf("CCBS Request"));
5418 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5419 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5420 break;
5421 case CCBS_DEACTIVATE:
5422 dbug(1,dprintf("CCBS Deactivate"));
5423 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5424 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5425 break;
5426 case CCBS_INTERROGATE:
5427 dbug(1,dprintf("CCBS Interrogate"));
5428 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5429 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430 break;
5432 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5433 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5434 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5435 plci_remove(plci);
5436 break;
5438 case ACTIVATION_MWI:
5439 case DEACTIVATION_MWI:
5440 if(pty_cai[5]==ACTIVATION_MWI)
5442 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5444 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5445 if(plci->cr_enquiry)
5447 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5448 plci_remove(plci);
5450 else
5452 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5454 break;
5455 case MWI_INDICATION:
5456 if(pty_cai[0]>=0x12)
5458 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5459 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5460 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5461 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5463 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5465 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5466 plci_remove(plci);
5467 return;
5469 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5470 pty_cai[0]=0;
5472 else
5474 for(i=0; i<max_appl; i++)
5476 if(a->Notification_Mask[i]&SMASK_MWI)
5478 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5479 pty_cai[0]=0;
5484 if(!pty_cai[0])
5485 { /* acknowledge */
5486 facility[2]= 0; /* returncode */
5488 else facility[2]= 0xff;
5490 else
5492 /* reject */
5493 facility[2]= 0xff; /* returncode */
5495 facility[0]= 2;
5496 facility[1]= MWI_RESPONSE; /* Function */
5497 add_p(plci,CAI,facility);
5498 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5499 sig_req(plci,S_SERVICE,0);
5500 send_req(plci);
5501 plci->command = 0;
5502 next_internal_command (Id, plci);
5503 break;
5504 case CONF_ADD: /* OK */
5505 case CONF_BEGIN:
5506 case CONF_DROP:
5507 case CONF_ISOLATE:
5508 case CONF_REATTACH:
5509 case CONF_PARTYDISC:
5510 CONF_Ind[0]=9;
5511 CONF_Ind[3]=6;
5512 switch(pty_cai[5])
5514 case CONF_BEGIN:
5515 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5516 if(pty_cai[0]==6)
5518 d=pty_cai[6];
5519 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5521 else
5523 PUT_DWORD(&CONF_Ind[6],0x0);
5525 break;
5526 case CONF_ISOLATE:
5527 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5528 CONF_Ind[0]=5;
5529 CONF_Ind[3]=2;
5530 break;
5531 case CONF_REATTACH:
5532 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5533 CONF_Ind[0]=5;
5534 CONF_Ind[3]=2;
5535 break;
5536 case CONF_DROP:
5537 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5538 CONF_Ind[0]=5;
5539 CONF_Ind[3]=2;
5540 break;
5541 case CONF_ADD:
5542 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5543 d=pty_cai[6];
5544 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5545 tplci=plci->relatedPTYPLCI;
5546 if(tplci) tplci->ptyState = CONNECTED;
5547 break;
5548 case CONF_PARTYDISC:
5549 CONF_Ind[0]=7;
5550 CONF_Ind[3]=4;
5551 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5552 d=pty_cai[6];
5553 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5554 break;
5556 plci->ptyState = CONNECTED;
5557 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5558 break;
5559 case CCBS_INFO_RETAIN:
5560 case CCBS_ERASECALLLINKAGEID:
5561 case CCBS_STOP_ALERTING:
5562 CONF_Ind[0]=5;
5563 CONF_Ind[3]=2;
5564 switch(pty_cai[5])
5566 case CCBS_INFO_RETAIN:
5567 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5568 break;
5569 case CCBS_STOP_ALERTING:
5570 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5571 break;
5572 case CCBS_ERASECALLLINKAGEID:
5573 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5574 CONF_Ind[0]=7;
5575 CONF_Ind[3]=4;
5576 CONF_Ind[6]=0;
5577 CONF_Ind[7]=0;
5578 break;
5580 w=pty_cai[6];
5581 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5583 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5585 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5587 else
5589 for(i=0; i<max_appl; i++)
5590 if(a->Notification_Mask[i]&SMASK_CCBS)
5591 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5593 break;
5595 break;
5596 case CALL_HOLD_REJ:
5597 cau = parms[7];
5598 if(cau)
5600 i = _L3_CAUSE | cau[2];
5601 if(cau[2]==0) i = 0x3603;
5603 else
5605 i = 0x3603;
5607 PUT_WORD(&SS_Ind[1],S_HOLD);
5608 PUT_WORD(&SS_Ind[4],i);
5609 if(plci->SuppState == HOLD_REQUEST)
5611 plci->SuppState = IDLE;
5612 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5614 break;
5616 case CALL_HOLD_ACK:
5617 if(plci->SuppState == HOLD_REQUEST)
5619 plci->SuppState = CALL_HELD;
5620 CodecIdCheck(a, plci);
5621 start_internal_command (Id, plci, hold_save_command);
5623 break;
5625 case CALL_RETRIEVE_REJ:
5626 cau = parms[7];
5627 if(cau)
5629 i = _L3_CAUSE | cau[2];
5630 if(cau[2]==0) i = 0x3603;
5632 else
5634 i = 0x3603;
5636 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5637 PUT_WORD(&SS_Ind[4],i);
5638 if(plci->SuppState == RETRIEVE_REQUEST)
5640 plci->SuppState = CALL_HELD;
5641 CodecIdCheck(a, plci);
5642 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5644 break;
5646 case CALL_RETRIEVE_ACK:
5647 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5648 if(plci->SuppState == RETRIEVE_REQUEST)
5650 plci->SuppState = IDLE;
5651 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5652 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5653 if(plci->tel)
5655 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5656 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5657 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5658 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5660 dbug(1,dprintf("Get B-ch"));
5661 start_internal_command (Id, plci, retrieve_restore_command);
5663 else
5664 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5666 else
5667 start_internal_command (Id, plci, retrieve_restore_command);
5669 break;
5671 case INDICATE_IND:
5672 if(plci->State != LISTENING) {
5673 sig_req(plci,HANGUP,0);
5674 send_req(plci);
5675 break;
5677 cip = find_cip(a,parms[4],parms[6]);
5678 cip_mask = 1L<<cip;
5679 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5680 clear_c_ind_mask (plci);
5681 if (!remove_started && !a->adapter_disabled)
5683 set_c_ind_mask_bit (plci, MAX_APPL);
5684 group_optimization(a, plci);
5685 for(i=0; i<max_appl; i++) {
5686 if(application[i].Id
5687 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5688 && CPN_filter_ok(parms[0],a,i)
5689 && test_group_ind_mask_bit (plci, i) ) {
5690 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5691 set_c_ind_mask_bit (plci, i);
5692 dump_c_ind_mask (plci);
5693 plci->State = INC_CON_PENDING;
5694 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5695 CALL_DIR_IN | CALL_DIR_ANSWER;
5696 if(esc_chi[0]) {
5697 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5698 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5700 /* if a listen on the ext controller is done, check if hook states */
5701 /* are supported or if just a on board codec must be activated */
5702 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5703 if(a->profile.Global_Options & HANDSET)
5704 plci->tel = ADV_VOICE;
5705 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5706 plci->tel = CODEC;
5707 if(plci->tel) Id|=EXT_CONTROLLER;
5708 a->codec_listen[i] = plci;
5711 sendf(&application[i],_CONNECT_I,Id,0,
5712 "wSSSSSSSbSSSSS", cip, /* CIP */
5713 parms[0], /* CalledPartyNumber */
5714 multi_CiPN_parms[0], /* CallingPartyNumber */
5715 parms[2], /* CalledPartySubad */
5716 parms[3], /* CallingPartySubad */
5717 parms[4], /* BearerCapability */
5718 parms[5], /* LowLC */
5719 parms[6], /* HighLC */
5720 ai_len, /* nested struct add_i */
5721 add_i[0], /* B channel info */
5722 add_i[1], /* keypad facility */
5723 add_i[2], /* user user data */
5724 add_i[3], /* nested facility */
5725 multi_CiPN_parms[1] /* second CiPN(SCR) */
5727 SendSSExtInd(&application[i],
5728 plci,
5730 multi_ssext_parms);
5731 SendSetupInfo(&application[i],
5732 plci,
5734 parms,
5735 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5738 clear_c_ind_mask_bit (plci, MAX_APPL);
5739 dump_c_ind_mask (plci);
5741 if(c_ind_mask_empty (plci)) {
5742 sig_req(plci,HANGUP,0);
5743 send_req(plci);
5744 plci->State = IDLE;
5746 plci->notifiedcall = 0;
5747 a->listen_active--;
5748 listen_check(a);
5749 break;
5751 case CALL_PEND_NOTIFY:
5752 plci->notifiedcall = 1;
5753 listen_check(a);
5754 break;
5756 case CALL_IND:
5757 case CALL_CON:
5758 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5760 if(plci->internal_command==PERM_COD_CONN_PEND)
5762 if(plci->State==ADVANCED_VOICE_NOSIG)
5764 dbug(1,dprintf("***Codec OK"));
5765 if(a->AdvSignalPLCI)
5767 tplci = a->AdvSignalPLCI;
5768 if(tplci->spoofed_msg)
5770 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5771 tplci->command = 0;
5772 tplci->internal_command = 0;
5773 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5774 switch (tplci->spoofed_msg)
5776 case CALL_RES:
5777 tplci->command = _CONNECT_I|RESPONSE;
5778 api_load_msg (&tplci->saved_msg, saved_parms);
5779 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5780 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5782 /* early B3 connect (CIP mask bit 9) no release after a disc */
5783 add_p(tplci,LLI,"\x01\x01");
5785 add_s(tplci, CONN_NR, &saved_parms[2]);
5786 add_s(tplci, LLC, &saved_parms[4]);
5787 add_ai(tplci, &saved_parms[5]);
5788 tplci->State = INC_CON_ACCEPT;
5789 sig_req(tplci, CALL_RES,0);
5790 send_req(tplci);
5791 break;
5793 case AWAITING_SELECT_B:
5794 dbug(1,dprintf("Select_B continue"));
5795 start_internal_command (x_Id, tplci, select_b_command);
5796 break;
5798 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5799 if(!tplci->Sig.Id)
5801 dbug(1,dprintf("No SigID!"));
5802 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5803 plci_remove(tplci);
5804 break;
5806 tplci->command = _MANUFACTURER_R;
5807 api_load_msg (&tplci->saved_msg, saved_parms);
5808 dir = saved_parms[2].info[0];
5809 if(dir==1) {
5810 sig_req(tplci,CALL_REQ,0);
5812 else if(!dir){
5813 sig_req(tplci,LISTEN_REQ,0);
5815 send_req(tplci);
5816 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5817 break;
5819 case (CALL_REQ|AWAITING_MANUF_CON):
5820 sig_req(tplci,CALL_REQ,0);
5821 send_req(tplci);
5822 break;
5824 case CALL_REQ:
5825 if(!tplci->Sig.Id)
5827 dbug(1,dprintf("No SigID!"));
5828 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5829 plci_remove(tplci);
5830 break;
5832 tplci->command = _CONNECT_R;
5833 api_load_msg (&tplci->saved_msg, saved_parms);
5834 add_s(tplci,CPN,&saved_parms[1]);
5835 add_s(tplci,DSA,&saved_parms[3]);
5836 add_ai(tplci,&saved_parms[9]);
5837 sig_req(tplci,CALL_REQ,0);
5838 send_req(tplci);
5839 break;
5841 case CALL_RETRIEVE:
5842 tplci->command = C_RETRIEVE_REQ;
5843 sig_req(tplci,CALL_RETRIEVE,0);
5844 send_req(tplci);
5845 break;
5847 tplci->spoofed_msg = 0;
5848 if (tplci->internal_command == 0)
5849 next_internal_command (x_Id, tplci);
5852 next_internal_command (Id, plci);
5853 break;
5855 dbug(1,dprintf("***Codec Hook Init Req"));
5856 plci->internal_command = PERM_COD_HOOK;
5857 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5858 sig_req(plci,TEL_CTRL,0);
5859 send_req(plci);
5862 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5863 && plci->State!=INC_ACT_PENDING)
5865 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5866 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5868 chi[2] = plci->b_channel;
5869 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5871 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5872 plci->State = INC_ACT_PENDING;
5874 break;
5876 case TEL_CTRL:
5877 Number = 0;
5878 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5879 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5880 switch (ie[1]&0x91) {
5881 case 0x80: /* hook off */
5882 case 0x81:
5883 if(plci->internal_command==PERM_COD_HOOK)
5885 dbug(1,dprintf("init:hook_off"));
5886 plci->hook_state = ie[1];
5887 next_internal_command (Id, plci);
5888 break;
5890 else /* ignore doubled hook indications */
5892 if( ((plci->hook_state)&0xf0)==0x80)
5894 dbug(1,dprintf("ignore hook"));
5895 break;
5897 plci->hook_state = ie[1]&0x91;
5899 /* check for incoming call pending */
5900 /* and signal '+'.Appl must decide */
5901 /* with connect_res if call must */
5902 /* accepted or not */
5903 for(i=0, tplci=NULL;i<max_appl;i++){
5904 if(a->codec_listen[i]
5905 && (a->codec_listen[i]->State==INC_CON_PENDING
5906 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5907 tplci = a->codec_listen[i];
5908 tplci->appl = &application[i];
5911 /* no incoming call, do outgoing call */
5912 /* and signal '+' if outg. setup */
5913 if(!a->AdvSignalPLCI && !tplci){
5914 if((i=get_plci(a))) {
5915 a->AdvSignalPLCI = &a->plci[i-1];
5916 tplci = a->AdvSignalPLCI;
5917 tplci->tel = ADV_VOICE;
5918 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5919 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5920 /* early B3 connect (CIP mask bit 9) no release after a disc */
5921 add_p(tplci,LLI,"\x01\x01");
5923 add_p(tplci, CAI, voice_cai);
5924 add_p(tplci, OAD, a->TelOAD);
5925 add_p(tplci, OSA, a->TelOSA);
5926 add_p(tplci,SHIFT|6,NULL);
5927 add_p(tplci,SIN,"\x02\x01\x00");
5928 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5929 sig_req(tplci,ASSIGN,DSIG_ID);
5930 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5931 a->AdvSignalPLCI->command = 0;
5932 tplci->appl = a->AdvSignalAppl;
5933 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5934 send_req(tplci);
5939 if(!tplci) break;
5940 Id = ((word)tplci->Id<<8)|a->Id;
5941 Id|=EXT_CONTROLLER;
5942 sendf(tplci->appl,
5943 _FACILITY_I,
5946 "ws", (word)0, "\x01+");
5947 break;
5949 case 0x90: /* hook on */
5950 case 0x91:
5951 if(plci->internal_command==PERM_COD_HOOK)
5953 dbug(1,dprintf("init:hook_on"));
5954 plci->hook_state = ie[1]&0x91;
5955 next_internal_command (Id, plci);
5956 break;
5958 else /* ignore doubled hook indications */
5960 if( ((plci->hook_state)&0xf0)==0x90) break;
5961 plci->hook_state = ie[1]&0x91;
5963 /* hangup the adv. voice call and signal '-' to the appl */
5964 if(a->AdvSignalPLCI) {
5965 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5966 if(plci->tel) Id|=EXT_CONTROLLER;
5967 sendf(a->AdvSignalAppl,
5968 _FACILITY_I,
5971 "ws", (word)0, "\x01-");
5972 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5973 a->AdvSignalPLCI->command = 0;
5974 sig_req(a->AdvSignalPLCI,HANGUP,0);
5975 send_req(a->AdvSignalPLCI);
5977 break;
5980 break;
5982 case RESUME:
5983 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5984 PUT_WORD(&resume_cau[4],GOOD);
5985 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5986 break;
5988 case SUSPEND:
5989 clear_c_ind_mask (plci);
5991 if (plci->NL.Id && !plci->nl_remove_id) {
5992 mixer_remove (plci);
5993 nl_req_ncci(plci,REMOVE,0);
5995 if (!plci->sig_remove_id) {
5996 plci->internal_command = 0;
5997 sig_req(plci,REMOVE,0);
5999 send_req(plci);
6000 if(!plci->channels) {
6001 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6002 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6004 break;
6006 case SUSPEND_REJ:
6007 break;
6009 case HANGUP:
6010 plci->hangup_flow_ctrl_timer=0;
6011 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6012 cau = parms[7];
6013 if(cau) {
6014 i = _L3_CAUSE | cau[2];
6015 if(cau[2]==0) i = 0;
6016 else if(cau[2]==8) i = _L1_ERROR;
6017 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6018 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6020 else {
6021 i = _L3_ERROR;
6024 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6026 for(i=0; i<max_appl; i++)
6028 if(test_c_ind_mask_bit (plci, i))
6029 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6032 else
6034 clear_c_ind_mask (plci);
6036 if(!plci->appl)
6038 if (plci->State == LISTENING)
6040 plci->notifiedcall=0;
6041 a->listen_active--;
6043 plci->State = INC_DIS_PENDING;
6044 if(c_ind_mask_empty (plci))
6046 plci->State = IDLE;
6047 if (plci->NL.Id && !plci->nl_remove_id)
6049 mixer_remove (plci);
6050 nl_req_ncci(plci,REMOVE,0);
6052 if (!plci->sig_remove_id)
6054 plci->internal_command = 0;
6055 sig_req(plci,REMOVE,0);
6057 send_req(plci);
6060 else
6062 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6063 /* result in a second HANGUP! Don't generate another */
6064 /* DISCONNECT */
6065 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6067 if(plci->State==RESUMING)
6069 PUT_WORD(&resume_cau[4],i);
6070 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6072 plci->State = INC_DIS_PENDING;
6073 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6076 break;
6078 case SSEXT_IND:
6079 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6080 break;
6082 case VSWITCH_REQ:
6083 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6084 break;
6085 case VSWITCH_IND:
6086 if(plci->relatedPTYPLCI &&
6087 plci->vswitchstate==3 &&
6088 plci->relatedPTYPLCI->vswitchstate==3 &&
6089 parms[MAXPARMSIDS-1][0])
6091 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6092 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6093 send_req(plci->relatedPTYPLCI);
6095 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6096 break;
6102 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6104 word i;
6105 byte * ie;
6106 word Info_Number;
6107 byte * Info_Element;
6108 word Info_Mask = 0;
6110 dbug(1,dprintf("SetupInfo"));
6112 for(i=0; i<MAXPARMSIDS; i++) {
6113 ie = parms[i];
6114 Info_Number = 0;
6115 Info_Element = ie;
6116 if(ie[0]) {
6117 switch(i) {
6118 case 0:
6119 dbug(1,dprintf("CPN "));
6120 Info_Number = 0x0070;
6121 Info_Mask = 0x80;
6122 Info_Sent_Flag = true;
6123 break;
6124 case 8: /* display */
6125 dbug(1,dprintf("display(%d)",i));
6126 Info_Number = 0x0028;
6127 Info_Mask = 0x04;
6128 Info_Sent_Flag = true;
6129 break;
6130 case 16: /* Channel Id */
6131 dbug(1,dprintf("CHI"));
6132 Info_Number = 0x0018;
6133 Info_Mask = 0x100;
6134 Info_Sent_Flag = true;
6135 mixer_set_bchannel_id (plci, Info_Element);
6136 break;
6137 case 19: /* Redirected Number */
6138 dbug(1,dprintf("RDN"));
6139 Info_Number = 0x0074;
6140 Info_Mask = 0x400;
6141 Info_Sent_Flag = true;
6142 break;
6143 case 20: /* Redirected Number extended */
6144 dbug(1,dprintf("RDX"));
6145 Info_Number = 0x0073;
6146 Info_Mask = 0x400;
6147 Info_Sent_Flag = true;
6148 break;
6149 case 22: /* Redirecing Number */
6150 dbug(1,dprintf("RIN"));
6151 Info_Number = 0x0076;
6152 Info_Mask = 0x400;
6153 Info_Sent_Flag = true;
6154 break;
6155 default:
6156 Info_Number = 0;
6157 break;
6161 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6162 Info_Number = 0x8000 |5;
6163 Info_Mask = 0x10;
6164 Info_Element = "";
6167 if(Info_Sent_Flag && Info_Number){
6168 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6169 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6176 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6178 word i;
6179 word j;
6180 word k;
6181 byte * ie;
6182 word Info_Number;
6183 byte * Info_Element;
6184 word Info_Mask = 0;
6185 static byte charges[5] = {4,0,0,0,0};
6186 static byte cause[] = {0x02,0x80,0x00};
6187 APPL *appl;
6189 dbug(1,dprintf("InfoParse "));
6192 !plci->appl
6193 && !plci->State
6194 && plci->Sig.Ind!=NCR_FACILITY
6197 dbug(1,dprintf("NoParse "));
6198 return;
6200 cause[2] = 0;
6201 for(i=0; i<MAXPARMSIDS; i++) {
6202 ie = parms[i];
6203 Info_Number = 0;
6204 Info_Element = ie;
6205 if(ie[0]) {
6206 switch(i) {
6207 case 0:
6208 dbug(1,dprintf("CPN "));
6209 Info_Number = 0x0070;
6210 Info_Mask = 0x80;
6211 break;
6212 case 7: /* ESC_CAU */
6213 dbug(1,dprintf("cau(0x%x)",ie[2]));
6214 Info_Number = 0x0008;
6215 Info_Mask = 0x00;
6216 cause[2] = ie[2];
6217 Info_Element = NULL;
6218 break;
6219 case 8: /* display */
6220 dbug(1,dprintf("display(%d)",i));
6221 Info_Number = 0x0028;
6222 Info_Mask = 0x04;
6223 break;
6224 case 9: /* Date display */
6225 dbug(1,dprintf("date(%d)",i));
6226 Info_Number = 0x0029;
6227 Info_Mask = 0x02;
6228 break;
6229 case 10: /* charges */
6230 for(j=0;j<4;j++) charges[1+j] = 0;
6231 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6232 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6233 Info_Number = 0x4000;
6234 Info_Mask = 0x40;
6235 Info_Element = charges;
6236 break;
6237 case 11: /* user user info */
6238 dbug(1,dprintf("uui"));
6239 Info_Number = 0x007E;
6240 Info_Mask = 0x08;
6241 break;
6242 case 12: /* congestion receiver ready */
6243 dbug(1,dprintf("clRDY"));
6244 Info_Number = 0x00B0;
6245 Info_Mask = 0x08;
6246 Info_Element = "";
6247 break;
6248 case 13: /* congestion receiver not ready */
6249 dbug(1,dprintf("clNRDY"));
6250 Info_Number = 0x00BF;
6251 Info_Mask = 0x08;
6252 Info_Element = "";
6253 break;
6254 case 15: /* Keypad Facility */
6255 dbug(1,dprintf("KEY"));
6256 Info_Number = 0x002C;
6257 Info_Mask = 0x20;
6258 break;
6259 case 16: /* Channel Id */
6260 dbug(1,dprintf("CHI"));
6261 Info_Number = 0x0018;
6262 Info_Mask = 0x100;
6263 mixer_set_bchannel_id (plci, Info_Element);
6264 break;
6265 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6266 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6267 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6268 Info_Number = 0x0008;
6269 Info_Mask = 0x01;
6270 if(cause[2] != ie[2]) Info_Element = cause;
6271 break;
6272 case 19: /* Redirected Number */
6273 dbug(1,dprintf("RDN"));
6274 Info_Number = 0x0074;
6275 Info_Mask = 0x400;
6276 break;
6277 case 22: /* Redirecing Number */
6278 dbug(1,dprintf("RIN"));
6279 Info_Number = 0x0076;
6280 Info_Mask = 0x400;
6281 break;
6282 case 23: /* Notification Indicator */
6283 dbug(1,dprintf("NI"));
6284 Info_Number = (word)NI;
6285 Info_Mask = 0x210;
6286 break;
6287 case 26: /* Call State */
6288 dbug(1,dprintf("CST"));
6289 Info_Number = (word)CST;
6290 Info_Mask = 0x01; /* do with cause i.e. for now */
6291 break;
6292 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6293 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6294 Info_Number = 0x8000 |ie[3];
6295 if(iesent) Info_Mask = 0xffff;
6296 else Info_Mask = 0x10;
6297 Info_Element = "";
6298 break;
6299 default:
6300 Info_Number = 0;
6301 Info_Mask = 0;
6302 Info_Element = "";
6303 break;
6307 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6309 for(j=0; j<max_appl; j++)
6311 appl = &application[j];
6312 if(Info_Number
6313 && appl->Id
6314 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6316 dbug(1,dprintf("NCR_Ind"));
6317 iesent=true;
6318 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6322 else if(!plci->appl)
6323 { /* overlap receiving broadcast */
6324 if(Info_Number==CPN
6325 || Info_Number==KEY
6326 || Info_Number==NI
6327 || Info_Number==DSP
6328 || Info_Number==UUI )
6330 for(j=0; j<max_appl; j++)
6332 if(test_c_ind_mask_bit (plci, j))
6334 dbug(1,dprintf("Ovl_Ind"));
6335 iesent=true;
6336 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6340 } /* all other signalling states */
6341 else if(Info_Number
6342 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6344 dbug(1,dprintf("Std_Ind"));
6345 iesent=true;
6346 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6352 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6353 dword info_mask, byte setupParse)
6355 word i;
6356 word j;
6357 byte * ie;
6358 word Info_Number;
6359 byte * Info_Element;
6360 APPL *appl;
6361 word Info_Mask = 0;
6362 byte iesent=0;
6365 !plci->appl
6366 && !plci->State
6367 && plci->Sig.Ind!=NCR_FACILITY
6368 && !setupParse
6371 dbug(1,dprintf("NoM-IEParse "));
6372 return 0;
6374 dbug(1,dprintf("M-IEParse "));
6376 for(i=0; i<MAX_MULTI_IE; i++)
6378 ie = parms[i];
6379 Info_Number = 0;
6380 Info_Element = ie;
6381 if(ie[0])
6383 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6384 Info_Number = (word)ie_type;
6385 Info_Mask = (word)info_mask;
6388 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6390 for(j=0; j<max_appl; j++)
6392 appl = &application[j];
6393 if(Info_Number
6394 && appl->Id
6395 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6397 iesent = true;
6398 dbug(1,dprintf("Mlt_NCR_Ind"));
6399 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6403 else if(!plci->appl && Info_Number)
6404 { /* overlap receiving broadcast */
6405 for(j=0; j<max_appl; j++)
6407 if(test_c_ind_mask_bit (plci, j))
6409 iesent = true;
6410 dbug(1,dprintf("Mlt_Ovl_Ind"));
6411 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6414 } /* all other signalling states */
6415 else if(Info_Number
6416 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6418 iesent = true;
6419 dbug(1,dprintf("Mlt_Std_Ind"));
6420 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6423 return iesent;
6426 static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6428 word i;
6429 /* Format of multi_ssext_parms[i][]:
6430 0 byte length
6431 1 byte SSEXTIE
6432 2 byte SSEXT_REQ/SSEXT_IND
6433 3 byte length
6434 4 word SSExtCommand
6435 6... Params
6438 plci
6439 && plci->State
6440 && plci->Sig.Ind!=NCR_FACILITY
6442 for(i=0;i<MAX_MULTI_IE;i++)
6444 if(parms[i][0]<6) continue;
6445 if(parms[i][2]==SSEXT_REQ) continue;
6447 if(appl)
6449 parms[i][0]=0; /* kill it */
6450 sendf(appl,_MANUFACTURER_I,
6453 "dwS",
6454 _DI_MANU_ID,
6455 _DI_SSEXT_CTRL,
6456 &parms[i][3]);
6458 else if(plci->appl)
6460 parms[i][0]=0; /* kill it */
6461 sendf(plci->appl,_MANUFACTURER_I,
6464 "dwS",
6465 _DI_MANU_ID,
6466 _DI_SSEXT_CTRL,
6467 &parms[i][3]);
6472 static void nl_ind(PLCI *plci)
6474 byte ch;
6475 word ncci;
6476 dword Id;
6477 DIVA_CAPI_ADAPTER * a;
6478 word NCCIcode;
6479 APPL * APPLptr;
6480 word count;
6481 word Num;
6482 word i, ncpi_state;
6483 byte len, ncci_state;
6484 word msg;
6485 word info = 0;
6486 word fax_feature_bits;
6487 byte fax_send_edata_ack;
6488 static byte v120_header_buffer[2 + 3] __attribute__ ((aligned(8)));
6489 static word fax_info[] = {
6490 0, /* T30_SUCCESS */
6491 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6492 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6493 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6494 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6495 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6496 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6497 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6498 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6499 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6500 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6501 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6502 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6503 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6504 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6505 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6509 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6511 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6523 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6524 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6525 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6527 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6528 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6529 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6530 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6535 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6536 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6539 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6542 static word rtp_info[] = {
6543 GOOD, /* RTP_SUCCESS */
6544 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6547 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6549 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6550 0x00000000, 0x00000000, 0x00000000, 0x00000000
6553 ch = plci->NL.IndCh;
6554 a = plci->adapter;
6555 ncci = a->ch_ncci[ch];
6556 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6557 if(plci->tel) Id|=EXT_CONTROLLER;
6558 APPLptr = plci->appl;
6559 dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6560 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6562 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6564 if (plci->nl_remove_id)
6566 plci->NL.RNR = 2; /* discard */
6567 dbug(1,dprintf("NL discard while remove pending"));
6568 return;
6570 if((plci->NL.Ind &0x0f)==N_CONNECT)
6572 if(plci->State==INC_DIS_PENDING
6573 || plci->State==OUTG_DIS_PENDING
6574 || plci->State==IDLE)
6576 plci->NL.RNR = 2; /* discard */
6577 dbug(1,dprintf("discard n_connect"));
6578 return;
6580 if(plci->State < INC_ACT_PENDING)
6582 plci->NL.RNR = 1; /* flow control */
6583 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6584 return;
6588 if(!APPLptr) /* no application or invalid data */
6589 { /* while reloading the DSP */
6590 dbug(1,dprintf("discard1"));
6591 plci->NL.RNR = 2;
6592 return;
6595 if (((plci->NL.Ind &0x0f) == N_UDATA)
6596 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6597 || (plci->B2_prot == 7)
6598 || (plci->B3_prot == 7)) )
6600 plci->ncpi_buffer[0] = 0;
6602 ncpi_state = plci->ncpi_state;
6603 if (plci->NL.complete == 1)
6605 byte * data = &plci->NL.RBuffer->P[0];
6607 if ((plci->NL.RBuffer->length >= 12)
6608 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6609 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6611 word conn_opt, ncpi_opt = 0x00;
6612 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6614 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6615 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6616 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6617 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6619 data++; /* indication code */
6620 data += 2; /* timestamp */
6621 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6622 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6623 data++; /* connected norm */
6624 conn_opt = GET_WORD(data);
6625 data += 2; /* connected options */
6627 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6629 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6631 ncpi_opt |= MDM_NCPI_ECM_V42;
6633 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6635 ncpi_opt |= MDM_NCPI_ECM_MNP;
6637 else
6639 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6641 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6643 ncpi_opt |= MDM_NCPI_COMPRESSED;
6645 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6646 plci->ncpi_buffer[0] = 4;
6648 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6651 if (plci->B3_prot == 7)
6653 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6654 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6655 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6657 a->ncci_state[ncci] = INC_ACT_PENDING;
6658 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6659 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6663 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6664 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6665 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6666 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6669 plci->NL.RNR = 2;
6670 return;
6674 if(plci->NL.complete == 2)
6676 if (((plci->NL.Ind &0x0f) == N_UDATA)
6677 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6679 switch(plci->RData[0].P[0])
6682 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6683 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6684 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6685 break;
6686 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6687 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6688 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6689 break;
6690 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6691 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6692 break;
6693 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6694 dtmf_confirmation (Id, plci);
6695 break;
6698 case UDATA_INDICATION_MIXER_TAP_DATA:
6699 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6700 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6701 if (i != 0)
6703 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6704 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6706 break;
6709 case UDATA_INDICATION_MIXER_COEFS_SET:
6710 mixer_indication_coefs_set (Id, plci);
6711 break;
6712 case UDATA_INDICATION_XCONNECT_FROM:
6713 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714 break;
6715 case UDATA_INDICATION_XCONNECT_TO:
6716 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6717 break;
6720 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6721 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6722 break;
6726 default:
6727 break;
6730 else
6732 if ((plci->RData[0].PLength != 0)
6733 && ((plci->B2_prot == B2_V120_ASYNC)
6734 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6735 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6738 sendf(plci->appl,_DATA_B3_I,Id,0,
6739 "dwww",
6740 plci->RData[1].P,
6741 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6742 plci->RNum,
6743 plci->RFlags);
6746 else
6749 sendf(plci->appl,_DATA_B3_I,Id,0,
6750 "dwww",
6751 plci->RData[0].P,
6752 plci->RData[0].PLength,
6753 plci->RNum,
6754 plci->RFlags);
6758 return;
6761 fax_feature_bits = 0;
6762 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6763 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6764 (plci->NL.Ind &0x0f)==N_DISC ||
6765 (plci->NL.Ind &0x0f)==N_EDATA ||
6766 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6768 info = 0;
6769 plci->ncpi_buffer[0] = 0;
6770 switch (plci->B3_prot) {
6771 case 0: /*XPARENT*/
6772 case 1: /*T.90 NL*/
6773 break; /* no network control protocol info - jfr */
6774 case 2: /*ISO8202*/
6775 case 3: /*X25 DCE*/
6776 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6777 plci->ncpi_buffer[0] = (byte)(i+3);
6778 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6779 plci->ncpi_buffer[2] = 0;
6780 plci->ncpi_buffer[3] = 0;
6781 break;
6782 case 4: /*T.30 - FAX*/
6783 case 5: /*T.30 - FAX*/
6784 if(plci->NL.RLength>=sizeof(T30_INFO))
6786 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6787 len = 9;
6788 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6789 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6790 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6791 if (plci->B3_prot == 5)
6793 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6794 i |= 0x8000; /* This is not an ECM connection */
6795 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6796 i |= 0x4000; /* This is a connection with MMR compression */
6797 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6798 i |= 0x2000; /* This is a connection with MR compression */
6799 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6800 i |= 0x0004; /* More documents */
6801 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6802 i |= 0x0002; /* Fax-polling indication */
6804 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6805 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6806 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6807 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6808 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6809 plci->ncpi_buffer[len] = 0;
6810 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6812 plci->ncpi_buffer[len] = 20;
6813 for (i = 0; i < 20; i++)
6814 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6816 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6818 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6819 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6820 else
6821 info = _FAX_PROTOCOL_ERROR;
6824 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6825 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6827 i = ((word)(offsetof(T30_INFO, station_id) + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6828 while (i < plci->NL.RBuffer->length)
6829 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6832 plci->ncpi_buffer[0] = len;
6833 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6834 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6836 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6837 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6838 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6839 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6840 || (((plci->NL.Ind &0x0f) == N_EDATA)
6841 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6842 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6843 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6845 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6847 if (((plci->NL.Ind &0x0f) == N_DISC)
6848 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6849 || (((plci->NL.Ind &0x0f) == N_EDATA)
6850 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6852 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6855 break;
6857 case B3_RTP:
6858 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6860 if (plci->NL.RLength != 0)
6862 info = rtp_info[plci->NL.RBuffer->P[0]];
6863 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6864 for (i = 1; i < plci->NL.RLength; i++)
6865 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6868 break;
6871 plci->NL.RNR = 2;
6873 switch(plci->NL.Ind &0x0f) {
6874 case N_EDATA:
6875 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6877 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6878 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6879 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6881 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6882 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6883 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6884 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6885 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6886 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6888 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6889 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6890 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6891 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6892 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6893 fax_send_edata_ack = false;
6896 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6898 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6900 case EDATA_T30_DIS:
6901 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6902 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6903 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6904 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6906 a->ncci_state[ncci] = INC_ACT_PENDING;
6907 if (plci->B3_prot == 4)
6908 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6909 else
6910 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6911 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6913 break;
6915 case EDATA_T30_TRAIN_OK:
6916 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6917 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6920 if (plci->B3_prot == 4)
6921 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6922 else
6923 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6924 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6926 break;
6928 case EDATA_T30_EOP_CAPI:
6929 if (a->ncci_state[ncci] == CONNECTED)
6931 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6932 a->ncci_state[ncci] = INC_DIS_PENDING;
6933 plci->ncpi_state = 0;
6934 fax_send_edata_ack = false;
6936 break;
6939 else
6941 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6943 case EDATA_T30_TRAIN_OK:
6944 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6945 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6946 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6948 if (plci->B3_prot == 4)
6949 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6950 else
6951 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6952 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6954 break;
6957 if (fax_send_edata_ack)
6959 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6960 plci->fax_edata_ack_length = 1;
6961 start_internal_command (Id, plci, fax_edata_ack_command);
6964 else
6966 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6968 break;
6969 case N_CONNECT:
6970 if (!a->ch_ncci[ch])
6972 ncci = get_ncci (plci, ch, 0);
6973 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6975 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6976 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6978 msg = _CONNECT_B3_I;
6979 if (a->ncci_state[ncci] == IDLE)
6980 plci->channels++;
6981 else if (plci->B3_prot == 1)
6982 msg = _CONNECT_B3_T90_ACTIVE_I;
6984 a->ncci_state[ncci] = INC_CON_PENDING;
6985 if(plci->B3_prot == 4)
6986 sendf(plci->appl,msg,Id,0,"s","");
6987 else
6988 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6989 break;
6990 case N_CONNECT_ACK:
6991 dbug(1,dprintf("N_connect_Ack"));
6992 if (plci->internal_command_queue[0]
6993 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6994 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6995 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6997 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6998 if (!plci->internal_command)
6999 next_internal_command (Id, plci);
7000 break;
7002 msg = _CONNECT_B3_ACTIVE_I;
7003 if (plci->B3_prot == 1)
7005 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7006 msg = _CONNECT_B3_T90_ACTIVE_I;
7007 a->ncci_state[ncci] = INC_ACT_PENDING;
7008 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7010 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7012 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7013 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7014 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7016 a->ncci_state[ncci] = INC_ACT_PENDING;
7017 if (plci->B3_prot == 4)
7018 sendf(plci->appl,msg,Id,0,"s","");
7019 else
7020 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7021 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7024 else
7026 a->ncci_state[ncci] = INC_ACT_PENDING;
7027 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7029 if (plci->adjust_b_restore)
7031 plci->adjust_b_restore = false;
7032 start_internal_command (Id, plci, adjust_b_restore);
7034 break;
7035 case N_DISC:
7036 case N_DISC_ACK:
7037 if (plci->internal_command_queue[0]
7038 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7039 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7040 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7042 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7043 if (!plci->internal_command)
7044 next_internal_command (Id, plci);
7046 ncci_state = a->ncci_state[ncci];
7047 ncci_remove (plci, ncci, false);
7049 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7050 /* channel, so we cannot store the state in ncci_state! The */
7051 /* information which channel we received a N_DISC is thus */
7052 /* stored in the inc_dis_ncci_table buffer. */
7053 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7054 plci->inc_dis_ncci_table[i] = (byte) ncci;
7056 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7057 if (!plci->channels
7058 && (plci->B1_resource == 16)
7059 && (plci->State <= CONNECTED))
7061 len = 9;
7062 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7063 PUT_WORD (&plci->ncpi_buffer[1], i);
7064 PUT_WORD (&plci->ncpi_buffer[3], 0);
7065 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7066 PUT_WORD (&plci->ncpi_buffer[5], i);
7067 PUT_WORD (&plci->ncpi_buffer[7], 0);
7068 plci->ncpi_buffer[len] = 0;
7069 plci->ncpi_buffer[0] = len;
7070 if(plci->B3_prot == 4)
7071 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7072 else
7075 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7076 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7078 plci->ncpi_buffer[++len] = 0;
7079 plci->ncpi_buffer[++len] = 0;
7080 plci->ncpi_buffer[++len] = 0;
7081 plci->ncpi_buffer[0] = len;
7084 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7086 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7087 plci->ncpi_state = 0;
7088 sig_req(plci,HANGUP,0);
7089 send_req(plci);
7090 plci->State = OUTG_DIS_PENDING;
7091 /* disc here */
7093 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7094 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7095 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7097 if (ncci_state == IDLE)
7099 if (plci->channels)
7100 plci->channels--;
7101 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7102 if(plci->State == SUSPENDING){
7103 sendf(plci->appl,
7104 _FACILITY_I,
7105 Id & 0xffffL,
7107 "ws", (word)3, "\x03\x04\x00\x00");
7108 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7110 plci_remove(plci);
7111 plci->State=IDLE;
7115 else if (plci->channels)
7117 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7118 plci->ncpi_state = 0;
7119 if ((ncci_state == OUTG_REJ_PENDING)
7120 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7122 sig_req(plci,HANGUP,0);
7123 send_req(plci);
7124 plci->State = OUTG_DIS_PENDING;
7127 break;
7128 case N_RESET:
7129 a->ncci_state[ncci] = INC_RES_PENDING;
7130 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7131 break;
7132 case N_RESET_ACK:
7133 a->ncci_state[ncci] = CONNECTED;
7134 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7135 break;
7137 case N_UDATA:
7138 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7140 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7141 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7142 plci->NL.R = plci->RData;
7143 plci->NL.RNum = 1;
7144 return;
7146 case N_BDATA:
7147 case N_DATA:
7148 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7149 || (a->ncci_state[ncci] == IDLE)
7150 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7152 plci->NL.RNR = 2;
7153 break;
7155 if ((a->ncci_state[ncci] != CONNECTED)
7156 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7157 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7159 dbug(1,dprintf("flow control"));
7160 plci->NL.RNR = 1; /* flow control */
7161 channel_x_off (plci, ch, 0);
7162 break;
7165 NCCIcode = ncci | (((word)a->Id) << 8);
7167 /* count all buffers within the Application pool */
7168 /* belonging to the same NCCI. If this is below the */
7169 /* number of buffers available per NCCI we accept */
7170 /* this packet, otherwise we reject it */
7171 count = 0;
7172 Num = 0xffff;
7173 for(i=0; i<APPLptr->MaxBuffer; i++) {
7174 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7175 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7178 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7180 dbug(3,dprintf("Flow-Control"));
7181 plci->NL.RNR = 1;
7182 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7183 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7185 plci->NL.RNR = 2;
7186 dbug(3,dprintf("DiscardData"));
7187 } else {
7188 channel_x_off (plci, ch, 0);
7190 break;
7192 else
7194 APPLptr->NCCIDataFlowCtrlTimer = 0;
7197 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7198 if(!plci->RData[0].P) {
7199 plci->NL.RNR = 1;
7200 channel_x_off (plci, ch, 0);
7201 break;
7204 APPLptr->DataNCCI[Num] = NCCIcode;
7205 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7206 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7208 plci->RNum = Num;
7209 plci->RFlags = plci->NL.Ind>>4;
7210 plci->RData[0].PLength = APPLptr->MaxDataLength;
7211 plci->NL.R = plci->RData;
7212 if ((plci->NL.RLength != 0)
7213 && ((plci->B2_prot == B2_V120_ASYNC)
7214 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7215 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7217 plci->RData[1].P = plci->RData[0].P;
7218 plci->RData[1].PLength = plci->RData[0].PLength;
7219 plci->RData[0].P = v120_header_buffer;
7220 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7221 plci->RData[0].PLength = 1;
7222 else
7223 plci->RData[0].PLength = 2;
7224 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7225 plci->RFlags |= 0x0010;
7226 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7227 plci->RFlags |= 0x8000;
7228 plci->NL.RNum = 2;
7230 else
7232 if((plci->NL.Ind &0x0f)==N_UDATA)
7233 plci->RFlags |= 0x0010;
7235 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7236 plci->RFlags |= 0x0001;
7238 plci->NL.RNum = 1;
7240 break;
7241 case N_DATA_ACK:
7242 data_ack (plci, ch);
7243 break;
7244 default:
7245 plci->NL.RNR = 2;
7246 break;
7250 /*------------------------------------------------------------------*/
7251 /* find a free PLCI */
7252 /*------------------------------------------------------------------*/
7254 static word get_plci(DIVA_CAPI_ADAPTER *a)
7256 word i,j;
7257 PLCI * plci;
7259 dump_plcis (a);
7260 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7261 if(i==a->max_plci) {
7262 dbug(1,dprintf("get_plci: out of PLCIs"));
7263 return 0;
7265 plci = &a->plci[i];
7266 plci->Id = (byte)(i+1);
7268 plci->Sig.Id = 0;
7269 plci->NL.Id = 0;
7270 plci->sig_req = 0;
7271 plci->nl_req = 0;
7273 plci->appl = NULL;
7274 plci->relatedPTYPLCI = NULL;
7275 plci->State = IDLE;
7276 plci->SuppState = IDLE;
7277 plci->channels = 0;
7278 plci->tel = 0;
7279 plci->B1_resource = 0;
7280 plci->B2_prot = 0;
7281 plci->B3_prot = 0;
7283 plci->command = 0;
7284 plci->m_command = 0;
7285 init_internal_command_queue (plci);
7286 plci->number = 0;
7287 plci->req_in_start = 0;
7288 plci->req_in = 0;
7289 plci->req_out = 0;
7290 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7291 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7292 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7294 plci->data_sent = false;
7295 plci->send_disc = 0;
7296 plci->sig_global_req = 0;
7297 plci->sig_remove_id = 0;
7298 plci->nl_global_req = 0;
7299 plci->nl_remove_id = 0;
7300 plci->adv_nl = 0;
7301 plci->manufacturer = false;
7302 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7303 plci->spoofed_msg = 0;
7304 plci->ptyState = 0;
7305 plci->cr_enquiry = false;
7306 plci->hangup_flow_ctrl_timer = 0;
7308 plci->ncci_ring_list = 0;
7309 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7310 clear_c_ind_mask (plci);
7311 set_group_ind_mask (plci);
7312 plci->fax_connect_info_length = 0;
7313 plci->nsf_control_bits = 0;
7314 plci->ncpi_state = 0x00;
7315 plci->ncpi_buffer[0] = 0;
7317 plci->requested_options_conn = 0;
7318 plci->requested_options = 0;
7319 plci->notifiedcall = 0;
7320 plci->vswitchstate = 0;
7321 plci->vsprot = 0;
7322 plci->vsprotdialect = 0;
7323 init_b1_config (plci);
7324 dbug(1,dprintf("get_plci(%x)",plci->Id));
7325 return i+1;
7328 /*------------------------------------------------------------------*/
7329 /* put a parameter in the parameter buffer */
7330 /*------------------------------------------------------------------*/
7332 static void add_p(PLCI * plci, byte code, byte * p)
7334 word p_length;
7336 p_length = 0;
7337 if(p) p_length = p[0];
7338 add_ie(plci, code, p, p_length);
7341 /*------------------------------------------------------------------*/
7342 /* put a structure in the parameter buffer */
7343 /*------------------------------------------------------------------*/
7344 static void add_s(PLCI * plci, byte code, API_PARSE * p)
7346 if(p) add_ie(plci, code, p->info, (word)p->length);
7349 /*------------------------------------------------------------------*/
7350 /* put multiple structures in the parameter buffer */
7351 /*------------------------------------------------------------------*/
7352 static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7354 byte i;
7356 if(p){
7357 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7358 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7359 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7360 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7365 /*------------------------------------------------------------------*/
7366 /* return the channel number sent by the application in a esc_chi */
7367 /*------------------------------------------------------------------*/
7368 static byte getChannel(API_PARSE * p)
7370 byte i;
7372 if(p){
7373 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7374 if(p->info[i]==2){
7375 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7379 return 0;
7383 /*------------------------------------------------------------------*/
7384 /* put an information element in the parameter buffer */
7385 /*------------------------------------------------------------------*/
7387 static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7389 word i;
7391 if(!(code &0x80) && !p_length) return;
7393 if(plci->req_in==plci->req_in_start) {
7394 plci->req_in +=2;
7396 else {
7397 plci->req_in--;
7399 plci->RBuffer[plci->req_in++] = code;
7401 if(p) {
7402 plci->RBuffer[plci->req_in++] = (byte)p_length;
7403 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7406 plci->RBuffer[plci->req_in++] = 0;
7409 /*------------------------------------------------------------------*/
7410 /* put a unstructured data into the buffer */
7411 /*------------------------------------------------------------------*/
7413 static void add_d(PLCI *plci, word length, byte *p)
7415 word i;
7417 if(plci->req_in==plci->req_in_start) {
7418 plci->req_in +=2;
7420 else {
7421 plci->req_in--;
7423 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7426 /*------------------------------------------------------------------*/
7427 /* put parameters from the Additional Info parameter in the */
7428 /* parameter buffer */
7429 /*------------------------------------------------------------------*/
7431 static void add_ai(PLCI *plci, API_PARSE *ai)
7433 word i;
7434 API_PARSE ai_parms[5];
7436 for(i=0;i<5;i++) ai_parms[i].length = 0;
7438 if(!ai->length)
7439 return;
7440 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7441 return;
7443 add_s (plci,KEY,&ai_parms[1]);
7444 add_s (plci,UUI,&ai_parms[2]);
7445 add_ss(plci,FTY,&ai_parms[3]);
7448 /*------------------------------------------------------------------*/
7449 /* put parameter for b1 protocol in the parameter buffer */
7450 /*------------------------------------------------------------------*/
7452 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7453 word b1_facilities)
7455 API_PARSE bp_parms[8];
7456 API_PARSE mdm_cfg[9];
7457 API_PARSE global_config[2];
7458 byte cai[256];
7459 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7460 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7461 word i;
7463 API_PARSE mdm_cfg_v18[4];
7464 word j, n, w;
7465 dword d;
7468 for(i=0;i<8;i++) bp_parms[i].length = 0;
7469 for(i=0;i<2;i++) global_config[i].length = 0;
7471 dbug(1,dprintf("add_b1"));
7472 api_save_msg(bp, "s", &plci->B_protocol);
7474 if(b_channel_info==2){
7475 plci->B1_resource = 0;
7476 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7477 add_p(plci, CAI, "\x01\x00");
7478 dbug(1,dprintf("Cai=1,0 (no resource)"));
7479 return 0;
7482 if(plci->tel == CODEC_PERMANENT) return 0;
7483 else if(plci->tel == CODEC){
7484 plci->B1_resource = 1;
7485 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7486 add_p(plci, CAI, "\x01\x01");
7487 dbug(1,dprintf("Cai=1,1 (Codec)"));
7488 return 0;
7490 else if(plci->tel == ADV_VOICE){
7491 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7492 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7493 voice_cai[1] = plci->B1_resource;
7494 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7495 add_p(plci, CAI, voice_cai);
7496 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7497 return 0;
7499 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7500 if (plci->call_dir & CALL_DIR_OUT)
7501 plci->call_dir |= CALL_DIR_ORIGINATE;
7502 else if (plci->call_dir & CALL_DIR_IN)
7503 plci->call_dir |= CALL_DIR_ANSWER;
7505 if(!bp->length){
7506 plci->B1_resource = 0x5;
7507 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7508 add_p(plci, CAI, "\x01\x05");
7509 return 0;
7512 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7513 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7514 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7516 bp_parms[6].length = 0;
7517 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7519 dbug(1,dprintf("b-form.!"));
7520 return _WRONG_MESSAGE_FORMAT;
7523 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7525 dbug(1,dprintf("b-form.!"));
7526 return _WRONG_MESSAGE_FORMAT;
7529 if(bp_parms[6].length)
7531 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7533 return _WRONG_MESSAGE_FORMAT;
7535 switch(GET_WORD(global_config[0].info))
7537 case 1:
7538 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7539 break;
7540 case 2:
7541 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7542 break;
7545 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7548 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7549 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7551 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7552 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7553 cai[1] = plci->B1_resource;
7554 cai[2] = 0;
7555 cai[3] = 0;
7556 cai[4] = 0;
7557 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7558 for (i = 0; i < bp_parms[3].length; i++)
7559 cai[7+i] = bp_parms[3].info[1+i];
7560 cai[0] = 6 + bp_parms[3].length;
7561 add_p(plci, CAI, cai);
7562 return 0;
7566 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7567 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7569 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7570 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7571 cai[1] = plci->B1_resource;
7572 cai[2] = 0;
7573 cai[3] = 0;
7574 cai[4] = 0;
7575 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7576 cai[0] = 6;
7577 add_p(plci, CAI, cai);
7578 return 0;
7582 if ((GET_WORD(bp_parms[0].info) >= 32)
7583 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7584 && ((GET_WORD(bp_parms[0].info) != 3)
7585 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7586 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7588 return _B1_NOT_SUPPORTED;
7590 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7591 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7592 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7593 cai[0] = 6;
7594 cai[1] = plci->B1_resource;
7595 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7597 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7598 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7599 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7600 { /* B1 - modem */
7601 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7603 if (bp_parms[3].length)
7605 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7607 return (_WRONG_MESSAGE_FORMAT);
7610 cai[2] = 0; /* Bit rate for adaptation */
7612 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7614 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7615 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7616 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7617 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7619 cai[3] = 0; /* Async framing parameters */
7620 switch (GET_WORD (mdm_cfg[2].info))
7621 { /* Parity */
7622 case 1: /* odd parity */
7623 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7624 dbug(1,dprintf("MDM: odd parity"));
7625 break;
7627 case 2: /* even parity */
7628 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7629 dbug(1,dprintf("MDM: even parity"));
7630 break;
7632 default:
7633 dbug(1,dprintf("MDM: no parity"));
7634 break;
7637 switch (GET_WORD (mdm_cfg[3].info))
7638 { /* stop bits */
7639 case 1: /* 2 stop bits */
7640 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7641 dbug(1,dprintf("MDM: 2 stop bits"));
7642 break;
7644 default:
7645 dbug(1,dprintf("MDM: 1 stop bit"));
7646 break;
7649 switch (GET_WORD (mdm_cfg[1].info))
7650 { /* char length */
7651 case 5:
7652 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7653 dbug(1,dprintf("MDM: 5 bits"));
7654 break;
7656 case 6:
7657 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7658 dbug(1,dprintf("MDM: 6 bits"));
7659 break;
7661 case 7:
7662 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7663 dbug(1,dprintf("MDM: 7 bits"));
7664 break;
7666 default:
7667 dbug(1,dprintf("MDM: 8 bits"));
7668 break;
7671 cai[7] = 0; /* Line taking options */
7672 cai[8] = 0; /* Modulation negotiation options */
7673 cai[9] = 0; /* Modulation options */
7675 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7677 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7678 dbug(1, dprintf("MDM: Reverse direction"));
7681 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7683 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7684 dbug(1, dprintf("MDM: Disable retrain"));
7687 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7689 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7690 dbug(1, dprintf("MDM: Disable ring tone"));
7693 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7695 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7696 dbug(1, dprintf("MDM: 1800 guard tone"));
7698 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7700 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7701 dbug(1, dprintf("MDM: 550 guard tone"));
7704 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7706 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7707 dbug(1, dprintf("MDM: V100"));
7709 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7711 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7712 dbug(1, dprintf("MDM: IN CLASS"));
7714 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7716 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7717 dbug(1, dprintf("MDM: DISABLED"));
7719 cai[0] = 20;
7721 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7722 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7724 plci->requested_options |= 1L << PRIVATE_V18;
7726 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7727 plci->requested_options |= 1L << PRIVATE_VOWN;
7729 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7730 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7732 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7734 i = 27;
7735 if (mdm_cfg[6].length >= 4)
7737 d = GET_DWORD(&mdm_cfg[6].info[1]);
7738 cai[7] |= (byte) d; /* line taking options */
7739 cai[9] |= (byte)(d >> 8); /* modulation options */
7740 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7741 cai[++i] = (byte)(d >> 24);
7742 if (mdm_cfg[6].length >= 8)
7744 d = GET_DWORD(&mdm_cfg[6].info[5]);
7745 cai[10] |= (byte) d; /* disabled modulations mask */
7746 cai[11] |= (byte)(d >> 8);
7747 if (mdm_cfg[6].length >= 12)
7749 d = GET_DWORD(&mdm_cfg[6].info[9]);
7750 cai[12] = (byte) d; /* enabled modulations mask */
7751 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7752 cai[++i] = (byte)(d >> 16);
7753 cai[++i] = (byte)(d >> 24);
7754 cai[++i] = 0;
7755 if (mdm_cfg[6].length >= 14)
7757 w = GET_WORD(&mdm_cfg[6].info[13]);
7758 if (w != 0)
7759 PUT_WORD(&cai[13], w); /* min tx speed */
7760 if (mdm_cfg[6].length >= 16)
7762 w = GET_WORD(&mdm_cfg[6].info[15]);
7763 if (w != 0)
7764 PUT_WORD(&cai[15], w); /* max tx speed */
7765 if (mdm_cfg[6].length >= 18)
7767 w = GET_WORD(&mdm_cfg[6].info[17]);
7768 if (w != 0)
7769 PUT_WORD(&cai[17], w); /* min rx speed */
7770 if (mdm_cfg[6].length >= 20)
7772 w = GET_WORD(&mdm_cfg[6].info[19]);
7773 if (w != 0)
7774 PUT_WORD(&cai[19], w); /* max rx speed */
7775 if (mdm_cfg[6].length >= 22)
7777 w = GET_WORD(&mdm_cfg[6].info[21]);
7778 cai[23] = (byte)(-((short) w)); /* transmit level */
7779 if (mdm_cfg[6].length >= 24)
7781 w = GET_WORD(&mdm_cfg[6].info[23]);
7782 cai[22] |= (byte) w; /* info options mask */
7783 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7793 cai[27] = i - 27;
7794 i++;
7795 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7797 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7799 for (n = 0; n < 3; n++)
7801 cai[i] = (byte)(mdm_cfg_v18[n].length);
7802 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7803 cai[i+j] = mdm_cfg_v18[n].info[j];
7804 i += cai[i] + 1;
7808 cai[0] = (byte)(i - 1);
7814 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7815 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7817 if(bp_parms[3].length){
7818 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7819 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7820 case 0:
7821 case 56000:
7822 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7823 dbug(1,dprintf("56k sync HSCX"));
7824 cai[1] = 8;
7825 cai[2] = 0;
7826 cai[3] = 0;
7828 else if(GET_WORD(bp_parms[0].info)==2){
7829 dbug(1,dprintf("56k async DSP"));
7830 cai[2] = 9;
7832 break;
7833 case 50: cai[2] = 1; break;
7834 case 75: cai[2] = 1; break;
7835 case 110: cai[2] = 1; break;
7836 case 150: cai[2] = 1; break;
7837 case 200: cai[2] = 1; break;
7838 case 300: cai[2] = 1; break;
7839 case 600: cai[2] = 1; break;
7840 case 1200: cai[2] = 2; break;
7841 case 2400: cai[2] = 3; break;
7842 case 4800: cai[2] = 4; break;
7843 case 7200: cai[2] = 10; break;
7844 case 9600: cai[2] = 5; break;
7845 case 12000: cai[2] = 13; break;
7846 case 24000: cai[2] = 0; break;
7847 case 14400: cai[2] = 11; break;
7848 case 19200: cai[2] = 6; break;
7849 case 28800: cai[2] = 12; break;
7850 case 38400: cai[2] = 7; break;
7851 case 48000: cai[2] = 8; break;
7852 case 76: cai[2] = 15; break; /* 75/1200 */
7853 case 1201: cai[2] = 14; break; /* 1200/75 */
7854 case 56001: cai[2] = 9; break; /* V.110 56000 */
7856 default:
7857 return _B1_PARM_NOT_SUPPORTED;
7859 cai[3] = 0;
7860 if (cai[1] == 13) /* v.110 async */
7862 if (bp_parms[3].length >= 8)
7864 switch (GET_WORD (&bp_parms[3].info[3]))
7865 { /* char length */
7866 case 5:
7867 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7868 break;
7869 case 6:
7870 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7871 break;
7872 case 7:
7873 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7874 break;
7876 switch (GET_WORD (&bp_parms[3].info[5]))
7877 { /* Parity */
7878 case 1: /* odd parity */
7879 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7880 break;
7881 case 2: /* even parity */
7882 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7883 break;
7885 switch (GET_WORD (&bp_parms[3].info[7]))
7886 { /* stop bits */
7887 case 1: /* 2 stop bits */
7888 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7889 break;
7894 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7895 dbug(1,dprintf("V.110 default 56k sync"));
7896 cai[1] = 8;
7897 cai[2] = 0;
7898 cai[3] = 0;
7900 else {
7901 dbug(1,dprintf("V.110 default 9600 async"));
7902 cai[2] = 5;
7905 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7906 dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7907 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7909 add_p(plci, CAI, cai);
7910 return 0;
7913 /*------------------------------------------------------------------*/
7914 /* put parameter for b2 and B3 protocol in the parameter buffer */
7915 /*------------------------------------------------------------------*/
7917 static word add_b23(PLCI *plci, API_PARSE *bp)
7919 word i, fax_control_bits;
7920 byte pos, len;
7921 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7922 API_PARSE bp_parms[8];
7923 API_PARSE * b1_config;
7924 API_PARSE * b2_config;
7925 API_PARSE b2_config_parms[8];
7926 API_PARSE * b3_config;
7927 API_PARSE b3_config_parms[6];
7928 API_PARSE global_config[2];
7930 static byte llc[3] = {2,0,0};
7931 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7932 static byte nlc[256];
7933 static byte lli[12] = {1,1};
7935 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7936 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7938 const byte llc3[] = {4,3,2,2,6,6,0};
7939 const byte header[] = {0,2,3,3,0,0,0};
7941 for(i=0;i<8;i++) bp_parms[i].length = 0;
7942 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7943 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7945 lli[0] = 1;
7946 lli[1] = 1;
7947 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7948 lli[1] |= 2;
7949 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7950 lli[1] |= 4;
7952 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7953 lli[1] |= 0x10;
7954 if (plci->rx_dma_descriptor <= 0) {
7955 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7956 if (plci->rx_dma_descriptor >= 0)
7957 plci->rx_dma_descriptor++;
7959 if (plci->rx_dma_descriptor > 0) {
7960 lli[0] = 6;
7961 lli[1] |= 0x40;
7962 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7963 lli[3] = (byte)plci->rx_dma_magic;
7964 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7965 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7966 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7970 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7971 lli[1] |= 0x20;
7974 dbug(1,dprintf("add_b23"));
7975 api_save_msg(bp, "s", &plci->B_protocol);
7977 if(!bp->length && plci->tel)
7979 plci->adv_nl = true;
7980 dbug(1,dprintf("Default adv.Nl"));
7981 add_p(plci,LLI,lli);
7982 plci->B2_prot = 1 /*XPARENT*/;
7983 plci->B3_prot = 0 /*XPARENT*/;
7984 llc[1] = 2;
7985 llc[2] = 4;
7986 add_p(plci, LLC, llc);
7987 dlc[0] = 2;
7988 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7989 add_p(plci, DLC, dlc);
7990 return 0;
7993 if(!bp->length) /*default*/
7995 dbug(1,dprintf("ret default"));
7996 add_p(plci,LLI,lli);
7997 plci->B2_prot = 0 /*X.75 */;
7998 plci->B3_prot = 0 /*XPARENT*/;
7999 llc[1] = 1;
8000 llc[2] = 4;
8001 add_p(plci, LLC, llc);
8002 dlc[0] = 2;
8003 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8004 add_p(plci, DLC, dlc);
8005 return 0;
8007 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8008 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8010 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8012 bp_parms[6].length = 0;
8013 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8015 dbug(1,dprintf("b-form.!"));
8016 return _WRONG_MESSAGE_FORMAT;
8019 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8021 dbug(1,dprintf("b-form.!"));
8022 return _WRONG_MESSAGE_FORMAT;
8025 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8027 if(GET_WORD(bp_parms[1].info)!=1
8028 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8029 plci->adv_nl = true;
8031 else if(plci->tel) return _B2_NOT_SUPPORTED;
8034 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8035 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8036 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8038 add_p(plci,LLI,lli);
8039 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8040 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8041 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8042 llc[2] = 4;
8043 add_p(plci, LLC, llc);
8044 dlc[0] = 2;
8045 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8046 dlc[3] = 3; /* Addr A */
8047 dlc[4] = 1; /* Addr B */
8048 dlc[5] = 7; /* modulo mode */
8049 dlc[6] = 7; /* window size */
8050 dlc[7] = 0; /* XID len Lo */
8051 dlc[8] = 0; /* XID len Hi */
8052 for (i = 0; i < bp_parms[4].length; i++)
8053 dlc[9+i] = bp_parms[4].info[1+i];
8054 dlc[0] = (byte)(8 + bp_parms[4].length);
8055 add_p(plci, DLC, dlc);
8056 for (i = 0; i < bp_parms[5].length; i++)
8057 nlc[1+i] = bp_parms[5].info[1+i];
8058 nlc[0] = (byte)(bp_parms[5].length);
8059 add_p(plci, NLC, nlc);
8060 return 0;
8065 if ((GET_WORD(bp_parms[1].info) >= 32)
8066 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8067 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8068 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8071 return _B2_NOT_SUPPORTED;
8073 if ((GET_WORD(bp_parms[2].info) >= 32)
8074 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8076 return _B3_NOT_SUPPORTED;
8078 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8079 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8080 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8081 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8083 return (add_modem_b23 (plci, bp_parms));
8086 add_p(plci,LLI,lli);
8088 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8089 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8090 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8092 if(bp_parms[6].length)
8094 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8096 return _WRONG_MESSAGE_FORMAT;
8098 switch(GET_WORD(global_config[0].info))
8100 case 1:
8101 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8102 break;
8103 case 2:
8104 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8105 break;
8108 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8111 if (plci->B2_prot == B2_PIAFS)
8112 llc[1] = PIAFS_CRC;
8113 else
8114 /* IMPLEMENT_PIAFS */
8116 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8117 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8119 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8121 add_p(plci, LLC, llc);
8123 dlc[0] = 2;
8124 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8125 header[GET_WORD(bp_parms[2].info)]);
8127 b1_config = &bp_parms[3];
8128 nlc[0] = 0;
8129 if(plci->B3_prot == 4
8130 || plci->B3_prot == 5)
8132 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8133 nlc[0] = sizeof(T30_INFO);
8134 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8135 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8136 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8137 if(b1_config->length>=2)
8139 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8142 b2_config = &bp_parms[4];
8145 if (llc[1] == PIAFS_CRC)
8147 if (plci->B3_prot != B3_TRANSPARENT)
8149 return _B_STACK_NOT_SUPPORTED;
8151 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8152 return _WRONG_MESSAGE_FORMAT;
8154 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8155 dlc[3] = 0; /* Addr A */
8156 dlc[4] = 0; /* Addr B */
8157 dlc[5] = 0; /* modulo mode */
8158 dlc[6] = 0; /* window size */
8159 if (b2_config->length >= 7){
8160 dlc[ 7] = 7;
8161 dlc[ 8] = 0;
8162 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8163 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8164 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8165 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8166 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8167 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8168 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8169 dlc[ 0] = 15;
8170 if(b2_config->length >= 8) { /* PIAFS control abilities */
8171 dlc[ 7] = 10;
8172 dlc[16] = 2; /* Length of PIAFS extention */
8173 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8174 dlc[18] = b2_config_parms[4].info[0]; /* value */
8175 dlc[ 0] = 18;
8178 else /* default values, 64K, variable, no compression */
8180 dlc[ 7] = 7;
8181 dlc[ 8] = 0;
8182 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8183 dlc[10] = 0x03; /* V.42bis P0 */
8184 dlc[11] = 0; /* V.42bis P0 */
8185 dlc[12] = 0; /* V.42bis P1 */
8186 dlc[13] = 0; /* V.42bis P1 */
8187 dlc[14] = 0; /* V.42bis P2 */
8188 dlc[15] = 0; /* V.42bis P2 */
8189 dlc[ 0] = 15;
8191 add_p(plci, DLC, dlc);
8193 else
8195 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8197 if (plci->B3_prot != B3_TRANSPARENT)
8198 return _B_STACK_NOT_SUPPORTED;
8200 dlc[0] = 6;
8201 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8202 dlc[3] = 0x08;
8203 dlc[4] = 0x01;
8204 dlc[5] = 127;
8205 dlc[6] = 7;
8206 if (b2_config->length != 0)
8208 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8209 return _WRONG_MESSAGE_FORMAT;
8211 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8212 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8213 if (b2_config->info[3] != 128)
8215 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8216 return _B2_PARM_NOT_SUPPORTED;
8218 dlc[5] = (byte)(b2_config->info[3] - 1);
8219 dlc[6] = b2_config->info[4];
8220 if(llc[1]==V120_V42BIS){
8221 if (b2_config->length >= 10){
8222 dlc[ 7] = 6;
8223 dlc[ 8] = 0;
8224 dlc[ 9] = b2_config_parms[4].info[0];
8225 dlc[10] = b2_config_parms[4].info[1];
8226 dlc[11] = b2_config_parms[5].info[0];
8227 dlc[12] = b2_config_parms[5].info[1];
8228 dlc[13] = b2_config_parms[6].info[0];
8229 dlc[14] = b2_config_parms[6].info[1];
8230 dlc[ 0] = 14;
8231 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8232 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8233 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8235 else {
8236 dlc[ 6] = 14;
8241 else
8243 if(b2_config->length)
8245 dbug(1,dprintf("B2-Config"));
8246 if(llc[1]==X75_V42BIS){
8247 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8249 return _WRONG_MESSAGE_FORMAT;
8252 else {
8253 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8255 return _WRONG_MESSAGE_FORMAT;
8258 /* if B2 Protocol is LAPD, b2_config structure is different */
8259 if(llc[1]==6)
8261 dlc[0] = 4;
8262 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8263 else dlc[2] = 0x01;
8264 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8266 SAPI = b2_config->info[2]; /* SAPI */
8268 dlc[1] = SAPI;
8269 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8271 dlc[3] = 127; /* Mode */
8273 else
8275 dlc[3] = 7; /* Mode */
8278 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8279 else dlc[4] = 1;
8280 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8281 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8283 else
8285 dlc[0] = (byte)(b2_config_parms[4].length+6);
8286 dlc[3] = b2_config->info[1];
8287 dlc[4] = b2_config->info[2];
8288 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8289 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8290 return _B2_PARM_NOT_SUPPORTED;
8293 dlc[5] = (byte)(b2_config->info[3]-1);
8294 dlc[6] = b2_config->info[4];
8295 if(dlc[6]>dlc[5]){
8296 dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8297 return _B2_PARM_NOT_SUPPORTED;
8300 if(llc[1]==X75_V42BIS) {
8301 if (b2_config->length >= 10){
8302 dlc[ 7] = 6;
8303 dlc[ 8] = 0;
8304 dlc[ 9] = b2_config_parms[4].info[0];
8305 dlc[10] = b2_config_parms[4].info[1];
8306 dlc[11] = b2_config_parms[5].info[0];
8307 dlc[12] = b2_config_parms[5].info[1];
8308 dlc[13] = b2_config_parms[6].info[0];
8309 dlc[14] = b2_config_parms[6].info[1];
8310 dlc[ 0] = 14;
8311 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8312 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8313 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8315 else {
8316 dlc[ 6] = 14;
8320 else {
8321 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8322 for(i=0; i<b2_config_parms[4].length; i++)
8323 dlc[11+i] = b2_config_parms[4].info[1+i];
8328 add_p(plci, DLC, dlc);
8330 b3_config = &bp_parms[5];
8331 if(b3_config->length)
8333 if(plci->B3_prot == 4
8334 || plci->B3_prot == 5)
8336 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8338 return _WRONG_MESSAGE_FORMAT;
8340 i = GET_WORD((byte *)(b3_config_parms[0].info));
8341 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8342 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8343 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8344 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8345 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8346 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8347 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8350 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8351 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8353 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8354 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8355 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8358 ((T30_INFO *)&nlc[1])->recording_properties =
8359 T30_RECORDING_WIDTH_ISO_A3 |
8360 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8361 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8363 if(plci->B3_prot == 5)
8365 if (i & 0x0002) /* Accept incoming fax-polling requests */
8366 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8367 if (i & 0x2000) /* Do not use MR compression */
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8369 if (i & 0x4000) /* Do not use MMR compression */
8370 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8371 if (i & 0x8000) /* Do not use ECM */
8372 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8373 if (plci->fax_connect_info_length != 0)
8375 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8376 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8377 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8378 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8379 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8382 /* copy station id to NLC */
8383 for(i=0; i<20; i++)
8385 if(i<b3_config_parms[2].length)
8387 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8389 else
8391 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8394 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8395 /* copy head line to NLC */
8396 if(b3_config_parms[3].length)
8398 byte *head_line = (void *) ((T30_INFO *)&nlc[1] + 1);
8400 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8401 if (pos != 0)
8403 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8404 pos = 0;
8405 else
8407 head_line[pos++] = ' ';
8408 head_line[pos++] = ' ';
8409 len = (byte)b3_config_parms[2].length;
8410 if (len > 20)
8411 len = 20;
8412 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8414 for (i = 0; i < len; i++)
8415 head_line[pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8416 head_line[pos++] = ' ';
8417 head_line[pos++] = ' ';
8422 len = (byte)b3_config_parms[3].length;
8423 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8424 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8425 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8426 nlc[0] += (byte)(pos + len);
8427 for (i = 0; i < len; i++)
8428 head_line[pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8430 else
8431 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8433 plci->nsf_control_bits = 0;
8434 if(plci->B3_prot == 5)
8436 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8437 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8439 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8441 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8442 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8444 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8446 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8447 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8449 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8450 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8452 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8453 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8454 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8456 len = nlc[0];
8457 pos = (byte)(offsetof(T30_INFO, station_id) + 20);
8458 if (pos < plci->fax_connect_info_length)
8460 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8461 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8463 else
8464 nlc[++len] = 0;
8465 if (pos < plci->fax_connect_info_length)
8467 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8468 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8470 else
8471 nlc[++len] = 0;
8472 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8473 & (1L << PRIVATE_FAX_NONSTANDARD))
8475 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8477 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8478 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8479 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8482 else
8484 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8486 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8487 nlc[++len] = 0;
8489 else
8491 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8492 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8493 nlc[++len] = (byte)(b3_config_parms[4].length);
8494 for (i = 0; i < b3_config_parms[4].length; i++)
8495 nlc[++len] = b3_config_parms[4].info[1+i];
8499 nlc[0] = len;
8500 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8501 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8503 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8508 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8509 len = (byte)(offsetof(T30_INFO, station_id) + 20);
8510 for (i = 0; i < len; i++)
8511 plci->fax_connect_info_buffer[i] = nlc[1+i];
8512 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8513 i += ((T30_INFO *)&nlc[1])->head_line_len;
8514 while (i < nlc[0])
8515 plci->fax_connect_info_buffer[len++] = nlc[++i];
8516 plci->fax_connect_info_length = len;
8518 else
8520 nlc[0] = 14;
8521 if(b3_config->length!=16)
8522 return _B3_PARM_NOT_SUPPORTED;
8523 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8524 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8525 return _B3_PARM_NOT_SUPPORTED;
8526 nlc[13] = b3_config->info[13];
8527 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8528 return _B3_PARM_NOT_SUPPORTED;
8529 nlc[14] = b3_config->info[15];
8532 else
8534 if (plci->B3_prot == 4
8535 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8537 add_p(plci, NLC, nlc);
8538 return 0;
8541 /*----------------------------------------------------------------*/
8542 /* make the same as add_b23, but only for the modem related */
8543 /* L2 and L3 B-Chan protocol. */
8544 /* */
8545 /* Enabled L2 and L3 Configurations: */
8546 /* If L1 == Modem all negotiation */
8547 /* only L2 == Modem with full negotiation is allowed */
8548 /* If L1 == Modem async or sync */
8549 /* only L2 == Transparent is allowed */
8550 /* L3 == Modem or L3 == Transparent are allowed */
8551 /* B2 Configuration for modem: */
8552 /* word : enable/disable compression, bitoptions */
8553 /* B3 Configuration for modem: */
8554 /* empty */
8555 /*----------------------------------------------------------------*/
8556 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8558 static byte lli[12] = {1,1};
8559 static byte llc[3] = {2,0,0};
8560 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8561 API_PARSE mdm_config[2];
8562 word i;
8563 word b2_config = 0;
8565 for(i=0;i<2;i++) mdm_config[i].length = 0;
8566 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8568 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8569 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8570 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8571 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8573 return (_B_STACK_NOT_SUPPORTED);
8575 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8576 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8578 return (_B_STACK_NOT_SUPPORTED);
8581 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8582 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8584 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8586 if (api_parse (&bp_parms[4].info[1],
8587 (word)bp_parms[4].length, "w",
8588 mdm_config))
8590 return (_WRONG_MESSAGE_FORMAT);
8592 b2_config = GET_WORD(mdm_config[0].info);
8595 /* OK, L2 is modem */
8597 lli[0] = 1;
8598 lli[1] = 1;
8599 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8600 lli[1] |= 2;
8601 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8602 lli[1] |= 4;
8604 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8605 lli[1] |= 0x10;
8606 if (plci->rx_dma_descriptor <= 0) {
8607 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8608 if (plci->rx_dma_descriptor >= 0)
8609 plci->rx_dma_descriptor++;
8611 if (plci->rx_dma_descriptor > 0) {
8612 lli[1] |= 0x40;
8613 lli[0] = 6;
8614 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8615 lli[3] = (byte)plci->rx_dma_magic;
8616 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8617 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8618 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8622 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8623 lli[1] |= 0x20;
8626 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8627 /*V42*/ 10 : /*V42_IN*/ 9;
8628 llc[2] = 4; /* pass L3 always transparent */
8629 add_p(plci, LLI, lli);
8630 add_p(plci, LLC, llc);
8631 i = 1;
8632 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8633 i += 2;
8634 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8636 if (bp_parms[4].length)
8638 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8639 dlc[i++] = 3; /* Addr A */
8640 dlc[i++] = 1; /* Addr B */
8641 dlc[i++] = 7; /* modulo mode */
8642 dlc[i++] = 7; /* window size */
8643 dlc[i++] = 0; /* XID len Lo */
8644 dlc[i++] = 0; /* XID len Hi */
8646 if (b2_config & MDM_B2_DISABLE_V42bis)
8648 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8650 if (b2_config & MDM_B2_DISABLE_MNP)
8652 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8654 if (b2_config & MDM_B2_DISABLE_TRANS)
8656 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8658 if (b2_config & MDM_B2_DISABLE_V42)
8660 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8662 if (b2_config & MDM_B2_DISABLE_COMP)
8664 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8666 i++;
8669 else
8671 dlc[i++] = 3; /* Addr A */
8672 dlc[i++] = 1; /* Addr B */
8673 dlc[i++] = 7; /* modulo mode */
8674 dlc[i++] = 7; /* window size */
8675 dlc[i++] = 0; /* XID len Lo */
8676 dlc[i++] = 0; /* XID len Hi */
8677 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8678 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8679 DLC_MODEMPROT_DISABLE_V42_DETECT |
8680 DLC_MODEMPROT_DISABLE_COMPRESSION;
8682 dlc[0] = (byte)(i - 1);
8683 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8684 add_p(plci, DLC, dlc);
8685 return (0);
8689 /*------------------------------------------------------------------*/
8690 /* send a request for the signaling entity */
8691 /*------------------------------------------------------------------*/
8693 void sig_req(PLCI * plci, byte req, byte Id)
8695 if(!plci) return;
8696 if(plci->adapter->adapter_disabled) return;
8697 dbug(1,dprintf("sig_req(%x)",req));
8698 if (req == REMOVE)
8699 plci->sig_remove_id = plci->Sig.Id;
8700 if(plci->req_in==plci->req_in_start) {
8701 plci->req_in +=2;
8702 plci->RBuffer[plci->req_in++] = 0;
8704 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8705 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8706 plci->RBuffer[plci->req_in++] = req; /* request */
8707 plci->RBuffer[plci->req_in++] = 0; /* channel */
8708 plci->req_in_start = plci->req_in;
8711 /*------------------------------------------------------------------*/
8712 /* send a request for the network layer entity */
8713 /*------------------------------------------------------------------*/
8715 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8717 if(!plci) return;
8718 if(plci->adapter->adapter_disabled) return;
8719 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8720 if (req == REMOVE)
8722 plci->nl_remove_id = plci->NL.Id;
8723 ncci_remove (plci, 0, (byte)(ncci != 0));
8724 ncci = 0;
8726 if(plci->req_in==plci->req_in_start) {
8727 plci->req_in +=2;
8728 plci->RBuffer[plci->req_in++] = 0;
8730 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8731 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8732 plci->RBuffer[plci->req_in++] = req; /* request */
8733 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8734 plci->req_in_start = plci->req_in;
8737 static void send_req(PLCI *plci)
8739 ENTITY * e;
8740 word l;
8741 /* word i; */
8743 if(!plci) return;
8744 if(plci->adapter->adapter_disabled) return;
8745 channel_xmit_xon (plci);
8747 /* if nothing to do, return */
8748 if(plci->req_in==plci->req_out) return;
8749 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8751 if(plci->nl_req || plci->sig_req) return;
8753 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8754 plci->req_out += 2;
8755 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8756 plci->req_out += l;
8757 if(plci->RBuffer[plci->req_out]==1)
8759 e = &plci->NL;
8760 plci->req_out++;
8761 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8762 e->ReqCh = plci->RBuffer[plci->req_out++];
8763 if(!(e->Id & 0x1f))
8765 e->Id = NL_ID;
8766 plci->RBuffer[plci->req_out-4] = CAI;
8767 plci->RBuffer[plci->req_out-3] = 1;
8768 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8769 plci->RBuffer[plci->req_out-1] = 0;
8770 l+=3;
8771 plci->nl_global_req = plci->nl_req;
8773 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8775 else
8777 e = &plci->Sig;
8778 if(plci->RBuffer[plci->req_out])
8779 e->Id = plci->RBuffer[plci->req_out];
8780 plci->req_out++;
8781 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8782 e->ReqCh = plci->RBuffer[plci->req_out++];
8783 if(!(e->Id & 0x1f))
8784 plci->sig_global_req = plci->sig_req;
8785 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8787 plci->XData[0].PLength = l;
8788 e->X = plci->XData;
8789 plci->adapter->request(e);
8790 dbug(1,dprintf("send_ok"));
8793 void send_data(PLCI * plci)
8795 DIVA_CAPI_ADAPTER * a;
8796 DATA_B3_DESC * data;
8797 NCCI *ncci_ptr;
8798 word ncci;
8800 if (!plci->nl_req && plci->ncci_ring_list)
8802 a = plci->adapter;
8803 ncci = plci->ncci_ring_list;
8806 ncci = a->ncci_next[ncci];
8807 ncci_ptr = &(a->ncci[ncci]);
8808 if (!(a->ncci_ch[ncci]
8809 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8811 if (ncci_ptr->data_pending)
8813 if ((a->ncci_state[ncci] == CONNECTED)
8814 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8815 || (plci->send_disc == ncci))
8817 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8818 if ((plci->B2_prot == B2_V120_ASYNC)
8819 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8820 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8822 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8823 plci->NData[1].PLength = data->Length;
8824 if (data->Flags & 0x10)
8825 plci->NData[0].P = v120_break_header;
8826 else
8827 plci->NData[0].P = v120_default_header;
8828 plci->NData[0].PLength = 1 ;
8829 plci->NL.XNum = 2;
8830 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8832 else
8834 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8835 plci->NData[0].PLength = data->Length;
8836 if (data->Flags & 0x10)
8837 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8839 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8840 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8842 else
8843 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8845 plci->NL.X = plci->NData;
8846 plci->NL.ReqCh = a->ncci_ch[ncci];
8847 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8848 plci->data_sent = true;
8849 plci->data_sent_ptr = data->P;
8850 a->request(&plci->NL);
8852 else {
8853 cleanup_ncci_data (plci, ncci);
8856 else if (plci->send_disc == ncci)
8858 /* dprintf("N_DISC"); */
8859 plci->NData[0].PLength = 0;
8860 plci->NL.ReqCh = a->ncci_ch[ncci];
8861 plci->NL.Req = plci->nl_req = N_DISC;
8862 a->request(&plci->NL);
8863 plci->command = _DISCONNECT_B3_R;
8864 plci->send_disc = 0;
8867 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8868 plci->ncci_ring_list = ncci;
8872 static void listen_check(DIVA_CAPI_ADAPTER *a)
8874 word i,j;
8875 PLCI * plci;
8876 byte activnotifiedcalls = 0;
8878 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8879 if (!remove_started && !a->adapter_disabled)
8881 for(i=0;i<a->max_plci;i++)
8883 plci = &(a->plci[i]);
8884 if(plci->notifiedcall) activnotifiedcalls++;
8886 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8888 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8889 if((j=get_plci(a))) {
8890 a->listen_active++;
8891 plci = &a->plci[j-1];
8892 plci->State = LISTENING;
8894 add_p(plci,OAD,"\x01\xfd");
8896 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8898 add_p(plci,CAI,"\x01\xc0");
8899 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8900 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8901 add_p(plci,SHIFT|6,NULL);
8902 add_p(plci,SIN,"\x02\x00\x00");
8903 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8904 sig_req(plci,ASSIGN,DSIG_ID);
8905 send_req(plci);
8911 /*------------------------------------------------------------------*/
8912 /* functions for all parameters sent in INDs */
8913 /*------------------------------------------------------------------*/
8915 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8917 word ploc; /* points to current location within packet */
8918 byte w;
8919 byte wlen;
8920 byte codeset,lock;
8921 byte * in;
8922 word i;
8923 word code;
8924 word mIEindex = 0;
8925 ploc = 0;
8926 codeset = 0;
8927 lock = 0;
8929 in = plci->Sig.RBuffer->P;
8930 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8931 { /* element but parms array is larger */
8932 parms[i] = (byte *)"";
8934 for(i=0; i<multiIEsize; i++)
8936 parms[i] = (byte *)"";
8939 while(ploc<plci->Sig.RBuffer->length-1) {
8941 /* read information element id and length */
8942 w = in[ploc];
8944 if(w & 0x80) {
8945 /* w &=0xf0; removed, cannot detect congestion levels */
8946 /* upper 4 bit masked with w==SHIFT now */
8947 wlen = 0;
8949 else {
8950 wlen = (byte)(in[ploc+1]+1);
8952 /* check if length valid (not exceeding end of packet) */
8953 if((ploc+wlen) > 270) return ;
8954 if(lock & 0x80) lock &=0x7f;
8955 else codeset = lock;
8957 if((w&0xf0)==SHIFT) {
8958 codeset = in[ploc];
8959 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8960 codeset &=7;
8961 lock |=0x80;
8963 else {
8964 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8965 else code = w;
8966 code |= (codeset<<8);
8968 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8970 if(i<parms_id[0]+1) {
8971 if(!multiIEsize) { /* with multiIEs use next field index, */
8972 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8975 parms[mIEindex] = &in[ploc+1];
8976 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8977 if(parms_id[i]==OAD
8978 || parms_id[i]==CONN_NR
8979 || parms_id[i]==CAD) {
8980 if(in[ploc+2] &0x80) {
8981 in[ploc+0] = (byte)(in[ploc+1]+1);
8982 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8983 in[ploc+2] = 0x80;
8984 parms[mIEindex] = &in[ploc];
8987 mIEindex++; /* effects multiIEs only */
8991 ploc +=(wlen+1);
8993 return ;
8996 /*------------------------------------------------------------------*/
8997 /* try to match a cip from received BC and HLC */
8998 /*------------------------------------------------------------------*/
9000 static byte ie_compare(byte *ie1, byte *ie2)
9002 word i;
9003 if(!ie1 || ! ie2) return false;
9004 if(!ie1[0]) return false;
9005 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9006 return true;
9009 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9011 word i;
9012 word j;
9014 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9016 for(j=16;j<29 &&
9017 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9018 if(j==29) return i;
9019 return j;
9023 static byte AddInfo(byte **add_i,
9024 byte **fty_i,
9025 byte *esc_chi,
9026 byte *facility)
9028 byte i;
9029 byte j;
9030 byte k;
9031 byte flen;
9032 byte len=0;
9033 /* facility is a nested structure */
9034 /* FTY can be more than once */
9036 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9038 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9041 else
9043 add_i[0] = (byte *)"";
9045 if(!fty_i[0][0])
9047 add_i[3] = (byte *)"";
9049 else
9050 { /* facility array found */
9051 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9053 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9054 len += fty_i[i][0];
9055 len += 2;
9056 flen=fty_i[i][0];
9057 facility[j++]=0x1c; /* copy fac IE */
9058 for(k=0;k<=flen;k++,j++)
9060 facility[j]=fty_i[i][k];
9061 /* dbug(1,dprintf("%x ",facility[j])); */
9064 facility[0] = len;
9065 add_i[3] = facility;
9067 /* dbug(1,dprintf("FacArrLen=%d ",len)); */
9068 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9069 len += 4; /* calculate length of all */
9070 return(len);
9073 /*------------------------------------------------------------------*/
9074 /* voice and codec features */
9075 /*------------------------------------------------------------------*/
9077 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9079 byte voice_chi[] = "\x02\x18\x01";
9080 byte channel;
9082 channel = chi[chi[0]]&0x3;
9083 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9084 voice_chi[2] = (channel) ? channel : 1;
9085 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9086 add_p(plci,ESC,voice_chi); /* Channel */
9087 sig_req(plci,TEL_CTRL,0);
9088 send_req(plci);
9089 if(a->AdvSignalPLCI)
9091 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9095 static void VoiceChannelOff(PLCI *plci)
9097 dbug(1,dprintf("ExtDevOFF"));
9098 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9099 sig_req(plci,TEL_CTRL,0);
9100 send_req(plci);
9101 if(plci->adapter->AdvSignalPLCI)
9103 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9108 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9109 byte hook_listen)
9111 word j;
9112 PLCI *splci;
9114 /* check if hardware supports handset with hook states (adv.codec) */
9115 /* or if just a on board codec is supported */
9116 /* the advanced codec plci is just for internal use */
9118 /* diva Pro with on-board codec: */
9119 if(a->profile.Global_Options & HANDSET)
9121 /* new call, but hook states are already signalled */
9122 if(a->AdvCodecFLAG)
9124 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9126 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9127 return 0x2001; /* codec in use by another application */
9129 if(plci!=NULL)
9131 a->AdvSignalPLCI = plci;
9132 plci->tel=ADV_VOICE;
9134 return 0; /* adv codec still used */
9136 if((j=get_plci(a)))
9138 splci = &a->plci[j-1];
9139 splci->tel = CODEC_PERMANENT;
9140 /* hook_listen indicates if a facility_req with handset/hook support */
9141 /* was sent. Otherwise if just a call on an external device was made */
9142 /* the codec will be used but the hook info will be discarded (just */
9143 /* the external controller is in use */
9144 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9145 else
9147 splci->State = ADVANCED_VOICE_NOSIG;
9148 if(plci)
9150 plci->spoofed_msg = SPOOFING_REQUIRED;
9152 /* indicate D-ch connect if */
9153 } /* codec is connected OK */
9154 if(plci!=NULL)
9156 a->AdvSignalPLCI = plci;
9157 plci->tel=ADV_VOICE;
9159 a->AdvSignalAppl = appl;
9160 a->AdvCodecFLAG = true;
9161 a->AdvCodecPLCI = splci;
9162 add_p(splci,CAI,"\x01\x15");
9163 add_p(splci,LLI,"\x01\x00");
9164 add_p(splci,ESC,"\x02\x18\x00");
9165 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9166 splci->internal_command = PERM_COD_ASSIGN;
9167 dbug(1,dprintf("Codec Assign"));
9168 sig_req(splci,ASSIGN,DSIG_ID);
9169 send_req(splci);
9171 else
9173 return 0x2001; /* wrong state, no more plcis */
9176 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9178 if(hook_listen) return 0x300B; /* Facility not supported */
9179 /* no hook with SCOM */
9180 if(plci!=NULL) plci->tel = CODEC;
9181 dbug(1,dprintf("S/SCOM codec"));
9182 /* first time we use the scom-s codec we must shut down the internal */
9183 /* handset application of the card. This can be done by an assign with */
9184 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9185 if(!a->scom_appl_disable){
9186 if((j=get_plci(a))) {
9187 splci = &a->plci[j-1];
9188 add_p(splci,CAI,"\x01\x80");
9189 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9190 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9191 send_req(splci);
9192 a->scom_appl_disable = true;
9194 else{
9195 return 0x2001; /* wrong state, no more plcis */
9199 else return 0x300B; /* Facility not supported */
9201 return 0;
9205 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9208 dbug(1,dprintf("CodecIdCheck"));
9210 if(a->AdvSignalPLCI == plci)
9212 dbug(1,dprintf("PLCI owns codec"));
9213 VoiceChannelOff(a->AdvCodecPLCI);
9214 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9216 dbug(1,dprintf("remove temp codec PLCI"));
9217 plci_remove(a->AdvCodecPLCI);
9218 a->AdvCodecFLAG = 0;
9219 a->AdvCodecPLCI = NULL;
9220 a->AdvSignalAppl = NULL;
9222 a->AdvSignalPLCI = NULL;
9226 /* -------------------------------------------------------------------
9227 Ask for physical address of card on PCI bus
9228 ------------------------------------------------------------------- */
9229 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9230 IDI_SYNC_REQ * preq) {
9231 a->sdram_bar = 0;
9232 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9233 ENTITY * e = (ENTITY *)preq;
9235 e->user[0] = a->Id - 1;
9236 preq->xdi_sdram_bar.info.bar = 0;
9237 preq->xdi_sdram_bar.Req = 0;
9238 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9240 (*(a->request))(e);
9242 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9243 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9247 /* -------------------------------------------------------------------
9248 Ask XDI about extended features
9249 ------------------------------------------------------------------- */
9250 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9251 IDI_SYNC_REQ * preq;
9252 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9254 char features[4];
9255 preq = (IDI_SYNC_REQ *)&buffer[0];
9257 if (!diva_xdi_extended_features) {
9258 ENTITY * e = (ENTITY *)preq;
9259 diva_xdi_extended_features |= 0x80000000;
9261 e->user[0] = a->Id - 1;
9262 preq->xdi_extended_features.Req = 0;
9263 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9264 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9265 preq->xdi_extended_features.info.features = &features[0];
9267 (*(a->request))(e);
9269 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9271 Check features located in the byte '0'
9273 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9274 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9276 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9277 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9278 dbug(1,dprintf("XDI provides RxDMA"));
9280 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9281 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9283 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9284 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9285 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9291 diva_ask_for_xdi_sdram_bar (a, preq);
9294 /*------------------------------------------------------------------*/
9295 /* automatic law */
9296 /*------------------------------------------------------------------*/
9297 /* called from OS specific part after init time to get the Law */
9298 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9299 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9301 word j;
9302 PLCI *splci;
9304 if(a->automatic_law) {
9305 return;
9307 if((j=get_plci(a))) {
9308 diva_get_extended_adapter_features (a);
9309 splci = &a->plci[j-1];
9310 a->automatic_lawPLCI = splci;
9311 a->automatic_law = 1;
9312 add_p(splci,CAI,"\x01\x80");
9313 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9314 splci->internal_command = USELAW_REQ;
9315 splci->command = 0;
9316 splci->number = 0;
9317 sig_req(splci,ASSIGN,DSIG_ID);
9318 send_req(splci);
9322 /* called from OS specific part if an application sends an Capi20Release */
9323 word CapiRelease(word Id)
9325 word i, j, appls_found;
9326 PLCI *plci;
9327 APPL *this;
9328 DIVA_CAPI_ADAPTER *a;
9330 if (!Id)
9332 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9333 return (_WRONG_APPL_ID);
9336 this = &application[Id-1]; /* get application pointer */
9338 for(i=0,appls_found=0; i<max_appl; i++)
9340 if(application[i].Id) /* an application has been found */
9342 appls_found++;
9346 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9348 a = &adapter[i];
9349 if (a->request)
9351 a->Info_Mask[Id-1] = 0;
9352 a->CIP_Mask[Id-1] = 0;
9353 a->Notification_Mask[Id-1] = 0;
9354 a->codec_listen[Id-1] = NULL;
9355 a->requested_options_table[Id-1] = 0;
9356 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9357 { /* with this application */
9358 plci = &a->plci[j];
9359 if(plci->Id) /* if plci owns no application */
9360 { /* it may be not jet connected */
9361 if(plci->State==INC_CON_PENDING
9362 || plci->State==INC_CON_ALERT)
9364 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9366 clear_c_ind_mask_bit (plci, (word)(Id-1));
9367 if(c_ind_mask_empty (plci))
9369 sig_req(plci,HANGUP,0);
9370 send_req(plci);
9371 plci->State = OUTG_DIS_PENDING;
9375 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9377 clear_c_ind_mask_bit (plci, (word)(Id-1));
9378 if(c_ind_mask_empty (plci))
9380 if(!plci->appl)
9382 plci_remove(plci);
9383 plci->State = IDLE;
9387 if(plci->appl==this)
9389 plci->appl = NULL;
9390 plci_remove(plci);
9391 plci->State = IDLE;
9395 listen_check(a);
9397 if(a->flag_dynamic_l1_down)
9399 if(appls_found==1) /* last application does a capi release */
9401 if((j=get_plci(a)))
9403 plci = &a->plci[j-1];
9404 plci->command = 0;
9405 add_p(plci,OAD,"\x01\xfd");
9406 add_p(plci,CAI,"\x01\x80");
9407 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9408 add_p(plci,SHIFT|6,NULL);
9409 add_p(plci,SIN,"\x02\x00\x00");
9410 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9411 sig_req(plci,ASSIGN,DSIG_ID);
9412 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9413 sig_req(plci,SIG_CTRL,0);
9414 send_req(plci);
9418 if(a->AdvSignalAppl==this)
9420 this->NullCREnable = false;
9421 if (a->AdvCodecPLCI)
9423 plci_remove(a->AdvCodecPLCI);
9424 a->AdvCodecPLCI->tel = 0;
9425 a->AdvCodecPLCI->adv_nl = 0;
9427 a->AdvSignalAppl = NULL;
9428 a->AdvSignalPLCI = NULL;
9429 a->AdvCodecFLAG = 0;
9430 a->AdvCodecPLCI = NULL;
9435 this->Id = 0;
9437 return GOOD;
9440 static word plci_remove_check(PLCI *plci)
9442 if(!plci) return true;
9443 if(!plci->NL.Id && c_ind_mask_empty (plci))
9445 if(plci->Sig.Id == 0xff)
9446 plci->Sig.Id = 0;
9447 if(!plci->Sig.Id)
9449 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9450 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9451 if (plci->Id)
9453 CodecIdCheck(plci->adapter, plci);
9454 clear_b1_config (plci);
9455 ncci_remove (plci, 0, false);
9456 plci_free_msg_in_queue (plci);
9457 channel_flow_control_remove (plci);
9458 plci->Id = 0;
9459 plci->State = IDLE;
9460 plci->channels = 0;
9461 plci->appl = NULL;
9462 plci->notifiedcall = 0;
9464 listen_check(plci->adapter);
9465 return true;
9468 return false;
9472 /*------------------------------------------------------------------*/
9474 static byte plci_nl_busy (PLCI *plci)
9476 /* only applicable for non-multiplexed protocols */
9477 return (plci->nl_req
9478 || (plci->ncci_ring_list
9479 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9480 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9484 /*------------------------------------------------------------------*/
9485 /* DTMF facilities */
9486 /*------------------------------------------------------------------*/
9489 static struct
9491 byte send_mask;
9492 byte listen_mask;
9493 byte character;
9494 byte code;
9495 } dtmf_digit_map[] =
9497 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9498 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9499 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9500 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9501 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9502 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9503 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9504 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9505 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9506 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9507 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9508 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9509 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9510 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9511 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9512 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9513 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9514 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9515 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9516 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9518 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9519 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9520 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9521 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9522 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9523 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9524 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9525 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9526 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9527 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9528 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9529 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9530 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9531 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9532 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9533 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9534 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9535 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9536 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9537 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9538 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9539 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9540 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9541 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9542 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9543 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9544 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9545 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9546 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9547 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9548 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9549 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9550 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9551 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9552 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9553 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9554 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9555 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9556 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9557 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9558 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9559 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9560 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9561 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9562 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9563 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9564 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9565 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9566 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9567 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9568 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9569 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9573 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9576 static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9578 word min_digit_duration, min_gap_duration;
9580 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9581 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9582 (char *)(FILE_), __LINE__, enable_mask));
9584 if (enable_mask != 0)
9586 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9587 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9588 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9589 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9590 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9591 plci->NData[0].PLength = 5;
9593 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9594 plci->NData[0].PLength += 2;
9595 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9598 else
9600 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9601 plci->NData[0].PLength = 1;
9603 capidtmf_recv_disable (&(plci->capidtmf_state));
9606 plci->NData[0].P = plci->internal_req_buffer;
9607 plci->NL.X = plci->NData;
9608 plci->NL.ReqCh = 0;
9609 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9610 plci->adapter->request (&plci->NL);
9614 static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9616 word w, i;
9618 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9619 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9620 (char *)(FILE_), __LINE__, digit_count));
9622 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9623 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9624 PUT_WORD (&plci->internal_req_buffer[1], w);
9625 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9626 PUT_WORD (&plci->internal_req_buffer[3], w);
9627 for (i = 0; i < digit_count; i++)
9629 w = 0;
9630 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9631 && (digit_buffer[i] != dtmf_digit_map[w].character))
9633 w++;
9635 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9636 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9638 plci->NData[0].PLength = 5 + digit_count;
9639 plci->NData[0].P = plci->internal_req_buffer;
9640 plci->NL.X = plci->NData;
9641 plci->NL.ReqCh = 0;
9642 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9643 plci->adapter->request (&plci->NL);
9647 static void dtmf_rec_clear_config (PLCI *plci)
9650 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9651 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9652 (char *)(FILE_), __LINE__));
9654 plci->dtmf_rec_active = 0;
9655 plci->dtmf_rec_pulse_ms = 0;
9656 plci->dtmf_rec_pause_ms = 0;
9658 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9663 static void dtmf_send_clear_config (PLCI *plci)
9666 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9667 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9668 (char *)(FILE_), __LINE__));
9670 plci->dtmf_send_requests = 0;
9671 plci->dtmf_send_pulse_ms = 0;
9672 plci->dtmf_send_pause_ms = 0;
9676 static void dtmf_prepare_switch (dword Id, PLCI *plci)
9679 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9680 UnMapId (Id), (char *)(FILE_), __LINE__));
9682 while (plci->dtmf_send_requests != 0)
9683 dtmf_confirmation (Id, plci);
9687 static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9690 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9691 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9693 return (GOOD);
9697 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9699 word Info;
9701 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9702 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9704 Info = GOOD;
9705 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9707 switch (plci->adjust_b_state)
9709 case ADJUST_B_RESTORE_DTMF_1:
9710 plci->internal_command = plci->adjust_b_command;
9711 if (plci_nl_busy (plci))
9713 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9714 break;
9716 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9717 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9718 break;
9719 case ADJUST_B_RESTORE_DTMF_2:
9720 if ((Rc != OK) && (Rc != OK_FC))
9722 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9723 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9724 Info = _WRONG_STATE;
9725 break;
9727 break;
9730 return (Info);
9734 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9736 word internal_command, Info;
9737 byte mask;
9738 byte result[4];
9740 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9741 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9742 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9743 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9745 Info = GOOD;
9746 result[0] = 2;
9747 PUT_WORD (&result[1], DTMF_SUCCESS);
9748 internal_command = plci->internal_command;
9749 plci->internal_command = 0;
9750 mask = 0x01;
9751 switch (plci->dtmf_cmd)
9754 case DTMF_LISTEN_TONE_START:
9755 mask <<= 1;
9756 case DTMF_LISTEN_MF_START:
9757 mask <<= 1;
9759 case DTMF_LISTEN_START:
9760 switch (internal_command)
9762 default:
9763 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9764 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9765 case DTMF_COMMAND_1:
9766 if (adjust_b_process (Id, plci, Rc) != GOOD)
9768 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9769 UnMapId (Id), (char *)(FILE_), __LINE__));
9770 Info = _FACILITY_NOT_SUPPORTED;
9771 break;
9773 if (plci->internal_command)
9774 return;
9775 case DTMF_COMMAND_2:
9776 if (plci_nl_busy (plci))
9778 plci->internal_command = DTMF_COMMAND_2;
9779 return;
9781 plci->internal_command = DTMF_COMMAND_3;
9782 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9783 return;
9784 case DTMF_COMMAND_3:
9785 if ((Rc != OK) && (Rc != OK_FC))
9787 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9788 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9789 Info = _FACILITY_NOT_SUPPORTED;
9790 break;
9793 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9795 plci->dtmf_rec_active |= mask;
9796 break;
9798 break;
9801 case DTMF_LISTEN_TONE_STOP:
9802 mask <<= 1;
9803 case DTMF_LISTEN_MF_STOP:
9804 mask <<= 1;
9806 case DTMF_LISTEN_STOP:
9807 switch (internal_command)
9809 default:
9810 plci->dtmf_rec_active &= ~mask;
9811 if (plci->dtmf_rec_active)
9812 break;
9814 case DTMF_COMMAND_1:
9815 if (plci->dtmf_rec_active)
9817 if (plci_nl_busy (plci))
9819 plci->internal_command = DTMF_COMMAND_1;
9820 return;
9822 plci->dtmf_rec_active &= ~mask;
9823 plci->internal_command = DTMF_COMMAND_2;
9824 dtmf_enable_receiver (plci, false);
9825 return;
9827 Rc = OK;
9828 case DTMF_COMMAND_2:
9829 if ((Rc != OK) && (Rc != OK_FC))
9831 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9832 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9833 Info = _FACILITY_NOT_SUPPORTED;
9834 break;
9837 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9838 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9839 case DTMF_COMMAND_3:
9840 if (adjust_b_process (Id, plci, Rc) != GOOD)
9842 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9843 UnMapId (Id), (char *)(FILE_), __LINE__));
9844 Info = _FACILITY_NOT_SUPPORTED;
9845 break;
9847 if (plci->internal_command)
9848 return;
9849 break;
9851 break;
9854 case DTMF_SEND_TONE:
9855 mask <<= 1;
9856 case DTMF_SEND_MF:
9857 mask <<= 1;
9859 case DTMF_DIGITS_SEND:
9860 switch (internal_command)
9862 default:
9863 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9864 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9865 DTMF_COMMAND_1);
9866 case DTMF_COMMAND_1:
9867 if (adjust_b_process (Id, plci, Rc) != GOOD)
9869 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9870 UnMapId (Id), (char *)(FILE_), __LINE__));
9871 Info = _FACILITY_NOT_SUPPORTED;
9872 break;
9874 if (plci->internal_command)
9875 return;
9876 case DTMF_COMMAND_2:
9877 if (plci_nl_busy (plci))
9879 plci->internal_command = DTMF_COMMAND_2;
9880 return;
9882 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9883 plci->internal_command = DTMF_COMMAND_3;
9884 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9885 return;
9886 case DTMF_COMMAND_3:
9887 if ((Rc != OK) && (Rc != OK_FC))
9889 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9890 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9891 if (plci->dtmf_send_requests != 0)
9892 (plci->dtmf_send_requests)--;
9893 Info = _FACILITY_NOT_SUPPORTED;
9894 break;
9896 return;
9898 break;
9900 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9901 "wws", Info, SELECTOR_DTMF, result);
9905 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9907 word Info;
9908 word i, j;
9909 byte mask;
9910 API_PARSE dtmf_parms[5];
9911 byte result[40];
9913 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9914 UnMapId (Id), (char *)(FILE_), __LINE__));
9916 Info = GOOD;
9917 result[0] = 2;
9918 PUT_WORD (&result[1], DTMF_SUCCESS);
9919 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9921 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9922 UnMapId (Id), (char *)(FILE_), __LINE__));
9923 Info = _FACILITY_NOT_SUPPORTED;
9925 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9927 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9928 UnMapId (Id), (char *)(FILE_), __LINE__));
9929 Info = _WRONG_MESSAGE_FORMAT;
9932 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9933 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9935 if (!((a->requested_options_table[appl->Id-1])
9936 & (1L << PRIVATE_DTMF_TONE)))
9938 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9939 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9940 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9942 else
9944 for (i = 0; i < 32; i++)
9945 result[4 + i] = 0;
9946 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9948 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9950 if (dtmf_digit_map[i].listen_mask != 0)
9951 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9954 else
9956 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9958 if (dtmf_digit_map[i].send_mask != 0)
9959 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9962 result[0] = 3 + 32;
9963 result[3] = 32;
9967 else if (plci == NULL)
9969 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9970 UnMapId (Id), (char *)(FILE_), __LINE__));
9971 Info = _WRONG_IDENTIFIER;
9973 else
9975 if (!plci->State
9976 || !plci->NL.Id || plci->nl_remove_id)
9978 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9979 UnMapId (Id), (char *)(FILE_), __LINE__));
9980 Info = _WRONG_STATE;
9982 else
9984 plci->command = 0;
9985 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9986 mask = 0x01;
9987 switch (plci->dtmf_cmd)
9990 case DTMF_LISTEN_TONE_START:
9991 case DTMF_LISTEN_TONE_STOP:
9992 mask <<= 1;
9993 case DTMF_LISTEN_MF_START:
9994 case DTMF_LISTEN_MF_STOP:
9995 mask <<= 1;
9996 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9997 & (1L << PRIVATE_DTMF_TONE)))
9999 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10000 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10001 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10002 break;
10005 case DTMF_LISTEN_START:
10006 case DTMF_LISTEN_STOP:
10007 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10008 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10010 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10011 UnMapId (Id), (char *)(FILE_), __LINE__));
10012 Info = _FACILITY_NOT_SUPPORTED;
10013 break;
10015 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10017 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10019 plci->dtmf_rec_pulse_ms = 0;
10020 plci->dtmf_rec_pause_ms = 0;
10022 else
10024 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10025 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10028 start_internal_command (Id, plci, dtmf_command);
10029 return (false);
10032 case DTMF_SEND_TONE:
10033 mask <<= 1;
10034 case DTMF_SEND_MF:
10035 mask <<= 1;
10036 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10037 & (1L << PRIVATE_DTMF_TONE)))
10039 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10040 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10041 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10042 break;
10045 case DTMF_DIGITS_SEND:
10046 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10048 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10049 UnMapId (Id), (char *)(FILE_), __LINE__));
10050 Info = _WRONG_MESSAGE_FORMAT;
10051 break;
10053 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10055 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10056 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10058 i = 0;
10059 j = 0;
10060 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10062 j = 0;
10063 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10064 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10065 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10067 j++;
10069 i++;
10071 if (j == DTMF_DIGIT_MAP_ENTRIES)
10073 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10074 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10075 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10076 break;
10078 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10080 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10081 UnMapId (Id), (char *)(FILE_), __LINE__));
10082 Info = _WRONG_STATE;
10083 break;
10085 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10086 start_internal_command (Id, plci, dtmf_command);
10087 return (false);
10089 default:
10090 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10091 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10092 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10096 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10097 "wws", Info, SELECTOR_DTMF, result);
10098 return (false);
10102 static void dtmf_confirmation (dword Id, PLCI *plci)
10104 word Info;
10105 word i;
10106 byte result[4];
10108 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10109 UnMapId (Id), (char *)(FILE_), __LINE__));
10111 Info = GOOD;
10112 result[0] = 2;
10113 PUT_WORD (&result[1], DTMF_SUCCESS);
10114 if (plci->dtmf_send_requests != 0)
10116 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10117 "wws", GOOD, SELECTOR_DTMF, result);
10118 (plci->dtmf_send_requests)--;
10119 for (i = 0; i < plci->dtmf_send_requests; i++)
10120 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10125 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10127 word i, j, n;
10129 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10130 UnMapId (Id), (char *)(FILE_), __LINE__));
10132 n = 0;
10133 for (i = 1; i < length; i++)
10135 j = 0;
10136 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10137 && ((msg[i] != dtmf_digit_map[j].code)
10138 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10140 j++;
10142 if (j < DTMF_DIGIT_MAP_ENTRIES)
10145 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10146 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10147 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10149 if (n + 1 == i)
10151 for (i = length; i > n + 1; i--)
10152 msg[i] = msg[i - 1];
10153 length++;
10154 i++;
10156 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10158 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10160 msg[++n] = dtmf_digit_map[j].character;
10163 if (n != 0)
10165 msg[0] = (byte) n;
10166 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10171 /*------------------------------------------------------------------*/
10172 /* DTMF parameters */
10173 /*------------------------------------------------------------------*/
10175 static void dtmf_parameter_write (PLCI *plci)
10177 word i;
10178 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10180 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10181 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10182 (char *)(FILE_), __LINE__));
10184 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10185 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10186 for (i = 0; i < plci->dtmf_parameter_length; i++)
10187 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10188 add_p (plci, FTY, parameter_buffer);
10189 sig_req (plci, TEL_CTRL, 0);
10190 send_req (plci);
10194 static void dtmf_parameter_clear_config (PLCI *plci)
10197 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10198 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10199 (char *)(FILE_), __LINE__));
10201 plci->dtmf_parameter_length = 0;
10205 static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10208 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10209 UnMapId (Id), (char *)(FILE_), __LINE__));
10214 static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10217 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10218 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10220 return (GOOD);
10224 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10226 word Info;
10228 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10229 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231 Info = GOOD;
10232 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10233 && (plci->dtmf_parameter_length != 0))
10235 switch (plci->adjust_b_state)
10237 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10238 plci->internal_command = plci->adjust_b_command;
10239 if (plci->sig_req)
10241 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10242 break;
10244 dtmf_parameter_write (plci);
10245 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10246 break;
10247 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10248 if ((Rc != OK) && (Rc != OK_FC))
10250 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10251 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10252 Info = _WRONG_STATE;
10253 break;
10255 break;
10258 return (Info);
10262 /*------------------------------------------------------------------*/
10263 /* Line interconnect facilities */
10264 /*------------------------------------------------------------------*/
10267 LI_CONFIG *li_config_table;
10268 word li_total_channels;
10271 /*------------------------------------------------------------------*/
10272 /* translate a CHI information element to a channel number */
10273 /* returns 0xff - any channel */
10274 /* 0xfe - chi wrong coding */
10275 /* 0xfd - D-channel */
10276 /* 0x00 - no channel */
10277 /* else channel number / PRI: timeslot */
10278 /* if channels is provided we accept more than one channel. */
10279 /*------------------------------------------------------------------*/
10281 static byte chi_to_channel (byte *chi, dword *pchannelmap)
10283 int p;
10284 int i;
10285 dword map;
10286 byte excl;
10287 byte ofs;
10288 byte ch;
10290 if (pchannelmap) *pchannelmap = 0;
10291 if(!chi[0]) return 0xff;
10292 excl = 0;
10294 if(chi[1] & 0x20) {
10295 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10296 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10297 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10298 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10299 if(chi[1] &0x08) excl = 0x40;
10301 /* int. id present */
10302 if(chi[1] &0x40) {
10303 p=i+1;
10304 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10305 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10308 /* coding standard, Number/Map, Channel Type */
10309 p=i+1;
10310 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10311 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10312 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10314 /* Number/Map */
10315 if(chi[p] &0x10) {
10317 /* map */
10318 if((chi[0]-p)==4) ofs = 0;
10319 else if((chi[0]-p)==3) ofs = 1;
10320 else return 0xfe;
10321 ch = 0;
10322 map = 0;
10323 for(i=0; i<4 && p<chi[0]; i++) {
10324 p++;
10325 ch += 8;
10326 map <<= 8;
10327 if(chi[p]) {
10328 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10329 map |= chi[p];
10332 ch += ofs;
10333 map <<= ofs;
10335 else {
10337 /* number */
10338 p=i+1;
10339 ch = chi[p] &0x3f;
10340 if(pchannelmap) {
10341 if((byte)(chi[0]-p)>30) return 0xfe;
10342 map = 0;
10343 for(i=p; i<=chi[0]; i++) {
10344 if ((chi[i] &0x7f) > 31) return 0xfe;
10345 map |= (1L << (chi[i] &0x7f));
10348 else {
10349 if(p!=chi[0]) return 0xfe;
10350 if (ch > 31) return 0xfe;
10351 map = (1L << ch);
10353 if(chi[p] &0x40) return 0xfe;
10355 if (pchannelmap) *pchannelmap = map;
10356 else if (map != ((dword)(1L << ch))) return 0xfe;
10357 return (byte)(excl | ch);
10359 else { /* not PRI */
10360 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10361 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10362 if(chi[1] &0x08) excl = 0x40;
10364 switch(chi[1] |0x98) {
10365 case 0x98: return 0;
10366 case 0x99:
10367 if (pchannelmap) *pchannelmap = 2;
10368 return excl |1;
10369 case 0x9a:
10370 if (pchannelmap) *pchannelmap = 4;
10371 return excl |2;
10372 case 0x9b: return 0xff;
10373 case 0x9c: return 0xfd; /* d-ch */
10374 default: return 0xfe;
10380 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10382 DIVA_CAPI_ADAPTER *a;
10383 PLCI *splci;
10384 byte old_id;
10386 a = plci->adapter;
10387 old_id = plci->li_bchannel_id;
10388 if (a->li_pri)
10390 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10391 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10392 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10393 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10394 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10396 else
10398 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
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 & 0x03;
10403 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10405 splci = a->AdvSignalPLCI;
10406 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10408 if ((splci->li_bchannel_id != 0)
10409 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10411 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10413 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10414 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10415 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10416 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10417 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10420 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10421 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10424 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10425 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10427 mixer_clear_config (plci);
10429 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10430 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10431 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10435 static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10437 DIVA_CAPI_ADAPTER *a;
10438 PLCI *splci;
10439 byte ch, old_id;
10441 a = plci->adapter;
10442 old_id = plci->li_bchannel_id;
10443 ch = chi_to_channel (chi, NULL);
10444 if (!(ch & 0x80))
10446 if (a->li_pri)
10448 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10449 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10450 plci->li_bchannel_id = (ch & 0x1f) + 1;
10451 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10452 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10454 else
10456 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
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;
10461 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10463 splci = a->AdvSignalPLCI;
10464 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10466 if ((splci->li_bchannel_id != 0)
10467 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10469 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10471 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10472 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10473 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10474 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10475 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10478 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10479 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10483 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10484 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10486 mixer_clear_config (plci);
10488 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10489 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10490 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10494 #define MIXER_MAX_DUMP_CHANNELS 34
10496 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10498 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10499 word n, i, j;
10500 char *p;
10501 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10503 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10504 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10506 for (i = 0; i < li_total_channels; i++)
10508 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10509 if (li_config_table[i].chflags != 0)
10510 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10511 else
10513 for (j = 0; j < li_total_channels; j++)
10515 if (((li_config_table[i].flag_table[j]) != 0)
10516 || ((li_config_table[j].flag_table[i]) != 0))
10518 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10520 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10521 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10523 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10528 for (i = 0; i < li_total_channels; i++)
10530 for (j = 0; j < li_total_channels; j++)
10532 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10533 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10534 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10537 for (n = 0; n < li_total_channels; n++)
10539 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10541 for (i = 0; i < li_total_channels; i++)
10543 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10545 for (j = 0; j < li_total_channels; j++)
10547 li_config_table[i].coef_table[j] |=
10548 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10554 for (i = 0; i < li_total_channels; i++)
10556 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10558 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10559 for (j = 0; j < li_total_channels; j++)
10561 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10562 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10564 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10565 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10568 for (i = 0; i < li_total_channels; i++)
10570 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10572 for (j = 0; j < li_total_channels; j++)
10574 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10575 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10576 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10577 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10578 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10579 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10580 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10581 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10583 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10585 for (j = 0; j < li_total_channels; j++)
10587 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10589 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10591 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10595 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10597 for (j = 0; j < li_total_channels; j++)
10599 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10600 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10603 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10605 for (j = 0; j < li_total_channels; j++)
10607 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10609 for (n = 0; n < li_total_channels; n++)
10611 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10613 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10614 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10616 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10617 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10618 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10620 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10621 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10629 for (i = 0; i < li_total_channels; i++)
10631 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10633 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10634 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10635 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10636 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10637 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10638 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10639 for (j = 0; j < li_total_channels; j++)
10641 if ((li_config_table[i].flag_table[j] &
10642 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10643 || (li_config_table[j].flag_table[i] &
10644 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10646 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10648 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10649 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10650 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10651 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10653 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10655 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10656 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10660 for (i = 0; i < li_total_channels; i++)
10662 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10664 j = 0;
10665 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10666 j++;
10667 if (j < li_total_channels)
10669 for (j = 0; j < li_total_channels; j++)
10671 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10672 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10673 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10678 n = li_total_channels;
10679 if (n > MIXER_MAX_DUMP_CHANNELS)
10680 n = MIXER_MAX_DUMP_CHANNELS;
10681 p = hex_line;
10682 for (j = 0; j < n; j++)
10684 if ((j & 0x7) == 0)
10685 *(p++) = ' ';
10686 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10687 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10689 *p = '\0';
10690 dbug (1, dprintf ("[%06lx] CURRENT %s",
10691 (dword)(UnMapController (a->Id)), (char *) hex_line));
10692 p = hex_line;
10693 for (j = 0; j < n; j++)
10695 if ((j & 0x7) == 0)
10696 *(p++) = ' ';
10697 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10698 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10700 *p = '\0';
10701 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10702 (dword)(UnMapController (a->Id)), (char *) hex_line));
10703 p = hex_line;
10704 for (j = 0; j < n; j++)
10706 if ((j & 0x7) == 0)
10707 *(p++) = ' ';
10708 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10709 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10711 *p = '\0';
10712 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10713 (dword)(UnMapController (a->Id)), (char *) hex_line));
10714 for (i = 0; i < n; i++)
10716 p = hex_line;
10717 for (j = 0; j < n; j++)
10719 if ((j & 0x7) == 0)
10720 *(p++) = ' ';
10721 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10722 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10724 *p = '\0';
10725 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10726 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10728 for (i = 0; i < n; i++)
10730 p = hex_line;
10731 for (j = 0; j < n; j++)
10733 if ((j & 0x7) == 0)
10734 *(p++) = ' ';
10735 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10736 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10738 *p = '\0';
10739 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10740 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10745 static struct
10747 byte mask;
10748 byte line_flags;
10749 } mixer_write_prog_pri[] =
10751 { LI_COEF_CH_CH, 0 },
10752 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10753 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10754 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10757 static struct
10759 byte from_ch;
10760 byte to_ch;
10761 byte mask;
10762 byte xconnect_override;
10763 } mixer_write_prog_bri[] =
10765 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10766 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10767 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10768 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10769 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10770 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10771 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10772 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10773 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10774 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10775 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10776 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10777 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10778 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10779 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10780 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10781 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10782 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10783 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10784 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10785 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10786 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10787 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10788 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10789 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10790 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10791 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10792 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10793 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10794 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10795 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10796 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10797 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10798 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10799 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10800 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10803 static byte mixer_swapped_index_bri[] =
10805 18, /* B to B */
10806 19, /* Alt B to B */
10807 20, /* PC to B */
10808 21, /* Alt PC to B */
10809 22, /* IC to B */
10810 23, /* Alt IC to B */
10811 24, /* B to PC */
10812 25, /* Alt B to PC */
10813 26, /* PC to PC */
10814 27, /* Alt PC to PC */
10815 28, /* IC to PC */
10816 29, /* Alt IC to PC */
10817 30, /* B to IC */
10818 31, /* Alt B to IC */
10819 32, /* PC to IC */
10820 33, /* Alt PC to IC */
10821 34, /* IC to IC */
10822 35, /* Alt IC to IC */
10823 0, /* Alt B to Alt B */
10824 1, /* B to Alt B */
10825 2, /* Alt PC to Alt B */
10826 3, /* PC to Alt B */
10827 4, /* Alt IC to Alt B */
10828 5, /* IC to Alt B */
10829 6, /* Alt B to Alt PC */
10830 7, /* B to Alt PC */
10831 8, /* Alt PC to Alt PC */
10832 9, /* PC to Alt PC */
10833 10, /* Alt IC to Alt PC */
10834 11, /* IC to Alt PC */
10835 12, /* Alt B to Alt IC */
10836 13, /* B to Alt IC */
10837 14, /* Alt PC to Alt IC */
10838 15, /* PC to Alt IC */
10839 16, /* Alt IC to Alt IC */
10840 17 /* IC to Alt IC */
10843 static struct
10845 byte mask;
10846 byte from_pc;
10847 byte to_pc;
10848 } xconnect_write_prog[] =
10850 { LI_COEF_CH_CH, false, false },
10851 { LI_COEF_CH_PC, false, true },
10852 { LI_COEF_PC_CH, true, false },
10853 { LI_COEF_PC_PC, true, true }
10857 static void xconnect_query_addresses (PLCI *plci)
10859 DIVA_CAPI_ADAPTER *a;
10860 word w, ch;
10861 byte *p;
10863 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10864 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10865 (char *)(FILE_), __LINE__));
10867 a = plci->adapter;
10868 if (a->li_pri && ((plci->li_bchannel_id == 0)
10869 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10871 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10872 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10873 (char *)(FILE_), __LINE__));
10874 return;
10876 p = plci->internal_req_buffer;
10877 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10878 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10879 w = ch;
10880 *(p++) = (byte) w;
10881 *(p++) = (byte)(w >> 8);
10882 w = ch | XCONNECT_CHANNEL_PORT_PC;
10883 *(p++) = (byte) w;
10884 *(p++) = (byte)(w >> 8);
10885 plci->NData[0].P = plci->internal_req_buffer;
10886 plci->NData[0].PLength = p - plci->internal_req_buffer;
10887 plci->NL.X = plci->NData;
10888 plci->NL.ReqCh = 0;
10889 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10890 plci->adapter->request (&plci->NL);
10894 static void xconnect_write_coefs (PLCI *plci, word internal_command)
10897 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10898 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10899 (char *)(FILE_), __LINE__, internal_command));
10901 plci->li_write_command = internal_command;
10902 plci->li_write_channel = 0;
10906 static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10908 DIVA_CAPI_ADAPTER *a;
10909 word w, n, i, j, r, s, to_ch;
10910 dword d;
10911 byte *p;
10912 struct xconnect_transfer_address_s *transfer_address;
10913 byte ch_map[MIXER_CHANNELS_BRI];
10915 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10916 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10918 a = plci->adapter;
10919 if ((plci->li_bchannel_id == 0)
10920 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10922 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10923 UnMapId (Id), (char *)(FILE_), __LINE__));
10924 return (true);
10926 i = a->li_base + (plci->li_bchannel_id - 1);
10927 j = plci->li_write_channel;
10928 p = plci->internal_req_buffer;
10929 if (j != 0)
10931 if ((Rc != OK) && (Rc != OK_FC))
10933 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10934 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10935 return (false);
10938 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10940 r = 0;
10941 s = 0;
10942 if (j < li_total_channels)
10944 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10946 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10947 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10948 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10949 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10951 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10952 while ((j < li_total_channels)
10953 && ((r == 0)
10954 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10955 || (!li_config_table[j].adapter->li_pri
10956 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10957 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10958 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10959 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10960 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10961 || ((li_config_table[j].adapter->li_base != a->li_base)
10962 && !(r & s &
10963 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10964 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10965 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10966 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10968 j++;
10969 if (j < li_total_channels)
10970 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10973 if (j < li_total_channels)
10975 plci->internal_command = plci->li_write_command;
10976 if (plci_nl_busy (plci))
10977 return (true);
10978 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10979 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10982 if (li_config_table[j].adapter->li_base != a->li_base)
10984 r &= s &
10985 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10986 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10987 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10988 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10990 n = 0;
10993 if (r & xconnect_write_prog[n].mask)
10995 if (xconnect_write_prog[n].from_pc)
10996 transfer_address = &(li_config_table[j].send_pc);
10997 else
10998 transfer_address = &(li_config_table[j].send_b);
10999 d = transfer_address->card_address.low;
11000 *(p++) = (byte) d;
11001 *(p++) = (byte)(d >> 8);
11002 *(p++) = (byte)(d >> 16);
11003 *(p++) = (byte)(d >> 24);
11004 d = transfer_address->card_address.high;
11005 *(p++) = (byte) d;
11006 *(p++) = (byte)(d >> 8);
11007 *(p++) = (byte)(d >> 16);
11008 *(p++) = (byte)(d >> 24);
11009 d = transfer_address->offset;
11010 *(p++) = (byte) d;
11011 *(p++) = (byte)(d >> 8);
11012 *(p++) = (byte)(d >> 16);
11013 *(p++) = (byte)(d >> 24);
11014 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11015 *(p++) = (byte) w;
11016 *(p++) = (byte)(w >> 8);
11017 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11018 (li_config_table[i].adapter->u_law ?
11019 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11020 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11021 *(p++) = (byte) w;
11022 *(p++) = (byte) 0;
11023 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11025 n++;
11026 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11027 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11028 if (n == ARRAY_SIZE(xconnect_write_prog))
11032 j++;
11033 if (j < li_total_channels)
11034 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11035 } while ((j < li_total_channels)
11036 && ((r == 0)
11037 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11038 || (!li_config_table[j].adapter->li_pri
11039 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11040 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11041 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11042 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11043 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11044 || ((li_config_table[j].adapter->li_base != a->li_base)
11045 && !(r & s &
11046 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11047 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11048 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11049 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11051 } while ((j < li_total_channels)
11052 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11054 else if (j == li_total_channels)
11056 plci->internal_command = plci->li_write_command;
11057 if (plci_nl_busy (plci))
11058 return (true);
11059 if (a->li_pri)
11061 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11062 w = 0;
11063 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11064 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11065 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11066 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11067 *(p++) = (byte) w;
11068 *(p++) = (byte)(w >> 8);
11070 else
11072 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11073 w = 0;
11074 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11075 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11077 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11079 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11080 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11081 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11082 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11083 *(p++) = (byte) w;
11084 *(p++) = (byte)(w >> 8);
11085 for (j = 0; j < sizeof(ch_map); j += 2)
11087 if (plci->li_bchannel_id == 2)
11089 ch_map[j] = (byte)(j+1);
11090 ch_map[j+1] = (byte) j;
11092 else
11094 ch_map[j] = (byte) j;
11095 ch_map[j+1] = (byte)(j+1);
11098 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11100 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11101 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11102 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11104 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11105 mixer_write_prog_bri[n].xconnect_override :
11106 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11107 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11109 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11110 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11113 else
11115 *p = 0x00;
11116 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11118 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11119 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11120 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11123 p++;
11126 j = li_total_channels + 1;
11129 else
11131 if (j <= li_total_channels)
11133 plci->internal_command = plci->li_write_command;
11134 if (plci_nl_busy (plci))
11135 return (true);
11136 if (j < a->li_base)
11137 j = a->li_base;
11138 if (a->li_pri)
11140 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11141 w = 0;
11142 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11143 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11144 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11145 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11146 *(p++) = (byte) w;
11147 *(p++) = (byte)(w >> 8);
11148 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11150 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11151 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11153 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11154 if (w & mixer_write_prog_pri[n].mask)
11156 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11157 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11159 else
11160 *(p++) = 0x00;
11162 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11163 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11165 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11166 if (w & mixer_write_prog_pri[n].mask)
11168 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11171 else
11172 *(p++) = 0x00;
11176 else
11178 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11179 w = 0;
11180 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11181 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11183 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11185 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11186 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11187 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11188 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11189 *(p++) = (byte) w;
11190 *(p++) = (byte)(w >> 8);
11191 for (j = 0; j < sizeof(ch_map); j += 2)
11193 if (plci->li_bchannel_id == 2)
11195 ch_map[j] = (byte)(j+1);
11196 ch_map[j+1] = (byte) j;
11198 else
11200 ch_map[j] = (byte) j;
11201 ch_map[j+1] = (byte)(j+1);
11204 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11206 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11207 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11208 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11210 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11211 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11212 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11214 else
11216 *p = 0x00;
11217 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11219 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11220 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11221 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11224 p++;
11227 j = li_total_channels + 1;
11230 plci->li_write_channel = j;
11231 if (p != plci->internal_req_buffer)
11233 plci->NData[0].P = plci->internal_req_buffer;
11234 plci->NData[0].PLength = p - plci->internal_req_buffer;
11235 plci->NL.X = plci->NData;
11236 plci->NL.ReqCh = 0;
11237 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11238 plci->adapter->request (&plci->NL);
11240 return (true);
11244 static void mixer_notify_update (PLCI *plci, byte others)
11246 DIVA_CAPI_ADAPTER *a;
11247 word i, w;
11248 PLCI *notify_plci;
11249 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11251 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11252 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11253 (char *)(FILE_), __LINE__, others));
11255 a = plci->adapter;
11256 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11258 if (others)
11259 plci->li_notify_update = true;
11260 i = 0;
11263 notify_plci = NULL;
11264 if (others)
11266 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11267 i++;
11268 if (i < li_total_channels)
11269 notify_plci = li_config_table[i++].plci;
11271 else
11273 if ((plci->li_bchannel_id != 0)
11274 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11276 notify_plci = plci;
11279 if ((notify_plci != NULL)
11280 && !notify_plci->li_notify_update
11281 && (notify_plci->appl != NULL)
11282 && (notify_plci->State)
11283 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11285 notify_plci->li_notify_update = true;
11286 ((CAPI_MSG *) msg)->header.length = 18;
11287 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11288 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11289 ((CAPI_MSG *) msg)->header.number = 0;
11290 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11291 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11292 ((CAPI_MSG *) msg)->header.ncci = 0;
11293 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11294 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11295 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11296 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11297 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11298 if (w != _QUEUE_FULL)
11300 if (w != 0)
11302 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11303 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11304 (char *)(FILE_), __LINE__,
11305 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11307 notify_plci->li_notify_update = false;
11310 } while (others && (notify_plci != NULL));
11311 if (others)
11312 plci->li_notify_update = false;
11317 static void mixer_clear_config (PLCI *plci)
11319 DIVA_CAPI_ADAPTER *a;
11320 word i, j;
11322 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11323 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11324 (char *)(FILE_), __LINE__));
11326 plci->li_notify_update = false;
11327 plci->li_plci_b_write_pos = 0;
11328 plci->li_plci_b_read_pos = 0;
11329 plci->li_plci_b_req_pos = 0;
11330 a = plci->adapter;
11331 if ((plci->li_bchannel_id != 0)
11332 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11334 i = a->li_base + (plci->li_bchannel_id - 1);
11335 li_config_table[i].curchnl = 0;
11336 li_config_table[i].channel = 0;
11337 li_config_table[i].chflags = 0;
11338 for (j = 0; j < li_total_channels; j++)
11340 li_config_table[j].flag_table[i] = 0;
11341 li_config_table[i].flag_table[j] = 0;
11342 li_config_table[i].coef_table[j] = 0;
11343 li_config_table[j].coef_table[i] = 0;
11345 if (!a->li_pri)
11347 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11348 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11350 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11351 li_config_table[i].curchnl = 0;
11352 li_config_table[i].channel = 0;
11353 li_config_table[i].chflags = 0;
11354 for (j = 0; j < li_total_channels; j++)
11356 li_config_table[i].flag_table[j] = 0;
11357 li_config_table[j].flag_table[i] = 0;
11358 li_config_table[i].coef_table[j] = 0;
11359 li_config_table[j].coef_table[i] = 0;
11361 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11363 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11364 li_config_table[i].curchnl = 0;
11365 li_config_table[i].channel = 0;
11366 li_config_table[i].chflags = 0;
11367 for (j = 0; j < li_total_channels; j++)
11369 li_config_table[i].flag_table[j] = 0;
11370 li_config_table[j].flag_table[i] = 0;
11371 li_config_table[i].coef_table[j] = 0;
11372 li_config_table[j].coef_table[i] = 0;
11381 static void mixer_prepare_switch (dword Id, PLCI *plci)
11384 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11385 UnMapId (Id), (char *)(FILE_), __LINE__));
11389 mixer_indication_coefs_set (Id, plci);
11390 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11394 static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11396 DIVA_CAPI_ADAPTER *a;
11397 word i, j;
11399 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11400 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11402 a = plci->adapter;
11403 if ((plci->li_bchannel_id != 0)
11404 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11406 i = a->li_base + (plci->li_bchannel_id - 1);
11407 for (j = 0; j < li_total_channels; j++)
11409 li_config_table[i].coef_table[j] &= 0xf;
11410 li_config_table[j].coef_table[i] &= 0xf;
11412 if (!a->li_pri)
11413 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11415 return (GOOD);
11419 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11421 DIVA_CAPI_ADAPTER *a;
11422 word Info;
11424 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11425 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11427 Info = GOOD;
11428 a = plci->adapter;
11429 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11430 && (plci->li_bchannel_id != 0)
11431 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11433 switch (plci->adjust_b_state)
11435 case ADJUST_B_RESTORE_MIXER_1:
11436 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11438 plci->internal_command = plci->adjust_b_command;
11439 if (plci_nl_busy (plci))
11441 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11442 break;
11444 xconnect_query_addresses (plci);
11445 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11446 break;
11448 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11449 Rc = OK;
11450 case ADJUST_B_RESTORE_MIXER_2:
11451 case ADJUST_B_RESTORE_MIXER_3:
11452 case ADJUST_B_RESTORE_MIXER_4:
11453 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11455 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11456 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11457 Info = _WRONG_STATE;
11458 break;
11460 if (Rc == OK)
11462 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11463 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11464 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11465 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11467 else if (Rc == 0)
11469 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11470 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11471 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11472 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11474 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11476 plci->internal_command = plci->adjust_b_command;
11477 break;
11479 case ADJUST_B_RESTORE_MIXER_5:
11480 xconnect_write_coefs (plci, plci->adjust_b_command);
11481 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11482 Rc = OK;
11483 case ADJUST_B_RESTORE_MIXER_6:
11484 if (!xconnect_write_coefs_process (Id, plci, Rc))
11486 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11487 UnMapId (Id), (char *)(FILE_), __LINE__));
11488 Info = _FACILITY_NOT_SUPPORTED;
11489 break;
11491 if (plci->internal_command)
11492 break;
11493 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11494 case ADJUST_B_RESTORE_MIXER_7:
11495 break;
11498 return (Info);
11502 static void mixer_command (dword Id, PLCI *plci, byte Rc)
11504 DIVA_CAPI_ADAPTER *a;
11505 word i, internal_command, Info;
11507 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11508 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11509 plci->li_cmd));
11511 Info = GOOD;
11512 a = plci->adapter;
11513 internal_command = plci->internal_command;
11514 plci->internal_command = 0;
11515 switch (plci->li_cmd)
11517 case LI_REQ_CONNECT:
11518 case LI_REQ_DISCONNECT:
11519 case LI_REQ_SILENT_UPDATE:
11520 switch (internal_command)
11522 default:
11523 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11525 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11526 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11528 case MIXER_COMMAND_1:
11529 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11531 if (adjust_b_process (Id, plci, Rc) != GOOD)
11533 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11534 UnMapId (Id), (char *)(FILE_), __LINE__));
11535 Info = _FACILITY_NOT_SUPPORTED;
11536 break;
11538 if (plci->internal_command)
11539 return;
11541 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11542 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11543 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11544 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11545 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11547 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11549 else
11553 mixer_indication_coefs_set (Id, plci);
11554 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11556 case MIXER_COMMAND_2:
11557 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11558 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11559 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11560 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11562 if (!xconnect_write_coefs_process (Id, plci, Rc))
11564 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11565 UnMapId (Id), (char *)(FILE_), __LINE__));
11566 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11570 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11571 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11572 i = (plci->li_plci_b_write_pos == 0) ?
11573 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11574 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11575 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11577 Info = _FACILITY_NOT_SUPPORTED;
11578 break;
11580 if (plci->internal_command)
11581 return;
11583 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11585 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11586 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11588 case MIXER_COMMAND_3:
11589 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11591 if (adjust_b_process (Id, plci, Rc) != GOOD)
11593 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11594 UnMapId (Id), (char *)(FILE_), __LINE__));
11595 Info = _FACILITY_NOT_SUPPORTED;
11596 break;
11598 if (plci->internal_command)
11599 return;
11601 break;
11603 break;
11605 if ((plci->li_bchannel_id == 0)
11606 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11608 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11609 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11611 else
11613 i = a->li_base + (plci->li_bchannel_id - 1);
11614 li_config_table[i].curchnl = plci->li_channel_bits;
11615 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11617 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11618 li_config_table[i].curchnl = plci->li_channel_bits;
11619 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11621 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11622 li_config_table[i].curchnl = plci->li_channel_bits;
11629 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11630 dword plci_b_id, byte connect, dword li_flags)
11632 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11633 PLCI *plci_b;
11634 DIVA_CAPI_ADAPTER *a_b;
11636 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11637 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11638 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11639 if (!a->li_pri && (plci->tel == ADV_VOICE)
11640 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11642 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11643 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11644 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11646 else
11648 ch_a_v = ch_a;
11649 ch_a_s = ch_a;
11651 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11652 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11653 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11655 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11656 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11657 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11659 else
11661 ch_b_v = ch_b;
11662 ch_b_s = ch_b;
11664 if (connect)
11666 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11667 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11668 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11671 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11672 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11673 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11674 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11675 if (ch_a_v == ch_b_v)
11677 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11678 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11680 else
11682 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11684 for (i = 0; i < li_total_channels; i++)
11686 if (i != ch_a_v)
11687 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11690 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11692 for (i = 0; i < li_total_channels; i++)
11694 if (i != ch_a_s)
11695 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11698 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11700 for (i = 0; i < li_total_channels; i++)
11702 if (i != ch_a_v)
11703 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11706 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11708 for (i = 0; i < li_total_channels; i++)
11710 if (i != ch_a_s)
11711 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11715 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11717 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11718 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11722 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11724 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11725 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11726 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11727 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11729 if (li_flags & LI_FLAG_MONITOR_A)
11731 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11732 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11734 if (li_flags & LI_FLAG_MONITOR_B)
11736 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11737 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11739 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11741 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11744 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11746 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11747 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11749 if (li_flags & LI_FLAG_MIX_A)
11751 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11752 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11754 if (li_flags & LI_FLAG_MIX_B)
11756 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11757 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11759 if (ch_a_v != ch_a_s)
11761 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11762 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11764 if (ch_b_v != ch_b_s)
11766 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11767 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11772 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11773 dword plci_b_id, byte connect, dword li_flags)
11775 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11776 PLCI *plci_b;
11777 DIVA_CAPI_ADAPTER *a_b;
11779 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11780 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11781 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11782 if (!a->li_pri && (plci->tel == ADV_VOICE)
11783 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11785 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11786 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11787 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11789 else
11791 ch_a_v = ch_a;
11792 ch_a_s = ch_a;
11794 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11795 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11796 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11798 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11799 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11800 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11802 else
11804 ch_b_v = ch_b;
11805 ch_b_s = ch_b;
11807 if (connect)
11809 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11810 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11811 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11812 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11813 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11814 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11816 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11826 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11827 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11831 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11833 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11834 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11835 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11836 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11838 if (li_flags & LI2_FLAG_MONITOR_B)
11840 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11841 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11843 if (li_flags & LI2_FLAG_MIX_B)
11845 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11846 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11848 if (li_flags & LI2_FLAG_MONITOR_X)
11849 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11850 if (li_flags & LI2_FLAG_MIX_X)
11851 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11852 if (li_flags & LI2_FLAG_LOOP_B)
11854 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11856 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11857 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859 if (li_flags & LI2_FLAG_LOOP_PC)
11860 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11861 if (li_flags & LI2_FLAG_LOOP_X)
11862 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11863 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11864 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11865 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11866 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11867 if (ch_a_v != ch_a_s)
11869 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11870 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11872 if (ch_b_v != ch_b_s)
11874 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11875 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11880 static word li_check_main_plci (dword Id, PLCI *plci)
11882 if (plci == NULL)
11884 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11885 UnMapId (Id), (char *)(FILE_), __LINE__));
11886 return (_WRONG_IDENTIFIER);
11888 if (!plci->State
11889 || !plci->NL.Id || plci->nl_remove_id
11890 || (plci->li_bchannel_id == 0))
11892 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11893 UnMapId (Id), (char *)(FILE_), __LINE__));
11894 return (_WRONG_STATE);
11896 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11897 return (GOOD);
11901 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11902 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11904 byte ctlr_b;
11905 PLCI *plci_b;
11907 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11908 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11910 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11911 UnMapId (Id), (char *)(FILE_), __LINE__));
11912 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11913 return (NULL);
11915 ctlr_b = 0;
11916 if ((plci_b_id & 0x7f) != 0)
11918 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11919 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11920 ctlr_b = 0;
11922 if ((ctlr_b == 0)
11923 || (((plci_b_id >> 8) & 0xff) == 0)
11924 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11926 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11927 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11928 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11929 return (NULL);
11931 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11932 if (!plci_b->State
11933 || !plci_b->NL.Id || plci_b->nl_remove_id
11934 || (plci_b->li_bchannel_id == 0))
11936 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11937 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11938 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11939 return (NULL);
11941 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11942 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11943 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11944 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11945 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11947 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11948 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11949 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11950 return (NULL);
11952 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11953 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11955 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11956 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11957 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11958 return (NULL);
11960 return (plci_b);
11964 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11965 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11967 byte ctlr_b;
11968 PLCI *plci_b;
11970 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11971 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11973 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11974 UnMapId (Id), (char *)(FILE_), __LINE__));
11975 PUT_WORD (p_result, _WRONG_STATE);
11976 return (NULL);
11978 ctlr_b = 0;
11979 if ((plci_b_id & 0x7f) != 0)
11981 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11982 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11983 ctlr_b = 0;
11985 if ((ctlr_b == 0)
11986 || (((plci_b_id >> 8) & 0xff) == 0)
11987 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11989 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11990 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11991 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11992 return (NULL);
11994 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11995 if (!plci_b->State
11996 || !plci_b->NL.Id || plci_b->nl_remove_id
11997 || (plci_b->li_bchannel_id == 0)
11998 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12000 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12001 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12002 PUT_WORD (p_result, _WRONG_STATE);
12003 return (NULL);
12005 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12006 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12007 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12008 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12010 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12011 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12012 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12013 return (NULL);
12015 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12016 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12018 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12019 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12020 PUT_WORD (p_result, _WRONG_STATE);
12021 return (NULL);
12023 return (plci_b);
12027 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12029 word Info;
12030 word i;
12031 dword d, li_flags, plci_b_id;
12032 PLCI *plci_b;
12033 API_PARSE li_parms[3];
12034 API_PARSE li_req_parms[3];
12035 API_PARSE li_participant_struct[2];
12036 API_PARSE li_participant_parms[3];
12037 word participant_parms_pos;
12038 byte result_buffer[32];
12039 byte *result;
12040 word result_pos;
12041 word plci_b_write_pos;
12043 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12044 UnMapId (Id), (char *)(FILE_), __LINE__));
12046 Info = GOOD;
12047 result = result_buffer;
12048 result_buffer[0] = 0;
12049 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12051 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12052 UnMapId (Id), (char *)(FILE_), __LINE__));
12053 Info = _FACILITY_NOT_SUPPORTED;
12055 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12057 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12058 UnMapId (Id), (char *)(FILE_), __LINE__));
12059 Info = _WRONG_MESSAGE_FORMAT;
12061 else
12063 result_buffer[0] = 3;
12064 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12065 result_buffer[3] = 0;
12066 switch (GET_WORD (li_parms[0].info))
12068 case LI_GET_SUPPORTED_SERVICES:
12069 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12071 result_buffer[0] = 17;
12072 result_buffer[3] = 14;
12073 PUT_WORD (&result_buffer[4], GOOD);
12074 d = 0;
12075 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12076 d |= LI_CONFERENCING_SUPPORTED;
12077 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12078 d |= LI_MONITORING_SUPPORTED;
12079 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12080 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12081 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12082 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12083 PUT_DWORD (&result_buffer[6], d);
12084 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12086 d = 0;
12087 for (i = 0; i < li_total_channels; i++)
12089 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12090 && (li_config_table[i].adapter->li_pri
12091 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12093 d++;
12097 else
12099 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12101 PUT_DWORD (&result_buffer[10], d / 2);
12102 PUT_DWORD (&result_buffer[14], d);
12104 else
12106 result_buffer[0] = 25;
12107 result_buffer[3] = 22;
12108 PUT_WORD (&result_buffer[4], GOOD);
12109 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12110 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12111 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12112 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12113 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12114 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12115 d |= LI2_PC_LOOPING_SUPPORTED;
12116 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12117 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12118 PUT_DWORD (&result_buffer[6], d);
12119 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12120 PUT_DWORD (&result_buffer[10], d / 2);
12121 PUT_DWORD (&result_buffer[14], d - 1);
12122 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12124 d = 0;
12125 for (i = 0; i < li_total_channels; i++)
12127 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12128 && (li_config_table[i].adapter->li_pri
12129 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12131 d++;
12135 PUT_DWORD (&result_buffer[18], d / 2);
12136 PUT_DWORD (&result_buffer[22], d - 1);
12138 break;
12140 case LI_REQ_CONNECT:
12141 if (li_parms[1].length == 8)
12143 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12144 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12146 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12147 UnMapId (Id), (char *)(FILE_), __LINE__));
12148 Info = _WRONG_MESSAGE_FORMAT;
12149 break;
12151 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12152 li_flags = GET_DWORD (li_req_parms[1].info);
12153 Info = li_check_main_plci (Id, plci);
12154 result_buffer[0] = 9;
12155 result_buffer[3] = 6;
12156 PUT_DWORD (&result_buffer[4], plci_b_id);
12157 PUT_WORD (&result_buffer[8], GOOD);
12158 if (Info != GOOD)
12159 break;
12160 result = plci->saved_msg.info;
12161 for (i = 0; i <= result_buffer[0]; i++)
12162 result[i] = result_buffer[i];
12163 plci_b_write_pos = plci->li_plci_b_write_pos;
12164 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12165 if (plci_b == NULL)
12166 break;
12167 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12168 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12169 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12170 plci->li_plci_b_write_pos = plci_b_write_pos;
12172 else
12174 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12175 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12177 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12178 UnMapId (Id), (char *)(FILE_), __LINE__));
12179 Info = _WRONG_MESSAGE_FORMAT;
12180 break;
12182 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12183 Info = li_check_main_plci (Id, plci);
12184 result_buffer[0] = 7;
12185 result_buffer[3] = 4;
12186 PUT_WORD (&result_buffer[4], Info);
12187 result_buffer[6] = 0;
12188 if (Info != GOOD)
12189 break;
12190 result = plci->saved_msg.info;
12191 for (i = 0; i <= result_buffer[0]; i++)
12192 result[i] = result_buffer[i];
12193 plci_b_write_pos = plci->li_plci_b_write_pos;
12194 participant_parms_pos = 0;
12195 result_pos = 7;
12196 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12197 while (participant_parms_pos < li_req_parms[1].length)
12199 result[result_pos] = 6;
12200 result_pos += 7;
12201 PUT_DWORD (&result[result_pos - 6], 0);
12202 PUT_WORD (&result[result_pos - 2], GOOD);
12203 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12204 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12207 UnMapId (Id), (char *)(FILE_), __LINE__));
12208 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12209 break;
12211 if (api_parse (&li_participant_struct[0].info[1],
12212 li_participant_struct[0].length, "dd", li_participant_parms))
12214 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12215 UnMapId (Id), (char *)(FILE_), __LINE__));
12216 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12217 break;
12219 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12220 li_flags = GET_DWORD (li_participant_parms[1].info);
12221 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12222 if (sizeof(result) - result_pos < 7)
12224 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12225 UnMapId (Id), (char *)(FILE_), __LINE__));
12226 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12227 break;
12229 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12230 if (plci_b != NULL)
12232 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12233 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12234 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12235 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12236 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12238 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12239 (&li_req_parms[1].info[1]));
12241 result[0] = (byte)(result_pos - 1);
12242 result[3] = (byte)(result_pos - 4);
12243 result[6] = (byte)(result_pos - 7);
12244 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12245 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12246 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12248 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12249 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12251 else
12252 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12253 plci->li_plci_b_write_pos = plci_b_write_pos;
12255 mixer_calculate_coefs (a);
12256 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12257 mixer_notify_update (plci, true);
12258 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12259 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12260 plci->command = 0;
12261 plci->li_cmd = GET_WORD (li_parms[0].info);
12262 start_internal_command (Id, plci, mixer_command);
12263 return (false);
12265 case LI_REQ_DISCONNECT:
12266 if (li_parms[1].length == 4)
12268 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12269 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12271 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12272 UnMapId (Id), (char *)(FILE_), __LINE__));
12273 Info = _WRONG_MESSAGE_FORMAT;
12274 break;
12276 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12277 Info = li_check_main_plci (Id, plci);
12278 result_buffer[0] = 9;
12279 result_buffer[3] = 6;
12280 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12281 PUT_WORD (&result_buffer[8], GOOD);
12282 if (Info != GOOD)
12283 break;
12284 result = plci->saved_msg.info;
12285 for (i = 0; i <= result_buffer[0]; i++)
12286 result[i] = result_buffer[i];
12287 plci_b_write_pos = plci->li_plci_b_write_pos;
12288 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12289 if (plci_b == NULL)
12290 break;
12291 li_update_connect (Id, a, plci, plci_b_id, false, 0);
12292 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12293 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12294 plci->li_plci_b_write_pos = plci_b_write_pos;
12296 else
12298 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12299 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12301 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12302 UnMapId (Id), (char *)(FILE_), __LINE__));
12303 Info = _WRONG_MESSAGE_FORMAT;
12304 break;
12306 Info = li_check_main_plci (Id, plci);
12307 result_buffer[0] = 7;
12308 result_buffer[3] = 4;
12309 PUT_WORD (&result_buffer[4], Info);
12310 result_buffer[6] = 0;
12311 if (Info != GOOD)
12312 break;
12313 result = plci->saved_msg.info;
12314 for (i = 0; i <= result_buffer[0]; i++)
12315 result[i] = result_buffer[i];
12316 plci_b_write_pos = plci->li_plci_b_write_pos;
12317 participant_parms_pos = 0;
12318 result_pos = 7;
12319 while (participant_parms_pos < li_req_parms[0].length)
12321 result[result_pos] = 6;
12322 result_pos += 7;
12323 PUT_DWORD (&result[result_pos - 6], 0);
12324 PUT_WORD (&result[result_pos - 2], GOOD);
12325 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12326 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12328 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12329 UnMapId (Id), (char *)(FILE_), __LINE__));
12330 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12331 break;
12333 if (api_parse (&li_participant_struct[0].info[1],
12334 li_participant_struct[0].length, "d", li_participant_parms))
12336 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12337 UnMapId (Id), (char *)(FILE_), __LINE__));
12338 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12339 break;
12341 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12342 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12343 if (sizeof(result) - result_pos < 7)
12345 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12346 UnMapId (Id), (char *)(FILE_), __LINE__));
12347 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12348 break;
12350 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12351 if (plci_b != NULL)
12353 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12354 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12355 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12357 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12358 (&li_req_parms[0].info[1]));
12360 result[0] = (byte)(result_pos - 1);
12361 result[3] = (byte)(result_pos - 4);
12362 result[6] = (byte)(result_pos - 7);
12363 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12364 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12365 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12367 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12368 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12370 else
12371 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12372 plci->li_plci_b_write_pos = plci_b_write_pos;
12374 mixer_calculate_coefs (a);
12375 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12376 mixer_notify_update (plci, true);
12377 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12378 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12379 plci->command = 0;
12380 plci->li_cmd = GET_WORD (li_parms[0].info);
12381 start_internal_command (Id, plci, mixer_command);
12382 return (false);
12384 case LI_REQ_SILENT_UPDATE:
12385 if (!plci || !plci->State
12386 || !plci->NL.Id || plci->nl_remove_id
12387 || (plci->li_bchannel_id == 0)
12388 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12390 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12391 UnMapId (Id), (char *)(FILE_), __LINE__));
12392 return (false);
12394 plci_b_write_pos = plci->li_plci_b_write_pos;
12395 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12396 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12398 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12399 UnMapId (Id), (char *)(FILE_), __LINE__));
12400 return (false);
12402 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12403 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12404 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12406 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12407 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12409 else
12410 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12411 plci->li_plci_b_write_pos = plci_b_write_pos;
12412 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12413 plci->command = 0;
12414 plci->li_cmd = GET_WORD (li_parms[0].info);
12415 start_internal_command (Id, plci, mixer_command);
12416 return (false);
12418 default:
12419 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12420 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12421 Info = _FACILITY_NOT_SUPPORTED;
12424 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12425 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12426 return (false);
12430 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12432 dword d;
12433 DIVA_CAPI_ADAPTER *a;
12434 byte result[12];
12436 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12437 UnMapId (Id), (char *)(FILE_), __LINE__));
12439 a = plci->adapter;
12440 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12444 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12445 if (!(d & LI_PLCI_B_SKIP_FLAG))
12447 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12449 if (d & LI_PLCI_B_DISC_FLAG)
12451 result[0] = 5;
12452 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12453 result[3] = 2;
12454 PUT_WORD (&result[4], _LI_USER_INITIATED);
12456 else
12458 result[0] = 7;
12459 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12460 result[3] = 4;
12461 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12464 else
12466 if (d & LI_PLCI_B_DISC_FLAG)
12468 result[0] = 9;
12469 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12470 result[3] = 6;
12471 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12472 PUT_WORD (&result[8], _LI_USER_INITIATED);
12474 else
12476 result[0] = 7;
12477 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12478 result[3] = 4;
12479 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12482 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12483 "ws", SELECTOR_LINE_INTERCONNECT, result);
12485 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12486 0 : plci->li_plci_b_read_pos + 1;
12487 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12492 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12494 word i, j, ch;
12495 struct xconnect_transfer_address_s s, *p;
12496 DIVA_CAPI_ADAPTER *a;
12498 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12499 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12501 a = plci->adapter;
12502 i = 1;
12503 for (i = 1; i < length; i += 16)
12505 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12506 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12507 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12508 ch = msg[i+12] | (msg[i+13] << 8);
12509 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12510 if (!a->li_pri && (plci->li_bchannel_id == 2))
12511 j = 1 - j;
12512 j += a->li_base;
12513 if (ch & XCONNECT_CHANNEL_PORT_PC)
12514 p = &(li_config_table[j].send_pc);
12515 else
12516 p = &(li_config_table[j].send_b);
12517 p->card_address.low = s.card_address.low;
12518 p->card_address.high = s.card_address.high;
12519 p->offset = s.offset;
12520 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12522 if (plci->internal_command_queue[0]
12523 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12524 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12525 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12527 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12528 if (!plci->internal_command)
12529 next_internal_command (Id, plci);
12531 mixer_notify_update (plci, true);
12535 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12538 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12539 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12544 static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12546 word plci_b_write_pos;
12548 plci_b_write_pos = plci->li_plci_b_write_pos;
12549 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12550 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12552 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12553 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12554 (char *)(FILE_), __LINE__));
12555 return (false);
12557 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12558 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12559 plci->li_plci_b_write_pos = plci_b_write_pos;
12560 return (true);
12564 static void mixer_remove (PLCI *plci)
12566 DIVA_CAPI_ADAPTER *a;
12567 PLCI *notify_plci;
12568 dword plci_b_id;
12569 word i, j;
12571 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12572 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12573 (char *)(FILE_), __LINE__));
12575 a = plci->adapter;
12576 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12577 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12579 if ((plci->li_bchannel_id != 0)
12580 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12582 i = a->li_base + (plci->li_bchannel_id - 1);
12583 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12585 for (j = 0; j < li_total_channels; j++)
12587 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12588 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12590 notify_plci = li_config_table[j].plci;
12591 if ((notify_plci != NULL)
12592 && (notify_plci != plci)
12593 && (notify_plci->appl != NULL)
12594 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12595 && (notify_plci->State)
12596 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12598 mixer_notify_source_removed (notify_plci, plci_b_id);
12602 mixer_clear_config (plci);
12603 mixer_calculate_coefs (a);
12604 mixer_notify_update (plci, true);
12606 li_config_table[i].plci = NULL;
12607 plci->li_bchannel_id = 0;
12613 /*------------------------------------------------------------------*/
12614 /* Echo canceller facilities */
12615 /*------------------------------------------------------------------*/
12618 static void ec_write_parameters (PLCI *plci)
12620 word w;
12621 byte parameter_buffer[6];
12623 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12624 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12625 (char *)(FILE_), __LINE__));
12627 parameter_buffer[0] = 5;
12628 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12629 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12630 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12631 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12632 PUT_WORD (&parameter_buffer[4], w);
12633 add_p (plci, FTY, parameter_buffer);
12634 sig_req (plci, TEL_CTRL, 0);
12635 send_req (plci);
12639 static void ec_clear_config (PLCI *plci)
12642 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12643 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12644 (char *)(FILE_), __LINE__));
12646 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12647 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12648 plci->ec_tail_length = 0;
12652 static void ec_prepare_switch (dword Id, PLCI *plci)
12655 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12656 UnMapId (Id), (char *)(FILE_), __LINE__));
12661 static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12664 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12665 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12667 return (GOOD);
12671 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12673 word Info;
12675 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12676 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12678 Info = GOOD;
12679 if (plci->B1_facilities & B1_FACILITY_EC)
12681 switch (plci->adjust_b_state)
12683 case ADJUST_B_RESTORE_EC_1:
12684 plci->internal_command = plci->adjust_b_command;
12685 if (plci->sig_req)
12687 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12688 break;
12690 ec_write_parameters (plci);
12691 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12692 break;
12693 case ADJUST_B_RESTORE_EC_2:
12694 if ((Rc != OK) && (Rc != OK_FC))
12696 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12697 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12698 Info = _WRONG_STATE;
12699 break;
12701 break;
12704 return (Info);
12708 static void ec_command (dword Id, PLCI *plci, byte Rc)
12710 word internal_command, Info;
12711 byte result[8];
12713 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12714 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12715 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12717 Info = GOOD;
12718 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12720 result[0] = 2;
12721 PUT_WORD (&result[1], EC_SUCCESS);
12723 else
12725 result[0] = 5;
12726 PUT_WORD (&result[1], plci->ec_cmd);
12727 result[3] = 2;
12728 PUT_WORD (&result[4], GOOD);
12730 internal_command = plci->internal_command;
12731 plci->internal_command = 0;
12732 switch (plci->ec_cmd)
12734 case EC_ENABLE_OPERATION:
12735 case EC_FREEZE_COEFFICIENTS:
12736 case EC_RESUME_COEFFICIENT_UPDATE:
12737 case EC_RESET_COEFFICIENTS:
12738 switch (internal_command)
12740 default:
12741 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12742 B1_FACILITY_EC), EC_COMMAND_1);
12743 case EC_COMMAND_1:
12744 if (adjust_b_process (Id, plci, Rc) != GOOD)
12746 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12747 UnMapId (Id), (char *)(FILE_), __LINE__));
12748 Info = _FACILITY_NOT_SUPPORTED;
12749 break;
12751 if (plci->internal_command)
12752 return;
12753 case EC_COMMAND_2:
12754 if (plci->sig_req)
12756 plci->internal_command = EC_COMMAND_2;
12757 return;
12759 plci->internal_command = EC_COMMAND_3;
12760 ec_write_parameters (plci);
12761 return;
12762 case EC_COMMAND_3:
12763 if ((Rc != OK) && (Rc != OK_FC))
12765 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12766 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12767 Info = _FACILITY_NOT_SUPPORTED;
12768 break;
12770 break;
12772 break;
12774 case EC_DISABLE_OPERATION:
12775 switch (internal_command)
12777 default:
12778 case EC_COMMAND_1:
12779 if (plci->B1_facilities & B1_FACILITY_EC)
12781 if (plci->sig_req)
12783 plci->internal_command = EC_COMMAND_1;
12784 return;
12786 plci->internal_command = EC_COMMAND_2;
12787 ec_write_parameters (plci);
12788 return;
12790 Rc = OK;
12791 case EC_COMMAND_2:
12792 if ((Rc != OK) && (Rc != OK_FC))
12794 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12795 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12796 Info = _FACILITY_NOT_SUPPORTED;
12797 break;
12799 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12800 ~B1_FACILITY_EC), EC_COMMAND_3);
12801 case EC_COMMAND_3:
12802 if (adjust_b_process (Id, plci, Rc) != GOOD)
12804 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12805 UnMapId (Id), (char *)(FILE_), __LINE__));
12806 Info = _FACILITY_NOT_SUPPORTED;
12807 break;
12809 if (plci->internal_command)
12810 return;
12811 break;
12813 break;
12815 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12816 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12817 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12821 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12823 word Info;
12824 word opt;
12825 API_PARSE ec_parms[3];
12826 byte result[16];
12828 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12829 UnMapId (Id), (char *)(FILE_), __LINE__));
12831 Info = GOOD;
12832 result[0] = 0;
12833 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12835 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12836 UnMapId (Id), (char *)(FILE_), __LINE__));
12837 Info = _FACILITY_NOT_SUPPORTED;
12839 else
12841 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12843 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12845 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12846 UnMapId (Id), (char *)(FILE_), __LINE__));
12847 Info = _WRONG_MESSAGE_FORMAT;
12849 else
12851 if (plci == NULL)
12853 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12854 UnMapId (Id), (char *)(FILE_), __LINE__));
12855 Info = _WRONG_IDENTIFIER;
12857 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12859 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12860 UnMapId (Id), (char *)(FILE_), __LINE__));
12861 Info = _WRONG_STATE;
12863 else
12865 plci->command = 0;
12866 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12867 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12868 result[0] = 2;
12869 PUT_WORD (&result[1], EC_SUCCESS);
12870 if (msg[1].length >= 4)
12872 opt = GET_WORD (&ec_parms[0].info[2]);
12873 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12874 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12875 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12876 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12877 if (opt & EC_DETECT_DISABLE_TONE)
12878 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12879 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12880 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12881 if (msg[1].length >= 6)
12883 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12886 switch (plci->ec_cmd)
12888 case EC_ENABLE_OPERATION:
12889 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12890 start_internal_command (Id, plci, ec_command);
12891 return (false);
12893 case EC_DISABLE_OPERATION:
12894 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12895 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12896 LEC_RESET_COEFFICIENTS;
12897 start_internal_command (Id, plci, ec_command);
12898 return (false);
12900 case EC_FREEZE_COEFFICIENTS:
12901 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12902 start_internal_command (Id, plci, ec_command);
12903 return (false);
12905 case EC_RESUME_COEFFICIENT_UPDATE:
12906 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12907 start_internal_command (Id, plci, ec_command);
12908 return (false);
12910 case EC_RESET_COEFFICIENTS:
12911 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12912 start_internal_command (Id, plci, ec_command);
12913 return (false);
12915 default:
12916 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12917 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12918 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12923 else
12925 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12927 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12928 UnMapId (Id), (char *)(FILE_), __LINE__));
12929 Info = _WRONG_MESSAGE_FORMAT;
12931 else
12933 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12935 result[0] = 11;
12936 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12937 result[3] = 8;
12938 PUT_WORD (&result[4], GOOD);
12939 PUT_WORD (&result[6], 0x0007);
12940 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12941 PUT_WORD (&result[10], 0);
12943 else if (plci == NULL)
12945 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12946 UnMapId (Id), (char *)(FILE_), __LINE__));
12947 Info = _WRONG_IDENTIFIER;
12949 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12951 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12952 UnMapId (Id), (char *)(FILE_), __LINE__));
12953 Info = _WRONG_STATE;
12955 else
12957 plci->command = 0;
12958 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12959 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12960 result[0] = 5;
12961 PUT_WORD (&result[1], plci->ec_cmd);
12962 result[3] = 2;
12963 PUT_WORD (&result[4], GOOD);
12964 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12965 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12966 plci->ec_tail_length = 0;
12967 if (ec_parms[1].length >= 2)
12969 opt = GET_WORD (&ec_parms[1].info[1]);
12970 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12971 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12972 if (opt & EC_DETECT_DISABLE_TONE)
12973 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12974 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12975 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12976 if (ec_parms[1].length >= 4)
12978 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12981 switch (plci->ec_cmd)
12983 case EC_ENABLE_OPERATION:
12984 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12985 start_internal_command (Id, plci, ec_command);
12986 return (false);
12988 case EC_DISABLE_OPERATION:
12989 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12990 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12991 LEC_RESET_COEFFICIENTS;
12992 start_internal_command (Id, plci, ec_command);
12993 return (false);
12995 default:
12996 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12997 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12998 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13004 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13005 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13006 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13007 return (false);
13011 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13013 byte result[8];
13015 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13016 UnMapId (Id), (char *)(FILE_), __LINE__));
13018 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13020 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13022 result[0] = 2;
13023 PUT_WORD (&result[1], 0);
13024 switch (msg[1])
13026 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13027 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13028 break;
13029 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13030 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13031 break;
13032 case LEC_DISABLE_RELEASED:
13033 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13034 break;
13037 else
13039 result[0] = 5;
13040 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13041 result[3] = 2;
13042 PUT_WORD (&result[4], 0);
13043 switch (msg[1])
13045 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13046 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13047 break;
13048 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13049 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13050 break;
13051 case LEC_DISABLE_RELEASED:
13052 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13053 break;
13056 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13057 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13063 /*------------------------------------------------------------------*/
13064 /* Advanced voice */
13065 /*------------------------------------------------------------------*/
13067 static void adv_voice_write_coefs (PLCI *plci, word write_command)
13069 DIVA_CAPI_ADAPTER *a;
13070 word i;
13071 byte *p;
13073 word w, n, j, k;
13074 byte ch_map[MIXER_CHANNELS_BRI];
13076 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13078 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13079 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13080 (char *)(FILE_), __LINE__, write_command));
13082 a = plci->adapter;
13083 p = coef_buffer + 1;
13084 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13085 i = 0;
13086 while (i + sizeof(word) <= a->adv_voice_coef_length)
13088 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13089 p += 2;
13090 i += 2;
13092 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13094 PUT_WORD (p, 0x8000);
13095 p += 2;
13096 i += 2;
13099 if (!a->li_pri && (plci->li_bchannel_id == 0))
13101 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13103 plci->li_bchannel_id = 1;
13104 li_config_table[a->li_base].plci = plci;
13105 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13106 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13107 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13109 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13111 plci->li_bchannel_id = 2;
13112 li_config_table[a->li_base + 1].plci = plci;
13113 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13114 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13115 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13118 if (!a->li_pri && (plci->li_bchannel_id != 0)
13119 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121 i = a->li_base + (plci->li_bchannel_id - 1);
13122 switch (write_command)
13124 case ADV_VOICE_WRITE_ACTIVATION:
13125 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13126 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13127 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13129 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13132 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13134 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13135 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13136 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13137 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13139 mixer_calculate_coefs (a);
13140 li_config_table[i].curchnl = li_config_table[i].channel;
13141 li_config_table[j].curchnl = li_config_table[j].channel;
13142 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13143 li_config_table[k].curchnl = li_config_table[k].channel;
13144 break;
13146 case ADV_VOICE_WRITE_DEACTIVATION:
13147 for (j = 0; j < li_total_channels; j++)
13149 li_config_table[i].flag_table[j] = 0;
13150 li_config_table[j].flag_table[i] = 0;
13152 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13153 for (j = 0; j < li_total_channels; j++)
13155 li_config_table[k].flag_table[j] = 0;
13156 li_config_table[j].flag_table[k] = 0;
13158 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13160 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13161 for (j = 0; j < li_total_channels; j++)
13163 li_config_table[k].flag_table[j] = 0;
13164 li_config_table[j].flag_table[k] = 0;
13167 mixer_calculate_coefs (a);
13168 break;
13170 if (plci->B1_facilities & B1_FACILITY_MIXER)
13172 w = 0;
13173 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13174 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13175 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13176 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13177 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13178 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13179 *(p++) = (byte) w;
13180 *(p++) = (byte)(w >> 8);
13181 for (j = 0; j < sizeof(ch_map); j += 2)
13183 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13184 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13186 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13188 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13189 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13190 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13192 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13193 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13194 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13196 else
13198 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13199 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13203 else
13205 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206 *(p++) = a->adv_voice_coef_buffer[i];
13209 else
13212 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213 *(p++) = a->adv_voice_coef_buffer[i];
13215 coef_buffer[0] = (p - coef_buffer) - 1;
13216 add_p (plci, FTY, coef_buffer);
13217 sig_req (plci, TEL_CTRL, 0);
13218 send_req (plci);
13222 static void adv_voice_clear_config (PLCI *plci)
13224 DIVA_CAPI_ADAPTER *a;
13226 word i, j;
13229 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13230 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13231 (char *)(FILE_), __LINE__));
13233 a = plci->adapter;
13234 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13236 a->adv_voice_coef_length = 0;
13238 if (!a->li_pri && (plci->li_bchannel_id != 0)
13239 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13241 i = a->li_base + (plci->li_bchannel_id - 1);
13242 li_config_table[i].curchnl = 0;
13243 li_config_table[i].channel = 0;
13244 li_config_table[i].chflags = 0;
13245 for (j = 0; j < li_total_channels; j++)
13247 li_config_table[i].flag_table[j] = 0;
13248 li_config_table[j].flag_table[i] = 0;
13249 li_config_table[i].coef_table[j] = 0;
13250 li_config_table[j].coef_table[i] = 0;
13252 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13253 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13254 li_config_table[i].curchnl = 0;
13255 li_config_table[i].channel = 0;
13256 li_config_table[i].chflags = 0;
13257 for (j = 0; j < li_total_channels; j++)
13259 li_config_table[i].flag_table[j] = 0;
13260 li_config_table[j].flag_table[i] = 0;
13261 li_config_table[i].coef_table[j] = 0;
13262 li_config_table[j].coef_table[i] = 0;
13264 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13266 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13267 li_config_table[i].curchnl = 0;
13268 li_config_table[i].channel = 0;
13269 li_config_table[i].chflags = 0;
13270 for (j = 0; j < li_total_channels; j++)
13272 li_config_table[i].flag_table[j] = 0;
13273 li_config_table[j].flag_table[i] = 0;
13274 li_config_table[i].coef_table[j] = 0;
13275 li_config_table[j].coef_table[i] = 0;
13284 static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13287 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13288 UnMapId (Id), (char *)(FILE_), __LINE__));
13293 static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13296 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13297 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13299 return (GOOD);
13303 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13305 DIVA_CAPI_ADAPTER *a;
13306 word Info;
13308 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13309 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13311 Info = GOOD;
13312 a = plci->adapter;
13313 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13314 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13316 switch (plci->adjust_b_state)
13318 case ADJUST_B_RESTORE_VOICE_1:
13319 plci->internal_command = plci->adjust_b_command;
13320 if (plci->sig_req)
13322 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13323 break;
13325 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13326 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13327 break;
13328 case ADJUST_B_RESTORE_VOICE_2:
13329 if ((Rc != OK) && (Rc != OK_FC))
13331 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13332 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13333 Info = _WRONG_STATE;
13334 break;
13336 break;
13339 return (Info);
13345 /*------------------------------------------------------------------*/
13346 /* B1 resource switching */
13347 /*------------------------------------------------------------------*/
13349 static byte b1_facilities_table[] =
13351 0x00, /* 0 No bchannel resources */
13352 0x00, /* 1 Codec (automatic law) */
13353 0x00, /* 2 Codec (A-law) */
13354 0x00, /* 3 Codec (y-law) */
13355 0x00, /* 4 HDLC for X.21 */
13356 0x00, /* 5 HDLC */
13357 0x00, /* 6 External Device 0 */
13358 0x00, /* 7 External Device 1 */
13359 0x00, /* 8 HDLC 56k */
13360 0x00, /* 9 Transparent */
13361 0x00, /* 10 Loopback to network */
13362 0x00, /* 11 Test pattern to net */
13363 0x00, /* 12 Rate adaptation sync */
13364 0x00, /* 13 Rate adaptation async */
13365 0x00, /* 14 R-Interface */
13366 0x00, /* 15 HDLC 128k leased line */
13367 0x00, /* 16 FAX */
13368 0x00, /* 17 Modem async */
13369 0x00, /* 18 Modem sync HDLC */
13370 0x00, /* 19 V.110 async HDLC */
13371 0x12, /* 20 Adv voice (Trans,mixer) */
13372 0x00, /* 21 Codec connected to IC */
13373 0x0c, /* 22 Trans,DTMF */
13374 0x1e, /* 23 Trans,DTMF+mixer */
13375 0x1f, /* 24 Trans,DTMF+mixer+local */
13376 0x13, /* 25 Trans,mixer+local */
13377 0x12, /* 26 HDLC,mixer */
13378 0x12, /* 27 HDLC 56k,mixer */
13379 0x2c, /* 28 Trans,LEC+DTMF */
13380 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13381 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13382 0x2c, /* 31 RTP,LEC+DTMF */
13383 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13384 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13385 0x00, /* 34 Signaling task */
13386 0x00, /* 35 PIAFS */
13387 0x0c, /* 36 Trans,DTMF+TONE */
13388 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13389 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13393 static word get_b1_facilities (PLCI * plci, byte b1_resource)
13395 word b1_facilities;
13397 b1_facilities = b1_facilities_table[b1_resource];
13398 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13401 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13402 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13405 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13406 b1_facilities |= B1_FACILITY_DTMFX;
13407 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13408 b1_facilities |= B1_FACILITY_DTMFR;
13411 if ((b1_resource == 17) || (b1_resource == 18))
13413 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13414 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13417 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13418 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13419 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13421 return (b1_facilities);
13425 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13427 byte b;
13429 switch (b1_resource)
13431 case 5:
13432 case 26:
13433 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13434 b = 26;
13435 else
13436 b = 5;
13437 break;
13439 case 8:
13440 case 27:
13441 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13442 b = 27;
13443 else
13444 b = 8;
13445 break;
13447 case 9:
13448 case 20:
13449 case 22:
13450 case 23:
13451 case 24:
13452 case 25:
13453 case 28:
13454 case 29:
13455 case 30:
13456 case 36:
13457 case 37:
13458 case 38:
13459 if (b1_facilities & B1_FACILITY_EC)
13461 if (b1_facilities & B1_FACILITY_LOCAL)
13462 b = 30;
13463 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13464 b = 29;
13465 else
13466 b = 28;
13469 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13470 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13471 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13473 if (b1_facilities & B1_FACILITY_LOCAL)
13474 b = 38;
13475 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13476 b = 37;
13477 else
13478 b = 36;
13481 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13482 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13483 || ((b1_facilities & B1_FACILITY_DTMFR)
13484 && ((b1_facilities & B1_FACILITY_MIXER)
13485 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13486 || ((b1_facilities & B1_FACILITY_DTMFX)
13487 && ((b1_facilities & B1_FACILITY_MIXER)
13488 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13490 if (b1_facilities & B1_FACILITY_LOCAL)
13491 b = 24;
13492 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13493 b = 23;
13494 else
13495 b = 22;
13497 else
13499 if (b1_facilities & B1_FACILITY_LOCAL)
13500 b = 25;
13501 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13502 b = 20;
13503 else
13504 b = 9;
13506 break;
13508 case 31:
13509 case 32:
13510 case 33:
13511 if (b1_facilities & B1_FACILITY_LOCAL)
13512 b = 33;
13513 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13514 b = 32;
13515 else
13516 b = 31;
13517 break;
13519 default:
13520 b = b1_resource;
13522 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13523 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13524 (char *)(FILE_), __LINE__,
13525 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13526 return (b);
13530 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13532 word removed_facilities;
13534 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13535 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13536 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13537 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13539 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13540 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13542 if (removed_facilities & B1_FACILITY_EC)
13543 ec_clear_config (plci);
13546 if (removed_facilities & B1_FACILITY_DTMFR)
13548 dtmf_rec_clear_config (plci);
13549 dtmf_parameter_clear_config (plci);
13551 if (removed_facilities & B1_FACILITY_DTMFX)
13552 dtmf_send_clear_config (plci);
13555 if (removed_facilities & B1_FACILITY_MIXER)
13556 mixer_clear_config (plci);
13558 if (removed_facilities & B1_FACILITY_VOICE)
13559 adv_voice_clear_config (plci);
13560 plci->B1_facilities = new_b1_facilities;
13564 static void adjust_b_clear (PLCI *plci)
13567 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13568 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13569 (char *)(FILE_), __LINE__));
13571 plci->adjust_b_restore = false;
13575 static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13577 word Info;
13578 byte b1_resource;
13579 NCCI * ncci_ptr;
13580 API_PARSE bp[2];
13582 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13583 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13585 Info = GOOD;
13586 switch (plci->adjust_b_state)
13588 case ADJUST_B_START:
13589 if ((plci->adjust_b_parms_msg == NULL)
13590 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13591 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13592 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13594 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13595 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13596 if (b1_resource == plci->B1_resource)
13598 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13599 break;
13601 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13603 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13604 UnMapId (Id), (char *)(FILE_), __LINE__,
13605 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13606 Info = _WRONG_STATE;
13607 break;
13610 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13613 mixer_prepare_switch (Id, plci);
13616 dtmf_prepare_switch (Id, plci);
13617 dtmf_parameter_prepare_switch (Id, plci);
13620 ec_prepare_switch (Id, plci);
13622 adv_voice_prepare_switch (Id, plci);
13624 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13625 Rc = OK;
13626 case ADJUST_B_SAVE_MIXER_1:
13627 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13630 Info = mixer_save_config (Id, plci, Rc);
13631 if ((Info != GOOD) || plci->internal_command)
13632 break;
13635 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13636 Rc = OK;
13637 case ADJUST_B_SAVE_DTMF_1:
13638 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13641 Info = dtmf_save_config (Id, plci, Rc);
13642 if ((Info != GOOD) || plci->internal_command)
13643 break;
13646 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13647 case ADJUST_B_REMOVE_L23_1:
13648 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13649 && plci->NL.Id && !plci->nl_remove_id)
13651 plci->internal_command = plci->adjust_b_command;
13652 if (plci->adjust_b_ncci != 0)
13654 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13655 while (ncci_ptr->data_pending)
13657 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13658 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13660 while (ncci_ptr->data_ack_pending)
13661 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13663 nl_req_ncci (plci, REMOVE,
13664 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13665 send_req (plci);
13666 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13667 break;
13669 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13670 Rc = OK;
13671 case ADJUST_B_REMOVE_L23_2:
13672 if ((Rc != OK) && (Rc != OK_FC))
13674 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13675 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13676 Info = _WRONG_STATE;
13677 break;
13679 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13681 if (plci_nl_busy (plci))
13683 plci->internal_command = plci->adjust_b_command;
13684 break;
13687 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13688 Rc = OK;
13689 case ADJUST_B_SAVE_EC_1:
13690 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13693 Info = ec_save_config (Id, plci, Rc);
13694 if ((Info != GOOD) || plci->internal_command)
13695 break;
13698 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13699 Rc = OK;
13700 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13701 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13704 Info = dtmf_parameter_save_config (Id, plci, Rc);
13705 if ((Info != GOOD) || plci->internal_command)
13706 break;
13709 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13710 Rc = OK;
13711 case ADJUST_B_SAVE_VOICE_1:
13712 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13714 Info = adv_voice_save_config (Id, plci, Rc);
13715 if ((Info != GOOD) || plci->internal_command)
13716 break;
13718 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13719 case ADJUST_B_SWITCH_L1_1:
13720 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13722 if (plci->sig_req)
13724 plci->internal_command = plci->adjust_b_command;
13725 break;
13727 if (plci->adjust_b_parms_msg != NULL)
13728 api_load_msg (plci->adjust_b_parms_msg, bp);
13729 else
13730 api_load_msg (&plci->B_protocol, bp);
13731 Info = add_b1 (plci, bp,
13732 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13733 plci->adjust_b_facilities);
13734 if (Info != GOOD)
13736 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13737 UnMapId (Id), (char *)(FILE_), __LINE__,
13738 plci->B1_resource, plci->adjust_b_facilities));
13739 break;
13741 plci->internal_command = plci->adjust_b_command;
13742 sig_req (plci, RESOURCES, 0);
13743 send_req (plci);
13744 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13745 break;
13747 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13748 Rc = OK;
13749 case ADJUST_B_SWITCH_L1_2:
13750 if ((Rc != OK) && (Rc != OK_FC))
13752 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13753 UnMapId (Id), (char *)(FILE_), __LINE__,
13754 Rc, plci->B1_resource, plci->adjust_b_facilities));
13755 Info = _WRONG_STATE;
13756 break;
13758 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13759 Rc = OK;
13760 case ADJUST_B_RESTORE_VOICE_1:
13761 case ADJUST_B_RESTORE_VOICE_2:
13762 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13764 Info = adv_voice_restore_config (Id, plci, Rc);
13765 if ((Info != GOOD) || plci->internal_command)
13766 break;
13768 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13769 Rc = OK;
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13771 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13772 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13775 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13776 if ((Info != GOOD) || plci->internal_command)
13777 break;
13780 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13781 Rc = OK;
13782 case ADJUST_B_RESTORE_EC_1:
13783 case ADJUST_B_RESTORE_EC_2:
13784 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13787 Info = ec_restore_config (Id, plci, Rc);
13788 if ((Info != GOOD) || plci->internal_command)
13789 break;
13792 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13793 case ADJUST_B_ASSIGN_L23_1:
13794 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13796 if (plci_nl_busy (plci))
13798 plci->internal_command = plci->adjust_b_command;
13799 break;
13801 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13802 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13803 if (plci->adjust_b_parms_msg != NULL)
13804 api_load_msg (plci->adjust_b_parms_msg, bp);
13805 else
13806 api_load_msg (&plci->B_protocol, bp);
13807 Info = add_b23 (plci, bp);
13808 if (Info != GOOD)
13810 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13811 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13812 break;
13814 plci->internal_command = plci->adjust_b_command;
13815 nl_req_ncci (plci, ASSIGN, 0);
13816 send_req (plci);
13817 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13818 break;
13820 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13821 Rc = ASSIGN_OK;
13822 case ADJUST_B_ASSIGN_L23_2:
13823 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13825 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13826 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13827 Info = _WRONG_STATE;
13828 break;
13830 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13832 if (Rc != ASSIGN_OK)
13834 plci->internal_command = plci->adjust_b_command;
13835 break;
13838 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13840 plci->adjust_b_restore = true;
13841 break;
13843 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13844 case ADJUST_B_CONNECT_1:
13845 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13847 plci->internal_command = plci->adjust_b_command;
13848 if (plci_nl_busy (plci))
13849 break;
13850 nl_req_ncci (plci, N_CONNECT, 0);
13851 send_req (plci);
13852 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13853 break;
13855 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13856 Rc = OK;
13857 case ADJUST_B_CONNECT_2:
13858 case ADJUST_B_CONNECT_3:
13859 case ADJUST_B_CONNECT_4:
13860 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13862 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13863 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13864 Info = _WRONG_STATE;
13865 break;
13867 if (Rc == OK)
13869 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13871 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13872 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13874 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13876 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13877 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13879 else if (Rc == 0)
13881 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13883 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13884 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13886 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13888 plci->internal_command = plci->adjust_b_command;
13889 break;
13891 Rc = OK;
13892 case ADJUST_B_RESTORE_DTMF_1:
13893 case ADJUST_B_RESTORE_DTMF_2:
13894 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13897 Info = dtmf_restore_config (Id, plci, Rc);
13898 if ((Info != GOOD) || plci->internal_command)
13899 break;
13902 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13903 Rc = OK;
13904 case ADJUST_B_RESTORE_MIXER_1:
13905 case ADJUST_B_RESTORE_MIXER_2:
13906 case ADJUST_B_RESTORE_MIXER_3:
13907 case ADJUST_B_RESTORE_MIXER_4:
13908 case ADJUST_B_RESTORE_MIXER_5:
13909 case ADJUST_B_RESTORE_MIXER_6:
13910 case ADJUST_B_RESTORE_MIXER_7:
13911 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13914 Info = mixer_restore_config (Id, plci, Rc);
13915 if ((Info != GOOD) || plci->internal_command)
13916 break;
13919 plci->adjust_b_state = ADJUST_B_END;
13920 case ADJUST_B_END:
13921 break;
13923 return (Info);
13927 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13930 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13931 UnMapId (Id), (char *)(FILE_), __LINE__,
13932 plci->B1_resource, b1_facilities));
13934 plci->adjust_b_parms_msg = bp_msg;
13935 plci->adjust_b_facilities = b1_facilities;
13936 plci->adjust_b_command = internal_command;
13937 plci->adjust_b_ncci = (word)(Id >> 16);
13938 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13939 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13940 else
13941 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13942 plci->adjust_b_state = ADJUST_B_START;
13943 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13944 UnMapId (Id), (char *)(FILE_), __LINE__,
13945 plci->B1_resource, b1_facilities));
13949 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13951 word internal_command;
13953 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13954 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13956 internal_command = plci->internal_command;
13957 plci->internal_command = 0;
13958 switch (internal_command)
13960 default:
13961 plci->command = 0;
13962 if (plci->req_in != 0)
13964 plci->internal_command = ADJUST_B_RESTORE_1;
13965 break;
13967 Rc = OK;
13968 case ADJUST_B_RESTORE_1:
13969 if ((Rc != OK) && (Rc != OK_FC))
13971 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13972 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13974 plci->adjust_b_parms_msg = NULL;
13975 plci->adjust_b_facilities = plci->B1_facilities;
13976 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13977 plci->adjust_b_ncci = (word)(Id >> 16);
13978 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13979 plci->adjust_b_state = ADJUST_B_START;
13980 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13981 UnMapId (Id), (char *)(FILE_), __LINE__));
13982 case ADJUST_B_RESTORE_2:
13983 if (adjust_b_process (Id, plci, Rc) != GOOD)
13985 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13986 UnMapId (Id), (char *)(FILE_), __LINE__));
13988 if (plci->internal_command)
13989 break;
13990 break;
13995 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13997 word Info;
13998 word internal_command;
14000 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14001 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14003 Info = GOOD;
14004 internal_command = plci->internal_command;
14005 plci->internal_command = 0;
14006 switch (internal_command)
14008 default:
14009 plci->command = 0;
14010 plci->adjust_b_parms_msg = NULL;
14011 plci->adjust_b_facilities = plci->B1_facilities;
14012 plci->adjust_b_command = RESET_B3_COMMAND_1;
14013 plci->adjust_b_ncci = (word)(Id >> 16);
14014 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14015 plci->adjust_b_state = ADJUST_B_START;
14016 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14017 UnMapId (Id), (char *)(FILE_), __LINE__));
14018 case RESET_B3_COMMAND_1:
14019 Info = adjust_b_process (Id, plci, Rc);
14020 if (Info != GOOD)
14022 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14023 UnMapId (Id), (char *)(FILE_), __LINE__));
14024 break;
14026 if (plci->internal_command)
14027 return;
14028 break;
14030 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14031 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14035 static void select_b_command (dword Id, PLCI *plci, byte Rc)
14037 word Info;
14038 word internal_command;
14039 byte esc_chi[3];
14041 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14042 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14044 Info = GOOD;
14045 internal_command = plci->internal_command;
14046 plci->internal_command = 0;
14047 switch (internal_command)
14049 default:
14050 plci->command = 0;
14051 plci->adjust_b_parms_msg = &plci->saved_msg;
14052 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14053 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14054 else
14055 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14056 plci->adjust_b_command = SELECT_B_COMMAND_1;
14057 plci->adjust_b_ncci = (word)(Id >> 16);
14058 if (plci->saved_msg.parms[0].length == 0)
14060 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061 ADJUST_B_MODE_NO_RESOURCE;
14063 else
14065 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14066 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14068 plci->adjust_b_state = ADJUST_B_START;
14069 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14070 UnMapId (Id), (char *)(FILE_), __LINE__));
14071 case SELECT_B_COMMAND_1:
14072 Info = adjust_b_process (Id, plci, Rc);
14073 if (Info != GOOD)
14075 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14076 UnMapId (Id), (char *)(FILE_), __LINE__));
14077 break;
14079 if (plci->internal_command)
14080 return;
14081 if (plci->tel == ADV_VOICE)
14083 esc_chi[0] = 0x02;
14084 esc_chi[1] = 0x18;
14085 esc_chi[2] = plci->b_channel;
14086 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14088 break;
14090 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14094 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14096 word Info;
14097 word internal_command;
14099 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14100 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14102 Info = GOOD;
14103 internal_command = plci->internal_command;
14104 plci->internal_command = 0;
14105 switch (internal_command)
14107 default:
14108 plci->command = 0;
14109 case FAX_CONNECT_ACK_COMMAND_1:
14110 if (plci_nl_busy (plci))
14112 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14113 return;
14115 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14116 plci->NData[0].P = plci->fax_connect_info_buffer;
14117 plci->NData[0].PLength = plci->fax_connect_info_length;
14118 plci->NL.X = plci->NData;
14119 plci->NL.ReqCh = 0;
14120 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14121 plci->adapter->request (&plci->NL);
14122 return;
14123 case FAX_CONNECT_ACK_COMMAND_2:
14124 if ((Rc != OK) && (Rc != OK_FC))
14126 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14127 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14128 break;
14131 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14132 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14134 if (plci->B3_prot == 4)
14135 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14136 else
14137 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14138 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14143 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14145 word Info;
14146 word internal_command;
14148 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14149 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14151 Info = GOOD;
14152 internal_command = plci->internal_command;
14153 plci->internal_command = 0;
14154 switch (internal_command)
14156 default:
14157 plci->command = 0;
14158 case FAX_EDATA_ACK_COMMAND_1:
14159 if (plci_nl_busy (plci))
14161 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14162 return;
14164 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14165 plci->NData[0].P = plci->fax_connect_info_buffer;
14166 plci->NData[0].PLength = plci->fax_edata_ack_length;
14167 plci->NL.X = plci->NData;
14168 plci->NL.ReqCh = 0;
14169 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14170 plci->adapter->request (&plci->NL);
14171 return;
14172 case FAX_EDATA_ACK_COMMAND_2:
14173 if ((Rc != OK) && (Rc != OK_FC))
14175 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14176 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14177 break;
14183 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14185 word Info;
14186 word internal_command;
14188 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14189 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14191 Info = GOOD;
14192 internal_command = plci->internal_command;
14193 plci->internal_command = 0;
14194 switch (internal_command)
14196 default:
14197 plci->command = 0;
14198 case FAX_CONNECT_INFO_COMMAND_1:
14199 if (plci_nl_busy (plci))
14201 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14202 return;
14204 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14205 plci->NData[0].P = plci->fax_connect_info_buffer;
14206 plci->NData[0].PLength = plci->fax_connect_info_length;
14207 plci->NL.X = plci->NData;
14208 plci->NL.ReqCh = 0;
14209 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14210 plci->adapter->request (&plci->NL);
14211 return;
14212 case FAX_CONNECT_INFO_COMMAND_2:
14213 if ((Rc != OK) && (Rc != OK_FC))
14215 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14216 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14217 Info = _WRONG_STATE;
14218 break;
14220 if (plci_nl_busy (plci))
14222 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14223 return;
14225 plci->command = _CONNECT_B3_R;
14226 nl_req_ncci (plci, N_CONNECT, 0);
14227 send_req (plci);
14228 return;
14230 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14234 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14236 word Info;
14237 word internal_command;
14239 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14240 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14242 Info = GOOD;
14243 internal_command = plci->internal_command;
14244 plci->internal_command = 0;
14245 switch (internal_command)
14247 default:
14248 plci->command = 0;
14249 plci->adjust_b_parms_msg = NULL;
14250 plci->adjust_b_facilities = plci->B1_facilities;
14251 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14252 plci->adjust_b_ncci = (word)(Id >> 16);
14253 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14254 plci->adjust_b_state = ADJUST_B_START;
14255 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14256 UnMapId (Id), (char *)(FILE_), __LINE__));
14257 case FAX_ADJUST_B23_COMMAND_1:
14258 Info = adjust_b_process (Id, plci, Rc);
14259 if (Info != GOOD)
14261 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14262 UnMapId (Id), (char *)(FILE_), __LINE__));
14263 break;
14265 if (plci->internal_command)
14266 return;
14267 case FAX_ADJUST_B23_COMMAND_2:
14268 if (plci_nl_busy (plci))
14270 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14271 return;
14273 plci->command = _CONNECT_B3_R;
14274 nl_req_ncci (plci, N_CONNECT, 0);
14275 send_req (plci);
14276 return;
14278 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14282 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14284 word internal_command;
14286 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14287 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14289 internal_command = plci->internal_command;
14290 plci->internal_command = 0;
14291 switch (internal_command)
14293 default:
14294 plci->command = 0;
14295 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14296 return;
14297 case FAX_DISCONNECT_COMMAND_1:
14298 case FAX_DISCONNECT_COMMAND_2:
14299 case FAX_DISCONNECT_COMMAND_3:
14300 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14302 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14303 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14304 break;
14306 if (Rc == OK)
14308 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14309 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14311 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14314 else if (Rc == 0)
14316 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14317 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14319 return;
14325 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14327 word Info;
14328 word internal_command;
14330 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14331 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14333 Info = GOOD;
14334 internal_command = plci->internal_command;
14335 plci->internal_command = 0;
14336 switch (internal_command)
14338 default:
14339 plci->command = 0;
14340 case RTP_CONNECT_B3_REQ_COMMAND_1:
14341 if (plci_nl_busy (plci))
14343 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14344 return;
14346 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14347 nl_req_ncci (plci, N_CONNECT, 0);
14348 send_req (plci);
14349 return;
14350 case RTP_CONNECT_B3_REQ_COMMAND_2:
14351 if ((Rc != OK) && (Rc != OK_FC))
14353 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14354 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14355 Info = _WRONG_STATE;
14356 break;
14358 if (plci_nl_busy (plci))
14360 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14361 return;
14363 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14364 plci->NData[0].PLength = plci->internal_req_buffer[0];
14365 plci->NData[0].P = plci->internal_req_buffer + 1;
14366 plci->NL.X = plci->NData;
14367 plci->NL.ReqCh = 0;
14368 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14369 plci->adapter->request (&plci->NL);
14370 break;
14371 case RTP_CONNECT_B3_REQ_COMMAND_3:
14372 return;
14374 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14378 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14380 word Info;
14381 word internal_command;
14383 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14384 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14386 Info = GOOD;
14387 internal_command = plci->internal_command;
14388 plci->internal_command = 0;
14389 switch (internal_command)
14391 default:
14392 plci->command = 0;
14393 case RTP_CONNECT_B3_RES_COMMAND_1:
14394 if (plci_nl_busy (plci))
14396 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14397 return;
14399 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14400 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14401 send_req (plci);
14402 return;
14403 case RTP_CONNECT_B3_RES_COMMAND_2:
14404 if ((Rc != OK) && (Rc != OK_FC))
14406 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14407 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14408 Info = _WRONG_STATE;
14409 break;
14411 if (plci_nl_busy (plci))
14413 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14414 return;
14416 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14417 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14418 plci->NData[0].PLength = plci->internal_req_buffer[0];
14419 plci->NData[0].P = plci->internal_req_buffer + 1;
14420 plci->NL.X = plci->NData;
14421 plci->NL.ReqCh = 0;
14422 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14423 plci->adapter->request (&plci->NL);
14424 return;
14425 case RTP_CONNECT_B3_RES_COMMAND_3:
14426 return;
14432 static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14434 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14435 word Info;
14436 word internal_command;
14438 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14439 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14441 Info = GOOD;
14442 internal_command = plci->internal_command;
14443 plci->internal_command = 0;
14444 switch (internal_command)
14446 default:
14447 if (!plci->NL.Id)
14448 break;
14449 plci->command = 0;
14450 plci->adjust_b_parms_msg = NULL;
14451 plci->adjust_b_facilities = plci->B1_facilities;
14452 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14453 plci->adjust_b_ncci = (word)(Id >> 16);
14454 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14455 plci->adjust_b_state = ADJUST_B_START;
14456 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14457 UnMapId (Id), (char *)(FILE_), __LINE__));
14458 case HOLD_SAVE_COMMAND_1:
14459 Info = adjust_b_process (Id, plci, Rc);
14460 if (Info != GOOD)
14462 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14463 UnMapId (Id), (char *)(FILE_), __LINE__));
14464 break;
14466 if (plci->internal_command)
14467 return;
14469 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14473 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14475 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14476 word Info;
14477 word internal_command;
14479 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14480 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14482 Info = GOOD;
14483 internal_command = plci->internal_command;
14484 plci->internal_command = 0;
14485 switch (internal_command)
14487 default:
14488 plci->command = 0;
14489 plci->adjust_b_parms_msg = NULL;
14490 plci->adjust_b_facilities = plci->B1_facilities;
14491 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14492 plci->adjust_b_ncci = (word)(Id >> 16);
14493 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14494 plci->adjust_b_state = ADJUST_B_START;
14495 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14496 UnMapId (Id), (char *)(FILE_), __LINE__));
14497 case RETRIEVE_RESTORE_COMMAND_1:
14498 Info = adjust_b_process (Id, plci, Rc);
14499 if (Info != GOOD)
14501 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14502 UnMapId (Id), (char *)(FILE_), __LINE__));
14503 break;
14505 if (plci->internal_command)
14506 return;
14508 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14512 static void init_b1_config (PLCI *plci)
14515 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14516 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14517 (char *)(FILE_), __LINE__));
14519 plci->B1_resource = 0;
14520 plci->B1_facilities = 0;
14522 plci->li_bchannel_id = 0;
14523 mixer_clear_config (plci);
14526 ec_clear_config (plci);
14529 dtmf_rec_clear_config (plci);
14530 dtmf_send_clear_config (plci);
14531 dtmf_parameter_clear_config (plci);
14533 adv_voice_clear_config (plci);
14534 adjust_b_clear (plci);
14538 static void clear_b1_config (PLCI *plci)
14541 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14542 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14543 (char *)(FILE_), __LINE__));
14545 adv_voice_clear_config (plci);
14546 adjust_b_clear (plci);
14548 ec_clear_config (plci);
14551 dtmf_rec_clear_config (plci);
14552 dtmf_send_clear_config (plci);
14553 dtmf_parameter_clear_config (plci);
14556 if ((plci->li_bchannel_id != 0)
14557 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14559 mixer_clear_config (plci);
14560 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14561 plci->li_bchannel_id = 0;
14564 plci->B1_resource = 0;
14565 plci->B1_facilities = 0;
14569 /* -----------------------------------------------------------------
14570 XON protocol local helpers
14571 ----------------------------------------------------------------- */
14572 static void channel_flow_control_remove (PLCI * plci) {
14573 DIVA_CAPI_ADAPTER * a = plci->adapter;
14574 word i;
14575 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14576 if (a->ch_flow_plci[i] == plci->Id) {
14577 a->ch_flow_plci[i] = 0;
14578 a->ch_flow_control[i] = 0;
14583 static void channel_x_on (PLCI * plci, byte ch) {
14584 DIVA_CAPI_ADAPTER * a = plci->adapter;
14585 if (a->ch_flow_control[ch] & N_XON_SENT) {
14586 a->ch_flow_control[ch] &= ~N_XON_SENT;
14590 static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14591 DIVA_CAPI_ADAPTER * a = plci->adapter;
14592 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14593 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14594 a->ch_flow_plci[ch] = plci->Id;
14595 a->ch_flow_control_pending++;
14599 static void channel_request_xon (PLCI * plci, byte ch) {
14600 DIVA_CAPI_ADAPTER * a = plci->adapter;
14602 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14603 a->ch_flow_control[ch] |= N_XON_REQ;
14604 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14605 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14609 static void channel_xmit_extended_xon (PLCI * plci) {
14610 DIVA_CAPI_ADAPTER * a;
14611 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14612 int i, one_requested = 0;
14614 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14615 return;
14618 for (i = 0; i < max_ch; i++) {
14619 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14620 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14621 (plci->Id == a->ch_flow_plci[i])) {
14622 channel_request_xon (plci, (byte)i);
14623 one_requested = 1;
14627 if (one_requested) {
14628 channel_xmit_xon (plci);
14633 Try to xmit next X_ON
14635 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14636 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14637 int i;
14639 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14640 return (0);
14643 if (a->last_flow_control_ch >= max_ch) {
14644 a->last_flow_control_ch = 1;
14646 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14647 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14648 (plci->Id == a->ch_flow_plci[i])) {
14649 a->last_flow_control_ch = i+1;
14650 return (i);
14654 for (i = 1; i < a->last_flow_control_ch; i++) {
14655 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14656 (plci->Id == a->ch_flow_plci[i])) {
14657 a->last_flow_control_ch = i+1;
14658 return (i);
14662 return (0);
14665 static void channel_xmit_xon (PLCI * plci) {
14666 DIVA_CAPI_ADAPTER * a = plci->adapter;
14667 byte ch;
14669 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14670 return;
14672 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14673 return;
14675 a->ch_flow_control[ch] &= ~N_XON_REQ;
14676 a->ch_flow_control[ch] |= N_XON_SENT;
14678 plci->NL.Req = plci->nl_req = (byte)N_XON;
14679 plci->NL.ReqCh = ch;
14680 plci->NL.X = plci->NData;
14681 plci->NL.XNum = 1;
14682 plci->NData[0].P = &plci->RBuffer[0];
14683 plci->NData[0].PLength = 0;
14685 plci->adapter->request(&plci->NL);
14688 static int channel_can_xon (PLCI * plci, byte ch) {
14689 APPL * APPLptr;
14690 DIVA_CAPI_ADAPTER * a;
14691 word NCCIcode;
14692 dword count;
14693 word Num;
14694 word i;
14696 APPLptr = plci->appl;
14697 a = plci->adapter;
14699 if (!APPLptr)
14700 return (0);
14702 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14704 /* count all buffers within the Application pool */
14705 /* belonging to the same NCCI. XON if a first is */
14706 /* used. */
14707 count = 0;
14708 Num = 0xffff;
14709 for(i=0; i<APPLptr->MaxBuffer; i++) {
14710 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14711 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14713 if ((count > 2) || (Num == 0xffff)) {
14714 return (0);
14716 return (1);
14720 /*------------------------------------------------------------------*/
14722 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14724 return 1;
14729 /**********************************************************************************/
14730 /* function groups the listening applications according to the CIP mask and the */
14731 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14732 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14733 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14734 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14735 /* OS specific part (per adapter). */
14736 /**********************************************************************************/
14737 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14739 word i,j,k,busy,group_found;
14740 dword info_mask_group[MAX_CIP_TYPES];
14741 dword cip_mask_group[MAX_CIP_TYPES];
14742 word appl_number_group_type[MAX_APPL];
14743 PLCI *auxplci;
14745 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14747 if(!a->group_optimization_enabled)
14749 dbug(1,dprintf("No group optimization"));
14750 return;
14753 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14755 for(i=0;i<MAX_CIP_TYPES;i++)
14757 info_mask_group[i] = 0;
14758 cip_mask_group [i] = 0;
14760 for(i=0;i<MAX_APPL;i++)
14762 appl_number_group_type[i] = 0;
14764 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14765 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14766 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14768 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14769 return; /* allow good application unfiltered access */
14772 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14774 if(application[i].Id && a->CIP_Mask[i] )
14776 for(k=0,busy=false; k<a->max_plci; k++)
14778 if(a->plci[k].Id)
14780 auxplci = &a->plci[k];
14781 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14783 busy = true;
14784 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14786 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14788 busy = true;
14789 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14794 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14796 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14797 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14798 appl_number_group_type[i] = MAX_CIP_TYPES;
14799 group_found=true;
14800 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14802 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14803 { /* is group already present ? */
14804 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14805 group_found=true;
14806 dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14808 else if(!info_mask_group[j])
14809 { /* establish a new group */
14810 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14811 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14812 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14813 group_found=true;
14814 dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14820 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14822 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14824 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14826 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14828 else
14830 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14831 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14833 if(appl_number_group_type[i] == appl_number_group_type[j])
14835 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14836 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14837 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14842 else /* application should not get a call */
14844 clear_group_ind_mask_bit (plci, i);
14852 /* OS notifies the driver about a application Capi_Register */
14853 word CapiRegister(word id)
14855 word i,j,appls_found;
14857 PLCI *plci;
14858 DIVA_CAPI_ADAPTER *a;
14860 for(i=0,appls_found=0; i<max_appl; i++)
14862 if( application[i].Id && (application[i].Id!=id) )
14864 appls_found++; /* an application has been found */
14868 if(appls_found) return true;
14869 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14871 a = &adapter[i];
14872 if(a->request)
14874 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14876 if(!appls_found) /* first application does a capi register */
14878 if((j=get_plci(a))) /* activate L1 of all adapters */
14880 plci = &a->plci[j-1];
14881 plci->command = 0;
14882 add_p(plci,OAD,"\x01\xfd");
14883 add_p(plci,CAI,"\x01\x80");
14884 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14885 add_p(plci,SHIFT|6,NULL);
14886 add_p(plci,SIN,"\x02\x00\x00");
14887 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14888 sig_req(plci,ASSIGN,DSIG_ID);
14889 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14890 sig_req(plci,SIG_CTRL,0);
14891 send_req(plci);
14897 return false;
14900 /*------------------------------------------------------------------*/
14902 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14904 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14906 word i;
14907 /* Format of vswitch_t:
14908 0 byte length
14909 1 byte VSWITCHIE
14910 2 byte VSWITCH_REQ/VSWITCH_IND
14911 3 byte reserved
14912 4 word VSwitchcommand
14913 6 word returnerror
14914 8... Params
14916 if(!plci ||
14917 !plci->appl ||
14918 !plci->State ||
14919 plci->Sig.Ind==NCR_FACILITY
14921 return;
14923 for(i=0;i<MAX_MULTI_IE;i++)
14925 if(!parms[i][0]) continue;
14926 if(parms[i][0]<7)
14928 parms[i][0]=0; /* kill it */
14929 continue;
14931 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14932 switch(parms[i][4])
14934 case VSJOIN:
14935 if(!plci->relatedPTYPLCI ||
14936 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14937 { /* Error */
14938 break;
14940 /* remember all necessary informations */
14941 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14943 break;
14945 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14946 { /* first indication after ECT-Request on Consultation Call */
14947 plci->vswitchstate=parms[i][9];
14948 parms[i][9]=2; /* State */
14949 /* now ask first Call to join */
14951 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14952 { /* Answer of VSWITCH_REQ from first Call */
14953 plci->vswitchstate=parms[i][9];
14954 /* tell consultation call to join
14955 and the protocol capabilities of the first call */
14957 else
14958 { /* Error */
14959 break;
14961 plci->vsprot=parms[i][10]; /* protocol */
14962 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14963 /* send join request to related PLCI */
14964 parms[i][1]=VSWITCHIE;
14965 parms[i][2]=VSWITCH_REQ;
14967 plci->relatedPTYPLCI->command = 0;
14968 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14969 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14970 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14971 send_req(plci->relatedPTYPLCI);
14972 break;
14973 case VSTRANSPORT:
14974 default:
14975 if(plci->relatedPTYPLCI &&
14976 plci->vswitchstate==3 &&
14977 plci->relatedPTYPLCI->vswitchstate==3)
14979 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14980 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14981 send_req(plci->relatedPTYPLCI);
14983 break;
14985 parms[i][0]=0; /* kill it */
14990 /*------------------------------------------------------------------*/
14992 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14993 ENTITY e;
14994 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14996 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14997 return (-1);
15000 pReq->xdi_dma_descriptor_operation.Req = 0;
15001 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15003 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15004 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15005 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15006 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15008 e.user[0] = plci->adapter->Id - 1;
15009 plci->adapter->request((ENTITY*)pReq);
15011 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15012 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15013 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15014 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15015 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15016 plci->adapter->Id,
15017 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15018 *dma_magic));
15019 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15020 } else {
15021 dbug(1,dprintf("dma_alloc failed"));
15022 return (-1);
15026 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15027 ENTITY e;
15028 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15030 if (nr < 0) {
15031 return;
15034 pReq->xdi_dma_descriptor_operation.Req = 0;
15035 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15037 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15038 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15039 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15040 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15042 e.user[0] = plci->adapter->Id - 1;
15043 plci->adapter->request((ENTITY*)pReq);
15045 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15046 dbug(1,dprintf("dma_free(%d)", nr));
15047 } else {
15048 dbug(1,dprintf("dma_free failed (%d)", nr));
15052 /*------------------------------------------------------------------*/