Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / isdn / hardware / eicon / message.c
blobdef7992a38e68d8900853dad20205a6eece8376e
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.
26 #include <linux/bitmap.h>
28 #include "platform.h"
29 #include "di_defs.h"
30 #include "pc.h"
31 #include "capi20.h"
32 #include "divacapi.h"
33 #include "mdm_msg.h"
34 #include "divasync.h"
36 #define FILE_ "MESSAGE.C"
37 #define dprintf
39 /*------------------------------------------------------------------*/
40 /* This is options supported for all adapters that are server by */
41 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
42 /* and it is not necessary to save it separate for every adapter */
43 /* Macrose defined here have only local meaning */
44 /*------------------------------------------------------------------*/
45 static dword diva_xdi_extended_features = 0;
47 #define DIVA_CAPI_USE_CMA 0x00000001
48 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
49 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
50 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
53 CAPI can request to process all return codes self only if:
54 protocol code supports this && xdi supports this
56 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
58 /*------------------------------------------------------------------*/
59 /* local function prototypes */
60 /*------------------------------------------------------------------*/
62 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
63 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
64 word CapiRelease(word);
65 word CapiRegister(word);
66 word api_put(APPL *, CAPI_MSG *);
67 static word api_parse(byte *, word, byte *, API_PARSE *);
68 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
69 static void api_load_msg(API_SAVE *in, API_PARSE *out);
71 word api_remove_start(void);
72 void api_remove_complete(void);
74 static void plci_remove(PLCI *);
75 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
76 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
78 void callback(ENTITY *);
80 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
81 static void data_rc(PLCI *, byte);
82 static void data_ack(PLCI *, byte);
83 static void sig_ind(PLCI *);
84 static void SendInfo(PLCI *, dword, byte **, byte);
85 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
86 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
88 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
90 static void nl_ind(PLCI *);
92 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
93 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
94 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
95 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
96 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
97 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
98 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
99 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
100 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
101 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
102 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
103 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
104 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
105 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
106 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
107 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static word get_plci(DIVA_CAPI_ADAPTER *);
118 static void add_p(PLCI *, byte, byte *);
119 static void add_s(PLCI *plci, byte code, API_PARSE *p);
120 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
121 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
122 static void add_d(PLCI *, word, byte *);
123 static void add_ai(PLCI *, API_PARSE *);
124 static word add_b1(PLCI *, API_PARSE *, word, word);
125 static word add_b23(PLCI *, API_PARSE *);
126 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
127 static void sig_req(PLCI *, byte, byte);
128 static void nl_req_ncci(PLCI *, byte, byte);
129 static void send_req(PLCI *);
130 static void send_data(PLCI *);
131 static word plci_remove_check(PLCI *);
132 static void listen_check(DIVA_CAPI_ADAPTER *);
133 static byte AddInfo(byte **, byte **, byte *, byte *);
134 static byte getChannel(API_PARSE *);
135 static void IndParse(PLCI *, const word *, byte **, byte);
136 static byte ie_compare(byte *, byte *);
137 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
138 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
141 XON protocol helpers
143 static void channel_flow_control_remove(PLCI *plci);
144 static void channel_x_off(PLCI *plci, byte ch, byte flag);
145 static void channel_x_on(PLCI *plci, byte ch);
146 static void channel_request_xon(PLCI *plci, byte ch);
147 static void channel_xmit_xon(PLCI *plci);
148 static int channel_can_xon(PLCI *plci, byte ch);
149 static void channel_xmit_extended_xon(PLCI *plci);
151 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
152 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
153 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
154 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
155 static void VoiceChannelOff(PLCI *plci);
156 static void adv_voice_write_coefs(PLCI *plci, word write_command);
157 static void adv_voice_clear_config(PLCI *plci);
159 static word get_b1_facilities(PLCI *plci, byte b1_resource);
160 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
161 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
162 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
163 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
164 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
165 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
166 static void select_b_command(dword Id, PLCI *plci, byte Rc);
167 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
168 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
169 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
170 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
171 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
172 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
173 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
174 static void init_b1_config(PLCI *plci);
175 static void clear_b1_config(PLCI *plci);
177 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
178 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
179 static void dtmf_confirmation(dword Id, PLCI *plci);
180 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
181 static void dtmf_parameter_write(PLCI *plci);
184 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
185 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
186 static void mixer_clear_config(PLCI *plci);
187 static void mixer_notify_update(PLCI *plci, byte others);
188 static void mixer_command(dword Id, PLCI *plci, byte Rc);
189 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
190 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
191 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
192 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
193 static void mixer_remove(PLCI *plci);
196 static void ec_command(dword Id, PLCI *plci, byte Rc);
197 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
198 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
201 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
202 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
205 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
206 static void diva_free_dma_descriptor(PLCI *plci, int nr);
208 /*------------------------------------------------------------------*/
209 /* external function prototypes */
210 /*------------------------------------------------------------------*/
212 extern byte MapController(byte);
213 extern byte UnMapController(byte);
214 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
215 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
217 void sendf(APPL *, word, dword, word, byte *, ...);
218 void *TransmitBufferSet(APPL *appl, dword ref);
219 void *TransmitBufferGet(APPL *appl, void *p);
220 void TransmitBufferFree(APPL *appl, void *p);
221 void *ReceiveBufferGet(APPL *appl, int Num);
223 int fax_head_line_time(char *buffer);
226 /*------------------------------------------------------------------*/
227 /* Global data definitions */
228 /*------------------------------------------------------------------*/
229 extern byte max_adapter;
230 extern byte max_appl;
231 extern DIVA_CAPI_ADAPTER *adapter;
232 extern APPL *application;
240 static byte remove_started = false;
241 static PLCI dummy_plci;
244 static struct _ftable {
245 word command;
246 byte *format;
247 byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
248 } ftable[] = {
249 {_DATA_B3_R, "dwww", data_b3_req},
250 {_DATA_B3_I | RESPONSE, "w", data_b3_res},
251 {_INFO_R, "ss", info_req},
252 {_INFO_I | RESPONSE, "", info_res},
253 {_CONNECT_R, "wsssssssss", connect_req},
254 {_CONNECT_I | RESPONSE, "wsssss", connect_res},
255 {_CONNECT_ACTIVE_I | RESPONSE, "", connect_a_res},
256 {_DISCONNECT_R, "s", disconnect_req},
257 {_DISCONNECT_I | RESPONSE, "", disconnect_res},
258 {_LISTEN_R, "dddss", listen_req},
259 {_ALERT_R, "s", alert_req},
260 {_FACILITY_R, "ws", facility_req},
261 {_FACILITY_I | RESPONSE, "ws", facility_res},
262 {_CONNECT_B3_R, "s", connect_b3_req},
263 {_CONNECT_B3_I | RESPONSE, "ws", connect_b3_res},
264 {_CONNECT_B3_ACTIVE_I | RESPONSE, "", connect_b3_a_res},
265 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
266 {_DISCONNECT_B3_I | RESPONSE, "", disconnect_b3_res},
267 {_RESET_B3_R, "s", reset_b3_req},
268 {_RESET_B3_I | RESPONSE, "", reset_b3_res},
269 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws", connect_b3_t90_a_res},
270 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "", connect_b3_t90_a_res},
271 {_SELECT_B_REQ, "s", select_b_req},
272 {_MANUFACTURER_R, "dws", manufacturer_req},
273 {_MANUFACTURER_I | RESPONSE, "dws", manufacturer_res},
274 {_MANUFACTURER_I | RESPONSE, "", manufacturer_res}
277 static byte *cip_bc[29][2] = {
278 { "", "" }, /* 0 */
279 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
280 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
281 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
282 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
283 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
284 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
285 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
286 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
287 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
288 { "", "" }, /* 10 */
289 { "", "" }, /* 11 */
290 { "", "" }, /* 12 */
291 { "", "" }, /* 13 */
292 { "", "" }, /* 14 */
293 { "", "" }, /* 15 */
295 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
296 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
297 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
298 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
299 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
300 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
301 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
302 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
303 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
304 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
305 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
306 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
307 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
310 static byte *cip_hlc[29] = {
311 "", /* 0 */
312 "", /* 1 */
313 "", /* 2 */
314 "", /* 3 */
315 "", /* 4 */
316 "", /* 5 */
317 "", /* 6 */
318 "", /* 7 */
319 "", /* 8 */
320 "", /* 9 */
321 "", /* 10 */
322 "", /* 11 */
323 "", /* 12 */
324 "", /* 13 */
325 "", /* 14 */
326 "", /* 15 */
328 "\x02\x91\x81", /* 16 */
329 "\x02\x91\x84", /* 17 */
330 "\x02\x91\xa1", /* 18 */
331 "\x02\x91\xa4", /* 19 */
332 "\x02\x91\xa8", /* 20 */
333 "\x02\x91\xb1", /* 21 */
334 "\x02\x91\xb2", /* 22 */
335 "\x02\x91\xb5", /* 23 */
336 "\x02\x91\xb8", /* 24 */
337 "\x02\x91\xc1", /* 25 */
338 "\x02\x91\x81", /* 26 */
339 "\x03\x91\xe0\x01", /* 27 */
340 "\x03\x91\xe0\x02" /* 28 */
343 /*------------------------------------------------------------------*/
345 #define V120_HEADER_LENGTH 1
346 #define V120_HEADER_EXTEND_BIT 0x80
347 #define V120_HEADER_BREAK_BIT 0x40
348 #define V120_HEADER_C1_BIT 0x04
349 #define V120_HEADER_C2_BIT 0x08
350 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
352 static byte v120_default_header[] =
355 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
359 static byte v120_break_header[] =
362 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
367 /*------------------------------------------------------------------*/
368 /* API_PUT function */
369 /*------------------------------------------------------------------*/
371 word api_put(APPL *appl, CAPI_MSG *msg)
373 word i, j, k, l, n;
374 word ret;
375 byte c;
376 byte controller;
377 DIVA_CAPI_ADAPTER *a;
378 PLCI *plci;
379 NCCI *ncci_ptr;
380 word ncci;
381 CAPI_MSG *m;
382 API_PARSE msg_parms[MAX_MSG_PARMS + 1];
384 if (msg->header.length < sizeof(msg->header) ||
385 msg->header.length > MAX_MSG_SIZE) {
386 dbug(1, dprintf("bad len"));
387 return _BAD_MSG;
390 controller = (byte)((msg->header.controller & 0x7f) - 1);
392 /* controller starts with 0 up to (max_adapter - 1) */
393 if (controller >= max_adapter)
395 dbug(1, dprintf("invalid ctrl"));
396 return _BAD_MSG;
399 a = &adapter[controller];
400 plci = NULL;
401 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
403 dbug(1, dprintf("plci=%x", msg->header.plci));
404 plci = &a->plci[msg->header.plci - 1];
405 ncci = GET_WORD(&msg->header.ncci);
406 if (plci->Id
407 && (plci->appl
408 || (plci->State == INC_CON_PENDING)
409 || (plci->State == INC_CON_ALERT)
410 || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
411 && ((ncci == 0)
412 || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
413 || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
415 i = plci->msg_in_read_pos;
416 j = plci->msg_in_write_pos;
417 if (j >= i)
419 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
420 i += MSG_IN_QUEUE_SIZE - j;
421 else
422 j = 0;
424 else
427 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
429 if (i > MSG_IN_QUEUE_SIZE - n)
430 i = MSG_IN_QUEUE_SIZE - n + 1;
431 i -= j;
434 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
437 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
438 msg->header.length, plci->msg_in_write_pos,
439 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
441 return _QUEUE_FULL;
443 c = false;
444 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
445 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
447 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
448 c = true;
450 if (msg->header.command == _DATA_B3_R)
452 if (msg->header.length < 20)
454 dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
455 return _BAD_MSG;
457 ncci_ptr = &(a->ncci[ncci]);
458 n = ncci_ptr->data_pending;
459 l = ncci_ptr->data_ack_pending;
460 k = plci->msg_in_read_pos;
461 while (k != plci->msg_in_write_pos)
463 if (k == plci->msg_in_wrap_pos)
464 k = 0;
465 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
466 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
468 n++;
469 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
470 l++;
473 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
474 MSG_IN_OVERHEAD + 3) & 0xfffc;
477 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
479 dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
480 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
482 return _QUEUE_FULL;
484 if (plci->req_in || plci->internal_command)
486 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
487 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
489 dbug(0, dprintf("Q-FULL3(requeue)"));
491 return _QUEUE_FULL;
493 c = true;
496 else
498 if (plci->req_in || plci->internal_command)
499 c = true;
500 else
502 plci->command = msg->header.command;
503 plci->number = msg->header.number;
506 if (c)
508 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
509 msg->header.command, plci->req_in, plci->internal_command,
510 msg->header.length, plci->msg_in_write_pos,
511 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
512 if (j == 0)
513 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
514 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
515 for (i = 0; i < msg->header.length; i++)
516 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
517 if (m->header.command == _DATA_B3_R)
520 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
524 j = (j + 3) & 0xfffc;
526 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
527 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
528 return 0;
531 else
533 plci = NULL;
536 dbug(1, dprintf("com=%x", msg->header.command));
538 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
539 for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
541 if (ftable[i].command == msg->header.command) {
542 /* break loop if the message is correct, otherwise continue scan */
543 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
544 if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
545 ret = 0;
546 break;
548 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
551 if (ret) {
552 dbug(1, dprintf("BAD_MSG"));
553 if (plci) plci->command = 0;
554 return ret;
558 c = ftable[i].function(GET_DWORD(&msg->header.controller),
559 msg->header.number,
561 plci,
562 appl,
563 msg_parms);
565 channel_xmit_extended_xon(plci);
567 if (c == 1) send_req(plci);
568 if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
569 if (plci && !plci->req_in) plci->command = 0;
570 return 0;
574 /*------------------------------------------------------------------*/
575 /* api_parse function, check the format of api messages */
576 /*------------------------------------------------------------------*/
578 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
580 word i;
581 word p;
583 for (i = 0, p = 0; format[i]; i++) {
584 if (parms)
586 parms[i].info = &msg[p];
588 switch (format[i]) {
589 case 'b':
590 p += 1;
591 break;
592 case 'w':
593 p += 2;
594 break;
595 case 'd':
596 p += 4;
597 break;
598 case 's':
599 if (msg[p] == 0xff) {
600 parms[i].info += 2;
601 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
602 p += (parms[i].length + 3);
604 else {
605 parms[i].length = msg[p];
606 p += (parms[i].length + 1);
608 break;
611 if (p > length) return true;
613 if (parms) parms[i].info = NULL;
614 return false;
617 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
619 word i, j, n = 0;
620 byte *p;
622 p = out->info;
623 for (i = 0; format[i] != '\0'; i++)
625 out->parms[i].info = p;
626 out->parms[i].length = in[i].length;
627 switch (format[i])
629 case 'b':
630 n = 1;
631 break;
632 case 'w':
633 n = 2;
634 break;
635 case 'd':
636 n = 4;
637 break;
638 case 's':
639 n = in[i].length + 1;
640 break;
642 for (j = 0; j < n; j++)
643 *(p++) = in[i].info[j];
645 out->parms[i].info = NULL;
646 out->parms[i].length = 0;
649 static void api_load_msg(API_SAVE *in, API_PARSE *out)
651 word i;
653 i = 0;
656 out[i].info = in->parms[i].info;
657 out[i].length = in->parms[i].length;
658 } while (in->parms[i++].info);
662 /*------------------------------------------------------------------*/
663 /* CAPI remove function */
664 /*------------------------------------------------------------------*/
666 word api_remove_start(void)
668 word i;
669 word j;
671 if (!remove_started) {
672 remove_started = true;
673 for (i = 0; i < max_adapter; i++) {
674 if (adapter[i].request) {
675 for (j = 0; j < adapter[i].max_plci; j++) {
676 if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
680 return 1;
682 else {
683 for (i = 0; i < max_adapter; i++) {
684 if (adapter[i].request) {
685 for (j = 0; j < adapter[i].max_plci; j++) {
686 if (adapter[i].plci[j].Sig.Id) return 1;
691 api_remove_complete();
692 return 0;
696 /*------------------------------------------------------------------*/
697 /* internal command queue */
698 /*------------------------------------------------------------------*/
700 static void init_internal_command_queue(PLCI *plci)
702 word i;
704 dbug(1, dprintf("%s,%d: init_internal_command_queue",
705 (char *)(FILE_), __LINE__));
707 plci->internal_command = 0;
708 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
709 plci->internal_command_queue[i] = NULL;
713 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
715 word i;
717 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
718 UnMapId(Id), (char *)(FILE_), __LINE__));
720 if (plci->internal_command == 0)
722 plci->internal_command_queue[0] = command_function;
723 (*command_function)(Id, plci, OK);
725 else
727 i = 1;
728 while (plci->internal_command_queue[i] != NULL)
729 i++;
730 plci->internal_command_queue[i] = command_function;
735 static void next_internal_command(dword Id, PLCI *plci)
737 word i;
739 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
740 UnMapId(Id), (char *)(FILE_), __LINE__));
742 plci->internal_command = 0;
743 plci->internal_command_queue[0] = NULL;
744 while (plci->internal_command_queue[1] != NULL)
746 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
747 plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
748 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
749 (*(plci->internal_command_queue[0]))(Id, plci, OK);
750 if (plci->internal_command != 0)
751 return;
752 plci->internal_command_queue[0] = NULL;
757 /*------------------------------------------------------------------*/
758 /* NCCI allocate/remove function */
759 /*------------------------------------------------------------------*/
761 static dword ncci_mapping_bug = 0;
763 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
765 DIVA_CAPI_ADAPTER *a;
766 word ncci, i, j, k;
768 a = plci->adapter;
769 if (!ch || a->ch_ncci[ch])
771 ncci_mapping_bug++;
772 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
773 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
774 ncci = ch;
776 else
778 if (force_ncci)
779 ncci = force_ncci;
780 else
782 if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
783 ncci = ch;
784 else
786 ncci = 1;
787 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
788 ncci++;
789 if (ncci == MAX_NCCI + 1)
791 ncci_mapping_bug++;
792 i = 1;
795 j = 1;
796 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
797 j++;
798 k = j;
799 if (j < MAX_NCCI + 1)
803 j++;
804 } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
806 } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
807 if (i < MAX_NL_CHANNEL + 1)
809 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
810 ncci_mapping_bug, ch, force_ncci, i, k, j));
812 else
814 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
815 ncci_mapping_bug, ch, force_ncci));
817 ncci = ch;
820 a->ncci_plci[ncci] = plci->Id;
821 a->ncci_state[ncci] = IDLE;
822 if (!plci->ncci_ring_list)
823 plci->ncci_ring_list = ncci;
824 else
825 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
826 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
828 a->ncci_ch[ncci] = ch;
829 a->ch_ncci[ch] = (byte) ncci;
830 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
831 ncci_mapping_bug, ch, force_ncci, ch, ncci));
833 return (ncci);
837 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
839 DIVA_CAPI_ADAPTER *a;
840 APPL *appl;
841 word i, ncci_code;
842 dword Id;
844 a = plci->adapter;
845 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
846 if (ncci)
848 if (a->ncci_plci[ncci] == plci->Id)
850 if (!plci->appl)
852 ncci_mapping_bug++;
853 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
854 ncci_mapping_bug, Id));
856 else
858 appl = plci->appl;
859 ncci_code = ncci | (((word) a->Id) << 8);
860 for (i = 0; i < appl->MaxBuffer; i++)
862 if ((appl->DataNCCI[i] == ncci_code)
863 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
865 appl->DataNCCI[i] = 0;
871 else
873 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
875 if (a->ncci_plci[ncci] == plci->Id)
877 if (!plci->appl)
879 ncci_mapping_bug++;
880 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
881 ncci_mapping_bug, Id));
883 else
885 appl = plci->appl;
886 ncci_code = ncci | (((word) a->Id) << 8);
887 for (i = 0; i < appl->MaxBuffer; i++)
889 if ((appl->DataNCCI[i] == ncci_code)
890 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
892 appl->DataNCCI[i] = 0;
902 static void cleanup_ncci_data(PLCI *plci, word ncci)
904 NCCI *ncci_ptr;
906 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
908 ncci_ptr = &(plci->adapter->ncci[ncci]);
909 if (plci->appl)
911 while (ncci_ptr->data_pending != 0)
913 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
914 TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
915 (ncci_ptr->data_out)++;
916 if (ncci_ptr->data_out == MAX_DATA_B3)
917 ncci_ptr->data_out = 0;
918 (ncci_ptr->data_pending)--;
921 ncci_ptr->data_out = 0;
922 ncci_ptr->data_pending = 0;
923 ncci_ptr->data_ack_out = 0;
924 ncci_ptr->data_ack_pending = 0;
929 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
931 DIVA_CAPI_ADAPTER *a;
932 dword Id;
933 word i;
935 a = plci->adapter;
936 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
937 if (!preserve_ncci)
938 ncci_free_receive_buffers(plci, ncci);
939 if (ncci)
941 if (a->ncci_plci[ncci] != plci->Id)
943 ncci_mapping_bug++;
944 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
945 ncci_mapping_bug, Id, preserve_ncci));
947 else
949 cleanup_ncci_data(plci, ncci);
950 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
951 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
952 a->ch_ncci[a->ncci_ch[ncci]] = 0;
953 if (!preserve_ncci)
955 a->ncci_ch[ncci] = 0;
956 a->ncci_plci[ncci] = 0;
957 a->ncci_state[ncci] = IDLE;
958 i = plci->ncci_ring_list;
959 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
960 i = a->ncci_next[i];
961 if ((i != 0) && (a->ncci_next[i] == ncci))
963 if (i == ncci)
964 plci->ncci_ring_list = 0;
965 else if (plci->ncci_ring_list == ncci)
966 plci->ncci_ring_list = i;
967 a->ncci_next[i] = a->ncci_next[ncci];
969 a->ncci_next[ncci] = 0;
973 else
975 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
977 if (a->ncci_plci[ncci] == plci->Id)
979 cleanup_ncci_data(plci, ncci);
980 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
981 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
982 a->ch_ncci[a->ncci_ch[ncci]] = 0;
983 if (!preserve_ncci)
985 a->ncci_ch[ncci] = 0;
986 a->ncci_plci[ncci] = 0;
987 a->ncci_state[ncci] = IDLE;
988 a->ncci_next[ncci] = 0;
992 if (!preserve_ncci)
993 plci->ncci_ring_list = 0;
998 /*------------------------------------------------------------------*/
999 /* PLCI remove function */
1000 /*------------------------------------------------------------------*/
1002 static void plci_free_msg_in_queue(PLCI *plci)
1004 word i;
1006 if (plci->appl)
1008 i = plci->msg_in_read_pos;
1009 while (i != plci->msg_in_write_pos)
1011 if (i == plci->msg_in_wrap_pos)
1012 i = 0;
1013 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1016 TransmitBufferFree(plci->appl,
1017 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1021 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1022 MSG_IN_OVERHEAD + 3) & 0xfffc;
1026 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1027 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1028 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1032 static void plci_remove(PLCI *plci)
1035 if (!plci) {
1036 dbug(1, dprintf("plci_remove(no plci)"));
1037 return;
1039 init_internal_command_queue(plci);
1040 dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1041 if (plci_remove_check(plci))
1043 return;
1045 if (plci->Sig.Id == 0xff)
1047 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1048 if (plci->NL.Id && !plci->nl_remove_id)
1050 nl_req_ncci(plci, REMOVE, 0);
1051 send_req(plci);
1054 else
1056 if (!plci->sig_remove_id
1057 && (plci->Sig.Id
1058 || (plci->req_in != plci->req_out)
1059 || (plci->nl_req || plci->sig_req)))
1061 sig_req(plci, HANGUP, 0);
1062 send_req(plci);
1065 ncci_remove(plci, 0, false);
1066 plci_free_msg_in_queue(plci);
1068 plci->channels = 0;
1069 plci->appl = NULL;
1070 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1071 plci->State = OUTG_DIS_PENDING;
1074 /*------------------------------------------------------------------*/
1075 /* translation function for each message */
1076 /*------------------------------------------------------------------*/
1078 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1079 PLCI *plci, APPL *appl, API_PARSE *parms)
1081 word ch;
1082 word i;
1083 word Info;
1084 byte LinkLayer;
1085 API_PARSE *ai;
1086 API_PARSE *bp;
1087 API_PARSE ai_parms[5];
1088 word channel = 0;
1089 dword ch_mask;
1090 byte m;
1091 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1092 static byte lli[2] = {0x01, 0x00};
1093 byte noCh = 0;
1094 word dir = 0;
1095 byte *p_chi = "";
1097 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1099 dbug(1, dprintf("connect_req(%d)", parms->length));
1100 Info = _WRONG_IDENTIFIER;
1101 if (a)
1103 if (a->adapter_disabled)
1105 dbug(1, dprintf("adapter disabled"));
1106 Id = ((word)1 << 8) | a->Id;
1107 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1108 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1109 return false;
1111 Info = _OUT_OF_PLCI;
1112 if ((i = get_plci(a)))
1114 Info = 0;
1115 plci = &a->plci[i - 1];
1116 plci->appl = appl;
1117 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1118 /* check 'external controller' bit for codec support */
1119 if (Id & EXT_CONTROLLER)
1121 if (AdvCodecSupport(a, plci, appl, 0))
1123 plci->Id = 0;
1124 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1125 return 2;
1128 ai = &parms[9];
1129 bp = &parms[5];
1130 ch = 0;
1131 if (bp->length)LinkLayer = bp->info[3];
1132 else LinkLayer = 0;
1133 if (ai->length)
1135 ch = 0xffff;
1136 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1138 ch = 0;
1139 if (ai_parms[0].length)
1141 ch = GET_WORD(ai_parms[0].info + 1);
1142 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1143 if (ch == 4) /* explizit CHI in message */
1145 /* check length of B-CH struct */
1146 if ((ai_parms[0].info)[3] >= 1)
1148 if ((ai_parms[0].info)[4] == CHI)
1150 p_chi = &((ai_parms[0].info)[5]);
1152 else
1154 p_chi = &((ai_parms[0].info)[3]);
1156 if (p_chi[0] > 35) /* check length of channel ID */
1158 Info = _WRONG_MESSAGE_FORMAT;
1161 else Info = _WRONG_MESSAGE_FORMAT;
1164 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1166 dir = GET_WORD(ai_parms[0].info + 3);
1167 ch_mask = 0;
1168 m = 0x3f;
1169 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1171 if (ai_parms[0].info[i + 5] != 0)
1173 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1174 Info = _WRONG_MESSAGE_FORMAT;
1175 else
1177 if (ch_mask == 0)
1178 channel = i;
1179 ch_mask |= 1L << i;
1182 m = 0;
1184 if (ch_mask == 0)
1185 Info = _WRONG_MESSAGE_FORMAT;
1186 if (!Info)
1188 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1190 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1191 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1192 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1194 else
1195 esc_chi[0] = 2;
1196 esc_chi[2] = (byte)channel;
1197 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1198 add_p(plci, LLI, lli);
1199 add_p(plci, ESC, esc_chi);
1200 plci->State = LOCAL_CONNECT;
1201 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1206 else Info = _WRONG_MESSAGE_FORMAT;
1209 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1210 plci->command = _CONNECT_R;
1211 plci->number = Number;
1212 /* x.31 or D-ch free SAPI in LinkLayer? */
1213 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1214 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1216 /* B-channel used for B3 connections (ch==0), or no B channel */
1217 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1218 if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1219 else Info = add_b1(plci, &parms[5], ch, 0);
1220 add_s(plci, OAD, &parms[2]);
1221 add_s(plci, OSA, &parms[4]);
1222 add_s(plci, BC, &parms[6]);
1223 add_s(plci, LLC, &parms[7]);
1224 add_s(plci, HLC, &parms[8]);
1225 if (a->Info_Mask[appl->Id - 1] & 0x200)
1227 /* early B3 connect (CIP mask bit 9) no release after a disc */
1228 add_p(plci, LLI, "\x01\x01");
1230 if (GET_WORD(parms[0].info) < 29) {
1231 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1232 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1234 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1235 sig_req(plci, ASSIGN, DSIG_ID);
1237 else if (ch == 1) {
1239 /* D-Channel used for B3 connections */
1240 plci->Sig.Id = 0xff;
1241 Info = 0;
1244 if (!Info && ch != 2 && !noCh) {
1245 Info = add_b23(plci, &parms[5]);
1246 if (!Info) {
1247 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1251 if (!Info)
1253 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1255 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1257 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1258 plci->spoofed_msg = CALL_REQ;
1259 plci->internal_command = BLOCK_PLCI;
1260 plci->command = 0;
1261 dbug(1, dprintf("Spoof"));
1262 send_req(plci);
1263 return false;
1265 if (ch == 4)add_p(plci, CHI, p_chi);
1266 add_s(plci, CPN, &parms[1]);
1267 add_s(plci, DSA, &parms[3]);
1268 if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1269 add_ai(plci, &parms[9]);
1270 if (!dir)sig_req(plci, CALL_REQ, 0);
1271 else
1273 plci->command = PERM_LIST_REQ;
1274 plci->appl = appl;
1275 sig_req(plci, LISTEN_REQ, 0);
1276 send_req(plci);
1277 return false;
1280 send_req(plci);
1281 return false;
1283 plci->Id = 0;
1286 sendf(appl,
1287 _CONNECT_R | CONFIRM,
1289 Number,
1290 "w", Info);
1291 return 2;
1294 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1295 PLCI *plci, APPL *appl, API_PARSE *parms)
1297 word i, Info;
1298 word Reject;
1299 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1300 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1301 API_PARSE *ai;
1302 API_PARSE ai_parms[5];
1303 word ch = 0;
1305 if (!plci) {
1306 dbug(1, dprintf("connect_res(no plci)"));
1307 return 0; /* no plci, no send */
1310 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1311 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1312 ai = &parms[5];
1313 dbug(1, dprintf("ai->length=%d", ai->length));
1315 if (ai->length)
1317 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1319 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1320 ch = 0;
1321 if (ai_parms[0].length)
1323 ch = GET_WORD(ai_parms[0].info + 1);
1324 dbug(1, dprintf("BCH-I=0x%x", ch));
1329 if (plci->State == INC_CON_CONNECTED_ALERT)
1331 dbug(1, dprintf("Connected Alert Call_Res"));
1332 if (a->Info_Mask[appl->Id - 1] & 0x200)
1334 /* early B3 connect (CIP mask bit 9) no release after a disc */
1335 add_p(plci, LLI, "\x01\x01");
1337 add_s(plci, CONN_NR, &parms[2]);
1338 add_s(plci, LLC, &parms[4]);
1339 add_ai(plci, &parms[5]);
1340 plci->State = INC_CON_ACCEPT;
1341 sig_req(plci, CALL_RES, 0);
1342 return 1;
1344 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1345 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1346 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
1347 Reject = GET_WORD(parms[0].info);
1348 dbug(1, dprintf("Reject=0x%x", Reject));
1349 if (Reject)
1351 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
1353 if ((Reject & 0xff00) == 0x3400)
1355 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1356 add_p(plci, ESC, esc_t);
1357 add_ai(plci, &parms[5]);
1358 sig_req(plci, REJECT, 0);
1360 else if (Reject == 1 || Reject >= 9)
1362 add_ai(plci, &parms[5]);
1363 sig_req(plci, HANGUP, 0);
1365 else
1367 esc_t[2] = cau_t[(Reject&0x000f)];
1368 add_p(plci, ESC, esc_t);
1369 add_ai(plci, &parms[5]);
1370 sig_req(plci, REJECT, 0);
1372 plci->appl = appl;
1374 else
1376 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1379 else {
1380 plci->appl = appl;
1381 if (Id & EXT_CONTROLLER) {
1382 if (AdvCodecSupport(a, plci, appl, 0)) {
1383 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1384 sig_req(plci, HANGUP, 0);
1385 return 1;
1387 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1389 Info = add_b23(plci, &parms[1]);
1390 if (Info)
1392 dbug(1, dprintf("connect_res(error from add_b23)"));
1393 sig_req(plci, HANGUP, 0);
1394 return 1;
1396 if (plci->adv_nl)
1398 nl_req_ncci(plci, ASSIGN, 0);
1402 else
1404 plci->tel = 0;
1405 if (ch != 2)
1407 Info = add_b23(plci, &parms[1]);
1408 if (Info)
1410 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1411 sig_req(plci, HANGUP, 0);
1412 return 1;
1415 nl_req_ncci(plci, ASSIGN, 0);
1418 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1420 api_save_msg(parms, "wsssss", &plci->saved_msg);
1421 plci->spoofed_msg = CALL_RES;
1422 plci->internal_command = BLOCK_PLCI;
1423 plci->command = 0;
1424 dbug(1, dprintf("Spoof"));
1426 else
1428 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1429 if (a->Info_Mask[appl->Id - 1] & 0x200)
1431 /* early B3 connect (CIP mask bit 9) no release after a disc */
1432 add_p(plci, LLI, "\x01\x01");
1434 add_s(plci, CONN_NR, &parms[2]);
1435 add_s(plci, LLC, &parms[4]);
1436 add_ai(plci, &parms[5]);
1437 plci->State = INC_CON_ACCEPT;
1438 sig_req(plci, CALL_RES, 0);
1441 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1442 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1445 return 1;
1448 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1449 PLCI *plci, APPL *appl, API_PARSE *msg)
1451 dbug(1, dprintf("connect_a_res"));
1452 return false;
1455 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1456 PLCI *plci, APPL *appl, API_PARSE *msg)
1458 word Info;
1459 word i;
1461 dbug(1, dprintf("disconnect_req"));
1463 Info = _WRONG_IDENTIFIER;
1465 if (plci)
1467 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1469 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1470 plci->appl = appl;
1471 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1472 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1473 plci->State = OUTG_DIS_PENDING;
1475 if (plci->Sig.Id && plci->appl)
1477 Info = 0;
1478 if (plci->Sig.Id != 0xff)
1480 if (plci->State != INC_DIS_PENDING)
1482 add_ai(plci, &msg[0]);
1483 sig_req(plci, HANGUP, 0);
1484 plci->State = OUTG_DIS_PENDING;
1485 return 1;
1488 else
1490 if (plci->NL.Id && !plci->nl_remove_id)
1492 mixer_remove(plci);
1493 nl_req_ncci(plci, REMOVE, 0);
1494 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1496 plci->State = INC_DIS_PENDING;
1498 return 1;
1503 if (!appl) return false;
1504 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1505 return false;
1508 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1509 PLCI *plci, APPL *appl, API_PARSE *msg)
1511 dbug(1, dprintf("disconnect_res"));
1512 if (plci)
1514 /* clear ind mask bit, just in case of collsion of */
1515 /* DISCONNECT_IND and CONNECT_RES */
1516 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1517 ncci_free_receive_buffers(plci, 0);
1518 if (plci_remove_check(plci))
1520 return 0;
1522 if (plci->State == INC_DIS_PENDING
1523 || plci->State == SUSPENDING) {
1524 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
1525 if (plci->State != SUSPENDING) plci->State = IDLE;
1526 dbug(1, dprintf("chs=%d", plci->channels));
1527 if (!plci->channels) {
1528 plci_remove(plci);
1533 return 0;
1536 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1537 PLCI *plci, APPL *appl, API_PARSE *parms)
1539 word Info;
1540 byte i;
1542 dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1544 Info = _WRONG_IDENTIFIER;
1545 if (a) {
1546 Info = 0;
1547 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1548 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1549 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1550 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1551 a->Info_Mask[appl->Id - 1] |= 0x10; /* call progression infos */
1554 /* check if external controller listen and switch listen on or off*/
1555 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1556 if (a->profile.Global_Options & ON_BOARD_CODEC) {
1557 dummy_plci.State = IDLE;
1558 a->codec_listen[appl->Id - 1] = &dummy_plci;
1559 a->TelOAD[0] = (byte)(parms[3].length);
1560 for (i = 1; parms[3].length >= i && i < 22; i++) {
1561 a->TelOAD[i] = parms[3].info[i];
1563 a->TelOAD[i] = 0;
1564 a->TelOSA[0] = (byte)(parms[4].length);
1565 for (i = 1; parms[4].length >= i && i < 22; i++) {
1566 a->TelOSA[i] = parms[4].info[i];
1568 a->TelOSA[i] = 0;
1570 else Info = 0x2002; /* wrong controller, codec not supported */
1572 else{ /* clear listen */
1573 a->codec_listen[appl->Id - 1] = (PLCI *)0;
1576 sendf(appl,
1577 _LISTEN_R | CONFIRM,
1579 Number,
1580 "w", Info);
1582 if (a) listen_check(a);
1583 return false;
1586 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1587 PLCI *plci, APPL *appl, API_PARSE *msg)
1589 word i;
1590 API_PARSE *ai;
1591 PLCI *rc_plci = NULL;
1592 API_PARSE ai_parms[5];
1593 word Info = 0;
1595 dbug(1, dprintf("info_req"));
1596 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1598 ai = &msg[1];
1600 if (ai->length)
1602 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1604 dbug(1, dprintf("AddInfo wrong"));
1605 Info = _WRONG_MESSAGE_FORMAT;
1608 if (!a) Info = _WRONG_STATE;
1610 if (!Info && plci)
1611 { /* no fac, with CPN, or KEY */
1612 rc_plci = plci;
1613 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1615 /* overlap sending option */
1616 dbug(1, dprintf("OvlSnd"));
1617 add_s(plci, CPN, &msg[0]);
1618 add_s(plci, KEY, &ai_parms[1]);
1619 sig_req(plci, INFO_REQ, 0);
1620 send_req(plci);
1621 return false;
1624 if (plci->State && ai_parms[2].length)
1626 /* User_Info option */
1627 dbug(1, dprintf("UUI"));
1628 add_s(plci, UUI, &ai_parms[2]);
1629 sig_req(plci, USER_DATA, 0);
1631 else if (plci->State && ai_parms[3].length)
1633 /* Facility option */
1634 dbug(1, dprintf("FAC"));
1635 add_s(plci, CPN, &msg[0]);
1636 add_ai(plci, &msg[1]);
1637 sig_req(plci, FACILITY_REQ, 0);
1639 else
1641 Info = _WRONG_STATE;
1644 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1646 /* NCR_Facility option -> send UUI and Keypad too */
1647 dbug(1, dprintf("NCR_FAC"));
1648 if ((i = get_plci(a)))
1650 rc_plci = &a->plci[i - 1];
1651 appl->NullCREnable = true;
1652 rc_plci->internal_command = C_NCR_FAC_REQ;
1653 rc_plci->appl = appl;
1654 add_p(rc_plci, CAI, "\x01\x80");
1655 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1656 sig_req(rc_plci, ASSIGN, DSIG_ID);
1657 send_req(rc_plci);
1659 else
1661 Info = _OUT_OF_PLCI;
1664 if (!Info)
1666 add_s(rc_plci, CPN, &msg[0]);
1667 add_ai(rc_plci, &msg[1]);
1668 sig_req(rc_plci, NCR_FACILITY, 0);
1669 send_req(rc_plci);
1670 return false;
1671 /* for application controlled supplementary services */
1675 if (!rc_plci)
1677 Info = _WRONG_MESSAGE_FORMAT;
1680 if (!Info)
1682 send_req(rc_plci);
1684 else
1685 { /* appl is not assigned to a PLCI or error condition */
1686 dbug(1, dprintf("localInfoCon"));
1687 sendf(appl,
1688 _INFO_R | CONFIRM,
1690 Number,
1691 "w", Info);
1693 return false;
1696 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1697 PLCI *plci, APPL *appl, API_PARSE *msg)
1699 dbug(1, dprintf("info_res"));
1700 return false;
1703 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1704 PLCI *plci, APPL *appl, API_PARSE *msg)
1706 word Info;
1707 byte ret;
1709 dbug(1, dprintf("alert_req"));
1711 Info = _WRONG_IDENTIFIER;
1712 ret = false;
1713 if (plci) {
1714 Info = _ALERT_IGNORED;
1715 if (plci->State != INC_CON_ALERT) {
1716 Info = _WRONG_STATE;
1717 if (plci->State == INC_CON_PENDING) {
1718 Info = 0;
1719 plci->State = INC_CON_ALERT;
1720 add_ai(plci, &msg[0]);
1721 sig_req(plci, CALL_ALERT, 0);
1722 ret = 1;
1726 sendf(appl,
1727 _ALERT_R | CONFIRM,
1729 Number,
1730 "w", Info);
1731 return ret;
1734 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1735 PLCI *plci, APPL *appl, API_PARSE *msg)
1737 word Info = 0;
1738 word i = 0;
1740 word selector;
1741 word SSreq;
1742 long relatedPLCIvalue;
1743 DIVA_CAPI_ADAPTER *relatedadapter;
1744 byte *SSparms = "";
1745 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1746 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1747 API_PARSE *parms;
1748 API_PARSE ss_parms[11];
1749 PLCI *rplci;
1750 byte cai[15];
1751 dword d;
1752 API_PARSE dummy;
1754 dbug(1, dprintf("facility_req"));
1755 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1757 parms = &msg[1];
1759 if (!a)
1761 dbug(1, dprintf("wrong Ctrl"));
1762 Info = _WRONG_IDENTIFIER;
1765 selector = GET_WORD(msg[0].info);
1767 if (!Info)
1769 switch (selector)
1771 case SELECTOR_HANDSET:
1772 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1773 break;
1775 case SELECTOR_SU_SERV:
1776 if (!msg[1].length)
1778 Info = _WRONG_MESSAGE_FORMAT;
1779 break;
1781 SSreq = GET_WORD(&(msg[1].info[1]));
1782 PUT_WORD(&RCparms[1], SSreq);
1783 SSparms = RCparms;
1784 switch (SSreq)
1786 case S_GET_SUPPORTED_SERVICES:
1787 if ((i = get_plci(a)))
1789 rplci = &a->plci[i - 1];
1790 rplci->appl = appl;
1791 add_p(rplci, CAI, "\x01\x80");
1792 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1793 sig_req(rplci, ASSIGN, DSIG_ID);
1794 send_req(rplci);
1796 else
1798 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1799 SSparms = (byte *)SSstruct;
1800 break;
1802 rplci->internal_command = GETSERV_REQ_PEND;
1803 rplci->number = Number;
1804 rplci->appl = appl;
1805 sig_req(rplci, S_SUPPORTED, 0);
1806 send_req(rplci);
1807 return false;
1808 break;
1810 case S_LISTEN:
1811 if (parms->length == 7)
1813 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1815 dbug(1, dprintf("format wrong"));
1816 Info = _WRONG_MESSAGE_FORMAT;
1817 break;
1820 else
1822 Info = _WRONG_MESSAGE_FORMAT;
1823 break;
1825 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1826 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1828 if ((i = get_plci(a)))
1830 rplci = &a->plci[i - 1];
1831 rplci->appl = appl;
1832 add_p(rplci, CAI, "\x01\x80");
1833 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1834 sig_req(rplci, ASSIGN, DSIG_ID);
1835 send_req(rplci);
1837 else
1839 break;
1841 rplci->internal_command = GET_MWI_STATE;
1842 rplci->number = Number;
1843 sig_req(rplci, MWI_POLL, 0);
1844 send_req(rplci);
1846 break;
1848 case S_HOLD:
1849 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1850 if (plci && plci->State && plci->SuppState == IDLE)
1852 plci->SuppState = HOLD_REQUEST;
1853 plci->command = C_HOLD_REQ;
1854 add_s(plci, CAI, &ss_parms[1]);
1855 sig_req(plci, CALL_HOLD, 0);
1856 send_req(plci);
1857 return false;
1859 else Info = 0x3010; /* wrong state */
1860 break;
1861 case S_RETRIEVE:
1862 if (plci && plci->State && plci->SuppState == CALL_HELD)
1864 if (Id & EXT_CONTROLLER)
1866 if (AdvCodecSupport(a, plci, appl, 0))
1868 Info = 0x3010; /* wrong state */
1869 break;
1872 else plci->tel = 0;
1874 plci->SuppState = RETRIEVE_REQUEST;
1875 plci->command = C_RETRIEVE_REQ;
1876 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1878 plci->spoofed_msg = CALL_RETRIEVE;
1879 plci->internal_command = BLOCK_PLCI;
1880 plci->command = 0;
1881 dbug(1, dprintf("Spoof"));
1882 return false;
1884 else
1886 sig_req(plci, CALL_RETRIEVE, 0);
1887 send_req(plci);
1888 return false;
1891 else Info = 0x3010; /* wrong state */
1892 break;
1893 case S_SUSPEND:
1894 if (parms->length)
1896 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1898 dbug(1, dprintf("format wrong"));
1899 Info = _WRONG_MESSAGE_FORMAT;
1900 break;
1903 if (plci && plci->State)
1905 add_s(plci, CAI, &ss_parms[2]);
1906 plci->command = SUSPEND_REQ;
1907 sig_req(plci, SUSPEND, 0);
1908 plci->State = SUSPENDING;
1909 send_req(plci);
1911 else Info = 0x3010; /* wrong state */
1912 break;
1914 case S_RESUME:
1915 if (!(i = get_plci(a)))
1917 Info = _OUT_OF_PLCI;
1918 break;
1920 rplci = &a->plci[i - 1];
1921 rplci->appl = appl;
1922 rplci->number = Number;
1923 rplci->tel = 0;
1924 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1925 /* check 'external controller' bit for codec support */
1926 if (Id & EXT_CONTROLLER)
1928 if (AdvCodecSupport(a, rplci, appl, 0))
1930 rplci->Id = 0;
1931 Info = 0x300A;
1932 break;
1935 if (parms->length)
1937 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1939 dbug(1, dprintf("format wrong"));
1940 rplci->Id = 0;
1941 Info = _WRONG_MESSAGE_FORMAT;
1942 break;
1945 dummy.length = 0;
1946 dummy.info = "\x00";
1947 add_b1(rplci, &dummy, 0, 0);
1948 if (a->Info_Mask[appl->Id - 1] & 0x200)
1950 /* early B3 connect (CIP mask bit 9) no release after a disc */
1951 add_p(rplci, LLI, "\x01\x01");
1953 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1954 sig_req(rplci, ASSIGN, DSIG_ID);
1955 send_req(rplci);
1956 add_s(rplci, CAI, &ss_parms[2]);
1957 rplci->command = RESUME_REQ;
1958 sig_req(rplci, RESUME, 0);
1959 rplci->State = RESUMING;
1960 send_req(rplci);
1961 break;
1963 case S_CONF_BEGIN: /* Request */
1964 case S_CONF_DROP:
1965 case S_CONF_ISOLATE:
1966 case S_CONF_REATTACH:
1967 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1969 dbug(1, dprintf("format wrong"));
1970 Info = _WRONG_MESSAGE_FORMAT;
1971 break;
1973 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
1975 d = GET_DWORD(ss_parms[2].info);
1976 if (d >= 0x80)
1978 dbug(1, dprintf("format wrong"));
1979 Info = _WRONG_MESSAGE_FORMAT;
1980 break;
1982 plci->ptyState = (byte)SSreq;
1983 plci->command = 0;
1984 cai[0] = 2;
1985 switch (SSreq)
1987 case S_CONF_BEGIN:
1988 cai[1] = CONF_BEGIN;
1989 plci->internal_command = CONF_BEGIN_REQ_PEND;
1990 break;
1991 case S_CONF_DROP:
1992 cai[1] = CONF_DROP;
1993 plci->internal_command = CONF_DROP_REQ_PEND;
1994 break;
1995 case S_CONF_ISOLATE:
1996 cai[1] = CONF_ISOLATE;
1997 plci->internal_command = CONF_ISOLATE_REQ_PEND;
1998 break;
1999 case S_CONF_REATTACH:
2000 cai[1] = CONF_REATTACH;
2001 plci->internal_command = CONF_REATTACH_REQ_PEND;
2002 break;
2004 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2005 add_p(plci, CAI, cai);
2006 sig_req(plci, S_SERVICE, 0);
2007 send_req(plci);
2008 return false;
2010 else Info = 0x3010; /* wrong state */
2011 break;
2013 case S_ECT:
2014 case S_3PTY_BEGIN:
2015 case S_3PTY_END:
2016 case S_CONF_ADD:
2017 if (parms->length == 7)
2019 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2021 dbug(1, dprintf("format wrong"));
2022 Info = _WRONG_MESSAGE_FORMAT;
2023 break;
2026 else if (parms->length == 8) /* workaround for the T-View-S */
2028 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2030 dbug(1, dprintf("format wrong"));
2031 Info = _WRONG_MESSAGE_FORMAT;
2032 break;
2035 else
2037 Info = _WRONG_MESSAGE_FORMAT;
2038 break;
2040 if (!msg[1].length)
2042 Info = _WRONG_MESSAGE_FORMAT;
2043 break;
2045 if (!plci)
2047 Info = _WRONG_IDENTIFIER;
2048 break;
2050 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2051 relatedPLCIvalue &= 0x0000FFFF;
2052 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2053 /* controller starts with 0 up to (max_adapter - 1) */
2054 if (((relatedPLCIvalue & 0x7f) == 0)
2055 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2056 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2058 if (SSreq == S_3PTY_END)
2060 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2061 rplci = plci;
2063 else
2065 Info = 0x3010; /* wrong state */
2066 break;
2069 else
2071 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2072 relatedPLCIvalue >>= 8;
2073 /* find PLCI PTR*/
2074 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2076 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2078 rplci = &relatedadapter->plci[i];
2081 if (!rplci || !relatedPLCIvalue)
2083 if (SSreq == S_3PTY_END)
2085 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2086 rplci = plci;
2088 else
2090 Info = 0x3010; /* wrong state */
2091 break;
2096 dbug(1, dprintf("rplci:%x", rplci));
2097 dbug(1, dprintf("plci:%x", plci));
2098 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2099 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2100 dbug(1, dprintf("SSreq:%x", SSreq));
2101 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2102 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2103 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2105 /* send PTY/ECT req, cannot check all states because of US stuff */
2106 if (!rplci->internal_command && rplci->appl)
2108 plci->command = 0;
2109 rplci->relatedPTYPLCI = plci;
2110 plci->relatedPTYPLCI = rplci;
2111 rplci->ptyState = (byte)SSreq;
2112 if (SSreq == S_ECT)
2114 rplci->internal_command = ECT_REQ_PEND;
2115 cai[1] = ECT_EXECUTE;
2117 rplci->vswitchstate = 0;
2118 rplci->vsprot = 0;
2119 rplci->vsprotdialect = 0;
2120 plci->vswitchstate = 0;
2121 plci->vsprot = 0;
2122 plci->vsprotdialect = 0;
2125 else if (SSreq == S_CONF_ADD)
2127 rplci->internal_command = CONF_ADD_REQ_PEND;
2128 cai[1] = CONF_ADD;
2130 else
2132 rplci->internal_command = PTY_REQ_PEND;
2133 cai[1] = (byte)(SSreq - 3);
2135 rplci->number = Number;
2136 if (plci != rplci) /* explicit invocation */
2138 cai[0] = 2;
2139 cai[2] = plci->Sig.Id;
2140 dbug(1, dprintf("explicit invocation"));
2142 else
2144 dbug(1, dprintf("implicit invocation"));
2145 cai[0] = 1;
2147 add_p(rplci, CAI, cai);
2148 sig_req(rplci, S_SERVICE, 0);
2149 send_req(rplci);
2150 return false;
2152 else
2154 dbug(0, dprintf("Wrong line"));
2155 Info = 0x3010; /* wrong state */
2156 break;
2158 break;
2160 case S_CALL_DEFLECTION:
2161 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2163 dbug(1, dprintf("format wrong"));
2164 Info = _WRONG_MESSAGE_FORMAT;
2165 break;
2167 if (!plci)
2169 Info = _WRONG_IDENTIFIER;
2170 break;
2172 /* reuse unused screening indicator */
2173 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2174 plci->command = 0;
2175 plci->internal_command = CD_REQ_PEND;
2176 appl->CDEnable = true;
2177 cai[0] = 1;
2178 cai[1] = CALL_DEFLECTION;
2179 add_p(plci, CAI, cai);
2180 add_p(plci, CPN, ss_parms[3].info);
2181 sig_req(plci, S_SERVICE, 0);
2182 send_req(plci);
2183 return false;
2184 break;
2186 case S_CALL_FORWARDING_START:
2187 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2189 dbug(1, dprintf("format wrong"));
2190 Info = _WRONG_MESSAGE_FORMAT;
2191 break;
2194 if ((i = get_plci(a)))
2196 rplci = &a->plci[i - 1];
2197 rplci->appl = appl;
2198 add_p(rplci, CAI, "\x01\x80");
2199 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2200 sig_req(rplci, ASSIGN, DSIG_ID);
2201 send_req(rplci);
2203 else
2205 Info = _OUT_OF_PLCI;
2206 break;
2209 /* reuse unused screening indicator */
2210 rplci->internal_command = CF_START_PEND;
2211 rplci->appl = appl;
2212 rplci->number = Number;
2213 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2214 cai[0] = 2;
2215 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2216 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2217 add_p(rplci, CAI, cai);
2218 add_p(rplci, OAD, ss_parms[5].info);
2219 add_p(rplci, CPN, ss_parms[6].info);
2220 sig_req(rplci, S_SERVICE, 0);
2221 send_req(rplci);
2222 return false;
2223 break;
2225 case S_INTERROGATE_DIVERSION:
2226 case S_INTERROGATE_NUMBERS:
2227 case S_CALL_FORWARDING_STOP:
2228 case S_CCBS_REQUEST:
2229 case S_CCBS_DEACTIVATE:
2230 case S_CCBS_INTERROGATE:
2231 switch (SSreq)
2233 case S_INTERROGATE_NUMBERS:
2234 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2236 dbug(0, dprintf("format wrong"));
2237 Info = _WRONG_MESSAGE_FORMAT;
2239 break;
2240 case S_CCBS_REQUEST:
2241 case S_CCBS_DEACTIVATE:
2242 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2244 dbug(0, dprintf("format wrong"));
2245 Info = _WRONG_MESSAGE_FORMAT;
2247 break;
2248 case S_CCBS_INTERROGATE:
2249 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2251 dbug(0, dprintf("format wrong"));
2252 Info = _WRONG_MESSAGE_FORMAT;
2254 break;
2255 default:
2256 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2258 dbug(0, dprintf("format wrong"));
2259 Info = _WRONG_MESSAGE_FORMAT;
2260 break;
2262 break;
2265 if (Info) break;
2266 if ((i = get_plci(a)))
2268 rplci = &a->plci[i - 1];
2269 switch (SSreq)
2271 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2272 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2273 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2274 break;
2275 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2276 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2277 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2278 break;
2279 case S_CALL_FORWARDING_STOP:
2280 rplci->internal_command = CF_STOP_PEND;
2281 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2282 break;
2283 case S_CCBS_REQUEST:
2284 cai[1] = CCBS_REQUEST;
2285 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2286 break;
2287 case S_CCBS_DEACTIVATE:
2288 cai[1] = CCBS_DEACTIVATE;
2289 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2290 break;
2291 case S_CCBS_INTERROGATE:
2292 cai[1] = CCBS_INTERROGATE;
2293 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2294 break;
2295 default:
2296 cai[1] = 0;
2297 break;
2299 rplci->appl = appl;
2300 rplci->number = Number;
2301 add_p(rplci, CAI, "\x01\x80");
2302 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2303 sig_req(rplci, ASSIGN, DSIG_ID);
2304 send_req(rplci);
2306 else
2308 Info = _OUT_OF_PLCI;
2309 break;
2312 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2313 switch (SSreq)
2315 case S_INTERROGATE_NUMBERS:
2316 cai[0] = 1;
2317 add_p(rplci, CAI, cai);
2318 break;
2319 case S_CCBS_REQUEST:
2320 case S_CCBS_DEACTIVATE:
2321 cai[0] = 3;
2322 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2323 add_p(rplci, CAI, cai);
2324 break;
2325 case S_CCBS_INTERROGATE:
2326 cai[0] = 3;
2327 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2328 add_p(rplci, CAI, cai);
2329 add_p(rplci, OAD, ss_parms[4].info);
2330 break;
2331 default:
2332 cai[0] = 2;
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 break;
2339 sig_req(rplci, S_SERVICE, 0);
2340 send_req(rplci);
2341 return false;
2342 break;
2344 case S_MWI_ACTIVATE:
2345 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2347 dbug(1, dprintf("format wrong"));
2348 Info = _WRONG_MESSAGE_FORMAT;
2349 break;
2351 if (!plci)
2353 if ((i = get_plci(a)))
2355 rplci = &a->plci[i - 1];
2356 rplci->appl = appl;
2357 rplci->cr_enquiry = true;
2358 add_p(rplci, CAI, "\x01\x80");
2359 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2360 sig_req(rplci, ASSIGN, DSIG_ID);
2361 send_req(rplci);
2363 else
2365 Info = _OUT_OF_PLCI;
2366 break;
2369 else
2371 rplci = plci;
2372 rplci->cr_enquiry = false;
2375 rplci->command = 0;
2376 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2377 rplci->appl = appl;
2378 rplci->number = Number;
2380 cai[0] = 13;
2381 cai[1] = ACTIVATION_MWI; /* Function */
2382 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2383 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2384 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2385 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2386 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2387 add_p(rplci, CAI, cai);
2388 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2389 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2390 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2391 add_p(rplci, UID, ss_parms[10].info); /* Time */
2392 sig_req(rplci, S_SERVICE, 0);
2393 send_req(rplci);
2394 return false;
2396 case S_MWI_DEACTIVATE:
2397 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2399 dbug(1, dprintf("format wrong"));
2400 Info = _WRONG_MESSAGE_FORMAT;
2401 break;
2403 if (!plci)
2405 if ((i = get_plci(a)))
2407 rplci = &a->plci[i - 1];
2408 rplci->appl = appl;
2409 rplci->cr_enquiry = true;
2410 add_p(rplci, CAI, "\x01\x80");
2411 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2412 sig_req(rplci, ASSIGN, DSIG_ID);
2413 send_req(rplci);
2415 else
2417 Info = _OUT_OF_PLCI;
2418 break;
2421 else
2423 rplci = plci;
2424 rplci->cr_enquiry = false;
2427 rplci->command = 0;
2428 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2429 rplci->appl = appl;
2430 rplci->number = Number;
2432 cai[0] = 5;
2433 cai[1] = DEACTIVATION_MWI; /* Function */
2434 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2435 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2436 add_p(rplci, CAI, cai);
2437 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2438 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2439 sig_req(rplci, S_SERVICE, 0);
2440 send_req(rplci);
2441 return false;
2443 default:
2444 Info = 0x300E; /* not supported */
2445 break;
2447 break; /* case SELECTOR_SU_SERV: end */
2450 case SELECTOR_DTMF:
2451 return (dtmf_request(Id, Number, a, plci, appl, msg));
2455 case SELECTOR_LINE_INTERCONNECT:
2456 return (mixer_request(Id, Number, a, plci, appl, msg));
2460 case PRIV_SELECTOR_ECHO_CANCELLER:
2461 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2462 return (ec_request(Id, Number, a, plci, appl, msg));
2464 case SELECTOR_ECHO_CANCELLER:
2465 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2466 return (ec_request(Id, Number, a, plci, appl, msg));
2469 case SELECTOR_V42BIS:
2470 default:
2471 Info = _FACILITY_NOT_SUPPORTED;
2472 break;
2473 } /* end of switch (selector) */
2476 dbug(1, dprintf("SendFacRc"));
2477 sendf(appl,
2478 _FACILITY_R | CONFIRM,
2480 Number,
2481 "wws", Info, selector, SSparms);
2482 return false;
2485 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2486 PLCI *plci, APPL *appl, API_PARSE *msg)
2488 dbug(1, dprintf("facility_res"));
2489 return false;
2492 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2493 PLCI *plci, APPL *appl, API_PARSE *parms)
2495 word Info = 0;
2496 byte req;
2497 byte len;
2498 word w;
2499 word fax_control_bits, fax_feature_bits, fax_info_change;
2500 API_PARSE *ncpi;
2501 byte pvc[2];
2503 API_PARSE fax_parms[9];
2504 word i;
2507 dbug(1, dprintf("connect_b3_req"));
2508 if (plci)
2510 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2511 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2513 Info = _WRONG_STATE;
2515 else
2517 /* local reply if assign unsuccessful
2518 or B3 protocol allows only one layer 3 connection
2519 and already connected
2520 or B2 protocol not any LAPD
2521 and connect_b3_req contradicts originate/answer direction */
2522 if (!plci->NL.Id
2523 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2524 && ((plci->channels != 0)
2525 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2526 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2528 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2529 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2530 Info = _WRONG_STATE;
2531 sendf(appl,
2532 _CONNECT_B3_R | CONFIRM,
2534 Number,
2535 "w", Info);
2536 return false;
2538 plci->requested_options_conn = 0;
2540 req = N_CONNECT;
2541 ncpi = &parms[0];
2542 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2544 if (ncpi->length > 2)
2546 /* check for PVC */
2547 if (ncpi->info[2] || ncpi->info[3])
2549 pvc[0] = ncpi->info[3];
2550 pvc[1] = ncpi->info[2];
2551 add_d(plci, 2, pvc);
2552 req = N_RESET;
2554 else
2556 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2557 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2561 else if (plci->B3_prot == 5)
2563 if (plci->NL.Id && !plci->nl_remove_id)
2565 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2566 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2567 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2568 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2570 len = offsetof(T30_INFO, universal_6);
2571 fax_info_change = false;
2572 if (ncpi->length >= 4)
2574 w = GET_WORD(&ncpi->info[3]);
2575 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2577 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2578 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2579 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2580 fax_info_change = true;
2582 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2583 if (w & 0x0002) /* Fax-polling request */
2584 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2585 if ((w & 0x0004) /* Request to send / poll another document */
2586 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2588 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2590 if (ncpi->length >= 6)
2592 w = GET_WORD(&ncpi->info[5]);
2593 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2595 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2596 fax_info_change = true;
2599 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2600 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2602 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2604 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2605 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2607 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2609 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2610 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2611 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2612 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2614 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2615 Info = _WRONG_MESSAGE_FORMAT;
2616 else
2618 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2619 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2621 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2622 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2623 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2625 w = fax_parms[4].length;
2626 if (w > 20)
2627 w = 20;
2628 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2629 for (i = 0; i < w; i++)
2630 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2631 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2632 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2633 w = fax_parms[5].length;
2634 if (w > 20)
2635 w = 20;
2636 plci->fax_connect_info_buffer[len++] = (byte) w;
2637 for (i = 0; i < w; i++)
2638 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2639 w = fax_parms[6].length;
2640 if (w > 20)
2641 w = 20;
2642 plci->fax_connect_info_buffer[len++] = (byte) w;
2643 for (i = 0; i < w; i++)
2644 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2645 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2646 & (1L << PRIVATE_FAX_NONSTANDARD))
2648 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2650 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2651 plci->fax_connect_info_buffer[len++] = 0;
2653 else
2655 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2656 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2657 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2658 for (i = 0; i < fax_parms[7].length; i++)
2659 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2664 else
2666 len = offsetof(T30_INFO, universal_6);
2668 fax_info_change = true;
2671 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2673 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2674 fax_info_change = true;
2677 if (Info == GOOD)
2679 plci->fax_connect_info_length = len;
2680 if (fax_info_change)
2682 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2684 start_internal_command(Id, plci, fax_connect_info_command);
2685 return false;
2687 else
2689 start_internal_command(Id, plci, fax_adjust_b23_command);
2690 return false;
2695 else Info = _WRONG_STATE;
2697 else Info = _WRONG_STATE;
2700 else if (plci->B3_prot == B3_RTP)
2702 plci->internal_req_buffer[0] = ncpi->length + 1;
2703 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2704 for (w = 0; w < ncpi->length; w++)
2705 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2706 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2707 return false;
2710 if (!Info)
2712 nl_req_ncci(plci, req, 0);
2713 return 1;
2717 else Info = _WRONG_IDENTIFIER;
2719 sendf(appl,
2720 _CONNECT_B3_R | CONFIRM,
2722 Number,
2723 "w", Info);
2724 return false;
2727 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2728 PLCI *plci, APPL *appl, API_PARSE *parms)
2730 word ncci;
2731 API_PARSE *ncpi;
2732 byte req;
2734 word w;
2737 API_PARSE fax_parms[9];
2738 word i;
2739 byte len;
2742 dbug(1, dprintf("connect_b3_res"));
2744 ncci = (word)(Id >> 16);
2745 if (plci && ncci) {
2746 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2747 if (GET_WORD(&parms[0].info[0]) != 0)
2749 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2750 channel_request_xon(plci, a->ncci_ch[ncci]);
2751 channel_xmit_xon(plci);
2752 cleanup_ncci_data(plci, ncci);
2753 nl_req_ncci(plci, N_DISC, (byte)ncci);
2754 return 1;
2756 a->ncci_state[ncci] = INC_ACT_PENDING;
2758 req = N_CONNECT_ACK;
2759 ncpi = &parms[1];
2760 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2763 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2764 & (1L << PRIVATE_FAX_NONSTANDARD))
2766 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2767 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2768 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2770 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2771 if (plci->fax_connect_info_length < len)
2773 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2774 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2776 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2778 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2780 else
2782 if (plci->fax_connect_info_length <= len)
2783 plci->fax_connect_info_buffer[len] = 0;
2784 len += 1 + plci->fax_connect_info_buffer[len];
2785 if (plci->fax_connect_info_length <= len)
2786 plci->fax_connect_info_buffer[len] = 0;
2787 len += 1 + plci->fax_connect_info_buffer[len];
2788 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2789 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2790 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2791 for (i = 0; i < fax_parms[7].length; i++)
2792 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2794 plci->fax_connect_info_length = len;
2795 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2796 start_internal_command(Id, plci, fax_connect_ack_command);
2797 return false;
2801 nl_req_ncci(plci, req, (byte)ncci);
2802 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2803 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2805 if (plci->B3_prot == 4)
2806 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2807 else
2808 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2809 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2813 else if (plci->B3_prot == B3_RTP)
2815 plci->internal_req_buffer[0] = ncpi->length + 1;
2816 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2817 for (w = 0; w < ncpi->length; w++)
2818 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2819 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2820 return false;
2823 else
2825 if (ncpi->length > 2) {
2826 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2827 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2829 nl_req_ncci(plci, req, (byte)ncci);
2830 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2831 if (plci->adjust_b_restore)
2833 plci->adjust_b_restore = false;
2834 start_internal_command(Id, plci, adjust_b_restore);
2837 return 1;
2840 return false;
2843 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2844 PLCI *plci, APPL *appl, API_PARSE *parms)
2846 word ncci;
2848 ncci = (word)(Id >> 16);
2849 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2851 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2852 && (plci->State != OUTG_DIS_PENDING))
2854 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2855 a->ncci_state[ncci] = CONNECTED;
2856 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2857 channel_request_xon(plci, a->ncci_ch[ncci]);
2858 channel_xmit_xon(plci);
2861 return false;
2864 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2865 PLCI *plci, APPL *appl, API_PARSE *parms)
2867 word Info;
2868 word ncci;
2869 API_PARSE *ncpi;
2871 dbug(1, dprintf("disconnect_b3_req"));
2873 Info = _WRONG_IDENTIFIER;
2874 ncci = (word)(Id >> 16);
2875 if (plci && ncci)
2877 Info = _WRONG_STATE;
2878 if ((a->ncci_state[ncci] == CONNECTED)
2879 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2880 || (a->ncci_state[ncci] == INC_CON_PENDING)
2881 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2883 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2884 channel_request_xon(plci, a->ncci_ch[ncci]);
2885 channel_xmit_xon(plci);
2887 if (a->ncci[ncci].data_pending
2888 && ((plci->B3_prot == B3_TRANSPARENT)
2889 || (plci->B3_prot == B3_T30)
2890 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
2892 plci->send_disc = (byte)ncci;
2893 plci->command = 0;
2894 return false;
2896 else
2898 cleanup_ncci_data(plci, ncci);
2900 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2902 ncpi = &parms[0];
2903 if (ncpi->length > 3)
2905 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
2908 nl_req_ncci(plci, N_DISC, (byte)ncci);
2910 return 1;
2913 sendf(appl,
2914 _DISCONNECT_B3_R | CONFIRM,
2916 Number,
2917 "w", Info);
2918 return false;
2921 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2922 PLCI *plci, APPL *appl, API_PARSE *parms)
2924 word ncci;
2925 word i;
2927 ncci = (word)(Id >> 16);
2928 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
2929 if (plci && ncci) {
2930 plci->requested_options_conn = 0;
2931 plci->fax_connect_info_length = 0;
2932 plci->ncpi_state = 0x00;
2933 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2934 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
2936 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
2938 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
2939 if (i < MAX_CHANNELS_PER_PLCI) {
2940 if (plci->channels)plci->channels--;
2941 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
2942 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
2944 ncci_free_receive_buffers(plci, ncci);
2946 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
2947 if (plci->State == SUSPENDING) {
2948 sendf(plci->appl,
2949 _FACILITY_I,
2950 Id & 0xffffL,
2952 "ws", (word)3, "\x03\x04\x00\x00");
2953 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
2955 plci_remove(plci);
2956 plci->State = IDLE;
2959 else
2961 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
2962 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
2963 && (a->ncci_state[ncci] == INC_DIS_PENDING))
2965 ncci_free_receive_buffers(plci, ncci);
2967 nl_req_ncci(plci, N_EDATA, (byte)ncci);
2969 plci->adapter->ncci_state[ncci] = IDLE;
2970 start_internal_command(Id, plci, fax_disconnect_command);
2971 return 1;
2975 return false;
2978 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2979 PLCI *plci, APPL *appl, API_PARSE *parms)
2981 NCCI *ncci_ptr;
2982 DATA_B3_DESC *data;
2983 word Info;
2984 word ncci;
2985 word i;
2987 dbug(1, dprintf("data_b3_req"));
2989 Info = _WRONG_IDENTIFIER;
2990 ncci = (word)(Id >> 16);
2991 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
2993 if (plci && ncci)
2995 Info = _WRONG_STATE;
2996 if ((a->ncci_state[ncci] == CONNECTED)
2997 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2999 /* queue data */
3000 ncci_ptr = &(a->ncci[ncci]);
3001 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3002 if (i >= MAX_DATA_B3)
3003 i -= MAX_DATA_B3;
3004 data = &(ncci_ptr->DBuffer[i]);
3005 data->Number = Number;
3006 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3007 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3010 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3013 else
3014 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3015 data->Length = GET_WORD(parms[1].info);
3016 data->Handle = GET_WORD(parms[2].info);
3017 data->Flags = GET_WORD(parms[3].info);
3018 (ncci_ptr->data_pending)++;
3020 /* check for delivery confirmation */
3021 if (data->Flags & 0x0004)
3023 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3024 if (i >= MAX_DATA_ACK)
3025 i -= MAX_DATA_ACK;
3026 ncci_ptr->DataAck[i].Number = data->Number;
3027 ncci_ptr->DataAck[i].Handle = data->Handle;
3028 (ncci_ptr->data_ack_pending)++;
3031 send_data(plci);
3032 return false;
3035 if (appl)
3037 if (plci)
3039 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3040 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3043 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3047 sendf(appl,
3048 _DATA_B3_R | CONFIRM,
3050 Number,
3051 "ww", GET_WORD(parms[2].info), Info);
3053 return false;
3056 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3057 PLCI *plci, APPL *appl, API_PARSE *parms)
3059 word n;
3060 word ncci;
3061 word NCCIcode;
3063 dbug(1, dprintf("data_b3_res"));
3065 ncci = (word)(Id >> 16);
3066 if (plci && ncci) {
3067 n = GET_WORD(parms[0].info);
3068 dbug(1, dprintf("free(%d)", n));
3069 NCCIcode = ncci | (((word) a->Id) << 8);
3070 if (n < appl->MaxBuffer &&
3071 appl->DataNCCI[n] == NCCIcode &&
3072 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3073 dbug(1, dprintf("found"));
3074 appl->DataNCCI[n] = 0;
3076 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3077 channel_request_xon(plci, a->ncci_ch[ncci]);
3079 channel_xmit_xon(plci);
3081 if (appl->DataFlags[n] & 4) {
3082 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3083 return 1;
3087 return false;
3090 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3091 PLCI *plci, APPL *appl, API_PARSE *parms)
3093 word Info;
3094 word ncci;
3096 dbug(1, dprintf("reset_b3_req"));
3098 Info = _WRONG_IDENTIFIER;
3099 ncci = (word)(Id >> 16);
3100 if (plci && ncci)
3102 Info = _WRONG_STATE;
3103 switch (plci->B3_prot)
3105 case B3_ISO8208:
3106 case B3_X25_DCE:
3107 if (a->ncci_state[ncci] == CONNECTED)
3109 nl_req_ncci(plci, N_RESET, (byte)ncci);
3110 send_req(plci);
3111 Info = GOOD;
3113 break;
3114 case B3_TRANSPARENT:
3115 if (a->ncci_state[ncci] == CONNECTED)
3117 start_internal_command(Id, plci, reset_b3_command);
3118 Info = GOOD;
3120 break;
3123 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3124 sendf(appl,
3125 _RESET_B3_R | CONFIRM,
3127 Number,
3128 "w", Info);
3129 return false;
3132 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3133 PLCI *plci, APPL *appl, API_PARSE *parms)
3135 word ncci;
3137 dbug(1, dprintf("reset_b3_res"));
3139 ncci = (word)(Id >> 16);
3140 if (plci && ncci) {
3141 switch (plci->B3_prot)
3143 case B3_ISO8208:
3144 case B3_X25_DCE:
3145 if (a->ncci_state[ncci] == INC_RES_PENDING)
3147 a->ncci_state[ncci] = CONNECTED;
3148 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3149 return true;
3151 break;
3154 return false;
3157 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3158 PLCI *plci, APPL *appl, API_PARSE *parms)
3160 word ncci;
3161 API_PARSE *ncpi;
3162 byte req;
3164 dbug(1, dprintf("connect_b3_t90_a_res"));
3166 ncci = (word)(Id >> 16);
3167 if (plci && ncci) {
3168 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3169 a->ncci_state[ncci] = CONNECTED;
3171 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3172 a->ncci_state[ncci] = CONNECTED;
3174 req = N_CONNECT_ACK;
3176 /* parms[0]==0 for CAPI original message definition! */
3177 if (parms[0].info) {
3178 ncpi = &parms[1];
3179 if (ncpi->length > 2) {
3180 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3181 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3184 nl_req_ncci(plci, req, (byte)ncci);
3185 return 1;
3188 return false;
3192 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3193 PLCI *plci, APPL *appl, API_PARSE *msg)
3195 word Info = 0;
3196 word i;
3197 byte tel;
3198 API_PARSE bp_parms[7];
3200 if (!plci || !msg)
3202 Info = _WRONG_IDENTIFIER;
3204 else
3206 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3207 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3208 dbug(1, dprintf("PlciState=0x%x", plci->State));
3209 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3211 /* check if no channel is open, no B3 connected only */
3212 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3213 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3215 Info = _WRONG_STATE;
3217 /* check message format and fill bp_parms pointer */
3218 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3220 Info = _WRONG_MESSAGE_FORMAT;
3222 else
3224 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3225 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3226 if (Id & EXT_CONTROLLER)
3228 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3229 return 0;
3231 plci->State = INC_CON_CONNECTED_ALERT;
3232 plci->appl = appl;
3233 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
3234 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
3235 /* disconnect the other appls its quasi a connect */
3236 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
3237 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3240 api_save_msg(msg, "s", &plci->saved_msg);
3241 tel = plci->tel;
3242 if (Id & EXT_CONTROLLER)
3244 if (tel) /* external controller in use by this PLCI */
3246 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3248 dbug(1, dprintf("Ext_Ctrl in use 1"));
3249 Info = _WRONG_STATE;
3252 else /* external controller NOT in use by this PLCI ? */
3254 if (a->AdvSignalPLCI)
3256 dbug(1, dprintf("Ext_Ctrl in use 2"));
3257 Info = _WRONG_STATE;
3259 else /* activate the codec */
3261 dbug(1, dprintf("Ext_Ctrl start"));
3262 if (AdvCodecSupport(a, plci, appl, 0))
3264 dbug(1, dprintf("Error in codec procedures"));
3265 Info = _WRONG_STATE;
3267 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3269 plci->spoofed_msg = AWAITING_SELECT_B;
3270 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3271 plci->command = 0;
3272 dbug(1, dprintf("continue if codec loaded"));
3273 return false;
3278 else /* external controller bit is OFF */
3280 if (tel) /* external controller in use, need to switch off */
3282 if (a->AdvSignalAppl == appl)
3284 CodecIdCheck(a, plci);
3285 plci->tel = 0;
3286 plci->adv_nl = 0;
3287 dbug(1, dprintf("Ext_Ctrl disable"));
3289 else
3291 dbug(1, dprintf("Ext_Ctrl not requested"));
3295 if (!Info)
3297 if (plci->call_dir & CALL_DIR_OUT)
3298 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3299 else if (plci->call_dir & CALL_DIR_IN)
3300 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3301 start_internal_command(Id, plci, select_b_command);
3302 return false;
3306 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3307 return false;
3310 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3311 PLCI *plci, APPL *appl, API_PARSE *parms)
3313 word command;
3314 word i;
3315 word ncci;
3316 API_PARSE *m;
3317 API_PARSE m_parms[5];
3318 word codec;
3319 byte req;
3320 byte ch;
3321 byte dir;
3322 static byte chi[2] = {0x01, 0x00};
3323 static byte lli[2] = {0x01, 0x00};
3324 static byte codec_cai[2] = {0x01, 0x01};
3325 static byte null_msg = {0};
3326 static API_PARSE null_parms = { 0, &null_msg };
3327 PLCI *v_plci;
3328 word Info = 0;
3330 dbug(1, dprintf("manufacturer_req"));
3331 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3333 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3334 Info = _WRONG_MESSAGE_FORMAT;
3336 command = GET_WORD(parms[1].info);
3337 m = &parms[2];
3338 if (!Info)
3340 switch (command) {
3341 case _DI_ASSIGN_PLCI:
3342 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3343 Info = _WRONG_MESSAGE_FORMAT;
3344 break;
3346 codec = GET_WORD(m_parms[0].info);
3347 ch = m_parms[1].info[0];
3348 dir = m_parms[2].info[0];
3349 if ((i = get_plci(a))) {
3350 plci = &a->plci[i - 1];
3351 plci->appl = appl;
3352 plci->command = _MANUFACTURER_R;
3353 plci->m_command = command;
3354 plci->number = Number;
3355 plci->State = LOCAL_CONNECT;
3356 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3357 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3359 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3360 chi[1] = (byte)(0x80 | ch);
3361 lli[1] = 0;
3362 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3363 switch (codec)
3365 case 0:
3366 Info = add_b1(plci, &m_parms[3], 0, 0);
3367 break;
3368 case 1:
3369 add_p(plci, CAI, codec_cai);
3370 break;
3371 /* manual 'swich on' to the codec support without signalling */
3372 /* first 'assign plci' with this function, then use */
3373 case 2:
3374 if (AdvCodecSupport(a, plci, appl, 0)) {
3375 Info = _RESOURCE_ERROR;
3377 else {
3378 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3379 lli[1] = 0x10; /* local call codec stream */
3381 break;
3384 plci->State = LOCAL_CONNECT;
3385 plci->manufacturer = true;
3386 plci->command = _MANUFACTURER_R;
3387 plci->m_command = command;
3388 plci->number = Number;
3390 if (!Info)
3392 add_p(plci, LLI, lli);
3393 add_p(plci, CHI, chi);
3394 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3395 sig_req(plci, ASSIGN, DSIG_ID);
3397 if (!codec)
3399 Info = add_b23(plci, &m_parms[3]);
3400 if (!Info)
3402 nl_req_ncci(plci, ASSIGN, 0);
3403 send_req(plci);
3406 if (!Info)
3408 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3409 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3411 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3412 plci->spoofed_msg = AWAITING_MANUF_CON;
3413 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3414 plci->command = 0;
3415 send_req(plci);
3416 return false;
3418 if (dir == 1) {
3419 sig_req(plci, CALL_REQ, 0);
3421 else if (!dir) {
3422 sig_req(plci, LISTEN_REQ, 0);
3424 send_req(plci);
3426 else
3428 sendf(appl,
3429 _MANUFACTURER_R | CONFIRM,
3431 Number,
3432 "dww", _DI_MANU_ID, command, Info);
3433 return 2;
3438 else Info = _OUT_OF_PLCI;
3439 break;
3441 case _DI_IDI_CTRL:
3442 if (!plci)
3444 Info = _WRONG_IDENTIFIER;
3445 break;
3447 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3448 Info = _WRONG_MESSAGE_FORMAT;
3449 break;
3451 req = m_parms[0].info[0];
3452 plci->command = _MANUFACTURER_R;
3453 plci->m_command = command;
3454 plci->number = Number;
3455 if (req == CALL_REQ)
3457 plci->b_channel = getChannel(&m_parms[1]);
3458 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3459 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3461 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3462 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3463 plci->command = 0;
3464 break;
3467 else if (req == LAW_REQ)
3469 plci->cr_enquiry = true;
3471 add_ss(plci, FTY, &m_parms[1]);
3472 sig_req(plci, req, 0);
3473 send_req(plci);
3474 if (req == HANGUP)
3476 if (plci->NL.Id && !plci->nl_remove_id)
3478 if (plci->channels)
3480 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3482 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3484 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3485 cleanup_ncci_data(plci, ncci);
3486 nl_req_ncci(plci, N_DISC, (byte)ncci);
3490 mixer_remove(plci);
3491 nl_req_ncci(plci, REMOVE, 0);
3492 send_req(plci);
3495 break;
3497 case _DI_SIG_CTRL:
3498 /* signalling control for loop activation B-channel */
3499 if (!plci)
3501 Info = _WRONG_IDENTIFIER;
3502 break;
3504 if (m->length) {
3505 plci->command = _MANUFACTURER_R;
3506 plci->number = Number;
3507 add_ss(plci, FTY, m);
3508 sig_req(plci, SIG_CTRL, 0);
3509 send_req(plci);
3511 else Info = _WRONG_MESSAGE_FORMAT;
3512 break;
3514 case _DI_RXT_CTRL:
3515 /* activation control for receiver/transmitter B-channel */
3516 if (!plci)
3518 Info = _WRONG_IDENTIFIER;
3519 break;
3521 if (m->length) {
3522 plci->command = _MANUFACTURER_R;
3523 plci->number = Number;
3524 add_ss(plci, FTY, m);
3525 sig_req(plci, DSP_CTRL, 0);
3526 send_req(plci);
3528 else Info = _WRONG_MESSAGE_FORMAT;
3529 break;
3531 case _DI_ADV_CODEC:
3532 case _DI_DSP_CTRL:
3533 /* TEL_CTRL commands to support non standard adjustments: */
3534 /* Ring on/off, Handset micro volume, external micro vol. */
3535 /* handset+external speaker volume, receiver+transm. gain,*/
3536 /* handsfree on (hookinfo off), set mixer command */
3538 if (command == _DI_ADV_CODEC)
3540 if (!a->AdvCodecPLCI) {
3541 Info = _WRONG_STATE;
3542 break;
3544 v_plci = a->AdvCodecPLCI;
3546 else
3548 if (plci
3549 && (m->length >= 3)
3550 && (m->info[1] == 0x1c)
3551 && (m->info[2] >= 1))
3553 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3555 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3557 Info = _WRONG_STATE;
3558 break;
3560 a->adv_voice_coef_length = m->info[2] - 1;
3561 if (a->adv_voice_coef_length > m->length - 3)
3562 a->adv_voice_coef_length = (byte)(m->length - 3);
3563 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3564 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3565 for (i = 0; i < a->adv_voice_coef_length; i++)
3566 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3567 if (plci->B1_facilities & B1_FACILITY_VOICE)
3568 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3569 break;
3571 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3573 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3575 Info = _FACILITY_NOT_SUPPORTED;
3576 break;
3579 plci->dtmf_parameter_length = m->info[2] - 1;
3580 if (plci->dtmf_parameter_length > m->length - 3)
3581 plci->dtmf_parameter_length = (byte)(m->length - 3);
3582 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3583 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3584 for (i = 0; i < plci->dtmf_parameter_length; i++)
3585 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3586 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3587 dtmf_parameter_write(plci);
3588 break;
3592 v_plci = plci;
3595 if (!v_plci)
3597 Info = _WRONG_IDENTIFIER;
3598 break;
3600 if (m->length) {
3601 add_ss(v_plci, FTY, m);
3602 sig_req(v_plci, TEL_CTRL, 0);
3603 send_req(v_plci);
3605 else Info = _WRONG_MESSAGE_FORMAT;
3607 break;
3609 case _DI_OPTIONS_REQUEST:
3610 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3611 Info = _WRONG_MESSAGE_FORMAT;
3612 break;
3614 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3616 Info = _FACILITY_NOT_SUPPORTED;
3617 break;
3619 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3620 break;
3624 default:
3625 Info = _WRONG_MESSAGE_FORMAT;
3626 break;
3630 sendf(appl,
3631 _MANUFACTURER_R | CONFIRM,
3633 Number,
3634 "dww", _DI_MANU_ID, command, Info);
3635 return false;
3639 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3640 PLCI *plci, APPL *appl, API_PARSE *msg)
3642 word indication;
3644 API_PARSE m_parms[3];
3645 API_PARSE *ncpi;
3646 API_PARSE fax_parms[9];
3647 word i;
3648 byte len;
3651 dbug(1, dprintf("manufacturer_res"));
3653 if ((msg[0].length == 0)
3654 || (msg[1].length == 0)
3655 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3657 return false;
3659 indication = GET_WORD(msg[1].info);
3660 switch (indication)
3663 case _DI_NEGOTIATE_B3:
3664 if (!plci)
3665 break;
3666 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3667 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3669 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3670 break;
3672 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3674 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3675 break;
3677 ncpi = &m_parms[1];
3678 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3679 if (plci->fax_connect_info_length < len)
3681 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3682 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3684 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3686 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3688 else
3690 if (plci->fax_connect_info_length <= len)
3691 plci->fax_connect_info_buffer[len] = 0;
3692 len += 1 + plci->fax_connect_info_buffer[len];
3693 if (plci->fax_connect_info_length <= len)
3694 plci->fax_connect_info_buffer[len] = 0;
3695 len += 1 + plci->fax_connect_info_buffer[len];
3696 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3697 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3698 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3699 for (i = 0; i < fax_parms[7].length; i++)
3700 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3702 plci->fax_connect_info_length = len;
3703 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3704 start_internal_command(Id, plci, fax_edata_ack_command);
3705 break;
3708 return false;
3711 /*------------------------------------------------------------------*/
3712 /* IDI callback function */
3713 /*------------------------------------------------------------------*/
3715 void callback(ENTITY *e)
3717 DIVA_CAPI_ADAPTER *a;
3718 APPL *appl;
3719 PLCI *plci;
3720 CAPI_MSG *m;
3721 word i, j;
3722 byte rc;
3723 byte ch;
3724 byte req;
3725 byte global_req;
3726 int no_cancel_rc;
3728 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3729 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3731 a = &(adapter[(byte)e->user[0]]);
3732 plci = &(a->plci[e->user[1]]);
3733 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3736 If new protocol code and new XDI is used then CAPI should work
3737 fully in accordance with IDI cpec an look on callback field instead
3738 of Rc field for return codes.
3740 if (((e->complete == 0xff) && no_cancel_rc) ||
3741 (e->Rc && !no_cancel_rc)) {
3742 rc = e->Rc;
3743 ch = e->RcCh;
3744 req = e->Req;
3745 e->Rc = 0;
3747 if (e->user[0] & 0x8000)
3750 If REMOVE request was sent then we have to wait until
3751 return code with Id set to zero arrives.
3752 All other return codes should be ignored.
3754 if (req == REMOVE)
3756 if (e->Id)
3758 dbug(1, dprintf("cancel RC in REMOVE state"));
3759 return;
3761 channel_flow_control_remove(plci);
3762 for (i = 0; i < 256; i++)
3764 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3765 a->FlowControlIdTable[i] = 0;
3767 plci->nl_remove_id = 0;
3768 if (plci->rx_dma_descriptor > 0) {
3769 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3770 plci->rx_dma_descriptor = 0;
3773 if (rc == OK_FC)
3775 a->FlowControlIdTable[ch] = e->Id;
3776 a->FlowControlSkipTable[ch] = 0;
3778 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3779 a->ch_flow_plci[ch] = plci->Id;
3780 plci->nl_req = 0;
3782 else
3785 Cancel return codes self, if feature was requested
3787 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3788 a->FlowControlIdTable[ch] = 0;
3789 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3790 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3791 return;
3795 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3797 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3798 if (ch == e->ReqCh)
3799 plci->nl_req = 0;
3801 else
3802 plci->nl_req = 0;
3804 if (plci->nl_req)
3805 control_rc(plci, 0, rc, ch, 0, true);
3806 else
3808 if (req == N_XON)
3810 channel_x_on(plci, ch);
3811 if (plci->internal_command)
3812 control_rc(plci, req, rc, ch, 0, true);
3814 else
3816 if (plci->nl_global_req)
3818 global_req = plci->nl_global_req;
3819 plci->nl_global_req = 0;
3820 if (rc != ASSIGN_OK) {
3821 e->Id = 0;
3822 if (plci->rx_dma_descriptor > 0) {
3823 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3824 plci->rx_dma_descriptor = 0;
3827 channel_xmit_xon(plci);
3828 control_rc(plci, 0, rc, ch, global_req, true);
3830 else if (plci->data_sent)
3832 channel_xmit_xon(plci);
3833 plci->data_sent = false;
3834 plci->NL.XNum = 1;
3835 data_rc(plci, ch);
3836 if (plci->internal_command)
3837 control_rc(plci, req, rc, ch, 0, true);
3839 else
3841 channel_xmit_xon(plci);
3842 control_rc(plci, req, rc, ch, 0, true);
3847 else
3850 If REMOVE request was sent then we have to wait until
3851 return code with Id set to zero arrives.
3852 All other return codes should be ignored.
3854 if (req == REMOVE)
3856 if (e->Id)
3858 dbug(1, dprintf("cancel RC in REMOVE state"));
3859 return;
3861 plci->sig_remove_id = 0;
3863 plci->sig_req = 0;
3864 if (plci->sig_global_req)
3866 global_req = plci->sig_global_req;
3867 plci->sig_global_req = 0;
3868 if (rc != ASSIGN_OK)
3869 e->Id = 0;
3870 channel_xmit_xon(plci);
3871 control_rc(plci, 0, rc, ch, global_req, false);
3873 else
3875 channel_xmit_xon(plci);
3876 control_rc(plci, req, rc, ch, 0, false);
3880 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3881 same callback. Also if new XDI and protocol code used then jump
3882 direct to finish.
3884 if (no_cancel_rc) {
3885 channel_xmit_xon(plci);
3886 goto capi_callback_suffix;
3890 channel_xmit_xon(plci);
3892 if (e->Ind) {
3893 if (e->user[0] & 0x8000) {
3894 byte Ind = e->Ind & 0x0f;
3895 byte Ch = e->IndCh;
3896 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
3897 (a->ch_flow_plci[Ch] == plci->Id)) {
3898 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
3899 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
3901 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3903 nl_ind(plci);
3904 if ((e->RNR != 1) &&
3905 (a->ch_flow_plci[Ch] == plci->Id) &&
3906 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
3907 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3908 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
3910 } else {
3911 sig_ind(plci);
3913 e->Ind = 0;
3916 capi_callback_suffix:
3918 while (!plci->req_in
3919 && !plci->internal_command
3920 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
3922 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
3924 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
3926 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
3927 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
3928 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
3929 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
3930 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3932 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3933 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
3935 else
3937 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
3939 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
3941 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
3942 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3944 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3946 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3947 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3949 i = api_put(appl, m);
3950 if (i != 0)
3952 if (m->header.command == _DATA_B3_R)
3954 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
3956 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
3957 break;
3960 if (plci->li_notify_update)
3962 plci->li_notify_update = false;
3963 mixer_notify_update(plci, false);
3967 send_data(plci);
3968 send_req(plci);
3972 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
3973 byte nl_rc)
3975 dword Id;
3976 dword rId;
3977 word Number;
3978 word Info = 0;
3979 word i;
3980 word ncci;
3981 DIVA_CAPI_ADAPTER *a;
3982 APPL *appl;
3983 PLCI *rplci;
3984 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
3985 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
3987 if (!plci) {
3988 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
3989 return;
3991 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
3992 if (plci->req_in != plci->req_out)
3994 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
3996 dbug(1, dprintf("req_1return"));
3997 return;
3999 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4001 plci->req_in = plci->req_in_start = plci->req_out = 0;
4002 dbug(1, dprintf("control_rc"));
4004 appl = plci->appl;
4005 a = plci->adapter;
4006 ncci = a->ch_ncci[ch];
4007 if (appl)
4009 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4010 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4011 Number = plci->number;
4012 dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4013 dbug(1, dprintf("channels=0x%x", plci->channels));
4014 if (plci_remove_check(plci))
4015 return;
4016 if (req == REMOVE && rc == ASSIGN_OK)
4018 sig_req(plci, HANGUP, 0);
4019 sig_req(plci, REMOVE, 0);
4020 send_req(plci);
4022 if (plci->command)
4024 switch (plci->command)
4026 case C_HOLD_REQ:
4027 dbug(1, dprintf("HoldRC=0x%x", rc));
4028 SSparms[1] = (byte)S_HOLD;
4029 if (rc != OK)
4031 plci->SuppState = IDLE;
4032 Info = 0x2001;
4034 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4035 break;
4037 case C_RETRIEVE_REQ:
4038 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4039 SSparms[1] = (byte)S_RETRIEVE;
4040 if (rc != OK)
4042 plci->SuppState = CALL_HELD;
4043 Info = 0x2001;
4045 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4046 break;
4048 case _INFO_R:
4049 dbug(1, dprintf("InfoRC=0x%x", rc));
4050 if (rc != OK) Info = _WRONG_STATE;
4051 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4052 break;
4054 case _CONNECT_R:
4055 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4056 if (plci->State == INC_DIS_PENDING)
4057 break;
4058 if (plci->Sig.Id != 0xff)
4060 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4061 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4063 dbug(1, dprintf("No more IDs/Call_Req failed"));
4064 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4065 plci_remove(plci);
4066 plci->State = IDLE;
4067 break;
4069 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4070 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4072 else /* D-ch activation */
4074 if (rc != ASSIGN_OK)
4076 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4077 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4078 plci_remove(plci);
4079 plci->State = IDLE;
4080 break;
4082 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4083 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4084 plci->State = INC_ACT_PENDING;
4086 break;
4088 case _CONNECT_I | RESPONSE:
4089 if (plci->State != INC_DIS_PENDING)
4090 plci->State = INC_CON_ACCEPT;
4091 break;
4093 case _DISCONNECT_R:
4094 if (plci->State == INC_DIS_PENDING)
4095 break;
4096 if (plci->Sig.Id != 0xff)
4098 plci->State = OUTG_DIS_PENDING;
4099 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4101 break;
4103 case SUSPEND_REQ:
4104 break;
4106 case RESUME_REQ:
4107 break;
4109 case _CONNECT_B3_R:
4110 if (rc != OK)
4112 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4113 break;
4115 ncci = get_ncci(plci, ch, 0);
4116 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4117 plci->channels++;
4118 if (req == N_RESET)
4120 a->ncci_state[ncci] = INC_ACT_PENDING;
4121 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4122 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4124 else
4126 a->ncci_state[ncci] = OUTG_CON_PENDING;
4127 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4129 break;
4131 case _CONNECT_B3_I | RESPONSE:
4132 break;
4134 case _RESET_B3_R:
4135 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4136 break;
4138 case _DISCONNECT_B3_R:
4139 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4140 break;
4142 case _MANUFACTURER_R:
4143 break;
4145 case PERM_LIST_REQ:
4146 if (rc != OK)
4148 Info = _WRONG_IDENTIFIER;
4149 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4150 plci_remove(plci);
4152 else
4153 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4154 break;
4156 default:
4157 break;
4159 plci->command = 0;
4161 else if (plci->internal_command)
4163 switch (plci->internal_command)
4165 case BLOCK_PLCI:
4166 return;
4168 case GET_MWI_STATE:
4169 if (rc == OK) /* command supported, wait for indication */
4171 return;
4173 plci_remove(plci);
4174 break;
4176 /* Get Supported Services */
4177 case GETSERV_REQ_PEND:
4178 if (rc == OK) /* command supported, wait for indication */
4180 break;
4182 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4183 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4184 plci_remove(plci);
4185 break;
4187 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4188 case INTERR_NUMBERS_REQ_PEND:
4189 case CF_START_PEND: /* Call Forwarding Start pending */
4190 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4191 case CCBS_REQUEST_REQ_PEND:
4192 case CCBS_DEACTIVATE_REQ_PEND:
4193 case CCBS_INTERROGATE_REQ_PEND:
4194 switch (plci->internal_command)
4196 case INTERR_DIVERSION_REQ_PEND:
4197 SSparms[1] = S_INTERROGATE_DIVERSION;
4198 break;
4199 case INTERR_NUMBERS_REQ_PEND:
4200 SSparms[1] = S_INTERROGATE_NUMBERS;
4201 break;
4202 case CF_START_PEND:
4203 SSparms[1] = S_CALL_FORWARDING_START;
4204 break;
4205 case CF_STOP_PEND:
4206 SSparms[1] = S_CALL_FORWARDING_STOP;
4207 break;
4208 case CCBS_REQUEST_REQ_PEND:
4209 SSparms[1] = S_CCBS_REQUEST;
4210 break;
4211 case CCBS_DEACTIVATE_REQ_PEND:
4212 SSparms[1] = S_CCBS_DEACTIVATE;
4213 break;
4214 case CCBS_INTERROGATE_REQ_PEND:
4215 SSparms[1] = S_CCBS_INTERROGATE;
4216 break;
4218 if (global_req == ASSIGN)
4220 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4221 return;
4223 if (!plci->appl) break;
4224 if (rc == ISDN_GUARD_REJ)
4226 Info = _CAPI_GUARD_ERROR;
4228 else if (rc != OK)
4230 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4232 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4233 plci->number, "wws", Info, (word)3, SSparms);
4234 if (Info) plci_remove(plci);
4235 break;
4237 /* 3pty conference pending */
4238 case PTY_REQ_PEND:
4239 if (!plci->relatedPTYPLCI) break;
4240 rplci = plci->relatedPTYPLCI;
4241 SSparms[1] = plci->ptyState;
4242 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4243 if (rplci->tel) rId |= EXT_CONTROLLER;
4244 if (rc != OK)
4246 Info = 0x300E; /* not supported */
4247 plci->relatedPTYPLCI = NULL;
4248 plci->ptyState = 0;
4250 sendf(rplci->appl,
4251 _FACILITY_R | CONFIRM,
4252 rId,
4253 plci->number,
4254 "wws", Info, (word)3, SSparms);
4255 break;
4257 /* Explicit Call Transfer pending */
4258 case ECT_REQ_PEND:
4259 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4260 if (!plci->relatedPTYPLCI) break;
4261 rplci = plci->relatedPTYPLCI;
4262 SSparms[1] = S_ECT;
4263 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4264 if (rplci->tel) rId |= EXT_CONTROLLER;
4265 if (rc != OK)
4267 Info = 0x300E; /* not supported */
4268 plci->relatedPTYPLCI = NULL;
4269 plci->ptyState = 0;
4271 sendf(rplci->appl,
4272 _FACILITY_R | CONFIRM,
4273 rId,
4274 plci->number,
4275 "wws", Info, (word)3, SSparms);
4276 break;
4278 case _MANUFACTURER_R:
4279 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4280 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4282 dbug(1, dprintf("No more IDs"));
4283 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4284 plci_remove(plci); /* after codec init, internal codec commands pending */
4286 break;
4288 case _CONNECT_R:
4289 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4290 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4292 dbug(1, dprintf("No more IDs"));
4293 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4294 plci_remove(plci); /* after codec init, internal codec commands pending */
4296 break;
4298 case PERM_COD_HOOK: /* finished with Hook_Ind */
4299 return;
4301 case PERM_COD_CALL:
4302 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4303 plci->internal_command = PERM_COD_CONN_PEND;
4304 return;
4306 case PERM_COD_ASSIGN:
4307 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4308 if (rc != ASSIGN_OK) break;
4309 sig_req(plci, CALL_REQ, 0);
4310 send_req(plci);
4311 plci->internal_command = PERM_COD_CALL;
4312 return;
4314 /* Null Call Reference Request pending */
4315 case C_NCR_FAC_REQ:
4316 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4317 if (global_req == ASSIGN)
4319 if (rc == ASSIGN_OK)
4321 return;
4323 else
4325 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4326 appl->NullCREnable = false;
4327 plci_remove(plci);
4330 else if (req == NCR_FACILITY)
4332 if (rc == OK)
4334 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4336 else
4338 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4339 appl->NullCREnable = false;
4341 plci_remove(plci);
4343 break;
4345 case HOOK_ON_REQ:
4346 if (plci->channels)
4348 if (a->ncci_state[ncci] == CONNECTED)
4350 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4351 cleanup_ncci_data(plci, ncci);
4352 nl_req_ncci(plci, N_DISC, (byte)ncci);
4354 break;
4356 break;
4358 case HOOK_OFF_REQ:
4359 if (plci->State == INC_DIS_PENDING)
4360 break;
4361 sig_req(plci, CALL_REQ, 0);
4362 send_req(plci);
4363 plci->State = OUTG_CON_PENDING;
4364 break;
4367 case MWI_ACTIVATE_REQ_PEND:
4368 case MWI_DEACTIVATE_REQ_PEND:
4369 if (global_req == ASSIGN && rc == ASSIGN_OK)
4371 dbug(1, dprintf("MWI_REQ assigned"));
4372 return;
4374 else if (rc != OK)
4376 if (rc == WRONG_IE)
4378 Info = 0x2007; /* Illegal message parameter coding */
4379 dbug(1, dprintf("MWI_REQ invalid parameter"));
4381 else
4383 Info = 0x300B; /* not supported */
4384 dbug(1, dprintf("MWI_REQ not supported"));
4386 /* 0x3010: Request not allowed in this state */
4387 PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4390 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4392 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4394 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4396 if (plci->cr_enquiry)
4398 sendf(plci->appl,
4399 _FACILITY_R | CONFIRM,
4400 Id & 0xf,
4401 plci->number,
4402 "wws", Info, (word)3, SSparms);
4403 if (rc != OK) plci_remove(plci);
4405 else
4407 sendf(plci->appl,
4408 _FACILITY_R | CONFIRM,
4410 plci->number,
4411 "wws", Info, (word)3, SSparms);
4413 break;
4415 case CONF_BEGIN_REQ_PEND:
4416 case CONF_ADD_REQ_PEND:
4417 case CONF_SPLIT_REQ_PEND:
4418 case CONF_DROP_REQ_PEND:
4419 case CONF_ISOLATE_REQ_PEND:
4420 case CONF_REATTACH_REQ_PEND:
4421 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4422 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4423 rplci = plci;
4424 rId = Id;
4425 switch (plci->internal_command)
4427 case CONF_BEGIN_REQ_PEND:
4428 SSparms[1] = S_CONF_BEGIN;
4429 break;
4430 case CONF_ADD_REQ_PEND:
4431 SSparms[1] = S_CONF_ADD;
4432 rplci = plci->relatedPTYPLCI;
4433 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4434 break;
4435 case CONF_SPLIT_REQ_PEND:
4436 SSparms[1] = S_CONF_SPLIT;
4437 break;
4438 case CONF_DROP_REQ_PEND:
4439 SSparms[1] = S_CONF_DROP;
4440 break;
4441 case CONF_ISOLATE_REQ_PEND:
4442 SSparms[1] = S_CONF_ISOLATE;
4443 break;
4444 case CONF_REATTACH_REQ_PEND:
4445 SSparms[1] = S_CONF_REATTACH;
4446 break;
4449 if (rc != OK)
4451 Info = 0x300E; /* not supported */
4452 plci->relatedPTYPLCI = NULL;
4453 plci->ptyState = 0;
4455 sendf(rplci->appl,
4456 _FACILITY_R | CONFIRM,
4457 rId,
4458 plci->number,
4459 "wws", Info, (word)3, SSparms);
4460 break;
4462 case VSWITCH_REQ_PEND:
4463 if (rc != OK)
4465 if (plci->relatedPTYPLCI)
4467 plci->relatedPTYPLCI->vswitchstate = 0;
4468 plci->relatedPTYPLCI->vsprot = 0;
4469 plci->relatedPTYPLCI->vsprotdialect = 0;
4471 plci->vswitchstate = 0;
4472 plci->vsprot = 0;
4473 plci->vsprotdialect = 0;
4475 else
4477 if (plci->relatedPTYPLCI &&
4478 plci->vswitchstate == 1 &&
4479 plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4480 plci->vswitchstate = 3;
4482 break;
4484 /* Call Deflection Request pending (SSCT) */
4485 case CD_REQ_PEND:
4486 SSparms[1] = S_CALL_DEFLECTION;
4487 if (rc != OK)
4489 Info = 0x300E; /* not supported */
4490 plci->appl->CDEnable = 0;
4492 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4493 plci->number, "wws", Info, (word)3, SSparms);
4494 break;
4496 case RTP_CONNECT_B3_REQ_COMMAND_2:
4497 if (rc == OK)
4499 ncci = get_ncci(plci, ch, 0);
4500 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4501 plci->channels++;
4502 a->ncci_state[ncci] = OUTG_CON_PENDING;
4504 /* fall through */
4506 default:
4507 if (plci->internal_command_queue[0])
4509 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4510 if (plci->internal_command)
4511 return;
4513 break;
4515 next_internal_command(Id, plci);
4518 else /* appl==0 */
4520 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4521 if (plci->tel) Id |= EXT_CONTROLLER;
4523 switch (plci->internal_command)
4525 case BLOCK_PLCI:
4526 return;
4528 case START_L1_SIG_ASSIGN_PEND:
4529 case REM_L1_SIG_ASSIGN_PEND:
4530 if (global_req == ASSIGN)
4532 break;
4534 else
4536 dbug(1, dprintf("***L1 Req rem PLCI"));
4537 plci->internal_command = 0;
4538 sig_req(plci, REMOVE, 0);
4539 send_req(plci);
4541 break;
4543 /* Call Deflection Request pending, just no appl ptr assigned */
4544 case CD_REQ_PEND:
4545 SSparms[1] = S_CALL_DEFLECTION;
4546 if (rc != OK)
4548 Info = 0x300E; /* not supported */
4550 for (i = 0; i < max_appl; i++)
4552 if (application[i].CDEnable)
4554 if (!application[i].Id) application[i].CDEnable = 0;
4555 else
4557 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4558 plci->number, "wws", Info, (word)3, SSparms);
4559 if (Info) application[i].CDEnable = 0;
4563 plci->internal_command = 0;
4564 break;
4566 case PERM_COD_HOOK: /* finished with Hook_Ind */
4567 return;
4569 case PERM_COD_CALL:
4570 plci->internal_command = PERM_COD_CONN_PEND;
4571 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4572 return;
4574 case PERM_COD_ASSIGN:
4575 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4576 plci->internal_command = 0;
4577 if (rc != ASSIGN_OK) break;
4578 plci->internal_command = PERM_COD_CALL;
4579 sig_req(plci, CALL_REQ, 0);
4580 send_req(plci);
4581 return;
4583 case LISTEN_SIG_ASSIGN_PEND:
4584 if (rc == ASSIGN_OK)
4586 plci->internal_command = 0;
4587 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4588 add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4589 sig_req(plci, INDICATE_REQ, 0);
4590 send_req(plci);
4592 else
4594 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4595 a->listen_active--;
4596 plci_remove(plci);
4597 plci->State = IDLE;
4599 break;
4601 case USELAW_REQ:
4602 if (global_req == ASSIGN)
4604 if (rc == ASSIGN_OK)
4606 sig_req(plci, LAW_REQ, 0);
4607 send_req(plci);
4608 dbug(1, dprintf("Auto-Law assigned"));
4610 else
4612 dbug(1, dprintf("Auto-Law assign failed"));
4613 a->automatic_law = 3;
4614 plci->internal_command = 0;
4615 a->automatic_lawPLCI = NULL;
4617 break;
4619 else if (req == LAW_REQ && rc == OK)
4621 dbug(1, dprintf("Auto-Law initiated"));
4622 a->automatic_law = 2;
4623 plci->internal_command = 0;
4625 else
4627 dbug(1, dprintf("Auto-Law not supported"));
4628 a->automatic_law = 3;
4629 plci->internal_command = 0;
4630 sig_req(plci, REMOVE, 0);
4631 send_req(plci);
4632 a->automatic_lawPLCI = NULL;
4634 break;
4636 plci_remove_check(plci);
4640 static void data_rc(PLCI *plci, byte ch)
4642 dword Id;
4643 DIVA_CAPI_ADAPTER *a;
4644 NCCI *ncci_ptr;
4645 DATA_B3_DESC *data;
4646 word ncci;
4648 if (plci->appl)
4650 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4651 a = plci->adapter;
4652 ncci = a->ch_ncci[ch];
4653 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4655 ncci_ptr = &(a->ncci[ncci]);
4656 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4657 if (ncci_ptr->data_pending)
4659 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4660 if (!(data->Flags & 4) && a->ncci_state[ncci])
4662 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4663 if (plci->tel) Id |= EXT_CONTROLLER;
4664 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4665 "ww", data->Handle, 0);
4667 (ncci_ptr->data_out)++;
4668 if (ncci_ptr->data_out == MAX_DATA_B3)
4669 ncci_ptr->data_out = 0;
4670 (ncci_ptr->data_pending)--;
4676 static void data_ack(PLCI *plci, byte ch)
4678 dword Id;
4679 DIVA_CAPI_ADAPTER *a;
4680 NCCI *ncci_ptr;
4681 word ncci;
4683 a = plci->adapter;
4684 ncci = a->ch_ncci[ch];
4685 ncci_ptr = &(a->ncci[ncci]);
4686 if (ncci_ptr->data_ack_pending)
4688 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4690 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4691 if (plci->tel) Id |= EXT_CONTROLLER;
4692 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4693 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4695 (ncci_ptr->data_ack_out)++;
4696 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4697 ncci_ptr->data_ack_out = 0;
4698 (ncci_ptr->data_ack_pending)--;
4702 static void sig_ind(PLCI *plci)
4704 dword x_Id;
4705 dword Id;
4706 dword rId;
4707 word i;
4708 word cip;
4709 dword cip_mask;
4710 byte *ie;
4711 DIVA_CAPI_ADAPTER *a;
4712 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4713 #define MAXPARMSIDS 31
4714 byte *parms[MAXPARMSIDS];
4715 byte *add_i[4];
4716 byte *multi_fac_parms[MAX_MULTI_IE];
4717 byte *multi_pi_parms[MAX_MULTI_IE];
4718 byte *multi_ssext_parms[MAX_MULTI_IE];
4719 byte *multi_CiPN_parms[MAX_MULTI_IE];
4721 byte *multi_vswitch_parms[MAX_MULTI_IE];
4723 byte ai_len;
4724 byte *esc_chi = "";
4725 byte *esc_law = "";
4726 byte *pty_cai = "";
4727 byte *esc_cr = "";
4728 byte *esc_profile = "";
4730 byte facility[256];
4731 PLCI *tplci = NULL;
4732 byte chi[] = "\x02\x18\x01";
4733 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4734 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4735 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4736 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4737 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4738 /* (see Info_Mask Bit 4, first IE. then the message type) */
4739 static const word parms_id[] =
4740 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4741 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4742 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4743 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4744 /* 14 FTY repl by ESC_CHI */
4745 /* 18 PI repl by ESC_LAW */
4746 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4747 static const word multi_fac_id[] = {1, FTY};
4748 static const word multi_pi_id[] = {1, PI};
4749 static const word multi_CiPN_id[] = {1, OAD};
4750 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4752 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4754 byte *cau;
4755 word ncci;
4756 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4757 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4758 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4759 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4760 byte force_mt_info = false;
4761 byte dir;
4762 dword d;
4763 word w;
4765 a = plci->adapter;
4766 Id = ((word)plci->Id << 8) | a->Id;
4767 PUT_WORD(&SS_Ind[4], 0x0000);
4769 if (plci->sig_remove_id)
4771 plci->Sig.RNR = 2; /* discard */
4772 dbug(1, dprintf("SIG discard while remove pending"));
4773 return;
4775 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4776 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4777 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4778 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4780 plci->Sig.RNR = 1;
4781 return;
4783 if (plci->Sig.Ind == HANGUP && plci->channels)
4785 plci->Sig.RNR = 1;
4786 plci->hangup_flow_ctrl_timer++;
4787 /* recover the network layer after timeout */
4788 if (plci->hangup_flow_ctrl_timer == 100)
4790 dbug(1, dprintf("Exceptional disc"));
4791 plci->Sig.RNR = 0;
4792 plci->hangup_flow_ctrl_timer = 0;
4793 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4795 if (a->ncci_plci[ncci] == plci->Id)
4797 cleanup_ncci_data(plci, ncci);
4798 if (plci->channels)plci->channels--;
4799 if (plci->appl)
4800 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4803 if (plci->appl)
4804 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4805 plci_remove(plci);
4806 plci->State = IDLE;
4808 return;
4811 /* do first parse the info with no OAD in, because OAD will be converted */
4812 /* first the multiple facility IE, then mult. progress ind. */
4813 /* then the parameters for the info_ind + conn_ind */
4814 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4815 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4816 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4818 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4820 IndParse(plci, parms_id, parms, 0);
4821 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4822 esc_chi = parms[14];
4823 esc_law = parms[18];
4824 pty_cai = parms[24];
4825 esc_cr = parms[25];
4826 esc_profile = parms[27];
4827 if (esc_cr[0] && plci)
4829 if (plci->cr_enquiry && plci->appl)
4831 plci->cr_enquiry = false;
4832 /* d = MANU_ID */
4833 /* w = m_command */
4834 /* b = total length */
4835 /* b = indication type */
4836 /* b = length of all IEs */
4837 /* b = IE1 */
4838 /* S = IE1 length + cont. */
4839 /* b = IE2 */
4840 /* S = IE2 length + cont. */
4841 sendf(plci->appl,
4842 _MANUFACTURER_I,
4845 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4846 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);
4849 /* create the additional info structure */
4850 add_i[1] = parms[15]; /* KEY of additional info */
4851 add_i[2] = parms[11]; /* UUI of additional info */
4852 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4854 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4855 /* indication returns by the card if requested by the function */
4856 /* AutomaticLaw() after driver init */
4857 if (a->automatic_law < 4)
4859 if (esc_law[0]) {
4860 if (esc_law[2]) {
4861 dbug(0, dprintf("u-Law selected"));
4862 a->u_law = 1;
4864 else {
4865 dbug(0, dprintf("a-Law selected"));
4866 a->u_law = 0;
4868 a->automatic_law = 4;
4869 if (plci == a->automatic_lawPLCI) {
4870 plci->internal_command = 0;
4871 sig_req(plci, REMOVE, 0);
4872 send_req(plci);
4873 a->automatic_lawPLCI = NULL;
4876 if (esc_profile[0])
4878 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4879 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4880 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4881 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4883 a->profile.Global_Options &= 0x000000ffL;
4884 a->profile.B1_Protocols &= 0x000003ffL;
4885 a->profile.B2_Protocols &= 0x00001fdfL;
4886 a->profile.B3_Protocols &= 0x000000b7L;
4888 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4889 GL_BCHANNEL_OPERATION_SUPPORTED;
4890 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4891 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4892 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4893 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4894 a->man_profile.private_options = 0;
4896 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4898 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4899 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4903 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4904 a->man_profile.private_options |= 1L << PRIVATE_RTP;
4905 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4906 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4909 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4910 a->man_profile.private_options |= 1L << PRIVATE_T38;
4913 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4914 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4917 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4918 a->man_profile.private_options |= 1L << PRIVATE_V18;
4921 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4922 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4925 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4926 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4929 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4930 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4933 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4934 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4937 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4938 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4941 else
4943 a->profile.Global_Options &= 0x0000007fL;
4944 a->profile.B1_Protocols &= 0x000003dfL;
4945 a->profile.B2_Protocols &= 0x00001adfL;
4946 a->profile.B3_Protocols &= 0x000000b7L;
4947 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4949 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4950 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4952 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4954 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4955 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4956 UnMapController(a->Id), a->profile.Global_Options,
4957 a->profile.B1_Protocols, a->profile.B2_Protocols,
4958 a->profile.B3_Protocols, a->manufacturer_features));
4960 /* codec plci for the handset/hook state support is just an internal id */
4961 if (plci != a->AdvCodecPLCI)
4963 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4964 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4965 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4966 SendInfo(plci, Id, parms, force_mt_info);
4968 VSwitchReqInd(plci, Id, multi_vswitch_parms);
4972 /* switch the codec to the b-channel */
4973 if (esc_chi[0] && plci && !plci->SuppState) {
4974 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4975 mixer_set_bchannel_id_esc(plci, plci->b_channel);
4976 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4977 if (plci->tel == ADV_VOICE && plci->appl) {
4978 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4982 if (plci->appl) plci->appl->Number++;
4984 switch (plci->Sig.Ind) {
4985 /* Response to Get_Supported_Services request */
4986 case S_SUPPORTED:
4987 dbug(1, dprintf("S_Supported"));
4988 if (!plci->appl) break;
4989 if (pty_cai[0] == 4)
4991 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4993 else
4995 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4997 PUT_WORD(&CF_Ind[1], 0);
4998 PUT_WORD(&CF_Ind[4], 0);
4999 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5000 plci_remove(plci);
5001 break;
5003 /* Supplementary Service rejected */
5004 case S_SERVICE_REJ:
5005 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5006 if (!pty_cai[0]) break;
5007 switch (pty_cai[5])
5009 case ECT_EXECUTE:
5010 case THREE_PTY_END:
5011 case THREE_PTY_BEGIN:
5012 if (!plci->relatedPTYPLCI) break;
5013 tplci = plci->relatedPTYPLCI;
5014 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5015 if (tplci->tel) rId |= EXT_CONTROLLER;
5016 if (pty_cai[5] == ECT_EXECUTE)
5018 PUT_WORD(&SS_Ind[1], S_ECT);
5020 plci->vswitchstate = 0;
5021 plci->relatedPTYPLCI->vswitchstate = 0;
5024 else
5026 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5028 if (pty_cai[2] != 0xff)
5030 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5032 else
5034 PUT_WORD(&SS_Ind[4], 0x300E);
5036 plci->relatedPTYPLCI = NULL;
5037 plci->ptyState = 0;
5038 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5039 break;
5041 case CALL_DEFLECTION:
5042 if (pty_cai[2] != 0xff)
5044 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5046 else
5048 PUT_WORD(&SS_Ind[4], 0x300E);
5050 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5051 for (i = 0; i < max_appl; i++)
5053 if (application[i].CDEnable)
5055 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5056 application[i].CDEnable = false;
5059 break;
5061 case DEACTIVATION_DIVERSION:
5062 case ACTIVATION_DIVERSION:
5063 case DIVERSION_INTERROGATE_CFU:
5064 case DIVERSION_INTERROGATE_CFB:
5065 case DIVERSION_INTERROGATE_CFNR:
5066 case DIVERSION_INTERROGATE_NUM:
5067 case CCBS_REQUEST:
5068 case CCBS_DEACTIVATE:
5069 case CCBS_INTERROGATE:
5070 if (!plci->appl) break;
5071 if (pty_cai[2] != 0xff)
5073 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5075 else
5077 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5079 switch (pty_cai[5])
5081 case DEACTIVATION_DIVERSION:
5082 dbug(1, dprintf("Deact_Div"));
5083 Interr_Err_Ind[0] = 0x9;
5084 Interr_Err_Ind[3] = 0x6;
5085 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5086 break;
5087 case ACTIVATION_DIVERSION:
5088 dbug(1, dprintf("Act_Div"));
5089 Interr_Err_Ind[0] = 0x9;
5090 Interr_Err_Ind[3] = 0x6;
5091 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5092 break;
5093 case DIVERSION_INTERROGATE_CFU:
5094 case DIVERSION_INTERROGATE_CFB:
5095 case DIVERSION_INTERROGATE_CFNR:
5096 dbug(1, dprintf("Interr_Div"));
5097 Interr_Err_Ind[0] = 0xa;
5098 Interr_Err_Ind[3] = 0x7;
5099 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5100 break;
5101 case DIVERSION_INTERROGATE_NUM:
5102 dbug(1, dprintf("Interr_Num"));
5103 Interr_Err_Ind[0] = 0xa;
5104 Interr_Err_Ind[3] = 0x7;
5105 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5106 break;
5107 case CCBS_REQUEST:
5108 dbug(1, dprintf("CCBS Request"));
5109 Interr_Err_Ind[0] = 0xd;
5110 Interr_Err_Ind[3] = 0xa;
5111 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5112 break;
5113 case CCBS_DEACTIVATE:
5114 dbug(1, dprintf("CCBS Deactivate"));
5115 Interr_Err_Ind[0] = 0x9;
5116 Interr_Err_Ind[3] = 0x6;
5117 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5118 break;
5119 case CCBS_INTERROGATE:
5120 dbug(1, dprintf("CCBS Interrogate"));
5121 Interr_Err_Ind[0] = 0xb;
5122 Interr_Err_Ind[3] = 0x8;
5123 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5124 break;
5126 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5127 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5128 plci_remove(plci);
5129 break;
5130 case ACTIVATION_MWI:
5131 case DEACTIVATION_MWI:
5132 if (pty_cai[5] == ACTIVATION_MWI)
5134 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5136 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5138 if (pty_cai[2] != 0xff)
5140 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5142 else
5144 PUT_WORD(&SS_Ind[4], 0x300E);
5147 if (plci->cr_enquiry)
5149 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5150 plci_remove(plci);
5152 else
5154 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5156 break;
5157 case CONF_ADD: /* ERROR */
5158 case CONF_BEGIN:
5159 case CONF_DROP:
5160 case CONF_ISOLATE:
5161 case CONF_REATTACH:
5162 CONF_Ind[0] = 9;
5163 CONF_Ind[3] = 6;
5164 switch (pty_cai[5])
5166 case CONF_BEGIN:
5167 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5168 plci->ptyState = 0;
5169 break;
5170 case CONF_DROP:
5171 CONF_Ind[0] = 5;
5172 CONF_Ind[3] = 2;
5173 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5174 plci->ptyState = CONNECTED;
5175 break;
5176 case CONF_ISOLATE:
5177 CONF_Ind[0] = 5;
5178 CONF_Ind[3] = 2;
5179 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5180 plci->ptyState = CONNECTED;
5181 break;
5182 case CONF_REATTACH:
5183 CONF_Ind[0] = 5;
5184 CONF_Ind[3] = 2;
5185 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5186 plci->ptyState = CONNECTED;
5187 break;
5188 case CONF_ADD:
5189 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5190 plci->relatedPTYPLCI = NULL;
5191 tplci = plci->relatedPTYPLCI;
5192 if (tplci) tplci->ptyState = CONNECTED;
5193 plci->ptyState = CONNECTED;
5194 break;
5197 if (pty_cai[2] != 0xff)
5199 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5201 else
5203 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5204 within the required time */
5207 PUT_DWORD(&CONF_Ind[6], 0x0);
5208 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5209 break;
5211 break;
5213 /* Supplementary Service indicates success */
5214 case S_SERVICE:
5215 dbug(1, dprintf("Service_Ind"));
5216 PUT_WORD(&CF_Ind[4], 0);
5217 switch (pty_cai[5])
5219 case THREE_PTY_END:
5220 case THREE_PTY_BEGIN:
5221 case ECT_EXECUTE:
5222 if (!plci->relatedPTYPLCI) break;
5223 tplci = plci->relatedPTYPLCI;
5224 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5225 if (tplci->tel) rId |= EXT_CONTROLLER;
5226 if (pty_cai[5] == ECT_EXECUTE)
5228 PUT_WORD(&SS_Ind[1], S_ECT);
5230 if (plci->vswitchstate != 3)
5233 plci->ptyState = IDLE;
5234 plci->relatedPTYPLCI = NULL;
5235 plci->ptyState = 0;
5239 dbug(1, dprintf("ECT OK"));
5240 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5245 else
5247 switch (plci->ptyState)
5249 case S_3PTY_BEGIN:
5250 plci->ptyState = CONNECTED;
5251 dbug(1, dprintf("3PTY ON"));
5252 break;
5254 case S_3PTY_END:
5255 plci->ptyState = IDLE;
5256 plci->relatedPTYPLCI = NULL;
5257 plci->ptyState = 0;
5258 dbug(1, dprintf("3PTY OFF"));
5259 break;
5261 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5262 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5264 break;
5266 case CALL_DEFLECTION:
5267 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5268 for (i = 0; i < max_appl; i++)
5270 if (application[i].CDEnable)
5272 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5273 application[i].CDEnable = false;
5276 break;
5278 case DEACTIVATION_DIVERSION:
5279 case ACTIVATION_DIVERSION:
5280 if (!plci->appl) break;
5281 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5282 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5283 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5284 plci_remove(plci);
5285 break;
5287 case DIVERSION_INTERROGATE_CFU:
5288 case DIVERSION_INTERROGATE_CFB:
5289 case DIVERSION_INTERROGATE_CFNR:
5290 case DIVERSION_INTERROGATE_NUM:
5291 case CCBS_REQUEST:
5292 case CCBS_DEACTIVATE:
5293 case CCBS_INTERROGATE:
5294 if (!plci->appl) break;
5295 switch (pty_cai[5])
5297 case DIVERSION_INTERROGATE_CFU:
5298 case DIVERSION_INTERROGATE_CFB:
5299 case DIVERSION_INTERROGATE_CFNR:
5300 dbug(1, dprintf("Interr_Div"));
5301 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5302 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5303 break;
5304 case DIVERSION_INTERROGATE_NUM:
5305 dbug(1, dprintf("Interr_Num"));
5306 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5307 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5308 break;
5309 case CCBS_REQUEST:
5310 dbug(1, dprintf("CCBS Request"));
5311 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5312 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5313 break;
5314 case CCBS_DEACTIVATE:
5315 dbug(1, dprintf("CCBS Deactivate"));
5316 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5317 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5318 break;
5319 case CCBS_INTERROGATE:
5320 dbug(1, dprintf("CCBS Interrogate"));
5321 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5322 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5323 break;
5325 PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5326 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5327 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5328 plci_remove(plci);
5329 break;
5331 case ACTIVATION_MWI:
5332 case DEACTIVATION_MWI:
5333 if (pty_cai[5] == ACTIVATION_MWI)
5335 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5337 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5338 if (plci->cr_enquiry)
5340 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5341 plci_remove(plci);
5343 else
5345 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5347 break;
5348 case MWI_INDICATION:
5349 if (pty_cai[0] >= 0x12)
5351 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5352 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5353 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5354 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5356 if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5358 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5359 plci_remove(plci);
5360 return;
5362 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5363 pty_cai[0] = 0;
5365 else
5367 for (i = 0; i < max_appl; i++)
5369 if (a->Notification_Mask[i]&SMASK_MWI)
5371 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5372 pty_cai[0] = 0;
5377 if (!pty_cai[0])
5378 { /* acknowledge */
5379 facility[2] = 0; /* returncode */
5381 else facility[2] = 0xff;
5383 else
5385 /* reject */
5386 facility[2] = 0xff; /* returncode */
5388 facility[0] = 2;
5389 facility[1] = MWI_RESPONSE; /* Function */
5390 add_p(plci, CAI, facility);
5391 add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5392 sig_req(plci, S_SERVICE, 0);
5393 send_req(plci);
5394 plci->command = 0;
5395 next_internal_command(Id, plci);
5396 break;
5397 case CONF_ADD: /* OK */
5398 case CONF_BEGIN:
5399 case CONF_DROP:
5400 case CONF_ISOLATE:
5401 case CONF_REATTACH:
5402 case CONF_PARTYDISC:
5403 CONF_Ind[0] = 9;
5404 CONF_Ind[3] = 6;
5405 switch (pty_cai[5])
5407 case CONF_BEGIN:
5408 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5409 if (pty_cai[0] == 6)
5411 d = pty_cai[6];
5412 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5414 else
5416 PUT_DWORD(&CONF_Ind[6], 0x0);
5418 break;
5419 case CONF_ISOLATE:
5420 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5421 CONF_Ind[0] = 5;
5422 CONF_Ind[3] = 2;
5423 break;
5424 case CONF_REATTACH:
5425 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5426 CONF_Ind[0] = 5;
5427 CONF_Ind[3] = 2;
5428 break;
5429 case CONF_DROP:
5430 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5431 CONF_Ind[0] = 5;
5432 CONF_Ind[3] = 2;
5433 break;
5434 case CONF_ADD:
5435 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5436 d = pty_cai[6];
5437 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5438 tplci = plci->relatedPTYPLCI;
5439 if (tplci) tplci->ptyState = CONNECTED;
5440 break;
5441 case CONF_PARTYDISC:
5442 CONF_Ind[0] = 7;
5443 CONF_Ind[3] = 4;
5444 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5445 d = pty_cai[6];
5446 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5447 break;
5449 plci->ptyState = CONNECTED;
5450 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5451 break;
5452 case CCBS_INFO_RETAIN:
5453 case CCBS_ERASECALLLINKAGEID:
5454 case CCBS_STOP_ALERTING:
5455 CONF_Ind[0] = 5;
5456 CONF_Ind[3] = 2;
5457 switch (pty_cai[5])
5459 case CCBS_INFO_RETAIN:
5460 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5461 break;
5462 case CCBS_STOP_ALERTING:
5463 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5464 break;
5465 case CCBS_ERASECALLLINKAGEID:
5466 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5467 CONF_Ind[0] = 7;
5468 CONF_Ind[3] = 4;
5469 CONF_Ind[6] = 0;
5470 CONF_Ind[7] = 0;
5471 break;
5473 w = pty_cai[6];
5474 PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5476 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5478 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5480 else
5482 for (i = 0; i < max_appl; i++)
5483 if (a->Notification_Mask[i] & SMASK_CCBS)
5484 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5486 break;
5488 break;
5489 case CALL_HOLD_REJ:
5490 cau = parms[7];
5491 if (cau)
5493 i = _L3_CAUSE | cau[2];
5494 if (cau[2] == 0) i = 0x3603;
5496 else
5498 i = 0x3603;
5500 PUT_WORD(&SS_Ind[1], S_HOLD);
5501 PUT_WORD(&SS_Ind[4], i);
5502 if (plci->SuppState == HOLD_REQUEST)
5504 plci->SuppState = IDLE;
5505 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5507 break;
5509 case CALL_HOLD_ACK:
5510 if (plci->SuppState == HOLD_REQUEST)
5512 plci->SuppState = CALL_HELD;
5513 CodecIdCheck(a, plci);
5514 start_internal_command(Id, plci, hold_save_command);
5516 break;
5518 case CALL_RETRIEVE_REJ:
5519 cau = parms[7];
5520 if (cau)
5522 i = _L3_CAUSE | cau[2];
5523 if (cau[2] == 0) i = 0x3603;
5525 else
5527 i = 0x3603;
5529 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5530 PUT_WORD(&SS_Ind[4], i);
5531 if (plci->SuppState == RETRIEVE_REQUEST)
5533 plci->SuppState = CALL_HELD;
5534 CodecIdCheck(a, plci);
5535 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5537 break;
5539 case CALL_RETRIEVE_ACK:
5540 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5541 if (plci->SuppState == RETRIEVE_REQUEST)
5543 plci->SuppState = IDLE;
5544 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5545 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5546 if (plci->tel)
5548 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5549 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5550 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5551 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5553 dbug(1, dprintf("Get B-ch"));
5554 start_internal_command(Id, plci, retrieve_restore_command);
5556 else
5557 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5559 else
5560 start_internal_command(Id, plci, retrieve_restore_command);
5562 break;
5564 case INDICATE_IND:
5565 if (plci->State != LISTENING) {
5566 sig_req(plci, HANGUP, 0);
5567 send_req(plci);
5568 break;
5570 cip = find_cip(a, parms[4], parms[6]);
5571 cip_mask = 1L << cip;
5572 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5573 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5574 if (!remove_started && !a->adapter_disabled)
5576 group_optimization(a, plci);
5577 for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5578 if (application[i].Id
5579 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5580 && CPN_filter_ok(parms[0], a, i)) {
5581 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5582 __set_bit(i, plci->c_ind_mask_table);
5583 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5584 plci->State = INC_CON_PENDING;
5585 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5586 CALL_DIR_IN | CALL_DIR_ANSWER;
5587 if (esc_chi[0]) {
5588 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5589 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5591 /* if a listen on the ext controller is done, check if hook states */
5592 /* are supported or if just a on board codec must be activated */
5593 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5594 if (a->profile.Global_Options & HANDSET)
5595 plci->tel = ADV_VOICE;
5596 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5597 plci->tel = CODEC;
5598 if (plci->tel) Id |= EXT_CONTROLLER;
5599 a->codec_listen[i] = plci;
5602 sendf(&application[i], _CONNECT_I, Id, 0,
5603 "wSSSSSSSbSSSSS", cip, /* CIP */
5604 parms[0], /* CalledPartyNumber */
5605 multi_CiPN_parms[0], /* CallingPartyNumber */
5606 parms[2], /* CalledPartySubad */
5607 parms[3], /* CallingPartySubad */
5608 parms[4], /* BearerCapability */
5609 parms[5], /* LowLC */
5610 parms[6], /* HighLC */
5611 ai_len, /* nested struct add_i */
5612 add_i[0], /* B channel info */
5613 add_i[1], /* keypad facility */
5614 add_i[2], /* user user data */
5615 add_i[3], /* nested facility */
5616 multi_CiPN_parms[1] /* second CiPN(SCR) */
5618 SendSSExtInd(&application[i],
5619 plci,
5621 multi_ssext_parms);
5622 SendSetupInfo(&application[i],
5623 plci,
5625 parms,
5626 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5629 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5631 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5632 sig_req(plci, HANGUP, 0);
5633 send_req(plci);
5634 plci->State = IDLE;
5636 plci->notifiedcall = 0;
5637 a->listen_active--;
5638 listen_check(a);
5639 break;
5641 case CALL_PEND_NOTIFY:
5642 plci->notifiedcall = 1;
5643 listen_check(a);
5644 break;
5646 case CALL_IND:
5647 case CALL_CON:
5648 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5650 if (plci->internal_command == PERM_COD_CONN_PEND)
5652 if (plci->State == ADVANCED_VOICE_NOSIG)
5654 dbug(1, dprintf("***Codec OK"));
5655 if (a->AdvSignalPLCI)
5657 tplci = a->AdvSignalPLCI;
5658 if (tplci->spoofed_msg)
5660 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5661 tplci->command = 0;
5662 tplci->internal_command = 0;
5663 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5664 switch (tplci->spoofed_msg)
5666 case CALL_RES:
5667 tplci->command = _CONNECT_I | RESPONSE;
5668 api_load_msg(&tplci->saved_msg, saved_parms);
5669 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5670 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5672 /* early B3 connect (CIP mask bit 9) no release after a disc */
5673 add_p(tplci, LLI, "\x01\x01");
5675 add_s(tplci, CONN_NR, &saved_parms[2]);
5676 add_s(tplci, LLC, &saved_parms[4]);
5677 add_ai(tplci, &saved_parms[5]);
5678 tplci->State = INC_CON_ACCEPT;
5679 sig_req(tplci, CALL_RES, 0);
5680 send_req(tplci);
5681 break;
5683 case AWAITING_SELECT_B:
5684 dbug(1, dprintf("Select_B continue"));
5685 start_internal_command(x_Id, tplci, select_b_command);
5686 break;
5688 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5689 if (!tplci->Sig.Id)
5691 dbug(1, dprintf("No SigID!"));
5692 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5693 plci_remove(tplci);
5694 break;
5696 tplci->command = _MANUFACTURER_R;
5697 api_load_msg(&tplci->saved_msg, saved_parms);
5698 dir = saved_parms[2].info[0];
5699 if (dir == 1) {
5700 sig_req(tplci, CALL_REQ, 0);
5702 else if (!dir) {
5703 sig_req(tplci, LISTEN_REQ, 0);
5705 send_req(tplci);
5706 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5707 break;
5709 case (CALL_REQ | AWAITING_MANUF_CON):
5710 sig_req(tplci, CALL_REQ, 0);
5711 send_req(tplci);
5712 break;
5714 case CALL_REQ:
5715 if (!tplci->Sig.Id)
5717 dbug(1, dprintf("No SigID!"));
5718 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5719 plci_remove(tplci);
5720 break;
5722 tplci->command = _CONNECT_R;
5723 api_load_msg(&tplci->saved_msg, saved_parms);
5724 add_s(tplci, CPN, &saved_parms[1]);
5725 add_s(tplci, DSA, &saved_parms[3]);
5726 add_ai(tplci, &saved_parms[9]);
5727 sig_req(tplci, CALL_REQ, 0);
5728 send_req(tplci);
5729 break;
5731 case CALL_RETRIEVE:
5732 tplci->command = C_RETRIEVE_REQ;
5733 sig_req(tplci, CALL_RETRIEVE, 0);
5734 send_req(tplci);
5735 break;
5737 tplci->spoofed_msg = 0;
5738 if (tplci->internal_command == 0)
5739 next_internal_command(x_Id, tplci);
5742 next_internal_command(Id, plci);
5743 break;
5745 dbug(1, dprintf("***Codec Hook Init Req"));
5746 plci->internal_command = PERM_COD_HOOK;
5747 add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5748 sig_req(plci, TEL_CTRL, 0);
5749 send_req(plci);
5752 else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5753 && plci->State != INC_ACT_PENDING)
5755 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5756 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5758 chi[2] = plci->b_channel;
5759 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5761 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5762 plci->State = INC_ACT_PENDING;
5764 break;
5766 case TEL_CTRL:
5767 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5768 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5769 switch (ie[1] & 0x91) {
5770 case 0x80: /* hook off */
5771 case 0x81:
5772 if (plci->internal_command == PERM_COD_HOOK)
5774 dbug(1, dprintf("init:hook_off"));
5775 plci->hook_state = ie[1];
5776 next_internal_command(Id, plci);
5777 break;
5779 else /* ignore doubled hook indications */
5781 if (((plci->hook_state) & 0xf0) == 0x80)
5783 dbug(1, dprintf("ignore hook"));
5784 break;
5786 plci->hook_state = ie[1]&0x91;
5788 /* check for incoming call pending */
5789 /* and signal '+'.Appl must decide */
5790 /* with connect_res if call must */
5791 /* accepted or not */
5792 for (i = 0, tplci = NULL; i < max_appl; i++) {
5793 if (a->codec_listen[i]
5794 && (a->codec_listen[i]->State == INC_CON_PENDING
5795 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5796 tplci = a->codec_listen[i];
5797 tplci->appl = &application[i];
5800 /* no incoming call, do outgoing call */
5801 /* and signal '+' if outg. setup */
5802 if (!a->AdvSignalPLCI && !tplci) {
5803 if ((i = get_plci(a))) {
5804 a->AdvSignalPLCI = &a->plci[i - 1];
5805 tplci = a->AdvSignalPLCI;
5806 tplci->tel = ADV_VOICE;
5807 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5808 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5809 /* early B3 connect (CIP mask bit 9) no release after a disc */
5810 add_p(tplci, LLI, "\x01\x01");
5812 add_p(tplci, CAI, voice_cai);
5813 add_p(tplci, OAD, a->TelOAD);
5814 add_p(tplci, OSA, a->TelOSA);
5815 add_p(tplci, SHIFT | 6, NULL);
5816 add_p(tplci, SIN, "\x02\x01\x00");
5817 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5818 sig_req(tplci, ASSIGN, DSIG_ID);
5819 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5820 a->AdvSignalPLCI->command = 0;
5821 tplci->appl = a->AdvSignalAppl;
5822 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5823 send_req(tplci);
5828 if (!tplci) break;
5829 Id = ((word)tplci->Id << 8) | a->Id;
5830 Id |= EXT_CONTROLLER;
5831 sendf(tplci->appl,
5832 _FACILITY_I,
5835 "ws", (word)0, "\x01+");
5836 break;
5838 case 0x90: /* hook on */
5839 case 0x91:
5840 if (plci->internal_command == PERM_COD_HOOK)
5842 dbug(1, dprintf("init:hook_on"));
5843 plci->hook_state = ie[1] & 0x91;
5844 next_internal_command(Id, plci);
5845 break;
5847 else /* ignore doubled hook indications */
5849 if (((plci->hook_state) & 0xf0) == 0x90) break;
5850 plci->hook_state = ie[1] & 0x91;
5852 /* hangup the adv. voice call and signal '-' to the appl */
5853 if (a->AdvSignalPLCI) {
5854 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5855 if (plci->tel) Id |= EXT_CONTROLLER;
5856 sendf(a->AdvSignalAppl,
5857 _FACILITY_I,
5860 "ws", (word)0, "\x01-");
5861 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5862 a->AdvSignalPLCI->command = 0;
5863 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5864 send_req(a->AdvSignalPLCI);
5866 break;
5869 break;
5871 case RESUME:
5872 __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5873 PUT_WORD(&resume_cau[4], GOOD);
5874 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5875 break;
5877 case SUSPEND:
5878 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5880 if (plci->NL.Id && !plci->nl_remove_id) {
5881 mixer_remove(plci);
5882 nl_req_ncci(plci, REMOVE, 0);
5884 if (!plci->sig_remove_id) {
5885 plci->internal_command = 0;
5886 sig_req(plci, REMOVE, 0);
5888 send_req(plci);
5889 if (!plci->channels) {
5890 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5891 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5893 break;
5895 case SUSPEND_REJ:
5896 break;
5898 case HANGUP:
5899 plci->hangup_flow_ctrl_timer = 0;
5900 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5901 cau = parms[7];
5902 if (cau) {
5903 i = _L3_CAUSE | cau[2];
5904 if (cau[2] == 0) i = 0;
5905 else if (cau[2] == 8) i = _L1_ERROR;
5906 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5907 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5909 else {
5910 i = _L3_ERROR;
5913 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5915 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5916 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5918 else
5920 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5922 if (!plci->appl)
5924 if (plci->State == LISTENING)
5926 plci->notifiedcall = 0;
5927 a->listen_active--;
5929 plci->State = INC_DIS_PENDING;
5930 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5932 plci->State = IDLE;
5933 if (plci->NL.Id && !plci->nl_remove_id)
5935 mixer_remove(plci);
5936 nl_req_ncci(plci, REMOVE, 0);
5938 if (!plci->sig_remove_id)
5940 plci->internal_command = 0;
5941 sig_req(plci, REMOVE, 0);
5943 send_req(plci);
5946 else
5948 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
5949 /* result in a second HANGUP! Don't generate another */
5950 /* DISCONNECT */
5951 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5953 if (plci->State == RESUMING)
5955 PUT_WORD(&resume_cau[4], i);
5956 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5958 plci->State = INC_DIS_PENDING;
5959 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5962 break;
5964 case SSEXT_IND:
5965 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5966 break;
5968 case VSWITCH_REQ:
5969 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5970 break;
5971 case VSWITCH_IND:
5972 if (plci->relatedPTYPLCI &&
5973 plci->vswitchstate == 3 &&
5974 plci->relatedPTYPLCI->vswitchstate == 3 &&
5975 parms[MAXPARMSIDS - 1][0])
5977 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5978 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5979 send_req(plci->relatedPTYPLCI);
5981 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5982 break;
5988 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5990 word i;
5991 byte *ie;
5992 word Info_Number;
5993 byte *Info_Element;
5994 word Info_Mask = 0;
5996 dbug(1, dprintf("SetupInfo"));
5998 for (i = 0; i < MAXPARMSIDS; i++) {
5999 ie = parms[i];
6000 Info_Number = 0;
6001 Info_Element = ie;
6002 if (ie[0]) {
6003 switch (i) {
6004 case 0:
6005 dbug(1, dprintf("CPN "));
6006 Info_Number = 0x0070;
6007 Info_Mask = 0x80;
6008 Info_Sent_Flag = true;
6009 break;
6010 case 8: /* display */
6011 dbug(1, dprintf("display(%d)", i));
6012 Info_Number = 0x0028;
6013 Info_Mask = 0x04;
6014 Info_Sent_Flag = true;
6015 break;
6016 case 16: /* Channel Id */
6017 dbug(1, dprintf("CHI"));
6018 Info_Number = 0x0018;
6019 Info_Mask = 0x100;
6020 Info_Sent_Flag = true;
6021 mixer_set_bchannel_id(plci, Info_Element);
6022 break;
6023 case 19: /* Redirected Number */
6024 dbug(1, dprintf("RDN"));
6025 Info_Number = 0x0074;
6026 Info_Mask = 0x400;
6027 Info_Sent_Flag = true;
6028 break;
6029 case 20: /* Redirected Number extended */
6030 dbug(1, dprintf("RDX"));
6031 Info_Number = 0x0073;
6032 Info_Mask = 0x400;
6033 Info_Sent_Flag = true;
6034 break;
6035 case 22: /* Redirecing Number */
6036 dbug(1, dprintf("RIN"));
6037 Info_Number = 0x0076;
6038 Info_Mask = 0x400;
6039 Info_Sent_Flag = true;
6040 break;
6041 default:
6042 Info_Number = 0;
6043 break;
6047 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6048 Info_Number = 0x8000 | 5;
6049 Info_Mask = 0x10;
6050 Info_Element = "";
6053 if (Info_Sent_Flag && Info_Number) {
6054 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6055 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6062 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6064 word i;
6065 word j;
6066 word k;
6067 byte *ie;
6068 word Info_Number;
6069 byte *Info_Element;
6070 word Info_Mask = 0;
6071 static byte charges[5] = {4, 0, 0, 0, 0};
6072 static byte cause[] = {0x02, 0x80, 0x00};
6073 APPL *appl;
6075 dbug(1, dprintf("InfoParse "));
6077 if (
6078 !plci->appl
6079 && !plci->State
6080 && plci->Sig.Ind != NCR_FACILITY
6083 dbug(1, dprintf("NoParse "));
6084 return;
6086 cause[2] = 0;
6087 for (i = 0; i < MAXPARMSIDS; i++) {
6088 ie = parms[i];
6089 Info_Number = 0;
6090 Info_Element = ie;
6091 if (ie[0]) {
6092 switch (i) {
6093 case 0:
6094 dbug(1, dprintf("CPN "));
6095 Info_Number = 0x0070;
6096 Info_Mask = 0x80;
6097 break;
6098 case 7: /* ESC_CAU */
6099 dbug(1, dprintf("cau(0x%x)", ie[2]));
6100 Info_Number = 0x0008;
6101 Info_Mask = 0x00;
6102 cause[2] = ie[2];
6103 Info_Element = NULL;
6104 break;
6105 case 8: /* display */
6106 dbug(1, dprintf("display(%d)", i));
6107 Info_Number = 0x0028;
6108 Info_Mask = 0x04;
6109 break;
6110 case 9: /* Date display */
6111 dbug(1, dprintf("date(%d)", i));
6112 Info_Number = 0x0029;
6113 Info_Mask = 0x02;
6114 break;
6115 case 10: /* charges */
6116 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6117 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6118 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6119 Info_Number = 0x4000;
6120 Info_Mask = 0x40;
6121 Info_Element = charges;
6122 break;
6123 case 11: /* user user info */
6124 dbug(1, dprintf("uui"));
6125 Info_Number = 0x007E;
6126 Info_Mask = 0x08;
6127 break;
6128 case 12: /* congestion receiver ready */
6129 dbug(1, dprintf("clRDY"));
6130 Info_Number = 0x00B0;
6131 Info_Mask = 0x08;
6132 Info_Element = "";
6133 break;
6134 case 13: /* congestion receiver not ready */
6135 dbug(1, dprintf("clNRDY"));
6136 Info_Number = 0x00BF;
6137 Info_Mask = 0x08;
6138 Info_Element = "";
6139 break;
6140 case 15: /* Keypad Facility */
6141 dbug(1, dprintf("KEY"));
6142 Info_Number = 0x002C;
6143 Info_Mask = 0x20;
6144 break;
6145 case 16: /* Channel Id */
6146 dbug(1, dprintf("CHI"));
6147 Info_Number = 0x0018;
6148 Info_Mask = 0x100;
6149 mixer_set_bchannel_id(plci, Info_Element);
6150 break;
6151 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6152 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6153 if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6154 Info_Number = 0x0008;
6155 Info_Mask = 0x01;
6156 if (cause[2] != ie[2]) Info_Element = cause;
6157 break;
6158 case 19: /* Redirected Number */
6159 dbug(1, dprintf("RDN"));
6160 Info_Number = 0x0074;
6161 Info_Mask = 0x400;
6162 break;
6163 case 22: /* Redirecing Number */
6164 dbug(1, dprintf("RIN"));
6165 Info_Number = 0x0076;
6166 Info_Mask = 0x400;
6167 break;
6168 case 23: /* Notification Indicator */
6169 dbug(1, dprintf("NI"));
6170 Info_Number = (word)NI;
6171 Info_Mask = 0x210;
6172 break;
6173 case 26: /* Call State */
6174 dbug(1, dprintf("CST"));
6175 Info_Number = (word)CST;
6176 Info_Mask = 0x01; /* do with cause i.e. for now */
6177 break;
6178 case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6179 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6180 Info_Number = 0x8000 | ie[3];
6181 if (iesent) Info_Mask = 0xffff;
6182 else Info_Mask = 0x10;
6183 Info_Element = "";
6184 break;
6185 default:
6186 Info_Number = 0;
6187 Info_Mask = 0;
6188 Info_Element = "";
6189 break;
6193 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6195 for (j = 0; j < max_appl; j++)
6197 appl = &application[j];
6198 if (Info_Number
6199 && appl->Id
6200 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6202 dbug(1, dprintf("NCR_Ind"));
6203 iesent = true;
6204 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6208 else if (!plci->appl)
6209 { /* overlap receiving broadcast */
6210 if (Info_Number == CPN
6211 || Info_Number == KEY
6212 || Info_Number == NI
6213 || Info_Number == DSP
6214 || Info_Number == UUI)
6216 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6217 dbug(1, dprintf("Ovl_Ind"));
6218 iesent = true;
6219 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6222 } /* all other signalling states */
6223 else if (Info_Number
6224 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6226 dbug(1, dprintf("Std_Ind"));
6227 iesent = true;
6228 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6234 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6235 dword info_mask, byte setupParse)
6237 word i;
6238 word j;
6239 byte *ie;
6240 word Info_Number;
6241 byte *Info_Element;
6242 APPL *appl;
6243 word Info_Mask = 0;
6244 byte iesent = 0;
6246 if (
6247 !plci->appl
6248 && !plci->State
6249 && plci->Sig.Ind != NCR_FACILITY
6250 && !setupParse
6253 dbug(1, dprintf("NoM-IEParse "));
6254 return 0;
6256 dbug(1, dprintf("M-IEParse "));
6258 for (i = 0; i < MAX_MULTI_IE; i++)
6260 ie = parms[i];
6261 Info_Number = 0;
6262 Info_Element = ie;
6263 if (ie[0])
6265 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6266 Info_Number = (word)ie_type;
6267 Info_Mask = (word)info_mask;
6270 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6272 for (j = 0; j < max_appl; j++)
6274 appl = &application[j];
6275 if (Info_Number
6276 && appl->Id
6277 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6279 iesent = true;
6280 dbug(1, dprintf("Mlt_NCR_Ind"));
6281 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6285 else if (!plci->appl && Info_Number)
6286 { /* overlap receiving broadcast */
6287 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6288 iesent = true;
6289 dbug(1, dprintf("Mlt_Ovl_Ind"));
6290 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6292 } /* all other signalling states */
6293 else if (Info_Number
6294 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6296 iesent = true;
6297 dbug(1, dprintf("Mlt_Std_Ind"));
6298 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6301 return iesent;
6304 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6306 word i;
6307 /* Format of multi_ssext_parms[i][]:
6308 0 byte length
6309 1 byte SSEXTIE
6310 2 byte SSEXT_REQ/SSEXT_IND
6311 3 byte length
6312 4 word SSExtCommand
6313 6... Params
6315 if (
6316 plci
6317 && plci->State
6318 && plci->Sig.Ind != NCR_FACILITY
6320 for (i = 0; i < MAX_MULTI_IE; i++)
6322 if (parms[i][0] < 6) continue;
6323 if (parms[i][2] == SSEXT_REQ) continue;
6325 if (appl)
6327 parms[i][0] = 0; /* kill it */
6328 sendf(appl, _MANUFACTURER_I,
6331 "dwS",
6332 _DI_MANU_ID,
6333 _DI_SSEXT_CTRL,
6334 &parms[i][3]);
6336 else if (plci->appl)
6338 parms[i][0] = 0; /* kill it */
6339 sendf(plci->appl, _MANUFACTURER_I,
6342 "dwS",
6343 _DI_MANU_ID,
6344 _DI_SSEXT_CTRL,
6345 &parms[i][3]);
6350 static void nl_ind(PLCI *plci)
6352 byte ch;
6353 word ncci;
6354 dword Id;
6355 DIVA_CAPI_ADAPTER *a;
6356 word NCCIcode;
6357 APPL *APPLptr;
6358 word count;
6359 word Num;
6360 word i, ncpi_state;
6361 byte len, ncci_state;
6362 word msg;
6363 word info = 0;
6364 word fax_feature_bits;
6365 byte fax_send_edata_ack;
6366 static byte v120_header_buffer[2 + 3];
6367 static word fax_info[] = {
6368 0, /* T30_SUCCESS */
6369 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6370 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6371 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6372 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6373 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6374 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6375 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6376 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6377 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6378 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6379 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6380 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6381 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6382 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6383 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6384 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6385 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6386 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6387 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6388 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6389 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6390 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6391 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6392 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6393 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6394 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6395 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6396 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6397 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6398 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6399 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6400 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6401 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6402 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6403 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6404 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6405 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6406 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6407 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6408 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6409 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6410 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6411 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6412 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6413 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6414 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6417 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6420 static word rtp_info[] = {
6421 GOOD, /* RTP_SUCCESS */
6422 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6425 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6427 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6428 0x00000000, 0x00000000, 0x00000000, 0x00000000
6431 ch = plci->NL.IndCh;
6432 a = plci->adapter;
6433 ncci = a->ch_ncci[ch];
6434 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6435 if (plci->tel) Id |= EXT_CONTROLLER;
6436 APPLptr = plci->appl;
6437 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",
6438 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6440 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6442 if (plci->nl_remove_id)
6444 plci->NL.RNR = 2; /* discard */
6445 dbug(1, dprintf("NL discard while remove pending"));
6446 return;
6448 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6450 if (plci->State == INC_DIS_PENDING
6451 || plci->State == OUTG_DIS_PENDING
6452 || plci->State == IDLE)
6454 plci->NL.RNR = 2; /* discard */
6455 dbug(1, dprintf("discard n_connect"));
6456 return;
6458 if (plci->State < INC_ACT_PENDING)
6460 plci->NL.RNR = 1; /* flow control */
6461 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6462 return;
6466 if (!APPLptr) /* no application or invalid data */
6467 { /* while reloading the DSP */
6468 dbug(1, dprintf("discard1"));
6469 plci->NL.RNR = 2;
6470 return;
6473 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6474 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6475 || (plci->B2_prot == 7)
6476 || (plci->B3_prot == 7)))
6478 plci->ncpi_buffer[0] = 0;
6480 ncpi_state = plci->ncpi_state;
6481 if (plci->NL.complete == 1)
6483 byte *data = &plci->NL.RBuffer->P[0];
6485 if ((plci->NL.RBuffer->length >= 12)
6486 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6487 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6489 word conn_opt, ncpi_opt = 0x00;
6490 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6492 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6493 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6494 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6495 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6497 data++; /* indication code */
6498 data += 2; /* timestamp */
6499 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6500 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6501 data++; /* connected norm */
6502 conn_opt = GET_WORD(data);
6503 data += 2; /* connected options */
6505 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6507 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6509 ncpi_opt |= MDM_NCPI_ECM_V42;
6511 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6513 ncpi_opt |= MDM_NCPI_ECM_MNP;
6515 else
6517 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6519 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6521 ncpi_opt |= MDM_NCPI_COMPRESSED;
6523 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6524 plci->ncpi_buffer[0] = 4;
6526 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6529 if (plci->B3_prot == 7)
6531 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6532 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6533 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6535 a->ncci_state[ncci] = INC_ACT_PENDING;
6536 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6537 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6541 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6542 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6543 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6544 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6547 plci->NL.RNR = 2;
6548 return;
6552 if (plci->NL.complete == 2)
6554 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6555 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6557 switch (plci->RData[0].P[0])
6560 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6561 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6562 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6563 break;
6564 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6565 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6566 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6567 break;
6568 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6569 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6570 break;
6571 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6572 dtmf_confirmation(Id, plci);
6573 break;
6576 case UDATA_INDICATION_MIXER_TAP_DATA:
6577 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6578 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6579 if (i != 0)
6581 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6582 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6584 break;
6587 case UDATA_INDICATION_MIXER_COEFS_SET:
6588 mixer_indication_coefs_set(Id, plci);
6589 break;
6590 case UDATA_INDICATION_XCONNECT_FROM:
6591 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6592 break;
6593 case UDATA_INDICATION_XCONNECT_TO:
6594 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6595 break;
6598 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6599 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6600 break;
6604 default:
6605 break;
6608 else
6610 if ((plci->RData[0].PLength != 0)
6611 && ((plci->B2_prot == B2_V120_ASYNC)
6612 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6613 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6616 sendf(plci->appl, _DATA_B3_I, Id, 0,
6617 "dwww",
6618 plci->RData[1].P,
6619 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6620 plci->RNum,
6621 plci->RFlags);
6624 else
6627 sendf(plci->appl, _DATA_B3_I, Id, 0,
6628 "dwww",
6629 plci->RData[0].P,
6630 plci->RData[0].PLength,
6631 plci->RNum,
6632 plci->RFlags);
6636 return;
6639 fax_feature_bits = 0;
6640 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6641 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6642 (plci->NL.Ind & 0x0f) == N_DISC ||
6643 (plci->NL.Ind & 0x0f) == N_EDATA ||
6644 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6646 info = 0;
6647 plci->ncpi_buffer[0] = 0;
6648 switch (plci->B3_prot) {
6649 case 0: /*XPARENT*/
6650 case 1: /*T.90 NL*/
6651 break; /* no network control protocol info - jfr */
6652 case 2: /*ISO8202*/
6653 case 3: /*X25 DCE*/
6654 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6655 plci->ncpi_buffer[0] = (byte)(i + 3);
6656 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6657 plci->ncpi_buffer[2] = 0;
6658 plci->ncpi_buffer[3] = 0;
6659 break;
6660 case 4: /*T.30 - FAX*/
6661 case 5: /*T.30 - FAX*/
6662 if (plci->NL.RLength >= sizeof(T30_INFO))
6664 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6665 len = 9;
6666 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6667 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6668 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6669 if (plci->B3_prot == 5)
6671 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6672 i |= 0x8000; /* This is not an ECM connection */
6673 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6674 i |= 0x4000; /* This is a connection with MMR compression */
6675 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6676 i |= 0x2000; /* This is a connection with MR compression */
6677 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6678 i |= 0x0004; /* More documents */
6679 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6680 i |= 0x0002; /* Fax-polling indication */
6682 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6683 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6684 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6685 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6686 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6687 plci->ncpi_buffer[len] = 0;
6688 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6690 plci->ncpi_buffer[len] = 20;
6691 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6692 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6694 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6696 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6697 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6698 else
6699 info = _FAX_PROTOCOL_ERROR;
6702 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6703 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6705 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6706 while (i < plci->NL.RBuffer->length)
6707 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6710 plci->ncpi_buffer[0] = len;
6711 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6712 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6714 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6715 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6716 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6717 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6718 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6719 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6720 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6721 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6723 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6725 if (((plci->NL.Ind & 0x0f) == N_DISC)
6726 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6727 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6728 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6730 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6733 break;
6735 case B3_RTP:
6736 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6738 if (plci->NL.RLength != 0)
6740 info = rtp_info[plci->NL.RBuffer->P[0]];
6741 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6742 for (i = 1; i < plci->NL.RLength; i++)
6743 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6746 break;
6749 plci->NL.RNR = 2;
6751 switch (plci->NL.Ind & 0x0f) {
6752 case N_EDATA:
6753 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6755 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6756 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6757 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6759 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6760 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6761 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6762 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6763 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6764 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6766 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6767 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6768 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6769 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6770 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6771 fax_send_edata_ack = false;
6774 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6776 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6778 case EDATA_T30_DIS:
6779 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6780 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6781 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6782 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6784 a->ncci_state[ncci] = INC_ACT_PENDING;
6785 if (plci->B3_prot == 4)
6786 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6787 else
6788 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6789 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6791 break;
6793 case EDATA_T30_TRAIN_OK:
6794 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6795 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6796 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6798 if (plci->B3_prot == 4)
6799 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6800 else
6801 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6802 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6804 break;
6806 case EDATA_T30_EOP_CAPI:
6807 if (a->ncci_state[ncci] == CONNECTED)
6809 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6810 a->ncci_state[ncci] = INC_DIS_PENDING;
6811 plci->ncpi_state = 0;
6812 fax_send_edata_ack = false;
6814 break;
6817 else
6819 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6821 case EDATA_T30_TRAIN_OK:
6822 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6823 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6824 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6826 if (plci->B3_prot == 4)
6827 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6828 else
6829 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6830 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6832 break;
6835 if (fax_send_edata_ack)
6837 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6838 plci->fax_edata_ack_length = 1;
6839 start_internal_command(Id, plci, fax_edata_ack_command);
6842 else
6844 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6846 break;
6847 case N_CONNECT:
6848 if (!a->ch_ncci[ch])
6850 ncci = get_ncci(plci, ch, 0);
6851 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6853 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6854 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6856 msg = _CONNECT_B3_I;
6857 if (a->ncci_state[ncci] == IDLE)
6858 plci->channels++;
6859 else if (plci->B3_prot == 1)
6860 msg = _CONNECT_B3_T90_ACTIVE_I;
6862 a->ncci_state[ncci] = INC_CON_PENDING;
6863 if (plci->B3_prot == 4)
6864 sendf(plci->appl, msg, Id, 0, "s", "");
6865 else
6866 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6867 break;
6868 case N_CONNECT_ACK:
6869 dbug(1, dprintf("N_connect_Ack"));
6870 if (plci->internal_command_queue[0]
6871 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6872 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6873 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6875 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6876 if (!plci->internal_command)
6877 next_internal_command(Id, plci);
6878 break;
6880 msg = _CONNECT_B3_ACTIVE_I;
6881 if (plci->B3_prot == 1)
6883 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6884 msg = _CONNECT_B3_T90_ACTIVE_I;
6885 a->ncci_state[ncci] = INC_ACT_PENDING;
6886 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6888 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6890 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6891 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6892 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6894 a->ncci_state[ncci] = INC_ACT_PENDING;
6895 if (plci->B3_prot == 4)
6896 sendf(plci->appl, msg, Id, 0, "s", "");
6897 else
6898 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6899 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6902 else
6904 a->ncci_state[ncci] = INC_ACT_PENDING;
6905 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6907 if (plci->adjust_b_restore)
6909 plci->adjust_b_restore = false;
6910 start_internal_command(Id, plci, adjust_b_restore);
6912 break;
6913 case N_DISC:
6914 case N_DISC_ACK:
6915 if (plci->internal_command_queue[0]
6916 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6917 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6918 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6920 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6921 if (!plci->internal_command)
6922 next_internal_command(Id, plci);
6924 ncci_state = a->ncci_state[ncci];
6925 ncci_remove(plci, ncci, false);
6927 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
6928 /* channel, so we cannot store the state in ncci_state! The */
6929 /* information which channel we received a N_DISC is thus */
6930 /* stored in the inc_dis_ncci_table buffer. */
6931 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6932 plci->inc_dis_ncci_table[i] = (byte) ncci;
6934 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6935 if (!plci->channels
6936 && (plci->B1_resource == 16)
6937 && (plci->State <= CONNECTED))
6939 len = 9;
6940 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6941 PUT_WORD(&plci->ncpi_buffer[1], i);
6942 PUT_WORD(&plci->ncpi_buffer[3], 0);
6943 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6944 PUT_WORD(&plci->ncpi_buffer[5], i);
6945 PUT_WORD(&plci->ncpi_buffer[7], 0);
6946 plci->ncpi_buffer[len] = 0;
6947 plci->ncpi_buffer[0] = len;
6948 if (plci->B3_prot == 4)
6949 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6950 else
6953 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6954 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6956 plci->ncpi_buffer[++len] = 0;
6957 plci->ncpi_buffer[++len] = 0;
6958 plci->ncpi_buffer[++len] = 0;
6959 plci->ncpi_buffer[0] = len;
6962 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6964 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6965 plci->ncpi_state = 0;
6966 sig_req(plci, HANGUP, 0);
6967 send_req(plci);
6968 plci->State = OUTG_DIS_PENDING;
6969 /* disc here */
6971 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6972 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6973 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6975 if (ncci_state == IDLE)
6977 if (plci->channels)
6978 plci->channels--;
6979 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6980 if (plci->State == SUSPENDING) {
6981 sendf(plci->appl,
6982 _FACILITY_I,
6983 Id & 0xffffL,
6985 "ws", (word)3, "\x03\x04\x00\x00");
6986 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6988 plci_remove(plci);
6989 plci->State = IDLE;
6993 else if (plci->channels)
6995 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6996 plci->ncpi_state = 0;
6997 if ((ncci_state == OUTG_REJ_PENDING)
6998 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7000 sig_req(plci, HANGUP, 0);
7001 send_req(plci);
7002 plci->State = OUTG_DIS_PENDING;
7005 break;
7006 case N_RESET:
7007 a->ncci_state[ncci] = INC_RES_PENDING;
7008 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7009 break;
7010 case N_RESET_ACK:
7011 a->ncci_state[ncci] = CONNECTED;
7012 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7013 break;
7015 case N_UDATA:
7016 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7018 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7019 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7020 plci->NL.R = plci->RData;
7021 plci->NL.RNum = 1;
7022 return;
7024 /* fall through */
7025 case N_BDATA:
7026 case N_DATA:
7027 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7028 || (a->ncci_state[ncci] == IDLE)
7029 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7031 plci->NL.RNR = 2;
7032 break;
7034 if ((a->ncci_state[ncci] != CONNECTED)
7035 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7036 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7038 dbug(1, dprintf("flow control"));
7039 plci->NL.RNR = 1; /* flow control */
7040 channel_x_off(plci, ch, 0);
7041 break;
7044 NCCIcode = ncci | (((word)a->Id) << 8);
7046 /* count all buffers within the Application pool */
7047 /* belonging to the same NCCI. If this is below the */
7048 /* number of buffers available per NCCI we accept */
7049 /* this packet, otherwise we reject it */
7050 count = 0;
7051 Num = 0xffff;
7052 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7053 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7054 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7057 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7059 dbug(3, dprintf("Flow-Control"));
7060 plci->NL.RNR = 1;
7061 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7062 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7064 plci->NL.RNR = 2;
7065 dbug(3, dprintf("DiscardData"));
7066 } else {
7067 channel_x_off(plci, ch, 0);
7069 break;
7071 else
7073 APPLptr->NCCIDataFlowCtrlTimer = 0;
7076 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7077 if (!plci->RData[0].P) {
7078 plci->NL.RNR = 1;
7079 channel_x_off(plci, ch, 0);
7080 break;
7083 APPLptr->DataNCCI[Num] = NCCIcode;
7084 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7085 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7087 plci->RNum = Num;
7088 plci->RFlags = plci->NL.Ind >> 4;
7089 plci->RData[0].PLength = APPLptr->MaxDataLength;
7090 plci->NL.R = plci->RData;
7091 if ((plci->NL.RLength != 0)
7092 && ((plci->B2_prot == B2_V120_ASYNC)
7093 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7094 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7096 plci->RData[1].P = plci->RData[0].P;
7097 plci->RData[1].PLength = plci->RData[0].PLength;
7098 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7099 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7100 plci->RData[0].PLength = 1;
7101 else
7102 plci->RData[0].PLength = 2;
7103 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7104 plci->RFlags |= 0x0010;
7105 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7106 plci->RFlags |= 0x8000;
7107 plci->NL.RNum = 2;
7109 else
7111 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7112 plci->RFlags |= 0x0010;
7114 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7115 plci->RFlags |= 0x0001;
7117 plci->NL.RNum = 1;
7119 break;
7120 case N_DATA_ACK:
7121 data_ack(plci, ch);
7122 break;
7123 default:
7124 plci->NL.RNR = 2;
7125 break;
7129 /*------------------------------------------------------------------*/
7130 /* find a free PLCI */
7131 /*------------------------------------------------------------------*/
7133 static word get_plci(DIVA_CAPI_ADAPTER *a)
7135 word i, j;
7136 PLCI *plci;
7138 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7139 if (i == a->max_plci) {
7140 dbug(1, dprintf("get_plci: out of PLCIs"));
7141 return 0;
7143 plci = &a->plci[i];
7144 plci->Id = (byte)(i + 1);
7146 plci->Sig.Id = 0;
7147 plci->NL.Id = 0;
7148 plci->sig_req = 0;
7149 plci->nl_req = 0;
7151 plci->appl = NULL;
7152 plci->relatedPTYPLCI = NULL;
7153 plci->State = IDLE;
7154 plci->SuppState = IDLE;
7155 plci->channels = 0;
7156 plci->tel = 0;
7157 plci->B1_resource = 0;
7158 plci->B2_prot = 0;
7159 plci->B3_prot = 0;
7161 plci->command = 0;
7162 plci->m_command = 0;
7163 init_internal_command_queue(plci);
7164 plci->number = 0;
7165 plci->req_in_start = 0;
7166 plci->req_in = 0;
7167 plci->req_out = 0;
7168 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7169 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7170 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7172 plci->data_sent = false;
7173 plci->send_disc = 0;
7174 plci->sig_global_req = 0;
7175 plci->sig_remove_id = 0;
7176 plci->nl_global_req = 0;
7177 plci->nl_remove_id = 0;
7178 plci->adv_nl = 0;
7179 plci->manufacturer = false;
7180 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7181 plci->spoofed_msg = 0;
7182 plci->ptyState = 0;
7183 plci->cr_enquiry = false;
7184 plci->hangup_flow_ctrl_timer = 0;
7186 plci->ncci_ring_list = 0;
7187 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7188 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7189 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7190 plci->fax_connect_info_length = 0;
7191 plci->nsf_control_bits = 0;
7192 plci->ncpi_state = 0x00;
7193 plci->ncpi_buffer[0] = 0;
7195 plci->requested_options_conn = 0;
7196 plci->requested_options = 0;
7197 plci->notifiedcall = 0;
7198 plci->vswitchstate = 0;
7199 plci->vsprot = 0;
7200 plci->vsprotdialect = 0;
7201 init_b1_config(plci);
7202 dbug(1, dprintf("get_plci(%x)", plci->Id));
7203 return i + 1;
7206 /*------------------------------------------------------------------*/
7207 /* put a parameter in the parameter buffer */
7208 /*------------------------------------------------------------------*/
7210 static void add_p(PLCI *plci, byte code, byte *p)
7212 word p_length;
7214 p_length = 0;
7215 if (p) p_length = p[0];
7216 add_ie(plci, code, p, p_length);
7219 /*------------------------------------------------------------------*/
7220 /* put a structure in the parameter buffer */
7221 /*------------------------------------------------------------------*/
7222 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7224 if (p) add_ie(plci, code, p->info, (word)p->length);
7227 /*------------------------------------------------------------------*/
7228 /* put multiple structures in the parameter buffer */
7229 /*------------------------------------------------------------------*/
7230 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7232 byte i;
7234 if (p) {
7235 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7236 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7237 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7238 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7243 /*------------------------------------------------------------------*/
7244 /* return the channel number sent by the application in a esc_chi */
7245 /*------------------------------------------------------------------*/
7246 static byte getChannel(API_PARSE *p)
7248 byte i;
7250 if (p) {
7251 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7252 if (p->info[i] == 2) {
7253 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7257 return 0;
7261 /*------------------------------------------------------------------*/
7262 /* put an information element in the parameter buffer */
7263 /*------------------------------------------------------------------*/
7265 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7267 word i;
7269 if (!(code & 0x80) && !p_length) return;
7271 if (plci->req_in == plci->req_in_start) {
7272 plci->req_in += 2;
7274 else {
7275 plci->req_in--;
7277 plci->RBuffer[plci->req_in++] = code;
7279 if (p) {
7280 plci->RBuffer[plci->req_in++] = (byte)p_length;
7281 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7284 plci->RBuffer[plci->req_in++] = 0;
7287 /*------------------------------------------------------------------*/
7288 /* put a unstructured data into the buffer */
7289 /*------------------------------------------------------------------*/
7291 static void add_d(PLCI *plci, word length, byte *p)
7293 word i;
7295 if (plci->req_in == plci->req_in_start) {
7296 plci->req_in += 2;
7298 else {
7299 plci->req_in--;
7301 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7304 /*------------------------------------------------------------------*/
7305 /* put parameters from the Additional Info parameter in the */
7306 /* parameter buffer */
7307 /*------------------------------------------------------------------*/
7309 static void add_ai(PLCI *plci, API_PARSE *ai)
7311 word i;
7312 API_PARSE ai_parms[5];
7314 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7316 if (!ai->length)
7317 return;
7318 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7319 return;
7321 add_s(plci, KEY, &ai_parms[1]);
7322 add_s(plci, UUI, &ai_parms[2]);
7323 add_ss(plci, FTY, &ai_parms[3]);
7326 /*------------------------------------------------------------------*/
7327 /* put parameter for b1 protocol in the parameter buffer */
7328 /*------------------------------------------------------------------*/
7330 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7331 word b1_facilities)
7333 API_PARSE bp_parms[8];
7334 API_PARSE mdm_cfg[9];
7335 API_PARSE global_config[2];
7336 byte cai[256];
7337 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7338 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7339 word i;
7341 API_PARSE mdm_cfg_v18[4];
7342 word j, n, w;
7343 dword d;
7346 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7347 for (i = 0; i < 2; i++) global_config[i].length = 0;
7349 dbug(1, dprintf("add_b1"));
7350 api_save_msg(bp, "s", &plci->B_protocol);
7352 if (b_channel_info == 2) {
7353 plci->B1_resource = 0;
7354 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7355 add_p(plci, CAI, "\x01\x00");
7356 dbug(1, dprintf("Cai=1,0 (no resource)"));
7357 return 0;
7360 if (plci->tel == CODEC_PERMANENT) return 0;
7361 else if (plci->tel == CODEC) {
7362 plci->B1_resource = 1;
7363 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7364 add_p(plci, CAI, "\x01\x01");
7365 dbug(1, dprintf("Cai=1,1 (Codec)"));
7366 return 0;
7368 else if (plci->tel == ADV_VOICE) {
7369 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7370 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7371 voice_cai[1] = plci->B1_resource;
7372 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7373 add_p(plci, CAI, voice_cai);
7374 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7375 return 0;
7377 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7378 if (plci->call_dir & CALL_DIR_OUT)
7379 plci->call_dir |= CALL_DIR_ORIGINATE;
7380 else if (plci->call_dir & CALL_DIR_IN)
7381 plci->call_dir |= CALL_DIR_ANSWER;
7383 if (!bp->length) {
7384 plci->B1_resource = 0x5;
7385 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7386 add_p(plci, CAI, "\x01\x05");
7387 return 0;
7390 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7391 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7392 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7394 bp_parms[6].length = 0;
7395 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7397 dbug(1, dprintf("b-form.!"));
7398 return _WRONG_MESSAGE_FORMAT;
7401 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7403 dbug(1, dprintf("b-form.!"));
7404 return _WRONG_MESSAGE_FORMAT;
7407 if (bp_parms[6].length)
7409 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7411 return _WRONG_MESSAGE_FORMAT;
7413 switch (GET_WORD(global_config[0].info))
7415 case 1:
7416 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7417 break;
7418 case 2:
7419 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7420 break;
7423 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7426 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7427 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7429 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7430 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7431 cai[1] = plci->B1_resource;
7432 cai[2] = 0;
7433 cai[3] = 0;
7434 cai[4] = 0;
7435 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7436 for (i = 0; i < bp_parms[3].length; i++)
7437 cai[7 + i] = bp_parms[3].info[1 + i];
7438 cai[0] = 6 + bp_parms[3].length;
7439 add_p(plci, CAI, cai);
7440 return 0;
7444 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7445 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7447 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7448 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7449 cai[1] = plci->B1_resource;
7450 cai[2] = 0;
7451 cai[3] = 0;
7452 cai[4] = 0;
7453 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7454 cai[0] = 6;
7455 add_p(plci, CAI, cai);
7456 return 0;
7460 if ((GET_WORD(bp_parms[0].info) >= 32)
7461 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7462 && ((GET_WORD(bp_parms[0].info) != 3)
7463 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7464 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7466 return _B1_NOT_SUPPORTED;
7468 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7469 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7470 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7471 cai[0] = 6;
7472 cai[1] = plci->B1_resource;
7473 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7475 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7476 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7477 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7478 { /* B1 - modem */
7479 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7481 if (bp_parms[3].length)
7483 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7485 return (_WRONG_MESSAGE_FORMAT);
7488 cai[2] = 0; /* Bit rate for adaptation */
7490 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7492 PUT_WORD(&cai[13], 0); /* Min Tx speed */
7493 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7494 PUT_WORD(&cai[17], 0); /* Min Rx speed */
7495 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7497 cai[3] = 0; /* Async framing parameters */
7498 switch (GET_WORD(mdm_cfg[2].info))
7499 { /* Parity */
7500 case 1: /* odd parity */
7501 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7502 dbug(1, dprintf("MDM: odd parity"));
7503 break;
7505 case 2: /* even parity */
7506 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7507 dbug(1, dprintf("MDM: even parity"));
7508 break;
7510 default:
7511 dbug(1, dprintf("MDM: no parity"));
7512 break;
7515 switch (GET_WORD(mdm_cfg[3].info))
7516 { /* stop bits */
7517 case 1: /* 2 stop bits */
7518 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7519 dbug(1, dprintf("MDM: 2 stop bits"));
7520 break;
7522 default:
7523 dbug(1, dprintf("MDM: 1 stop bit"));
7524 break;
7527 switch (GET_WORD(mdm_cfg[1].info))
7528 { /* char length */
7529 case 5:
7530 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7531 dbug(1, dprintf("MDM: 5 bits"));
7532 break;
7534 case 6:
7535 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7536 dbug(1, dprintf("MDM: 6 bits"));
7537 break;
7539 case 7:
7540 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7541 dbug(1, dprintf("MDM: 7 bits"));
7542 break;
7544 default:
7545 dbug(1, dprintf("MDM: 8 bits"));
7546 break;
7549 cai[7] = 0; /* Line taking options */
7550 cai[8] = 0; /* Modulation negotiation options */
7551 cai[9] = 0; /* Modulation options */
7553 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7555 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7556 dbug(1, dprintf("MDM: Reverse direction"));
7559 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7561 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7562 dbug(1, dprintf("MDM: Disable retrain"));
7565 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7567 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7568 dbug(1, dprintf("MDM: Disable ring tone"));
7571 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7573 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7574 dbug(1, dprintf("MDM: 1800 guard tone"));
7576 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7578 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7579 dbug(1, dprintf("MDM: 550 guard tone"));
7582 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7584 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7585 dbug(1, dprintf("MDM: V100"));
7587 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7589 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7590 dbug(1, dprintf("MDM: IN CLASS"));
7592 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7594 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7595 dbug(1, dprintf("MDM: DISABLED"));
7597 cai[0] = 20;
7599 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7600 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7602 plci->requested_options |= 1L << PRIVATE_V18;
7604 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7605 plci->requested_options |= 1L << PRIVATE_VOWN;
7607 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7608 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7610 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7612 i = 27;
7613 if (mdm_cfg[6].length >= 4)
7615 d = GET_DWORD(&mdm_cfg[6].info[1]);
7616 cai[7] |= (byte) d; /* line taking options */
7617 cai[9] |= (byte)(d >> 8); /* modulation options */
7618 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7619 cai[++i] = (byte)(d >> 24);
7620 if (mdm_cfg[6].length >= 8)
7622 d = GET_DWORD(&mdm_cfg[6].info[5]);
7623 cai[10] |= (byte) d; /* disabled modulations mask */
7624 cai[11] |= (byte)(d >> 8);
7625 if (mdm_cfg[6].length >= 12)
7627 d = GET_DWORD(&mdm_cfg[6].info[9]);
7628 cai[12] = (byte) d; /* enabled modulations mask */
7629 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7630 cai[++i] = (byte)(d >> 16);
7631 cai[++i] = (byte)(d >> 24);
7632 cai[++i] = 0;
7633 if (mdm_cfg[6].length >= 14)
7635 w = GET_WORD(&mdm_cfg[6].info[13]);
7636 if (w != 0)
7637 PUT_WORD(&cai[13], w); /* min tx speed */
7638 if (mdm_cfg[6].length >= 16)
7640 w = GET_WORD(&mdm_cfg[6].info[15]);
7641 if (w != 0)
7642 PUT_WORD(&cai[15], w); /* max tx speed */
7643 if (mdm_cfg[6].length >= 18)
7645 w = GET_WORD(&mdm_cfg[6].info[17]);
7646 if (w != 0)
7647 PUT_WORD(&cai[17], w); /* min rx speed */
7648 if (mdm_cfg[6].length >= 20)
7650 w = GET_WORD(&mdm_cfg[6].info[19]);
7651 if (w != 0)
7652 PUT_WORD(&cai[19], w); /* max rx speed */
7653 if (mdm_cfg[6].length >= 22)
7655 w = GET_WORD(&mdm_cfg[6].info[21]);
7656 cai[23] = (byte)(-((short) w)); /* transmit level */
7657 if (mdm_cfg[6].length >= 24)
7659 w = GET_WORD(&mdm_cfg[6].info[23]);
7660 cai[22] |= (byte) w; /* info options mask */
7661 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7671 cai[27] = i - 27;
7672 i++;
7673 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7675 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7677 for (n = 0; n < 3; n++)
7679 cai[i] = (byte)(mdm_cfg_v18[n].length);
7680 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7681 cai[i + j] = mdm_cfg_v18[n].info[j];
7682 i += cai[i] + 1;
7686 cai[0] = (byte)(i - 1);
7692 if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7693 GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7695 if (bp_parms[3].length) {
7696 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7697 switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7698 case 0:
7699 case 56000:
7700 if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7701 dbug(1, dprintf("56k sync HSCX"));
7702 cai[1] = 8;
7703 cai[2] = 0;
7704 cai[3] = 0;
7706 else if (GET_WORD(bp_parms[0].info) == 2) {
7707 dbug(1, dprintf("56k async DSP"));
7708 cai[2] = 9;
7710 break;
7711 case 50: cai[2] = 1; break;
7712 case 75: cai[2] = 1; break;
7713 case 110: cai[2] = 1; break;
7714 case 150: cai[2] = 1; break;
7715 case 200: cai[2] = 1; break;
7716 case 300: cai[2] = 1; break;
7717 case 600: cai[2] = 1; break;
7718 case 1200: cai[2] = 2; break;
7719 case 2400: cai[2] = 3; break;
7720 case 4800: cai[2] = 4; break;
7721 case 7200: cai[2] = 10; break;
7722 case 9600: cai[2] = 5; break;
7723 case 12000: cai[2] = 13; break;
7724 case 24000: cai[2] = 0; break;
7725 case 14400: cai[2] = 11; break;
7726 case 19200: cai[2] = 6; break;
7727 case 28800: cai[2] = 12; break;
7728 case 38400: cai[2] = 7; break;
7729 case 48000: cai[2] = 8; break;
7730 case 76: cai[2] = 15; break; /* 75/1200 */
7731 case 1201: cai[2] = 14; break; /* 1200/75 */
7732 case 56001: cai[2] = 9; break; /* V.110 56000 */
7734 default:
7735 return _B1_PARM_NOT_SUPPORTED;
7737 cai[3] = 0;
7738 if (cai[1] == 13) /* v.110 async */
7740 if (bp_parms[3].length >= 8)
7742 switch (GET_WORD(&bp_parms[3].info[3]))
7743 { /* char length */
7744 case 5:
7745 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7746 break;
7747 case 6:
7748 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7749 break;
7750 case 7:
7751 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7752 break;
7754 switch (GET_WORD(&bp_parms[3].info[5]))
7755 { /* Parity */
7756 case 1: /* odd parity */
7757 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7758 break;
7759 case 2: /* even parity */
7760 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7761 break;
7763 switch (GET_WORD(&bp_parms[3].info[7]))
7764 { /* stop bits */
7765 case 1: /* 2 stop bits */
7766 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7767 break;
7772 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7773 dbug(1, dprintf("V.110 default 56k sync"));
7774 cai[1] = 8;
7775 cai[2] = 0;
7776 cai[3] = 0;
7778 else {
7779 dbug(1, dprintf("V.110 default 9600 async"));
7780 cai[2] = 5;
7783 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7784 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]));
7785 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7787 add_p(plci, CAI, cai);
7788 return 0;
7791 /*------------------------------------------------------------------*/
7792 /* put parameter for b2 and B3 protocol in the parameter buffer */
7793 /*------------------------------------------------------------------*/
7795 static word add_b23(PLCI *plci, API_PARSE *bp)
7797 word i, fax_control_bits;
7798 byte pos, len;
7799 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7800 API_PARSE bp_parms[8];
7801 API_PARSE *b1_config;
7802 API_PARSE *b2_config;
7803 API_PARSE b2_config_parms[8];
7804 API_PARSE *b3_config;
7805 API_PARSE b3_config_parms[6];
7806 API_PARSE global_config[2];
7808 static byte llc[3] = {2,0,0};
7809 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7810 static byte nlc[256];
7811 static byte lli[12] = {1,1};
7813 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7814 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7816 const byte llc3[] = {4,3,2,2,6,6,0};
7817 const byte header[] = {0,2,3,3,0,0,0};
7819 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7820 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7821 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7823 lli[0] = 1;
7824 lli[1] = 1;
7825 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7826 lli[1] |= 2;
7827 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7828 lli[1] |= 4;
7830 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7831 lli[1] |= 0x10;
7832 if (plci->rx_dma_descriptor <= 0) {
7833 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7834 if (plci->rx_dma_descriptor >= 0)
7835 plci->rx_dma_descriptor++;
7837 if (plci->rx_dma_descriptor > 0) {
7838 lli[0] = 6;
7839 lli[1] |= 0x40;
7840 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7841 lli[3] = (byte)plci->rx_dma_magic;
7842 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7843 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7844 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7848 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7849 lli[1] |= 0x20;
7852 dbug(1, dprintf("add_b23"));
7853 api_save_msg(bp, "s", &plci->B_protocol);
7855 if (!bp->length && plci->tel)
7857 plci->adv_nl = true;
7858 dbug(1, dprintf("Default adv.Nl"));
7859 add_p(plci, LLI, lli);
7860 plci->B2_prot = 1 /*XPARENT*/;
7861 plci->B3_prot = 0 /*XPARENT*/;
7862 llc[1] = 2;
7863 llc[2] = 4;
7864 add_p(plci, LLC, llc);
7865 dlc[0] = 2;
7866 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7867 add_p(plci, DLC, dlc);
7868 return 0;
7871 if (!bp->length) /*default*/
7873 dbug(1, dprintf("ret default"));
7874 add_p(plci, LLI, lli);
7875 plci->B2_prot = 0 /*X.75 */;
7876 plci->B3_prot = 0 /*XPARENT*/;
7877 llc[1] = 1;
7878 llc[2] = 4;
7879 add_p(plci, LLC, llc);
7880 dlc[0] = 2;
7881 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7882 add_p(plci, DLC, dlc);
7883 return 0;
7885 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7886 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7888 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7890 bp_parms[6].length = 0;
7891 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7893 dbug(1, dprintf("b-form.!"));
7894 return _WRONG_MESSAGE_FORMAT;
7897 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7899 dbug(1, dprintf("b-form.!"));
7900 return _WRONG_MESSAGE_FORMAT;
7903 if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7905 if (GET_WORD(bp_parms[1].info) != 1
7906 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7907 plci->adv_nl = true;
7909 else if (plci->tel) return _B2_NOT_SUPPORTED;
7912 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7913 && (GET_WORD(bp_parms[2].info) == B3_RTP)
7914 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7916 add_p(plci, LLI, lli);
7917 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7918 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7919 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7920 llc[2] = 4;
7921 add_p(plci, LLC, llc);
7922 dlc[0] = 2;
7923 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7924 dlc[3] = 3; /* Addr A */
7925 dlc[4] = 1; /* Addr B */
7926 dlc[5] = 7; /* modulo mode */
7927 dlc[6] = 7; /* window size */
7928 dlc[7] = 0; /* XID len Lo */
7929 dlc[8] = 0; /* XID len Hi */
7930 for (i = 0; i < bp_parms[4].length; i++)
7931 dlc[9 + i] = bp_parms[4].info[1 + i];
7932 dlc[0] = (byte)(8 + bp_parms[4].length);
7933 add_p(plci, DLC, dlc);
7934 for (i = 0; i < bp_parms[5].length; i++)
7935 nlc[1 + i] = bp_parms[5].info[1 + i];
7936 nlc[0] = (byte)(bp_parms[5].length);
7937 add_p(plci, NLC, nlc);
7938 return 0;
7943 if ((GET_WORD(bp_parms[1].info) >= 32)
7944 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7945 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7946 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7949 return _B2_NOT_SUPPORTED;
7951 if ((GET_WORD(bp_parms[2].info) >= 32)
7952 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7954 return _B3_NOT_SUPPORTED;
7956 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7957 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7958 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7959 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7961 return (add_modem_b23(plci, bp_parms));
7964 add_p(plci, LLI, lli);
7966 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7967 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7968 if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7970 if (bp_parms[6].length)
7972 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7974 return _WRONG_MESSAGE_FORMAT;
7976 switch (GET_WORD(global_config[0].info))
7978 case 1:
7979 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7980 break;
7981 case 2:
7982 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7983 break;
7986 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7989 if (plci->B2_prot == B2_PIAFS)
7990 llc[1] = PIAFS_CRC;
7991 else
7992 /* IMPLEMENT_PIAFS */
7994 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7995 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7997 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7999 add_p(plci, LLC, llc);
8001 dlc[0] = 2;
8002 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8003 header[GET_WORD(bp_parms[2].info)]);
8005 b1_config = &bp_parms[3];
8006 nlc[0] = 0;
8007 if (plci->B3_prot == 4
8008 || plci->B3_prot == 5)
8010 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8011 nlc[0] = sizeof(T30_INFO);
8012 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8013 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8014 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8015 if (b1_config->length >= 2)
8017 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8020 b2_config = &bp_parms[4];
8023 if (llc[1] == PIAFS_CRC)
8025 if (plci->B3_prot != B3_TRANSPARENT)
8027 return _B_STACK_NOT_SUPPORTED;
8029 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8030 return _WRONG_MESSAGE_FORMAT;
8032 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8033 dlc[3] = 0; /* Addr A */
8034 dlc[4] = 0; /* Addr B */
8035 dlc[5] = 0; /* modulo mode */
8036 dlc[6] = 0; /* window size */
8037 if (b2_config->length >= 7) {
8038 dlc[7] = 7;
8039 dlc[8] = 0;
8040 dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8041 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8042 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8043 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8044 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8045 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8046 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8047 dlc[0] = 15;
8048 if (b2_config->length >= 8) { /* PIAFS control abilities */
8049 dlc[7] = 10;
8050 dlc[16] = 2; /* Length of PIAFS extension */
8051 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8052 dlc[18] = b2_config_parms[4].info[0]; /* value */
8053 dlc[0] = 18;
8056 else /* default values, 64K, variable, no compression */
8058 dlc[7] = 7;
8059 dlc[8] = 0;
8060 dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8061 dlc[10] = 0x03; /* V.42bis P0 */
8062 dlc[11] = 0; /* V.42bis P0 */
8063 dlc[12] = 0; /* V.42bis P1 */
8064 dlc[13] = 0; /* V.42bis P1 */
8065 dlc[14] = 0; /* V.42bis P2 */
8066 dlc[15] = 0; /* V.42bis P2 */
8067 dlc[0] = 15;
8069 add_p(plci, DLC, dlc);
8071 else
8073 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8075 if (plci->B3_prot != B3_TRANSPARENT)
8076 return _B_STACK_NOT_SUPPORTED;
8078 dlc[0] = 6;
8079 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8080 dlc[3] = 0x08;
8081 dlc[4] = 0x01;
8082 dlc[5] = 127;
8083 dlc[6] = 7;
8084 if (b2_config->length != 0)
8086 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8087 return _WRONG_MESSAGE_FORMAT;
8089 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8090 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8091 if (b2_config->info[3] != 128)
8093 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8094 return _B2_PARM_NOT_SUPPORTED;
8096 dlc[5] = (byte)(b2_config->info[3] - 1);
8097 dlc[6] = b2_config->info[4];
8098 if (llc[1] == V120_V42BIS) {
8099 if (b2_config->length >= 10) {
8100 dlc[7] = 6;
8101 dlc[8] = 0;
8102 dlc[9] = b2_config_parms[4].info[0];
8103 dlc[10] = b2_config_parms[4].info[1];
8104 dlc[11] = b2_config_parms[5].info[0];
8105 dlc[12] = b2_config_parms[5].info[1];
8106 dlc[13] = b2_config_parms[6].info[0];
8107 dlc[14] = b2_config_parms[6].info[1];
8108 dlc[0] = 14;
8109 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8110 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8111 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8113 else {
8114 dlc[6] = 14;
8119 else
8121 if (b2_config->length)
8123 dbug(1, dprintf("B2-Config"));
8124 if (llc[1] == X75_V42BIS) {
8125 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8127 return _WRONG_MESSAGE_FORMAT;
8130 else {
8131 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8133 return _WRONG_MESSAGE_FORMAT;
8136 /* if B2 Protocol is LAPD, b2_config structure is different */
8137 if (llc[1] == 6)
8139 dlc[0] = 4;
8140 if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8141 else dlc[2] = 0x01;
8142 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8144 SAPI = b2_config->info[2]; /* SAPI */
8146 dlc[1] = SAPI;
8147 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8149 dlc[3] = 127; /* Mode */
8151 else
8153 dlc[3] = 7; /* Mode */
8156 if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8157 else dlc[4] = 1;
8158 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8159 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8161 else
8163 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8164 dlc[3] = b2_config->info[1];
8165 dlc[4] = b2_config->info[2];
8166 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8167 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8168 return _B2_PARM_NOT_SUPPORTED;
8171 dlc[5] = (byte)(b2_config->info[3] - 1);
8172 dlc[6] = b2_config->info[4];
8173 if (dlc[6] > dlc[5]) {
8174 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]));
8175 return _B2_PARM_NOT_SUPPORTED;
8178 if (llc[1] == X75_V42BIS) {
8179 if (b2_config->length >= 10) {
8180 dlc[7] = 6;
8181 dlc[8] = 0;
8182 dlc[9] = b2_config_parms[4].info[0];
8183 dlc[10] = b2_config_parms[4].info[1];
8184 dlc[11] = b2_config_parms[5].info[0];
8185 dlc[12] = b2_config_parms[5].info[1];
8186 dlc[13] = b2_config_parms[6].info[0];
8187 dlc[14] = b2_config_parms[6].info[1];
8188 dlc[0] = 14;
8189 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8190 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8191 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8193 else {
8194 dlc[6] = 14;
8198 else {
8199 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8200 for (i = 0; i < b2_config_parms[4].length; i++)
8201 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8206 add_p(plci, DLC, dlc);
8208 b3_config = &bp_parms[5];
8209 if (b3_config->length)
8211 if (plci->B3_prot == 4
8212 || plci->B3_prot == 5)
8214 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8216 return _WRONG_MESSAGE_FORMAT;
8218 i = GET_WORD((byte *)(b3_config_parms[0].info));
8219 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8220 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8221 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8222 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8223 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8224 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8225 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8228 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8229 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8231 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8232 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8233 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8236 ((T30_INFO *)&nlc[1])->recording_properties =
8237 T30_RECORDING_WIDTH_ISO_A3 |
8238 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8239 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8241 if (plci->B3_prot == 5)
8243 if (i & 0x0002) /* Accept incoming fax-polling requests */
8244 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8245 if (i & 0x2000) /* Do not use MR compression */
8246 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8247 if (i & 0x4000) /* Do not use MMR compression */
8248 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8249 if (i & 0x8000) /* Do not use ECM */
8250 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8251 if (plci->fax_connect_info_length != 0)
8253 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8254 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8255 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8256 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8257 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8260 /* copy station id to NLC */
8261 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8263 if (i < b3_config_parms[2].length)
8265 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8267 else
8269 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8272 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8273 /* copy head line to NLC */
8274 if (b3_config_parms[3].length)
8277 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8278 if (pos != 0)
8280 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8281 pos = 0;
8282 else
8284 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8285 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8286 len = (byte)b3_config_parms[2].length;
8287 if (len > 20)
8288 len = 20;
8289 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8291 for (i = 0; i < len; i++)
8292 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8293 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8294 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8299 len = (byte)b3_config_parms[3].length;
8300 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8301 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8302 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8303 nlc[0] += (byte)(pos + len);
8304 for (i = 0; i < len; i++)
8305 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8306 } else
8307 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8309 plci->nsf_control_bits = 0;
8310 if (plci->B3_prot == 5)
8312 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8313 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8315 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8317 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8318 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8320 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8322 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8323 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8325 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8326 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8328 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8329 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8330 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8332 len = nlc[0];
8333 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8334 if (pos < plci->fax_connect_info_length)
8336 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8337 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8339 else
8340 nlc[++len] = 0;
8341 if (pos < plci->fax_connect_info_length)
8343 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8344 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8346 else
8347 nlc[++len] = 0;
8348 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8349 & (1L << PRIVATE_FAX_NONSTANDARD))
8351 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8353 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8354 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8355 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8356 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8358 else
8360 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8362 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8363 nlc[++len] = 0;
8365 else
8367 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8368 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8369 nlc[++len] = (byte)(b3_config_parms[4].length);
8370 for (i = 0; i < b3_config_parms[4].length; i++)
8371 nlc[++len] = b3_config_parms[4].info[1 + i];
8375 nlc[0] = len;
8376 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8377 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8379 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8384 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8385 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8386 for (i = 0; i < len; i++)
8387 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8388 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8389 i += ((T30_INFO *)&nlc[1])->head_line_len;
8390 while (i < nlc[0])
8391 plci->fax_connect_info_buffer[len++] = nlc[++i];
8392 plci->fax_connect_info_length = len;
8394 else
8396 nlc[0] = 14;
8397 if (b3_config->length != 16)
8398 return _B3_PARM_NOT_SUPPORTED;
8399 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8400 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8401 return _B3_PARM_NOT_SUPPORTED;
8402 nlc[13] = b3_config->info[13];
8403 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8404 return _B3_PARM_NOT_SUPPORTED;
8405 nlc[14] = b3_config->info[15];
8408 else
8410 if (plci->B3_prot == 4
8411 || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8413 add_p(plci, NLC, nlc);
8414 return 0;
8417 /*----------------------------------------------------------------*/
8418 /* make the same as add_b23, but only for the modem related */
8419 /* L2 and L3 B-Chan protocol. */
8420 /* */
8421 /* Enabled L2 and L3 Configurations: */
8422 /* If L1 == Modem all negotiation */
8423 /* only L2 == Modem with full negotiation is allowed */
8424 /* If L1 == Modem async or sync */
8425 /* only L2 == Transparent is allowed */
8426 /* L3 == Modem or L3 == Transparent are allowed */
8427 /* B2 Configuration for modem: */
8428 /* word : enable/disable compression, bitoptions */
8429 /* B3 Configuration for modem: */
8430 /* empty */
8431 /*----------------------------------------------------------------*/
8432 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8434 static byte lli[12] = {1,1};
8435 static byte llc[3] = {2,0,0};
8436 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8437 API_PARSE mdm_config[2];
8438 word i;
8439 word b2_config = 0;
8441 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8442 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8444 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8445 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8446 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8447 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8449 return (_B_STACK_NOT_SUPPORTED);
8451 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8452 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8454 return (_B_STACK_NOT_SUPPORTED);
8457 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8458 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8460 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8462 if (api_parse(&bp_parms[4].info[1],
8463 (word)bp_parms[4].length, "w",
8464 mdm_config))
8466 return (_WRONG_MESSAGE_FORMAT);
8468 b2_config = GET_WORD(mdm_config[0].info);
8471 /* OK, L2 is modem */
8473 lli[0] = 1;
8474 lli[1] = 1;
8475 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8476 lli[1] |= 2;
8477 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8478 lli[1] |= 4;
8480 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8481 lli[1] |= 0x10;
8482 if (plci->rx_dma_descriptor <= 0) {
8483 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8484 if (plci->rx_dma_descriptor >= 0)
8485 plci->rx_dma_descriptor++;
8487 if (plci->rx_dma_descriptor > 0) {
8488 lli[1] |= 0x40;
8489 lli[0] = 6;
8490 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8491 lli[3] = (byte)plci->rx_dma_magic;
8492 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8493 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8494 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8498 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8499 lli[1] |= 0x20;
8502 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8503 /*V42*/ 10 : /*V42_IN*/ 9;
8504 llc[2] = 4; /* pass L3 always transparent */
8505 add_p(plci, LLI, lli);
8506 add_p(plci, LLC, llc);
8507 i = 1;
8508 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8509 i += 2;
8510 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8512 if (bp_parms[4].length)
8514 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8515 dlc[i++] = 3; /* Addr A */
8516 dlc[i++] = 1; /* Addr B */
8517 dlc[i++] = 7; /* modulo mode */
8518 dlc[i++] = 7; /* window size */
8519 dlc[i++] = 0; /* XID len Lo */
8520 dlc[i++] = 0; /* XID len Hi */
8522 if (b2_config & MDM_B2_DISABLE_V42bis)
8524 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8526 if (b2_config & MDM_B2_DISABLE_MNP)
8528 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8530 if (b2_config & MDM_B2_DISABLE_TRANS)
8532 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8534 if (b2_config & MDM_B2_DISABLE_V42)
8536 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8538 if (b2_config & MDM_B2_DISABLE_COMP)
8540 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8542 i++;
8545 else
8547 dlc[i++] = 3; /* Addr A */
8548 dlc[i++] = 1; /* Addr B */
8549 dlc[i++] = 7; /* modulo mode */
8550 dlc[i++] = 7; /* window size */
8551 dlc[i++] = 0; /* XID len Lo */
8552 dlc[i++] = 0; /* XID len Hi */
8553 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8554 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8555 DLC_MODEMPROT_DISABLE_V42_DETECT |
8556 DLC_MODEMPROT_DISABLE_COMPRESSION;
8558 dlc[0] = (byte)(i - 1);
8559 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8560 add_p(plci, DLC, dlc);
8561 return (0);
8565 /*------------------------------------------------------------------*/
8566 /* send a request for the signaling entity */
8567 /*------------------------------------------------------------------*/
8569 static void sig_req(PLCI *plci, byte req, byte Id)
8571 if (!plci) return;
8572 if (plci->adapter->adapter_disabled) return;
8573 dbug(1, dprintf("sig_req(%x)", req));
8574 if (req == REMOVE)
8575 plci->sig_remove_id = plci->Sig.Id;
8576 if (plci->req_in == plci->req_in_start) {
8577 plci->req_in += 2;
8578 plci->RBuffer[plci->req_in++] = 0;
8580 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8581 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8582 plci->RBuffer[plci->req_in++] = req; /* request */
8583 plci->RBuffer[plci->req_in++] = 0; /* channel */
8584 plci->req_in_start = plci->req_in;
8587 /*------------------------------------------------------------------*/
8588 /* send a request for the network layer entity */
8589 /*------------------------------------------------------------------*/
8591 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8593 if (!plci) return;
8594 if (plci->adapter->adapter_disabled) return;
8595 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8596 if (req == REMOVE)
8598 plci->nl_remove_id = plci->NL.Id;
8599 ncci_remove(plci, 0, (byte)(ncci != 0));
8600 ncci = 0;
8602 if (plci->req_in == plci->req_in_start) {
8603 plci->req_in += 2;
8604 plci->RBuffer[plci->req_in++] = 0;
8606 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8607 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8608 plci->RBuffer[plci->req_in++] = req; /* request */
8609 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8610 plci->req_in_start = plci->req_in;
8613 static void send_req(PLCI *plci)
8615 ENTITY *e;
8616 word l;
8617 /* word i; */
8619 if (!plci) return;
8620 if (plci->adapter->adapter_disabled) return;
8621 channel_xmit_xon(plci);
8623 /* if nothing to do, return */
8624 if (plci->req_in == plci->req_out) return;
8625 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8627 if (plci->nl_req || plci->sig_req) return;
8629 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8630 plci->req_out += 2;
8631 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8632 plci->req_out += l;
8633 if (plci->RBuffer[plci->req_out] == 1)
8635 e = &plci->NL;
8636 plci->req_out++;
8637 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8638 e->ReqCh = plci->RBuffer[plci->req_out++];
8639 if (!(e->Id & 0x1f))
8641 e->Id = NL_ID;
8642 plci->RBuffer[plci->req_out - 4] = CAI;
8643 plci->RBuffer[plci->req_out - 3] = 1;
8644 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8645 plci->RBuffer[plci->req_out - 1] = 0;
8646 l += 3;
8647 plci->nl_global_req = plci->nl_req;
8649 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8651 else
8653 e = &plci->Sig;
8654 if (plci->RBuffer[plci->req_out])
8655 e->Id = plci->RBuffer[plci->req_out];
8656 plci->req_out++;
8657 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8658 e->ReqCh = plci->RBuffer[plci->req_out++];
8659 if (!(e->Id & 0x1f))
8660 plci->sig_global_req = plci->sig_req;
8661 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8663 plci->XData[0].PLength = l;
8664 e->X = plci->XData;
8665 plci->adapter->request(e);
8666 dbug(1, dprintf("send_ok"));
8669 static void send_data(PLCI *plci)
8671 DIVA_CAPI_ADAPTER *a;
8672 DATA_B3_DESC *data;
8673 NCCI *ncci_ptr;
8674 word ncci;
8676 if (!plci->nl_req && plci->ncci_ring_list)
8678 a = plci->adapter;
8679 ncci = plci->ncci_ring_list;
8682 ncci = a->ncci_next[ncci];
8683 ncci_ptr = &(a->ncci[ncci]);
8684 if (!(a->ncci_ch[ncci]
8685 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8687 if (ncci_ptr->data_pending)
8689 if ((a->ncci_state[ncci] == CONNECTED)
8690 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8691 || (plci->send_disc == ncci))
8693 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8694 if ((plci->B2_prot == B2_V120_ASYNC)
8695 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8696 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8698 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8699 plci->NData[1].PLength = data->Length;
8700 if (data->Flags & 0x10)
8701 plci->NData[0].P = v120_break_header;
8702 else
8703 plci->NData[0].P = v120_default_header;
8704 plci->NData[0].PLength = 1;
8705 plci->NL.XNum = 2;
8706 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8708 else
8710 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8711 plci->NData[0].PLength = data->Length;
8712 if (data->Flags & 0x10)
8713 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8715 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8716 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8718 else
8719 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8721 plci->NL.X = plci->NData;
8722 plci->NL.ReqCh = a->ncci_ch[ncci];
8723 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8724 plci->data_sent = true;
8725 plci->data_sent_ptr = data->P;
8726 a->request(&plci->NL);
8728 else {
8729 cleanup_ncci_data(plci, ncci);
8732 else if (plci->send_disc == ncci)
8734 /* dprintf("N_DISC"); */
8735 plci->NData[0].PLength = 0;
8736 plci->NL.ReqCh = a->ncci_ch[ncci];
8737 plci->NL.Req = plci->nl_req = N_DISC;
8738 a->request(&plci->NL);
8739 plci->command = _DISCONNECT_B3_R;
8740 plci->send_disc = 0;
8743 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8744 plci->ncci_ring_list = ncci;
8748 static void listen_check(DIVA_CAPI_ADAPTER *a)
8750 word i, j;
8751 PLCI *plci;
8752 byte activnotifiedcalls = 0;
8754 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8755 if (!remove_started && !a->adapter_disabled)
8757 for (i = 0; i < a->max_plci; i++)
8759 plci = &(a->plci[i]);
8760 if (plci->notifiedcall) activnotifiedcalls++;
8762 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8764 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8765 if ((j = get_plci(a))) {
8766 a->listen_active++;
8767 plci = &a->plci[j - 1];
8768 plci->State = LISTENING;
8770 add_p(plci, OAD, "\x01\xfd");
8772 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8774 add_p(plci, CAI, "\x01\xc0");
8775 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8776 add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8777 add_p(plci, SHIFT | 6, NULL);
8778 add_p(plci, SIN, "\x02\x00\x00");
8779 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8780 sig_req(plci, ASSIGN, DSIG_ID);
8781 send_req(plci);
8787 /*------------------------------------------------------------------*/
8788 /* functions for all parameters sent in INDs */
8789 /*------------------------------------------------------------------*/
8791 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8793 word ploc; /* points to current location within packet */
8794 byte w;
8795 byte wlen;
8796 byte codeset, lock;
8797 byte *in;
8798 word i;
8799 word code;
8800 word mIEindex = 0;
8801 ploc = 0;
8802 codeset = 0;
8803 lock = 0;
8805 in = plci->Sig.RBuffer->P;
8806 for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8807 { /* element but parms array is larger */
8808 parms[i] = (byte *)"";
8810 for (i = 0; i < multiIEsize; i++)
8812 parms[i] = (byte *)"";
8815 while (ploc < plci->Sig.RBuffer->length - 1) {
8817 /* read information element id and length */
8818 w = in[ploc];
8820 if (w & 0x80) {
8821 /* w &=0xf0; removed, cannot detect congestion levels */
8822 /* upper 4 bit masked with w==SHIFT now */
8823 wlen = 0;
8825 else {
8826 wlen = (byte)(in[ploc + 1] + 1);
8828 /* check if length valid (not exceeding end of packet) */
8829 if ((ploc + wlen) > 270) return;
8830 if (lock & 0x80) lock &= 0x7f;
8831 else codeset = lock;
8833 if ((w & 0xf0) == SHIFT) {
8834 codeset = in[ploc];
8835 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8836 codeset &= 7;
8837 lock |= 0x80;
8839 else {
8840 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8841 else code = w;
8842 code |= (codeset << 8);
8844 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8846 if (i < parms_id[0] + 1) {
8847 if (!multiIEsize) { /* with multiIEs use next field index, */
8848 mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8851 parms[mIEindex] = &in[ploc + 1];
8852 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8853 if (parms_id[i] == OAD
8854 || parms_id[i] == CONN_NR
8855 || parms_id[i] == CAD) {
8856 if (in[ploc + 2] & 0x80) {
8857 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8858 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8859 in[ploc + 2] = 0x80;
8860 parms[mIEindex] = &in[ploc];
8863 mIEindex++; /* effects multiIEs only */
8867 ploc += (wlen + 1);
8869 return;
8872 /*------------------------------------------------------------------*/
8873 /* try to match a cip from received BC and HLC */
8874 /*------------------------------------------------------------------*/
8876 static byte ie_compare(byte *ie1, byte *ie2)
8878 word i;
8879 if (!ie1 || !ie2) return false;
8880 if (!ie1[0]) return false;
8881 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8882 return true;
8885 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8887 word i;
8888 word j;
8890 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8892 for (j = 16; j < 29 &&
8893 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8894 if (j == 29) return i;
8895 return j;
8899 static byte AddInfo(byte **add_i,
8900 byte **fty_i,
8901 byte *esc_chi,
8902 byte *facility)
8904 byte i;
8905 byte j;
8906 byte k;
8907 byte flen;
8908 byte len = 0;
8909 /* facility is a nested structure */
8910 /* FTY can be more than once */
8912 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8914 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8917 else
8919 add_i[0] = (byte *)"";
8921 if (!fty_i[0][0])
8923 add_i[3] = (byte *)"";
8925 else
8926 { /* facility array found */
8927 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8929 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8930 len += fty_i[i][0];
8931 len += 2;
8932 flen = fty_i[i][0];
8933 facility[j++] = 0x1c; /* copy fac IE */
8934 for (k = 0; k <= flen; k++, j++)
8936 facility[j] = fty_i[i][k];
8937 /* dbug(1, dprintf("%x ",facility[j])); */
8940 facility[0] = len;
8941 add_i[3] = facility;
8943 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
8944 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8945 len += 4; /* calculate length of all */
8946 return (len);
8949 /*------------------------------------------------------------------*/
8950 /* voice and codec features */
8951 /*------------------------------------------------------------------*/
8953 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8955 byte voice_chi[] = "\x02\x18\x01";
8956 byte channel;
8958 channel = chi[chi[0]] & 0x3;
8959 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8960 voice_chi[2] = (channel) ? channel : 1;
8961 add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
8962 add_p(plci, ESC, voice_chi); /* Channel */
8963 sig_req(plci, TEL_CTRL, 0);
8964 send_req(plci);
8965 if (a->AdvSignalPLCI)
8967 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8971 static void VoiceChannelOff(PLCI *plci)
8973 dbug(1, dprintf("ExtDevOFF"));
8974 add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
8975 sig_req(plci, TEL_CTRL, 0);
8976 send_req(plci);
8977 if (plci->adapter->AdvSignalPLCI)
8979 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8984 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8985 byte hook_listen)
8987 word j;
8988 PLCI *splci;
8990 /* check if hardware supports handset with hook states (adv.codec) */
8991 /* or if just a on board codec is supported */
8992 /* the advanced codec plci is just for internal use */
8994 /* diva Pro with on-board codec: */
8995 if (a->profile.Global_Options & HANDSET)
8997 /* new call, but hook states are already signalled */
8998 if (a->AdvCodecFLAG)
9000 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9002 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9003 return 0x2001; /* codec in use by another application */
9005 if (plci != NULL)
9007 a->AdvSignalPLCI = plci;
9008 plci->tel = ADV_VOICE;
9010 return 0; /* adv codec still used */
9012 if ((j = get_plci(a)))
9014 splci = &a->plci[j - 1];
9015 splci->tel = CODEC_PERMANENT;
9016 /* hook_listen indicates if a facility_req with handset/hook support */
9017 /* was sent. Otherwise if just a call on an external device was made */
9018 /* the codec will be used but the hook info will be discarded (just */
9019 /* the external controller is in use */
9020 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9021 else
9023 splci->State = ADVANCED_VOICE_NOSIG;
9024 if (plci)
9026 plci->spoofed_msg = SPOOFING_REQUIRED;
9028 /* indicate D-ch connect if */
9029 } /* codec is connected OK */
9030 if (plci != NULL)
9032 a->AdvSignalPLCI = plci;
9033 plci->tel = ADV_VOICE;
9035 a->AdvSignalAppl = appl;
9036 a->AdvCodecFLAG = true;
9037 a->AdvCodecPLCI = splci;
9038 add_p(splci, CAI, "\x01\x15");
9039 add_p(splci, LLI, "\x01\x00");
9040 add_p(splci, ESC, "\x02\x18\x00");
9041 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9042 splci->internal_command = PERM_COD_ASSIGN;
9043 dbug(1, dprintf("Codec Assign"));
9044 sig_req(splci, ASSIGN, DSIG_ID);
9045 send_req(splci);
9047 else
9049 return 0x2001; /* wrong state, no more plcis */
9052 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9054 if (hook_listen) return 0x300B; /* Facility not supported */
9055 /* no hook with SCOM */
9056 if (plci != NULL) plci->tel = CODEC;
9057 dbug(1, dprintf("S/SCOM codec"));
9058 /* first time we use the scom-s codec we must shut down the internal */
9059 /* handset application of the card. This can be done by an assign with */
9060 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9061 if (!a->scom_appl_disable) {
9062 if ((j = get_plci(a))) {
9063 splci = &a->plci[j - 1];
9064 add_p(splci, CAI, "\x01\x80");
9065 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9066 sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9067 send_req(splci);
9068 a->scom_appl_disable = true;
9070 else{
9071 return 0x2001; /* wrong state, no more plcis */
9075 else return 0x300B; /* Facility not supported */
9077 return 0;
9081 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9084 dbug(1, dprintf("CodecIdCheck"));
9086 if (a->AdvSignalPLCI == plci)
9088 dbug(1, dprintf("PLCI owns codec"));
9089 VoiceChannelOff(a->AdvCodecPLCI);
9090 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9092 dbug(1, dprintf("remove temp codec PLCI"));
9093 plci_remove(a->AdvCodecPLCI);
9094 a->AdvCodecFLAG = 0;
9095 a->AdvCodecPLCI = NULL;
9096 a->AdvSignalAppl = NULL;
9098 a->AdvSignalPLCI = NULL;
9102 /* -------------------------------------------------------------------
9103 Ask for physical address of card on PCI bus
9104 ------------------------------------------------------------------- */
9105 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9106 IDI_SYNC_REQ *preq) {
9107 a->sdram_bar = 0;
9108 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9109 ENTITY *e = (ENTITY *)preq;
9111 e->user[0] = a->Id - 1;
9112 preq->xdi_sdram_bar.info.bar = 0;
9113 preq->xdi_sdram_bar.Req = 0;
9114 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9116 (*(a->request))(e);
9118 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9119 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9123 /* -------------------------------------------------------------------
9124 Ask XDI about extended features
9125 ------------------------------------------------------------------- */
9126 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9127 IDI_SYNC_REQ *preq;
9128 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9130 char features[4];
9131 preq = (IDI_SYNC_REQ *)&buffer[0];
9133 if (!diva_xdi_extended_features) {
9134 ENTITY *e = (ENTITY *)preq;
9135 diva_xdi_extended_features |= 0x80000000;
9137 e->user[0] = a->Id - 1;
9138 preq->xdi_extended_features.Req = 0;
9139 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9140 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9141 preq->xdi_extended_features.info.features = &features[0];
9143 (*(a->request))(e);
9145 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9147 Check features located in the byte '0'
9149 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9150 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9152 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9153 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9154 dbug(1, dprintf("XDI provides RxDMA"));
9156 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9157 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9159 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9160 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9161 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9167 diva_ask_for_xdi_sdram_bar(a, preq);
9170 /*------------------------------------------------------------------*/
9171 /* automatic law */
9172 /*------------------------------------------------------------------*/
9173 /* called from OS specific part after init time to get the Law */
9174 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9175 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9177 word j;
9178 PLCI *splci;
9180 if (a->automatic_law) {
9181 return;
9183 if ((j = get_plci(a))) {
9184 diva_get_extended_adapter_features(a);
9185 splci = &a->plci[j - 1];
9186 a->automatic_lawPLCI = splci;
9187 a->automatic_law = 1;
9188 add_p(splci, CAI, "\x01\x80");
9189 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9190 splci->internal_command = USELAW_REQ;
9191 splci->command = 0;
9192 splci->number = 0;
9193 sig_req(splci, ASSIGN, DSIG_ID);
9194 send_req(splci);
9198 /* called from OS specific part if an application sends an Capi20Release */
9199 word CapiRelease(word Id)
9201 word i, j, appls_found;
9202 PLCI *plci;
9203 APPL *this;
9204 DIVA_CAPI_ADAPTER *a;
9206 if (!Id)
9208 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9209 return (_WRONG_APPL_ID);
9212 this = &application[Id - 1]; /* get application pointer */
9214 for (i = 0, appls_found = 0; i < max_appl; i++)
9216 if (application[i].Id) /* an application has been found */
9218 appls_found++;
9222 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9224 a = &adapter[i];
9225 if (a->request)
9227 a->Info_Mask[Id - 1] = 0;
9228 a->CIP_Mask[Id - 1] = 0;
9229 a->Notification_Mask[Id - 1] = 0;
9230 a->codec_listen[Id - 1] = NULL;
9231 a->requested_options_table[Id - 1] = 0;
9232 for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9233 { /* with this application */
9234 plci = &a->plci[j];
9235 if (plci->Id) /* if plci owns no application */
9236 { /* it may be not jet connected */
9237 if (plci->State == INC_CON_PENDING
9238 || plci->State == INC_CON_ALERT)
9240 if (test_bit(Id - 1, plci->c_ind_mask_table))
9242 __clear_bit(Id - 1, plci->c_ind_mask_table);
9243 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9245 sig_req(plci, HANGUP, 0);
9246 send_req(plci);
9247 plci->State = OUTG_DIS_PENDING;
9251 if (test_bit(Id - 1, plci->c_ind_mask_table))
9253 __clear_bit(Id - 1, plci->c_ind_mask_table);
9254 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9256 if (!plci->appl)
9258 plci_remove(plci);
9259 plci->State = IDLE;
9263 if (plci->appl == this)
9265 plci->appl = NULL;
9266 plci_remove(plci);
9267 plci->State = IDLE;
9271 listen_check(a);
9273 if (a->flag_dynamic_l1_down)
9275 if (appls_found == 1) /* last application does a capi release */
9277 if ((j = get_plci(a)))
9279 plci = &a->plci[j - 1];
9280 plci->command = 0;
9281 add_p(plci, OAD, "\x01\xfd");
9282 add_p(plci, CAI, "\x01\x80");
9283 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9284 add_p(plci, SHIFT | 6, NULL);
9285 add_p(plci, SIN, "\x02\x00\x00");
9286 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9287 sig_req(plci, ASSIGN, DSIG_ID);
9288 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9289 sig_req(plci, SIG_CTRL, 0);
9290 send_req(plci);
9294 if (a->AdvSignalAppl == this)
9296 this->NullCREnable = false;
9297 if (a->AdvCodecPLCI)
9299 plci_remove(a->AdvCodecPLCI);
9300 a->AdvCodecPLCI->tel = 0;
9301 a->AdvCodecPLCI->adv_nl = 0;
9303 a->AdvSignalAppl = NULL;
9304 a->AdvSignalPLCI = NULL;
9305 a->AdvCodecFLAG = 0;
9306 a->AdvCodecPLCI = NULL;
9311 this->Id = 0;
9313 return GOOD;
9316 static word plci_remove_check(PLCI *plci)
9318 if (!plci) return true;
9319 if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9321 if (plci->Sig.Id == 0xff)
9322 plci->Sig.Id = 0;
9323 if (!plci->Sig.Id)
9325 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9326 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9327 if (plci->Id)
9329 CodecIdCheck(plci->adapter, plci);
9330 clear_b1_config(plci);
9331 ncci_remove(plci, 0, false);
9332 plci_free_msg_in_queue(plci);
9333 channel_flow_control_remove(plci);
9334 plci->Id = 0;
9335 plci->State = IDLE;
9336 plci->channels = 0;
9337 plci->appl = NULL;
9338 plci->notifiedcall = 0;
9340 listen_check(plci->adapter);
9341 return true;
9344 return false;
9348 /*------------------------------------------------------------------*/
9350 static byte plci_nl_busy(PLCI *plci)
9352 /* only applicable for non-multiplexed protocols */
9353 return (plci->nl_req
9354 || (plci->ncci_ring_list
9355 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9356 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9360 /*------------------------------------------------------------------*/
9361 /* DTMF facilities */
9362 /*------------------------------------------------------------------*/
9365 static struct
9367 byte send_mask;
9368 byte listen_mask;
9369 byte character;
9370 byte code;
9371 } dtmf_digit_map[] =
9373 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9374 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9375 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9376 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9377 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9378 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9379 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9380 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9381 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9382 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9383 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9384 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9385 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9386 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9387 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9388 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9389 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9390 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9391 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9392 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9394 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9395 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9396 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9397 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9398 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9399 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9400 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9401 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9402 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9403 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9404 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9405 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9406 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9407 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9408 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9409 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9410 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9411 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9412 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9413 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9414 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9415 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9416 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9417 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9418 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9419 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9420 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9421 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9422 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9423 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9424 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9425 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9426 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9427 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9428 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9429 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9430 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9431 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9432 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9433 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9434 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9435 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9436 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9437 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9438 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9439 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9440 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9441 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9442 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9443 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9444 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9445 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9449 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9452 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9454 word min_digit_duration, min_gap_duration;
9456 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9457 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9458 (char *)(FILE_), __LINE__, enable_mask));
9460 if (enable_mask != 0)
9462 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9463 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9464 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9465 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9466 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9467 plci->NData[0].PLength = 5;
9469 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9470 plci->NData[0].PLength += 2;
9471 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9474 else
9476 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9477 plci->NData[0].PLength = 1;
9479 capidtmf_recv_disable(&(plci->capidtmf_state));
9482 plci->NData[0].P = plci->internal_req_buffer;
9483 plci->NL.X = plci->NData;
9484 plci->NL.ReqCh = 0;
9485 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9486 plci->adapter->request(&plci->NL);
9490 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9492 word w, i;
9494 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9495 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9496 (char *)(FILE_), __LINE__, digit_count));
9498 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9499 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9500 PUT_WORD(&plci->internal_req_buffer[1], w);
9501 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9502 PUT_WORD(&plci->internal_req_buffer[3], w);
9503 for (i = 0; i < digit_count; i++)
9505 w = 0;
9506 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9507 && (digit_buffer[i] != dtmf_digit_map[w].character))
9509 w++;
9511 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9512 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9514 plci->NData[0].PLength = 5 + digit_count;
9515 plci->NData[0].P = plci->internal_req_buffer;
9516 plci->NL.X = plci->NData;
9517 plci->NL.ReqCh = 0;
9518 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9519 plci->adapter->request(&plci->NL);
9523 static void dtmf_rec_clear_config(PLCI *plci)
9526 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9527 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9528 (char *)(FILE_), __LINE__));
9530 plci->dtmf_rec_active = 0;
9531 plci->dtmf_rec_pulse_ms = 0;
9532 plci->dtmf_rec_pause_ms = 0;
9534 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9539 static void dtmf_send_clear_config(PLCI *plci)
9542 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9543 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9544 (char *)(FILE_), __LINE__));
9546 plci->dtmf_send_requests = 0;
9547 plci->dtmf_send_pulse_ms = 0;
9548 plci->dtmf_send_pause_ms = 0;
9552 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9555 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9556 UnMapId(Id), (char *)(FILE_), __LINE__));
9558 while (plci->dtmf_send_requests != 0)
9559 dtmf_confirmation(Id, plci);
9563 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9566 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9567 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9569 return (GOOD);
9573 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9575 word Info;
9577 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9578 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9580 Info = GOOD;
9581 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9583 switch (plci->adjust_b_state)
9585 case ADJUST_B_RESTORE_DTMF_1:
9586 plci->internal_command = plci->adjust_b_command;
9587 if (plci_nl_busy(plci))
9589 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9590 break;
9592 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9593 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9594 break;
9595 case ADJUST_B_RESTORE_DTMF_2:
9596 if ((Rc != OK) && (Rc != OK_FC))
9598 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9599 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9600 Info = _WRONG_STATE;
9601 break;
9603 break;
9606 return (Info);
9610 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9612 word internal_command, Info;
9613 byte mask;
9614 byte result[4];
9616 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9617 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9618 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9619 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9621 Info = GOOD;
9622 result[0] = 2;
9623 PUT_WORD(&result[1], DTMF_SUCCESS);
9624 internal_command = plci->internal_command;
9625 plci->internal_command = 0;
9626 mask = 0x01;
9627 switch (plci->dtmf_cmd)
9630 case DTMF_LISTEN_TONE_START:
9631 mask <<= 1; /* fall through */
9632 case DTMF_LISTEN_MF_START:
9633 mask <<= 1; /* fall through */
9635 case DTMF_LISTEN_START:
9636 switch (internal_command)
9638 default:
9639 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9640 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9641 /* fall through */
9642 case DTMF_COMMAND_1:
9643 if (adjust_b_process(Id, plci, Rc) != GOOD)
9645 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9646 UnMapId(Id), (char *)(FILE_), __LINE__));
9647 Info = _FACILITY_NOT_SUPPORTED;
9648 break;
9650 if (plci->internal_command)
9651 return;
9652 /* fall through */
9653 case DTMF_COMMAND_2:
9654 if (plci_nl_busy(plci))
9656 plci->internal_command = DTMF_COMMAND_2;
9657 return;
9659 plci->internal_command = DTMF_COMMAND_3;
9660 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9661 return;
9662 case DTMF_COMMAND_3:
9663 if ((Rc != OK) && (Rc != OK_FC))
9665 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9666 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9667 Info = _FACILITY_NOT_SUPPORTED;
9668 break;
9671 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9673 plci->dtmf_rec_active |= mask;
9674 break;
9676 break;
9679 case DTMF_LISTEN_TONE_STOP:
9680 mask <<= 1; /* fall through */
9681 case DTMF_LISTEN_MF_STOP:
9682 mask <<= 1; /* fall through */
9684 case DTMF_LISTEN_STOP:
9685 switch (internal_command)
9687 default:
9688 plci->dtmf_rec_active &= ~mask;
9689 if (plci->dtmf_rec_active)
9690 break;
9692 case DTMF_COMMAND_1:
9693 if (plci->dtmf_rec_active)
9695 if (plci_nl_busy (plci))
9697 plci->internal_command = DTMF_COMMAND_1;
9698 return;
9700 plci->dtmf_rec_active &= ~mask;
9701 plci->internal_command = DTMF_COMMAND_2;
9702 dtmf_enable_receiver (plci, false);
9703 return;
9705 Rc = OK;
9706 case DTMF_COMMAND_2:
9707 if ((Rc != OK) && (Rc != OK_FC))
9709 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9710 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9711 Info = _FACILITY_NOT_SUPPORTED;
9712 break;
9715 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9716 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9717 /* fall through */
9718 case DTMF_COMMAND_3:
9719 if (adjust_b_process(Id, plci, Rc) != GOOD)
9721 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9722 UnMapId(Id), (char *)(FILE_), __LINE__));
9723 Info = _FACILITY_NOT_SUPPORTED;
9724 break;
9726 if (plci->internal_command)
9727 return;
9728 break;
9730 break;
9733 case DTMF_SEND_TONE:
9734 mask <<= 1; /* fall through */
9735 case DTMF_SEND_MF:
9736 mask <<= 1; /* fall through */
9738 case DTMF_DIGITS_SEND:
9739 switch (internal_command)
9741 default:
9742 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9743 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9744 DTMF_COMMAND_1);
9745 /* fall through */
9746 case DTMF_COMMAND_1:
9747 if (adjust_b_process(Id, plci, Rc) != GOOD)
9749 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9750 UnMapId(Id), (char *)(FILE_), __LINE__));
9751 Info = _FACILITY_NOT_SUPPORTED;
9752 break;
9754 if (plci->internal_command)
9755 return;
9756 /* fall through */
9757 case DTMF_COMMAND_2:
9758 if (plci_nl_busy(plci))
9760 plci->internal_command = DTMF_COMMAND_2;
9761 return;
9763 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9764 plci->internal_command = DTMF_COMMAND_3;
9765 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9766 return;
9767 case DTMF_COMMAND_3:
9768 if ((Rc != OK) && (Rc != OK_FC))
9770 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9771 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9772 if (plci->dtmf_send_requests != 0)
9773 (plci->dtmf_send_requests)--;
9774 Info = _FACILITY_NOT_SUPPORTED;
9775 break;
9777 return;
9779 break;
9781 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9782 "wws", Info, SELECTOR_DTMF, result);
9786 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9788 word Info;
9789 word i, j;
9790 byte mask;
9791 API_PARSE dtmf_parms[5];
9792 byte result[40];
9794 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9795 UnMapId(Id), (char *)(FILE_), __LINE__));
9797 Info = GOOD;
9798 result[0] = 2;
9799 PUT_WORD(&result[1], DTMF_SUCCESS);
9800 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9802 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9803 UnMapId(Id), (char *)(FILE_), __LINE__));
9804 Info = _FACILITY_NOT_SUPPORTED;
9806 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9808 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9809 UnMapId(Id), (char *)(FILE_), __LINE__));
9810 Info = _WRONG_MESSAGE_FORMAT;
9813 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9814 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9816 if (!((a->requested_options_table[appl->Id - 1])
9817 & (1L << PRIVATE_DTMF_TONE)))
9819 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9820 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9821 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9823 else
9825 for (i = 0; i < 32; i++)
9826 result[4 + i] = 0;
9827 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9829 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9831 if (dtmf_digit_map[i].listen_mask != 0)
9832 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9835 else
9837 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9839 if (dtmf_digit_map[i].send_mask != 0)
9840 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9843 result[0] = 3 + 32;
9844 result[3] = 32;
9848 else if (plci == NULL)
9850 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9851 UnMapId(Id), (char *)(FILE_), __LINE__));
9852 Info = _WRONG_IDENTIFIER;
9854 else
9856 if (!plci->State
9857 || !plci->NL.Id || plci->nl_remove_id)
9859 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9860 UnMapId(Id), (char *)(FILE_), __LINE__));
9861 Info = _WRONG_STATE;
9863 else
9865 plci->command = 0;
9866 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9867 mask = 0x01;
9868 switch (plci->dtmf_cmd)
9871 case DTMF_LISTEN_TONE_START:
9872 case DTMF_LISTEN_TONE_STOP:
9873 mask <<= 1; /* fall through */
9874 case DTMF_LISTEN_MF_START:
9875 case DTMF_LISTEN_MF_STOP:
9876 mask <<= 1;
9877 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9878 & (1L << PRIVATE_DTMF_TONE)))
9880 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9881 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9882 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9883 break;
9885 /* fall through */
9887 case DTMF_LISTEN_START:
9888 case DTMF_LISTEN_STOP:
9889 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9890 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9892 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9893 UnMapId(Id), (char *)(FILE_), __LINE__));
9894 Info = _FACILITY_NOT_SUPPORTED;
9895 break;
9897 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9899 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9901 plci->dtmf_rec_pulse_ms = 0;
9902 plci->dtmf_rec_pause_ms = 0;
9904 else
9906 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9907 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9910 start_internal_command(Id, plci, dtmf_command);
9911 return (false);
9914 case DTMF_SEND_TONE:
9915 mask <<= 1; /* fall through */
9916 case DTMF_SEND_MF:
9917 mask <<= 1;
9918 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9919 & (1L << PRIVATE_DTMF_TONE)))
9921 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9922 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9923 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9924 break;
9926 /* fall through */
9928 case DTMF_DIGITS_SEND:
9929 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9931 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9932 UnMapId(Id), (char *)(FILE_), __LINE__));
9933 Info = _WRONG_MESSAGE_FORMAT;
9934 break;
9936 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9938 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9939 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9941 i = 0;
9942 j = 0;
9943 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9945 j = 0;
9946 while ((j < DTMF_DIGIT_MAP_ENTRIES)
9947 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9948 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9950 j++;
9952 i++;
9954 if (j == DTMF_DIGIT_MAP_ENTRIES)
9956 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9957 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9958 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9959 break;
9961 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9963 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9964 UnMapId(Id), (char *)(FILE_), __LINE__));
9965 Info = _WRONG_STATE;
9966 break;
9968 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9969 start_internal_command(Id, plci, dtmf_command);
9970 return (false);
9972 default:
9973 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9974 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9975 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9979 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9980 "wws", Info, SELECTOR_DTMF, result);
9981 return (false);
9985 static void dtmf_confirmation(dword Id, PLCI *plci)
9987 word i;
9988 byte result[4];
9990 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9991 UnMapId(Id), (char *)(FILE_), __LINE__));
9993 result[0] = 2;
9994 PUT_WORD(&result[1], DTMF_SUCCESS);
9995 if (plci->dtmf_send_requests != 0)
9997 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9998 "wws", GOOD, SELECTOR_DTMF, result);
9999 (plci->dtmf_send_requests)--;
10000 for (i = 0; i < plci->dtmf_send_requests; i++)
10001 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10006 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10008 word i, j, n;
10010 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10011 UnMapId(Id), (char *)(FILE_), __LINE__));
10013 n = 0;
10014 for (i = 1; i < length; i++)
10016 j = 0;
10017 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10018 && ((msg[i] != dtmf_digit_map[j].code)
10019 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10021 j++;
10023 if (j < DTMF_DIGIT_MAP_ENTRIES)
10026 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10027 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10028 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10030 if (n + 1 == i)
10032 for (i = length; i > n + 1; i--)
10033 msg[i] = msg[i - 1];
10034 length++;
10035 i++;
10037 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10039 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10041 msg[++n] = dtmf_digit_map[j].character;
10044 if (n != 0)
10046 msg[0] = (byte) n;
10047 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10052 /*------------------------------------------------------------------*/
10053 /* DTMF parameters */
10054 /*------------------------------------------------------------------*/
10056 static void dtmf_parameter_write(PLCI *plci)
10058 word i;
10059 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10061 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10062 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10063 (char *)(FILE_), __LINE__));
10065 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10066 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10067 for (i = 0; i < plci->dtmf_parameter_length; i++)
10068 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10069 add_p(plci, FTY, parameter_buffer);
10070 sig_req(plci, TEL_CTRL, 0);
10071 send_req(plci);
10075 static void dtmf_parameter_clear_config(PLCI *plci)
10078 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10079 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10080 (char *)(FILE_), __LINE__));
10082 plci->dtmf_parameter_length = 0;
10086 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10089 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10090 UnMapId(Id), (char *)(FILE_), __LINE__));
10095 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10098 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10099 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10101 return (GOOD);
10105 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10107 word Info;
10109 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10110 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10112 Info = GOOD;
10113 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10114 && (plci->dtmf_parameter_length != 0))
10116 switch (plci->adjust_b_state)
10118 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10119 plci->internal_command = plci->adjust_b_command;
10120 if (plci->sig_req)
10122 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10123 break;
10125 dtmf_parameter_write(plci);
10126 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10127 break;
10128 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10129 if ((Rc != OK) && (Rc != OK_FC))
10131 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10132 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10133 Info = _WRONG_STATE;
10134 break;
10136 break;
10139 return (Info);
10143 /*------------------------------------------------------------------*/
10144 /* Line interconnect facilities */
10145 /*------------------------------------------------------------------*/
10148 LI_CONFIG *li_config_table;
10149 word li_total_channels;
10152 /*------------------------------------------------------------------*/
10153 /* translate a CHI information element to a channel number */
10154 /* returns 0xff - any channel */
10155 /* 0xfe - chi wrong coding */
10156 /* 0xfd - D-channel */
10157 /* 0x00 - no channel */
10158 /* else channel number / PRI: timeslot */
10159 /* if channels is provided we accept more than one channel. */
10160 /*------------------------------------------------------------------*/
10162 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10164 int p;
10165 int i;
10166 dword map;
10167 byte excl;
10168 byte ofs;
10169 byte ch;
10171 if (pchannelmap) *pchannelmap = 0;
10172 if (!chi[0]) return 0xff;
10173 excl = 0;
10175 if (chi[1] & 0x20) {
10176 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10177 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10178 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10179 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10180 if (chi[1] & 0x08) excl = 0x40;
10182 /* int. id present */
10183 if (chi[1] & 0x40) {
10184 p = i + 1;
10185 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10186 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10189 /* coding standard, Number/Map, Channel Type */
10190 p = i + 1;
10191 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10192 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10193 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10195 /* Number/Map */
10196 if (chi[p] & 0x10) {
10198 /* map */
10199 if ((chi[0] - p) == 4) ofs = 0;
10200 else if ((chi[0] - p) == 3) ofs = 1;
10201 else return 0xfe;
10202 ch = 0;
10203 map = 0;
10204 for (i = 0; i < 4 && p < chi[0]; i++) {
10205 p++;
10206 ch += 8;
10207 map <<= 8;
10208 if (chi[p]) {
10209 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10210 map |= chi[p];
10213 ch += ofs;
10214 map <<= ofs;
10216 else {
10218 /* number */
10219 p = i + 1;
10220 ch = chi[p] & 0x3f;
10221 if (pchannelmap) {
10222 if ((byte)(chi[0] - p) > 30) return 0xfe;
10223 map = 0;
10224 for (i = p; i <= chi[0]; i++) {
10225 if ((chi[i] & 0x7f) > 31) return 0xfe;
10226 map |= (1L << (chi[i] & 0x7f));
10229 else {
10230 if (p != chi[0]) return 0xfe;
10231 if (ch > 31) return 0xfe;
10232 map = (1L << ch);
10234 if (chi[p] & 0x40) return 0xfe;
10236 if (pchannelmap) *pchannelmap = map;
10237 else if (map != ((dword)(1L << ch))) return 0xfe;
10238 return (byte)(excl | ch);
10240 else { /* not PRI */
10241 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10242 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10243 if (chi[1] & 0x08) excl = 0x40;
10245 switch (chi[1] | 0x98) {
10246 case 0x98: return 0;
10247 case 0x99:
10248 if (pchannelmap) *pchannelmap = 2;
10249 return excl | 1;
10250 case 0x9a:
10251 if (pchannelmap) *pchannelmap = 4;
10252 return excl | 2;
10253 case 0x9b: return 0xff;
10254 case 0x9c: return 0xfd; /* d-ch */
10255 default: return 0xfe;
10261 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10263 DIVA_CAPI_ADAPTER *a;
10264 PLCI *splci;
10265 byte old_id;
10267 a = plci->adapter;
10268 old_id = plci->li_bchannel_id;
10269 if (a->li_pri)
10271 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10272 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10273 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10274 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10275 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10277 else
10279 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10281 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10282 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10283 plci->li_bchannel_id = bchannel_id & 0x03;
10284 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10286 splci = a->AdvSignalPLCI;
10287 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10289 if ((splci->li_bchannel_id != 0)
10290 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10292 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10294 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10295 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10296 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10297 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10298 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10301 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10302 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10305 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10306 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10308 mixer_clear_config(plci);
10310 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10311 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10312 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10316 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10318 DIVA_CAPI_ADAPTER *a;
10319 PLCI *splci;
10320 byte ch, old_id;
10322 a = plci->adapter;
10323 old_id = plci->li_bchannel_id;
10324 ch = chi_to_channel(chi, NULL);
10325 if (!(ch & 0x80))
10327 if (a->li_pri)
10329 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10330 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10331 plci->li_bchannel_id = (ch & 0x1f) + 1;
10332 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10333 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10335 else
10337 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10339 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10340 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10341 plci->li_bchannel_id = ch & 0x1f;
10342 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10344 splci = a->AdvSignalPLCI;
10345 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10347 if ((splci->li_bchannel_id != 0)
10348 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10350 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10352 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10353 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10354 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10355 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10356 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10359 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10360 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10364 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10365 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10367 mixer_clear_config(plci);
10369 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10370 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10371 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10375 #define MIXER_MAX_DUMP_CHANNELS 34
10377 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10379 word n, i, j;
10380 char *p;
10381 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10383 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10384 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10386 for (i = 0; i < li_total_channels; i++)
10388 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10389 if (li_config_table[i].chflags != 0)
10390 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10391 else
10393 for (j = 0; j < li_total_channels; j++)
10395 if (((li_config_table[i].flag_table[j]) != 0)
10396 || ((li_config_table[j].flag_table[i]) != 0))
10398 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10400 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10401 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10403 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10408 for (i = 0; i < li_total_channels; i++)
10410 for (j = 0; j < li_total_channels; j++)
10412 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10413 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10414 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10417 for (n = 0; n < li_total_channels; n++)
10419 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10421 for (i = 0; i < li_total_channels; i++)
10423 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10425 for (j = 0; j < li_total_channels; j++)
10427 li_config_table[i].coef_table[j] |=
10428 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10434 for (i = 0; i < li_total_channels; i++)
10436 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10438 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10439 for (j = 0; j < li_total_channels; j++)
10441 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10442 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10444 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10445 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10448 for (i = 0; i < li_total_channels; i++)
10450 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10452 for (j = 0; j < li_total_channels; j++)
10454 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10455 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10456 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10457 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10458 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10459 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10460 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10461 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10463 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10465 for (j = 0; j < li_total_channels; j++)
10467 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10469 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10470 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10471 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10475 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10477 for (j = 0; j < li_total_channels; j++)
10479 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10480 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10483 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10485 for (j = 0; j < li_total_channels; j++)
10487 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10489 for (n = 0; n < li_total_channels; n++)
10491 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10493 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10494 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10496 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10497 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10498 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10500 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10501 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10509 for (i = 0; i < li_total_channels; i++)
10511 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10513 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10514 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10515 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10516 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10517 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10518 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10519 for (j = 0; j < li_total_channels; j++)
10521 if ((li_config_table[i].flag_table[j] &
10522 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10523 || (li_config_table[j].flag_table[i] &
10524 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10526 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10528 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10529 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10530 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10531 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10533 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10535 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10536 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10540 for (i = 0; i < li_total_channels; i++)
10542 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10544 j = 0;
10545 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10546 j++;
10547 if (j < li_total_channels)
10549 for (j = 0; j < li_total_channels; j++)
10551 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10552 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10553 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10558 n = li_total_channels;
10559 if (n > MIXER_MAX_DUMP_CHANNELS)
10560 n = MIXER_MAX_DUMP_CHANNELS;
10562 p = hex_line;
10563 for (j = 0; j < n; j++)
10565 if ((j & 0x7) == 0)
10566 *(p++) = ' ';
10567 p = hex_byte_pack(p, li_config_table[j].curchnl);
10569 *p = '\0';
10570 dbug(1, dprintf("[%06lx] CURRENT %s",
10571 (dword)(UnMapController(a->Id)), (char *)hex_line));
10572 p = hex_line;
10573 for (j = 0; j < n; j++)
10575 if ((j & 0x7) == 0)
10576 *(p++) = ' ';
10577 p = hex_byte_pack(p, li_config_table[j].channel);
10579 *p = '\0';
10580 dbug(1, dprintf("[%06lx] CHANNEL %s",
10581 (dword)(UnMapController(a->Id)), (char *)hex_line));
10582 p = hex_line;
10583 for (j = 0; j < n; j++)
10585 if ((j & 0x7) == 0)
10586 *(p++) = ' ';
10587 p = hex_byte_pack(p, li_config_table[j].chflags);
10589 *p = '\0';
10590 dbug(1, dprintf("[%06lx] CHFLAG %s",
10591 (dword)(UnMapController(a->Id)), (char *)hex_line));
10592 for (i = 0; i < n; i++)
10594 p = hex_line;
10595 for (j = 0; j < n; j++)
10597 if ((j & 0x7) == 0)
10598 *(p++) = ' ';
10599 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10601 *p = '\0';
10602 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10603 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10605 for (i = 0; i < n; i++)
10607 p = hex_line;
10608 for (j = 0; j < n; j++)
10610 if ((j & 0x7) == 0)
10611 *(p++) = ' ';
10612 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10614 *p = '\0';
10615 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10616 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10621 static struct
10623 byte mask;
10624 byte line_flags;
10625 } mixer_write_prog_pri[] =
10627 { LI_COEF_CH_CH, 0 },
10628 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10629 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10630 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10633 static struct
10635 byte from_ch;
10636 byte to_ch;
10637 byte mask;
10638 byte xconnect_override;
10639 } mixer_write_prog_bri[] =
10641 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10642 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10643 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10644 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10645 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10646 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10647 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10648 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10649 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10650 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10651 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10652 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10653 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10654 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10655 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10656 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10657 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10658 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10659 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10660 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10661 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10662 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10663 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10664 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10665 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10666 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10667 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10668 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10669 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10670 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10671 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10672 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10673 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10674 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10675 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10676 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10679 static byte mixer_swapped_index_bri[] =
10681 18, /* B to B */
10682 19, /* Alt B to B */
10683 20, /* PC to B */
10684 21, /* Alt PC to B */
10685 22, /* IC to B */
10686 23, /* Alt IC to B */
10687 24, /* B to PC */
10688 25, /* Alt B to PC */
10689 26, /* PC to PC */
10690 27, /* Alt PC to PC */
10691 28, /* IC to PC */
10692 29, /* Alt IC to PC */
10693 30, /* B to IC */
10694 31, /* Alt B to IC */
10695 32, /* PC to IC */
10696 33, /* Alt PC to IC */
10697 34, /* IC to IC */
10698 35, /* Alt IC to IC */
10699 0, /* Alt B to Alt B */
10700 1, /* B to Alt B */
10701 2, /* Alt PC to Alt B */
10702 3, /* PC to Alt B */
10703 4, /* Alt IC to Alt B */
10704 5, /* IC to Alt B */
10705 6, /* Alt B to Alt PC */
10706 7, /* B to Alt PC */
10707 8, /* Alt PC to Alt PC */
10708 9, /* PC to Alt PC */
10709 10, /* Alt IC to Alt PC */
10710 11, /* IC to Alt PC */
10711 12, /* Alt B to Alt IC */
10712 13, /* B to Alt IC */
10713 14, /* Alt PC to Alt IC */
10714 15, /* PC to Alt IC */
10715 16, /* Alt IC to Alt IC */
10716 17 /* IC to Alt IC */
10719 static struct
10721 byte mask;
10722 byte from_pc;
10723 byte to_pc;
10724 } xconnect_write_prog[] =
10726 { LI_COEF_CH_CH, false, false },
10727 { LI_COEF_CH_PC, false, true },
10728 { LI_COEF_PC_CH, true, false },
10729 { LI_COEF_PC_PC, true, true }
10733 static void xconnect_query_addresses(PLCI *plci)
10735 DIVA_CAPI_ADAPTER *a;
10736 word w, ch;
10737 byte *p;
10739 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10740 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10741 (char *)(FILE_), __LINE__));
10743 a = plci->adapter;
10744 if (a->li_pri && ((plci->li_bchannel_id == 0)
10745 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10747 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10748 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10749 (char *)(FILE_), __LINE__));
10750 return;
10752 p = plci->internal_req_buffer;
10753 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10754 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10755 w = ch;
10756 *(p++) = (byte) w;
10757 *(p++) = (byte)(w >> 8);
10758 w = ch | XCONNECT_CHANNEL_PORT_PC;
10759 *(p++) = (byte) w;
10760 *(p++) = (byte)(w >> 8);
10761 plci->NData[0].P = plci->internal_req_buffer;
10762 plci->NData[0].PLength = p - plci->internal_req_buffer;
10763 plci->NL.X = plci->NData;
10764 plci->NL.ReqCh = 0;
10765 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10766 plci->adapter->request(&plci->NL);
10770 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10773 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10774 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10775 (char *)(FILE_), __LINE__, internal_command));
10777 plci->li_write_command = internal_command;
10778 plci->li_write_channel = 0;
10782 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10784 DIVA_CAPI_ADAPTER *a;
10785 word w, n, i, j, r, s, to_ch;
10786 dword d;
10787 byte *p;
10788 struct xconnect_transfer_address_s *transfer_address;
10789 byte ch_map[MIXER_CHANNELS_BRI];
10791 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10792 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10794 a = plci->adapter;
10795 if ((plci->li_bchannel_id == 0)
10796 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10798 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10799 UnMapId(Id), (char *)(FILE_), __LINE__));
10800 return (true);
10802 i = a->li_base + (plci->li_bchannel_id - 1);
10803 j = plci->li_write_channel;
10804 p = plci->internal_req_buffer;
10805 if (j != 0)
10807 if ((Rc != OK) && (Rc != OK_FC))
10809 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10810 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10811 return (false);
10814 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10816 r = 0;
10817 s = 0;
10818 if (j < li_total_channels)
10820 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10822 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10823 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10824 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10825 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10827 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10828 while ((j < li_total_channels)
10829 && ((r == 0)
10830 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10831 || (!li_config_table[j].adapter->li_pri
10832 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10833 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10834 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10835 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10836 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10837 || ((li_config_table[j].adapter->li_base != a->li_base)
10838 && !(r & s &
10839 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10840 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10841 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10842 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10844 j++;
10845 if (j < li_total_channels)
10846 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10849 if (j < li_total_channels)
10851 plci->internal_command = plci->li_write_command;
10852 if (plci_nl_busy(plci))
10853 return (true);
10854 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10855 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10858 if (li_config_table[j].adapter->li_base != a->li_base)
10860 r &= s &
10861 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10862 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10863 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10864 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10866 n = 0;
10869 if (r & xconnect_write_prog[n].mask)
10871 if (xconnect_write_prog[n].from_pc)
10872 transfer_address = &(li_config_table[j].send_pc);
10873 else
10874 transfer_address = &(li_config_table[j].send_b);
10875 d = transfer_address->card_address.low;
10876 *(p++) = (byte) d;
10877 *(p++) = (byte)(d >> 8);
10878 *(p++) = (byte)(d >> 16);
10879 *(p++) = (byte)(d >> 24);
10880 d = transfer_address->card_address.high;
10881 *(p++) = (byte) d;
10882 *(p++) = (byte)(d >> 8);
10883 *(p++) = (byte)(d >> 16);
10884 *(p++) = (byte)(d >> 24);
10885 d = transfer_address->offset;
10886 *(p++) = (byte) d;
10887 *(p++) = (byte)(d >> 8);
10888 *(p++) = (byte)(d >> 16);
10889 *(p++) = (byte)(d >> 24);
10890 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10891 *(p++) = (byte) w;
10892 *(p++) = (byte)(w >> 8);
10893 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10894 (li_config_table[i].adapter->u_law ?
10895 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10896 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10897 *(p++) = (byte) w;
10898 *(p++) = (byte) 0;
10899 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10901 n++;
10902 } while ((n < ARRAY_SIZE(xconnect_write_prog))
10903 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10904 if (n == ARRAY_SIZE(xconnect_write_prog))
10908 j++;
10909 if (j < li_total_channels)
10910 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10911 } while ((j < li_total_channels)
10912 && ((r == 0)
10913 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10914 || (!li_config_table[j].adapter->li_pri
10915 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10916 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10917 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10918 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10919 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10920 || ((li_config_table[j].adapter->li_base != a->li_base)
10921 && !(r & s &
10922 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10923 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10924 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10925 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10927 } while ((j < li_total_channels)
10928 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10930 else if (j == li_total_channels)
10932 plci->internal_command = plci->li_write_command;
10933 if (plci_nl_busy(plci))
10934 return (true);
10935 if (a->li_pri)
10937 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10938 w = 0;
10939 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10940 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10941 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10942 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10943 *(p++) = (byte) w;
10944 *(p++) = (byte)(w >> 8);
10946 else
10948 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10949 w = 0;
10950 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10951 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10953 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10955 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10956 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10957 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10958 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10959 *(p++) = (byte) w;
10960 *(p++) = (byte)(w >> 8);
10961 for (j = 0; j < sizeof(ch_map); j += 2)
10963 if (plci->li_bchannel_id == 2)
10965 ch_map[j] = (byte)(j + 1);
10966 ch_map[j + 1] = (byte) j;
10968 else
10970 ch_map[j] = (byte) j;
10971 ch_map[j + 1] = (byte)(j + 1);
10974 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10976 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10977 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10978 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10980 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10981 mixer_write_prog_bri[n].xconnect_override :
10982 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10983 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10985 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10986 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10989 else
10991 *p = 0x00;
10992 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10994 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10995 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10996 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10999 p++;
11002 j = li_total_channels + 1;
11005 else
11007 if (j <= li_total_channels)
11009 plci->internal_command = plci->li_write_command;
11010 if (plci_nl_busy(plci))
11011 return (true);
11012 if (j < a->li_base)
11013 j = a->li_base;
11014 if (a->li_pri)
11016 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11017 w = 0;
11018 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11019 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11020 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11021 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11022 *(p++) = (byte) w;
11023 *(p++) = (byte)(w >> 8);
11024 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11026 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11027 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11029 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030 if (w & mixer_write_prog_pri[n].mask)
11032 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11033 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11035 else
11036 *(p++) = 0x00;
11038 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11039 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11041 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11042 if (w & mixer_write_prog_pri[n].mask)
11044 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11045 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11047 else
11048 *(p++) = 0x00;
11052 else
11054 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11055 w = 0;
11056 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11057 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11059 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11061 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11062 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11063 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11064 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11065 *(p++) = (byte) w;
11066 *(p++) = (byte)(w >> 8);
11067 for (j = 0; j < sizeof(ch_map); j += 2)
11069 if (plci->li_bchannel_id == 2)
11071 ch_map[j] = (byte)(j + 1);
11072 ch_map[j + 1] = (byte) j;
11074 else
11076 ch_map[j] = (byte) j;
11077 ch_map[j + 1] = (byte)(j + 1);
11080 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11082 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11083 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11084 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11086 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11087 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11088 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11090 else
11092 *p = 0x00;
11093 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11095 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11096 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11097 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11100 p++;
11103 j = li_total_channels + 1;
11106 plci->li_write_channel = j;
11107 if (p != plci->internal_req_buffer)
11109 plci->NData[0].P = plci->internal_req_buffer;
11110 plci->NData[0].PLength = p - plci->internal_req_buffer;
11111 plci->NL.X = plci->NData;
11112 plci->NL.ReqCh = 0;
11113 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11114 plci->adapter->request(&plci->NL);
11116 return (true);
11120 static void mixer_notify_update(PLCI *plci, byte others)
11122 DIVA_CAPI_ADAPTER *a;
11123 word i, w;
11124 PLCI *notify_plci;
11125 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11127 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11128 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11129 (char *)(FILE_), __LINE__, others));
11131 a = plci->adapter;
11132 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11134 if (others)
11135 plci->li_notify_update = true;
11136 i = 0;
11139 notify_plci = NULL;
11140 if (others)
11142 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11143 i++;
11144 if (i < li_total_channels)
11145 notify_plci = li_config_table[i++].plci;
11147 else
11149 if ((plci->li_bchannel_id != 0)
11150 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11152 notify_plci = plci;
11155 if ((notify_plci != NULL)
11156 && !notify_plci->li_notify_update
11157 && (notify_plci->appl != NULL)
11158 && (notify_plci->State)
11159 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11161 notify_plci->li_notify_update = true;
11162 ((CAPI_MSG *) msg)->header.length = 18;
11163 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11164 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11165 ((CAPI_MSG *) msg)->header.number = 0;
11166 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11167 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11168 ((CAPI_MSG *) msg)->header.ncci = 0;
11169 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11170 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11171 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11172 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11173 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11174 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11175 if (w != _QUEUE_FULL)
11177 if (w != 0)
11179 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11180 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11181 (char *)(FILE_), __LINE__,
11182 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11184 notify_plci->li_notify_update = false;
11187 } while (others && (notify_plci != NULL));
11188 if (others)
11189 plci->li_notify_update = false;
11194 static void mixer_clear_config(PLCI *plci)
11196 DIVA_CAPI_ADAPTER *a;
11197 word i, j;
11199 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11200 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11201 (char *)(FILE_), __LINE__));
11203 plci->li_notify_update = false;
11204 plci->li_plci_b_write_pos = 0;
11205 plci->li_plci_b_read_pos = 0;
11206 plci->li_plci_b_req_pos = 0;
11207 a = plci->adapter;
11208 if ((plci->li_bchannel_id != 0)
11209 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11211 i = a->li_base + (plci->li_bchannel_id - 1);
11212 li_config_table[i].curchnl = 0;
11213 li_config_table[i].channel = 0;
11214 li_config_table[i].chflags = 0;
11215 for (j = 0; j < li_total_channels; j++)
11217 li_config_table[j].flag_table[i] = 0;
11218 li_config_table[i].flag_table[j] = 0;
11219 li_config_table[i].coef_table[j] = 0;
11220 li_config_table[j].coef_table[i] = 0;
11222 if (!a->li_pri)
11224 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11225 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11227 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11228 li_config_table[i].curchnl = 0;
11229 li_config_table[i].channel = 0;
11230 li_config_table[i].chflags = 0;
11231 for (j = 0; j < li_total_channels; j++)
11233 li_config_table[i].flag_table[j] = 0;
11234 li_config_table[j].flag_table[i] = 0;
11235 li_config_table[i].coef_table[j] = 0;
11236 li_config_table[j].coef_table[i] = 0;
11238 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11240 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11241 li_config_table[i].curchnl = 0;
11242 li_config_table[i].channel = 0;
11243 li_config_table[i].chflags = 0;
11244 for (j = 0; j < li_total_channels; j++)
11246 li_config_table[i].flag_table[j] = 0;
11247 li_config_table[j].flag_table[i] = 0;
11248 li_config_table[i].coef_table[j] = 0;
11249 li_config_table[j].coef_table[i] = 0;
11258 static void mixer_prepare_switch(dword Id, PLCI *plci)
11261 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11262 UnMapId(Id), (char *)(FILE_), __LINE__));
11266 mixer_indication_coefs_set(Id, plci);
11267 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11271 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11273 DIVA_CAPI_ADAPTER *a;
11274 word i, j;
11276 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11277 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11279 a = plci->adapter;
11280 if ((plci->li_bchannel_id != 0)
11281 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11283 i = a->li_base + (plci->li_bchannel_id - 1);
11284 for (j = 0; j < li_total_channels; j++)
11286 li_config_table[i].coef_table[j] &= 0xf;
11287 li_config_table[j].coef_table[i] &= 0xf;
11289 if (!a->li_pri)
11290 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11292 return (GOOD);
11296 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11298 DIVA_CAPI_ADAPTER *a;
11299 word Info;
11301 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11302 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11304 Info = GOOD;
11305 a = plci->adapter;
11306 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11307 && (plci->li_bchannel_id != 0)
11308 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11310 switch (plci->adjust_b_state)
11312 case ADJUST_B_RESTORE_MIXER_1:
11313 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11315 plci->internal_command = plci->adjust_b_command;
11316 if (plci_nl_busy(plci))
11318 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11319 break;
11321 xconnect_query_addresses(plci);
11322 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11323 break;
11325 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11326 Rc = OK;
11327 /* fall through */
11328 case ADJUST_B_RESTORE_MIXER_2:
11329 case ADJUST_B_RESTORE_MIXER_3:
11330 case ADJUST_B_RESTORE_MIXER_4:
11331 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11333 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11334 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11335 Info = _WRONG_STATE;
11336 break;
11338 if (Rc == OK)
11340 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11341 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11342 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11343 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11345 else if (Rc == 0)
11347 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11348 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11349 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11350 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11352 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11354 plci->internal_command = plci->adjust_b_command;
11355 break;
11357 /* fall through */
11358 case ADJUST_B_RESTORE_MIXER_5:
11359 xconnect_write_coefs(plci, plci->adjust_b_command);
11360 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11361 Rc = OK;
11362 /* fall through */
11363 case ADJUST_B_RESTORE_MIXER_6:
11364 if (!xconnect_write_coefs_process(Id, plci, Rc))
11366 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11367 UnMapId(Id), (char *)(FILE_), __LINE__));
11368 Info = _FACILITY_NOT_SUPPORTED;
11369 break;
11371 if (plci->internal_command)
11372 break;
11373 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11374 case ADJUST_B_RESTORE_MIXER_7:
11375 break;
11378 return (Info);
11382 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11384 DIVA_CAPI_ADAPTER *a;
11385 word i, internal_command;
11387 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11388 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11389 plci->li_cmd));
11391 a = plci->adapter;
11392 internal_command = plci->internal_command;
11393 plci->internal_command = 0;
11394 switch (plci->li_cmd)
11396 case LI_REQ_CONNECT:
11397 case LI_REQ_DISCONNECT:
11398 case LI_REQ_SILENT_UPDATE:
11399 switch (internal_command)
11401 default:
11402 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11404 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11405 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11407 /* fall through */
11408 case MIXER_COMMAND_1:
11409 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11411 if (adjust_b_process(Id, plci, Rc) != GOOD)
11413 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11414 UnMapId(Id), (char *)(FILE_), __LINE__));
11415 break;
11417 if (plci->internal_command)
11418 return;
11420 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11421 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11422 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11423 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11424 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11426 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11428 else
11432 mixer_indication_coefs_set(Id, plci);
11433 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11435 /* fall through */
11436 case MIXER_COMMAND_2:
11437 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11438 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11439 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11440 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11442 if (!xconnect_write_coefs_process(Id, plci, Rc))
11444 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11445 UnMapId(Id), (char *)(FILE_), __LINE__));
11446 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11450 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11451 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11452 i = (plci->li_plci_b_write_pos == 0) ?
11453 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11454 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11455 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11457 break;
11459 if (plci->internal_command)
11460 return;
11462 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11464 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11465 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11467 /* fall through */
11468 case MIXER_COMMAND_3:
11469 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11471 if (adjust_b_process(Id, plci, Rc) != GOOD)
11473 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11474 UnMapId(Id), (char *)(FILE_), __LINE__));
11475 break;
11477 if (plci->internal_command)
11478 return;
11480 break;
11482 break;
11484 if ((plci->li_bchannel_id == 0)
11485 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11487 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11488 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11490 else
11492 i = a->li_base + (plci->li_bchannel_id - 1);
11493 li_config_table[i].curchnl = plci->li_channel_bits;
11494 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11496 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11497 li_config_table[i].curchnl = plci->li_channel_bits;
11498 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11500 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11501 li_config_table[i].curchnl = plci->li_channel_bits;
11508 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11509 dword plci_b_id, byte connect, dword li_flags)
11511 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11512 PLCI *plci_b;
11513 DIVA_CAPI_ADAPTER *a_b;
11515 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11516 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11517 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11518 if (!a->li_pri && (plci->tel == ADV_VOICE)
11519 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11521 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11522 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11523 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11525 else
11527 ch_a_v = ch_a;
11528 ch_a_s = ch_a;
11530 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11531 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11532 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11534 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11535 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11536 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11538 else
11540 ch_b_v = ch_b;
11541 ch_b_s = ch_b;
11543 if (connect)
11545 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11546 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11547 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11548 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11550 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11551 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11552 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11553 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11554 if (ch_a_v == ch_b_v)
11556 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11557 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11559 else
11561 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11563 for (i = 0; i < li_total_channels; i++)
11565 if (i != ch_a_v)
11566 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11569 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11571 for (i = 0; i < li_total_channels; i++)
11573 if (i != ch_a_s)
11574 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11577 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11579 for (i = 0; i < li_total_channels; i++)
11581 if (i != ch_a_v)
11582 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11585 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11587 for (i = 0; i < li_total_channels; i++)
11589 if (i != ch_a_s)
11590 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11594 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11596 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11597 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11598 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11599 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11601 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11603 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11604 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11605 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11606 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11608 if (li_flags & LI_FLAG_MONITOR_A)
11610 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11611 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11613 if (li_flags & LI_FLAG_MONITOR_B)
11615 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11616 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11618 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11620 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11621 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11623 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11625 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11626 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11628 if (li_flags & LI_FLAG_MIX_A)
11630 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11631 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11633 if (li_flags & LI_FLAG_MIX_B)
11635 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11636 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11638 if (ch_a_v != ch_a_s)
11640 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11641 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11643 if (ch_b_v != ch_b_s)
11645 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11646 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11651 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11652 dword plci_b_id, byte connect, dword li_flags)
11654 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11655 PLCI *plci_b;
11656 DIVA_CAPI_ADAPTER *a_b;
11658 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11659 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11660 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11661 if (!a->li_pri && (plci->tel == ADV_VOICE)
11662 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11664 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11665 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11668 else
11670 ch_a_v = ch_a;
11671 ch_a_s = ch_a;
11673 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11674 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11675 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11677 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11678 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11679 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11681 else
11683 ch_b_v = ch_b;
11684 ch_b_s = ch_b;
11686 if (connect)
11688 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11689 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11690 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11691 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11692 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11693 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11695 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11696 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11697 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11698 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11699 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11700 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11701 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11702 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11703 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11705 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11706 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11707 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11708 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11710 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11712 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11713 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11714 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11715 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11717 if (li_flags & LI2_FLAG_MONITOR_B)
11719 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11720 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11722 if (li_flags & LI2_FLAG_MIX_B)
11724 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11725 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11727 if (li_flags & LI2_FLAG_MONITOR_X)
11728 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11729 if (li_flags & LI2_FLAG_MIX_X)
11730 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11731 if (li_flags & LI2_FLAG_LOOP_B)
11733 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11734 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11735 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11736 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11738 if (li_flags & LI2_FLAG_LOOP_PC)
11739 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11740 if (li_flags & LI2_FLAG_LOOP_X)
11741 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11742 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11743 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11744 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11745 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11746 if (ch_a_v != ch_a_s)
11748 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11749 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11751 if (ch_b_v != ch_b_s)
11753 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11754 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11759 static word li_check_main_plci(dword Id, PLCI *plci)
11761 if (plci == NULL)
11763 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11764 UnMapId(Id), (char *)(FILE_), __LINE__));
11765 return (_WRONG_IDENTIFIER);
11767 if (!plci->State
11768 || !plci->NL.Id || plci->nl_remove_id
11769 || (plci->li_bchannel_id == 0))
11771 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11772 UnMapId(Id), (char *)(FILE_), __LINE__));
11773 return (_WRONG_STATE);
11775 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11776 return (GOOD);
11780 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11781 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11783 byte ctlr_b;
11784 PLCI *plci_b;
11786 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11787 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11789 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11790 UnMapId(Id), (char *)(FILE_), __LINE__));
11791 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11792 return (NULL);
11794 ctlr_b = 0;
11795 if ((plci_b_id & 0x7f) != 0)
11797 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11798 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11799 ctlr_b = 0;
11801 if ((ctlr_b == 0)
11802 || (((plci_b_id >> 8) & 0xff) == 0)
11803 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11805 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11806 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11807 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11808 return (NULL);
11810 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11811 if (!plci_b->State
11812 || !plci_b->NL.Id || plci_b->nl_remove_id
11813 || (plci_b->li_bchannel_id == 0))
11815 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11816 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11817 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11818 return (NULL);
11820 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11821 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11822 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11823 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11824 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11826 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11827 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11828 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11829 return (NULL);
11831 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11832 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11834 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11835 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11836 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11837 return (NULL);
11839 return (plci_b);
11843 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11844 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11846 byte ctlr_b;
11847 PLCI *plci_b;
11849 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11850 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11852 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11853 UnMapId(Id), (char *)(FILE_), __LINE__));
11854 PUT_WORD(p_result, _WRONG_STATE);
11855 return (NULL);
11857 ctlr_b = 0;
11858 if ((plci_b_id & 0x7f) != 0)
11860 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11861 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11862 ctlr_b = 0;
11864 if ((ctlr_b == 0)
11865 || (((plci_b_id >> 8) & 0xff) == 0)
11866 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11868 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11869 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11870 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11871 return (NULL);
11873 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11874 if (!plci_b->State
11875 || !plci_b->NL.Id || plci_b->nl_remove_id
11876 || (plci_b->li_bchannel_id == 0)
11877 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11879 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11880 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11881 PUT_WORD(p_result, _WRONG_STATE);
11882 return (NULL);
11884 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11885 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11886 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11887 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11889 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11890 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11891 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11892 return (NULL);
11894 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11895 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11897 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11898 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11899 PUT_WORD(p_result, _WRONG_STATE);
11900 return (NULL);
11902 return (plci_b);
11906 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
11908 word Info;
11909 word i;
11910 dword d, li_flags, plci_b_id;
11911 PLCI *plci_b;
11912 API_PARSE li_parms[3];
11913 API_PARSE li_req_parms[3];
11914 API_PARSE li_participant_struct[2];
11915 API_PARSE li_participant_parms[3];
11916 word participant_parms_pos;
11917 byte result_buffer[32];
11918 byte *result;
11919 word result_pos;
11920 word plci_b_write_pos;
11922 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11923 UnMapId(Id), (char *)(FILE_), __LINE__));
11925 Info = GOOD;
11926 result = result_buffer;
11927 result_buffer[0] = 0;
11928 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11930 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11931 UnMapId(Id), (char *)(FILE_), __LINE__));
11932 Info = _FACILITY_NOT_SUPPORTED;
11934 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11936 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11937 UnMapId(Id), (char *)(FILE_), __LINE__));
11938 Info = _WRONG_MESSAGE_FORMAT;
11940 else
11942 result_buffer[0] = 3;
11943 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11944 result_buffer[3] = 0;
11945 switch (GET_WORD(li_parms[0].info))
11947 case LI_GET_SUPPORTED_SERVICES:
11948 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11950 result_buffer[0] = 17;
11951 result_buffer[3] = 14;
11952 PUT_WORD(&result_buffer[4], GOOD);
11953 d = 0;
11954 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11955 d |= LI_CONFERENCING_SUPPORTED;
11956 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11957 d |= LI_MONITORING_SUPPORTED;
11958 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11959 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11960 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11961 d |= LI_CROSS_CONTROLLER_SUPPORTED;
11962 PUT_DWORD(&result_buffer[6], d);
11963 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11965 d = 0;
11966 for (i = 0; i < li_total_channels; i++)
11968 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11969 && (li_config_table[i].adapter->li_pri
11970 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11972 d++;
11976 else
11978 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11980 PUT_DWORD(&result_buffer[10], d / 2);
11981 PUT_DWORD(&result_buffer[14], d);
11983 else
11985 result_buffer[0] = 25;
11986 result_buffer[3] = 22;
11987 PUT_WORD(&result_buffer[4], GOOD);
11988 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11989 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11990 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11991 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11992 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11993 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11994 d |= LI2_PC_LOOPING_SUPPORTED;
11995 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11996 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11997 PUT_DWORD(&result_buffer[6], d);
11998 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11999 PUT_DWORD(&result_buffer[10], d / 2);
12000 PUT_DWORD(&result_buffer[14], d - 1);
12001 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12003 d = 0;
12004 for (i = 0; i < li_total_channels; i++)
12006 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007 && (li_config_table[i].adapter->li_pri
12008 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12010 d++;
12014 PUT_DWORD(&result_buffer[18], d / 2);
12015 PUT_DWORD(&result_buffer[22], d - 1);
12017 break;
12019 case LI_REQ_CONNECT:
12020 if (li_parms[1].length == 8)
12022 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12023 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12025 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12026 UnMapId(Id), (char *)(FILE_), __LINE__));
12027 Info = _WRONG_MESSAGE_FORMAT;
12028 break;
12030 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12031 li_flags = GET_DWORD(li_req_parms[1].info);
12032 Info = li_check_main_plci(Id, plci);
12033 result_buffer[0] = 9;
12034 result_buffer[3] = 6;
12035 PUT_DWORD(&result_buffer[4], plci_b_id);
12036 PUT_WORD(&result_buffer[8], GOOD);
12037 if (Info != GOOD)
12038 break;
12039 result = plci->saved_msg.info;
12040 for (i = 0; i <= result_buffer[0]; i++)
12041 result[i] = result_buffer[i];
12042 plci_b_write_pos = plci->li_plci_b_write_pos;
12043 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12044 if (plci_b == NULL)
12045 break;
12046 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12047 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12048 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12049 plci->li_plci_b_write_pos = plci_b_write_pos;
12051 else
12053 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12054 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12056 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12057 UnMapId(Id), (char *)(FILE_), __LINE__));
12058 Info = _WRONG_MESSAGE_FORMAT;
12059 break;
12061 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12062 Info = li_check_main_plci(Id, plci);
12063 result_buffer[0] = 7;
12064 result_buffer[3] = 4;
12065 PUT_WORD(&result_buffer[4], Info);
12066 result_buffer[6] = 0;
12067 if (Info != GOOD)
12068 break;
12069 result = plci->saved_msg.info;
12070 for (i = 0; i <= result_buffer[0]; i++)
12071 result[i] = result_buffer[i];
12072 plci_b_write_pos = plci->li_plci_b_write_pos;
12073 participant_parms_pos = 0;
12074 result_pos = 7;
12075 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12076 while (participant_parms_pos < li_req_parms[1].length)
12078 result[result_pos] = 6;
12079 result_pos += 7;
12080 PUT_DWORD(&result[result_pos - 6], 0);
12081 PUT_WORD(&result[result_pos - 2], GOOD);
12082 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12083 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12085 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12086 UnMapId(Id), (char *)(FILE_), __LINE__));
12087 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12088 break;
12090 if (api_parse(&li_participant_struct[0].info[1],
12091 li_participant_struct[0].length, "dd", li_participant_parms))
12093 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12094 UnMapId(Id), (char *)(FILE_), __LINE__));
12095 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12096 break;
12098 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12099 li_flags = GET_DWORD(li_participant_parms[1].info);
12100 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12101 if (sizeof(result) - result_pos < 7)
12103 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12104 UnMapId(Id), (char *)(FILE_), __LINE__));
12105 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12106 break;
12108 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12109 if (plci_b != NULL)
12111 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12112 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12113 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12114 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12115 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12117 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12118 (&li_req_parms[1].info[1]));
12120 result[0] = (byte)(result_pos - 1);
12121 result[3] = (byte)(result_pos - 4);
12122 result[6] = (byte)(result_pos - 7);
12123 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12124 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12125 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12127 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12128 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12130 else
12131 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12132 plci->li_plci_b_write_pos = plci_b_write_pos;
12134 mixer_calculate_coefs(a);
12135 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12136 mixer_notify_update(plci, true);
12137 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12138 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12139 plci->command = 0;
12140 plci->li_cmd = GET_WORD(li_parms[0].info);
12141 start_internal_command(Id, plci, mixer_command);
12142 return (false);
12144 case LI_REQ_DISCONNECT:
12145 if (li_parms[1].length == 4)
12147 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12148 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12150 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12151 UnMapId(Id), (char *)(FILE_), __LINE__));
12152 Info = _WRONG_MESSAGE_FORMAT;
12153 break;
12155 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12156 Info = li_check_main_plci(Id, plci);
12157 result_buffer[0] = 9;
12158 result_buffer[3] = 6;
12159 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12160 PUT_WORD(&result_buffer[8], GOOD);
12161 if (Info != GOOD)
12162 break;
12163 result = plci->saved_msg.info;
12164 for (i = 0; i <= result_buffer[0]; i++)
12165 result[i] = result_buffer[i];
12166 plci_b_write_pos = plci->li_plci_b_write_pos;
12167 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12168 if (plci_b == NULL)
12169 break;
12170 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12171 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12172 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12173 plci->li_plci_b_write_pos = plci_b_write_pos;
12175 else
12177 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12178 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12180 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12181 UnMapId(Id), (char *)(FILE_), __LINE__));
12182 Info = _WRONG_MESSAGE_FORMAT;
12183 break;
12185 Info = li_check_main_plci(Id, plci);
12186 result_buffer[0] = 7;
12187 result_buffer[3] = 4;
12188 PUT_WORD(&result_buffer[4], Info);
12189 result_buffer[6] = 0;
12190 if (Info != GOOD)
12191 break;
12192 result = plci->saved_msg.info;
12193 for (i = 0; i <= result_buffer[0]; i++)
12194 result[i] = result_buffer[i];
12195 plci_b_write_pos = plci->li_plci_b_write_pos;
12196 participant_parms_pos = 0;
12197 result_pos = 7;
12198 while (participant_parms_pos < li_req_parms[0].length)
12200 result[result_pos] = 6;
12201 result_pos += 7;
12202 PUT_DWORD(&result[result_pos - 6], 0);
12203 PUT_WORD(&result[result_pos - 2], GOOD);
12204 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12205 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12207 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208 UnMapId(Id), (char *)(FILE_), __LINE__));
12209 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210 break;
12212 if (api_parse(&li_participant_struct[0].info[1],
12213 li_participant_struct[0].length, "d", li_participant_parms))
12215 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 UnMapId(Id), (char *)(FILE_), __LINE__));
12217 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218 break;
12220 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221 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, false, 0);
12233 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12234 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12236 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12237 (&li_req_parms[0].info[1]));
12239 result[0] = (byte)(result_pos - 1);
12240 result[3] = (byte)(result_pos - 4);
12241 result[6] = (byte)(result_pos - 7);
12242 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12243 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12244 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12246 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12247 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12249 else
12250 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12251 plci->li_plci_b_write_pos = plci_b_write_pos;
12253 mixer_calculate_coefs(a);
12254 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12255 mixer_notify_update(plci, true);
12256 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12257 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12258 plci->command = 0;
12259 plci->li_cmd = GET_WORD(li_parms[0].info);
12260 start_internal_command(Id, plci, mixer_command);
12261 return (false);
12263 case LI_REQ_SILENT_UPDATE:
12264 if (!plci || !plci->State
12265 || !plci->NL.Id || plci->nl_remove_id
12266 || (plci->li_bchannel_id == 0)
12267 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12269 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12270 UnMapId(Id), (char *)(FILE_), __LINE__));
12271 return (false);
12273 plci_b_write_pos = plci->li_plci_b_write_pos;
12274 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12275 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12277 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12278 UnMapId(Id), (char *)(FILE_), __LINE__));
12279 return (false);
12281 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12282 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12283 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12285 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12286 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12288 else
12289 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12290 plci->li_plci_b_write_pos = plci_b_write_pos;
12291 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12292 plci->command = 0;
12293 plci->li_cmd = GET_WORD(li_parms[0].info);
12294 start_internal_command(Id, plci, mixer_command);
12295 return (false);
12297 default:
12298 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12299 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12300 Info = _FACILITY_NOT_SUPPORTED;
12303 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12304 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12305 return (false);
12309 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12311 dword d;
12312 byte result[12];
12314 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12315 UnMapId(Id), (char *)(FILE_), __LINE__));
12317 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12321 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12322 if (!(d & LI_PLCI_B_SKIP_FLAG))
12324 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12326 if (d & LI_PLCI_B_DISC_FLAG)
12328 result[0] = 5;
12329 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12330 result[3] = 2;
12331 PUT_WORD(&result[4], _LI_USER_INITIATED);
12333 else
12335 result[0] = 7;
12336 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12337 result[3] = 4;
12338 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12341 else
12343 if (d & LI_PLCI_B_DISC_FLAG)
12345 result[0] = 9;
12346 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12347 result[3] = 6;
12348 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12349 PUT_WORD(&result[8], _LI_USER_INITIATED);
12351 else
12353 result[0] = 7;
12354 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12355 result[3] = 4;
12356 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12359 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12360 "ws", SELECTOR_LINE_INTERCONNECT, result);
12362 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12363 0 : plci->li_plci_b_read_pos + 1;
12364 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12369 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12371 word i, j, ch;
12372 struct xconnect_transfer_address_s s, *p;
12373 DIVA_CAPI_ADAPTER *a;
12375 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12376 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12378 a = plci->adapter;
12379 i = 1;
12380 for (i = 1; i < length; i += 16)
12382 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12383 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12384 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12385 ch = msg[i + 12] | (msg[i + 13] << 8);
12386 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12387 if (!a->li_pri && (plci->li_bchannel_id == 2))
12388 j = 1 - j;
12389 j += a->li_base;
12390 if (ch & XCONNECT_CHANNEL_PORT_PC)
12391 p = &(li_config_table[j].send_pc);
12392 else
12393 p = &(li_config_table[j].send_b);
12394 p->card_address.low = s.card_address.low;
12395 p->card_address.high = s.card_address.high;
12396 p->offset = s.offset;
12397 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12399 if (plci->internal_command_queue[0]
12400 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12401 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12402 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12404 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12405 if (!plci->internal_command)
12406 next_internal_command(Id, plci);
12408 mixer_notify_update(plci, true);
12412 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12415 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12416 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12421 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12423 word plci_b_write_pos;
12425 plci_b_write_pos = plci->li_plci_b_write_pos;
12426 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12427 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12429 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12430 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12431 (char *)(FILE_), __LINE__));
12432 return (false);
12434 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12435 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12436 plci->li_plci_b_write_pos = plci_b_write_pos;
12437 return (true);
12441 static void mixer_remove(PLCI *plci)
12443 DIVA_CAPI_ADAPTER *a;
12444 PLCI *notify_plci;
12445 dword plci_b_id;
12446 word i, j;
12448 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12449 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12450 (char *)(FILE_), __LINE__));
12452 a = plci->adapter;
12453 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12454 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12456 if ((plci->li_bchannel_id != 0)
12457 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12459 i = a->li_base + (plci->li_bchannel_id - 1);
12460 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12462 for (j = 0; j < li_total_channels; j++)
12464 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12465 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12467 notify_plci = li_config_table[j].plci;
12468 if ((notify_plci != NULL)
12469 && (notify_plci != plci)
12470 && (notify_plci->appl != NULL)
12471 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12472 && (notify_plci->State)
12473 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12475 mixer_notify_source_removed(notify_plci, plci_b_id);
12479 mixer_clear_config(plci);
12480 mixer_calculate_coefs(a);
12481 mixer_notify_update(plci, true);
12483 li_config_table[i].plci = NULL;
12484 plci->li_bchannel_id = 0;
12490 /*------------------------------------------------------------------*/
12491 /* Echo canceller facilities */
12492 /*------------------------------------------------------------------*/
12495 static void ec_write_parameters(PLCI *plci)
12497 word w;
12498 byte parameter_buffer[6];
12500 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12501 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12502 (char *)(FILE_), __LINE__));
12504 parameter_buffer[0] = 5;
12505 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12506 PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12507 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12508 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12509 PUT_WORD(&parameter_buffer[4], w);
12510 add_p(plci, FTY, parameter_buffer);
12511 sig_req(plci, TEL_CTRL, 0);
12512 send_req(plci);
12516 static void ec_clear_config(PLCI *plci)
12519 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12520 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12521 (char *)(FILE_), __LINE__));
12523 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12524 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12525 plci->ec_tail_length = 0;
12529 static void ec_prepare_switch(dword Id, PLCI *plci)
12532 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12533 UnMapId(Id), (char *)(FILE_), __LINE__));
12538 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12541 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12542 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12544 return (GOOD);
12548 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12550 word Info;
12552 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12553 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12555 Info = GOOD;
12556 if (plci->B1_facilities & B1_FACILITY_EC)
12558 switch (plci->adjust_b_state)
12560 case ADJUST_B_RESTORE_EC_1:
12561 plci->internal_command = plci->adjust_b_command;
12562 if (plci->sig_req)
12564 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12565 break;
12567 ec_write_parameters(plci);
12568 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12569 break;
12570 case ADJUST_B_RESTORE_EC_2:
12571 if ((Rc != OK) && (Rc != OK_FC))
12573 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12574 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12575 Info = _WRONG_STATE;
12576 break;
12578 break;
12581 return (Info);
12585 static void ec_command(dword Id, PLCI *plci, byte Rc)
12587 word internal_command, Info;
12588 byte result[8];
12590 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12591 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12592 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12594 Info = GOOD;
12595 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12597 result[0] = 2;
12598 PUT_WORD(&result[1], EC_SUCCESS);
12600 else
12602 result[0] = 5;
12603 PUT_WORD(&result[1], plci->ec_cmd);
12604 result[3] = 2;
12605 PUT_WORD(&result[4], GOOD);
12607 internal_command = plci->internal_command;
12608 plci->internal_command = 0;
12609 switch (plci->ec_cmd)
12611 case EC_ENABLE_OPERATION:
12612 case EC_FREEZE_COEFFICIENTS:
12613 case EC_RESUME_COEFFICIENT_UPDATE:
12614 case EC_RESET_COEFFICIENTS:
12615 switch (internal_command)
12617 default:
12618 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12619 B1_FACILITY_EC), EC_COMMAND_1);
12620 /* fall through */
12621 case EC_COMMAND_1:
12622 if (adjust_b_process(Id, plci, Rc) != GOOD)
12624 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12625 UnMapId(Id), (char *)(FILE_), __LINE__));
12626 Info = _FACILITY_NOT_SUPPORTED;
12627 break;
12629 if (plci->internal_command)
12630 return;
12631 /* fall through */
12632 case EC_COMMAND_2:
12633 if (plci->sig_req)
12635 plci->internal_command = EC_COMMAND_2;
12636 return;
12638 plci->internal_command = EC_COMMAND_3;
12639 ec_write_parameters(plci);
12640 return;
12641 case EC_COMMAND_3:
12642 if ((Rc != OK) && (Rc != OK_FC))
12644 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12645 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12646 Info = _FACILITY_NOT_SUPPORTED;
12647 break;
12649 break;
12651 break;
12653 case EC_DISABLE_OPERATION:
12654 switch (internal_command)
12656 default:
12657 case EC_COMMAND_1:
12658 if (plci->B1_facilities & B1_FACILITY_EC)
12660 if (plci->sig_req)
12662 plci->internal_command = EC_COMMAND_1;
12663 return;
12665 plci->internal_command = EC_COMMAND_2;
12666 ec_write_parameters(plci);
12667 return;
12669 Rc = OK;
12670 /* fall through */
12671 case EC_COMMAND_2:
12672 if ((Rc != OK) && (Rc != OK_FC))
12674 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12675 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12676 Info = _FACILITY_NOT_SUPPORTED;
12677 break;
12679 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12680 ~B1_FACILITY_EC), EC_COMMAND_3);
12681 /* fall through */
12682 case EC_COMMAND_3:
12683 if (adjust_b_process(Id, plci, Rc) != GOOD)
12685 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12686 UnMapId(Id), (char *)(FILE_), __LINE__));
12687 Info = _FACILITY_NOT_SUPPORTED;
12688 break;
12690 if (plci->internal_command)
12691 return;
12692 break;
12694 break;
12696 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12697 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12698 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12702 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12704 word Info;
12705 word opt;
12706 API_PARSE ec_parms[3];
12707 byte result[16];
12709 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12710 UnMapId(Id), (char *)(FILE_), __LINE__));
12712 Info = GOOD;
12713 result[0] = 0;
12714 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12716 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12717 UnMapId(Id), (char *)(FILE_), __LINE__));
12718 Info = _FACILITY_NOT_SUPPORTED;
12720 else
12722 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12724 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12726 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12727 UnMapId(Id), (char *)(FILE_), __LINE__));
12728 Info = _WRONG_MESSAGE_FORMAT;
12730 else
12732 if (plci == NULL)
12734 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12735 UnMapId(Id), (char *)(FILE_), __LINE__));
12736 Info = _WRONG_IDENTIFIER;
12738 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12740 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12741 UnMapId(Id), (char *)(FILE_), __LINE__));
12742 Info = _WRONG_STATE;
12744 else
12746 plci->command = 0;
12747 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12748 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12749 result[0] = 2;
12750 PUT_WORD(&result[1], EC_SUCCESS);
12751 if (msg[1].length >= 4)
12753 opt = GET_WORD(&ec_parms[0].info[2]);
12754 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12755 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12756 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12757 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12758 if (opt & EC_DETECT_DISABLE_TONE)
12759 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12760 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12761 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12762 if (msg[1].length >= 6)
12764 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12767 switch (plci->ec_cmd)
12769 case EC_ENABLE_OPERATION:
12770 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12771 start_internal_command(Id, plci, ec_command);
12772 return (false);
12774 case EC_DISABLE_OPERATION:
12775 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12776 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12777 LEC_RESET_COEFFICIENTS;
12778 start_internal_command(Id, plci, ec_command);
12779 return (false);
12781 case EC_FREEZE_COEFFICIENTS:
12782 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12783 start_internal_command(Id, plci, ec_command);
12784 return (false);
12786 case EC_RESUME_COEFFICIENT_UPDATE:
12787 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12788 start_internal_command(Id, plci, ec_command);
12789 return (false);
12791 case EC_RESET_COEFFICIENTS:
12792 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12793 start_internal_command(Id, plci, ec_command);
12794 return (false);
12796 default:
12797 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12798 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12799 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12804 else
12806 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12808 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12809 UnMapId(Id), (char *)(FILE_), __LINE__));
12810 Info = _WRONG_MESSAGE_FORMAT;
12812 else
12814 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12816 result[0] = 11;
12817 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12818 result[3] = 8;
12819 PUT_WORD(&result[4], GOOD);
12820 PUT_WORD(&result[6], 0x0007);
12821 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12822 PUT_WORD(&result[10], 0);
12824 else if (plci == NULL)
12826 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12827 UnMapId(Id), (char *)(FILE_), __LINE__));
12828 Info = _WRONG_IDENTIFIER;
12830 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12832 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12833 UnMapId(Id), (char *)(FILE_), __LINE__));
12834 Info = _WRONG_STATE;
12836 else
12838 plci->command = 0;
12839 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12840 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12841 result[0] = 5;
12842 PUT_WORD(&result[1], plci->ec_cmd);
12843 result[3] = 2;
12844 PUT_WORD(&result[4], GOOD);
12845 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12846 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12847 plci->ec_tail_length = 0;
12848 if (ec_parms[1].length >= 2)
12850 opt = GET_WORD(&ec_parms[1].info[1]);
12851 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12852 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12853 if (opt & EC_DETECT_DISABLE_TONE)
12854 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12855 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12856 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12857 if (ec_parms[1].length >= 4)
12859 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12862 switch (plci->ec_cmd)
12864 case EC_ENABLE_OPERATION:
12865 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12866 start_internal_command(Id, plci, ec_command);
12867 return (false);
12869 case EC_DISABLE_OPERATION:
12870 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12871 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12872 LEC_RESET_COEFFICIENTS;
12873 start_internal_command(Id, plci, ec_command);
12874 return (false);
12876 default:
12877 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12878 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12879 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12885 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12886 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12887 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12888 return (false);
12892 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12894 byte result[8];
12896 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12897 UnMapId(Id), (char *)(FILE_), __LINE__));
12899 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12901 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12903 result[0] = 2;
12904 PUT_WORD(&result[1], 0);
12905 switch (msg[1])
12907 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909 break;
12910 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912 break;
12913 case LEC_DISABLE_RELEASED:
12914 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12915 break;
12918 else
12920 result[0] = 5;
12921 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12922 result[3] = 2;
12923 PUT_WORD(&result[4], 0);
12924 switch (msg[1])
12926 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12927 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12928 break;
12929 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12930 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12931 break;
12932 case LEC_DISABLE_RELEASED:
12933 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12934 break;
12937 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12938 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12944 /*------------------------------------------------------------------*/
12945 /* Advanced voice */
12946 /*------------------------------------------------------------------*/
12948 static void adv_voice_write_coefs(PLCI *plci, word write_command)
12950 DIVA_CAPI_ADAPTER *a;
12951 word i;
12952 byte *p;
12954 word w, n, j, k;
12955 byte ch_map[MIXER_CHANNELS_BRI];
12957 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12959 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12960 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12961 (char *)(FILE_), __LINE__, write_command));
12963 a = plci->adapter;
12964 p = coef_buffer + 1;
12965 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12966 i = 0;
12967 while (i + sizeof(word) <= a->adv_voice_coef_length)
12969 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12970 p += 2;
12971 i += 2;
12973 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12975 PUT_WORD(p, 0x8000);
12976 p += 2;
12977 i += 2;
12980 if (!a->li_pri && (plci->li_bchannel_id == 0))
12982 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12984 plci->li_bchannel_id = 1;
12985 li_config_table[a->li_base].plci = plci;
12986 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12987 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12988 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12990 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12992 plci->li_bchannel_id = 2;
12993 li_config_table[a->li_base + 1].plci = plci;
12994 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12995 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12996 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12999 if (!a->li_pri && (plci->li_bchannel_id != 0)
13000 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13002 i = a->li_base + (plci->li_bchannel_id - 1);
13003 switch (write_command)
13005 case ADV_VOICE_WRITE_ACTIVATION:
13006 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13007 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13008 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13010 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13011 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13013 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13015 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13016 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13017 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13018 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13020 mixer_calculate_coefs(a);
13021 li_config_table[i].curchnl = li_config_table[i].channel;
13022 li_config_table[j].curchnl = li_config_table[j].channel;
13023 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13024 li_config_table[k].curchnl = li_config_table[k].channel;
13025 break;
13027 case ADV_VOICE_WRITE_DEACTIVATION:
13028 for (j = 0; j < li_total_channels; j++)
13030 li_config_table[i].flag_table[j] = 0;
13031 li_config_table[j].flag_table[i] = 0;
13033 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13034 for (j = 0; j < li_total_channels; j++)
13036 li_config_table[k].flag_table[j] = 0;
13037 li_config_table[j].flag_table[k] = 0;
13039 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13041 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13042 for (j = 0; j < li_total_channels; j++)
13044 li_config_table[k].flag_table[j] = 0;
13045 li_config_table[j].flag_table[k] = 0;
13048 mixer_calculate_coefs(a);
13049 break;
13051 if (plci->B1_facilities & B1_FACILITY_MIXER)
13053 w = 0;
13054 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13055 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13056 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13057 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13058 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13059 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13060 *(p++) = (byte) w;
13061 *(p++) = (byte)(w >> 8);
13062 for (j = 0; j < sizeof(ch_map); j += 2)
13064 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13065 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13067 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13069 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13070 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13071 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13073 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13074 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13075 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13077 else
13079 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13080 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13084 else
13086 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13087 *(p++) = a->adv_voice_coef_buffer[i];
13090 else
13093 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13094 *(p++) = a->adv_voice_coef_buffer[i];
13096 coef_buffer[0] = (p - coef_buffer) - 1;
13097 add_p(plci, FTY, coef_buffer);
13098 sig_req(plci, TEL_CTRL, 0);
13099 send_req(plci);
13103 static void adv_voice_clear_config(PLCI *plci)
13105 DIVA_CAPI_ADAPTER *a;
13107 word i, j;
13110 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13111 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13112 (char *)(FILE_), __LINE__));
13114 a = plci->adapter;
13115 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13117 a->adv_voice_coef_length = 0;
13119 if (!a->li_pri && (plci->li_bchannel_id != 0)
13120 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13122 i = a->li_base + (plci->li_bchannel_id - 1);
13123 li_config_table[i].curchnl = 0;
13124 li_config_table[i].channel = 0;
13125 li_config_table[i].chflags = 0;
13126 for (j = 0; j < li_total_channels; j++)
13128 li_config_table[i].flag_table[j] = 0;
13129 li_config_table[j].flag_table[i] = 0;
13130 li_config_table[i].coef_table[j] = 0;
13131 li_config_table[j].coef_table[i] = 0;
13133 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13134 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13135 li_config_table[i].curchnl = 0;
13136 li_config_table[i].channel = 0;
13137 li_config_table[i].chflags = 0;
13138 for (j = 0; j < li_total_channels; j++)
13140 li_config_table[i].flag_table[j] = 0;
13141 li_config_table[j].flag_table[i] = 0;
13142 li_config_table[i].coef_table[j] = 0;
13143 li_config_table[j].coef_table[i] = 0;
13145 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13147 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148 li_config_table[i].curchnl = 0;
13149 li_config_table[i].channel = 0;
13150 li_config_table[i].chflags = 0;
13151 for (j = 0; j < li_total_channels; j++)
13153 li_config_table[i].flag_table[j] = 0;
13154 li_config_table[j].flag_table[i] = 0;
13155 li_config_table[i].coef_table[j] = 0;
13156 li_config_table[j].coef_table[i] = 0;
13165 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13168 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13169 UnMapId(Id), (char *)(FILE_), __LINE__));
13174 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13177 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13178 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13180 return (GOOD);
13184 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13186 DIVA_CAPI_ADAPTER *a;
13187 word Info;
13189 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13190 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13192 Info = GOOD;
13193 a = plci->adapter;
13194 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13195 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13197 switch (plci->adjust_b_state)
13199 case ADJUST_B_RESTORE_VOICE_1:
13200 plci->internal_command = plci->adjust_b_command;
13201 if (plci->sig_req)
13203 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13204 break;
13206 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13207 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13208 break;
13209 case ADJUST_B_RESTORE_VOICE_2:
13210 if ((Rc != OK) && (Rc != OK_FC))
13212 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13213 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13214 Info = _WRONG_STATE;
13215 break;
13217 break;
13220 return (Info);
13226 /*------------------------------------------------------------------*/
13227 /* B1 resource switching */
13228 /*------------------------------------------------------------------*/
13230 static byte b1_facilities_table[] =
13232 0x00, /* 0 No bchannel resources */
13233 0x00, /* 1 Codec (automatic law) */
13234 0x00, /* 2 Codec (A-law) */
13235 0x00, /* 3 Codec (y-law) */
13236 0x00, /* 4 HDLC for X.21 */
13237 0x00, /* 5 HDLC */
13238 0x00, /* 6 External Device 0 */
13239 0x00, /* 7 External Device 1 */
13240 0x00, /* 8 HDLC 56k */
13241 0x00, /* 9 Transparent */
13242 0x00, /* 10 Loopback to network */
13243 0x00, /* 11 Test pattern to net */
13244 0x00, /* 12 Rate adaptation sync */
13245 0x00, /* 13 Rate adaptation async */
13246 0x00, /* 14 R-Interface */
13247 0x00, /* 15 HDLC 128k leased line */
13248 0x00, /* 16 FAX */
13249 0x00, /* 17 Modem async */
13250 0x00, /* 18 Modem sync HDLC */
13251 0x00, /* 19 V.110 async HDLC */
13252 0x12, /* 20 Adv voice (Trans,mixer) */
13253 0x00, /* 21 Codec connected to IC */
13254 0x0c, /* 22 Trans,DTMF */
13255 0x1e, /* 23 Trans,DTMF+mixer */
13256 0x1f, /* 24 Trans,DTMF+mixer+local */
13257 0x13, /* 25 Trans,mixer+local */
13258 0x12, /* 26 HDLC,mixer */
13259 0x12, /* 27 HDLC 56k,mixer */
13260 0x2c, /* 28 Trans,LEC+DTMF */
13261 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13262 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13263 0x2c, /* 31 RTP,LEC+DTMF */
13264 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13265 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13266 0x00, /* 34 Signaling task */
13267 0x00, /* 35 PIAFS */
13268 0x0c, /* 36 Trans,DTMF+TONE */
13269 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13270 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13274 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13276 word b1_facilities;
13278 b1_facilities = b1_facilities_table[b1_resource];
13279 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13282 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13283 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13286 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13287 b1_facilities |= B1_FACILITY_DTMFX;
13288 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13289 b1_facilities |= B1_FACILITY_DTMFR;
13292 if ((b1_resource == 17) || (b1_resource == 18))
13294 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13295 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13298 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13299 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13300 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13302 return (b1_facilities);
13306 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13308 byte b;
13310 switch (b1_resource)
13312 case 5:
13313 case 26:
13314 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13315 b = 26;
13316 else
13317 b = 5;
13318 break;
13320 case 8:
13321 case 27:
13322 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13323 b = 27;
13324 else
13325 b = 8;
13326 break;
13328 case 9:
13329 case 20:
13330 case 22:
13331 case 23:
13332 case 24:
13333 case 25:
13334 case 28:
13335 case 29:
13336 case 30:
13337 case 36:
13338 case 37:
13339 case 38:
13340 if (b1_facilities & B1_FACILITY_EC)
13342 if (b1_facilities & B1_FACILITY_LOCAL)
13343 b = 30;
13344 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13345 b = 29;
13346 else
13347 b = 28;
13350 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13351 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13352 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13354 if (b1_facilities & B1_FACILITY_LOCAL)
13355 b = 38;
13356 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13357 b = 37;
13358 else
13359 b = 36;
13362 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13363 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13364 || ((b1_facilities & B1_FACILITY_DTMFR)
13365 && ((b1_facilities & B1_FACILITY_MIXER)
13366 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13367 || ((b1_facilities & B1_FACILITY_DTMFX)
13368 && ((b1_facilities & B1_FACILITY_MIXER)
13369 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13371 if (b1_facilities & B1_FACILITY_LOCAL)
13372 b = 24;
13373 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13374 b = 23;
13375 else
13376 b = 22;
13378 else
13380 if (b1_facilities & B1_FACILITY_LOCAL)
13381 b = 25;
13382 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13383 b = 20;
13384 else
13385 b = 9;
13387 break;
13389 case 31:
13390 case 32:
13391 case 33:
13392 if (b1_facilities & B1_FACILITY_LOCAL)
13393 b = 33;
13394 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13395 b = 32;
13396 else
13397 b = 31;
13398 break;
13400 default:
13401 b = b1_resource;
13403 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13404 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13405 (char *)(FILE_), __LINE__,
13406 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13407 return (b);
13411 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13413 word removed_facilities;
13415 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13416 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13417 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13418 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13420 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13421 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13423 if (removed_facilities & B1_FACILITY_EC)
13424 ec_clear_config(plci);
13427 if (removed_facilities & B1_FACILITY_DTMFR)
13429 dtmf_rec_clear_config(plci);
13430 dtmf_parameter_clear_config(plci);
13432 if (removed_facilities & B1_FACILITY_DTMFX)
13433 dtmf_send_clear_config(plci);
13436 if (removed_facilities & B1_FACILITY_MIXER)
13437 mixer_clear_config(plci);
13439 if (removed_facilities & B1_FACILITY_VOICE)
13440 adv_voice_clear_config(plci);
13441 plci->B1_facilities = new_b1_facilities;
13445 static void adjust_b_clear(PLCI *plci)
13448 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13449 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13450 (char *)(FILE_), __LINE__));
13452 plci->adjust_b_restore = false;
13456 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13458 word Info;
13459 byte b1_resource;
13460 NCCI *ncci_ptr;
13461 API_PARSE bp[2];
13463 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13464 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13466 Info = GOOD;
13467 switch (plci->adjust_b_state)
13469 case ADJUST_B_START:
13470 if ((plci->adjust_b_parms_msg == NULL)
13471 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13472 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13473 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13475 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13476 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13477 if (b1_resource == plci->B1_resource)
13479 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13480 break;
13482 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13484 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13485 UnMapId(Id), (char *)(FILE_), __LINE__,
13486 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13487 Info = _WRONG_STATE;
13488 break;
13491 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13494 mixer_prepare_switch(Id, plci);
13497 dtmf_prepare_switch(Id, plci);
13498 dtmf_parameter_prepare_switch(Id, plci);
13501 ec_prepare_switch(Id, plci);
13503 adv_voice_prepare_switch(Id, plci);
13505 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13506 Rc = OK;
13507 /* fall through */
13508 case ADJUST_B_SAVE_MIXER_1:
13509 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13512 Info = mixer_save_config(Id, plci, Rc);
13513 if ((Info != GOOD) || plci->internal_command)
13514 break;
13517 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13518 Rc = OK;
13519 /* fall through */
13520 case ADJUST_B_SAVE_DTMF_1:
13521 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13524 Info = dtmf_save_config(Id, plci, Rc);
13525 if ((Info != GOOD) || plci->internal_command)
13526 break;
13529 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13530 /* fall through */
13531 case ADJUST_B_REMOVE_L23_1:
13532 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13533 && plci->NL.Id && !plci->nl_remove_id)
13535 plci->internal_command = plci->adjust_b_command;
13536 if (plci->adjust_b_ncci != 0)
13538 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13539 while (ncci_ptr->data_pending)
13541 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13542 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13544 while (ncci_ptr->data_ack_pending)
13545 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13547 nl_req_ncci(plci, REMOVE,
13548 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13549 send_req(plci);
13550 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13551 break;
13553 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13554 Rc = OK;
13555 /* fall through */
13556 case ADJUST_B_REMOVE_L23_2:
13557 if ((Rc != OK) && (Rc != OK_FC))
13559 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13560 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13561 Info = _WRONG_STATE;
13562 break;
13564 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13566 if (plci_nl_busy(plci))
13568 plci->internal_command = plci->adjust_b_command;
13569 break;
13572 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13573 Rc = OK;
13574 /* fall through */
13575 case ADJUST_B_SAVE_EC_1:
13576 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13579 Info = ec_save_config(Id, plci, Rc);
13580 if ((Info != GOOD) || plci->internal_command)
13581 break;
13584 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13585 Rc = OK;
13586 /* fall through */
13587 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13588 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13591 Info = dtmf_parameter_save_config(Id, plci, Rc);
13592 if ((Info != GOOD) || plci->internal_command)
13593 break;
13596 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13597 Rc = OK;
13598 /* fall through */
13599 case ADJUST_B_SAVE_VOICE_1:
13600 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13602 Info = adv_voice_save_config(Id, plci, Rc);
13603 if ((Info != GOOD) || plci->internal_command)
13604 break;
13606 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13607 /* fall through */
13608 case ADJUST_B_SWITCH_L1_1:
13609 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13611 if (plci->sig_req)
13613 plci->internal_command = plci->adjust_b_command;
13614 break;
13616 if (plci->adjust_b_parms_msg != NULL)
13617 api_load_msg(plci->adjust_b_parms_msg, bp);
13618 else
13619 api_load_msg(&plci->B_protocol, bp);
13620 Info = add_b1(plci, bp,
13621 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13622 plci->adjust_b_facilities);
13623 if (Info != GOOD)
13625 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13626 UnMapId(Id), (char *)(FILE_), __LINE__,
13627 plci->B1_resource, plci->adjust_b_facilities));
13628 break;
13630 plci->internal_command = plci->adjust_b_command;
13631 sig_req(plci, RESOURCES, 0);
13632 send_req(plci);
13633 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13634 break;
13636 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13637 Rc = OK;
13638 /* fall through */
13639 case ADJUST_B_SWITCH_L1_2:
13640 if ((Rc != OK) && (Rc != OK_FC))
13642 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13643 UnMapId(Id), (char *)(FILE_), __LINE__,
13644 Rc, plci->B1_resource, plci->adjust_b_facilities));
13645 Info = _WRONG_STATE;
13646 break;
13648 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13649 Rc = OK;
13650 /* fall through */
13651 case ADJUST_B_RESTORE_VOICE_1:
13652 case ADJUST_B_RESTORE_VOICE_2:
13653 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13655 Info = adv_voice_restore_config(Id, plci, Rc);
13656 if ((Info != GOOD) || plci->internal_command)
13657 break;
13659 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13660 Rc = OK;
13661 /* fall through */
13662 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13663 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13664 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13667 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13668 if ((Info != GOOD) || plci->internal_command)
13669 break;
13672 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13673 Rc = OK;
13674 /* fall through */
13675 case ADJUST_B_RESTORE_EC_1:
13676 case ADJUST_B_RESTORE_EC_2:
13677 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13680 Info = ec_restore_config(Id, plci, Rc);
13681 if ((Info != GOOD) || plci->internal_command)
13682 break;
13685 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13686 /* fall through */
13687 case ADJUST_B_ASSIGN_L23_1:
13688 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13690 if (plci_nl_busy(plci))
13692 plci->internal_command = plci->adjust_b_command;
13693 break;
13695 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13696 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13697 if (plci->adjust_b_parms_msg != NULL)
13698 api_load_msg(plci->adjust_b_parms_msg, bp);
13699 else
13700 api_load_msg(&plci->B_protocol, bp);
13701 Info = add_b23(plci, bp);
13702 if (Info != GOOD)
13704 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13705 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13706 break;
13708 plci->internal_command = plci->adjust_b_command;
13709 nl_req_ncci(plci, ASSIGN, 0);
13710 send_req(plci);
13711 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13712 break;
13714 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13715 Rc = ASSIGN_OK;
13716 /* fall through */
13717 case ADJUST_B_ASSIGN_L23_2:
13718 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13720 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13721 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13722 Info = _WRONG_STATE;
13723 break;
13725 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13727 if (Rc != ASSIGN_OK)
13729 plci->internal_command = plci->adjust_b_command;
13730 break;
13733 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13735 plci->adjust_b_restore = true;
13736 break;
13738 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13739 /* fall through */
13740 case ADJUST_B_CONNECT_1:
13741 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13743 plci->internal_command = plci->adjust_b_command;
13744 if (plci_nl_busy(plci))
13745 break;
13746 nl_req_ncci(plci, N_CONNECT, 0);
13747 send_req(plci);
13748 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13749 break;
13751 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13752 Rc = OK;
13753 /* fall through */
13754 case ADJUST_B_CONNECT_2:
13755 case ADJUST_B_CONNECT_3:
13756 case ADJUST_B_CONNECT_4:
13757 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13759 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13760 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13761 Info = _WRONG_STATE;
13762 break;
13764 if (Rc == OK)
13766 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13768 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13769 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13771 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13772 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13773 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13774 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13776 else if (Rc == 0)
13778 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13779 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13780 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13781 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13783 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13785 plci->internal_command = plci->adjust_b_command;
13786 break;
13788 Rc = OK;
13789 /* fall through */
13790 case ADJUST_B_RESTORE_DTMF_1:
13791 case ADJUST_B_RESTORE_DTMF_2:
13792 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13795 Info = dtmf_restore_config(Id, plci, Rc);
13796 if ((Info != GOOD) || plci->internal_command)
13797 break;
13800 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13801 Rc = OK;
13802 /* fall through */
13803 case ADJUST_B_RESTORE_MIXER_1:
13804 case ADJUST_B_RESTORE_MIXER_2:
13805 case ADJUST_B_RESTORE_MIXER_3:
13806 case ADJUST_B_RESTORE_MIXER_4:
13807 case ADJUST_B_RESTORE_MIXER_5:
13808 case ADJUST_B_RESTORE_MIXER_6:
13809 case ADJUST_B_RESTORE_MIXER_7:
13810 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13813 Info = mixer_restore_config(Id, plci, Rc);
13814 if ((Info != GOOD) || plci->internal_command)
13815 break;
13818 plci->adjust_b_state = ADJUST_B_END;
13819 case ADJUST_B_END:
13820 break;
13822 return (Info);
13826 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13829 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13830 UnMapId(Id), (char *)(FILE_), __LINE__,
13831 plci->B1_resource, b1_facilities));
13833 plci->adjust_b_parms_msg = bp_msg;
13834 plci->adjust_b_facilities = b1_facilities;
13835 plci->adjust_b_command = internal_command;
13836 plci->adjust_b_ncci = (word)(Id >> 16);
13837 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13838 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13839 else
13840 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13841 plci->adjust_b_state = ADJUST_B_START;
13842 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13843 UnMapId(Id), (char *)(FILE_), __LINE__,
13844 plci->B1_resource, b1_facilities));
13848 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13850 word internal_command;
13852 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13853 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13855 internal_command = plci->internal_command;
13856 plci->internal_command = 0;
13857 switch (internal_command)
13859 default:
13860 plci->command = 0;
13861 if (plci->req_in != 0)
13863 plci->internal_command = ADJUST_B_RESTORE_1;
13864 break;
13866 Rc = OK;
13867 /* fall through */
13868 case ADJUST_B_RESTORE_1:
13869 if ((Rc != OK) && (Rc != OK_FC))
13871 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13872 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13874 plci->adjust_b_parms_msg = NULL;
13875 plci->adjust_b_facilities = plci->B1_facilities;
13876 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13877 plci->adjust_b_ncci = (word)(Id >> 16);
13878 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13879 plci->adjust_b_state = ADJUST_B_START;
13880 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13881 UnMapId(Id), (char *)(FILE_), __LINE__));
13882 /* fall through */
13883 case ADJUST_B_RESTORE_2:
13884 if (adjust_b_process(Id, plci, Rc) != GOOD)
13886 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13887 UnMapId(Id), (char *)(FILE_), __LINE__));
13889 if (plci->internal_command)
13890 break;
13891 break;
13896 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13898 word Info;
13899 word internal_command;
13901 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13902 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13904 Info = GOOD;
13905 internal_command = plci->internal_command;
13906 plci->internal_command = 0;
13907 switch (internal_command)
13909 default:
13910 plci->command = 0;
13911 plci->adjust_b_parms_msg = NULL;
13912 plci->adjust_b_facilities = plci->B1_facilities;
13913 plci->adjust_b_command = RESET_B3_COMMAND_1;
13914 plci->adjust_b_ncci = (word)(Id >> 16);
13915 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13916 plci->adjust_b_state = ADJUST_B_START;
13917 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13918 UnMapId(Id), (char *)(FILE_), __LINE__));
13919 /* fall through */
13920 case RESET_B3_COMMAND_1:
13921 Info = adjust_b_process(Id, plci, Rc);
13922 if (Info != GOOD)
13924 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13925 UnMapId(Id), (char *)(FILE_), __LINE__));
13926 break;
13928 if (plci->internal_command)
13929 return;
13930 break;
13932 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13933 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13937 static void select_b_command(dword Id, PLCI *plci, byte Rc)
13939 word Info;
13940 word internal_command;
13941 byte esc_chi[3];
13943 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13944 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13946 Info = GOOD;
13947 internal_command = plci->internal_command;
13948 plci->internal_command = 0;
13949 switch (internal_command)
13951 default:
13952 plci->command = 0;
13953 plci->adjust_b_parms_msg = &plci->saved_msg;
13954 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13955 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13956 else
13957 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13958 plci->adjust_b_command = SELECT_B_COMMAND_1;
13959 plci->adjust_b_ncci = (word)(Id >> 16);
13960 if (plci->saved_msg.parms[0].length == 0)
13962 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13963 ADJUST_B_MODE_NO_RESOURCE;
13965 else
13967 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13968 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13970 plci->adjust_b_state = ADJUST_B_START;
13971 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13972 UnMapId(Id), (char *)(FILE_), __LINE__));
13973 /* fall through */
13974 case SELECT_B_COMMAND_1:
13975 Info = adjust_b_process(Id, plci, Rc);
13976 if (Info != GOOD)
13978 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13979 UnMapId(Id), (char *)(FILE_), __LINE__));
13980 break;
13982 if (plci->internal_command)
13983 return;
13984 if (plci->tel == ADV_VOICE)
13986 esc_chi[0] = 0x02;
13987 esc_chi[1] = 0x18;
13988 esc_chi[2] = plci->b_channel;
13989 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13991 break;
13993 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13997 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13999 word internal_command;
14001 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14002 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14004 internal_command = plci->internal_command;
14005 plci->internal_command = 0;
14006 switch (internal_command)
14008 default:
14009 plci->command = 0; /* fall through */
14010 case FAX_CONNECT_ACK_COMMAND_1:
14011 if (plci_nl_busy(plci))
14013 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14014 return;
14016 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14017 plci->NData[0].P = plci->fax_connect_info_buffer;
14018 plci->NData[0].PLength = plci->fax_connect_info_length;
14019 plci->NL.X = plci->NData;
14020 plci->NL.ReqCh = 0;
14021 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14022 plci->adapter->request(&plci->NL);
14023 return;
14024 case FAX_CONNECT_ACK_COMMAND_2:
14025 if ((Rc != OK) && (Rc != OK_FC))
14027 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14028 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14029 break;
14032 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14033 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14035 if (plci->B3_prot == 4)
14036 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14037 else
14038 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14039 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14044 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14046 word internal_command;
14048 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14049 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14051 internal_command = plci->internal_command;
14052 plci->internal_command = 0;
14053 switch (internal_command)
14055 default:
14056 plci->command = 0;
14057 /* fall through */
14058 case FAX_EDATA_ACK_COMMAND_1:
14059 if (plci_nl_busy(plci))
14061 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14062 return;
14064 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14065 plci->NData[0].P = plci->fax_connect_info_buffer;
14066 plci->NData[0].PLength = plci->fax_edata_ack_length;
14067 plci->NL.X = plci->NData;
14068 plci->NL.ReqCh = 0;
14069 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14070 plci->adapter->request(&plci->NL);
14071 return;
14072 case FAX_EDATA_ACK_COMMAND_2:
14073 if ((Rc != OK) && (Rc != OK_FC))
14075 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14076 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14077 break;
14083 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14085 word Info;
14086 word internal_command;
14088 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14089 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14091 Info = GOOD;
14092 internal_command = plci->internal_command;
14093 plci->internal_command = 0;
14094 switch (internal_command)
14096 default:
14097 plci->command = 0; /* fall through */
14098 case FAX_CONNECT_INFO_COMMAND_1:
14099 if (plci_nl_busy(plci))
14101 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14102 return;
14104 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14105 plci->NData[0].P = plci->fax_connect_info_buffer;
14106 plci->NData[0].PLength = plci->fax_connect_info_length;
14107 plci->NL.X = plci->NData;
14108 plci->NL.ReqCh = 0;
14109 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14110 plci->adapter->request(&plci->NL);
14111 return;
14112 case FAX_CONNECT_INFO_COMMAND_2:
14113 if ((Rc != OK) && (Rc != OK_FC))
14115 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14116 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14117 Info = _WRONG_STATE;
14118 break;
14120 if (plci_nl_busy(plci))
14122 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14123 return;
14125 plci->command = _CONNECT_B3_R;
14126 nl_req_ncci(plci, N_CONNECT, 0);
14127 send_req(plci);
14128 return;
14130 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14134 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14136 word Info;
14137 word internal_command;
14139 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14140 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14142 Info = GOOD;
14143 internal_command = plci->internal_command;
14144 plci->internal_command = 0;
14145 switch (internal_command)
14147 default:
14148 plci->command = 0;
14149 plci->adjust_b_parms_msg = NULL;
14150 plci->adjust_b_facilities = plci->B1_facilities;
14151 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14152 plci->adjust_b_ncci = (word)(Id >> 16);
14153 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14154 plci->adjust_b_state = ADJUST_B_START;
14155 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14156 UnMapId(Id), (char *)(FILE_), __LINE__));
14157 /* fall through */
14158 case FAX_ADJUST_B23_COMMAND_1:
14159 Info = adjust_b_process(Id, plci, Rc);
14160 if (Info != GOOD)
14162 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14163 UnMapId(Id), (char *)(FILE_), __LINE__));
14164 break;
14166 if (plci->internal_command)
14167 return;
14168 /* fall through */
14169 case FAX_ADJUST_B23_COMMAND_2:
14170 if (plci_nl_busy(plci))
14172 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14173 return;
14175 plci->command = _CONNECT_B3_R;
14176 nl_req_ncci(plci, N_CONNECT, 0);
14177 send_req(plci);
14178 return;
14180 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14184 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14186 word internal_command;
14188 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14189 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14191 internal_command = plci->internal_command;
14192 plci->internal_command = 0;
14193 switch (internal_command)
14195 default:
14196 plci->command = 0;
14197 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14198 return;
14199 case FAX_DISCONNECT_COMMAND_1:
14200 case FAX_DISCONNECT_COMMAND_2:
14201 case FAX_DISCONNECT_COMMAND_3:
14202 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14204 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14205 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14206 break;
14208 if (Rc == OK)
14210 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14211 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14213 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14216 else if (Rc == 0)
14218 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14219 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14221 return;
14227 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14229 word Info;
14230 word internal_command;
14232 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14233 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14235 Info = GOOD;
14236 internal_command = plci->internal_command;
14237 plci->internal_command = 0;
14238 switch (internal_command)
14240 default:
14241 plci->command = 0; /* fall through */
14242 case RTP_CONNECT_B3_REQ_COMMAND_1:
14243 if (plci_nl_busy(plci))
14245 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14246 return;
14248 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14249 nl_req_ncci(plci, N_CONNECT, 0);
14250 send_req(plci);
14251 return;
14252 case RTP_CONNECT_B3_REQ_COMMAND_2:
14253 if ((Rc != OK) && (Rc != OK_FC))
14255 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14256 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14257 Info = _WRONG_STATE;
14258 break;
14260 if (plci_nl_busy(plci))
14262 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14263 return;
14265 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14266 plci->NData[0].PLength = plci->internal_req_buffer[0];
14267 plci->NData[0].P = plci->internal_req_buffer + 1;
14268 plci->NL.X = plci->NData;
14269 plci->NL.ReqCh = 0;
14270 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14271 plci->adapter->request(&plci->NL);
14272 break;
14273 case RTP_CONNECT_B3_REQ_COMMAND_3:
14274 return;
14276 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14280 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14282 word internal_command;
14284 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14285 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14287 internal_command = plci->internal_command;
14288 plci->internal_command = 0;
14289 switch (internal_command)
14291 default:
14292 plci->command = 0; /* fall through */
14293 case RTP_CONNECT_B3_RES_COMMAND_1:
14294 if (plci_nl_busy(plci))
14296 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14297 return;
14299 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14300 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14301 send_req(plci);
14302 return;
14303 case RTP_CONNECT_B3_RES_COMMAND_2:
14304 if ((Rc != OK) && (Rc != OK_FC))
14306 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14307 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14308 break;
14310 if (plci_nl_busy(plci))
14312 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14313 return;
14315 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14316 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14317 plci->NData[0].PLength = plci->internal_req_buffer[0];
14318 plci->NData[0].P = plci->internal_req_buffer + 1;
14319 plci->NL.X = plci->NData;
14320 plci->NL.ReqCh = 0;
14321 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14322 plci->adapter->request(&plci->NL);
14323 return;
14324 case RTP_CONNECT_B3_RES_COMMAND_3:
14325 return;
14331 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14333 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14334 word Info;
14335 word internal_command;
14337 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14338 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14340 Info = GOOD;
14341 internal_command = plci->internal_command;
14342 plci->internal_command = 0;
14343 switch (internal_command)
14345 default:
14346 if (!plci->NL.Id)
14347 break;
14348 plci->command = 0;
14349 plci->adjust_b_parms_msg = NULL;
14350 plci->adjust_b_facilities = plci->B1_facilities;
14351 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14352 plci->adjust_b_ncci = (word)(Id >> 16);
14353 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14354 plci->adjust_b_state = ADJUST_B_START;
14355 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14356 UnMapId(Id), (char *)(FILE_), __LINE__));
14357 /* fall through */
14358 case HOLD_SAVE_COMMAND_1:
14359 Info = adjust_b_process(Id, plci, Rc);
14360 if (Info != GOOD)
14362 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14363 UnMapId(Id), (char *)(FILE_), __LINE__));
14364 break;
14366 if (plci->internal_command)
14367 return;
14369 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14373 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14375 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14376 word Info;
14377 word internal_command;
14379 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14380 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14382 Info = GOOD;
14383 internal_command = plci->internal_command;
14384 plci->internal_command = 0;
14385 switch (internal_command)
14387 default:
14388 plci->command = 0;
14389 plci->adjust_b_parms_msg = NULL;
14390 plci->adjust_b_facilities = plci->B1_facilities;
14391 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14392 plci->adjust_b_ncci = (word)(Id >> 16);
14393 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14394 plci->adjust_b_state = ADJUST_B_START;
14395 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14396 UnMapId(Id), (char *)(FILE_), __LINE__));
14397 /* fall through */
14398 case RETRIEVE_RESTORE_COMMAND_1:
14399 Info = adjust_b_process(Id, plci, Rc);
14400 if (Info != GOOD)
14402 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14403 UnMapId(Id), (char *)(FILE_), __LINE__));
14404 break;
14406 if (plci->internal_command)
14407 return;
14409 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14413 static void init_b1_config(PLCI *plci)
14416 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14417 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14418 (char *)(FILE_), __LINE__));
14420 plci->B1_resource = 0;
14421 plci->B1_facilities = 0;
14423 plci->li_bchannel_id = 0;
14424 mixer_clear_config(plci);
14427 ec_clear_config(plci);
14430 dtmf_rec_clear_config(plci);
14431 dtmf_send_clear_config(plci);
14432 dtmf_parameter_clear_config(plci);
14434 adv_voice_clear_config(plci);
14435 adjust_b_clear(plci);
14439 static void clear_b1_config(PLCI *plci)
14442 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14443 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14444 (char *)(FILE_), __LINE__));
14446 adv_voice_clear_config(plci);
14447 adjust_b_clear(plci);
14449 ec_clear_config(plci);
14452 dtmf_rec_clear_config(plci);
14453 dtmf_send_clear_config(plci);
14454 dtmf_parameter_clear_config(plci);
14457 if ((plci->li_bchannel_id != 0)
14458 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14460 mixer_clear_config(plci);
14461 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14462 plci->li_bchannel_id = 0;
14465 plci->B1_resource = 0;
14466 plci->B1_facilities = 0;
14470 /* -----------------------------------------------------------------
14471 XON protocol local helpers
14472 ----------------------------------------------------------------- */
14473 static void channel_flow_control_remove(PLCI *plci) {
14474 DIVA_CAPI_ADAPTER *a = plci->adapter;
14475 word i;
14476 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14477 if (a->ch_flow_plci[i] == plci->Id) {
14478 a->ch_flow_plci[i] = 0;
14479 a->ch_flow_control[i] = 0;
14484 static void channel_x_on(PLCI *plci, byte ch) {
14485 DIVA_CAPI_ADAPTER *a = plci->adapter;
14486 if (a->ch_flow_control[ch] & N_XON_SENT) {
14487 a->ch_flow_control[ch] &= ~N_XON_SENT;
14491 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14492 DIVA_CAPI_ADAPTER *a = plci->adapter;
14493 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14494 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14495 a->ch_flow_plci[ch] = plci->Id;
14496 a->ch_flow_control_pending++;
14500 static void channel_request_xon(PLCI *plci, byte ch) {
14501 DIVA_CAPI_ADAPTER *a = plci->adapter;
14503 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14504 a->ch_flow_control[ch] |= N_XON_REQ;
14505 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14506 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14510 static void channel_xmit_extended_xon(PLCI *plci) {
14511 DIVA_CAPI_ADAPTER *a;
14512 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14513 int i, one_requested = 0;
14515 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14516 return;
14519 for (i = 0; i < max_ch; i++) {
14520 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14521 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14522 (plci->Id == a->ch_flow_plci[i])) {
14523 channel_request_xon(plci, (byte)i);
14524 one_requested = 1;
14528 if (one_requested) {
14529 channel_xmit_xon(plci);
14534 Try to xmit next X_ON
14536 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14537 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14538 int i;
14540 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14541 return (0);
14544 if (a->last_flow_control_ch >= max_ch) {
14545 a->last_flow_control_ch = 1;
14547 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14548 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14549 (plci->Id == a->ch_flow_plci[i])) {
14550 a->last_flow_control_ch = i + 1;
14551 return (i);
14555 for (i = 1; i < a->last_flow_control_ch; i++) {
14556 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14557 (plci->Id == a->ch_flow_plci[i])) {
14558 a->last_flow_control_ch = i + 1;
14559 return (i);
14563 return (0);
14566 static void channel_xmit_xon(PLCI *plci) {
14567 DIVA_CAPI_ADAPTER *a = plci->adapter;
14568 byte ch;
14570 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14571 return;
14573 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14574 return;
14576 a->ch_flow_control[ch] &= ~N_XON_REQ;
14577 a->ch_flow_control[ch] |= N_XON_SENT;
14579 plci->NL.Req = plci->nl_req = (byte)N_XON;
14580 plci->NL.ReqCh = ch;
14581 plci->NL.X = plci->NData;
14582 plci->NL.XNum = 1;
14583 plci->NData[0].P = &plci->RBuffer[0];
14584 plci->NData[0].PLength = 0;
14586 plci->adapter->request(&plci->NL);
14589 static int channel_can_xon(PLCI *plci, byte ch) {
14590 APPL *APPLptr;
14591 DIVA_CAPI_ADAPTER *a;
14592 word NCCIcode;
14593 dword count;
14594 word Num;
14595 word i;
14597 APPLptr = plci->appl;
14598 a = plci->adapter;
14600 if (!APPLptr)
14601 return (0);
14603 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14605 /* count all buffers within the Application pool */
14606 /* belonging to the same NCCI. XON if a first is */
14607 /* used. */
14608 count = 0;
14609 Num = 0xffff;
14610 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14611 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14612 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14614 if ((count > 2) || (Num == 0xffff)) {
14615 return (0);
14617 return (1);
14621 /*------------------------------------------------------------------*/
14623 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14625 return 1;
14630 /**********************************************************************************/
14631 /* function groups the listening applications according to the CIP mask and the */
14632 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14633 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14634 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14635 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14636 /* OS specific part (per adapter). */
14637 /**********************************************************************************/
14638 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14640 word i, j, k, busy, group_found;
14641 dword info_mask_group[MAX_CIP_TYPES];
14642 dword cip_mask_group[MAX_CIP_TYPES];
14643 word appl_number_group_type[MAX_APPL];
14644 PLCI *auxplci;
14646 /* all APPLs within this inc. call are allowed to dial in */
14647 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14649 if (!a->group_optimization_enabled)
14651 dbug(1, dprintf("No group optimization"));
14652 return;
14655 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14657 for (i = 0; i < MAX_CIP_TYPES; i++)
14659 info_mask_group[i] = 0;
14660 cip_mask_group[i] = 0;
14662 for (i = 0; i < MAX_APPL; i++)
14664 appl_number_group_type[i] = 0;
14666 for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14667 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14668 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14670 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14671 return; /* allow good application unfiltered access */
14674 for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14676 if (application[i].Id && a->CIP_Mask[i])
14678 for (k = 0, busy = false; k < a->max_plci; k++)
14680 if (a->plci[k].Id)
14682 auxplci = &a->plci[k];
14683 if (auxplci->appl == &application[i]) {
14684 /* application has a busy PLCI */
14685 busy = true;
14686 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14687 } else if (test_bit(i, plci->c_ind_mask_table)) {
14688 /* application has an incoming call pending */
14689 busy = true;
14690 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14695 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14697 if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14698 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14699 appl_number_group_type[i] = MAX_CIP_TYPES;
14700 group_found = true;
14701 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14703 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14704 { /* is group already present ? */
14705 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14706 group_found = true;
14707 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]));
14709 else if (!info_mask_group[j])
14710 { /* establish a new group */
14711 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14712 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14713 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14714 group_found = true;
14715 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]));
14721 for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14723 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14725 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14727 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14729 else
14731 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14732 for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14734 if (appl_number_group_type[i] == appl_number_group_type[j])
14736 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14737 /* disable call on other group members */
14738 __clear_bit(j, plci->group_optimization_mask_table);
14739 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14744 else /* application should not get a call */
14746 __clear_bit(i, plci->group_optimization_mask_table);
14754 /* OS notifies the driver about a application Capi_Register */
14755 word CapiRegister(word id)
14757 word i, j, appls_found;
14759 PLCI *plci;
14760 DIVA_CAPI_ADAPTER *a;
14762 for (i = 0, appls_found = 0; i < max_appl; i++)
14764 if (application[i].Id && (application[i].Id != id))
14766 appls_found++; /* an application has been found */
14770 if (appls_found) return true;
14771 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14773 a = &adapter[i];
14774 if (a->request)
14776 if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14778 if (!appls_found) /* first application does a capi register */
14780 if ((j = get_plci(a))) /* activate L1 of all adapters */
14782 plci = &a->plci[j - 1];
14783 plci->command = 0;
14784 add_p(plci, OAD, "\x01\xfd");
14785 add_p(plci, CAI, "\x01\x80");
14786 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14787 add_p(plci, SHIFT | 6, NULL);
14788 add_p(plci, SIN, "\x02\x00\x00");
14789 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14790 sig_req(plci, ASSIGN, DSIG_ID);
14791 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14792 sig_req(plci, SIG_CTRL, 0);
14793 send_req(plci);
14799 return false;
14802 /*------------------------------------------------------------------*/
14804 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14806 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14808 word i;
14809 /* Format of vswitch_t:
14810 0 byte length
14811 1 byte VSWITCHIE
14812 2 byte VSWITCH_REQ/VSWITCH_IND
14813 3 byte reserved
14814 4 word VSwitchcommand
14815 6 word returnerror
14816 8... Params
14818 if (!plci ||
14819 !plci->appl ||
14820 !plci->State ||
14821 plci->Sig.Ind == NCR_FACILITY
14823 return;
14825 for (i = 0; i < MAX_MULTI_IE; i++)
14827 if (!parms[i][0]) continue;
14828 if (parms[i][0] < 7)
14830 parms[i][0] = 0; /* kill it */
14831 continue;
14833 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14834 switch (parms[i][4])
14836 case VSJOIN:
14837 if (!plci->relatedPTYPLCI ||
14838 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14839 { /* Error */
14840 break;
14842 /* remember all necessary informations */
14843 if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14845 break;
14847 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14848 { /* first indication after ECT-Request on Consultation Call */
14849 plci->vswitchstate = parms[i][9];
14850 parms[i][9] = 2; /* State */
14851 /* now ask first Call to join */
14853 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14854 { /* Answer of VSWITCH_REQ from first Call */
14855 plci->vswitchstate = parms[i][9];
14856 /* tell consultation call to join
14857 and the protocol capabilities of the first call */
14859 else
14860 { /* Error */
14861 break;
14863 plci->vsprot = parms[i][10]; /* protocol */
14864 plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14865 /* send join request to related PLCI */
14866 parms[i][1] = VSWITCHIE;
14867 parms[i][2] = VSWITCH_REQ;
14869 plci->relatedPTYPLCI->command = 0;
14870 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14871 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14872 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14873 send_req(plci->relatedPTYPLCI);
14874 break;
14875 case VSTRANSPORT:
14876 default:
14877 if (plci->relatedPTYPLCI &&
14878 plci->vswitchstate == 3 &&
14879 plci->relatedPTYPLCI->vswitchstate == 3)
14881 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14882 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14883 send_req(plci->relatedPTYPLCI);
14885 break;
14887 parms[i][0] = 0; /* kill it */
14892 /*------------------------------------------------------------------*/
14894 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14895 ENTITY e;
14896 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14898 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14899 return (-1);
14902 pReq->xdi_dma_descriptor_operation.Req = 0;
14903 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14905 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14906 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14907 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14908 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14910 e.user[0] = plci->adapter->Id - 1;
14911 plci->adapter->request((ENTITY *)pReq);
14913 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14914 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14915 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14916 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14917 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14918 plci->adapter->Id,
14919 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14920 *dma_magic));
14921 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14922 } else {
14923 dbug(1, dprintf("dma_alloc failed"));
14924 return (-1);
14928 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14929 ENTITY e;
14930 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14932 if (nr < 0) {
14933 return;
14936 pReq->xdi_dma_descriptor_operation.Req = 0;
14937 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14939 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14940 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
14941 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14942 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14944 e.user[0] = plci->adapter->Id - 1;
14945 plci->adapter->request((ENTITY *)pReq);
14947 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14948 dbug(1, dprintf("dma_free(%d)", nr));
14949 } else {
14950 dbug(1, dprintf("dma_free failed (%d)", nr));
14954 /*------------------------------------------------------------------*/