]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/isdn/hardware/eicon/message.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[mirror_ubuntu-artful-kernel.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2 *
3 Copyright (c) Eicon Networks, 2002.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision : 2.1
9 *
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.
14 *
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.
19 *
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.
23 *
24 */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter */
55 /* Macrose defined here have only local meaning */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
63
64 /*
65 CAPI can request to process all return codes self only if:
66 protocol code supports this && xdi supports this
67 */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
75 static void set_group_ind_mask(PLCI *plci);
76 static void clear_group_ind_mask_bit(PLCI *plci, word b);
77 static byte test_group_ind_mask_bit(PLCI *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL *, CAPI_MSG *);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
92
93 void callback(ENTITY *);
94
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte **, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
101 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
102
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
104
105 static void nl_ind(PLCI *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI *plci, byte code, API_PARSE *p);
135 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
136 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, const word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
154
155 /*
156 XON protocol helpers
157 */
158 static void channel_flow_control_remove(PLCI *plci);
159 static void channel_x_off(PLCI *plci, byte ch, byte flag);
160 static void channel_x_on(PLCI *plci, byte ch);
161 static void channel_request_xon(PLCI *plci, byte ch);
162 static void channel_xmit_xon(PLCI *plci);
163 static int channel_can_xon(PLCI *plci, byte ch);
164 static void channel_xmit_extended_xon(PLCI *plci);
165
166 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs(PLCI *plci, word write_command);
172 static void adv_voice_clear_config(PLCI *plci);
173
174 static word get_b1_facilities(PLCI *plci, byte b1_resource);
175 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
181 static void select_b_command(dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config(PLCI *plci);
190 static void clear_b1_config(PLCI *plci);
191
192 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation(dword Id, PLCI *plci);
195 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write(PLCI *plci);
197
198
199 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
201 static void mixer_clear_config(PLCI *plci);
202 static void mixer_notify_update(PLCI *plci, byte others);
203 static void mixer_command(dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove(PLCI *plci);
209
210
211 static void ec_command(dword Id, PLCI *plci, byte Rc);
212 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
214
215
216 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
218
219
220 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor(PLCI *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController(byte);
228 extern byte UnMapController(byte);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
231
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void *TransmitBufferSet(APPL *appl, dword ref);
234 void *TransmitBufferGet(APPL *appl, void *p);
235 void TransmitBufferFree(APPL *appl, void *p);
236 void *ReceiveBufferGet(APPL *appl, int Num);
237
238 int fax_head_line_time(char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER *adapter;
247 extern APPL *application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260 word command;
261 byte *format;
262 byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263 } ftable[] = {
264 {_DATA_B3_R, "dwww", data_b3_req},
265 {_DATA_B3_I | RESPONSE, "w", data_b3_res},
266 {_INFO_R, "ss", info_req},
267 {_INFO_I | RESPONSE, "", info_res},
268 {_CONNECT_R, "wsssssssss", connect_req},
269 {_CONNECT_I | RESPONSE, "wsssss", connect_res},
270 {_CONNECT_ACTIVE_I | RESPONSE, "", connect_a_res},
271 {_DISCONNECT_R, "s", disconnect_req},
272 {_DISCONNECT_I | RESPONSE, "", disconnect_res},
273 {_LISTEN_R, "dddss", listen_req},
274 {_ALERT_R, "s", alert_req},
275 {_FACILITY_R, "ws", facility_req},
276 {_FACILITY_I | RESPONSE, "ws", facility_res},
277 {_CONNECT_B3_R, "s", connect_b3_req},
278 {_CONNECT_B3_I | RESPONSE, "ws", connect_b3_res},
279 {_CONNECT_B3_ACTIVE_I | RESPONSE, "", connect_b3_a_res},
280 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
281 {_DISCONNECT_B3_I | RESPONSE, "", disconnect_b3_res},
282 {_RESET_B3_R, "s", reset_b3_req},
283 {_RESET_B3_I | RESPONSE, "", reset_b3_res},
284 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws", connect_b3_t90_a_res},
285 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "", connect_b3_t90_a_res},
286 {_SELECT_B_REQ, "s", select_b_req},
287 {_MANUFACTURER_R, "dws", manufacturer_req},
288 {_MANUFACTURER_I | RESPONSE, "dws", manufacturer_res},
289 {_MANUFACTURER_I | RESPONSE, "", manufacturer_res}
290 };
291
292 static byte *cip_bc[29][2] = {
293 { "", "" }, /* 0 */
294 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
295 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
296 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
297 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
298 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
299 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
300 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
303 { "", "" }, /* 10 */
304 { "", "" }, /* 11 */
305 { "", "" }, /* 12 */
306 { "", "" }, /* 13 */
307 { "", "" }, /* 14 */
308 { "", "" }, /* 15 */
309
310 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
311 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
312 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
320 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
322 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
323 };
324
325 static byte *cip_hlc[29] = {
326 "", /* 0 */
327 "", /* 1 */
328 "", /* 2 */
329 "", /* 3 */
330 "", /* 4 */
331 "", /* 5 */
332 "", /* 6 */
333 "", /* 7 */
334 "", /* 8 */
335 "", /* 9 */
336 "", /* 10 */
337 "", /* 11 */
338 "", /* 12 */
339 "", /* 13 */
340 "", /* 14 */
341 "", /* 15 */
342
343 "\x02\x91\x81", /* 16 */
344 "\x02\x91\x84", /* 17 */
345 "\x02\x91\xa1", /* 18 */
346 "\x02\x91\xa4", /* 19 */
347 "\x02\x91\xa8", /* 20 */
348 "\x02\x91\xb1", /* 21 */
349 "\x02\x91\xb2", /* 22 */
350 "\x02\x91\xb5", /* 23 */
351 "\x02\x91\xb8", /* 24 */
352 "\x02\x91\xc1", /* 25 */
353 "\x02\x91\x81", /* 26 */
354 "\x03\x91\xe0\x01", /* 27 */
355 "\x03\x91\xe0\x02" /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT 0x80
362 #define V120_HEADER_BREAK_BIT 0x40
363 #define V120_HEADER_C1_BIT 0x04
364 #define V120_HEADER_C2_BIT 0x08
365 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL *appl, CAPI_MSG *msg)
387 {
388 word i, j, k, l, n;
389 word ret;
390 byte c;
391 byte controller;
392 DIVA_CAPI_ADAPTER *a;
393 PLCI *plci;
394 NCCI *ncci_ptr;
395 word ncci;
396 CAPI_MSG *m;
397 API_PARSE msg_parms[MAX_MSG_PARMS + 1];
398
399 if (msg->header.length < sizeof(msg->header) ||
400 msg->header.length > MAX_MSG_SIZE) {
401 dbug(1, dprintf("bad len"));
402 return _BAD_MSG;
403 }
404
405 controller = (byte)((msg->header.controller & 0x7f) - 1);
406
407 /* controller starts with 0 up to (max_adapter - 1) */
408 if (controller >= max_adapter)
409 {
410 dbug(1, dprintf("invalid ctrl"));
411 return _BAD_MSG;
412 }
413
414 a = &adapter[controller];
415 plci = NULL;
416 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417 {
418 dbug(1, dprintf("plci=%x", msg->header.plci));
419 plci = &a->plci[msg->header.plci - 1];
420 ncci = GET_WORD(&msg->header.ncci);
421 if (plci->Id
422 && (plci->appl
423 || (plci->State == INC_CON_PENDING)
424 || (plci->State == INC_CON_ALERT)
425 || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
426 && ((ncci == 0)
427 || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
428 || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
429 {
430 i = plci->msg_in_read_pos;
431 j = plci->msg_in_write_pos;
432 if (j >= i)
433 {
434 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435 i += MSG_IN_QUEUE_SIZE - j;
436 else
437 j = 0;
438 }
439 else
440 {
441
442 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444 if (i > MSG_IN_QUEUE_SIZE - n)
445 i = MSG_IN_QUEUE_SIZE - n + 1;
446 i -= j;
447 }
448
449 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451 {
452 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453 msg->header.length, plci->msg_in_write_pos,
454 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456 return _QUEUE_FULL;
457 }
458 c = false;
459 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461 {
462 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463 c = true;
464 }
465 if (msg->header.command == _DATA_B3_R)
466 {
467 if (msg->header.length < 20)
468 {
469 dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470 return _BAD_MSG;
471 }
472 ncci_ptr = &(a->ncci[ncci]);
473 n = ncci_ptr->data_pending;
474 l = ncci_ptr->data_ack_pending;
475 k = plci->msg_in_read_pos;
476 while (k != plci->msg_in_write_pos)
477 {
478 if (k == plci->msg_in_wrap_pos)
479 k = 0;
480 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482 {
483 n++;
484 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485 l++;
486 }
487
488 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489 MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491 }
492 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493 {
494 dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497 return _QUEUE_FULL;
498 }
499 if (plci->req_in || plci->internal_command)
500 {
501 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503 {
504 dbug(0, dprintf("Q-FULL3(requeue)"));
505
506 return _QUEUE_FULL;
507 }
508 c = true;
509 }
510 }
511 else
512 {
513 if (plci->req_in || plci->internal_command)
514 c = true;
515 else
516 {
517 plci->command = msg->header.command;
518 plci->number = msg->header.number;
519 }
520 }
521 if (c)
522 {
523 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524 msg->header.command, plci->req_in, plci->internal_command,
525 msg->header.length, plci->msg_in_write_pos,
526 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527 if (j == 0)
528 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530 for (i = 0; i < msg->header.length; i++)
531 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532 if (m->header.command == _DATA_B3_R)
533 {
534
535 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
536
537 }
538
539 j = (j + 3) & 0xfffc;
540
541 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543 return 0;
544 }
545 }
546 else
547 {
548 plci = NULL;
549 }
550 }
551 dbug(1, dprintf("com=%x", msg->header.command));
552
553 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
554 for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555
556 if (ftable[i].command == msg->header.command) {
557 /* break loop if the message is correct, otherwise continue scan */
558 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
559 if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
560 ret = 0;
561 break;
562 }
563 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
564 }
565 }
566 if (ret) {
567 dbug(1, dprintf("BAD_MSG"));
568 if (plci) plci->command = 0;
569 return ret;
570 }
571
572
573 c = ftable[i].function(GET_DWORD(&msg->header.controller),
574 msg->header.number,
575 a,
576 plci,
577 appl,
578 msg_parms);
579
580 channel_xmit_extended_xon(plci);
581
582 if (c == 1) send_req(plci);
583 if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584 if (plci && !plci->req_in) plci->command = 0;
585 return 0;
586 }
587
588
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages */
591 /*------------------------------------------------------------------*/
592
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595 word i;
596 word p;
597
598 for (i = 0, p = 0; format[i]; i++) {
599 if (parms)
600 {
601 parms[i].info = &msg[p];
602 }
603 switch (format[i]) {
604 case 'b':
605 p += 1;
606 break;
607 case 'w':
608 p += 2;
609 break;
610 case 'd':
611 p += 4;
612 break;
613 case 's':
614 if (msg[p] == 0xff) {
615 parms[i].info += 2;
616 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617 p += (parms[i].length + 3);
618 }
619 else {
620 parms[i].length = msg[p];
621 p += (parms[i].length + 1);
622 }
623 break;
624 }
625
626 if (p > length) return true;
627 }
628 if (parms) parms[i].info = NULL;
629 return false;
630 }
631
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634 word i, j, n = 0;
635 byte *p;
636
637 p = out->info;
638 for (i = 0; format[i] != '\0'; i++)
639 {
640 out->parms[i].info = p;
641 out->parms[i].length = in[i].length;
642 switch (format[i])
643 {
644 case 'b':
645 n = 1;
646 break;
647 case 'w':
648 n = 2;
649 break;
650 case 'd':
651 n = 4;
652 break;
653 case 's':
654 n = in[i].length + 1;
655 break;
656 }
657 for (j = 0; j < n; j++)
658 *(p++) = in[i].info[j];
659 }
660 out->parms[i].info = NULL;
661 out->parms[i].length = 0;
662 }
663
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666 word i;
667
668 i = 0;
669 do
670 {
671 out[i].info = in->parms[i].info;
672 out[i].length = in->parms[i].length;
673 } while (in->parms[i++].info);
674 }
675
676
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function */
679 /*------------------------------------------------------------------*/
680
681 word api_remove_start(void)
682 {
683 word i;
684 word j;
685
686 if (!remove_started) {
687 remove_started = true;
688 for (i = 0; i < max_adapter; i++) {
689 if (adapter[i].request) {
690 for (j = 0; j < adapter[i].max_plci; j++) {
691 if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692 }
693 }
694 }
695 return 1;
696 }
697 else {
698 for (i = 0; i < max_adapter; i++) {
699 if (adapter[i].request) {
700 for (j = 0; j < adapter[i].max_plci; j++) {
701 if (adapter[i].plci[j].Sig.Id) return 1;
702 }
703 }
704 }
705 }
706 api_remove_complete();
707 return 0;
708 }
709
710
711 /*------------------------------------------------------------------*/
712 /* internal command queue */
713 /*------------------------------------------------------------------*/
714
715 static void init_internal_command_queue(PLCI *plci)
716 {
717 word i;
718
719 dbug(1, dprintf("%s,%d: init_internal_command_queue",
720 (char *)(FILE_), __LINE__));
721
722 plci->internal_command = 0;
723 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724 plci->internal_command_queue[i] = NULL;
725 }
726
727
728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
729 {
730 word i;
731
732 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733 UnMapId(Id), (char *)(FILE_), __LINE__));
734
735 if (plci->internal_command == 0)
736 {
737 plci->internal_command_queue[0] = command_function;
738 (*command_function)(Id, plci, OK);
739 }
740 else
741 {
742 i = 1;
743 while (plci->internal_command_queue[i] != NULL)
744 i++;
745 plci->internal_command_queue[i] = command_function;
746 }
747 }
748
749
750 static void next_internal_command(dword Id, PLCI *plci)
751 {
752 word i;
753
754 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755 UnMapId(Id), (char *)(FILE_), __LINE__));
756
757 plci->internal_command = 0;
758 plci->internal_command_queue[0] = NULL;
759 while (plci->internal_command_queue[1] != NULL)
760 {
761 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762 plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765 if (plci->internal_command != 0)
766 return;
767 plci->internal_command_queue[0] = NULL;
768 }
769 }
770
771
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function */
774 /*------------------------------------------------------------------*/
775
776 static dword ncci_mapping_bug = 0;
777
778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
779 {
780 DIVA_CAPI_ADAPTER *a;
781 word ncci, i, j, k;
782
783 a = plci->adapter;
784 if (!ch || a->ch_ncci[ch])
785 {
786 ncci_mapping_bug++;
787 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789 ncci = ch;
790 }
791 else
792 {
793 if (force_ncci)
794 ncci = force_ncci;
795 else
796 {
797 if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
798 ncci = ch;
799 else
800 {
801 ncci = 1;
802 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
803 ncci++;
804 if (ncci == MAX_NCCI + 1)
805 {
806 ncci_mapping_bug++;
807 i = 1;
808 do
809 {
810 j = 1;
811 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
812 j++;
813 k = j;
814 if (j < MAX_NCCI + 1)
815 {
816 do
817 {
818 j++;
819 } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
820 }
821 } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822 if (i < MAX_NL_CHANNEL + 1)
823 {
824 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 ncci_mapping_bug, ch, force_ncci, i, k, j));
826 }
827 else
828 {
829 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830 ncci_mapping_bug, ch, force_ncci));
831 }
832 ncci = ch;
833 }
834 }
835 a->ncci_plci[ncci] = plci->Id;
836 a->ncci_state[ncci] = IDLE;
837 if (!plci->ncci_ring_list)
838 plci->ncci_ring_list = ncci;
839 else
840 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842 }
843 a->ncci_ch[ncci] = ch;
844 a->ch_ncci[ch] = (byte) ncci;
845 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846 ncci_mapping_bug, ch, force_ncci, ch, ncci));
847 }
848 return (ncci);
849 }
850
851
852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
853 {
854 DIVA_CAPI_ADAPTER *a;
855 APPL *appl;
856 word i, ncci_code;
857 dword Id;
858
859 a = plci->adapter;
860 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861 if (ncci)
862 {
863 if (a->ncci_plci[ncci] == plci->Id)
864 {
865 if (!plci->appl)
866 {
867 ncci_mapping_bug++;
868 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869 ncci_mapping_bug, Id));
870 }
871 else
872 {
873 appl = plci->appl;
874 ncci_code = ncci | (((word) a->Id) << 8);
875 for (i = 0; i < appl->MaxBuffer; i++)
876 {
877 if ((appl->DataNCCI[i] == ncci_code)
878 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879 {
880 appl->DataNCCI[i] = 0;
881 }
882 }
883 }
884 }
885 }
886 else
887 {
888 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
889 {
890 if (a->ncci_plci[ncci] == plci->Id)
891 {
892 if (!plci->appl)
893 {
894 ncci_mapping_bug++;
895 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896 ncci_mapping_bug, Id));
897 }
898 else
899 {
900 appl = plci->appl;
901 ncci_code = ncci | (((word) a->Id) << 8);
902 for (i = 0; i < appl->MaxBuffer; i++)
903 {
904 if ((appl->DataNCCI[i] == ncci_code)
905 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906 {
907 appl->DataNCCI[i] = 0;
908 }
909 }
910 }
911 }
912 }
913 }
914 }
915
916
917 static void cleanup_ncci_data(PLCI *plci, word ncci)
918 {
919 NCCI *ncci_ptr;
920
921 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922 {
923 ncci_ptr = &(plci->adapter->ncci[ncci]);
924 if (plci->appl)
925 {
926 while (ncci_ptr->data_pending != 0)
927 {
928 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929 TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930 (ncci_ptr->data_out)++;
931 if (ncci_ptr->data_out == MAX_DATA_B3)
932 ncci_ptr->data_out = 0;
933 (ncci_ptr->data_pending)--;
934 }
935 }
936 ncci_ptr->data_out = 0;
937 ncci_ptr->data_pending = 0;
938 ncci_ptr->data_ack_out = 0;
939 ncci_ptr->data_ack_pending = 0;
940 }
941 }
942
943
944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
945 {
946 DIVA_CAPI_ADAPTER *a;
947 dword Id;
948 word i;
949
950 a = plci->adapter;
951 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952 if (!preserve_ncci)
953 ncci_free_receive_buffers(plci, ncci);
954 if (ncci)
955 {
956 if (a->ncci_plci[ncci] != plci->Id)
957 {
958 ncci_mapping_bug++;
959 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 ncci_mapping_bug, Id, preserve_ncci));
961 }
962 else
963 {
964 cleanup_ncci_data(plci, ncci);
965 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967 a->ch_ncci[a->ncci_ch[ncci]] = 0;
968 if (!preserve_ncci)
969 {
970 a->ncci_ch[ncci] = 0;
971 a->ncci_plci[ncci] = 0;
972 a->ncci_state[ncci] = IDLE;
973 i = plci->ncci_ring_list;
974 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975 i = a->ncci_next[i];
976 if ((i != 0) && (a->ncci_next[i] == ncci))
977 {
978 if (i == ncci)
979 plci->ncci_ring_list = 0;
980 else if (plci->ncci_ring_list == ncci)
981 plci->ncci_ring_list = i;
982 a->ncci_next[i] = a->ncci_next[ncci];
983 }
984 a->ncci_next[ncci] = 0;
985 }
986 }
987 }
988 else
989 {
990 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
991 {
992 if (a->ncci_plci[ncci] == plci->Id)
993 {
994 cleanup_ncci_data(plci, ncci);
995 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997 a->ch_ncci[a->ncci_ch[ncci]] = 0;
998 if (!preserve_ncci)
999 {
1000 a->ncci_ch[ncci] = 0;
1001 a->ncci_plci[ncci] = 0;
1002 a->ncci_state[ncci] = IDLE;
1003 a->ncci_next[ncci] = 0;
1004 }
1005 }
1006 }
1007 if (!preserve_ncci)
1008 plci->ncci_ring_list = 0;
1009 }
1010 }
1011
1012
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function */
1015 /*------------------------------------------------------------------*/
1016
1017 static void plci_free_msg_in_queue(PLCI *plci)
1018 {
1019 word i;
1020
1021 if (plci->appl)
1022 {
1023 i = plci->msg_in_read_pos;
1024 while (i != plci->msg_in_write_pos)
1025 {
1026 if (i == plci->msg_in_wrap_pos)
1027 i = 0;
1028 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029 {
1030
1031 TransmitBufferFree(plci->appl,
1032 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034 }
1035
1036 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037 MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039 }
1040 }
1041 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044 }
1045
1046
1047 static void plci_remove(PLCI *plci)
1048 {
1049
1050 if (!plci) {
1051 dbug(1, dprintf("plci_remove(no plci)"));
1052 return;
1053 }
1054 init_internal_command_queue(plci);
1055 dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056 if (plci_remove_check(plci))
1057 {
1058 return;
1059 }
1060 if (plci->Sig.Id == 0xff)
1061 {
1062 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063 if (plci->NL.Id && !plci->nl_remove_id)
1064 {
1065 nl_req_ncci(plci, REMOVE, 0);
1066 send_req(plci);
1067 }
1068 }
1069 else
1070 {
1071 if (!plci->sig_remove_id
1072 && (plci->Sig.Id
1073 || (plci->req_in != plci->req_out)
1074 || (plci->nl_req || plci->sig_req)))
1075 {
1076 sig_req(plci, HANGUP, 0);
1077 send_req(plci);
1078 }
1079 }
1080 ncci_remove(plci, 0, false);
1081 plci_free_msg_in_queue(plci);
1082
1083 plci->channels = 0;
1084 plci->appl = NULL;
1085 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086 plci->State = OUTG_DIS_PENDING;
1087 }
1088
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers */
1091 /*------------------------------------------------------------------*/
1092
1093 static void set_group_ind_mask(PLCI *plci)
1094 {
1095 word i;
1096
1097 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098 plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100
1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1102 {
1103 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105
1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1107 {
1108 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL */
1113 /*------------------------------------------------------------------*/
1114
1115 static void clear_c_ind_mask(PLCI *plci)
1116 {
1117 word i;
1118
1119 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120 plci->c_ind_mask_table[i] = 0;
1121 }
1122
1123 static byte c_ind_mask_empty(PLCI *plci)
1124 {
1125 word i;
1126
1127 i = 0;
1128 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129 i++;
1130 return (i == C_IND_MASK_DWORDS);
1131 }
1132
1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1134 {
1135 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137
1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1139 {
1140 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142
1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1144 {
1145 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147
1148 static void dump_c_ind_mask(PLCI *plci)
1149 {
1150 word i, j, k;
1151 dword d;
1152 char *p;
1153 char buf[40];
1154
1155 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1156 {
1157 p = buf + 36;
1158 *p = '\0';
1159 for (j = 0; j < 4; j++)
1160 {
1161 if (i + j < C_IND_MASK_DWORDS)
1162 {
1163 d = plci->c_ind_mask_table[i + j];
1164 for (k = 0; k < 8; k++)
1165 {
1166 *(--p) = hex_asc_lo(d);
1167 d >>= 4;
1168 }
1169 }
1170 else if (i != 0)
1171 {
1172 for (k = 0; k < 8; k++)
1173 *(--p) = ' ';
1174 }
1175 *(--p) = ' ';
1176 }
1177 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1178 }
1179 }
1180
1181
1182
1183
1184
1185 #define dump_plcis(a)
1186
1187
1188
1189 /*------------------------------------------------------------------*/
1190 /* translation function for each message */
1191 /*------------------------------------------------------------------*/
1192
1193 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1194 PLCI *plci, APPL *appl, API_PARSE *parms)
1195 {
1196 word ch;
1197 word i;
1198 word Info;
1199 byte LinkLayer;
1200 API_PARSE *ai;
1201 API_PARSE *bp;
1202 API_PARSE ai_parms[5];
1203 word channel = 0;
1204 dword ch_mask;
1205 byte m;
1206 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1207 static byte lli[2] = {0x01, 0x00};
1208 byte noCh = 0;
1209 word dir = 0;
1210 byte *p_chi = "";
1211
1212 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1213
1214 dbug(1, dprintf("connect_req(%d)", parms->length));
1215 Info = _WRONG_IDENTIFIER;
1216 if (a)
1217 {
1218 if (a->adapter_disabled)
1219 {
1220 dbug(1, dprintf("adapter disabled"));
1221 Id = ((word)1 << 8) | a->Id;
1222 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1223 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1224 return false;
1225 }
1226 Info = _OUT_OF_PLCI;
1227 if ((i = get_plci(a)))
1228 {
1229 Info = 0;
1230 plci = &a->plci[i - 1];
1231 plci->appl = appl;
1232 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1233 /* check 'external controller' bit for codec support */
1234 if (Id & EXT_CONTROLLER)
1235 {
1236 if (AdvCodecSupport(a, plci, appl, 0))
1237 {
1238 plci->Id = 0;
1239 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1240 return 2;
1241 }
1242 }
1243 ai = &parms[9];
1244 bp = &parms[5];
1245 ch = 0;
1246 if (bp->length)LinkLayer = bp->info[3];
1247 else LinkLayer = 0;
1248 if (ai->length)
1249 {
1250 ch = 0xffff;
1251 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1252 {
1253 ch = 0;
1254 if (ai_parms[0].length)
1255 {
1256 ch = GET_WORD(ai_parms[0].info + 1);
1257 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1258 if (ch == 4) /* explizit CHI in message */
1259 {
1260 /* check length of B-CH struct */
1261 if ((ai_parms[0].info)[3] >= 1)
1262 {
1263 if ((ai_parms[0].info)[4] == CHI)
1264 {
1265 p_chi = &((ai_parms[0].info)[5]);
1266 }
1267 else
1268 {
1269 p_chi = &((ai_parms[0].info)[3]);
1270 }
1271 if (p_chi[0] > 35) /* check length of channel ID */
1272 {
1273 Info = _WRONG_MESSAGE_FORMAT;
1274 }
1275 }
1276 else Info = _WRONG_MESSAGE_FORMAT;
1277 }
1278
1279 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1280 {
1281 dir = GET_WORD(ai_parms[0].info + 3);
1282 ch_mask = 0;
1283 m = 0x3f;
1284 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1285 {
1286 if (ai_parms[0].info[i + 5] != 0)
1287 {
1288 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1289 Info = _WRONG_MESSAGE_FORMAT;
1290 else
1291 {
1292 if (ch_mask == 0)
1293 channel = i;
1294 ch_mask |= 1L << i;
1295 }
1296 }
1297 m = 0;
1298 }
1299 if (ch_mask == 0)
1300 Info = _WRONG_MESSAGE_FORMAT;
1301 if (!Info)
1302 {
1303 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1304 {
1305 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1306 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1307 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1308 }
1309 else
1310 esc_chi[0] = 2;
1311 esc_chi[2] = (byte)channel;
1312 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1313 add_p(plci, LLI, lli);
1314 add_p(plci, ESC, esc_chi);
1315 plci->State = LOCAL_CONNECT;
1316 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1317 }
1318 }
1319 }
1320 }
1321 else Info = _WRONG_MESSAGE_FORMAT;
1322 }
1323
1324 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1325 plci->command = _CONNECT_R;
1326 plci->number = Number;
1327 /* x.31 or D-ch free SAPI in LinkLayer? */
1328 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1329 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1330 {
1331 /* B-channel used for B3 connections (ch==0), or no B channel */
1332 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1333 if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1334 else Info = add_b1(plci, &parms[5], ch, 0);
1335 add_s(plci, OAD, &parms[2]);
1336 add_s(plci, OSA, &parms[4]);
1337 add_s(plci, BC, &parms[6]);
1338 add_s(plci, LLC, &parms[7]);
1339 add_s(plci, HLC, &parms[8]);
1340 if (a->Info_Mask[appl->Id - 1] & 0x200)
1341 {
1342 /* early B3 connect (CIP mask bit 9) no release after a disc */
1343 add_p(plci, LLI, "\x01\x01");
1344 }
1345 if (GET_WORD(parms[0].info) < 29) {
1346 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1347 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1348 }
1349 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1350 sig_req(plci, ASSIGN, DSIG_ID);
1351 }
1352 else if (ch == 1) {
1353
1354 /* D-Channel used for B3 connections */
1355 plci->Sig.Id = 0xff;
1356 Info = 0;
1357 }
1358
1359 if (!Info && ch != 2 && !noCh) {
1360 Info = add_b23(plci, &parms[5]);
1361 if (!Info) {
1362 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1363 }
1364 }
1365
1366 if (!Info)
1367 {
1368 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1369 {
1370 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1371 {
1372 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1373 plci->spoofed_msg = CALL_REQ;
1374 plci->internal_command = BLOCK_PLCI;
1375 plci->command = 0;
1376 dbug(1, dprintf("Spoof"));
1377 send_req(plci);
1378 return false;
1379 }
1380 if (ch == 4)add_p(plci, CHI, p_chi);
1381 add_s(plci, CPN, &parms[1]);
1382 add_s(plci, DSA, &parms[3]);
1383 if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1384 add_ai(plci, &parms[9]);
1385 if (!dir)sig_req(plci, CALL_REQ, 0);
1386 else
1387 {
1388 plci->command = PERM_LIST_REQ;
1389 plci->appl = appl;
1390 sig_req(plci, LISTEN_REQ, 0);
1391 send_req(plci);
1392 return false;
1393 }
1394 }
1395 send_req(plci);
1396 return false;
1397 }
1398 plci->Id = 0;
1399 }
1400 }
1401 sendf(appl,
1402 _CONNECT_R | CONFIRM,
1403 Id,
1404 Number,
1405 "w", Info);
1406 return 2;
1407 }
1408
1409 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1410 PLCI *plci, APPL *appl, API_PARSE *parms)
1411 {
1412 word i, Info;
1413 word Reject;
1414 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1415 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1416 API_PARSE *ai;
1417 API_PARSE ai_parms[5];
1418 word ch = 0;
1419
1420 if (!plci) {
1421 dbug(1, dprintf("connect_res(no plci)"));
1422 return 0; /* no plci, no send */
1423 }
1424
1425 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1426 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1427 ai = &parms[5];
1428 dbug(1, dprintf("ai->length=%d", ai->length));
1429
1430 if (ai->length)
1431 {
1432 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1433 {
1434 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1435 ch = 0;
1436 if (ai_parms[0].length)
1437 {
1438 ch = GET_WORD(ai_parms[0].info + 1);
1439 dbug(1, dprintf("BCH-I=0x%x", ch));
1440 }
1441 }
1442 }
1443
1444 if (plci->State == INC_CON_CONNECTED_ALERT)
1445 {
1446 dbug(1, dprintf("Connected Alert Call_Res"));
1447 if (a->Info_Mask[appl->Id - 1] & 0x200)
1448 {
1449 /* early B3 connect (CIP mask bit 9) no release after a disc */
1450 add_p(plci, LLI, "\x01\x01");
1451 }
1452 add_s(plci, CONN_NR, &parms[2]);
1453 add_s(plci, LLC, &parms[4]);
1454 add_ai(plci, &parms[5]);
1455 plci->State = INC_CON_ACCEPT;
1456 sig_req(plci, CALL_RES, 0);
1457 return 1;
1458 }
1459 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1460 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1461 dump_c_ind_mask(plci);
1462 Reject = GET_WORD(parms[0].info);
1463 dbug(1, dprintf("Reject=0x%x", Reject));
1464 if (Reject)
1465 {
1466 if (c_ind_mask_empty(plci))
1467 {
1468 if ((Reject & 0xff00) == 0x3400)
1469 {
1470 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1471 add_p(plci, ESC, esc_t);
1472 add_ai(plci, &parms[5]);
1473 sig_req(plci, REJECT, 0);
1474 }
1475 else if (Reject == 1 || Reject >= 9)
1476 {
1477 add_ai(plci, &parms[5]);
1478 sig_req(plci, HANGUP, 0);
1479 }
1480 else
1481 {
1482 esc_t[2] = cau_t[(Reject&0x000f)];
1483 add_p(plci, ESC, esc_t);
1484 add_ai(plci, &parms[5]);
1485 sig_req(plci, REJECT, 0);
1486 }
1487 plci->appl = appl;
1488 }
1489 else
1490 {
1491 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1492 }
1493 }
1494 else {
1495 plci->appl = appl;
1496 if (Id & EXT_CONTROLLER) {
1497 if (AdvCodecSupport(a, plci, appl, 0)) {
1498 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1499 sig_req(plci, HANGUP, 0);
1500 return 1;
1501 }
1502 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1503 {
1504 Info = add_b23(plci, &parms[1]);
1505 if (Info)
1506 {
1507 dbug(1, dprintf("connect_res(error from add_b23)"));
1508 sig_req(plci, HANGUP, 0);
1509 return 1;
1510 }
1511 if (plci->adv_nl)
1512 {
1513 nl_req_ncci(plci, ASSIGN, 0);
1514 }
1515 }
1516 }
1517 else
1518 {
1519 plci->tel = 0;
1520 if (ch != 2)
1521 {
1522 Info = add_b23(plci, &parms[1]);
1523 if (Info)
1524 {
1525 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1526 sig_req(plci, HANGUP, 0);
1527 return 1;
1528 }
1529 }
1530 nl_req_ncci(plci, ASSIGN, 0);
1531 }
1532
1533 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1534 {
1535 api_save_msg(parms, "wsssss", &plci->saved_msg);
1536 plci->spoofed_msg = CALL_RES;
1537 plci->internal_command = BLOCK_PLCI;
1538 plci->command = 0;
1539 dbug(1, dprintf("Spoof"));
1540 }
1541 else
1542 {
1543 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1544 if (a->Info_Mask[appl->Id - 1] & 0x200)
1545 {
1546 /* early B3 connect (CIP mask bit 9) no release after a disc */
1547 add_p(plci, LLI, "\x01\x01");
1548 }
1549 add_s(plci, CONN_NR, &parms[2]);
1550 add_s(plci, LLC, &parms[4]);
1551 add_ai(plci, &parms[5]);
1552 plci->State = INC_CON_ACCEPT;
1553 sig_req(plci, CALL_RES, 0);
1554 }
1555
1556 for (i = 0; i < max_appl; i++) {
1557 if (test_c_ind_mask_bit(plci, i)) {
1558 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1559 }
1560 }
1561 }
1562 }
1563 return 1;
1564 }
1565
1566 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1567 PLCI *plci, APPL *appl, API_PARSE *msg)
1568 {
1569 dbug(1, dprintf("connect_a_res"));
1570 return false;
1571 }
1572
1573 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1574 PLCI *plci, APPL *appl, API_PARSE *msg)
1575 {
1576 word Info;
1577 word i;
1578
1579 dbug(1, dprintf("disconnect_req"));
1580
1581 Info = _WRONG_IDENTIFIER;
1582
1583 if (plci)
1584 {
1585 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1586 {
1587 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1588 plci->appl = appl;
1589 for (i = 0; i < max_appl; i++)
1590 {
1591 if (test_c_ind_mask_bit(plci, i))
1592 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1593 }
1594 plci->State = OUTG_DIS_PENDING;
1595 }
1596 if (plci->Sig.Id && plci->appl)
1597 {
1598 Info = 0;
1599 if (plci->Sig.Id != 0xff)
1600 {
1601 if (plci->State != INC_DIS_PENDING)
1602 {
1603 add_ai(plci, &msg[0]);
1604 sig_req(plci, HANGUP, 0);
1605 plci->State = OUTG_DIS_PENDING;
1606 return 1;
1607 }
1608 }
1609 else
1610 {
1611 if (plci->NL.Id && !plci->nl_remove_id)
1612 {
1613 mixer_remove(plci);
1614 nl_req_ncci(plci, REMOVE, 0);
1615 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1616 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1617 plci->State = INC_DIS_PENDING;
1618 }
1619 return 1;
1620 }
1621 }
1622 }
1623
1624 if (!appl) return false;
1625 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1626 return false;
1627 }
1628
1629 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1630 PLCI *plci, APPL *appl, API_PARSE *msg)
1631 {
1632 dbug(1, dprintf("disconnect_res"));
1633 if (plci)
1634 {
1635 /* clear ind mask bit, just in case of collsion of */
1636 /* DISCONNECT_IND and CONNECT_RES */
1637 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1638 ncci_free_receive_buffers(plci, 0);
1639 if (plci_remove_check(plci))
1640 {
1641 return 0;
1642 }
1643 if (plci->State == INC_DIS_PENDING
1644 || plci->State == SUSPENDING) {
1645 if (c_ind_mask_empty(plci)) {
1646 if (plci->State != SUSPENDING) plci->State = IDLE;
1647 dbug(1, dprintf("chs=%d", plci->channels));
1648 if (!plci->channels) {
1649 plci_remove(plci);
1650 }
1651 }
1652 }
1653 }
1654 return 0;
1655 }
1656
1657 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1658 PLCI *plci, APPL *appl, API_PARSE *parms)
1659 {
1660 word Info;
1661 byte i;
1662
1663 dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1664
1665 Info = _WRONG_IDENTIFIER;
1666 if (a) {
1667 Info = 0;
1668 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1669 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1670 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1671 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1672 a->Info_Mask[appl->Id - 1] |= 0x10; /* call progression infos */
1673 }
1674
1675 /* check if external controller listen and switch listen on or off*/
1676 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1677 if (a->profile.Global_Options & ON_BOARD_CODEC) {
1678 dummy_plci.State = IDLE;
1679 a->codec_listen[appl->Id - 1] = &dummy_plci;
1680 a->TelOAD[0] = (byte)(parms[3].length);
1681 for (i = 1; parms[3].length >= i && i < 22; i++) {
1682 a->TelOAD[i] = parms[3].info[i];
1683 }
1684 a->TelOAD[i] = 0;
1685 a->TelOSA[0] = (byte)(parms[4].length);
1686 for (i = 1; parms[4].length >= i && i < 22; i++) {
1687 a->TelOSA[i] = parms[4].info[i];
1688 }
1689 a->TelOSA[i] = 0;
1690 }
1691 else Info = 0x2002; /* wrong controller, codec not supported */
1692 }
1693 else{ /* clear listen */
1694 a->codec_listen[appl->Id - 1] = (PLCI *)0;
1695 }
1696 }
1697 sendf(appl,
1698 _LISTEN_R | CONFIRM,
1699 Id,
1700 Number,
1701 "w", Info);
1702
1703 if (a) listen_check(a);
1704 return false;
1705 }
1706
1707 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1708 PLCI *plci, APPL *appl, API_PARSE *msg)
1709 {
1710 word i;
1711 API_PARSE *ai;
1712 PLCI *rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1714 word Info = 0;
1715
1716 dbug(1, dprintf("info_req"));
1717 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1718
1719 ai = &msg[1];
1720
1721 if (ai->length)
1722 {
1723 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1724 {
1725 dbug(1, dprintf("AddInfo wrong"));
1726 Info = _WRONG_MESSAGE_FORMAT;
1727 }
1728 }
1729 if (!a) Info = _WRONG_STATE;
1730
1731 if (!Info && plci)
1732 { /* no fac, with CPN, or KEY */
1733 rc_plci = plci;
1734 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1735 {
1736 /* overlap sending option */
1737 dbug(1, dprintf("OvlSnd"));
1738 add_s(plci, CPN, &msg[0]);
1739 add_s(plci, KEY, &ai_parms[1]);
1740 sig_req(plci, INFO_REQ, 0);
1741 send_req(plci);
1742 return false;
1743 }
1744
1745 if (plci->State && ai_parms[2].length)
1746 {
1747 /* User_Info option */
1748 dbug(1, dprintf("UUI"));
1749 add_s(plci, UUI, &ai_parms[2]);
1750 sig_req(plci, USER_DATA, 0);
1751 }
1752 else if (plci->State && ai_parms[3].length)
1753 {
1754 /* Facility option */
1755 dbug(1, dprintf("FAC"));
1756 add_s(plci, CPN, &msg[0]);
1757 add_ai(plci, &msg[1]);
1758 sig_req(plci, FACILITY_REQ, 0);
1759 }
1760 else
1761 {
1762 Info = _WRONG_STATE;
1763 }
1764 }
1765 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766 {
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1, dprintf("NCR_FAC"));
1769 if ((i = get_plci(a)))
1770 {
1771 rc_plci = &a->plci[i - 1];
1772 appl->NullCREnable = true;
1773 rc_plci->internal_command = C_NCR_FAC_REQ;
1774 rc_plci->appl = appl;
1775 add_p(rc_plci, CAI, "\x01\x80");
1776 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci, ASSIGN, DSIG_ID);
1778 send_req(rc_plci);
1779 }
1780 else
1781 {
1782 Info = _OUT_OF_PLCI;
1783 }
1784
1785 if (!Info)
1786 {
1787 add_s(rc_plci, CPN, &msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci, NCR_FACILITY, 0);
1790 send_req(rc_plci);
1791 return false;
1792 /* for application controlled supplementary services */
1793 }
1794 }
1795
1796 if (!rc_plci)
1797 {
1798 Info = _WRONG_MESSAGE_FORMAT;
1799 }
1800
1801 if (!Info)
1802 {
1803 send_req(rc_plci);
1804 }
1805 else
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1, dprintf("localInfoCon"));
1808 sendf(appl,
1809 _INFO_R | CONFIRM,
1810 Id,
1811 Number,
1812 "w", Info);
1813 }
1814 return false;
1815 }
1816
1817 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1818 PLCI *plci, APPL *appl, API_PARSE *msg)
1819 {
1820 dbug(1, dprintf("info_res"));
1821 return false;
1822 }
1823
1824 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1825 PLCI *plci, APPL *appl, API_PARSE *msg)
1826 {
1827 word Info;
1828 byte ret;
1829
1830 dbug(1, dprintf("alert_req"));
1831
1832 Info = _WRONG_IDENTIFIER;
1833 ret = false;
1834 if (plci) {
1835 Info = _ALERT_IGNORED;
1836 if (plci->State != INC_CON_ALERT) {
1837 Info = _WRONG_STATE;
1838 if (plci->State == INC_CON_PENDING) {
1839 Info = 0;
1840 plci->State = INC_CON_ALERT;
1841 add_ai(plci, &msg[0]);
1842 sig_req(plci, CALL_ALERT, 0);
1843 ret = 1;
1844 }
1845 }
1846 }
1847 sendf(appl,
1848 _ALERT_R | CONFIRM,
1849 Id,
1850 Number,
1851 "w", Info);
1852 return ret;
1853 }
1854
1855 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1856 PLCI *plci, APPL *appl, API_PARSE *msg)
1857 {
1858 word Info = 0;
1859 word i = 0;
1860
1861 word selector;
1862 word SSreq;
1863 long relatedPLCIvalue;
1864 DIVA_CAPI_ADAPTER *relatedadapter;
1865 byte *SSparms = "";
1866 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1867 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1868 API_PARSE *parms;
1869 API_PARSE ss_parms[11];
1870 PLCI *rplci;
1871 byte cai[15];
1872 dword d;
1873 API_PARSE dummy;
1874
1875 dbug(1, dprintf("facility_req"));
1876 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1877
1878 parms = &msg[1];
1879
1880 if (!a)
1881 {
1882 dbug(1, dprintf("wrong Ctrl"));
1883 Info = _WRONG_IDENTIFIER;
1884 }
1885
1886 selector = GET_WORD(msg[0].info);
1887
1888 if (!Info)
1889 {
1890 switch (selector)
1891 {
1892 case SELECTOR_HANDSET:
1893 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1894 break;
1895
1896 case SELECTOR_SU_SERV:
1897 if (!msg[1].length)
1898 {
1899 Info = _WRONG_MESSAGE_FORMAT;
1900 break;
1901 }
1902 SSreq = GET_WORD(&(msg[1].info[1]));
1903 PUT_WORD(&RCparms[1], SSreq);
1904 SSparms = RCparms;
1905 switch (SSreq)
1906 {
1907 case S_GET_SUPPORTED_SERVICES:
1908 if ((i = get_plci(a)))
1909 {
1910 rplci = &a->plci[i - 1];
1911 rplci->appl = appl;
1912 add_p(rplci, CAI, "\x01\x80");
1913 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1914 sig_req(rplci, ASSIGN, DSIG_ID);
1915 send_req(rplci);
1916 }
1917 else
1918 {
1919 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1920 SSparms = (byte *)SSstruct;
1921 break;
1922 }
1923 rplci->internal_command = GETSERV_REQ_PEND;
1924 rplci->number = Number;
1925 rplci->appl = appl;
1926 sig_req(rplci, S_SUPPORTED, 0);
1927 send_req(rplci);
1928 return false;
1929 break;
1930
1931 case S_LISTEN:
1932 if (parms->length == 7)
1933 {
1934 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1935 {
1936 dbug(1, dprintf("format wrong"));
1937 Info = _WRONG_MESSAGE_FORMAT;
1938 break;
1939 }
1940 }
1941 else
1942 {
1943 Info = _WRONG_MESSAGE_FORMAT;
1944 break;
1945 }
1946 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1947 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1948 {
1949 if ((i = get_plci(a)))
1950 {
1951 rplci = &a->plci[i - 1];
1952 rplci->appl = appl;
1953 add_p(rplci, CAI, "\x01\x80");
1954 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1955 sig_req(rplci, ASSIGN, DSIG_ID);
1956 send_req(rplci);
1957 }
1958 else
1959 {
1960 break;
1961 }
1962 rplci->internal_command = GET_MWI_STATE;
1963 rplci->number = Number;
1964 sig_req(rplci, MWI_POLL, 0);
1965 send_req(rplci);
1966 }
1967 break;
1968
1969 case S_HOLD:
1970 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1971 if (plci && plci->State && plci->SuppState == IDLE)
1972 {
1973 plci->SuppState = HOLD_REQUEST;
1974 plci->command = C_HOLD_REQ;
1975 add_s(plci, CAI, &ss_parms[1]);
1976 sig_req(plci, CALL_HOLD, 0);
1977 send_req(plci);
1978 return false;
1979 }
1980 else Info = 0x3010; /* wrong state */
1981 break;
1982 case S_RETRIEVE:
1983 if (plci && plci->State && plci->SuppState == CALL_HELD)
1984 {
1985 if (Id & EXT_CONTROLLER)
1986 {
1987 if (AdvCodecSupport(a, plci, appl, 0))
1988 {
1989 Info = 0x3010; /* wrong state */
1990 break;
1991 }
1992 }
1993 else plci->tel = 0;
1994
1995 plci->SuppState = RETRIEVE_REQUEST;
1996 plci->command = C_RETRIEVE_REQ;
1997 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1998 {
1999 plci->spoofed_msg = CALL_RETRIEVE;
2000 plci->internal_command = BLOCK_PLCI;
2001 plci->command = 0;
2002 dbug(1, dprintf("Spoof"));
2003 return false;
2004 }
2005 else
2006 {
2007 sig_req(plci, CALL_RETRIEVE, 0);
2008 send_req(plci);
2009 return false;
2010 }
2011 }
2012 else Info = 0x3010; /* wrong state */
2013 break;
2014 case S_SUSPEND:
2015 if (parms->length)
2016 {
2017 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2018 {
2019 dbug(1, dprintf("format wrong"));
2020 Info = _WRONG_MESSAGE_FORMAT;
2021 break;
2022 }
2023 }
2024 if (plci && plci->State)
2025 {
2026 add_s(plci, CAI, &ss_parms[2]);
2027 plci->command = SUSPEND_REQ;
2028 sig_req(plci, SUSPEND, 0);
2029 plci->State = SUSPENDING;
2030 send_req(plci);
2031 }
2032 else Info = 0x3010; /* wrong state */
2033 break;
2034
2035 case S_RESUME:
2036 if (!(i = get_plci(a)))
2037 {
2038 Info = _OUT_OF_PLCI;
2039 break;
2040 }
2041 rplci = &a->plci[i - 1];
2042 rplci->appl = appl;
2043 rplci->number = Number;
2044 rplci->tel = 0;
2045 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2046 /* check 'external controller' bit for codec support */
2047 if (Id & EXT_CONTROLLER)
2048 {
2049 if (AdvCodecSupport(a, rplci, appl, 0))
2050 {
2051 rplci->Id = 0;
2052 Info = 0x300A;
2053 break;
2054 }
2055 }
2056 if (parms->length)
2057 {
2058 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2059 {
2060 dbug(1, dprintf("format wrong"));
2061 rplci->Id = 0;
2062 Info = _WRONG_MESSAGE_FORMAT;
2063 break;
2064 }
2065 }
2066 dummy.length = 0;
2067 dummy.info = "\x00";
2068 add_b1(rplci, &dummy, 0, 0);
2069 if (a->Info_Mask[appl->Id - 1] & 0x200)
2070 {
2071 /* early B3 connect (CIP mask bit 9) no release after a disc */
2072 add_p(rplci, LLI, "\x01\x01");
2073 }
2074 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2075 sig_req(rplci, ASSIGN, DSIG_ID);
2076 send_req(rplci);
2077 add_s(rplci, CAI, &ss_parms[2]);
2078 rplci->command = RESUME_REQ;
2079 sig_req(rplci, RESUME, 0);
2080 rplci->State = RESUMING;
2081 send_req(rplci);
2082 break;
2083
2084 case S_CONF_BEGIN: /* Request */
2085 case S_CONF_DROP:
2086 case S_CONF_ISOLATE:
2087 case S_CONF_REATTACH:
2088 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2089 {
2090 dbug(1, dprintf("format wrong"));
2091 Info = _WRONG_MESSAGE_FORMAT;
2092 break;
2093 }
2094 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2095 {
2096 d = GET_DWORD(ss_parms[2].info);
2097 if (d >= 0x80)
2098 {
2099 dbug(1, dprintf("format wrong"));
2100 Info = _WRONG_MESSAGE_FORMAT;
2101 break;
2102 }
2103 plci->ptyState = (byte)SSreq;
2104 plci->command = 0;
2105 cai[0] = 2;
2106 switch (SSreq)
2107 {
2108 case S_CONF_BEGIN:
2109 cai[1] = CONF_BEGIN;
2110 plci->internal_command = CONF_BEGIN_REQ_PEND;
2111 break;
2112 case S_CONF_DROP:
2113 cai[1] = CONF_DROP;
2114 plci->internal_command = CONF_DROP_REQ_PEND;
2115 break;
2116 case S_CONF_ISOLATE:
2117 cai[1] = CONF_ISOLATE;
2118 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2119 break;
2120 case S_CONF_REATTACH:
2121 cai[1] = CONF_REATTACH;
2122 plci->internal_command = CONF_REATTACH_REQ_PEND;
2123 break;
2124 }
2125 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2126 add_p(plci, CAI, cai);
2127 sig_req(plci, S_SERVICE, 0);
2128 send_req(plci);
2129 return false;
2130 }
2131 else Info = 0x3010; /* wrong state */
2132 break;
2133
2134 case S_ECT:
2135 case S_3PTY_BEGIN:
2136 case S_3PTY_END:
2137 case S_CONF_ADD:
2138 if (parms->length == 7)
2139 {
2140 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2141 {
2142 dbug(1, dprintf("format wrong"));
2143 Info = _WRONG_MESSAGE_FORMAT;
2144 break;
2145 }
2146 }
2147 else if (parms->length == 8) /* workaround for the T-View-S */
2148 {
2149 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2150 {
2151 dbug(1, dprintf("format wrong"));
2152 Info = _WRONG_MESSAGE_FORMAT;
2153 break;
2154 }
2155 }
2156 else
2157 {
2158 Info = _WRONG_MESSAGE_FORMAT;
2159 break;
2160 }
2161 if (!msg[1].length)
2162 {
2163 Info = _WRONG_MESSAGE_FORMAT;
2164 break;
2165 }
2166 if (!plci)
2167 {
2168 Info = _WRONG_IDENTIFIER;
2169 break;
2170 }
2171 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2172 relatedPLCIvalue &= 0x0000FFFF;
2173 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2174 /* controller starts with 0 up to (max_adapter - 1) */
2175 if (((relatedPLCIvalue & 0x7f) == 0)
2176 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2177 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2178 {
2179 if (SSreq == S_3PTY_END)
2180 {
2181 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2182 rplci = plci;
2183 }
2184 else
2185 {
2186 Info = 0x3010; /* wrong state */
2187 break;
2188 }
2189 }
2190 else
2191 {
2192 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2193 relatedPLCIvalue >>= 8;
2194 /* find PLCI PTR*/
2195 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2196 {
2197 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2198 {
2199 rplci = &relatedadapter->plci[i];
2200 }
2201 }
2202 if (!rplci || !relatedPLCIvalue)
2203 {
2204 if (SSreq == S_3PTY_END)
2205 {
2206 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2207 rplci = plci;
2208 }
2209 else
2210 {
2211 Info = 0x3010; /* wrong state */
2212 break;
2213 }
2214 }
2215 }
2216 /*
2217 dbug(1, dprintf("rplci:%x", rplci));
2218 dbug(1, dprintf("plci:%x", plci));
2219 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2220 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2221 dbug(1, dprintf("SSreq:%x", SSreq));
2222 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2223 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2224 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2225 */
2226 /* send PTY/ECT req, cannot check all states because of US stuff */
2227 if (!rplci->internal_command && rplci->appl)
2228 {
2229 plci->command = 0;
2230 rplci->relatedPTYPLCI = plci;
2231 plci->relatedPTYPLCI = rplci;
2232 rplci->ptyState = (byte)SSreq;
2233 if (SSreq == S_ECT)
2234 {
2235 rplci->internal_command = ECT_REQ_PEND;
2236 cai[1] = ECT_EXECUTE;
2237
2238 rplci->vswitchstate = 0;
2239 rplci->vsprot = 0;
2240 rplci->vsprotdialect = 0;
2241 plci->vswitchstate = 0;
2242 plci->vsprot = 0;
2243 plci->vsprotdialect = 0;
2244
2245 }
2246 else if (SSreq == S_CONF_ADD)
2247 {
2248 rplci->internal_command = CONF_ADD_REQ_PEND;
2249 cai[1] = CONF_ADD;
2250 }
2251 else
2252 {
2253 rplci->internal_command = PTY_REQ_PEND;
2254 cai[1] = (byte)(SSreq - 3);
2255 }
2256 rplci->number = Number;
2257 if (plci != rplci) /* explicit invocation */
2258 {
2259 cai[0] = 2;
2260 cai[2] = plci->Sig.Id;
2261 dbug(1, dprintf("explicit invocation"));
2262 }
2263 else
2264 {
2265 dbug(1, dprintf("implicit invocation"));
2266 cai[0] = 1;
2267 }
2268 add_p(rplci, CAI, cai);
2269 sig_req(rplci, S_SERVICE, 0);
2270 send_req(rplci);
2271 return false;
2272 }
2273 else
2274 {
2275 dbug(0, dprintf("Wrong line"));
2276 Info = 0x3010; /* wrong state */
2277 break;
2278 }
2279 break;
2280
2281 case S_CALL_DEFLECTION:
2282 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2283 {
2284 dbug(1, dprintf("format wrong"));
2285 Info = _WRONG_MESSAGE_FORMAT;
2286 break;
2287 }
2288 if (!plci)
2289 {
2290 Info = _WRONG_IDENTIFIER;
2291 break;
2292 }
2293 /* reuse unused screening indicator */
2294 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2295 plci->command = 0;
2296 plci->internal_command = CD_REQ_PEND;
2297 appl->CDEnable = true;
2298 cai[0] = 1;
2299 cai[1] = CALL_DEFLECTION;
2300 add_p(plci, CAI, cai);
2301 add_p(plci, CPN, ss_parms[3].info);
2302 sig_req(plci, S_SERVICE, 0);
2303 send_req(plci);
2304 return false;
2305 break;
2306
2307 case S_CALL_FORWARDING_START:
2308 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2309 {
2310 dbug(1, dprintf("format wrong"));
2311 Info = _WRONG_MESSAGE_FORMAT;
2312 break;
2313 }
2314
2315 if ((i = get_plci(a)))
2316 {
2317 rplci = &a->plci[i - 1];
2318 rplci->appl = appl;
2319 add_p(rplci, CAI, "\x01\x80");
2320 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2321 sig_req(rplci, ASSIGN, DSIG_ID);
2322 send_req(rplci);
2323 }
2324 else
2325 {
2326 Info = _OUT_OF_PLCI;
2327 break;
2328 }
2329
2330 /* reuse unused screening indicator */
2331 rplci->internal_command = CF_START_PEND;
2332 rplci->appl = appl;
2333 rplci->number = Number;
2334 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2335 cai[0] = 2;
2336 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2337 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2338 add_p(rplci, CAI, cai);
2339 add_p(rplci, OAD, ss_parms[5].info);
2340 add_p(rplci, CPN, ss_parms[6].info);
2341 sig_req(rplci, S_SERVICE, 0);
2342 send_req(rplci);
2343 return false;
2344 break;
2345
2346 case S_INTERROGATE_DIVERSION:
2347 case S_INTERROGATE_NUMBERS:
2348 case S_CALL_FORWARDING_STOP:
2349 case S_CCBS_REQUEST:
2350 case S_CCBS_DEACTIVATE:
2351 case S_CCBS_INTERROGATE:
2352 switch (SSreq)
2353 {
2354 case S_INTERROGATE_NUMBERS:
2355 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2356 {
2357 dbug(0, dprintf("format wrong"));
2358 Info = _WRONG_MESSAGE_FORMAT;
2359 }
2360 break;
2361 case S_CCBS_REQUEST:
2362 case S_CCBS_DEACTIVATE:
2363 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2364 {
2365 dbug(0, dprintf("format wrong"));
2366 Info = _WRONG_MESSAGE_FORMAT;
2367 }
2368 break;
2369 case S_CCBS_INTERROGATE:
2370 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2371 {
2372 dbug(0, dprintf("format wrong"));
2373 Info = _WRONG_MESSAGE_FORMAT;
2374 }
2375 break;
2376 default:
2377 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2378 {
2379 dbug(0, dprintf("format wrong"));
2380 Info = _WRONG_MESSAGE_FORMAT;
2381 break;
2382 }
2383 break;
2384 }
2385
2386 if (Info) break;
2387 if ((i = get_plci(a)))
2388 {
2389 rplci = &a->plci[i - 1];
2390 switch (SSreq)
2391 {
2392 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2393 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2394 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2395 break;
2396 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2397 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2398 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2399 break;
2400 case S_CALL_FORWARDING_STOP:
2401 rplci->internal_command = CF_STOP_PEND;
2402 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2403 break;
2404 case S_CCBS_REQUEST:
2405 cai[1] = CCBS_REQUEST;
2406 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2407 break;
2408 case S_CCBS_DEACTIVATE:
2409 cai[1] = CCBS_DEACTIVATE;
2410 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2411 break;
2412 case S_CCBS_INTERROGATE:
2413 cai[1] = CCBS_INTERROGATE;
2414 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2415 break;
2416 default:
2417 cai[1] = 0;
2418 break;
2419 }
2420 rplci->appl = appl;
2421 rplci->number = Number;
2422 add_p(rplci, CAI, "\x01\x80");
2423 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2424 sig_req(rplci, ASSIGN, DSIG_ID);
2425 send_req(rplci);
2426 }
2427 else
2428 {
2429 Info = _OUT_OF_PLCI;
2430 break;
2431 }
2432
2433 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2434 switch (SSreq)
2435 {
2436 case S_INTERROGATE_NUMBERS:
2437 cai[0] = 1;
2438 add_p(rplci, CAI, cai);
2439 break;
2440 case S_CCBS_REQUEST:
2441 case S_CCBS_DEACTIVATE:
2442 cai[0] = 3;
2443 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2444 add_p(rplci, CAI, cai);
2445 break;
2446 case S_CCBS_INTERROGATE:
2447 cai[0] = 3;
2448 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2449 add_p(rplci, CAI, cai);
2450 add_p(rplci, OAD, ss_parms[4].info);
2451 break;
2452 default:
2453 cai[0] = 2;
2454 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2455 add_p(rplci, CAI, cai);
2456 add_p(rplci, OAD, ss_parms[5].info);
2457 break;
2458 }
2459
2460 sig_req(rplci, S_SERVICE, 0);
2461 send_req(rplci);
2462 return false;
2463 break;
2464
2465 case S_MWI_ACTIVATE:
2466 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2467 {
2468 dbug(1, dprintf("format wrong"));
2469 Info = _WRONG_MESSAGE_FORMAT;
2470 break;
2471 }
2472 if (!plci)
2473 {
2474 if ((i = get_plci(a)))
2475 {
2476 rplci = &a->plci[i - 1];
2477 rplci->appl = appl;
2478 rplci->cr_enquiry = true;
2479 add_p(rplci, CAI, "\x01\x80");
2480 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2481 sig_req(rplci, ASSIGN, DSIG_ID);
2482 send_req(rplci);
2483 }
2484 else
2485 {
2486 Info = _OUT_OF_PLCI;
2487 break;
2488 }
2489 }
2490 else
2491 {
2492 rplci = plci;
2493 rplci->cr_enquiry = false;
2494 }
2495
2496 rplci->command = 0;
2497 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2498 rplci->appl = appl;
2499 rplci->number = Number;
2500
2501 cai[0] = 13;
2502 cai[1] = ACTIVATION_MWI; /* Function */
2503 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2504 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2505 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2506 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2507 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2508 add_p(rplci, CAI, cai);
2509 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2510 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2511 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2512 add_p(rplci, UID, ss_parms[10].info); /* Time */
2513 sig_req(rplci, S_SERVICE, 0);
2514 send_req(rplci);
2515 return false;
2516
2517 case S_MWI_DEACTIVATE:
2518 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2519 {
2520 dbug(1, dprintf("format wrong"));
2521 Info = _WRONG_MESSAGE_FORMAT;
2522 break;
2523 }
2524 if (!plci)
2525 {
2526 if ((i = get_plci(a)))
2527 {
2528 rplci = &a->plci[i - 1];
2529 rplci->appl = appl;
2530 rplci->cr_enquiry = true;
2531 add_p(rplci, CAI, "\x01\x80");
2532 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2533 sig_req(rplci, ASSIGN, DSIG_ID);
2534 send_req(rplci);
2535 }
2536 else
2537 {
2538 Info = _OUT_OF_PLCI;
2539 break;
2540 }
2541 }
2542 else
2543 {
2544 rplci = plci;
2545 rplci->cr_enquiry = false;
2546 }
2547
2548 rplci->command = 0;
2549 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2550 rplci->appl = appl;
2551 rplci->number = Number;
2552
2553 cai[0] = 5;
2554 cai[1] = DEACTIVATION_MWI; /* Function */
2555 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2556 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2557 add_p(rplci, CAI, cai);
2558 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2559 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2560 sig_req(rplci, S_SERVICE, 0);
2561 send_req(rplci);
2562 return false;
2563
2564 default:
2565 Info = 0x300E; /* not supported */
2566 break;
2567 }
2568 break; /* case SELECTOR_SU_SERV: end */
2569
2570
2571 case SELECTOR_DTMF:
2572 return (dtmf_request(Id, Number, a, plci, appl, msg));
2573
2574
2575
2576 case SELECTOR_LINE_INTERCONNECT:
2577 return (mixer_request(Id, Number, a, plci, appl, msg));
2578
2579
2580
2581 case PRIV_SELECTOR_ECHO_CANCELLER:
2582 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2583 return (ec_request(Id, Number, a, plci, appl, msg));
2584
2585 case SELECTOR_ECHO_CANCELLER:
2586 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2587 return (ec_request(Id, Number, a, plci, appl, msg));
2588
2589
2590 case SELECTOR_V42BIS:
2591 default:
2592 Info = _FACILITY_NOT_SUPPORTED;
2593 break;
2594 } /* end of switch (selector) */
2595 }
2596
2597 dbug(1, dprintf("SendFacRc"));
2598 sendf(appl,
2599 _FACILITY_R | CONFIRM,
2600 Id,
2601 Number,
2602 "wws", Info, selector, SSparms);
2603 return false;
2604 }
2605
2606 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2607 PLCI *plci, APPL *appl, API_PARSE *msg)
2608 {
2609 dbug(1, dprintf("facility_res"));
2610 return false;
2611 }
2612
2613 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2614 PLCI *plci, APPL *appl, API_PARSE *parms)
2615 {
2616 word Info = 0;
2617 byte req;
2618 byte len;
2619 word w;
2620 word fax_control_bits, fax_feature_bits, fax_info_change;
2621 API_PARSE *ncpi;
2622 byte pvc[2];
2623
2624 API_PARSE fax_parms[9];
2625 word i;
2626
2627
2628 dbug(1, dprintf("connect_b3_req"));
2629 if (plci)
2630 {
2631 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2632 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2633 {
2634 Info = _WRONG_STATE;
2635 }
2636 else
2637 {
2638 /* local reply if assign unsuccessful
2639 or B3 protocol allows only one layer 3 connection
2640 and already connected
2641 or B2 protocol not any LAPD
2642 and connect_b3_req contradicts originate/answer direction */
2643 if (!plci->NL.Id
2644 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2645 && ((plci->channels != 0)
2646 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2647 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2648 {
2649 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2650 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2651 Info = _WRONG_STATE;
2652 sendf(appl,
2653 _CONNECT_B3_R | CONFIRM,
2654 Id,
2655 Number,
2656 "w", Info);
2657 return false;
2658 }
2659 plci->requested_options_conn = 0;
2660
2661 req = N_CONNECT;
2662 ncpi = &parms[0];
2663 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2664 {
2665 if (ncpi->length > 2)
2666 {
2667 /* check for PVC */
2668 if (ncpi->info[2] || ncpi->info[3])
2669 {
2670 pvc[0] = ncpi->info[3];
2671 pvc[1] = ncpi->info[2];
2672 add_d(plci, 2, pvc);
2673 req = N_RESET;
2674 }
2675 else
2676 {
2677 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2678 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2679 }
2680 }
2681 }
2682 else if (plci->B3_prot == 5)
2683 {
2684 if (plci->NL.Id && !plci->nl_remove_id)
2685 {
2686 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2687 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2688 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2689 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2690 {
2691 len = offsetof(T30_INFO, universal_6);
2692 fax_info_change = false;
2693 if (ncpi->length >= 4)
2694 {
2695 w = GET_WORD(&ncpi->info[3]);
2696 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2697 {
2698 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2699 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2700 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2701 fax_info_change = true;
2702 }
2703 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2704 if (w & 0x0002) /* Fax-polling request */
2705 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2706 if ((w & 0x0004) /* Request to send / poll another document */
2707 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2708 {
2709 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2710 }
2711 if (ncpi->length >= 6)
2712 {
2713 w = GET_WORD(&ncpi->info[5]);
2714 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2715 {
2716 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2717 fax_info_change = true;
2718 }
2719
2720 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2721 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2722 {
2723 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2724 }
2725 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2726 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2727 {
2728 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2729 }
2730 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2731 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2732 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2733 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2734 {
2735 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2736 Info = _WRONG_MESSAGE_FORMAT;
2737 else
2738 {
2739 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2740 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2741 {
2742 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2743 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2744 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2745 }
2746 w = fax_parms[4].length;
2747 if (w > 20)
2748 w = 20;
2749 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2750 for (i = 0; i < w; i++)
2751 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2752 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2753 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2754 w = fax_parms[5].length;
2755 if (w > 20)
2756 w = 20;
2757 plci->fax_connect_info_buffer[len++] = (byte) w;
2758 for (i = 0; i < w; i++)
2759 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2760 w = fax_parms[6].length;
2761 if (w > 20)
2762 w = 20;
2763 plci->fax_connect_info_buffer[len++] = (byte) w;
2764 for (i = 0; i < w; i++)
2765 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2766 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2767 & (1L << PRIVATE_FAX_NONSTANDARD))
2768 {
2769 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2770 {
2771 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2772 plci->fax_connect_info_buffer[len++] = 0;
2773 }
2774 else
2775 {
2776 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2777 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2778 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2779 for (i = 0; i < fax_parms[7].length; i++)
2780 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2781 }
2782 }
2783 }
2784 }
2785 else
2786 {
2787 len = offsetof(T30_INFO, universal_6);
2788 }
2789 fax_info_change = true;
2790
2791 }
2792 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2793 {
2794 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2795 fax_info_change = true;
2796 }
2797 }
2798 if (Info == GOOD)
2799 {
2800 plci->fax_connect_info_length = len;
2801 if (fax_info_change)
2802 {
2803 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2804 {
2805 start_internal_command(Id, plci, fax_connect_info_command);
2806 return false;
2807 }
2808 else
2809 {
2810 start_internal_command(Id, plci, fax_adjust_b23_command);
2811 return false;
2812 }
2813 }
2814 }
2815 }
2816 else Info = _WRONG_STATE;
2817 }
2818 else Info = _WRONG_STATE;
2819 }
2820
2821 else if (plci->B3_prot == B3_RTP)
2822 {
2823 plci->internal_req_buffer[0] = ncpi->length + 1;
2824 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2825 for (w = 0; w < ncpi->length; w++)
2826 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2827 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2828 return false;
2829 }
2830
2831 if (!Info)
2832 {
2833 nl_req_ncci(plci, req, 0);
2834 return 1;
2835 }
2836 }
2837 }
2838 else Info = _WRONG_IDENTIFIER;
2839
2840 sendf(appl,
2841 _CONNECT_B3_R | CONFIRM,
2842 Id,
2843 Number,
2844 "w", Info);
2845 return false;
2846 }
2847
2848 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2849 PLCI *plci, APPL *appl, API_PARSE *parms)
2850 {
2851 word ncci;
2852 API_PARSE *ncpi;
2853 byte req;
2854
2855 word w;
2856
2857
2858 API_PARSE fax_parms[9];
2859 word i;
2860 byte len;
2861
2862
2863 dbug(1, dprintf("connect_b3_res"));
2864
2865 ncci = (word)(Id >> 16);
2866 if (plci && ncci) {
2867 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2868 if (GET_WORD(&parms[0].info[0]) != 0)
2869 {
2870 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2871 channel_request_xon(plci, a->ncci_ch[ncci]);
2872 channel_xmit_xon(plci);
2873 cleanup_ncci_data(plci, ncci);
2874 nl_req_ncci(plci, N_DISC, (byte)ncci);
2875 return 1;
2876 }
2877 a->ncci_state[ncci] = INC_ACT_PENDING;
2878
2879 req = N_CONNECT_ACK;
2880 ncpi = &parms[1];
2881 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2882 {
2883
2884 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2885 & (1L << PRIVATE_FAX_NONSTANDARD))
2886 {
2887 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2888 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2889 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2890 {
2891 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2892 if (plci->fax_connect_info_length < len)
2893 {
2894 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2895 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2896 }
2897 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2898 {
2899 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2900 }
2901 else
2902 {
2903 if (plci->fax_connect_info_length <= len)
2904 plci->fax_connect_info_buffer[len] = 0;
2905 len += 1 + plci->fax_connect_info_buffer[len];
2906 if (plci->fax_connect_info_length <= len)
2907 plci->fax_connect_info_buffer[len] = 0;
2908 len += 1 + plci->fax_connect_info_buffer[len];
2909 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2910 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2911 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2912 for (i = 0; i < fax_parms[7].length; i++)
2913 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2914 }
2915 plci->fax_connect_info_length = len;
2916 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2917 start_internal_command(Id, plci, fax_connect_ack_command);
2918 return false;
2919 }
2920 }
2921
2922 nl_req_ncci(plci, req, (byte)ncci);
2923 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2924 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2925 {
2926 if (plci->B3_prot == 4)
2927 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2928 else
2929 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2930 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2931 }
2932 }
2933
2934 else if (plci->B3_prot == B3_RTP)
2935 {
2936 plci->internal_req_buffer[0] = ncpi->length + 1;
2937 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2938 for (w = 0; w < ncpi->length; w++)
2939 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2940 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2941 return false;
2942 }
2943
2944 else
2945 {
2946 if (ncpi->length > 2) {
2947 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2948 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2949 }
2950 nl_req_ncci(plci, req, (byte)ncci);
2951 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2952 if (plci->adjust_b_restore)
2953 {
2954 plci->adjust_b_restore = false;
2955 start_internal_command(Id, plci, adjust_b_restore);
2956 }
2957 }
2958 return 1;
2959 }
2960 }
2961 return false;
2962 }
2963
2964 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2965 PLCI *plci, APPL *appl, API_PARSE *parms)
2966 {
2967 word ncci;
2968
2969 ncci = (word)(Id >> 16);
2970 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2971
2972 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2973 && (plci->State != OUTG_DIS_PENDING))
2974 {
2975 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2976 a->ncci_state[ncci] = CONNECTED;
2977 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2978 channel_request_xon(plci, a->ncci_ch[ncci]);
2979 channel_xmit_xon(plci);
2980 }
2981 }
2982 return false;
2983 }
2984
2985 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2986 PLCI *plci, APPL *appl, API_PARSE *parms)
2987 {
2988 word Info;
2989 word ncci;
2990 API_PARSE *ncpi;
2991
2992 dbug(1, dprintf("disconnect_b3_req"));
2993
2994 Info = _WRONG_IDENTIFIER;
2995 ncci = (word)(Id >> 16);
2996 if (plci && ncci)
2997 {
2998 Info = _WRONG_STATE;
2999 if ((a->ncci_state[ncci] == CONNECTED)
3000 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3001 || (a->ncci_state[ncci] == INC_CON_PENDING)
3002 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3003 {
3004 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3005 channel_request_xon(plci, a->ncci_ch[ncci]);
3006 channel_xmit_xon(plci);
3007
3008 if (a->ncci[ncci].data_pending
3009 && ((plci->B3_prot == B3_TRANSPARENT)
3010 || (plci->B3_prot == B3_T30)
3011 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3012 {
3013 plci->send_disc = (byte)ncci;
3014 plci->command = 0;
3015 return false;
3016 }
3017 else
3018 {
3019 cleanup_ncci_data(plci, ncci);
3020
3021 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3022 {
3023 ncpi = &parms[0];
3024 if (ncpi->length > 3)
3025 {
3026 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3027 }
3028 }
3029 nl_req_ncci(plci, N_DISC, (byte)ncci);
3030 }
3031 return 1;
3032 }
3033 }
3034 sendf(appl,
3035 _DISCONNECT_B3_R | CONFIRM,
3036 Id,
3037 Number,
3038 "w", Info);
3039 return false;
3040 }
3041
3042 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3043 PLCI *plci, APPL *appl, API_PARSE *parms)
3044 {
3045 word ncci;
3046 word i;
3047
3048 ncci = (word)(Id >> 16);
3049 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3050 if (plci && ncci) {
3051 plci->requested_options_conn = 0;
3052 plci->fax_connect_info_length = 0;
3053 plci->ncpi_state = 0x00;
3054 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3055 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3056 {
3057 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3058 }
3059 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3060 if (i < MAX_CHANNELS_PER_PLCI) {
3061 if (plci->channels)plci->channels--;
3062 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3063 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3064
3065 ncci_free_receive_buffers(plci, ncci);
3066
3067 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3068 if (plci->State == SUSPENDING) {
3069 sendf(plci->appl,
3070 _FACILITY_I,
3071 Id & 0xffffL,
3072 0,
3073 "ws", (word)3, "\x03\x04\x00\x00");
3074 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3075 }
3076 plci_remove(plci);
3077 plci->State = IDLE;
3078 }
3079 }
3080 else
3081 {
3082 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3083 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3084 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3085 {
3086 ncci_free_receive_buffers(plci, ncci);
3087
3088 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3089
3090 plci->adapter->ncci_state[ncci] = IDLE;
3091 start_internal_command(Id, plci, fax_disconnect_command);
3092 return 1;
3093 }
3094 }
3095 }
3096 return false;
3097 }
3098
3099 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3100 PLCI *plci, APPL *appl, API_PARSE *parms)
3101 {
3102 NCCI *ncci_ptr;
3103 DATA_B3_DESC *data;
3104 word Info;
3105 word ncci;
3106 word i;
3107
3108 dbug(1, dprintf("data_b3_req"));
3109
3110 Info = _WRONG_IDENTIFIER;
3111 ncci = (word)(Id >> 16);
3112 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3113
3114 if (plci && ncci)
3115 {
3116 Info = _WRONG_STATE;
3117 if ((a->ncci_state[ncci] == CONNECTED)
3118 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3119 {
3120 /* queue data */
3121 ncci_ptr = &(a->ncci[ncci]);
3122 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3123 if (i >= MAX_DATA_B3)
3124 i -= MAX_DATA_B3;
3125 data = &(ncci_ptr->DBuffer[i]);
3126 data->Number = Number;
3127 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3128 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3129 {
3130
3131 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3132
3133 }
3134 else
3135 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3136 data->Length = GET_WORD(parms[1].info);
3137 data->Handle = GET_WORD(parms[2].info);
3138 data->Flags = GET_WORD(parms[3].info);
3139 (ncci_ptr->data_pending)++;
3140
3141 /* check for delivery confirmation */
3142 if (data->Flags & 0x0004)
3143 {
3144 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3145 if (i >= MAX_DATA_ACK)
3146 i -= MAX_DATA_ACK;
3147 ncci_ptr->DataAck[i].Number = data->Number;
3148 ncci_ptr->DataAck[i].Handle = data->Handle;
3149 (ncci_ptr->data_ack_pending)++;
3150 }
3151
3152 send_data(plci);
3153 return false;
3154 }
3155 }
3156 if (appl)
3157 {
3158 if (plci)
3159 {
3160 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3161 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3162 {
3163
3164 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3165
3166 }
3167 }
3168 sendf(appl,
3169 _DATA_B3_R | CONFIRM,
3170 Id,
3171 Number,
3172 "ww", GET_WORD(parms[2].info), Info);
3173 }
3174 return false;
3175 }
3176
3177 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3178 PLCI *plci, APPL *appl, API_PARSE *parms)
3179 {
3180 word n;
3181 word ncci;
3182 word NCCIcode;
3183
3184 dbug(1, dprintf("data_b3_res"));
3185
3186 ncci = (word)(Id >> 16);
3187 if (plci && ncci) {
3188 n = GET_WORD(parms[0].info);
3189 dbug(1, dprintf("free(%d)", n));
3190 NCCIcode = ncci | (((word) a->Id) << 8);
3191 if (n < appl->MaxBuffer &&
3192 appl->DataNCCI[n] == NCCIcode &&
3193 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3194 dbug(1, dprintf("found"));
3195 appl->DataNCCI[n] = 0;
3196
3197 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3198 channel_request_xon(plci, a->ncci_ch[ncci]);
3199 }
3200 channel_xmit_xon(plci);
3201
3202 if (appl->DataFlags[n] & 4) {
3203 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3204 return 1;
3205 }
3206 }
3207 }
3208 return false;
3209 }
3210
3211 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3212 PLCI *plci, APPL *appl, API_PARSE *parms)
3213 {
3214 word Info;
3215 word ncci;
3216
3217 dbug(1, dprintf("reset_b3_req"));
3218
3219 Info = _WRONG_IDENTIFIER;
3220 ncci = (word)(Id >> 16);
3221 if (plci && ncci)
3222 {
3223 Info = _WRONG_STATE;
3224 switch (plci->B3_prot)
3225 {
3226 case B3_ISO8208:
3227 case B3_X25_DCE:
3228 if (a->ncci_state[ncci] == CONNECTED)
3229 {
3230 nl_req_ncci(plci, N_RESET, (byte)ncci);
3231 send_req(plci);
3232 Info = GOOD;
3233 }
3234 break;
3235 case B3_TRANSPARENT:
3236 if (a->ncci_state[ncci] == CONNECTED)
3237 {
3238 start_internal_command(Id, plci, reset_b3_command);
3239 Info = GOOD;
3240 }
3241 break;
3242 }
3243 }
3244 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3245 sendf(appl,
3246 _RESET_B3_R | CONFIRM,
3247 Id,
3248 Number,
3249 "w", Info);
3250 return false;
3251 }
3252
3253 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3254 PLCI *plci, APPL *appl, API_PARSE *parms)
3255 {
3256 word ncci;
3257
3258 dbug(1, dprintf("reset_b3_res"));
3259
3260 ncci = (word)(Id >> 16);
3261 if (plci && ncci) {
3262 switch (plci->B3_prot)
3263 {
3264 case B3_ISO8208:
3265 case B3_X25_DCE:
3266 if (a->ncci_state[ncci] == INC_RES_PENDING)
3267 {
3268 a->ncci_state[ncci] = CONNECTED;
3269 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3270 return true;
3271 }
3272 break;
3273 }
3274 }
3275 return false;
3276 }
3277
3278 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3279 PLCI *plci, APPL *appl, API_PARSE *parms)
3280 {
3281 word ncci;
3282 API_PARSE *ncpi;
3283 byte req;
3284
3285 dbug(1, dprintf("connect_b3_t90_a_res"));
3286
3287 ncci = (word)(Id >> 16);
3288 if (plci && ncci) {
3289 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3290 a->ncci_state[ncci] = CONNECTED;
3291 }
3292 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3293 a->ncci_state[ncci] = CONNECTED;
3294
3295 req = N_CONNECT_ACK;
3296
3297 /* parms[0]==0 for CAPI original message definition! */
3298 if (parms[0].info) {
3299 ncpi = &parms[1];
3300 if (ncpi->length > 2) {
3301 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3302 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3303 }
3304 }
3305 nl_req_ncci(plci, req, (byte)ncci);
3306 return 1;
3307 }
3308 }
3309 return false;
3310 }
3311
3312
3313 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3314 PLCI *plci, APPL *appl, API_PARSE *msg)
3315 {
3316 word Info = 0;
3317 word i;
3318 byte tel;
3319 API_PARSE bp_parms[7];
3320
3321 if (!plci || !msg)
3322 {
3323 Info = _WRONG_IDENTIFIER;
3324 }
3325 else
3326 {
3327 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3328 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3329 dbug(1, dprintf("PlciState=0x%x", plci->State));
3330 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3331
3332 /* check if no channel is open, no B3 connected only */
3333 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3334 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3335 {
3336 Info = _WRONG_STATE;
3337 }
3338 /* check message format and fill bp_parms pointer */
3339 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3340 {
3341 Info = _WRONG_MESSAGE_FORMAT;
3342 }
3343 else
3344 {
3345 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3346 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3347 if (Id & EXT_CONTROLLER)
3348 {
3349 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3350 return 0;
3351 }
3352 plci->State = INC_CON_CONNECTED_ALERT;
3353 plci->appl = appl;
3354 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3355 dump_c_ind_mask(plci);
3356 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3357 { /* its quasi a connect */
3358 if (test_c_ind_mask_bit(plci, i))
3359 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3360 }
3361 }
3362
3363 api_save_msg(msg, "s", &plci->saved_msg);
3364 tel = plci->tel;
3365 if (Id & EXT_CONTROLLER)
3366 {
3367 if (tel) /* external controller in use by this PLCI */
3368 {
3369 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3370 {
3371 dbug(1, dprintf("Ext_Ctrl in use 1"));
3372 Info = _WRONG_STATE;
3373 }
3374 }
3375 else /* external controller NOT in use by this PLCI ? */
3376 {
3377 if (a->AdvSignalPLCI)
3378 {
3379 dbug(1, dprintf("Ext_Ctrl in use 2"));
3380 Info = _WRONG_STATE;
3381 }
3382 else /* activate the codec */
3383 {
3384 dbug(1, dprintf("Ext_Ctrl start"));
3385 if (AdvCodecSupport(a, plci, appl, 0))
3386 {
3387 dbug(1, dprintf("Error in codec procedures"));
3388 Info = _WRONG_STATE;
3389 }
3390 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3391 {
3392 plci->spoofed_msg = AWAITING_SELECT_B;
3393 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3394 plci->command = 0;
3395 dbug(1, dprintf("continue if codec loaded"));
3396 return false;
3397 }
3398 }
3399 }
3400 }
3401 else /* external controller bit is OFF */
3402 {
3403 if (tel) /* external controller in use, need to switch off */
3404 {
3405 if (a->AdvSignalAppl == appl)
3406 {
3407 CodecIdCheck(a, plci);
3408 plci->tel = 0;
3409 plci->adv_nl = 0;
3410 dbug(1, dprintf("Ext_Ctrl disable"));
3411 }
3412 else
3413 {
3414 dbug(1, dprintf("Ext_Ctrl not requested"));
3415 }
3416 }
3417 }
3418 if (!Info)
3419 {
3420 if (plci->call_dir & CALL_DIR_OUT)
3421 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3422 else if (plci->call_dir & CALL_DIR_IN)
3423 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3424 start_internal_command(Id, plci, select_b_command);
3425 return false;
3426 }
3427 }
3428 }
3429 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3430 return false;
3431 }
3432
3433 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3434 PLCI *plci, APPL *appl, API_PARSE *parms)
3435 {
3436 word command;
3437 word i;
3438 word ncci;
3439 API_PARSE *m;
3440 API_PARSE m_parms[5];
3441 word codec;
3442 byte req;
3443 byte ch;
3444 byte dir;
3445 static byte chi[2] = {0x01, 0x00};
3446 static byte lli[2] = {0x01, 0x00};
3447 static byte codec_cai[2] = {0x01, 0x01};
3448 static byte null_msg = {0};
3449 static API_PARSE null_parms = { 0, &null_msg };
3450 PLCI *v_plci;
3451 word Info = 0;
3452
3453 dbug(1, dprintf("manufacturer_req"));
3454 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3455
3456 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3457 Info = _WRONG_MESSAGE_FORMAT;
3458 }
3459 command = GET_WORD(parms[1].info);
3460 m = &parms[2];
3461 if (!Info)
3462 {
3463 switch (command) {
3464 case _DI_ASSIGN_PLCI:
3465 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3466 Info = _WRONG_MESSAGE_FORMAT;
3467 break;
3468 }
3469 codec = GET_WORD(m_parms[0].info);
3470 ch = m_parms[1].info[0];
3471 dir = m_parms[2].info[0];
3472 if ((i = get_plci(a))) {
3473 plci = &a->plci[i - 1];
3474 plci->appl = appl;
3475 plci->command = _MANUFACTURER_R;
3476 plci->m_command = command;
3477 plci->number = Number;
3478 plci->State = LOCAL_CONNECT;
3479 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3480 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3481
3482 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3483 chi[1] = (byte)(0x80 | ch);
3484 lli[1] = 0;
3485 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3486 switch (codec)
3487 {
3488 case 0:
3489 Info = add_b1(plci, &m_parms[3], 0, 0);
3490 break;
3491 case 1:
3492 add_p(plci, CAI, codec_cai);
3493 break;
3494 /* manual 'swich on' to the codec support without signalling */
3495 /* first 'assign plci' with this function, then use */
3496 case 2:
3497 if (AdvCodecSupport(a, plci, appl, 0)) {
3498 Info = _RESOURCE_ERROR;
3499 }
3500 else {
3501 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3502 lli[1] = 0x10; /* local call codec stream */
3503 }
3504 break;
3505 }
3506
3507 plci->State = LOCAL_CONNECT;
3508 plci->manufacturer = true;
3509 plci->command = _MANUFACTURER_R;
3510 plci->m_command = command;
3511 plci->number = Number;
3512
3513 if (!Info)
3514 {
3515 add_p(plci, LLI, lli);
3516 add_p(plci, CHI, chi);
3517 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3518 sig_req(plci, ASSIGN, DSIG_ID);
3519
3520 if (!codec)
3521 {
3522 Info = add_b23(plci, &m_parms[3]);
3523 if (!Info)
3524 {
3525 nl_req_ncci(plci, ASSIGN, 0);
3526 send_req(plci);
3527 }
3528 }
3529 if (!Info)
3530 {
3531 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3532 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3533 {
3534 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3535 plci->spoofed_msg = AWAITING_MANUF_CON;
3536 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3537 plci->command = 0;
3538 send_req(plci);
3539 return false;
3540 }
3541 if (dir == 1) {
3542 sig_req(plci, CALL_REQ, 0);
3543 }
3544 else if (!dir) {
3545 sig_req(plci, LISTEN_REQ, 0);
3546 }
3547 send_req(plci);
3548 }
3549 else
3550 {
3551 sendf(appl,
3552 _MANUFACTURER_R | CONFIRM,
3553 Id,
3554 Number,
3555 "dww", _DI_MANU_ID, command, Info);
3556 return 2;
3557 }
3558 }
3559 }
3560 }
3561 else Info = _OUT_OF_PLCI;
3562 break;
3563
3564 case _DI_IDI_CTRL:
3565 if (!plci)
3566 {
3567 Info = _WRONG_IDENTIFIER;
3568 break;
3569 }
3570 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3571 Info = _WRONG_MESSAGE_FORMAT;
3572 break;
3573 }
3574 req = m_parms[0].info[0];
3575 plci->command = _MANUFACTURER_R;
3576 plci->m_command = command;
3577 plci->number = Number;
3578 if (req == CALL_REQ)
3579 {
3580 plci->b_channel = getChannel(&m_parms[1]);
3581 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3582 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3583 {
3584 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3585 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3586 plci->command = 0;
3587 break;
3588 }
3589 }
3590 else if (req == LAW_REQ)
3591 {
3592 plci->cr_enquiry = true;
3593 }
3594 add_ss(plci, FTY, &m_parms[1]);
3595 sig_req(plci, req, 0);
3596 send_req(plci);
3597 if (req == HANGUP)
3598 {
3599 if (plci->NL.Id && !plci->nl_remove_id)
3600 {
3601 if (plci->channels)
3602 {
3603 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3604 {
3605 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3606 {
3607 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3608 cleanup_ncci_data(plci, ncci);
3609 nl_req_ncci(plci, N_DISC, (byte)ncci);
3610 }
3611 }
3612 }
3613 mixer_remove(plci);
3614 nl_req_ncci(plci, REMOVE, 0);
3615 send_req(plci);
3616 }
3617 }
3618 break;
3619
3620 case _DI_SIG_CTRL:
3621 /* signalling control for loop activation B-channel */
3622 if (!plci)
3623 {
3624 Info = _WRONG_IDENTIFIER;
3625 break;
3626 }
3627 if (m->length) {
3628 plci->command = _MANUFACTURER_R;
3629 plci->number = Number;
3630 add_ss(plci, FTY, m);
3631 sig_req(plci, SIG_CTRL, 0);
3632 send_req(plci);
3633 }
3634 else Info = _WRONG_MESSAGE_FORMAT;
3635 break;
3636
3637 case _DI_RXT_CTRL:
3638 /* activation control for receiver/transmitter B-channel */
3639 if (!plci)
3640 {
3641 Info = _WRONG_IDENTIFIER;
3642 break;
3643 }
3644 if (m->length) {
3645 plci->command = _MANUFACTURER_R;
3646 plci->number = Number;
3647 add_ss(plci, FTY, m);
3648 sig_req(plci, DSP_CTRL, 0);
3649 send_req(plci);
3650 }
3651 else Info = _WRONG_MESSAGE_FORMAT;
3652 break;
3653
3654 case _DI_ADV_CODEC:
3655 case _DI_DSP_CTRL:
3656 /* TEL_CTRL commands to support non standard adjustments: */
3657 /* Ring on/off, Handset micro volume, external micro vol. */
3658 /* handset+external speaker volume, receiver+transm. gain,*/
3659 /* handsfree on (hookinfo off), set mixer command */
3660
3661 if (command == _DI_ADV_CODEC)
3662 {
3663 if (!a->AdvCodecPLCI) {
3664 Info = _WRONG_STATE;
3665 break;
3666 }
3667 v_plci = a->AdvCodecPLCI;
3668 }
3669 else
3670 {
3671 if (plci
3672 && (m->length >= 3)
3673 && (m->info[1] == 0x1c)
3674 && (m->info[2] >= 1))
3675 {
3676 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3677 {
3678 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3679 {
3680 Info = _WRONG_STATE;
3681 break;
3682 }
3683 a->adv_voice_coef_length = m->info[2] - 1;
3684 if (a->adv_voice_coef_length > m->length - 3)
3685 a->adv_voice_coef_length = (byte)(m->length - 3);
3686 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3687 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3688 for (i = 0; i < a->adv_voice_coef_length; i++)
3689 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3690 if (plci->B1_facilities & B1_FACILITY_VOICE)
3691 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3692 break;
3693 }
3694 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3695 {
3696 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3697 {
3698 Info = _FACILITY_NOT_SUPPORTED;
3699 break;
3700 }
3701
3702 plci->dtmf_parameter_length = m->info[2] - 1;
3703 if (plci->dtmf_parameter_length > m->length - 3)
3704 plci->dtmf_parameter_length = (byte)(m->length - 3);
3705 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3706 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3707 for (i = 0; i < plci->dtmf_parameter_length; i++)
3708 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3709 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3710 dtmf_parameter_write(plci);
3711 break;
3712
3713 }
3714 }
3715 v_plci = plci;
3716 }
3717
3718 if (!v_plci)
3719 {
3720 Info = _WRONG_IDENTIFIER;
3721 break;
3722 }
3723 if (m->length) {
3724 add_ss(v_plci, FTY, m);
3725 sig_req(v_plci, TEL_CTRL, 0);
3726 send_req(v_plci);
3727 }
3728 else Info = _WRONG_MESSAGE_FORMAT;
3729
3730 break;
3731
3732 case _DI_OPTIONS_REQUEST:
3733 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3734 Info = _WRONG_MESSAGE_FORMAT;
3735 break;
3736 }
3737 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3738 {
3739 Info = _FACILITY_NOT_SUPPORTED;
3740 break;
3741 }
3742 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3743 break;
3744
3745
3746
3747 default:
3748 Info = _WRONG_MESSAGE_FORMAT;
3749 break;
3750 }
3751 }
3752
3753 sendf(appl,
3754 _MANUFACTURER_R | CONFIRM,
3755 Id,
3756 Number,
3757 "dww", _DI_MANU_ID, command, Info);
3758 return false;
3759 }
3760
3761
3762 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3763 PLCI *plci, APPL *appl, API_PARSE *msg)
3764 {
3765 word indication;
3766
3767 API_PARSE m_parms[3];
3768 API_PARSE *ncpi;
3769 API_PARSE fax_parms[9];
3770 word i;
3771 byte len;
3772
3773
3774 dbug(1, dprintf("manufacturer_res"));
3775
3776 if ((msg[0].length == 0)
3777 || (msg[1].length == 0)
3778 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3779 {
3780 return false;
3781 }
3782 indication = GET_WORD(msg[1].info);
3783 switch (indication)
3784 {
3785
3786 case _DI_NEGOTIATE_B3:
3787 if (!plci)
3788 break;
3789 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3790 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3791 {
3792 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3793 break;
3794 }
3795 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3796 {
3797 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3798 break;
3799 }
3800 ncpi = &m_parms[1];
3801 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3802 if (plci->fax_connect_info_length < len)
3803 {
3804 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3805 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3806 }
3807 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3808 {
3809 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3810 }
3811 else
3812 {
3813 if (plci->fax_connect_info_length <= len)
3814 plci->fax_connect_info_buffer[len] = 0;
3815 len += 1 + plci->fax_connect_info_buffer[len];
3816 if (plci->fax_connect_info_length <= len)
3817 plci->fax_connect_info_buffer[len] = 0;
3818 len += 1 + plci->fax_connect_info_buffer[len];
3819 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3820 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3821 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3822 for (i = 0; i < fax_parms[7].length; i++)
3823 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3824 }
3825 plci->fax_connect_info_length = len;
3826 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3827 start_internal_command(Id, plci, fax_edata_ack_command);
3828 break;
3829
3830 }
3831 return false;
3832 }
3833
3834 /*------------------------------------------------------------------*/
3835 /* IDI callback function */
3836 /*------------------------------------------------------------------*/
3837
3838 void callback(ENTITY *e)
3839 {
3840 DIVA_CAPI_ADAPTER *a;
3841 APPL *appl;
3842 PLCI *plci;
3843 CAPI_MSG *m;
3844 word i, j;
3845 byte rc;
3846 byte ch;
3847 byte req;
3848 byte global_req;
3849 int no_cancel_rc;
3850
3851 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3852 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3853
3854 a = &(adapter[(byte)e->user[0]]);
3855 plci = &(a->plci[e->user[1]]);
3856 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3857
3858 /*
3859 If new protocol code and new XDI is used then CAPI should work
3860 fully in accordance with IDI cpec an look on callback field instead
3861 of Rc field for return codes.
3862 */
3863 if (((e->complete == 0xff) && no_cancel_rc) ||
3864 (e->Rc && !no_cancel_rc)) {
3865 rc = e->Rc;
3866 ch = e->RcCh;
3867 req = e->Req;
3868 e->Rc = 0;
3869
3870 if (e->user[0] & 0x8000)
3871 {
3872 /*
3873 If REMOVE request was sent then we have to wait until
3874 return code with Id set to zero arrives.
3875 All other return codes should be ignored.
3876 */
3877 if (req == REMOVE)
3878 {
3879 if (e->Id)
3880 {
3881 dbug(1, dprintf("cancel RC in REMOVE state"));
3882 return;
3883 }
3884 channel_flow_control_remove(plci);
3885 for (i = 0; i < 256; i++)
3886 {
3887 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3888 a->FlowControlIdTable[i] = 0;
3889 }
3890 plci->nl_remove_id = 0;
3891 if (plci->rx_dma_descriptor > 0) {
3892 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3893 plci->rx_dma_descriptor = 0;
3894 }
3895 }
3896 if (rc == OK_FC)
3897 {
3898 a->FlowControlIdTable[ch] = e->Id;
3899 a->FlowControlSkipTable[ch] = 0;
3900
3901 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3902 a->ch_flow_plci[ch] = plci->Id;
3903 plci->nl_req = 0;
3904 }
3905 else
3906 {
3907 /*
3908 Cancel return codes self, if feature was requested
3909 */
3910 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3911 a->FlowControlIdTable[ch] = 0;
3912 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3913 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3914 return;
3915 }
3916 }
3917
3918 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3919 {
3920 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3921 if (ch == e->ReqCh)
3922 plci->nl_req = 0;
3923 }
3924 else
3925 plci->nl_req = 0;
3926 }
3927 if (plci->nl_req)
3928 control_rc(plci, 0, rc, ch, 0, true);
3929 else
3930 {
3931 if (req == N_XON)
3932 {
3933 channel_x_on(plci, ch);
3934 if (plci->internal_command)
3935 control_rc(plci, req, rc, ch, 0, true);
3936 }
3937 else
3938 {
3939 if (plci->nl_global_req)
3940 {
3941 global_req = plci->nl_global_req;
3942 plci->nl_global_req = 0;
3943 if (rc != ASSIGN_OK) {
3944 e->Id = 0;
3945 if (plci->rx_dma_descriptor > 0) {
3946 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3947 plci->rx_dma_descriptor = 0;
3948 }
3949 }
3950 channel_xmit_xon(plci);
3951 control_rc(plci, 0, rc, ch, global_req, true);
3952 }
3953 else if (plci->data_sent)
3954 {
3955 channel_xmit_xon(plci);
3956 plci->data_sent = false;
3957 plci->NL.XNum = 1;
3958 data_rc(plci, ch);
3959 if (plci->internal_command)
3960 control_rc(plci, req, rc, ch, 0, true);
3961 }
3962 else
3963 {
3964 channel_xmit_xon(plci);
3965 control_rc(plci, req, rc, ch, 0, true);
3966 }
3967 }
3968 }
3969 }
3970 else
3971 {
3972 /*
3973 If REMOVE request was sent then we have to wait until
3974 return code with Id set to zero arrives.
3975 All other return codes should be ignored.
3976 */
3977 if (req == REMOVE)
3978 {
3979 if (e->Id)
3980 {
3981 dbug(1, dprintf("cancel RC in REMOVE state"));
3982 return;
3983 }
3984 plci->sig_remove_id = 0;
3985 }
3986 plci->sig_req = 0;
3987 if (plci->sig_global_req)
3988 {
3989 global_req = plci->sig_global_req;
3990 plci->sig_global_req = 0;
3991 if (rc != ASSIGN_OK)
3992 e->Id = 0;
3993 channel_xmit_xon(plci);
3994 control_rc(plci, 0, rc, ch, global_req, false);
3995 }
3996 else
3997 {
3998 channel_xmit_xon(plci);
3999 control_rc(plci, req, rc, ch, 0, false);
4000 }
4001 }
4002 /*
4003 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4004 same callback. Also if new XDI and protocol code used then jump
4005 direct to finish.
4006 */
4007 if (no_cancel_rc) {
4008 channel_xmit_xon(plci);
4009 goto capi_callback_suffix;
4010 }
4011 }
4012
4013 channel_xmit_xon(plci);
4014
4015 if (e->Ind) {
4016 if (e->user[0] & 0x8000) {
4017 byte Ind = e->Ind & 0x0f;
4018 byte Ch = e->IndCh;
4019 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4020 (a->ch_flow_plci[Ch] == plci->Id)) {
4021 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4022 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4023 }
4024 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4025 }
4026 nl_ind(plci);
4027 if ((e->RNR != 1) &&
4028 (a->ch_flow_plci[Ch] == plci->Id) &&
4029 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4030 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4031 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4032 }
4033 } else {
4034 sig_ind(plci);
4035 }
4036 e->Ind = 0;
4037 }
4038
4039 capi_callback_suffix:
4040
4041 while (!plci->req_in
4042 && !plci->internal_command
4043 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4044 {
4045 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4046
4047 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4048
4049 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4050 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4051 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4052 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4053 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4054 {
4055 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4056 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4057 }
4058 else
4059 {
4060 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4061 }
4062 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4063 {
4064 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4065 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4066 }
4067 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4068 {
4069 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4071 }
4072 i = api_put(appl, m);
4073 if (i != 0)
4074 {
4075 if (m->header.command == _DATA_B3_R)
4076
4077 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4078
4079 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4080 break;
4081 }
4082
4083 if (plci->li_notify_update)
4084 {
4085 plci->li_notify_update = false;
4086 mixer_notify_update(plci, false);
4087 }
4088
4089 }
4090 send_data(plci);
4091 send_req(plci);
4092 }
4093
4094
4095 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4096 byte nl_rc)
4097 {
4098 dword Id;
4099 dword rId;
4100 word Number;
4101 word Info = 0;
4102 word i;
4103 word ncci;
4104 DIVA_CAPI_ADAPTER *a;
4105 APPL *appl;
4106 PLCI *rplci;
4107 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4108 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4109
4110 if (!plci) {
4111 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4112 return;
4113 }
4114 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4115 if (plci->req_in != plci->req_out)
4116 {
4117 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4118 {
4119 dbug(1, dprintf("req_1return"));
4120 return;
4121 }
4122 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4123 }
4124 plci->req_in = plci->req_in_start = plci->req_out = 0;
4125 dbug(1, dprintf("control_rc"));
4126
4127 appl = plci->appl;
4128 a = plci->adapter;
4129 ncci = a->ch_ncci[ch];
4130 if (appl)
4131 {
4132 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4133 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4134 Number = plci->number;
4135 dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4136 dbug(1, dprintf("channels=0x%x", plci->channels));
4137 if (plci_remove_check(plci))
4138 return;
4139 if (req == REMOVE && rc == ASSIGN_OK)
4140 {
4141 sig_req(plci, HANGUP, 0);
4142 sig_req(plci, REMOVE, 0);
4143 send_req(plci);
4144 }
4145 if (plci->command)
4146 {
4147 switch (plci->command)
4148 {
4149 case C_HOLD_REQ:
4150 dbug(1, dprintf("HoldRC=0x%x", rc));
4151 SSparms[1] = (byte)S_HOLD;
4152 if (rc != OK)
4153 {
4154 plci->SuppState = IDLE;
4155 Info = 0x2001;
4156 }
4157 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4158 break;
4159
4160 case C_RETRIEVE_REQ:
4161 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4162 SSparms[1] = (byte)S_RETRIEVE;
4163 if (rc != OK)
4164 {
4165 plci->SuppState = CALL_HELD;
4166 Info = 0x2001;
4167 }
4168 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4169 break;
4170
4171 case _INFO_R:
4172 dbug(1, dprintf("InfoRC=0x%x", rc));
4173 if (rc != OK) Info = _WRONG_STATE;
4174 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4175 break;
4176
4177 case _CONNECT_R:
4178 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4179 if (plci->State == INC_DIS_PENDING)
4180 break;
4181 if (plci->Sig.Id != 0xff)
4182 {
4183 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4184 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4185 {
4186 dbug(1, dprintf("No more IDs/Call_Req failed"));
4187 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4188 plci_remove(plci);
4189 plci->State = IDLE;
4190 break;
4191 }
4192 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4193 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4194 }
4195 else /* D-ch activation */
4196 {
4197 if (rc != ASSIGN_OK)
4198 {
4199 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4200 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4201 plci_remove(plci);
4202 plci->State = IDLE;
4203 break;
4204 }
4205 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4206 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4207 plci->State = INC_ACT_PENDING;
4208 }
4209 break;
4210
4211 case _CONNECT_I | RESPONSE:
4212 if (plci->State != INC_DIS_PENDING)
4213 plci->State = INC_CON_ACCEPT;
4214 break;
4215
4216 case _DISCONNECT_R:
4217 if (plci->State == INC_DIS_PENDING)
4218 break;
4219 if (plci->Sig.Id != 0xff)
4220 {
4221 plci->State = OUTG_DIS_PENDING;
4222 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4223 }
4224 break;
4225
4226 case SUSPEND_REQ:
4227 break;
4228
4229 case RESUME_REQ:
4230 break;
4231
4232 case _CONNECT_B3_R:
4233 if (rc != OK)
4234 {
4235 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4236 break;
4237 }
4238 ncci = get_ncci(plci, ch, 0);
4239 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4240 plci->channels++;
4241 if (req == N_RESET)
4242 {
4243 a->ncci_state[ncci] = INC_ACT_PENDING;
4244 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4245 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4246 }
4247 else
4248 {
4249 a->ncci_state[ncci] = OUTG_CON_PENDING;
4250 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4251 }
4252 break;
4253
4254 case _CONNECT_B3_I | RESPONSE:
4255 break;
4256
4257 case _RESET_B3_R:
4258 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4259 break;
4260
4261 case _DISCONNECT_B3_R:
4262 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4263 break;
4264
4265 case _MANUFACTURER_R:
4266 break;
4267
4268 case PERM_LIST_REQ:
4269 if (rc != OK)
4270 {
4271 Info = _WRONG_IDENTIFIER;
4272 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4273 plci_remove(plci);
4274 }
4275 else
4276 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4277 break;
4278
4279 default:
4280 break;
4281 }
4282 plci->command = 0;
4283 }
4284 else if (plci->internal_command)
4285 {
4286 switch (plci->internal_command)
4287 {
4288 case BLOCK_PLCI:
4289 return;
4290
4291 case GET_MWI_STATE:
4292 if (rc == OK) /* command supported, wait for indication */
4293 {
4294 return;
4295 }
4296 plci_remove(plci);
4297 break;
4298
4299 /* Get Supported Services */
4300 case GETSERV_REQ_PEND:
4301 if (rc == OK) /* command supported, wait for indication */
4302 {
4303 break;
4304 }
4305 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4306 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4307 plci_remove(plci);
4308 break;
4309
4310 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4311 case INTERR_NUMBERS_REQ_PEND:
4312 case CF_START_PEND: /* Call Forwarding Start pending */
4313 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4314 case CCBS_REQUEST_REQ_PEND:
4315 case CCBS_DEACTIVATE_REQ_PEND:
4316 case CCBS_INTERROGATE_REQ_PEND:
4317 switch (plci->internal_command)
4318 {
4319 case INTERR_DIVERSION_REQ_PEND:
4320 SSparms[1] = S_INTERROGATE_DIVERSION;
4321 break;
4322 case INTERR_NUMBERS_REQ_PEND:
4323 SSparms[1] = S_INTERROGATE_NUMBERS;
4324 break;
4325 case CF_START_PEND:
4326 SSparms[1] = S_CALL_FORWARDING_START;
4327 break;
4328 case CF_STOP_PEND:
4329 SSparms[1] = S_CALL_FORWARDING_STOP;
4330 break;
4331 case CCBS_REQUEST_REQ_PEND:
4332 SSparms[1] = S_CCBS_REQUEST;
4333 break;
4334 case CCBS_DEACTIVATE_REQ_PEND:
4335 SSparms[1] = S_CCBS_DEACTIVATE;
4336 break;
4337 case CCBS_INTERROGATE_REQ_PEND:
4338 SSparms[1] = S_CCBS_INTERROGATE;
4339 break;
4340 }
4341 if (global_req == ASSIGN)
4342 {
4343 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4344 return;
4345 }
4346 if (!plci->appl) break;
4347 if (rc == ISDN_GUARD_REJ)
4348 {
4349 Info = _CAPI_GUARD_ERROR;
4350 }
4351 else if (rc != OK)
4352 {
4353 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4354 }
4355 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4356 plci->number, "wws", Info, (word)3, SSparms);
4357 if (Info) plci_remove(plci);
4358 break;
4359
4360 /* 3pty conference pending */
4361 case PTY_REQ_PEND:
4362 if (!plci->relatedPTYPLCI) break;
4363 rplci = plci->relatedPTYPLCI;
4364 SSparms[1] = plci->ptyState;
4365 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4366 if (rplci->tel) rId |= EXT_CONTROLLER;
4367 if (rc != OK)
4368 {
4369 Info = 0x300E; /* not supported */
4370 plci->relatedPTYPLCI = NULL;
4371 plci->ptyState = 0;
4372 }
4373 sendf(rplci->appl,
4374 _FACILITY_R | CONFIRM,
4375 rId,
4376 plci->number,
4377 "wws", Info, (word)3, SSparms);
4378 break;
4379
4380 /* Explicit Call Transfer pending */
4381 case ECT_REQ_PEND:
4382 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4383 if (!plci->relatedPTYPLCI) break;
4384 rplci = plci->relatedPTYPLCI;
4385 SSparms[1] = S_ECT;
4386 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4387 if (rplci->tel) rId |= EXT_CONTROLLER;
4388 if (rc != OK)
4389 {
4390 Info = 0x300E; /* not supported */
4391 plci->relatedPTYPLCI = NULL;
4392 plci->ptyState = 0;
4393 }
4394 sendf(rplci->appl,
4395 _FACILITY_R | CONFIRM,
4396 rId,
4397 plci->number,
4398 "wws", Info, (word)3, SSparms);
4399 break;
4400
4401 case _MANUFACTURER_R:
4402 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4403 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4404 {
4405 dbug(1, dprintf("No more IDs"));
4406 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4407 plci_remove(plci); /* after codec init, internal codec commands pending */
4408 }
4409 break;
4410
4411 case _CONNECT_R:
4412 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4413 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4414 {
4415 dbug(1, dprintf("No more IDs"));
4416 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4417 plci_remove(plci); /* after codec init, internal codec commands pending */
4418 }
4419 break;
4420
4421 case PERM_COD_HOOK: /* finished with Hook_Ind */
4422 return;
4423
4424 case PERM_COD_CALL:
4425 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4426 plci->internal_command = PERM_COD_CONN_PEND;
4427 return;
4428
4429 case PERM_COD_ASSIGN:
4430 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4431 if (rc != ASSIGN_OK) break;
4432 sig_req(plci, CALL_REQ, 0);
4433 send_req(plci);
4434 plci->internal_command = PERM_COD_CALL;
4435 return;
4436
4437 /* Null Call Reference Request pending */
4438 case C_NCR_FAC_REQ:
4439 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4440 if (global_req == ASSIGN)
4441 {
4442 if (rc == ASSIGN_OK)
4443 {
4444 return;
4445 }
4446 else
4447 {
4448 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4449 appl->NullCREnable = false;
4450 plci_remove(plci);
4451 }
4452 }
4453 else if (req == NCR_FACILITY)
4454 {
4455 if (rc == OK)
4456 {
4457 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4458 }
4459 else
4460 {
4461 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4462 appl->NullCREnable = false;
4463 }
4464 plci_remove(plci);
4465 }
4466 break;
4467
4468 case HOOK_ON_REQ:
4469 if (plci->channels)
4470 {
4471 if (a->ncci_state[ncci] == CONNECTED)
4472 {
4473 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4474 cleanup_ncci_data(plci, ncci);
4475 nl_req_ncci(plci, N_DISC, (byte)ncci);
4476 }
4477 break;
4478 }
4479 break;
4480
4481 case HOOK_OFF_REQ:
4482 if (plci->State == INC_DIS_PENDING)
4483 break;
4484 sig_req(plci, CALL_REQ, 0);
4485 send_req(plci);
4486 plci->State = OUTG_CON_PENDING;
4487 break;
4488
4489
4490 case MWI_ACTIVATE_REQ_PEND:
4491 case MWI_DEACTIVATE_REQ_PEND:
4492 if (global_req == ASSIGN && rc == ASSIGN_OK)
4493 {
4494 dbug(1, dprintf("MWI_REQ assigned"));
4495 return;
4496 }
4497 else if (rc != OK)
4498 {
4499 if (rc == WRONG_IE)
4500 {
4501 Info = 0x2007; /* Illegal message parameter coding */
4502 dbug(1, dprintf("MWI_REQ invalid parameter"));
4503 }
4504 else
4505 {
4506 Info = 0x300B; /* not supported */
4507 dbug(1, dprintf("MWI_REQ not supported"));
4508 }
4509 /* 0x3010: Request not allowed in this state */
4510 PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4511
4512 }
4513 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4514 {
4515 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4516 }
4517 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4518
4519 if (plci->cr_enquiry)
4520 {
4521 sendf(plci->appl,
4522 _FACILITY_R | CONFIRM,
4523 Id & 0xf,
4524 plci->number,
4525 "wws", Info, (word)3, SSparms);
4526 if (rc != OK) plci_remove(plci);
4527 }
4528 else
4529 {
4530 sendf(plci->appl,
4531 _FACILITY_R | CONFIRM,
4532 Id,
4533 plci->number,
4534 "wws", Info, (word)3, SSparms);
4535 }
4536 break;
4537
4538 case CONF_BEGIN_REQ_PEND:
4539 case CONF_ADD_REQ_PEND:
4540 case CONF_SPLIT_REQ_PEND:
4541 case CONF_DROP_REQ_PEND:
4542 case CONF_ISOLATE_REQ_PEND:
4543 case CONF_REATTACH_REQ_PEND:
4544 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4545 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4546 rplci = plci;
4547 rId = Id;
4548 switch (plci->internal_command)
4549 {
4550 case CONF_BEGIN_REQ_PEND:
4551 SSparms[1] = S_CONF_BEGIN;
4552 break;
4553 case CONF_ADD_REQ_PEND:
4554 SSparms[1] = S_CONF_ADD;
4555 rplci = plci->relatedPTYPLCI;
4556 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4557 break;
4558 case CONF_SPLIT_REQ_PEND:
4559 SSparms[1] = S_CONF_SPLIT;
4560 break;
4561 case CONF_DROP_REQ_PEND:
4562 SSparms[1] = S_CONF_DROP;
4563 break;
4564 case CONF_ISOLATE_REQ_PEND:
4565 SSparms[1] = S_CONF_ISOLATE;
4566 break;
4567 case CONF_REATTACH_REQ_PEND:
4568 SSparms[1] = S_CONF_REATTACH;
4569 break;
4570 }
4571
4572 if (rc != OK)
4573 {
4574 Info = 0x300E; /* not supported */
4575 plci->relatedPTYPLCI = NULL;
4576 plci->ptyState = 0;
4577 }
4578 sendf(rplci->appl,
4579 _FACILITY_R | CONFIRM,
4580 rId,
4581 plci->number,
4582 "wws", Info, (word)3, SSparms);
4583 break;
4584
4585 case VSWITCH_REQ_PEND:
4586 if (rc != OK)
4587 {
4588 if (plci->relatedPTYPLCI)
4589 {
4590 plci->relatedPTYPLCI->vswitchstate = 0;
4591 plci->relatedPTYPLCI->vsprot = 0;
4592 plci->relatedPTYPLCI->vsprotdialect = 0;
4593 }
4594 plci->vswitchstate = 0;
4595 plci->vsprot = 0;
4596 plci->vsprotdialect = 0;
4597 }
4598 else
4599 {
4600 if (plci->relatedPTYPLCI &&
4601 plci->vswitchstate == 1 &&
4602 plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4603 plci->vswitchstate = 3;
4604 }
4605 break;
4606
4607 /* Call Deflection Request pending (SSCT) */
4608 case CD_REQ_PEND:
4609 SSparms[1] = S_CALL_DEFLECTION;
4610 if (rc != OK)
4611 {
4612 Info = 0x300E; /* not supported */
4613 plci->appl->CDEnable = 0;
4614 }
4615 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4616 plci->number, "wws", Info, (word)3, SSparms);
4617 break;
4618
4619 case RTP_CONNECT_B3_REQ_COMMAND_2:
4620 if (rc == OK)
4621 {
4622 ncci = get_ncci(plci, ch, 0);
4623 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4624 plci->channels++;
4625 a->ncci_state[ncci] = OUTG_CON_PENDING;
4626 }
4627
4628 default:
4629 if (plci->internal_command_queue[0])
4630 {
4631 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4632 if (plci->internal_command)
4633 return;
4634 }
4635 break;
4636 }
4637 next_internal_command(Id, plci);
4638 }
4639 }
4640 else /* appl==0 */
4641 {
4642 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4643 if (plci->tel) Id |= EXT_CONTROLLER;
4644
4645 switch (plci->internal_command)
4646 {
4647 case BLOCK_PLCI:
4648 return;
4649
4650 case START_L1_SIG_ASSIGN_PEND:
4651 case REM_L1_SIG_ASSIGN_PEND:
4652 if (global_req == ASSIGN)
4653 {
4654 break;
4655 }
4656 else
4657 {
4658 dbug(1, dprintf("***L1 Req rem PLCI"));
4659 plci->internal_command = 0;
4660 sig_req(plci, REMOVE, 0);
4661 send_req(plci);
4662 }
4663 break;
4664
4665 /* Call Deflection Request pending, just no appl ptr assigned */
4666 case CD_REQ_PEND:
4667 SSparms[1] = S_CALL_DEFLECTION;
4668 if (rc != OK)
4669 {
4670 Info = 0x300E; /* not supported */
4671 }
4672 for (i = 0; i < max_appl; i++)
4673 {
4674 if (application[i].CDEnable)
4675 {
4676 if (!application[i].Id) application[i].CDEnable = 0;
4677 else
4678 {
4679 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4680 plci->number, "wws", Info, (word)3, SSparms);
4681 if (Info) application[i].CDEnable = 0;
4682 }
4683 }
4684 }
4685 plci->internal_command = 0;
4686 break;
4687
4688 case PERM_COD_HOOK: /* finished with Hook_Ind */
4689 return;
4690
4691 case PERM_COD_CALL:
4692 plci->internal_command = PERM_COD_CONN_PEND;
4693 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4694 return;
4695
4696 case PERM_COD_ASSIGN:
4697 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4698 plci->internal_command = 0;
4699 if (rc != ASSIGN_OK) break;
4700 plci->internal_command = PERM_COD_CALL;
4701 sig_req(plci, CALL_REQ, 0);
4702 send_req(plci);
4703 return;
4704
4705 case LISTEN_SIG_ASSIGN_PEND:
4706 if (rc == ASSIGN_OK)
4707 {
4708 plci->internal_command = 0;
4709 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4710 add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4711 sig_req(plci, INDICATE_REQ, 0);
4712 send_req(plci);
4713 }
4714 else
4715 {
4716 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4717 a->listen_active--;
4718 plci_remove(plci);
4719 plci->State = IDLE;
4720 }
4721 break;
4722
4723 case USELAW_REQ:
4724 if (global_req == ASSIGN)
4725 {
4726 if (rc == ASSIGN_OK)
4727 {
4728 sig_req(plci, LAW_REQ, 0);
4729 send_req(plci);
4730 dbug(1, dprintf("Auto-Law assigned"));
4731 }
4732 else
4733 {
4734 dbug(1, dprintf("Auto-Law assign failed"));
4735 a->automatic_law = 3;
4736 plci->internal_command = 0;
4737 a->automatic_lawPLCI = NULL;
4738 }
4739 break;
4740 }
4741 else if (req == LAW_REQ && rc == OK)
4742 {
4743 dbug(1, dprintf("Auto-Law initiated"));
4744 a->automatic_law = 2;
4745 plci->internal_command = 0;
4746 }
4747 else
4748 {
4749 dbug(1, dprintf("Auto-Law not supported"));
4750 a->automatic_law = 3;
4751 plci->internal_command = 0;
4752 sig_req(plci, REMOVE, 0);
4753 send_req(plci);
4754 a->automatic_lawPLCI = NULL;
4755 }
4756 break;
4757 }
4758 plci_remove_check(plci);
4759 }
4760 }
4761
4762 static void data_rc(PLCI *plci, byte ch)
4763 {
4764 dword Id;
4765 DIVA_CAPI_ADAPTER *a;
4766 NCCI *ncci_ptr;
4767 DATA_B3_DESC *data;
4768 word ncci;
4769
4770 if (plci->appl)
4771 {
4772 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4773 a = plci->adapter;
4774 ncci = a->ch_ncci[ch];
4775 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4776 {
4777 ncci_ptr = &(a->ncci[ncci]);
4778 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4779 if (ncci_ptr->data_pending)
4780 {
4781 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4782 if (!(data->Flags & 4) && a->ncci_state[ncci])
4783 {
4784 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4785 if (plci->tel) Id |= EXT_CONTROLLER;
4786 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4787 "ww", data->Handle, 0);
4788 }
4789 (ncci_ptr->data_out)++;
4790 if (ncci_ptr->data_out == MAX_DATA_B3)
4791 ncci_ptr->data_out = 0;
4792 (ncci_ptr->data_pending)--;
4793 }
4794 }
4795 }
4796 }
4797
4798 static void data_ack(PLCI *plci, byte ch)
4799 {
4800 dword Id;
4801 DIVA_CAPI_ADAPTER *a;
4802 NCCI *ncci_ptr;
4803 word ncci;
4804
4805 a = plci->adapter;
4806 ncci = a->ch_ncci[ch];
4807 ncci_ptr = &(a->ncci[ncci]);
4808 if (ncci_ptr->data_ack_pending)
4809 {
4810 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4811 {
4812 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4813 if (plci->tel) Id |= EXT_CONTROLLER;
4814 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4815 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4816 }
4817 (ncci_ptr->data_ack_out)++;
4818 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4819 ncci_ptr->data_ack_out = 0;
4820 (ncci_ptr->data_ack_pending)--;
4821 }
4822 }
4823
4824 static void sig_ind(PLCI *plci)
4825 {
4826 dword x_Id;
4827 dword Id;
4828 dword rId;
4829 word i;
4830 word cip;
4831 dword cip_mask;
4832 byte *ie;
4833 DIVA_CAPI_ADAPTER *a;
4834 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4835 #define MAXPARMSIDS 31
4836 byte *parms[MAXPARMSIDS];
4837 byte *add_i[4];
4838 byte *multi_fac_parms[MAX_MULTI_IE];
4839 byte *multi_pi_parms[MAX_MULTI_IE];
4840 byte *multi_ssext_parms[MAX_MULTI_IE];
4841 byte *multi_CiPN_parms[MAX_MULTI_IE];
4842
4843 byte *multi_vswitch_parms[MAX_MULTI_IE];
4844
4845 byte ai_len;
4846 byte *esc_chi = "";
4847 byte *esc_law = "";
4848 byte *pty_cai = "";
4849 byte *esc_cr = "";
4850 byte *esc_profile = "";
4851
4852 byte facility[256];
4853 PLCI *tplci = NULL;
4854 byte chi[] = "\x02\x18\x01";
4855 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4856 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4857 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4858 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4859 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4860 /* (see Info_Mask Bit 4, first IE. then the message type) */
4861 static const word parms_id[] =
4862 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4863 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4864 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4865 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4866 /* 14 FTY repl by ESC_CHI */
4867 /* 18 PI repl by ESC_LAW */
4868 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4869 static const word multi_fac_id[] = {1, FTY};
4870 static const word multi_pi_id[] = {1, PI};
4871 static const word multi_CiPN_id[] = {1, OAD};
4872 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4873
4874 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4875
4876 byte *cau;
4877 word ncci;
4878 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4879 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4880 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4881 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4882 byte force_mt_info = false;
4883 byte dir;
4884 dword d;
4885 word w;
4886
4887 a = plci->adapter;
4888 Id = ((word)plci->Id << 8) | a->Id;
4889 PUT_WORD(&SS_Ind[4], 0x0000);
4890
4891 if (plci->sig_remove_id)
4892 {
4893 plci->Sig.RNR = 2; /* discard */
4894 dbug(1, dprintf("SIG discard while remove pending"));
4895 return;
4896 }
4897 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4898 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4899 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4900 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4901 {
4902 plci->Sig.RNR = 1;
4903 return;
4904 }
4905 if (plci->Sig.Ind == HANGUP && plci->channels)
4906 {
4907 plci->Sig.RNR = 1;
4908 plci->hangup_flow_ctrl_timer++;
4909 /* recover the network layer after timeout */
4910 if (plci->hangup_flow_ctrl_timer == 100)
4911 {
4912 dbug(1, dprintf("Exceptional disc"));
4913 plci->Sig.RNR = 0;
4914 plci->hangup_flow_ctrl_timer = 0;
4915 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4916 {
4917 if (a->ncci_plci[ncci] == plci->Id)
4918 {
4919 cleanup_ncci_data(plci, ncci);
4920 if (plci->channels)plci->channels--;
4921 if (plci->appl)
4922 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4923 }
4924 }
4925 if (plci->appl)
4926 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4927 plci_remove(plci);
4928 plci->State = IDLE;
4929 }
4930 return;
4931 }
4932
4933 /* do first parse the info with no OAD in, because OAD will be converted */
4934 /* first the multiple facility IE, then mult. progress ind. */
4935 /* then the parameters for the info_ind + conn_ind */
4936 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4937 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4938 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4939
4940 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4941
4942 IndParse(plci, parms_id, parms, 0);
4943 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4944 esc_chi = parms[14];
4945 esc_law = parms[18];
4946 pty_cai = parms[24];
4947 esc_cr = parms[25];
4948 esc_profile = parms[27];
4949 if (esc_cr[0] && plci)
4950 {
4951 if (plci->cr_enquiry && plci->appl)
4952 {
4953 plci->cr_enquiry = false;
4954 /* d = MANU_ID */
4955 /* w = m_command */
4956 /* b = total length */
4957 /* b = indication type */
4958 /* b = length of all IEs */
4959 /* b = IE1 */
4960 /* S = IE1 length + cont. */
4961 /* b = IE2 */
4962 /* S = IE2 length + cont. */
4963 sendf(plci->appl,
4964 _MANUFACTURER_I,
4965 Id,
4966 0,
4967 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4968 2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4969 }
4970 }
4971 /* create the additional info structure */
4972 add_i[1] = parms[15]; /* KEY of additional info */
4973 add_i[2] = parms[11]; /* UUI of additional info */
4974 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4975
4976 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4977 /* indication returns by the card if requested by the function */
4978 /* AutomaticLaw() after driver init */
4979 if (a->automatic_law < 4)
4980 {
4981 if (esc_law[0]) {
4982 if (esc_law[2]) {
4983 dbug(0, dprintf("u-Law selected"));
4984 a->u_law = 1;
4985 }
4986 else {
4987 dbug(0, dprintf("a-Law selected"));
4988 a->u_law = 0;
4989 }
4990 a->automatic_law = 4;
4991 if (plci == a->automatic_lawPLCI) {
4992 plci->internal_command = 0;
4993 sig_req(plci, REMOVE, 0);
4994 send_req(plci);
4995 a->automatic_lawPLCI = NULL;
4996 }
4997 }
4998 if (esc_profile[0])
4999 {
5000 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5001 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5002 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5003 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5004
5005 a->profile.Global_Options &= 0x000000ffL;
5006 a->profile.B1_Protocols &= 0x000003ffL;
5007 a->profile.B2_Protocols &= 0x00001fdfL;
5008 a->profile.B3_Protocols &= 0x000000b7L;
5009
5010 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5011 GL_BCHANNEL_OPERATION_SUPPORTED;
5012 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5013 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5014 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5015 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5016 a->man_profile.private_options = 0;
5017
5018 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5019 {
5020 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5021 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5022 }
5023
5024
5025 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5026 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5027 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5028 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5029
5030
5031 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5032 a->man_profile.private_options |= 1L << PRIVATE_T38;
5033
5034
5035 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5036 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5037
5038
5039 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5040 a->man_profile.private_options |= 1L << PRIVATE_V18;
5041
5042
5043 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5044 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5045
5046
5047 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5048 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5049
5050
5051 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5052 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5053
5054
5055 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5056 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5057
5058
5059 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5060 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5061
5062 }
5063 else
5064 {
5065 a->profile.Global_Options &= 0x0000007fL;
5066 a->profile.B1_Protocols &= 0x000003dfL;
5067 a->profile.B2_Protocols &= 0x00001adfL;
5068 a->profile.B3_Protocols &= 0x000000b7L;
5069 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5070 }
5071 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5072 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5073 {
5074 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5075 }
5076 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5077 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5078 UnMapController(a->Id), a->profile.Global_Options,
5079 a->profile.B1_Protocols, a->profile.B2_Protocols,
5080 a->profile.B3_Protocols, a->manufacturer_features));
5081 }
5082 /* codec plci for the handset/hook state support is just an internal id */
5083 if (plci != a->AdvCodecPLCI)
5084 {
5085 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5086 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5087 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5088 SendInfo(plci, Id, parms, force_mt_info);
5089
5090 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5091
5092 }
5093
5094 /* switch the codec to the b-channel */
5095 if (esc_chi[0] && plci && !plci->SuppState) {
5096 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5097 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5098 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5099 if (plci->tel == ADV_VOICE && plci->appl) {
5100 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5101 }
5102 }
5103
5104 if (plci->appl) plci->appl->Number++;
5105
5106 switch (plci->Sig.Ind) {
5107 /* Response to Get_Supported_Services request */
5108 case S_SUPPORTED:
5109 dbug(1, dprintf("S_Supported"));
5110 if (!plci->appl) break;
5111 if (pty_cai[0] == 4)
5112 {
5113 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5114 }
5115 else
5116 {
5117 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5118 }
5119 PUT_WORD(&CF_Ind[1], 0);
5120 PUT_WORD(&CF_Ind[4], 0);
5121 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5122 plci_remove(plci);
5123 break;
5124
5125 /* Supplementary Service rejected */
5126 case S_SERVICE_REJ:
5127 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5128 if (!pty_cai[0]) break;
5129 switch (pty_cai[5])
5130 {
5131 case ECT_EXECUTE:
5132 case THREE_PTY_END:
5133 case THREE_PTY_BEGIN:
5134 if (!plci->relatedPTYPLCI) break;
5135 tplci = plci->relatedPTYPLCI;
5136 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5137 if (tplci->tel) rId |= EXT_CONTROLLER;
5138 if (pty_cai[5] == ECT_EXECUTE)
5139 {
5140 PUT_WORD(&SS_Ind[1], S_ECT);
5141
5142 plci->vswitchstate = 0;
5143 plci->relatedPTYPLCI->vswitchstate = 0;
5144
5145 }
5146 else
5147 {
5148 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5149 }
5150 if (pty_cai[2] != 0xff)
5151 {
5152 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5153 }
5154 else
5155 {
5156 PUT_WORD(&SS_Ind[4], 0x300E);
5157 }
5158 plci->relatedPTYPLCI = NULL;
5159 plci->ptyState = 0;
5160 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5161 break;
5162
5163 case CALL_DEFLECTION:
5164 if (pty_cai[2] != 0xff)
5165 {
5166 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5167 }
5168 else
5169 {
5170 PUT_WORD(&SS_Ind[4], 0x300E);
5171 }
5172 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5173 for (i = 0; i < max_appl; i++)
5174 {
5175 if (application[i].CDEnable)
5176 {
5177 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5178 application[i].CDEnable = false;
5179 }
5180 }
5181 break;
5182
5183 case DEACTIVATION_DIVERSION:
5184 case ACTIVATION_DIVERSION:
5185 case DIVERSION_INTERROGATE_CFU:
5186 case DIVERSION_INTERROGATE_CFB:
5187 case DIVERSION_INTERROGATE_CFNR:
5188 case DIVERSION_INTERROGATE_NUM:
5189 case CCBS_REQUEST:
5190 case CCBS_DEACTIVATE:
5191 case CCBS_INTERROGATE:
5192 if (!plci->appl) break;
5193 if (pty_cai[2] != 0xff)
5194 {
5195 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5196 }
5197 else
5198 {
5199 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5200 }
5201 switch (pty_cai[5])
5202 {
5203 case DEACTIVATION_DIVERSION:
5204 dbug(1, dprintf("Deact_Div"));
5205 Interr_Err_Ind[0] = 0x9;
5206 Interr_Err_Ind[3] = 0x6;
5207 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5208 break;
5209 case ACTIVATION_DIVERSION:
5210 dbug(1, dprintf("Act_Div"));
5211 Interr_Err_Ind[0] = 0x9;
5212 Interr_Err_Ind[3] = 0x6;
5213 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5214 break;
5215 case DIVERSION_INTERROGATE_CFU:
5216 case DIVERSION_INTERROGATE_CFB:
5217 case DIVERSION_INTERROGATE_CFNR:
5218 dbug(1, dprintf("Interr_Div"));
5219 Interr_Err_Ind[0] = 0xa;
5220 Interr_Err_Ind[3] = 0x7;
5221 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5222 break;
5223 case DIVERSION_INTERROGATE_NUM:
5224 dbug(1, dprintf("Interr_Num"));
5225 Interr_Err_Ind[0] = 0xa;
5226 Interr_Err_Ind[3] = 0x7;
5227 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5228 break;
5229 case CCBS_REQUEST:
5230 dbug(1, dprintf("CCBS Request"));
5231 Interr_Err_Ind[0] = 0xd;
5232 Interr_Err_Ind[3] = 0xa;
5233 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5234 break;
5235 case CCBS_DEACTIVATE:
5236 dbug(1, dprintf("CCBS Deactivate"));
5237 Interr_Err_Ind[0] = 0x9;
5238 Interr_Err_Ind[3] = 0x6;
5239 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5240 break;
5241 case CCBS_INTERROGATE:
5242 dbug(1, dprintf("CCBS Interrogate"));
5243 Interr_Err_Ind[0] = 0xb;
5244 Interr_Err_Ind[3] = 0x8;
5245 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5246 break;
5247 }
5248 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5249 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5250 plci_remove(plci);
5251 break;
5252 case ACTIVATION_MWI:
5253 case DEACTIVATION_MWI:
5254 if (pty_cai[5] == ACTIVATION_MWI)
5255 {
5256 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5257 }
5258 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5259
5260 if (pty_cai[2] != 0xff)
5261 {
5262 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5263 }
5264 else
5265 {
5266 PUT_WORD(&SS_Ind[4], 0x300E);
5267 }
5268
5269 if (plci->cr_enquiry)
5270 {
5271 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5272 plci_remove(plci);
5273 }
5274 else
5275 {
5276 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5277 }
5278 break;
5279 case CONF_ADD: /* ERROR */
5280 case CONF_BEGIN:
5281 case CONF_DROP:
5282 case CONF_ISOLATE:
5283 case CONF_REATTACH:
5284 CONF_Ind[0] = 9;
5285 CONF_Ind[3] = 6;
5286 switch (pty_cai[5])
5287 {
5288 case CONF_BEGIN:
5289 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5290 plci->ptyState = 0;
5291 break;
5292 case CONF_DROP:
5293 CONF_Ind[0] = 5;
5294 CONF_Ind[3] = 2;
5295 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5296 plci->ptyState = CONNECTED;
5297 break;
5298 case CONF_ISOLATE:
5299 CONF_Ind[0] = 5;
5300 CONF_Ind[3] = 2;
5301 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5302 plci->ptyState = CONNECTED;
5303 break;
5304 case CONF_REATTACH:
5305 CONF_Ind[0] = 5;
5306 CONF_Ind[3] = 2;
5307 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5308 plci->ptyState = CONNECTED;
5309 break;
5310 case CONF_ADD:
5311 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5312 plci->relatedPTYPLCI = NULL;
5313 tplci = plci->relatedPTYPLCI;
5314 if (tplci) tplci->ptyState = CONNECTED;
5315 plci->ptyState = CONNECTED;
5316 break;
5317 }
5318
5319 if (pty_cai[2] != 0xff)
5320 {
5321 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5322 }
5323 else
5324 {
5325 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5326 within the required time */
5327 }
5328
5329 PUT_DWORD(&CONF_Ind[6], 0x0);
5330 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5331 break;
5332 }
5333 break;
5334
5335 /* Supplementary Service indicates success */
5336 case S_SERVICE:
5337 dbug(1, dprintf("Service_Ind"));
5338 PUT_WORD(&CF_Ind[4], 0);
5339 switch (pty_cai[5])
5340 {
5341 case THREE_PTY_END:
5342 case THREE_PTY_BEGIN:
5343 case ECT_EXECUTE:
5344 if (!plci->relatedPTYPLCI) break;
5345 tplci = plci->relatedPTYPLCI;
5346 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5347 if (tplci->tel) rId |= EXT_CONTROLLER;
5348 if (pty_cai[5] == ECT_EXECUTE)
5349 {
5350 PUT_WORD(&SS_Ind[1], S_ECT);
5351
5352 if (plci->vswitchstate != 3)
5353 {
5354
5355 plci->ptyState = IDLE;
5356 plci->relatedPTYPLCI = NULL;
5357 plci->ptyState = 0;
5358
5359 }
5360
5361 dbug(1, dprintf("ECT OK"));
5362 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5363
5364
5365
5366 }
5367 else
5368 {
5369 switch (plci->ptyState)
5370 {
5371 case S_3PTY_BEGIN:
5372 plci->ptyState = CONNECTED;
5373 dbug(1, dprintf("3PTY ON"));
5374 break;
5375
5376 case S_3PTY_END:
5377 plci->ptyState = IDLE;
5378 plci->relatedPTYPLCI = NULL;
5379 plci->ptyState = 0;
5380 dbug(1, dprintf("3PTY OFF"));
5381 break;
5382 }
5383 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5384 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5385 }
5386 break;
5387
5388 case CALL_DEFLECTION:
5389 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5390 for (i = 0; i < max_appl; i++)
5391 {
5392 if (application[i].CDEnable)
5393 {
5394 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5395 application[i].CDEnable = false;
5396 }
5397 }
5398 break;
5399
5400 case DEACTIVATION_DIVERSION:
5401 case ACTIVATION_DIVERSION:
5402 if (!plci->appl) break;
5403 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5404 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5405 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5406 plci_remove(plci);
5407 break;
5408
5409 case DIVERSION_INTERROGATE_CFU:
5410 case DIVERSION_INTERROGATE_CFB:
5411 case DIVERSION_INTERROGATE_CFNR:
5412 case DIVERSION_INTERROGATE_NUM:
5413 case CCBS_REQUEST:
5414 case CCBS_DEACTIVATE:
5415 case CCBS_INTERROGATE:
5416 if (!plci->appl) break;
5417 switch (pty_cai[5])
5418 {
5419 case DIVERSION_INTERROGATE_CFU:
5420 case DIVERSION_INTERROGATE_CFB:
5421 case DIVERSION_INTERROGATE_CFNR:
5422 dbug(1, dprintf("Interr_Div"));
5423 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5424 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5425 break;
5426 case DIVERSION_INTERROGATE_NUM:
5427 dbug(1, dprintf("Interr_Num"));
5428 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5429 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5430 break;
5431 case CCBS_REQUEST:
5432 dbug(1, dprintf("CCBS Request"));
5433 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5434 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5435 break;
5436 case CCBS_DEACTIVATE:
5437 dbug(1, dprintf("CCBS Deactivate"));
5438 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5439 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5440 break;
5441 case CCBS_INTERROGATE:
5442 dbug(1, dprintf("CCBS Interrogate"));
5443 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5444 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5445 break;
5446 }
5447 PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5448 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5449 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5450 plci_remove(plci);
5451 break;
5452
5453 case ACTIVATION_MWI:
5454 case DEACTIVATION_MWI:
5455 if (pty_cai[5] == ACTIVATION_MWI)
5456 {
5457 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5458 }
5459 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5460 if (plci->cr_enquiry)
5461 {
5462 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5463 plci_remove(plci);
5464 }
5465 else
5466 {
5467 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5468 }
5469 break;
5470 case MWI_INDICATION:
5471 if (pty_cai[0] >= 0x12)
5472 {
5473 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5474 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5475 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5476 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5477 {
5478 if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5479 {
5480 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5481 plci_remove(plci);
5482 return;
5483 }
5484 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5485 pty_cai[0] = 0;
5486 }
5487 else
5488 {
5489 for (i = 0; i < max_appl; i++)
5490 {
5491 if (a->Notification_Mask[i]&SMASK_MWI)
5492 {
5493 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5494 pty_cai[0] = 0;
5495 }
5496 }
5497 }
5498
5499 if (!pty_cai[0])
5500 { /* acknowledge */
5501 facility[2] = 0; /* returncode */
5502 }
5503 else facility[2] = 0xff;
5504 }
5505 else
5506 {
5507 /* reject */
5508 facility[2] = 0xff; /* returncode */
5509 }
5510 facility[0] = 2;
5511 facility[1] = MWI_RESPONSE; /* Function */
5512 add_p(plci, CAI, facility);
5513 add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5514 sig_req(plci, S_SERVICE, 0);
5515 send_req(plci);
5516 plci->command = 0;
5517 next_internal_command(Id, plci);
5518 break;
5519 case CONF_ADD: /* OK */
5520 case CONF_BEGIN:
5521 case CONF_DROP:
5522 case CONF_ISOLATE:
5523 case CONF_REATTACH:
5524 case CONF_PARTYDISC:
5525 CONF_Ind[0] = 9;
5526 CONF_Ind[3] = 6;
5527 switch (pty_cai[5])
5528 {
5529 case CONF_BEGIN:
5530 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5531 if (pty_cai[0] == 6)
5532 {
5533 d = pty_cai[6];
5534 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5535 }
5536 else
5537 {
5538 PUT_DWORD(&CONF_Ind[6], 0x0);
5539 }
5540 break;
5541 case CONF_ISOLATE:
5542 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5543 CONF_Ind[0] = 5;
5544 CONF_Ind[3] = 2;
5545 break;
5546 case CONF_REATTACH:
5547 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5548 CONF_Ind[0] = 5;
5549 CONF_Ind[3] = 2;
5550 break;
5551 case CONF_DROP:
5552 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5553 CONF_Ind[0] = 5;
5554 CONF_Ind[3] = 2;
5555 break;
5556 case CONF_ADD:
5557 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5558 d = pty_cai[6];
5559 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5560 tplci = plci->relatedPTYPLCI;
5561 if (tplci) tplci->ptyState = CONNECTED;
5562 break;
5563 case CONF_PARTYDISC:
5564 CONF_Ind[0] = 7;
5565 CONF_Ind[3] = 4;
5566 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5567 d = pty_cai[6];
5568 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5569 break;
5570 }
5571 plci->ptyState = CONNECTED;
5572 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5573 break;
5574 case CCBS_INFO_RETAIN:
5575 case CCBS_ERASECALLLINKAGEID:
5576 case CCBS_STOP_ALERTING:
5577 CONF_Ind[0] = 5;
5578 CONF_Ind[3] = 2;
5579 switch (pty_cai[5])
5580 {
5581 case CCBS_INFO_RETAIN:
5582 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5583 break;
5584 case CCBS_STOP_ALERTING:
5585 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5586 break;
5587 case CCBS_ERASECALLLINKAGEID:
5588 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5589 CONF_Ind[0] = 7;
5590 CONF_Ind[3] = 4;
5591 CONF_Ind[6] = 0;
5592 CONF_Ind[7] = 0;
5593 break;
5594 }
5595 w = pty_cai[6];
5596 PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5597
5598 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5599 {
5600 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5601 }
5602 else
5603 {
5604 for (i = 0; i < max_appl; i++)
5605 if (a->Notification_Mask[i] & SMASK_CCBS)
5606 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5607 }
5608 break;
5609 }
5610 break;
5611 case CALL_HOLD_REJ:
5612 cau = parms[7];
5613 if (cau)
5614 {
5615 i = _L3_CAUSE | cau[2];
5616 if (cau[2] == 0) i = 0x3603;
5617 }
5618 else
5619 {
5620 i = 0x3603;
5621 }
5622 PUT_WORD(&SS_Ind[1], S_HOLD);
5623 PUT_WORD(&SS_Ind[4], i);
5624 if (plci->SuppState == HOLD_REQUEST)
5625 {
5626 plci->SuppState = IDLE;
5627 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5628 }
5629 break;
5630
5631 case CALL_HOLD_ACK:
5632 if (plci->SuppState == HOLD_REQUEST)
5633 {
5634 plci->SuppState = CALL_HELD;
5635 CodecIdCheck(a, plci);
5636 start_internal_command(Id, plci, hold_save_command);
5637 }
5638 break;
5639
5640 case CALL_RETRIEVE_REJ:
5641 cau = parms[7];
5642 if (cau)
5643 {
5644 i = _L3_CAUSE | cau[2];
5645 if (cau[2] == 0) i = 0x3603;
5646 }
5647 else
5648 {
5649 i = 0x3603;
5650 }
5651 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5652 PUT_WORD(&SS_Ind[4], i);
5653 if (plci->SuppState == RETRIEVE_REQUEST)
5654 {
5655 plci->SuppState = CALL_HELD;
5656 CodecIdCheck(a, plci);
5657 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5658 }
5659 break;
5660
5661 case CALL_RETRIEVE_ACK:
5662 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5663 if (plci->SuppState == RETRIEVE_REQUEST)
5664 {
5665 plci->SuppState = IDLE;
5666 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5667 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5668 if (plci->tel)
5669 {
5670 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5671 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5672 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5673 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5674 {
5675 dbug(1, dprintf("Get B-ch"));
5676 start_internal_command(Id, plci, retrieve_restore_command);
5677 }
5678 else
5679 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5680 }
5681 else
5682 start_internal_command(Id, plci, retrieve_restore_command);
5683 }
5684 break;
5685
5686 case INDICATE_IND:
5687 if (plci->State != LISTENING) {
5688 sig_req(plci, HANGUP, 0);
5689 send_req(plci);
5690 break;
5691 }
5692 cip = find_cip(a, parms[4], parms[6]);
5693 cip_mask = 1L << cip;
5694 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5695 clear_c_ind_mask(plci);
5696 if (!remove_started && !a->adapter_disabled)
5697 {
5698 set_c_ind_mask_bit(plci, MAX_APPL);
5699 group_optimization(a, plci);
5700 for (i = 0; i < max_appl; i++) {
5701 if (application[i].Id
5702 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5703 && CPN_filter_ok(parms[0], a, i)
5704 && test_group_ind_mask_bit(plci, i)) {
5705 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5706 set_c_ind_mask_bit(plci, i);
5707 dump_c_ind_mask(plci);
5708 plci->State = INC_CON_PENDING;
5709 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5710 CALL_DIR_IN | CALL_DIR_ANSWER;
5711 if (esc_chi[0]) {
5712 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5713 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5714 }
5715 /* if a listen on the ext controller is done, check if hook states */
5716 /* are supported or if just a on board codec must be activated */
5717 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5718 if (a->profile.Global_Options & HANDSET)
5719 plci->tel = ADV_VOICE;
5720 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5721 plci->tel = CODEC;
5722 if (plci->tel) Id |= EXT_CONTROLLER;
5723 a->codec_listen[i] = plci;
5724 }
5725
5726 sendf(&application[i], _CONNECT_I, Id, 0,
5727 "wSSSSSSSbSSSSS", cip, /* CIP */
5728 parms[0], /* CalledPartyNumber */
5729 multi_CiPN_parms[0], /* CallingPartyNumber */
5730 parms[2], /* CalledPartySubad */
5731 parms[3], /* CallingPartySubad */
5732 parms[4], /* BearerCapability */
5733 parms[5], /* LowLC */
5734 parms[6], /* HighLC */
5735 ai_len, /* nested struct add_i */
5736 add_i[0], /* B channel info */
5737 add_i[1], /* keypad facility */
5738 add_i[2], /* user user data */
5739 add_i[3], /* nested facility */
5740 multi_CiPN_parms[1] /* second CiPN(SCR) */
5741 );
5742 SendSSExtInd(&application[i],
5743 plci,
5744 Id,
5745 multi_ssext_parms);
5746 SendSetupInfo(&application[i],
5747 plci,
5748 Id,
5749 parms,
5750 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5751 }
5752 }
5753 clear_c_ind_mask_bit(plci, MAX_APPL);
5754 dump_c_ind_mask(plci);
5755 }
5756 if (c_ind_mask_empty(plci)) {
5757 sig_req(plci, HANGUP, 0);
5758 send_req(plci);
5759 plci->State = IDLE;
5760 }
5761 plci->notifiedcall = 0;
5762 a->listen_active--;
5763 listen_check(a);
5764 break;
5765
5766 case CALL_PEND_NOTIFY:
5767 plci->notifiedcall = 1;
5768 listen_check(a);
5769 break;
5770
5771 case CALL_IND:
5772 case CALL_CON:
5773 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5774 {
5775 if (plci->internal_command == PERM_COD_CONN_PEND)
5776 {
5777 if (plci->State == ADVANCED_VOICE_NOSIG)
5778 {
5779 dbug(1, dprintf("***Codec OK"));
5780 if (a->AdvSignalPLCI)
5781 {
5782 tplci = a->AdvSignalPLCI;
5783 if (tplci->spoofed_msg)
5784 {
5785 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5786 tplci->command = 0;
5787 tplci->internal_command = 0;
5788 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5789 switch (tplci->spoofed_msg)
5790 {
5791 case CALL_RES:
5792 tplci->command = _CONNECT_I | RESPONSE;
5793 api_load_msg(&tplci->saved_msg, saved_parms);
5794 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5795 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5796 {
5797 /* early B3 connect (CIP mask bit 9) no release after a disc */
5798 add_p(tplci, LLI, "\x01\x01");
5799 }
5800 add_s(tplci, CONN_NR, &saved_parms[2]);
5801 add_s(tplci, LLC, &saved_parms[4]);
5802 add_ai(tplci, &saved_parms[5]);
5803 tplci->State = INC_CON_ACCEPT;
5804 sig_req(tplci, CALL_RES, 0);
5805 send_req(tplci);
5806 break;
5807
5808 case AWAITING_SELECT_B:
5809 dbug(1, dprintf("Select_B continue"));
5810 start_internal_command(x_Id, tplci, select_b_command);
5811 break;
5812
5813 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5814 if (!tplci->Sig.Id)
5815 {
5816 dbug(1, dprintf("No SigID!"));
5817 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5818 plci_remove(tplci);
5819 break;
5820 }
5821 tplci->command = _MANUFACTURER_R;
5822 api_load_msg(&tplci->saved_msg, saved_parms);
5823 dir = saved_parms[2].info[0];
5824 if (dir == 1) {
5825 sig_req(tplci, CALL_REQ, 0);
5826 }
5827 else if (!dir) {
5828 sig_req(tplci, LISTEN_REQ, 0);
5829 }
5830 send_req(tplci);
5831 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5832 break;
5833
5834 case (CALL_REQ | AWAITING_MANUF_CON):
5835 sig_req(tplci, CALL_REQ, 0);
5836 send_req(tplci);
5837 break;
5838
5839 case CALL_REQ:
5840 if (!tplci->Sig.Id)
5841 {
5842 dbug(1, dprintf("No SigID!"));
5843 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5844 plci_remove(tplci);
5845 break;
5846 }
5847 tplci->command = _CONNECT_R;
5848 api_load_msg(&tplci->saved_msg, saved_parms);
5849 add_s(tplci, CPN, &saved_parms[1]);
5850 add_s(tplci, DSA, &saved_parms[3]);
5851 add_ai(tplci, &saved_parms[9]);
5852 sig_req(tplci, CALL_REQ, 0);
5853 send_req(tplci);
5854 break;
5855
5856 case CALL_RETRIEVE:
5857 tplci->command = C_RETRIEVE_REQ;
5858 sig_req(tplci, CALL_RETRIEVE, 0);
5859 send_req(tplci);
5860 break;
5861 }
5862 tplci->spoofed_msg = 0;
5863 if (tplci->internal_command == 0)
5864 next_internal_command(x_Id, tplci);
5865 }
5866 }
5867 next_internal_command(Id, plci);
5868 break;
5869 }
5870 dbug(1, dprintf("***Codec Hook Init Req"));
5871 plci->internal_command = PERM_COD_HOOK;
5872 add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5873 sig_req(plci, TEL_CTRL, 0);
5874 send_req(plci);
5875 }
5876 }
5877 else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5878 && plci->State != INC_ACT_PENDING)
5879 {
5880 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5881 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5882 {
5883 chi[2] = plci->b_channel;
5884 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5885 }
5886 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5887 plci->State = INC_ACT_PENDING;
5888 }
5889 break;
5890
5891 case TEL_CTRL:
5892 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5893 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5894 switch (ie[1] & 0x91) {
5895 case 0x80: /* hook off */
5896 case 0x81:
5897 if (plci->internal_command == PERM_COD_HOOK)
5898 {
5899 dbug(1, dprintf("init:hook_off"));
5900 plci->hook_state = ie[1];
5901 next_internal_command(Id, plci);
5902 break;
5903 }
5904 else /* ignore doubled hook indications */
5905 {
5906 if (((plci->hook_state) & 0xf0) == 0x80)
5907 {
5908 dbug(1, dprintf("ignore hook"));
5909 break;
5910 }
5911 plci->hook_state = ie[1]&0x91;
5912 }
5913 /* check for incoming call pending */
5914 /* and signal '+'.Appl must decide */
5915 /* with connect_res if call must */
5916 /* accepted or not */
5917 for (i = 0, tplci = NULL; i < max_appl; i++) {
5918 if (a->codec_listen[i]
5919 && (a->codec_listen[i]->State == INC_CON_PENDING
5920 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5921 tplci = a->codec_listen[i];
5922 tplci->appl = &application[i];
5923 }
5924 }
5925 /* no incoming call, do outgoing call */
5926 /* and signal '+' if outg. setup */
5927 if (!a->AdvSignalPLCI && !tplci) {
5928 if ((i = get_plci(a))) {
5929 a->AdvSignalPLCI = &a->plci[i - 1];
5930 tplci = a->AdvSignalPLCI;
5931 tplci->tel = ADV_VOICE;
5932 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5933 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5934 /* early B3 connect (CIP mask bit 9) no release after a disc */
5935 add_p(tplci, LLI, "\x01\x01");
5936 }
5937 add_p(tplci, CAI, voice_cai);
5938 add_p(tplci, OAD, a->TelOAD);
5939 add_p(tplci, OSA, a->TelOSA);
5940 add_p(tplci, SHIFT | 6, NULL);
5941 add_p(tplci, SIN, "\x02\x01\x00");
5942 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5943 sig_req(tplci, ASSIGN, DSIG_ID);
5944 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5945 a->AdvSignalPLCI->command = 0;
5946 tplci->appl = a->AdvSignalAppl;
5947 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5948 send_req(tplci);
5949 }
5950
5951 }
5952
5953 if (!tplci) break;
5954 Id = ((word)tplci->Id << 8) | a->Id;
5955 Id |= EXT_CONTROLLER;
5956 sendf(tplci->appl,
5957 _FACILITY_I,
5958 Id,
5959 0,
5960 "ws", (word)0, "\x01+");
5961 break;
5962
5963 case 0x90: /* hook on */
5964 case 0x91:
5965 if (plci->internal_command == PERM_COD_HOOK)
5966 {
5967 dbug(1, dprintf("init:hook_on"));
5968 plci->hook_state = ie[1] & 0x91;
5969 next_internal_command(Id, plci);
5970 break;
5971 }
5972 else /* ignore doubled hook indications */
5973 {
5974 if (((plci->hook_state) & 0xf0) == 0x90) break;
5975 plci->hook_state = ie[1] & 0x91;
5976 }
5977 /* hangup the adv. voice call and signal '-' to the appl */
5978 if (a->AdvSignalPLCI) {
5979 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5980 if (plci->tel) Id |= EXT_CONTROLLER;
5981 sendf(a->AdvSignalAppl,
5982 _FACILITY_I,
5983 Id,
5984 0,
5985 "ws", (word)0, "\x01-");
5986 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5987 a->AdvSignalPLCI->command = 0;
5988 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5989 send_req(a->AdvSignalPLCI);
5990 }
5991 break;
5992 }
5993 }
5994 break;
5995
5996 case RESUME:
5997 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
5998 PUT_WORD(&resume_cau[4], GOOD);
5999 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6000 break;
6001
6002 case SUSPEND:
6003 clear_c_ind_mask(plci);
6004
6005 if (plci->NL.Id && !plci->nl_remove_id) {
6006 mixer_remove(plci);
6007 nl_req_ncci(plci, REMOVE, 0);
6008 }
6009 if (!plci->sig_remove_id) {
6010 plci->internal_command = 0;
6011 sig_req(plci, REMOVE, 0);
6012 }
6013 send_req(plci);
6014 if (!plci->channels) {
6015 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6016 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6017 }
6018 break;
6019
6020 case SUSPEND_REJ:
6021 break;
6022
6023 case HANGUP:
6024 plci->hangup_flow_ctrl_timer = 0;
6025 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6026 cau = parms[7];
6027 if (cau) {
6028 i = _L3_CAUSE | cau[2];
6029 if (cau[2] == 0) i = 0;
6030 else if (cau[2] == 8) i = _L1_ERROR;
6031 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6032 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6033 }
6034 else {
6035 i = _L3_ERROR;
6036 }
6037
6038 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6039 {
6040 for (i = 0; i < max_appl; i++)
6041 {
6042 if (test_c_ind_mask_bit(plci, i))
6043 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6044 }
6045 }
6046 else
6047 {
6048 clear_c_ind_mask(plci);
6049 }
6050 if (!plci->appl)
6051 {
6052 if (plci->State == LISTENING)
6053 {
6054 plci->notifiedcall = 0;
6055 a->listen_active--;
6056 }
6057 plci->State = INC_DIS_PENDING;
6058 if (c_ind_mask_empty(plci))
6059 {
6060 plci->State = IDLE;
6061 if (plci->NL.Id && !plci->nl_remove_id)
6062 {
6063 mixer_remove(plci);
6064 nl_req_ncci(plci, REMOVE, 0);
6065 }
6066 if (!plci->sig_remove_id)
6067 {
6068 plci->internal_command = 0;
6069 sig_req(plci, REMOVE, 0);
6070 }
6071 send_req(plci);
6072 }
6073 }
6074 else
6075 {
6076 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6077 /* result in a second HANGUP! Don't generate another */
6078 /* DISCONNECT */
6079 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6080 {
6081 if (plci->State == RESUMING)
6082 {
6083 PUT_WORD(&resume_cau[4], i);
6084 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6085 }
6086 plci->State = INC_DIS_PENDING;
6087 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6088 }
6089 }
6090 break;
6091
6092 case SSEXT_IND:
6093 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6094 break;
6095
6096 case VSWITCH_REQ:
6097 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6098 break;
6099 case VSWITCH_IND:
6100 if (plci->relatedPTYPLCI &&
6101 plci->vswitchstate == 3 &&
6102 plci->relatedPTYPLCI->vswitchstate == 3 &&
6103 parms[MAXPARMSIDS - 1][0])
6104 {
6105 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6106 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6107 send_req(plci->relatedPTYPLCI);
6108 }
6109 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6110 break;
6111
6112 }
6113 }
6114
6115
6116 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6117 {
6118 word i;
6119 byte *ie;
6120 word Info_Number;
6121 byte *Info_Element;
6122 word Info_Mask = 0;
6123
6124 dbug(1, dprintf("SetupInfo"));
6125
6126 for (i = 0; i < MAXPARMSIDS; i++) {
6127 ie = parms[i];
6128 Info_Number = 0;
6129 Info_Element = ie;
6130 if (ie[0]) {
6131 switch (i) {
6132 case 0:
6133 dbug(1, dprintf("CPN "));
6134 Info_Number = 0x0070;
6135 Info_Mask = 0x80;
6136 Info_Sent_Flag = true;
6137 break;
6138 case 8: /* display */
6139 dbug(1, dprintf("display(%d)", i));
6140 Info_Number = 0x0028;
6141 Info_Mask = 0x04;
6142 Info_Sent_Flag = true;
6143 break;
6144 case 16: /* Channel Id */
6145 dbug(1, dprintf("CHI"));
6146 Info_Number = 0x0018;
6147 Info_Mask = 0x100;
6148 Info_Sent_Flag = true;
6149 mixer_set_bchannel_id(plci, Info_Element);
6150 break;
6151 case 19: /* Redirected Number */
6152 dbug(1, dprintf("RDN"));
6153 Info_Number = 0x0074;
6154 Info_Mask = 0x400;
6155 Info_Sent_Flag = true;
6156 break;
6157 case 20: /* Redirected Number extended */
6158 dbug(1, dprintf("RDX"));
6159 Info_Number = 0x0073;
6160 Info_Mask = 0x400;
6161 Info_Sent_Flag = true;
6162 break;
6163 case 22: /* Redirecing Number */
6164 dbug(1, dprintf("RIN"));
6165 Info_Number = 0x0076;
6166 Info_Mask = 0x400;
6167 Info_Sent_Flag = true;
6168 break;
6169 default:
6170 Info_Number = 0;
6171 break;
6172 }
6173 }
6174
6175 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6176 Info_Number = 0x8000 | 5;
6177 Info_Mask = 0x10;
6178 Info_Element = "";
6179 }
6180
6181 if (Info_Sent_Flag && Info_Number) {
6182 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6183 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6184 }
6185 }
6186 }
6187 }
6188
6189
6190 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6191 {
6192 word i;
6193 word j;
6194 word k;
6195 byte *ie;
6196 word Info_Number;
6197 byte *Info_Element;
6198 word Info_Mask = 0;
6199 static byte charges[5] = {4, 0, 0, 0, 0};
6200 static byte cause[] = {0x02, 0x80, 0x00};
6201 APPL *appl;
6202
6203 dbug(1, dprintf("InfoParse "));
6204
6205 if (
6206 !plci->appl
6207 && !plci->State
6208 && plci->Sig.Ind != NCR_FACILITY
6209 )
6210 {
6211 dbug(1, dprintf("NoParse "));
6212 return;
6213 }
6214 cause[2] = 0;
6215 for (i = 0; i < MAXPARMSIDS; i++) {
6216 ie = parms[i];
6217 Info_Number = 0;
6218 Info_Element = ie;
6219 if (ie[0]) {
6220 switch (i) {
6221 case 0:
6222 dbug(1, dprintf("CPN "));
6223 Info_Number = 0x0070;
6224 Info_Mask = 0x80;
6225 break;
6226 case 7: /* ESC_CAU */
6227 dbug(1, dprintf("cau(0x%x)", ie[2]));
6228 Info_Number = 0x0008;
6229 Info_Mask = 0x00;
6230 cause[2] = ie[2];
6231 Info_Element = NULL;
6232 break;
6233 case 8: /* display */
6234 dbug(1, dprintf("display(%d)", i));
6235 Info_Number = 0x0028;
6236 Info_Mask = 0x04;
6237 break;
6238 case 9: /* Date display */
6239 dbug(1, dprintf("date(%d)", i));
6240 Info_Number = 0x0029;
6241 Info_Mask = 0x02;
6242 break;
6243 case 10: /* charges */
6244 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6245 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6246 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6247 Info_Number = 0x4000;
6248 Info_Mask = 0x40;
6249 Info_Element = charges;
6250 break;
6251 case 11: /* user user info */
6252 dbug(1, dprintf("uui"));
6253 Info_Number = 0x007E;
6254 Info_Mask = 0x08;
6255 break;
6256 case 12: /* congestion receiver ready */
6257 dbug(1, dprintf("clRDY"));
6258 Info_Number = 0x00B0;
6259 Info_Mask = 0x08;
6260 Info_Element = "";
6261 break;
6262 case 13: /* congestion receiver not ready */
6263 dbug(1, dprintf("clNRDY"));
6264 Info_Number = 0x00BF;
6265 Info_Mask = 0x08;
6266 Info_Element = "";
6267 break;
6268 case 15: /* Keypad Facility */
6269 dbug(1, dprintf("KEY"));
6270 Info_Number = 0x002C;
6271 Info_Mask = 0x20;
6272 break;
6273 case 16: /* Channel Id */
6274 dbug(1, dprintf("CHI"));
6275 Info_Number = 0x0018;
6276 Info_Mask = 0x100;
6277 mixer_set_bchannel_id(plci, Info_Element);
6278 break;
6279 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6280 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6281 if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6282 Info_Number = 0x0008;
6283 Info_Mask = 0x01;
6284 if (cause[2] != ie[2]) Info_Element = cause;
6285 break;
6286 case 19: /* Redirected Number */
6287 dbug(1, dprintf("RDN"));
6288 Info_Number = 0x0074;
6289 Info_Mask = 0x400;
6290 break;
6291 case 22: /* Redirecing Number */
6292 dbug(1, dprintf("RIN"));
6293 Info_Number = 0x0076;
6294 Info_Mask = 0x400;
6295 break;
6296 case 23: /* Notification Indicator */
6297 dbug(1, dprintf("NI"));
6298 Info_Number = (word)NI;
6299 Info_Mask = 0x210;
6300 break;
6301 case 26: /* Call State */
6302 dbug(1, dprintf("CST"));
6303 Info_Number = (word)CST;
6304 Info_Mask = 0x01; /* do with cause i.e. for now */
6305 break;
6306 case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6307 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6308 Info_Number = 0x8000 | ie[3];
6309 if (iesent) Info_Mask = 0xffff;
6310 else Info_Mask = 0x10;
6311 Info_Element = "";
6312 break;
6313 default:
6314 Info_Number = 0;
6315 Info_Mask = 0;
6316 Info_Element = "";
6317 break;
6318 }
6319 }
6320
6321 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6322 {
6323 for (j = 0; j < max_appl; j++)
6324 {
6325 appl = &application[j];
6326 if (Info_Number
6327 && appl->Id
6328 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6329 {
6330 dbug(1, dprintf("NCR_Ind"));
6331 iesent = true;
6332 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6333 }
6334 }
6335 }
6336 else if (!plci->appl)
6337 { /* overlap receiving broadcast */
6338 if (Info_Number == CPN
6339 || Info_Number == KEY
6340 || Info_Number == NI
6341 || Info_Number == DSP
6342 || Info_Number == UUI)
6343 {
6344 for (j = 0; j < max_appl; j++)
6345 {
6346 if (test_c_ind_mask_bit(plci, j))
6347 {
6348 dbug(1, dprintf("Ovl_Ind"));
6349 iesent = true;
6350 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6351 }
6352 }
6353 }
6354 } /* all other signalling states */
6355 else if (Info_Number
6356 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6357 {
6358 dbug(1, dprintf("Std_Ind"));
6359 iesent = true;
6360 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6361 }
6362 }
6363 }
6364
6365
6366 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6367 dword info_mask, byte setupParse)
6368 {
6369 word i;
6370 word j;
6371 byte *ie;
6372 word Info_Number;
6373 byte *Info_Element;
6374 APPL *appl;
6375 word Info_Mask = 0;
6376 byte iesent = 0;
6377
6378 if (
6379 !plci->appl
6380 && !plci->State
6381 && plci->Sig.Ind != NCR_FACILITY
6382 && !setupParse
6383 )
6384 {
6385 dbug(1, dprintf("NoM-IEParse "));
6386 return 0;
6387 }
6388 dbug(1, dprintf("M-IEParse "));
6389
6390 for (i = 0; i < MAX_MULTI_IE; i++)
6391 {
6392 ie = parms[i];
6393 Info_Number = 0;
6394 Info_Element = ie;
6395 if (ie[0])
6396 {
6397 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6398 Info_Number = (word)ie_type;
6399 Info_Mask = (word)info_mask;
6400 }
6401
6402 if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6403 {
6404 for (j = 0; j < max_appl; j++)
6405 {
6406 appl = &application[j];
6407 if (Info_Number
6408 && appl->Id
6409 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6410 {
6411 iesent = true;
6412 dbug(1, dprintf("Mlt_NCR_Ind"));
6413 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6414 }
6415 }
6416 }
6417 else if (!plci->appl && Info_Number)
6418 { /* overlap receiving broadcast */
6419 for (j = 0; j < max_appl; j++)
6420 {
6421 if (test_c_ind_mask_bit(plci, j))
6422 {
6423 iesent = true;
6424 dbug(1, dprintf("Mlt_Ovl_Ind"));
6425 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6426 }
6427 }
6428 } /* all other signalling states */
6429 else if (Info_Number
6430 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6431 {
6432 iesent = true;
6433 dbug(1, dprintf("Mlt_Std_Ind"));
6434 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6435 }
6436 }
6437 return iesent;
6438 }
6439
6440 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6441 {
6442 word i;
6443 /* Format of multi_ssext_parms[i][]:
6444 0 byte length
6445 1 byte SSEXTIE
6446 2 byte SSEXT_REQ/SSEXT_IND
6447 3 byte length
6448 4 word SSExtCommand
6449 6... Params
6450 */
6451 if (
6452 plci
6453 && plci->State
6454 && plci->Sig.Ind != NCR_FACILITY
6455 )
6456 for (i = 0; i < MAX_MULTI_IE; i++)
6457 {
6458 if (parms[i][0] < 6) continue;
6459 if (parms[i][2] == SSEXT_REQ) continue;
6460
6461 if (appl)
6462 {
6463 parms[i][0] = 0; /* kill it */
6464 sendf(appl, _MANUFACTURER_I,
6465 Id,
6466 0,
6467 "dwS",
6468 _DI_MANU_ID,
6469 _DI_SSEXT_CTRL,
6470 &parms[i][3]);
6471 }
6472 else if (plci->appl)
6473 {
6474 parms[i][0] = 0; /* kill it */
6475 sendf(plci->appl, _MANUFACTURER_I,
6476 Id,
6477 0,
6478 "dwS",
6479 _DI_MANU_ID,
6480 _DI_SSEXT_CTRL,
6481 &parms[i][3]);
6482 }
6483 }
6484 };
6485
6486 static void nl_ind(PLCI *plci)
6487 {
6488 byte ch;
6489 word ncci;
6490 dword Id;
6491 DIVA_CAPI_ADAPTER *a;
6492 word NCCIcode;
6493 APPL *APPLptr;
6494 word count;
6495 word Num;
6496 word i, ncpi_state;
6497 byte len, ncci_state;
6498 word msg;
6499 word info = 0;
6500 word fax_feature_bits;
6501 byte fax_send_edata_ack;
6502 static byte v120_header_buffer[2 + 3];
6503 static word fax_info[] = {
6504 0, /* T30_SUCCESS */
6505 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6510 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6511 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6512 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6513 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6514 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6515 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6516 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6517 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6518 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6523 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6524 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6525 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6537 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6538 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6539 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6540 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6541 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6542 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6543 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6544 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6545 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6546 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6547 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6548 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6549 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6550 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6551 };
6552
6553 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6554
6555
6556 static word rtp_info[] = {
6557 GOOD, /* RTP_SUCCESS */
6558 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6559 };
6560
6561 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6562 {
6563 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6564 0x00000000, 0x00000000, 0x00000000, 0x00000000
6565 };
6566
6567 ch = plci->NL.IndCh;
6568 a = plci->adapter;
6569 ncci = a->ch_ncci[ch];
6570 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6571 if (plci->tel) Id |= EXT_CONTROLLER;
6572 APPLptr = plci->appl;
6573 dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6574 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6575
6576 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6577
6578 if (plci->nl_remove_id)
6579 {
6580 plci->NL.RNR = 2; /* discard */
6581 dbug(1, dprintf("NL discard while remove pending"));
6582 return;
6583 }
6584 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6585 {
6586 if (plci->State == INC_DIS_PENDING
6587 || plci->State == OUTG_DIS_PENDING
6588 || plci->State == IDLE)
6589 {
6590 plci->NL.RNR = 2; /* discard */
6591 dbug(1, dprintf("discard n_connect"));
6592 return;
6593 }
6594 if (plci->State < INC_ACT_PENDING)
6595 {
6596 plci->NL.RNR = 1; /* flow control */
6597 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6598 return;
6599 }
6600 }
6601
6602 if (!APPLptr) /* no application or invalid data */
6603 { /* while reloading the DSP */
6604 dbug(1, dprintf("discard1"));
6605 plci->NL.RNR = 2;
6606 return;
6607 }
6608
6609 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6610 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6611 || (plci->B2_prot == 7)
6612 || (plci->B3_prot == 7)))
6613 {
6614 plci->ncpi_buffer[0] = 0;
6615
6616 ncpi_state = plci->ncpi_state;
6617 if (plci->NL.complete == 1)
6618 {
6619 byte *data = &plci->NL.RBuffer->P[0];
6620
6621 if ((plci->NL.RBuffer->length >= 12)
6622 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6623 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6624 {
6625 word conn_opt, ncpi_opt = 0x00;
6626 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6627
6628 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6629 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6630 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6631 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6632
6633 data++; /* indication code */
6634 data += 2; /* timestamp */
6635 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6636 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6637 data++; /* connected norm */
6638 conn_opt = GET_WORD(data);
6639 data += 2; /* connected options */
6640
6641 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6642
6643 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6644 {
6645 ncpi_opt |= MDM_NCPI_ECM_V42;
6646 }
6647 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6648 {
6649 ncpi_opt |= MDM_NCPI_ECM_MNP;
6650 }
6651 else
6652 {
6653 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6654 }
6655 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6656 {
6657 ncpi_opt |= MDM_NCPI_COMPRESSED;
6658 }
6659 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6660 plci->ncpi_buffer[0] = 4;
6661
6662 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6663 }
6664 }
6665 if (plci->B3_prot == 7)
6666 {
6667 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6668 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6669 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6670 {
6671 a->ncci_state[ncci] = INC_ACT_PENDING;
6672 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6673 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6674 }
6675 }
6676
6677 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6678 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6679 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6680 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6681
6682 {
6683 plci->NL.RNR = 2;
6684 return;
6685 }
6686 }
6687
6688 if (plci->NL.complete == 2)
6689 {
6690 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6691 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6692 {
6693 switch (plci->RData[0].P[0])
6694 {
6695
6696 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6697 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6698 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6699 break;
6700 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6701 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6702 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6703 break;
6704 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6705 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6706 break;
6707 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6708 dtmf_confirmation(Id, plci);
6709 break;
6710
6711
6712 case UDATA_INDICATION_MIXER_TAP_DATA:
6713 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6714 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6715 if (i != 0)
6716 {
6717 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6718 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6719 }
6720 break;
6721
6722
6723 case UDATA_INDICATION_MIXER_COEFS_SET:
6724 mixer_indication_coefs_set(Id, plci);
6725 break;
6726 case UDATA_INDICATION_XCONNECT_FROM:
6727 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6728 break;
6729 case UDATA_INDICATION_XCONNECT_TO:
6730 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6731 break;
6732
6733
6734 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6735 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6736 break;
6737
6738
6739
6740 default:
6741 break;
6742 }
6743 }
6744 else
6745 {
6746 if ((plci->RData[0].PLength != 0)
6747 && ((plci->B2_prot == B2_V120_ASYNC)
6748 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6749 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6750 {
6751
6752 sendf(plci->appl, _DATA_B3_I, Id, 0,
6753 "dwww",
6754 plci->RData[1].P,
6755 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6756 plci->RNum,
6757 plci->RFlags);
6758
6759 }
6760 else
6761 {
6762
6763 sendf(plci->appl, _DATA_B3_I, Id, 0,
6764 "dwww",
6765 plci->RData[0].P,
6766 plci->RData[0].PLength,
6767 plci->RNum,
6768 plci->RFlags);
6769
6770 }
6771 }
6772 return;
6773 }
6774
6775 fax_feature_bits = 0;
6776 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6777 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6778 (plci->NL.Ind & 0x0f) == N_DISC ||
6779 (plci->NL.Ind & 0x0f) == N_EDATA ||
6780 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6781 {
6782 info = 0;
6783 plci->ncpi_buffer[0] = 0;
6784 switch (plci->B3_prot) {
6785 case 0: /*XPARENT*/
6786 case 1: /*T.90 NL*/
6787 break; /* no network control protocol info - jfr */
6788 case 2: /*ISO8202*/
6789 case 3: /*X25 DCE*/
6790 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6791 plci->ncpi_buffer[0] = (byte)(i + 3);
6792 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6793 plci->ncpi_buffer[2] = 0;
6794 plci->ncpi_buffer[3] = 0;
6795 break;
6796 case 4: /*T.30 - FAX*/
6797 case 5: /*T.30 - FAX*/
6798 if (plci->NL.RLength >= sizeof(T30_INFO))
6799 {
6800 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6801 len = 9;
6802 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6803 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6804 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6805 if (plci->B3_prot == 5)
6806 {
6807 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6808 i |= 0x8000; /* This is not an ECM connection */
6809 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6810 i |= 0x4000; /* This is a connection with MMR compression */
6811 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6812 i |= 0x2000; /* This is a connection with MR compression */
6813 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6814 i |= 0x0004; /* More documents */
6815 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6816 i |= 0x0002; /* Fax-polling indication */
6817 }
6818 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6819 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6820 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6821 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6822 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6823 plci->ncpi_buffer[len] = 0;
6824 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6825 {
6826 plci->ncpi_buffer[len] = 20;
6827 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6828 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6829 }
6830 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6831 {
6832 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6833 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6834 else
6835 info = _FAX_PROTOCOL_ERROR;
6836 }
6837
6838 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6839 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6840 {
6841 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6842 while (i < plci->NL.RBuffer->length)
6843 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6844 }
6845
6846 plci->ncpi_buffer[0] = len;
6847 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6848 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6849
6850 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6851 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6852 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6853 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6854 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6855 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6856 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6857 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6858 {
6859 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6860 }
6861 if (((plci->NL.Ind & 0x0f) == N_DISC)
6862 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6863 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6864 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6865 {
6866 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6867 }
6868 }
6869 break;
6870
6871 case B3_RTP:
6872 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6873 {
6874 if (plci->NL.RLength != 0)
6875 {
6876 info = rtp_info[plci->NL.RBuffer->P[0]];
6877 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6878 for (i = 1; i < plci->NL.RLength; i++)
6879 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6880 }
6881 }
6882 break;
6883
6884 }
6885 plci->NL.RNR = 2;
6886 }
6887 switch (plci->NL.Ind & 0x0f) {
6888 case N_EDATA:
6889 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6890 {
6891 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6892 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6893 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6894
6895 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6896 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6897 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6898 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6899 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6900 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6901 {
6902 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6903 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6904 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6905 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6906 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6907 fax_send_edata_ack = false;
6908 }
6909
6910 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6911 {
6912 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6913 {
6914 case EDATA_T30_DIS:
6915 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6916 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6917 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6919 {
6920 a->ncci_state[ncci] = INC_ACT_PENDING;
6921 if (plci->B3_prot == 4)
6922 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6923 else
6924 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6925 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6926 }
6927 break;
6928
6929 case EDATA_T30_TRAIN_OK:
6930 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6931 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6932 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6933 {
6934 if (plci->B3_prot == 4)
6935 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6936 else
6937 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6938 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6939 }
6940 break;
6941
6942 case EDATA_T30_EOP_CAPI:
6943 if (a->ncci_state[ncci] == CONNECTED)
6944 {
6945 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6946 a->ncci_state[ncci] = INC_DIS_PENDING;
6947 plci->ncpi_state = 0;
6948 fax_send_edata_ack = false;
6949 }
6950 break;
6951 }
6952 }
6953 else
6954 {
6955 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6956 {
6957 case EDATA_T30_TRAIN_OK:
6958 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6959 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6960 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6961 {
6962 if (plci->B3_prot == 4)
6963 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6964 else
6965 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6966 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6967 }
6968 break;
6969 }
6970 }
6971 if (fax_send_edata_ack)
6972 {
6973 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6974 plci->fax_edata_ack_length = 1;
6975 start_internal_command(Id, plci, fax_edata_ack_command);
6976 }
6977 }
6978 else
6979 {
6980 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6981 }
6982 break;
6983 case N_CONNECT:
6984 if (!a->ch_ncci[ch])
6985 {
6986 ncci = get_ncci(plci, ch, 0);
6987 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6988 }
6989 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6990 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6991
6992 msg = _CONNECT_B3_I;
6993 if (a->ncci_state[ncci] == IDLE)
6994 plci->channels++;
6995 else if (plci->B3_prot == 1)
6996 msg = _CONNECT_B3_T90_ACTIVE_I;
6997
6998 a->ncci_state[ncci] = INC_CON_PENDING;
6999 if (plci->B3_prot == 4)
7000 sendf(plci->appl, msg, Id, 0, "s", "");
7001 else
7002 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7003 break;
7004 case N_CONNECT_ACK:
7005 dbug(1, dprintf("N_connect_Ack"));
7006 if (plci->internal_command_queue[0]
7007 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7008 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7009 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7010 {
7011 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7012 if (!plci->internal_command)
7013 next_internal_command(Id, plci);
7014 break;
7015 }
7016 msg = _CONNECT_B3_ACTIVE_I;
7017 if (plci->B3_prot == 1)
7018 {
7019 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7020 msg = _CONNECT_B3_T90_ACTIVE_I;
7021 a->ncci_state[ncci] = INC_ACT_PENDING;
7022 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7023 }
7024 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7025 {
7026 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7027 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7028 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7029 {
7030 a->ncci_state[ncci] = INC_ACT_PENDING;
7031 if (plci->B3_prot == 4)
7032 sendf(plci->appl, msg, Id, 0, "s", "");
7033 else
7034 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7035 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7036 }
7037 }
7038 else
7039 {
7040 a->ncci_state[ncci] = INC_ACT_PENDING;
7041 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7042 }
7043 if (plci->adjust_b_restore)
7044 {
7045 plci->adjust_b_restore = false;
7046 start_internal_command(Id, plci, adjust_b_restore);
7047 }
7048 break;
7049 case N_DISC:
7050 case N_DISC_ACK:
7051 if (plci->internal_command_queue[0]
7052 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7053 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7054 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7055 {
7056 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7057 if (!plci->internal_command)
7058 next_internal_command(Id, plci);
7059 }
7060 ncci_state = a->ncci_state[ncci];
7061 ncci_remove(plci, ncci, false);
7062
7063 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7064 /* channel, so we cannot store the state in ncci_state! The */
7065 /* information which channel we received a N_DISC is thus */
7066 /* stored in the inc_dis_ncci_table buffer. */
7067 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7068 plci->inc_dis_ncci_table[i] = (byte) ncci;
7069
7070 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7071 if (!plci->channels
7072 && (plci->B1_resource == 16)
7073 && (plci->State <= CONNECTED))
7074 {
7075 len = 9;
7076 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7077 PUT_WORD(&plci->ncpi_buffer[1], i);
7078 PUT_WORD(&plci->ncpi_buffer[3], 0);
7079 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7080 PUT_WORD(&plci->ncpi_buffer[5], i);
7081 PUT_WORD(&plci->ncpi_buffer[7], 0);
7082 plci->ncpi_buffer[len] = 0;
7083 plci->ncpi_buffer[0] = len;
7084 if (plci->B3_prot == 4)
7085 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7086 else
7087 {
7088
7089 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7090 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7091 {
7092 plci->ncpi_buffer[++len] = 0;
7093 plci->ncpi_buffer[++len] = 0;
7094 plci->ncpi_buffer[++len] = 0;
7095 plci->ncpi_buffer[0] = len;
7096 }
7097
7098 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7099 }
7100 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7101 plci->ncpi_state = 0;
7102 sig_req(plci, HANGUP, 0);
7103 send_req(plci);
7104 plci->State = OUTG_DIS_PENDING;
7105 /* disc here */
7106 }
7107 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7108 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7109 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7110 {
7111 if (ncci_state == IDLE)
7112 {
7113 if (plci->channels)
7114 plci->channels--;
7115 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7116 if (plci->State == SUSPENDING) {
7117 sendf(plci->appl,
7118 _FACILITY_I,
7119 Id & 0xffffL,
7120 0,
7121 "ws", (word)3, "\x03\x04\x00\x00");
7122 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7123 }
7124 plci_remove(plci);
7125 plci->State = IDLE;
7126 }
7127 }
7128 }
7129 else if (plci->channels)
7130 {
7131 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7132 plci->ncpi_state = 0;
7133 if ((ncci_state == OUTG_REJ_PENDING)
7134 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7135 {
7136 sig_req(plci, HANGUP, 0);
7137 send_req(plci);
7138 plci->State = OUTG_DIS_PENDING;
7139 }
7140 }
7141 break;
7142 case N_RESET:
7143 a->ncci_state[ncci] = INC_RES_PENDING;
7144 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7145 break;
7146 case N_RESET_ACK:
7147 a->ncci_state[ncci] = CONNECTED;
7148 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7149 break;
7150
7151 case N_UDATA:
7152 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7153 {
7154 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7155 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7156 plci->NL.R = plci->RData;
7157 plci->NL.RNum = 1;
7158 return;
7159 }
7160 case N_BDATA:
7161 case N_DATA:
7162 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7163 || (a->ncci_state[ncci] == IDLE)
7164 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7165 {
7166 plci->NL.RNR = 2;
7167 break;
7168 }
7169 if ((a->ncci_state[ncci] != CONNECTED)
7170 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7171 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7172 {
7173 dbug(1, dprintf("flow control"));
7174 plci->NL.RNR = 1; /* flow control */
7175 channel_x_off(plci, ch, 0);
7176 break;
7177 }
7178
7179 NCCIcode = ncci | (((word)a->Id) << 8);
7180
7181 /* count all buffers within the Application pool */
7182 /* belonging to the same NCCI. If this is below the */
7183 /* number of buffers available per NCCI we accept */
7184 /* this packet, otherwise we reject it */
7185 count = 0;
7186 Num = 0xffff;
7187 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7188 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7189 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7190 }
7191
7192 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7193 {
7194 dbug(3, dprintf("Flow-Control"));
7195 plci->NL.RNR = 1;
7196 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7197 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7198 {
7199 plci->NL.RNR = 2;
7200 dbug(3, dprintf("DiscardData"));
7201 } else {
7202 channel_x_off(plci, ch, 0);
7203 }
7204 break;
7205 }
7206 else
7207 {
7208 APPLptr->NCCIDataFlowCtrlTimer = 0;
7209 }
7210
7211 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7212 if (!plci->RData[0].P) {
7213 plci->NL.RNR = 1;
7214 channel_x_off(plci, ch, 0);
7215 break;
7216 }
7217
7218 APPLptr->DataNCCI[Num] = NCCIcode;
7219 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7220 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7221
7222 plci->RNum = Num;
7223 plci->RFlags = plci->NL.Ind >> 4;
7224 plci->RData[0].PLength = APPLptr->MaxDataLength;
7225 plci->NL.R = plci->RData;
7226 if ((plci->NL.RLength != 0)
7227 && ((plci->B2_prot == B2_V120_ASYNC)
7228 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7229 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7230 {
7231 plci->RData[1].P = plci->RData[0].P;
7232 plci->RData[1].PLength = plci->RData[0].PLength;
7233 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7234 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7235 plci->RData[0].PLength = 1;
7236 else
7237 plci->RData[0].PLength = 2;
7238 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7239 plci->RFlags |= 0x0010;
7240 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7241 plci->RFlags |= 0x8000;
7242 plci->NL.RNum = 2;
7243 }
7244 else
7245 {
7246 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7247 plci->RFlags |= 0x0010;
7248
7249 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7250 plci->RFlags |= 0x0001;
7251
7252 plci->NL.RNum = 1;
7253 }
7254 break;
7255 case N_DATA_ACK:
7256 data_ack(plci, ch);
7257 break;
7258 default:
7259 plci->NL.RNR = 2;
7260 break;
7261 }
7262 }
7263
7264 /*------------------------------------------------------------------*/
7265 /* find a free PLCI */
7266 /*------------------------------------------------------------------*/
7267
7268 static word get_plci(DIVA_CAPI_ADAPTER *a)
7269 {
7270 word i, j;
7271 PLCI *plci;
7272
7273 dump_plcis(a);
7274 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7275 if (i == a->max_plci) {
7276 dbug(1, dprintf("get_plci: out of PLCIs"));
7277 return 0;
7278 }
7279 plci = &a->plci[i];
7280 plci->Id = (byte)(i + 1);
7281
7282 plci->Sig.Id = 0;
7283 plci->NL.Id = 0;
7284 plci->sig_req = 0;
7285 plci->nl_req = 0;
7286
7287 plci->appl = NULL;
7288 plci->relatedPTYPLCI = NULL;
7289 plci->State = IDLE;
7290 plci->SuppState = IDLE;
7291 plci->channels = 0;
7292 plci->tel = 0;
7293 plci->B1_resource = 0;
7294 plci->B2_prot = 0;
7295 plci->B3_prot = 0;
7296
7297 plci->command = 0;
7298 plci->m_command = 0;
7299 init_internal_command_queue(plci);
7300 plci->number = 0;
7301 plci->req_in_start = 0;
7302 plci->req_in = 0;
7303 plci->req_out = 0;
7304 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7305 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7306 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7307
7308 plci->data_sent = false;
7309 plci->send_disc = 0;
7310 plci->sig_global_req = 0;
7311 plci->sig_remove_id = 0;
7312 plci->nl_global_req = 0;
7313 plci->nl_remove_id = 0;
7314 plci->adv_nl = 0;
7315 plci->manufacturer = false;
7316 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7317 plci->spoofed_msg = 0;
7318 plci->ptyState = 0;
7319 plci->cr_enquiry = false;
7320 plci->hangup_flow_ctrl_timer = 0;
7321
7322 plci->ncci_ring_list = 0;
7323 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7324 clear_c_ind_mask(plci);
7325 set_group_ind_mask(plci);
7326 plci->fax_connect_info_length = 0;
7327 plci->nsf_control_bits = 0;
7328 plci->ncpi_state = 0x00;
7329 plci->ncpi_buffer[0] = 0;
7330
7331 plci->requested_options_conn = 0;
7332 plci->requested_options = 0;
7333 plci->notifiedcall = 0;
7334 plci->vswitchstate = 0;
7335 plci->vsprot = 0;
7336 plci->vsprotdialect = 0;
7337 init_b1_config(plci);
7338 dbug(1, dprintf("get_plci(%x)", plci->Id));
7339 return i + 1;
7340 }
7341
7342 /*------------------------------------------------------------------*/
7343 /* put a parameter in the parameter buffer */
7344 /*------------------------------------------------------------------*/
7345
7346 static void add_p(PLCI *plci, byte code, byte *p)
7347 {
7348 word p_length;
7349
7350 p_length = 0;
7351 if (p) p_length = p[0];
7352 add_ie(plci, code, p, p_length);
7353 }
7354
7355 /*------------------------------------------------------------------*/
7356 /* put a structure in the parameter buffer */
7357 /*------------------------------------------------------------------*/
7358 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7359 {
7360 if (p) add_ie(plci, code, p->info, (word)p->length);
7361 }
7362
7363 /*------------------------------------------------------------------*/
7364 /* put multiple structures in the parameter buffer */
7365 /*------------------------------------------------------------------*/
7366 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7367 {
7368 byte i;
7369
7370 if (p) {
7371 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7372 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7373 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7374 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7375 }
7376 }
7377 }
7378
7379 /*------------------------------------------------------------------*/
7380 /* return the channel number sent by the application in a esc_chi */
7381 /*------------------------------------------------------------------*/
7382 static byte getChannel(API_PARSE *p)
7383 {
7384 byte i;
7385
7386 if (p) {
7387 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7388 if (p->info[i] == 2) {
7389 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7390 }
7391 }
7392 }
7393 return 0;
7394 }
7395
7396
7397 /*------------------------------------------------------------------*/
7398 /* put an information element in the parameter buffer */
7399 /*------------------------------------------------------------------*/
7400
7401 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7402 {
7403 word i;
7404
7405 if (!(code & 0x80) && !p_length) return;
7406
7407 if (plci->req_in == plci->req_in_start) {
7408 plci->req_in += 2;
7409 }
7410 else {
7411 plci->req_in--;
7412 }
7413 plci->RBuffer[plci->req_in++] = code;
7414
7415 if (p) {
7416 plci->RBuffer[plci->req_in++] = (byte)p_length;
7417 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7418 }
7419
7420 plci->RBuffer[plci->req_in++] = 0;
7421 }
7422
7423 /*------------------------------------------------------------------*/
7424 /* put a unstructured data into the buffer */
7425 /*------------------------------------------------------------------*/
7426
7427 static void add_d(PLCI *plci, word length, byte *p)
7428 {
7429 word i;
7430
7431 if (plci->req_in == plci->req_in_start) {
7432 plci->req_in += 2;
7433 }
7434 else {
7435 plci->req_in--;
7436 }
7437 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7438 }
7439
7440 /*------------------------------------------------------------------*/
7441 /* put parameters from the Additional Info parameter in the */
7442 /* parameter buffer */
7443 /*------------------------------------------------------------------*/
7444
7445 static void add_ai(PLCI *plci, API_PARSE *ai)
7446 {
7447 word i;
7448 API_PARSE ai_parms[5];
7449
7450 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7451
7452 if (!ai->length)
7453 return;
7454 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7455 return;
7456
7457 add_s(plci, KEY, &ai_parms[1]);
7458 add_s(plci, UUI, &ai_parms[2]);
7459 add_ss(plci, FTY, &ai_parms[3]);
7460 }
7461
7462 /*------------------------------------------------------------------*/
7463 /* put parameter for b1 protocol in the parameter buffer */
7464 /*------------------------------------------------------------------*/
7465
7466 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7467 word b1_facilities)
7468 {
7469 API_PARSE bp_parms[8];
7470 API_PARSE mdm_cfg[9];
7471 API_PARSE global_config[2];
7472 byte cai[256];
7473 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7474 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7475 word i;
7476
7477 API_PARSE mdm_cfg_v18[4];
7478 word j, n, w;
7479 dword d;
7480
7481
7482 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7483 for (i = 0; i < 2; i++) global_config[i].length = 0;
7484
7485 dbug(1, dprintf("add_b1"));
7486 api_save_msg(bp, "s", &plci->B_protocol);
7487
7488 if (b_channel_info == 2) {
7489 plci->B1_resource = 0;
7490 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7491 add_p(plci, CAI, "\x01\x00");
7492 dbug(1, dprintf("Cai=1,0 (no resource)"));
7493 return 0;
7494 }
7495
7496 if (plci->tel == CODEC_PERMANENT) return 0;
7497 else if (plci->tel == CODEC) {
7498 plci->B1_resource = 1;
7499 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7500 add_p(plci, CAI, "\x01\x01");
7501 dbug(1, dprintf("Cai=1,1 (Codec)"));
7502 return 0;
7503 }
7504 else if (plci->tel == ADV_VOICE) {
7505 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7506 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7507 voice_cai[1] = plci->B1_resource;
7508 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7509 add_p(plci, CAI, voice_cai);
7510 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7511 return 0;
7512 }
7513 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7514 if (plci->call_dir & CALL_DIR_OUT)
7515 plci->call_dir |= CALL_DIR_ORIGINATE;
7516 else if (plci->call_dir & CALL_DIR_IN)
7517 plci->call_dir |= CALL_DIR_ANSWER;
7518
7519 if (!bp->length) {
7520 plci->B1_resource = 0x5;
7521 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7522 add_p(plci, CAI, "\x01\x05");
7523 return 0;
7524 }
7525
7526 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7527 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7528 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7529 {
7530 bp_parms[6].length = 0;
7531 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7532 {
7533 dbug(1, dprintf("b-form.!"));
7534 return _WRONG_MESSAGE_FORMAT;
7535 }
7536 }
7537 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7538 {
7539 dbug(1, dprintf("b-form.!"));
7540 return _WRONG_MESSAGE_FORMAT;
7541 }
7542
7543 if (bp_parms[6].length)
7544 {
7545 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7546 {
7547 return _WRONG_MESSAGE_FORMAT;
7548 }
7549 switch (GET_WORD(global_config[0].info))
7550 {
7551 case 1:
7552 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7553 break;
7554 case 2:
7555 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7556 break;
7557 }
7558 }
7559 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7560
7561
7562 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7563 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7564 {
7565 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567 cai[1] = plci->B1_resource;
7568 cai[2] = 0;
7569 cai[3] = 0;
7570 cai[4] = 0;
7571 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7572 for (i = 0; i < bp_parms[3].length; i++)
7573 cai[7 + i] = bp_parms[3].info[1 + i];
7574 cai[0] = 6 + bp_parms[3].length;
7575 add_p(plci, CAI, cai);
7576 return 0;
7577 }
7578
7579
7580 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7581 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7582 {
7583 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7584 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7585 cai[1] = plci->B1_resource;
7586 cai[2] = 0;
7587 cai[3] = 0;
7588 cai[4] = 0;
7589 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7590 cai[0] = 6;
7591 add_p(plci, CAI, cai);
7592 return 0;
7593 }
7594
7595
7596 if ((GET_WORD(bp_parms[0].info) >= 32)
7597 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7598 && ((GET_WORD(bp_parms[0].info) != 3)
7599 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7600 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7601 {
7602 return _B1_NOT_SUPPORTED;
7603 }
7604 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7605 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7606 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7607 cai[0] = 6;
7608 cai[1] = plci->B1_resource;
7609 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7610
7611 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7612 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7613 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7614 { /* B1 - modem */
7615 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7616
7617 if (bp_parms[3].length)
7618 {
7619 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7620 {
7621 return (_WRONG_MESSAGE_FORMAT);
7622 }
7623
7624 cai[2] = 0; /* Bit rate for adaptation */
7625
7626 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7627
7628 PUT_WORD(&cai[13], 0); /* Min Tx speed */
7629 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7630 PUT_WORD(&cai[17], 0); /* Min Rx speed */
7631 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7632
7633 cai[3] = 0; /* Async framing parameters */
7634 switch (GET_WORD(mdm_cfg[2].info))
7635 { /* Parity */
7636 case 1: /* odd parity */
7637 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7638 dbug(1, dprintf("MDM: odd parity"));
7639 break;
7640
7641 case 2: /* even parity */
7642 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7643 dbug(1, dprintf("MDM: even parity"));
7644 break;
7645
7646 default:
7647 dbug(1, dprintf("MDM: no parity"));
7648 break;
7649 }
7650
7651 switch (GET_WORD(mdm_cfg[3].info))
7652 { /* stop bits */
7653 case 1: /* 2 stop bits */
7654 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7655 dbug(1, dprintf("MDM: 2 stop bits"));
7656 break;
7657
7658 default:
7659 dbug(1, dprintf("MDM: 1 stop bit"));
7660 break;
7661 }
7662
7663 switch (GET_WORD(mdm_cfg[1].info))
7664 { /* char length */
7665 case 5:
7666 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7667 dbug(1, dprintf("MDM: 5 bits"));
7668 break;
7669
7670 case 6:
7671 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7672 dbug(1, dprintf("MDM: 6 bits"));
7673 break;
7674
7675 case 7:
7676 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7677 dbug(1, dprintf("MDM: 7 bits"));
7678 break;
7679
7680 default:
7681 dbug(1, dprintf("MDM: 8 bits"));
7682 break;
7683 }
7684
7685 cai[7] = 0; /* Line taking options */
7686 cai[8] = 0; /* Modulation negotiation options */
7687 cai[9] = 0; /* Modulation options */
7688
7689 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7690 {
7691 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7692 dbug(1, dprintf("MDM: Reverse direction"));
7693 }
7694
7695 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7696 {
7697 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7698 dbug(1, dprintf("MDM: Disable retrain"));
7699 }
7700
7701 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7702 {
7703 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7704 dbug(1, dprintf("MDM: Disable ring tone"));
7705 }
7706
7707 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7708 {
7709 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7710 dbug(1, dprintf("MDM: 1800 guard tone"));
7711 }
7712 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7713 {
7714 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7715 dbug(1, dprintf("MDM: 550 guard tone"));
7716 }
7717
7718 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7719 {
7720 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7721 dbug(1, dprintf("MDM: V100"));
7722 }
7723 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7724 {
7725 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7726 dbug(1, dprintf("MDM: IN CLASS"));
7727 }
7728 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7729 {
7730 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7731 dbug(1, dprintf("MDM: DISABLED"));
7732 }
7733 cai[0] = 20;
7734
7735 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7736 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7737 {
7738 plci->requested_options |= 1L << PRIVATE_V18;
7739 }
7740 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7741 plci->requested_options |= 1L << PRIVATE_VOWN;
7742
7743 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7744 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7745 {
7746 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7747 {
7748 i = 27;
7749 if (mdm_cfg[6].length >= 4)
7750 {
7751 d = GET_DWORD(&mdm_cfg[6].info[1]);
7752 cai[7] |= (byte) d; /* line taking options */
7753 cai[9] |= (byte)(d >> 8); /* modulation options */
7754 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7755 cai[++i] = (byte)(d >> 24);
7756 if (mdm_cfg[6].length >= 8)
7757 {
7758 d = GET_DWORD(&mdm_cfg[6].info[5]);
7759 cai[10] |= (byte) d; /* disabled modulations mask */
7760 cai[11] |= (byte)(d >> 8);
7761 if (mdm_cfg[6].length >= 12)
7762 {
7763 d = GET_DWORD(&mdm_cfg[6].info[9]);
7764 cai[12] = (byte) d; /* enabled modulations mask */
7765 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7766 cai[++i] = (byte)(d >> 16);
7767 cai[++i] = (byte)(d >> 24);
7768 cai[++i] = 0;
7769 if (mdm_cfg[6].length >= 14)
7770 {
7771 w = GET_WORD(&mdm_cfg[6].info[13]);
7772 if (w != 0)
7773 PUT_WORD(&cai[13], w); /* min tx speed */
7774 if (mdm_cfg[6].length >= 16)
7775 {
7776 w = GET_WORD(&mdm_cfg[6].info[15]);
7777 if (w != 0)
7778 PUT_WORD(&cai[15], w); /* max tx speed */
7779 if (mdm_cfg[6].length >= 18)
7780 {
7781 w = GET_WORD(&mdm_cfg[6].info[17]);
7782 if (w != 0)
7783 PUT_WORD(&cai[17], w); /* min rx speed */
7784 if (mdm_cfg[6].length >= 20)
7785 {
7786 w = GET_WORD(&mdm_cfg[6].info[19]);
7787 if (w != 0)
7788 PUT_WORD(&cai[19], w); /* max rx speed */
7789 if (mdm_cfg[6].length >= 22)
7790 {
7791 w = GET_WORD(&mdm_cfg[6].info[21]);
7792 cai[23] = (byte)(-((short) w)); /* transmit level */
7793 if (mdm_cfg[6].length >= 24)
7794 {
7795 w = GET_WORD(&mdm_cfg[6].info[23]);
7796 cai[22] |= (byte) w; /* info options mask */
7797 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7798 }
7799 }
7800 }
7801 }
7802 }
7803 }
7804 }
7805 }
7806 }
7807 cai[27] = i - 27;
7808 i++;
7809 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7810 {
7811 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7812 {
7813 for (n = 0; n < 3; n++)
7814 {
7815 cai[i] = (byte)(mdm_cfg_v18[n].length);
7816 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7817 cai[i + j] = mdm_cfg_v18[n].info[j];
7818 i += cai[i] + 1;
7819 }
7820 }
7821 }
7822 cai[0] = (byte)(i - 1);
7823 }
7824 }
7825
7826 }
7827 }
7828 if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7829 GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7830 {
7831 if (bp_parms[3].length) {
7832 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7833 switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7834 case 0:
7835 case 56000:
7836 if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7837 dbug(1, dprintf("56k sync HSCX"));
7838 cai[1] = 8;
7839 cai[2] = 0;
7840 cai[3] = 0;
7841 }
7842 else if (GET_WORD(bp_parms[0].info) == 2) {
7843 dbug(1, dprintf("56k async DSP"));
7844 cai[2] = 9;
7845 }
7846 break;
7847 case 50: cai[2] = 1; break;
7848 case 75: cai[2] = 1; break;
7849 case 110: cai[2] = 1; break;
7850 case 150: cai[2] = 1; break;
7851 case 200: cai[2] = 1; break;
7852 case 300: cai[2] = 1; break;
7853 case 600: cai[2] = 1; break;
7854 case 1200: cai[2] = 2; break;
7855 case 2400: cai[2] = 3; break;
7856 case 4800: cai[2] = 4; break;
7857 case 7200: cai[2] = 10; break;
7858 case 9600: cai[2] = 5; break;
7859 case 12000: cai[2] = 13; break;
7860 case 24000: cai[2] = 0; break;
7861 case 14400: cai[2] = 11; break;
7862 case 19200: cai[2] = 6; break;
7863 case 28800: cai[2] = 12; break;
7864 case 38400: cai[2] = 7; break;
7865 case 48000: cai[2] = 8; break;
7866 case 76: cai[2] = 15; break; /* 75/1200 */
7867 case 1201: cai[2] = 14; break; /* 1200/75 */
7868 case 56001: cai[2] = 9; break; /* V.110 56000 */
7869
7870 default:
7871 return _B1_PARM_NOT_SUPPORTED;
7872 }
7873 cai[3] = 0;
7874 if (cai[1] == 13) /* v.110 async */
7875 {
7876 if (bp_parms[3].length >= 8)
7877 {
7878 switch (GET_WORD(&bp_parms[3].info[3]))
7879 { /* char length */
7880 case 5:
7881 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7882 break;
7883 case 6:
7884 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7885 break;
7886 case 7:
7887 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7888 break;
7889 }
7890 switch (GET_WORD(&bp_parms[3].info[5]))
7891 { /* Parity */
7892 case 1: /* odd parity */
7893 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7894 break;
7895 case 2: /* even parity */
7896 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7897 break;
7898 }
7899 switch (GET_WORD(&bp_parms[3].info[7]))
7900 { /* stop bits */
7901 case 1: /* 2 stop bits */
7902 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7903 break;
7904 }
7905 }
7906 }
7907 }
7908 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7909 dbug(1, dprintf("V.110 default 56k sync"));
7910 cai[1] = 8;
7911 cai[2] = 0;
7912 cai[3] = 0;
7913 }
7914 else {
7915 dbug(1, dprintf("V.110 default 9600 async"));
7916 cai[2] = 5;
7917 }
7918 }
7919 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7920 dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7921 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7922
7923 add_p(plci, CAI, cai);
7924 return 0;
7925 }
7926
7927 /*------------------------------------------------------------------*/
7928 /* put parameter for b2 and B3 protocol in the parameter buffer */
7929 /*------------------------------------------------------------------*/
7930
7931 static word add_b23(PLCI *plci, API_PARSE *bp)
7932 {
7933 word i, fax_control_bits;
7934 byte pos, len;
7935 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7936 API_PARSE bp_parms[8];
7937 API_PARSE *b1_config;
7938 API_PARSE *b2_config;
7939 API_PARSE b2_config_parms[8];
7940 API_PARSE *b3_config;
7941 API_PARSE b3_config_parms[6];
7942 API_PARSE global_config[2];
7943
7944 static byte llc[3] = {2,0,0};
7945 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7946 static byte nlc[256];
7947 static byte lli[12] = {1,1};
7948
7949 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7950 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7951
7952 const byte llc3[] = {4,3,2,2,6,6,0};
7953 const byte header[] = {0,2,3,3,0,0,0};
7954
7955 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7956 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7957 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7958
7959 lli[0] = 1;
7960 lli[1] = 1;
7961 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7962 lli[1] |= 2;
7963 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7964 lli[1] |= 4;
7965
7966 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7967 lli[1] |= 0x10;
7968 if (plci->rx_dma_descriptor <= 0) {
7969 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7970 if (plci->rx_dma_descriptor >= 0)
7971 plci->rx_dma_descriptor++;
7972 }
7973 if (plci->rx_dma_descriptor > 0) {
7974 lli[0] = 6;
7975 lli[1] |= 0x40;
7976 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7977 lli[3] = (byte)plci->rx_dma_magic;
7978 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7979 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7980 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7981 }
7982 }
7983
7984 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7985 lli[1] |= 0x20;
7986 }
7987
7988 dbug(1, dprintf("add_b23"));
7989 api_save_msg(bp, "s", &plci->B_protocol);
7990
7991 if (!bp->length && plci->tel)
7992 {
7993 plci->adv_nl = true;
7994 dbug(1, dprintf("Default adv.Nl"));
7995 add_p(plci, LLI, lli);
7996 plci->B2_prot = 1 /*XPARENT*/;
7997 plci->B3_prot = 0 /*XPARENT*/;
7998 llc[1] = 2;
7999 llc[2] = 4;
8000 add_p(plci, LLC, llc);
8001 dlc[0] = 2;
8002 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8003 add_p(plci, DLC, dlc);
8004 return 0;
8005 }
8006
8007 if (!bp->length) /*default*/
8008 {
8009 dbug(1, dprintf("ret default"));
8010 add_p(plci, LLI, lli);
8011 plci->B2_prot = 0 /*X.75 */;
8012 plci->B3_prot = 0 /*XPARENT*/;
8013 llc[1] = 1;
8014 llc[2] = 4;
8015 add_p(plci, LLC, llc);
8016 dlc[0] = 2;
8017 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8018 add_p(plci, DLC, dlc);
8019 return 0;
8020 }
8021 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8022 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8023
8024 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8025 {
8026 bp_parms[6].length = 0;
8027 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8028 {
8029 dbug(1, dprintf("b-form.!"));
8030 return _WRONG_MESSAGE_FORMAT;
8031 }
8032 }
8033 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8034 {
8035 dbug(1, dprintf("b-form.!"));
8036 return _WRONG_MESSAGE_FORMAT;
8037 }
8038
8039 if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8040 {
8041 if (GET_WORD(bp_parms[1].info) != 1
8042 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8043 plci->adv_nl = true;
8044 }
8045 else if (plci->tel) return _B2_NOT_SUPPORTED;
8046
8047
8048 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8049 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8050 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8051 {
8052 add_p(plci, LLI, lli);
8053 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8054 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8055 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8056 llc[2] = 4;
8057 add_p(plci, LLC, llc);
8058 dlc[0] = 2;
8059 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8060 dlc[3] = 3; /* Addr A */
8061 dlc[4] = 1; /* Addr B */
8062 dlc[5] = 7; /* modulo mode */
8063 dlc[6] = 7; /* window size */
8064 dlc[7] = 0; /* XID len Lo */
8065 dlc[8] = 0; /* XID len Hi */
8066 for (i = 0; i < bp_parms[4].length; i++)
8067 dlc[9 + i] = bp_parms[4].info[1 + i];
8068 dlc[0] = (byte)(8 + bp_parms[4].length);
8069 add_p(plci, DLC, dlc);
8070 for (i = 0; i < bp_parms[5].length; i++)
8071 nlc[1 + i] = bp_parms[5].info[1 + i];
8072 nlc[0] = (byte)(bp_parms[5].length);
8073 add_p(plci, NLC, nlc);
8074 return 0;
8075 }
8076
8077
8078
8079 if ((GET_WORD(bp_parms[1].info) >= 32)
8080 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8081 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8082 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8083
8084 {
8085 return _B2_NOT_SUPPORTED;
8086 }
8087 if ((GET_WORD(bp_parms[2].info) >= 32)
8088 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8089 {
8090 return _B3_NOT_SUPPORTED;
8091 }
8092 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8093 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8094 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8095 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8096 {
8097 return (add_modem_b23(plci, bp_parms));
8098 }
8099
8100 add_p(plci, LLI, lli);
8101
8102 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8103 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8104 if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8105
8106 if (bp_parms[6].length)
8107 {
8108 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8109 {
8110 return _WRONG_MESSAGE_FORMAT;
8111 }
8112 switch (GET_WORD(global_config[0].info))
8113 {
8114 case 1:
8115 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8116 break;
8117 case 2:
8118 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8119 break;
8120 }
8121 }
8122 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8123
8124
8125 if (plci->B2_prot == B2_PIAFS)
8126 llc[1] = PIAFS_CRC;
8127 else
8128 /* IMPLEMENT_PIAFS */
8129 {
8130 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8131 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8132 }
8133 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8134
8135 add_p(plci, LLC, llc);
8136
8137 dlc[0] = 2;
8138 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8139 header[GET_WORD(bp_parms[2].info)]);
8140
8141 b1_config = &bp_parms[3];
8142 nlc[0] = 0;
8143 if (plci->B3_prot == 4
8144 || plci->B3_prot == 5)
8145 {
8146 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8147 nlc[0] = sizeof(T30_INFO);
8148 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8149 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8150 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8151 if (b1_config->length >= 2)
8152 {
8153 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8154 }
8155 }
8156 b2_config = &bp_parms[4];
8157
8158
8159 if (llc[1] == PIAFS_CRC)
8160 {
8161 if (plci->B3_prot != B3_TRANSPARENT)
8162 {
8163 return _B_STACK_NOT_SUPPORTED;
8164 }
8165 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8166 return _WRONG_MESSAGE_FORMAT;
8167 }
8168 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8169 dlc[3] = 0; /* Addr A */
8170 dlc[4] = 0; /* Addr B */
8171 dlc[5] = 0; /* modulo mode */
8172 dlc[6] = 0; /* window size */
8173 if (b2_config->length >= 7) {
8174 dlc[7] = 7;
8175 dlc[8] = 0;
8176 dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8177 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8178 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8179 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8180 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8181 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8182 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8183 dlc[0] = 15;
8184 if (b2_config->length >= 8) { /* PIAFS control abilities */
8185 dlc[7] = 10;
8186 dlc[16] = 2; /* Length of PIAFS extension */
8187 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8188 dlc[18] = b2_config_parms[4].info[0]; /* value */
8189 dlc[0] = 18;
8190 }
8191 }
8192 else /* default values, 64K, variable, no compression */
8193 {
8194 dlc[7] = 7;
8195 dlc[8] = 0;
8196 dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8197 dlc[10] = 0x03; /* V.42bis P0 */
8198 dlc[11] = 0; /* V.42bis P0 */
8199 dlc[12] = 0; /* V.42bis P1 */
8200 dlc[13] = 0; /* V.42bis P1 */
8201 dlc[14] = 0; /* V.42bis P2 */
8202 dlc[15] = 0; /* V.42bis P2 */
8203 dlc[0] = 15;
8204 }
8205 add_p(plci, DLC, dlc);
8206 }
8207 else
8208
8209 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8210 {
8211 if (plci->B3_prot != B3_TRANSPARENT)
8212 return _B_STACK_NOT_SUPPORTED;
8213
8214 dlc[0] = 6;
8215 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8216 dlc[3] = 0x08;
8217 dlc[4] = 0x01;
8218 dlc[5] = 127;
8219 dlc[6] = 7;
8220 if (b2_config->length != 0)
8221 {
8222 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8223 return _WRONG_MESSAGE_FORMAT;
8224 }
8225 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8226 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8227 if (b2_config->info[3] != 128)
8228 {
8229 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8230 return _B2_PARM_NOT_SUPPORTED;
8231 }
8232 dlc[5] = (byte)(b2_config->info[3] - 1);
8233 dlc[6] = b2_config->info[4];
8234 if (llc[1] == V120_V42BIS) {
8235 if (b2_config->length >= 10) {
8236 dlc[7] = 6;
8237 dlc[8] = 0;
8238 dlc[9] = b2_config_parms[4].info[0];
8239 dlc[10] = b2_config_parms[4].info[1];
8240 dlc[11] = b2_config_parms[5].info[0];
8241 dlc[12] = b2_config_parms[5].info[1];
8242 dlc[13] = b2_config_parms[6].info[0];
8243 dlc[14] = b2_config_parms[6].info[1];
8244 dlc[0] = 14;
8245 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8246 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8247 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8248 }
8249 else {
8250 dlc[6] = 14;
8251 }
8252 }
8253 }
8254 }
8255 else
8256 {
8257 if (b2_config->length)
8258 {
8259 dbug(1, dprintf("B2-Config"));
8260 if (llc[1] == X75_V42BIS) {
8261 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8262 {
8263 return _WRONG_MESSAGE_FORMAT;
8264 }
8265 }
8266 else {
8267 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8268 {
8269 return _WRONG_MESSAGE_FORMAT;
8270 }
8271 }
8272 /* if B2 Protocol is LAPD, b2_config structure is different */
8273 if (llc[1] == 6)
8274 {
8275 dlc[0] = 4;
8276 if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8277 else dlc[2] = 0x01;
8278 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8279 {
8280 SAPI = b2_config->info[2]; /* SAPI */
8281 }
8282 dlc[1] = SAPI;
8283 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8284 {
8285 dlc[3] = 127; /* Mode */
8286 }
8287 else
8288 {
8289 dlc[3] = 7; /* Mode */
8290 }
8291
8292 if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8293 else dlc[4] = 1;
8294 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8295 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8296 }
8297 else
8298 {
8299 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8300 dlc[3] = b2_config->info[1];
8301 dlc[4] = b2_config->info[2];
8302 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8303 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8304 return _B2_PARM_NOT_SUPPORTED;
8305 }
8306
8307 dlc[5] = (byte)(b2_config->info[3] - 1);
8308 dlc[6] = b2_config->info[4];
8309 if (dlc[6] > dlc[5]) {
8310 dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8311 return _B2_PARM_NOT_SUPPORTED;
8312 }
8313
8314 if (llc[1] == X75_V42BIS) {
8315 if (b2_config->length >= 10) {
8316 dlc[7] = 6;
8317 dlc[8] = 0;
8318 dlc[9] = b2_config_parms[4].info[0];
8319 dlc[10] = b2_config_parms[4].info[1];
8320 dlc[11] = b2_config_parms[5].info[0];
8321 dlc[12] = b2_config_parms[5].info[1];
8322 dlc[13] = b2_config_parms[6].info[0];
8323 dlc[14] = b2_config_parms[6].info[1];
8324 dlc[0] = 14;
8325 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8326 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8327 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8328 }
8329 else {
8330 dlc[6] = 14;
8331 }
8332
8333 }
8334 else {
8335 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8336 for (i = 0; i < b2_config_parms[4].length; i++)
8337 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8338 }
8339 }
8340 }
8341 }
8342 add_p(plci, DLC, dlc);
8343
8344 b3_config = &bp_parms[5];
8345 if (b3_config->length)
8346 {
8347 if (plci->B3_prot == 4
8348 || plci->B3_prot == 5)
8349 {
8350 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8351 {
8352 return _WRONG_MESSAGE_FORMAT;
8353 }
8354 i = GET_WORD((byte *)(b3_config_parms[0].info));
8355 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8356 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8357 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8358 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8359 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8360 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8361 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8362 {
8363
8364 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8365 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8366 {
8367 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8368 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8369 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8370 }
8371
8372 ((T30_INFO *)&nlc[1])->recording_properties =
8373 T30_RECORDING_WIDTH_ISO_A3 |
8374 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8375 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8376 }
8377 if (plci->B3_prot == 5)
8378 {
8379 if (i & 0x0002) /* Accept incoming fax-polling requests */
8380 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8381 if (i & 0x2000) /* Do not use MR compression */
8382 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8383 if (i & 0x4000) /* Do not use MMR compression */
8384 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8385 if (i & 0x8000) /* Do not use ECM */
8386 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8387 if (plci->fax_connect_info_length != 0)
8388 {
8389 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8390 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8391 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8392 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8393 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8394 }
8395 }
8396 /* copy station id to NLC */
8397 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8398 {
8399 if (i < b3_config_parms[2].length)
8400 {
8401 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8402 }
8403 else
8404 {
8405 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8406 }
8407 }
8408 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8409 /* copy head line to NLC */
8410 if (b3_config_parms[3].length)
8411 {
8412
8413 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8414 if (pos != 0)
8415 {
8416 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8417 pos = 0;
8418 else
8419 {
8420 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8421 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8422 len = (byte)b3_config_parms[2].length;
8423 if (len > 20)
8424 len = 20;
8425 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8426 {
8427 for (i = 0; i < len; i++)
8428 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8429 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8430 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8431 }
8432 }
8433 }
8434
8435 len = (byte)b3_config_parms[3].length;
8436 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8437 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8438 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8439 nlc[0] += (byte)(pos + len);
8440 for (i = 0; i < len; i++)
8441 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8442 } else
8443 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8444
8445 plci->nsf_control_bits = 0;
8446 if (plci->B3_prot == 5)
8447 {
8448 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8449 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8450 {
8451 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8452 }
8453 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8454 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8455 {
8456 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8457 }
8458 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8459 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8460 {
8461 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8462 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8463 {
8464 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8465 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8466 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8467 }
8468 len = nlc[0];
8469 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8470 if (pos < plci->fax_connect_info_length)
8471 {
8472 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8473 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8474 }
8475 else
8476 nlc[++len] = 0;
8477 if (pos < plci->fax_connect_info_length)
8478 {
8479 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8481 }
8482 else
8483 nlc[++len] = 0;
8484 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8485 & (1L << PRIVATE_FAX_NONSTANDARD))
8486 {
8487 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8488 {
8489 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8490 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8491 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8492 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8493 }
8494 else
8495 {
8496 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8497 {
8498 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8499 nlc[++len] = 0;
8500 }
8501 else
8502 {
8503 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8504 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8505 nlc[++len] = (byte)(b3_config_parms[4].length);
8506 for (i = 0; i < b3_config_parms[4].length; i++)
8507 nlc[++len] = b3_config_parms[4].info[1 + i];
8508 }
8509 }
8510 }
8511 nlc[0] = len;
8512 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8513 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8514 {
8515 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8516 }
8517 }
8518 }
8519
8520 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8521 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8522 for (i = 0; i < len; i++)
8523 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8524 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8525 i += ((T30_INFO *)&nlc[1])->head_line_len;
8526 while (i < nlc[0])
8527 plci->fax_connect_info_buffer[len++] = nlc[++i];
8528 plci->fax_connect_info_length = len;
8529 }
8530 else
8531 {
8532 nlc[0] = 14;
8533 if (b3_config->length != 16)
8534 return _B3_PARM_NOT_SUPPORTED;
8535 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8536 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8537 return _B3_PARM_NOT_SUPPORTED;
8538 nlc[13] = b3_config->info[13];
8539 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8540 return _B3_PARM_NOT_SUPPORTED;
8541 nlc[14] = b3_config->info[15];
8542 }
8543 }
8544 else
8545 {
8546 if (plci->B3_prot == 4
8547 || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8548 }
8549 add_p(plci, NLC, nlc);
8550 return 0;
8551 }
8552
8553 /*----------------------------------------------------------------*/
8554 /* make the same as add_b23, but only for the modem related */
8555 /* L2 and L3 B-Chan protocol. */
8556 /* */
8557 /* Enabled L2 and L3 Configurations: */
8558 /* If L1 == Modem all negotiation */
8559 /* only L2 == Modem with full negotiation is allowed */
8560 /* If L1 == Modem async or sync */
8561 /* only L2 == Transparent is allowed */
8562 /* L3 == Modem or L3 == Transparent are allowed */
8563 /* B2 Configuration for modem: */
8564 /* word : enable/disable compression, bitoptions */
8565 /* B3 Configuration for modem: */
8566 /* empty */
8567 /*----------------------------------------------------------------*/
8568 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8569 {
8570 static byte lli[12] = {1,1};
8571 static byte llc[3] = {2,0,0};
8572 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8573 API_PARSE mdm_config[2];
8574 word i;
8575 word b2_config = 0;
8576
8577 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8578 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8579
8580 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8581 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8582 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8583 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8584 {
8585 return (_B_STACK_NOT_SUPPORTED);
8586 }
8587 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8588 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8589 {
8590 return (_B_STACK_NOT_SUPPORTED);
8591 }
8592
8593 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8594 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8595
8596 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8597 {
8598 if (api_parse(&bp_parms[4].info[1],
8599 (word)bp_parms[4].length, "w",
8600 mdm_config))
8601 {
8602 return (_WRONG_MESSAGE_FORMAT);
8603 }
8604 b2_config = GET_WORD(mdm_config[0].info);
8605 }
8606
8607 /* OK, L2 is modem */
8608
8609 lli[0] = 1;
8610 lli[1] = 1;
8611 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8612 lli[1] |= 2;
8613 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8614 lli[1] |= 4;
8615
8616 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8617 lli[1] |= 0x10;
8618 if (plci->rx_dma_descriptor <= 0) {
8619 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8620 if (plci->rx_dma_descriptor >= 0)
8621 plci->rx_dma_descriptor++;
8622 }
8623 if (plci->rx_dma_descriptor > 0) {
8624 lli[1] |= 0x40;
8625 lli[0] = 6;
8626 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8627 lli[3] = (byte)plci->rx_dma_magic;
8628 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8629 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8630 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8631 }
8632 }
8633
8634 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8635 lli[1] |= 0x20;
8636 }
8637
8638 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8639 /*V42*/ 10 : /*V42_IN*/ 9;
8640 llc[2] = 4; /* pass L3 always transparent */
8641 add_p(plci, LLI, lli);
8642 add_p(plci, LLC, llc);
8643 i = 1;
8644 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8645 i += 2;
8646 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8647 {
8648 if (bp_parms[4].length)
8649 {
8650 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8651 dlc[i++] = 3; /* Addr A */
8652 dlc[i++] = 1; /* Addr B */
8653 dlc[i++] = 7; /* modulo mode */
8654 dlc[i++] = 7; /* window size */
8655 dlc[i++] = 0; /* XID len Lo */
8656 dlc[i++] = 0; /* XID len Hi */
8657
8658 if (b2_config & MDM_B2_DISABLE_V42bis)
8659 {
8660 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8661 }
8662 if (b2_config & MDM_B2_DISABLE_MNP)
8663 {
8664 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8665 }
8666 if (b2_config & MDM_B2_DISABLE_TRANS)
8667 {
8668 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8669 }
8670 if (b2_config & MDM_B2_DISABLE_V42)
8671 {
8672 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8673 }
8674 if (b2_config & MDM_B2_DISABLE_COMP)
8675 {
8676 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8677 }
8678 i++;
8679 }
8680 }
8681 else
8682 {
8683 dlc[i++] = 3; /* Addr A */
8684 dlc[i++] = 1; /* Addr B */
8685 dlc[i++] = 7; /* modulo mode */
8686 dlc[i++] = 7; /* window size */
8687 dlc[i++] = 0; /* XID len Lo */
8688 dlc[i++] = 0; /* XID len Hi */
8689 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8690 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8691 DLC_MODEMPROT_DISABLE_V42_DETECT |
8692 DLC_MODEMPROT_DISABLE_COMPRESSION;
8693 }
8694 dlc[0] = (byte)(i - 1);
8695 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8696 add_p(plci, DLC, dlc);
8697 return (0);
8698 }
8699
8700
8701 /*------------------------------------------------------------------*/
8702 /* send a request for the signaling entity */
8703 /*------------------------------------------------------------------*/
8704
8705 static void sig_req(PLCI *plci, byte req, byte Id)
8706 {
8707 if (!plci) return;
8708 if (plci->adapter->adapter_disabled) return;
8709 dbug(1, dprintf("sig_req(%x)", req));
8710 if (req == REMOVE)
8711 plci->sig_remove_id = plci->Sig.Id;
8712 if (plci->req_in == plci->req_in_start) {
8713 plci->req_in += 2;
8714 plci->RBuffer[plci->req_in++] = 0;
8715 }
8716 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8717 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8718 plci->RBuffer[plci->req_in++] = req; /* request */
8719 plci->RBuffer[plci->req_in++] = 0; /* channel */
8720 plci->req_in_start = plci->req_in;
8721 }
8722
8723 /*------------------------------------------------------------------*/
8724 /* send a request for the network layer entity */
8725 /*------------------------------------------------------------------*/
8726
8727 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8728 {
8729 if (!plci) return;
8730 if (plci->adapter->adapter_disabled) return;
8731 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8732 if (req == REMOVE)
8733 {
8734 plci->nl_remove_id = plci->NL.Id;
8735 ncci_remove(plci, 0, (byte)(ncci != 0));
8736 ncci = 0;
8737 }
8738 if (plci->req_in == plci->req_in_start) {
8739 plci->req_in += 2;
8740 plci->RBuffer[plci->req_in++] = 0;
8741 }
8742 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8743 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8744 plci->RBuffer[plci->req_in++] = req; /* request */
8745 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8746 plci->req_in_start = plci->req_in;
8747 }
8748
8749 static void send_req(PLCI *plci)
8750 {
8751 ENTITY *e;
8752 word l;
8753 /* word i; */
8754
8755 if (!plci) return;
8756 if (plci->adapter->adapter_disabled) return;
8757 channel_xmit_xon(plci);
8758
8759 /* if nothing to do, return */
8760 if (plci->req_in == plci->req_out) return;
8761 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8762
8763 if (plci->nl_req || plci->sig_req) return;
8764
8765 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8766 plci->req_out += 2;
8767 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8768 plci->req_out += l;
8769 if (plci->RBuffer[plci->req_out] == 1)
8770 {
8771 e = &plci->NL;
8772 plci->req_out++;
8773 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8774 e->ReqCh = plci->RBuffer[plci->req_out++];
8775 if (!(e->Id & 0x1f))
8776 {
8777 e->Id = NL_ID;
8778 plci->RBuffer[plci->req_out - 4] = CAI;
8779 plci->RBuffer[plci->req_out - 3] = 1;
8780 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8781 plci->RBuffer[plci->req_out - 1] = 0;
8782 l += 3;
8783 plci->nl_global_req = plci->nl_req;
8784 }
8785 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8786 }
8787 else
8788 {
8789 e = &plci->Sig;
8790 if (plci->RBuffer[plci->req_out])
8791 e->Id = plci->RBuffer[plci->req_out];
8792 plci->req_out++;
8793 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8794 e->ReqCh = plci->RBuffer[plci->req_out++];
8795 if (!(e->Id & 0x1f))
8796 plci->sig_global_req = plci->sig_req;
8797 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8798 }
8799 plci->XData[0].PLength = l;
8800 e->X = plci->XData;
8801 plci->adapter->request(e);
8802 dbug(1, dprintf("send_ok"));
8803 }
8804
8805 static void send_data(PLCI *plci)
8806 {
8807 DIVA_CAPI_ADAPTER *a;
8808 DATA_B3_DESC *data;
8809 NCCI *ncci_ptr;
8810 word ncci;
8811
8812 if (!plci->nl_req && plci->ncci_ring_list)
8813 {
8814 a = plci->adapter;
8815 ncci = plci->ncci_ring_list;
8816 do
8817 {
8818 ncci = a->ncci_next[ncci];
8819 ncci_ptr = &(a->ncci[ncci]);
8820 if (!(a->ncci_ch[ncci]
8821 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8822 {
8823 if (ncci_ptr->data_pending)
8824 {
8825 if ((a->ncci_state[ncci] == CONNECTED)
8826 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8827 || (plci->send_disc == ncci))
8828 {
8829 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8830 if ((plci->B2_prot == B2_V120_ASYNC)
8831 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8832 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8833 {
8834 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8835 plci->NData[1].PLength = data->Length;
8836 if (data->Flags & 0x10)
8837 plci->NData[0].P = v120_break_header;
8838 else
8839 plci->NData[0].P = v120_default_header;
8840 plci->NData[0].PLength = 1;
8841 plci->NL.XNum = 2;
8842 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8843 }
8844 else
8845 {
8846 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8847 plci->NData[0].PLength = data->Length;
8848 if (data->Flags & 0x10)
8849 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8850
8851 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8852 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8853
8854 else
8855 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8856 }
8857 plci->NL.X = plci->NData;
8858 plci->NL.ReqCh = a->ncci_ch[ncci];
8859 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8860 plci->data_sent = true;
8861 plci->data_sent_ptr = data->P;
8862 a->request(&plci->NL);
8863 }
8864 else {
8865 cleanup_ncci_data(plci, ncci);
8866 }
8867 }
8868 else if (plci->send_disc == ncci)
8869 {
8870 /* dprintf("N_DISC"); */
8871 plci->NData[0].PLength = 0;
8872 plci->NL.ReqCh = a->ncci_ch[ncci];
8873 plci->NL.Req = plci->nl_req = N_DISC;
8874 a->request(&plci->NL);
8875 plci->command = _DISCONNECT_B3_R;
8876 plci->send_disc = 0;
8877 }
8878 }
8879 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8880 plci->ncci_ring_list = ncci;
8881 }
8882 }
8883
8884 static void listen_check(DIVA_CAPI_ADAPTER *a)
8885 {
8886 word i, j;
8887 PLCI *plci;
8888 byte activnotifiedcalls = 0;
8889
8890 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8891 if (!remove_started && !a->adapter_disabled)
8892 {
8893 for (i = 0; i < a->max_plci; i++)
8894 {
8895 plci = &(a->plci[i]);
8896 if (plci->notifiedcall) activnotifiedcalls++;
8897 }
8898 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8899
8900 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8901 if ((j = get_plci(a))) {
8902 a->listen_active++;
8903 plci = &a->plci[j - 1];
8904 plci->State = LISTENING;
8905
8906 add_p(plci, OAD, "\x01\xfd");
8907
8908 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8909
8910 add_p(plci, CAI, "\x01\xc0");
8911 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8912 add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8913 add_p(plci, SHIFT | 6, NULL);
8914 add_p(plci, SIN, "\x02\x00\x00");
8915 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8916 sig_req(plci, ASSIGN, DSIG_ID);
8917 send_req(plci);
8918 }
8919 }
8920 }
8921 }
8922
8923 /*------------------------------------------------------------------*/
8924 /* functions for all parameters sent in INDs */
8925 /*------------------------------------------------------------------*/
8926
8927 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8928 {
8929 word ploc; /* points to current location within packet */
8930 byte w;
8931 byte wlen;
8932 byte codeset, lock;
8933 byte *in;
8934 word i;
8935 word code;
8936 word mIEindex = 0;
8937 ploc = 0;
8938 codeset = 0;
8939 lock = 0;
8940
8941 in = plci->Sig.RBuffer->P;
8942 for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8943 { /* element but parms array is larger */
8944 parms[i] = (byte *)"";
8945 }
8946 for (i = 0; i < multiIEsize; i++)
8947 {
8948 parms[i] = (byte *)"";
8949 }
8950
8951 while (ploc < plci->Sig.RBuffer->length - 1) {
8952
8953 /* read information element id and length */
8954 w = in[ploc];
8955
8956 if (w & 0x80) {
8957 /* w &=0xf0; removed, cannot detect congestion levels */
8958 /* upper 4 bit masked with w==SHIFT now */
8959 wlen = 0;
8960 }
8961 else {
8962 wlen = (byte)(in[ploc + 1] + 1);
8963 }
8964 /* check if length valid (not exceeding end of packet) */
8965 if ((ploc + wlen) > 270) return;
8966 if (lock & 0x80) lock &= 0x7f;
8967 else codeset = lock;
8968
8969 if ((w & 0xf0) == SHIFT) {
8970 codeset = in[ploc];
8971 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8972 codeset &= 7;
8973 lock |= 0x80;
8974 }
8975 else {
8976 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8977 else code = w;
8978 code |= (codeset << 8);
8979
8980 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8981
8982 if (i < parms_id[0] + 1) {
8983 if (!multiIEsize) { /* with multiIEs use next field index, */
8984 mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8985 }
8986
8987 parms[mIEindex] = &in[ploc + 1];
8988 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8989 if (parms_id[i] == OAD
8990 || parms_id[i] == CONN_NR
8991 || parms_id[i] == CAD) {
8992 if (in[ploc + 2] & 0x80) {
8993 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8994 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8995 in[ploc + 2] = 0x80;
8996 parms[mIEindex] = &in[ploc];
8997 }
8998 }
8999 mIEindex++; /* effects multiIEs only */
9000 }
9001 }
9002
9003 ploc += (wlen + 1);
9004 }
9005 return;
9006 }
9007
9008 /*------------------------------------------------------------------*/
9009 /* try to match a cip from received BC and HLC */
9010 /*------------------------------------------------------------------*/
9011
9012 static byte ie_compare(byte *ie1, byte *ie2)
9013 {
9014 word i;
9015 if (!ie1 || !ie2) return false;
9016 if (!ie1[0]) return false;
9017 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9018 return true;
9019 }
9020
9021 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9022 {
9023 word i;
9024 word j;
9025
9026 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9027
9028 for (j = 16; j < 29 &&
9029 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9030 if (j == 29) return i;
9031 return j;
9032 }
9033
9034
9035 static byte AddInfo(byte **add_i,
9036 byte **fty_i,
9037 byte *esc_chi,
9038 byte *facility)
9039 {
9040 byte i;
9041 byte j;
9042 byte k;
9043 byte flen;
9044 byte len = 0;
9045 /* facility is a nested structure */
9046 /* FTY can be more than once */
9047
9048 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9049 {
9050 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9051 }
9052
9053 else
9054 {
9055 add_i[0] = (byte *)"";
9056 }
9057 if (!fty_i[0][0])
9058 {
9059 add_i[3] = (byte *)"";
9060 }
9061 else
9062 { /* facility array found */
9063 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9064 {
9065 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9066 len += fty_i[i][0];
9067 len += 2;
9068 flen = fty_i[i][0];
9069 facility[j++] = 0x1c; /* copy fac IE */
9070 for (k = 0; k <= flen; k++, j++)
9071 {
9072 facility[j] = fty_i[i][k];
9073 /* dbug(1, dprintf("%x ",facility[j])); */
9074 }
9075 }
9076 facility[0] = len;
9077 add_i[3] = facility;
9078 }
9079 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
9080 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9081 len += 4; /* calculate length of all */
9082 return (len);
9083 }
9084
9085 /*------------------------------------------------------------------*/
9086 /* voice and codec features */
9087 /*------------------------------------------------------------------*/
9088
9089 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9090 {
9091 byte voice_chi[] = "\x02\x18\x01";
9092 byte channel;
9093
9094 channel = chi[chi[0]] & 0x3;
9095 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9096 voice_chi[2] = (channel) ? channel : 1;
9097 add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
9098 add_p(plci, ESC, voice_chi); /* Channel */
9099 sig_req(plci, TEL_CTRL, 0);
9100 send_req(plci);
9101 if (a->AdvSignalPLCI)
9102 {
9103 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9104 }
9105 }
9106
9107 static void VoiceChannelOff(PLCI *plci)
9108 {
9109 dbug(1, dprintf("ExtDevOFF"));
9110 add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
9111 sig_req(plci, TEL_CTRL, 0);
9112 send_req(plci);
9113 if (plci->adapter->AdvSignalPLCI)
9114 {
9115 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9116 }
9117 }
9118
9119
9120 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9121 byte hook_listen)
9122 {
9123 word j;
9124 PLCI *splci;
9125
9126 /* check if hardware supports handset with hook states (adv.codec) */
9127 /* or if just a on board codec is supported */
9128 /* the advanced codec plci is just for internal use */
9129
9130 /* diva Pro with on-board codec: */
9131 if (a->profile.Global_Options & HANDSET)
9132 {
9133 /* new call, but hook states are already signalled */
9134 if (a->AdvCodecFLAG)
9135 {
9136 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9137 {
9138 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9139 return 0x2001; /* codec in use by another application */
9140 }
9141 if (plci != NULL)
9142 {
9143 a->AdvSignalPLCI = plci;
9144 plci->tel = ADV_VOICE;
9145 }
9146 return 0; /* adv codec still used */
9147 }
9148 if ((j = get_plci(a)))
9149 {
9150 splci = &a->plci[j - 1];
9151 splci->tel = CODEC_PERMANENT;
9152 /* hook_listen indicates if a facility_req with handset/hook support */
9153 /* was sent. Otherwise if just a call on an external device was made */
9154 /* the codec will be used but the hook info will be discarded (just */
9155 /* the external controller is in use */
9156 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9157 else
9158 {
9159 splci->State = ADVANCED_VOICE_NOSIG;
9160 if (plci)
9161 {
9162 plci->spoofed_msg = SPOOFING_REQUIRED;
9163 }
9164 /* indicate D-ch connect if */
9165 } /* codec is connected OK */
9166 if (plci != NULL)
9167 {
9168 a->AdvSignalPLCI = plci;
9169 plci->tel = ADV_VOICE;
9170 }
9171 a->AdvSignalAppl = appl;
9172 a->AdvCodecFLAG = true;
9173 a->AdvCodecPLCI = splci;
9174 add_p(splci, CAI, "\x01\x15");
9175 add_p(splci, LLI, "\x01\x00");
9176 add_p(splci, ESC, "\x02\x18\x00");
9177 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9178 splci->internal_command = PERM_COD_ASSIGN;
9179 dbug(1, dprintf("Codec Assign"));
9180 sig_req(splci, ASSIGN, DSIG_ID);
9181 send_req(splci);
9182 }
9183 else
9184 {
9185 return 0x2001; /* wrong state, no more plcis */
9186 }
9187 }
9188 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9189 {
9190 if (hook_listen) return 0x300B; /* Facility not supported */
9191 /* no hook with SCOM */
9192 if (plci != NULL) plci->tel = CODEC;
9193 dbug(1, dprintf("S/SCOM codec"));
9194 /* first time we use the scom-s codec we must shut down the internal */
9195 /* handset application of the card. This can be done by an assign with */
9196 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9197 if (!a->scom_appl_disable) {
9198 if ((j = get_plci(a))) {
9199 splci = &a->plci[j - 1];
9200 add_p(splci, CAI, "\x01\x80");
9201 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9202 sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9203 send_req(splci);
9204 a->scom_appl_disable = true;
9205 }
9206 else{
9207 return 0x2001; /* wrong state, no more plcis */
9208 }
9209 }
9210 }
9211 else return 0x300B; /* Facility not supported */
9212
9213 return 0;
9214 }
9215
9216
9217 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9218 {
9219
9220 dbug(1, dprintf("CodecIdCheck"));
9221
9222 if (a->AdvSignalPLCI == plci)
9223 {
9224 dbug(1, dprintf("PLCI owns codec"));
9225 VoiceChannelOff(a->AdvCodecPLCI);
9226 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9227 {
9228 dbug(1, dprintf("remove temp codec PLCI"));
9229 plci_remove(a->AdvCodecPLCI);
9230 a->AdvCodecFLAG = 0;
9231 a->AdvCodecPLCI = NULL;
9232 a->AdvSignalAppl = NULL;
9233 }
9234 a->AdvSignalPLCI = NULL;
9235 }
9236 }
9237
9238 /* -------------------------------------------------------------------
9239 Ask for physical address of card on PCI bus
9240 ------------------------------------------------------------------- */
9241 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9242 IDI_SYNC_REQ *preq) {
9243 a->sdram_bar = 0;
9244 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9245 ENTITY *e = (ENTITY *)preq;
9246
9247 e->user[0] = a->Id - 1;
9248 preq->xdi_sdram_bar.info.bar = 0;
9249 preq->xdi_sdram_bar.Req = 0;
9250 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9251
9252 (*(a->request))(e);
9253
9254 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9255 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9256 }
9257 }
9258
9259 /* -------------------------------------------------------------------
9260 Ask XDI about extended features
9261 ------------------------------------------------------------------- */
9262 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9263 IDI_SYNC_REQ *preq;
9264 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9265
9266 char features[4];
9267 preq = (IDI_SYNC_REQ *)&buffer[0];
9268
9269 if (!diva_xdi_extended_features) {
9270 ENTITY *e = (ENTITY *)preq;
9271 diva_xdi_extended_features |= 0x80000000;
9272
9273 e->user[0] = a->Id - 1;
9274 preq->xdi_extended_features.Req = 0;
9275 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9276 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9277 preq->xdi_extended_features.info.features = &features[0];
9278
9279 (*(a->request))(e);
9280
9281 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9282 /*
9283 Check features located in the byte '0'
9284 */
9285 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9286 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9287 }
9288 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9289 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9290 dbug(1, dprintf("XDI provides RxDMA"));
9291 }
9292 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9293 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9294 }
9295 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9296 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9297 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9298 }
9299
9300 }
9301 }
9302
9303 diva_ask_for_xdi_sdram_bar(a, preq);
9304 }
9305
9306 /*------------------------------------------------------------------*/
9307 /* automatic law */
9308 /*------------------------------------------------------------------*/
9309 /* called from OS specific part after init time to get the Law */
9310 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9311 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9312 {
9313 word j;
9314 PLCI *splci;
9315
9316 if (a->automatic_law) {
9317 return;
9318 }
9319 if ((j = get_plci(a))) {
9320 diva_get_extended_adapter_features(a);
9321 splci = &a->plci[j - 1];
9322 a->automatic_lawPLCI = splci;
9323 a->automatic_law = 1;
9324 add_p(splci, CAI, "\x01\x80");
9325 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9326 splci->internal_command = USELAW_REQ;
9327 splci->command = 0;
9328 splci->number = 0;
9329 sig_req(splci, ASSIGN, DSIG_ID);
9330 send_req(splci);
9331 }
9332 }
9333
9334 /* called from OS specific part if an application sends an Capi20Release */
9335 word CapiRelease(word Id)
9336 {
9337 word i, j, appls_found;
9338 PLCI *plci;
9339 APPL *this;
9340 DIVA_CAPI_ADAPTER *a;
9341
9342 if (!Id)
9343 {
9344 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9345 return (_WRONG_APPL_ID);
9346 }
9347
9348 this = &application[Id - 1]; /* get application pointer */
9349
9350 for (i = 0, appls_found = 0; i < max_appl; i++)
9351 {
9352 if (application[i].Id) /* an application has been found */
9353 {
9354 appls_found++;
9355 }
9356 }
9357
9358 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9359 {
9360 a = &adapter[i];
9361 if (a->request)
9362 {
9363 a->Info_Mask[Id - 1] = 0;
9364 a->CIP_Mask[Id - 1] = 0;
9365 a->Notification_Mask[Id - 1] = 0;
9366 a->codec_listen[Id - 1] = NULL;
9367 a->requested_options_table[Id - 1] = 0;
9368 for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9369 { /* with this application */
9370 plci = &a->plci[j];
9371 if (plci->Id) /* if plci owns no application */
9372 { /* it may be not jet connected */
9373 if (plci->State == INC_CON_PENDING
9374 || plci->State == INC_CON_ALERT)
9375 {
9376 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9377 {
9378 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9379 if (c_ind_mask_empty(plci))
9380 {
9381 sig_req(plci, HANGUP, 0);
9382 send_req(plci);
9383 plci->State = OUTG_DIS_PENDING;
9384 }
9385 }
9386 }
9387 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9388 {
9389 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9390 if (c_ind_mask_empty(plci))
9391 {
9392 if (!plci->appl)
9393 {
9394 plci_remove(plci);
9395 plci->State = IDLE;
9396 }
9397 }
9398 }
9399 if (plci->appl == this)
9400 {
9401 plci->appl = NULL;
9402 plci_remove(plci);
9403 plci->State = IDLE;
9404 }
9405 }
9406 }
9407 listen_check(a);
9408
9409 if (a->flag_dynamic_l1_down)
9410 {
9411 if (appls_found == 1) /* last application does a capi release */
9412 {
9413 if ((j = get_plci(a)))
9414 {
9415 plci = &a->plci[j - 1];
9416 plci->command = 0;
9417 add_p(plci, OAD, "\x01\xfd");
9418 add_p(plci, CAI, "\x01\x80");
9419 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9420 add_p(plci, SHIFT | 6, NULL);
9421 add_p(plci, SIN, "\x02\x00\x00");
9422 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9423 sig_req(plci, ASSIGN, DSIG_ID);
9424 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9425 sig_req(plci, SIG_CTRL, 0);
9426 send_req(plci);
9427 }
9428 }
9429 }
9430 if (a->AdvSignalAppl == this)
9431 {
9432 this->NullCREnable = false;
9433 if (a->AdvCodecPLCI)
9434 {
9435 plci_remove(a->AdvCodecPLCI);
9436 a->AdvCodecPLCI->tel = 0;
9437 a->AdvCodecPLCI->adv_nl = 0;
9438 }
9439 a->AdvSignalAppl = NULL;
9440 a->AdvSignalPLCI = NULL;
9441 a->AdvCodecFLAG = 0;
9442 a->AdvCodecPLCI = NULL;
9443 }
9444 }
9445 }
9446
9447 this->Id = 0;
9448
9449 return GOOD;
9450 }
9451
9452 static word plci_remove_check(PLCI *plci)
9453 {
9454 if (!plci) return true;
9455 if (!plci->NL.Id && c_ind_mask_empty(plci))
9456 {
9457 if (plci->Sig.Id == 0xff)
9458 plci->Sig.Id = 0;
9459 if (!plci->Sig.Id)
9460 {
9461 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9462 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9463 if (plci->Id)
9464 {
9465 CodecIdCheck(plci->adapter, plci);
9466 clear_b1_config(plci);
9467 ncci_remove(plci, 0, false);
9468 plci_free_msg_in_queue(plci);
9469 channel_flow_control_remove(plci);
9470 plci->Id = 0;
9471 plci->State = IDLE;
9472 plci->channels = 0;
9473 plci->appl = NULL;
9474 plci->notifiedcall = 0;
9475 }
9476 listen_check(plci->adapter);
9477 return true;
9478 }
9479 }
9480 return false;
9481 }
9482
9483
9484 /*------------------------------------------------------------------*/
9485
9486 static byte plci_nl_busy(PLCI *plci)
9487 {
9488 /* only applicable for non-multiplexed protocols */
9489 return (plci->nl_req
9490 || (plci->ncci_ring_list
9491 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9492 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9493 }
9494
9495
9496 /*------------------------------------------------------------------*/
9497 /* DTMF facilities */
9498 /*------------------------------------------------------------------*/
9499
9500
9501 static struct
9502 {
9503 byte send_mask;
9504 byte listen_mask;
9505 byte character;
9506 byte code;
9507 } dtmf_digit_map[] =
9508 {
9509 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9510 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9511 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9512 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9513 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9514 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9515 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9516 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9517 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9518 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9519 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9520 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9521 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9522 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9523 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9524 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9525 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9526 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9527 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9528 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9529
9530 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9531 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9532 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9533 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9534 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9535 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9536 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9537 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9538 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9539 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9540 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9541 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9542 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9543 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9544 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9545 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9546 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9547 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9548 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9549 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9550 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9551 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9552 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9553 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9554 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9555 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9556 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9557 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9558 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9559 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9560 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9561 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9562 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9563 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9564 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9565 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9566 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9567 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9568 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9569 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9570 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9571 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9572 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9573 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9574 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9575 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9576 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9577 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9578 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9579 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9580 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9581 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9582
9583 };
9584
9585 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9586
9587
9588 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9589 {
9590 word min_digit_duration, min_gap_duration;
9591
9592 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9593 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9594 (char *)(FILE_), __LINE__, enable_mask));
9595
9596 if (enable_mask != 0)
9597 {
9598 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9599 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9600 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9601 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9602 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9603 plci->NData[0].PLength = 5;
9604
9605 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9606 plci->NData[0].PLength += 2;
9607 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9608
9609 }
9610 else
9611 {
9612 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9613 plci->NData[0].PLength = 1;
9614
9615 capidtmf_recv_disable(&(plci->capidtmf_state));
9616
9617 }
9618 plci->NData[0].P = plci->internal_req_buffer;
9619 plci->NL.X = plci->NData;
9620 plci->NL.ReqCh = 0;
9621 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9622 plci->adapter->request(&plci->NL);
9623 }
9624
9625
9626 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9627 {
9628 word w, i;
9629
9630 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9631 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9632 (char *)(FILE_), __LINE__, digit_count));
9633
9634 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9635 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9636 PUT_WORD(&plci->internal_req_buffer[1], w);
9637 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9638 PUT_WORD(&plci->internal_req_buffer[3], w);
9639 for (i = 0; i < digit_count; i++)
9640 {
9641 w = 0;
9642 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9643 && (digit_buffer[i] != dtmf_digit_map[w].character))
9644 {
9645 w++;
9646 }
9647 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9648 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9649 }
9650 plci->NData[0].PLength = 5 + digit_count;
9651 plci->NData[0].P = plci->internal_req_buffer;
9652 plci->NL.X = plci->NData;
9653 plci->NL.ReqCh = 0;
9654 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9655 plci->adapter->request(&plci->NL);
9656 }
9657
9658
9659 static void dtmf_rec_clear_config(PLCI *plci)
9660 {
9661
9662 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9663 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9664 (char *)(FILE_), __LINE__));
9665
9666 plci->dtmf_rec_active = 0;
9667 plci->dtmf_rec_pulse_ms = 0;
9668 plci->dtmf_rec_pause_ms = 0;
9669
9670 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9671
9672 }
9673
9674
9675 static void dtmf_send_clear_config(PLCI *plci)
9676 {
9677
9678 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9679 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9680 (char *)(FILE_), __LINE__));
9681
9682 plci->dtmf_send_requests = 0;
9683 plci->dtmf_send_pulse_ms = 0;
9684 plci->dtmf_send_pause_ms = 0;
9685 }
9686
9687
9688 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9689 {
9690
9691 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9692 UnMapId(Id), (char *)(FILE_), __LINE__));
9693
9694 while (plci->dtmf_send_requests != 0)
9695 dtmf_confirmation(Id, plci);
9696 }
9697
9698
9699 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9700 {
9701
9702 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9703 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9704
9705 return (GOOD);
9706 }
9707
9708
9709 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9710 {
9711 word Info;
9712
9713 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9714 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9715
9716 Info = GOOD;
9717 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9718 {
9719 switch (plci->adjust_b_state)
9720 {
9721 case ADJUST_B_RESTORE_DTMF_1:
9722 plci->internal_command = plci->adjust_b_command;
9723 if (plci_nl_busy(plci))
9724 {
9725 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9726 break;
9727 }
9728 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9729 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9730 break;
9731 case ADJUST_B_RESTORE_DTMF_2:
9732 if ((Rc != OK) && (Rc != OK_FC))
9733 {
9734 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9735 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9736 Info = _WRONG_STATE;
9737 break;
9738 }
9739 break;
9740 }
9741 }
9742 return (Info);
9743 }
9744
9745
9746 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9747 {
9748 word internal_command, Info;
9749 byte mask;
9750 byte result[4];
9751
9752 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9753 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9754 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9755 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9756
9757 Info = GOOD;
9758 result[0] = 2;
9759 PUT_WORD(&result[1], DTMF_SUCCESS);
9760 internal_command = plci->internal_command;
9761 plci->internal_command = 0;
9762 mask = 0x01;
9763 switch (plci->dtmf_cmd)
9764 {
9765
9766 case DTMF_LISTEN_TONE_START:
9767 mask <<= 1;
9768 case DTMF_LISTEN_MF_START:
9769 mask <<= 1;
9770
9771 case DTMF_LISTEN_START:
9772 switch (internal_command)
9773 {
9774 default:
9775 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9776 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9777 case DTMF_COMMAND_1:
9778 if (adjust_b_process(Id, plci, Rc) != GOOD)
9779 {
9780 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9781 UnMapId(Id), (char *)(FILE_), __LINE__));
9782 Info = _FACILITY_NOT_SUPPORTED;
9783 break;
9784 }
9785 if (plci->internal_command)
9786 return;
9787 case DTMF_COMMAND_2:
9788 if (plci_nl_busy(plci))
9789 {
9790 plci->internal_command = DTMF_COMMAND_2;
9791 return;
9792 }
9793 plci->internal_command = DTMF_COMMAND_3;
9794 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9795 return;
9796 case DTMF_COMMAND_3:
9797 if ((Rc != OK) && (Rc != OK_FC))
9798 {
9799 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9800 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9801 Info = _FACILITY_NOT_SUPPORTED;
9802 break;
9803 }
9804
9805 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9806
9807 plci->dtmf_rec_active |= mask;
9808 break;
9809 }
9810 break;
9811
9812
9813 case DTMF_LISTEN_TONE_STOP:
9814 mask <<= 1;
9815 case DTMF_LISTEN_MF_STOP:
9816 mask <<= 1;
9817
9818 case DTMF_LISTEN_STOP:
9819 switch (internal_command)
9820 {
9821 default:
9822 plci->dtmf_rec_active &= ~mask;
9823 if (plci->dtmf_rec_active)
9824 break;
9825 /*
9826 case DTMF_COMMAND_1:
9827 if (plci->dtmf_rec_active)
9828 {
9829 if (plci_nl_busy (plci))
9830 {
9831 plci->internal_command = DTMF_COMMAND_1;
9832 return;
9833 }
9834 plci->dtmf_rec_active &= ~mask;
9835 plci->internal_command = DTMF_COMMAND_2;
9836 dtmf_enable_receiver (plci, false);
9837 return;
9838 }
9839 Rc = OK;
9840 case DTMF_COMMAND_2:
9841 if ((Rc != OK) && (Rc != OK_FC))
9842 {
9843 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9844 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9845 Info = _FACILITY_NOT_SUPPORTED;
9846 break;
9847 }
9848 */
9849 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9850 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9851 case DTMF_COMMAND_3:
9852 if (adjust_b_process(Id, plci, Rc) != GOOD)
9853 {
9854 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9855 UnMapId(Id), (char *)(FILE_), __LINE__));
9856 Info = _FACILITY_NOT_SUPPORTED;
9857 break;
9858 }
9859 if (plci->internal_command)
9860 return;
9861 break;
9862 }
9863 break;
9864
9865
9866 case DTMF_SEND_TONE:
9867 mask <<= 1;
9868 case DTMF_SEND_MF:
9869 mask <<= 1;
9870
9871 case DTMF_DIGITS_SEND:
9872 switch (internal_command)
9873 {
9874 default:
9875 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9876 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9877 DTMF_COMMAND_1);
9878 case DTMF_COMMAND_1:
9879 if (adjust_b_process(Id, plci, Rc) != GOOD)
9880 {
9881 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9882 UnMapId(Id), (char *)(FILE_), __LINE__));
9883 Info = _FACILITY_NOT_SUPPORTED;
9884 break;
9885 }
9886 if (plci->internal_command)
9887 return;
9888 case DTMF_COMMAND_2:
9889 if (plci_nl_busy(plci))
9890 {
9891 plci->internal_command = DTMF_COMMAND_2;
9892 return;
9893 }
9894 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9895 plci->internal_command = DTMF_COMMAND_3;
9896 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9897 return;
9898 case DTMF_COMMAND_3:
9899 if ((Rc != OK) && (Rc != OK_FC))
9900 {
9901 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9902 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9903 if (plci->dtmf_send_requests != 0)
9904 (plci->dtmf_send_requests)--;
9905 Info = _FACILITY_NOT_SUPPORTED;
9906 break;
9907 }
9908 return;
9909 }
9910 break;
9911 }
9912 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9913 "wws", Info, SELECTOR_DTMF, result);
9914 }
9915
9916
9917 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9918 {
9919 word Info;
9920 word i, j;
9921 byte mask;
9922 API_PARSE dtmf_parms[5];
9923 byte result[40];
9924
9925 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9926 UnMapId(Id), (char *)(FILE_), __LINE__));
9927
9928 Info = GOOD;
9929 result[0] = 2;
9930 PUT_WORD(&result[1], DTMF_SUCCESS);
9931 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9932 {
9933 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9934 UnMapId(Id), (char *)(FILE_), __LINE__));
9935 Info = _FACILITY_NOT_SUPPORTED;
9936 }
9937 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9938 {
9939 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9940 UnMapId(Id), (char *)(FILE_), __LINE__));
9941 Info = _WRONG_MESSAGE_FORMAT;
9942 }
9943
9944 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9945 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9946 {
9947 if (!((a->requested_options_table[appl->Id - 1])
9948 & (1L << PRIVATE_DTMF_TONE)))
9949 {
9950 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9951 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9952 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9953 }
9954 else
9955 {
9956 for (i = 0; i < 32; i++)
9957 result[4 + i] = 0;
9958 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9959 {
9960 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9961 {
9962 if (dtmf_digit_map[i].listen_mask != 0)
9963 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9964 }
9965 }
9966 else
9967 {
9968 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9969 {
9970 if (dtmf_digit_map[i].send_mask != 0)
9971 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9972 }
9973 }
9974 result[0] = 3 + 32;
9975 result[3] = 32;
9976 }
9977 }
9978
9979 else if (plci == NULL)
9980 {
9981 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9982 UnMapId(Id), (char *)(FILE_), __LINE__));
9983 Info = _WRONG_IDENTIFIER;
9984 }
9985 else
9986 {
9987 if (!plci->State
9988 || !plci->NL.Id || plci->nl_remove_id)
9989 {
9990 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9991 UnMapId(Id), (char *)(FILE_), __LINE__));
9992 Info = _WRONG_STATE;
9993 }
9994 else
9995 {
9996 plci->command = 0;
9997 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9998 mask = 0x01;
9999 switch (plci->dtmf_cmd)
10000 {
10001
10002 case DTMF_LISTEN_TONE_START:
10003 case DTMF_LISTEN_TONE_STOP:
10004 mask <<= 1;
10005 case DTMF_LISTEN_MF_START:
10006 case DTMF_LISTEN_MF_STOP:
10007 mask <<= 1;
10008 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10009 & (1L << PRIVATE_DTMF_TONE)))
10010 {
10011 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10012 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10013 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10014 break;
10015 }
10016
10017 case DTMF_LISTEN_START:
10018 case DTMF_LISTEN_STOP:
10019 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10020 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10021 {
10022 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10023 UnMapId(Id), (char *)(FILE_), __LINE__));
10024 Info = _FACILITY_NOT_SUPPORTED;
10025 break;
10026 }
10027 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10028 {
10029 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10030 {
10031 plci->dtmf_rec_pulse_ms = 0;
10032 plci->dtmf_rec_pause_ms = 0;
10033 }
10034 else
10035 {
10036 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10037 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10038 }
10039 }
10040 start_internal_command(Id, plci, dtmf_command);
10041 return (false);
10042
10043
10044 case DTMF_SEND_TONE:
10045 mask <<= 1;
10046 case DTMF_SEND_MF:
10047 mask <<= 1;
10048 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10049 & (1L << PRIVATE_DTMF_TONE)))
10050 {
10051 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10052 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10053 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10054 break;
10055 }
10056
10057 case DTMF_DIGITS_SEND:
10058 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10059 {
10060 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10061 UnMapId(Id), (char *)(FILE_), __LINE__));
10062 Info = _WRONG_MESSAGE_FORMAT;
10063 break;
10064 }
10065 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10066 {
10067 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10068 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10069 }
10070 i = 0;
10071 j = 0;
10072 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10073 {
10074 j = 0;
10075 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10076 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10077 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10078 {
10079 j++;
10080 }
10081 i++;
10082 }
10083 if (j == DTMF_DIGIT_MAP_ENTRIES)
10084 {
10085 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10086 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10087 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10088 break;
10089 }
10090 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10091 {
10092 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10093 UnMapId(Id), (char *)(FILE_), __LINE__));
10094 Info = _WRONG_STATE;
10095 break;
10096 }
10097 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10098 start_internal_command(Id, plci, dtmf_command);
10099 return (false);
10100
10101 default:
10102 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10103 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10104 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10105 }
10106 }
10107 }
10108 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10109 "wws", Info, SELECTOR_DTMF, result);
10110 return (false);
10111 }
10112
10113
10114 static void dtmf_confirmation(dword Id, PLCI *plci)
10115 {
10116 word i;
10117 byte result[4];
10118
10119 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10120 UnMapId(Id), (char *)(FILE_), __LINE__));
10121
10122 result[0] = 2;
10123 PUT_WORD(&result[1], DTMF_SUCCESS);
10124 if (plci->dtmf_send_requests != 0)
10125 {
10126 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10127 "wws", GOOD, SELECTOR_DTMF, result);
10128 (plci->dtmf_send_requests)--;
10129 for (i = 0; i < plci->dtmf_send_requests; i++)
10130 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10131 }
10132 }
10133
10134
10135 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10136 {
10137 word i, j, n;
10138
10139 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10140 UnMapId(Id), (char *)(FILE_), __LINE__));
10141
10142 n = 0;
10143 for (i = 1; i < length; i++)
10144 {
10145 j = 0;
10146 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10147 && ((msg[i] != dtmf_digit_map[j].code)
10148 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10149 {
10150 j++;
10151 }
10152 if (j < DTMF_DIGIT_MAP_ENTRIES)
10153 {
10154
10155 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10156 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10157 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10158 {
10159 if (n + 1 == i)
10160 {
10161 for (i = length; i > n + 1; i--)
10162 msg[i] = msg[i - 1];
10163 length++;
10164 i++;
10165 }
10166 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10167 }
10168 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10169
10170 msg[++n] = dtmf_digit_map[j].character;
10171 }
10172 }
10173 if (n != 0)
10174 {
10175 msg[0] = (byte) n;
10176 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10177 }
10178 }
10179
10180
10181 /*------------------------------------------------------------------*/
10182 /* DTMF parameters */
10183 /*------------------------------------------------------------------*/
10184
10185 static void dtmf_parameter_write(PLCI *plci)
10186 {
10187 word i;
10188 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10189
10190 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10191 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10192 (char *)(FILE_), __LINE__));
10193
10194 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10195 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10196 for (i = 0; i < plci->dtmf_parameter_length; i++)
10197 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10198 add_p(plci, FTY, parameter_buffer);
10199 sig_req(plci, TEL_CTRL, 0);
10200 send_req(plci);
10201 }
10202
10203
10204 static void dtmf_parameter_clear_config(PLCI *plci)
10205 {
10206
10207 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10208 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10209 (char *)(FILE_), __LINE__));
10210
10211 plci->dtmf_parameter_length = 0;
10212 }
10213
10214
10215 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10216 {
10217
10218 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10219 UnMapId(Id), (char *)(FILE_), __LINE__));
10220
10221 }
10222
10223
10224 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10225 {
10226
10227 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10228 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10229
10230 return (GOOD);
10231 }
10232
10233
10234 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10235 {
10236 word Info;
10237
10238 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10239 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10240
10241 Info = GOOD;
10242 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10243 && (plci->dtmf_parameter_length != 0))
10244 {
10245 switch (plci->adjust_b_state)
10246 {
10247 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10248 plci->internal_command = plci->adjust_b_command;
10249 if (plci->sig_req)
10250 {
10251 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10252 break;
10253 }
10254 dtmf_parameter_write(plci);
10255 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10256 break;
10257 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10258 if ((Rc != OK) && (Rc != OK_FC))
10259 {
10260 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10261 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10262 Info = _WRONG_STATE;
10263 break;
10264 }
10265 break;
10266 }
10267 }
10268 return (Info);
10269 }
10270
10271
10272 /*------------------------------------------------------------------*/
10273 /* Line interconnect facilities */
10274 /*------------------------------------------------------------------*/
10275
10276
10277 LI_CONFIG *li_config_table;
10278 word li_total_channels;
10279
10280
10281 /*------------------------------------------------------------------*/
10282 /* translate a CHI information element to a channel number */
10283 /* returns 0xff - any channel */
10284 /* 0xfe - chi wrong coding */
10285 /* 0xfd - D-channel */
10286 /* 0x00 - no channel */
10287 /* else channel number / PRI: timeslot */
10288 /* if channels is provided we accept more than one channel. */
10289 /*------------------------------------------------------------------*/
10290
10291 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10292 {
10293 int p;
10294 int i;
10295 dword map;
10296 byte excl;
10297 byte ofs;
10298 byte ch;
10299
10300 if (pchannelmap) *pchannelmap = 0;
10301 if (!chi[0]) return 0xff;
10302 excl = 0;
10303
10304 if (chi[1] & 0x20) {
10305 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10306 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10307 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10308 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10309 if (chi[1] & 0x08) excl = 0x40;
10310
10311 /* int. id present */
10312 if (chi[1] & 0x40) {
10313 p = i + 1;
10314 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10315 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10316 }
10317
10318 /* coding standard, Number/Map, Channel Type */
10319 p = i + 1;
10320 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10321 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10322 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10323
10324 /* Number/Map */
10325 if (chi[p] & 0x10) {
10326
10327 /* map */
10328 if ((chi[0] - p) == 4) ofs = 0;
10329 else if ((chi[0] - p) == 3) ofs = 1;
10330 else return 0xfe;
10331 ch = 0;
10332 map = 0;
10333 for (i = 0; i < 4 && p < chi[0]; i++) {
10334 p++;
10335 ch += 8;
10336 map <<= 8;
10337 if (chi[p]) {
10338 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10339 map |= chi[p];
10340 }
10341 }
10342 ch += ofs;
10343 map <<= ofs;
10344 }
10345 else {
10346
10347 /* number */
10348 p = i + 1;
10349 ch = chi[p] & 0x3f;
10350 if (pchannelmap) {
10351 if ((byte)(chi[0] - p) > 30) return 0xfe;
10352 map = 0;
10353 for (i = p; i <= chi[0]; i++) {
10354 if ((chi[i] & 0x7f) > 31) return 0xfe;
10355 map |= (1L << (chi[i] & 0x7f));
10356 }
10357 }
10358 else {
10359 if (p != chi[0]) return 0xfe;
10360 if (ch > 31) return 0xfe;
10361 map = (1L << ch);
10362 }
10363 if (chi[p] & 0x40) return 0xfe;
10364 }
10365 if (pchannelmap) *pchannelmap = map;
10366 else if (map != ((dword)(1L << ch))) return 0xfe;
10367 return (byte)(excl | ch);
10368 }
10369 else { /* not PRI */
10370 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10371 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10372 if (chi[1] & 0x08) excl = 0x40;
10373
10374 switch (chi[1] | 0x98) {
10375 case 0x98: return 0;
10376 case 0x99:
10377 if (pchannelmap) *pchannelmap = 2;
10378 return excl | 1;
10379 case 0x9a:
10380 if (pchannelmap) *pchannelmap = 4;
10381 return excl | 2;
10382 case 0x9b: return 0xff;
10383 case 0x9c: return 0xfd; /* d-ch */
10384 default: return 0xfe;
10385 }
10386 }
10387 }
10388
10389
10390 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10391 {
10392 DIVA_CAPI_ADAPTER *a;
10393 PLCI *splci;
10394 byte old_id;
10395
10396 a = plci->adapter;
10397 old_id = plci->li_bchannel_id;
10398 if (a->li_pri)
10399 {
10400 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10401 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10402 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10403 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10404 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10405 }
10406 else
10407 {
10408 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10409 {
10410 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10411 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10412 plci->li_bchannel_id = bchannel_id & 0x03;
10413 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10414 {
10415 splci = a->AdvSignalPLCI;
10416 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10417 {
10418 if ((splci->li_bchannel_id != 0)
10419 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10420 {
10421 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10422 }
10423 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10424 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10425 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10426 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10427 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10428 }
10429 }
10430 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10431 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10432 }
10433 }
10434 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10435 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10436 {
10437 mixer_clear_config(plci);
10438 }
10439 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10440 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10441 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10442 }
10443
10444
10445 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10446 {
10447 DIVA_CAPI_ADAPTER *a;
10448 PLCI *splci;
10449 byte ch, old_id;
10450
10451 a = plci->adapter;
10452 old_id = plci->li_bchannel_id;
10453 ch = chi_to_channel(chi, NULL);
10454 if (!(ch & 0x80))
10455 {
10456 if (a->li_pri)
10457 {
10458 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10459 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10460 plci->li_bchannel_id = (ch & 0x1f) + 1;
10461 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10462 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10463 }
10464 else
10465 {
10466 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10467 {
10468 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10469 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10470 plci->li_bchannel_id = ch & 0x1f;
10471 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10472 {
10473 splci = a->AdvSignalPLCI;
10474 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10475 {
10476 if ((splci->li_bchannel_id != 0)
10477 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10478 {
10479 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10480 }
10481 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10482 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10483 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10484 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10485 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10486 }
10487 }
10488 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10489 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10490 }
10491 }
10492 }
10493 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10494 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10495 {
10496 mixer_clear_config(plci);
10497 }
10498 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10499 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10500 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10501 }
10502
10503
10504 #define MIXER_MAX_DUMP_CHANNELS 34
10505
10506 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10507 {
10508 word n, i, j;
10509 char *p;
10510 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10511
10512 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10513 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10514
10515 for (i = 0; i < li_total_channels; i++)
10516 {
10517 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10518 if (li_config_table[i].chflags != 0)
10519 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10520 else
10521 {
10522 for (j = 0; j < li_total_channels; j++)
10523 {
10524 if (((li_config_table[i].flag_table[j]) != 0)
10525 || ((li_config_table[j].flag_table[i]) != 0))
10526 {
10527 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10528 }
10529 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10530 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10531 {
10532 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10533 }
10534 }
10535 }
10536 }
10537 for (i = 0; i < li_total_channels; i++)
10538 {
10539 for (j = 0; j < li_total_channels; j++)
10540 {
10541 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10542 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10543 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10544 }
10545 }
10546 for (n = 0; n < li_total_channels; n++)
10547 {
10548 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10549 {
10550 for (i = 0; i < li_total_channels; i++)
10551 {
10552 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10553 {
10554 for (j = 0; j < li_total_channels; j++)
10555 {
10556 li_config_table[i].coef_table[j] |=
10557 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10558 }
10559 }
10560 }
10561 }
10562 }
10563 for (i = 0; i < li_total_channels; i++)
10564 {
10565 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10566 {
10567 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10568 for (j = 0; j < li_total_channels; j++)
10569 {
10570 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10571 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10572 }
10573 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10574 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10575 }
10576 }
10577 for (i = 0; i < li_total_channels; i++)
10578 {
10579 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10580 {
10581 for (j = 0; j < li_total_channels; j++)
10582 {
10583 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10584 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10585 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10586 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10587 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10588 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10589 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10590 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10591 }
10592 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10593 {
10594 for (j = 0; j < li_total_channels; j++)
10595 {
10596 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10597 {
10598 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10599 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10600 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10601 }
10602 }
10603 }
10604 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10605 {
10606 for (j = 0; j < li_total_channels; j++)
10607 {
10608 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10609 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10610 }
10611 }
10612 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10613 {
10614 for (j = 0; j < li_total_channels; j++)
10615 {
10616 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10617 {
10618 for (n = 0; n < li_total_channels; n++)
10619 {
10620 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10621 {
10622 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10623 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10624 {
10625 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10626 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10627 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10628 }
10629 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10631 }
10632 }
10633 }
10634 }
10635 }
10636 }
10637 }
10638 for (i = 0; i < li_total_channels; i++)
10639 {
10640 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10641 {
10642 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10643 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10644 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10645 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10646 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10647 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10648 for (j = 0; j < li_total_channels; j++)
10649 {
10650 if ((li_config_table[i].flag_table[j] &
10651 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10652 || (li_config_table[j].flag_table[i] &
10653 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10654 {
10655 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10656 }
10657 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10658 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10659 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10660 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10661 }
10662 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10663 {
10664 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10665 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10666 }
10667 }
10668 }
10669 for (i = 0; i < li_total_channels; i++)
10670 {
10671 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10672 {
10673 j = 0;
10674 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10675 j++;
10676 if (j < li_total_channels)
10677 {
10678 for (j = 0; j < li_total_channels; j++)
10679 {
10680 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10681 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10682 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10683 }
10684 }
10685 }
10686 }
10687 n = li_total_channels;
10688 if (n > MIXER_MAX_DUMP_CHANNELS)
10689 n = MIXER_MAX_DUMP_CHANNELS;
10690
10691 p = hex_line;
10692 for (j = 0; j < n; j++)
10693 {
10694 if ((j & 0x7) == 0)
10695 *(p++) = ' ';
10696 p = hex_byte_pack(p, li_config_table[j].curchnl);
10697 }
10698 *p = '\0';
10699 dbug(1, dprintf("[%06lx] CURRENT %s",
10700 (dword)(UnMapController(a->Id)), (char *)hex_line));
10701 p = hex_line;
10702 for (j = 0; j < n; j++)
10703 {
10704 if ((j & 0x7) == 0)
10705 *(p++) = ' ';
10706 p = hex_byte_pack(p, li_config_table[j].channel);
10707 }
10708 *p = '\0';
10709 dbug(1, dprintf("[%06lx] CHANNEL %s",
10710 (dword)(UnMapController(a->Id)), (char *)hex_line));
10711 p = hex_line;
10712 for (j = 0; j < n; j++)
10713 {
10714 if ((j & 0x7) == 0)
10715 *(p++) = ' ';
10716 p = hex_byte_pack(p, li_config_table[j].chflags);
10717 }
10718 *p = '\0';
10719 dbug(1, dprintf("[%06lx] CHFLAG %s",
10720 (dword)(UnMapController(a->Id)), (char *)hex_line));
10721 for (i = 0; i < n; i++)
10722 {
10723 p = hex_line;
10724 for (j = 0; j < n; j++)
10725 {
10726 if ((j & 0x7) == 0)
10727 *(p++) = ' ';
10728 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10729 }
10730 *p = '\0';
10731 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10732 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10733 }
10734 for (i = 0; i < n; i++)
10735 {
10736 p = hex_line;
10737 for (j = 0; j < n; j++)
10738 {
10739 if ((j & 0x7) == 0)
10740 *(p++) = ' ';
10741 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10742 }
10743 *p = '\0';
10744 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10745 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10746 }
10747 }
10748
10749
10750 static struct
10751 {
10752 byte mask;
10753 byte line_flags;
10754 } mixer_write_prog_pri[] =
10755 {
10756 { LI_COEF_CH_CH, 0 },
10757 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10758 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10759 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10760 };
10761
10762 static struct
10763 {
10764 byte from_ch;
10765 byte to_ch;
10766 byte mask;
10767 byte xconnect_override;
10768 } mixer_write_prog_bri[] =
10769 {
10770 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10771 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10772 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10773 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10774 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10775 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10776 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10777 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10778 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10779 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10780 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10781 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10782 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10783 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10784 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10785 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10786 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10787 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10788 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10789 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10790 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10791 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10792 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10793 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10794 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10795 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10796 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10797 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10798 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10799 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10800 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10801 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10802 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10803 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10804 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10805 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10806 };
10807
10808 static byte mixer_swapped_index_bri[] =
10809 {
10810 18, /* B to B */
10811 19, /* Alt B to B */
10812 20, /* PC to B */
10813 21, /* Alt PC to B */
10814 22, /* IC to B */
10815 23, /* Alt IC to B */
10816 24, /* B to PC */
10817 25, /* Alt B to PC */
10818 26, /* PC to PC */
10819 27, /* Alt PC to PC */
10820 28, /* IC to PC */
10821 29, /* Alt IC to PC */
10822 30, /* B to IC */
10823 31, /* Alt B to IC */
10824 32, /* PC to IC */
10825 33, /* Alt PC to IC */
10826 34, /* IC to IC */
10827 35, /* Alt IC to IC */
10828 0, /* Alt B to Alt B */
10829 1, /* B to Alt B */
10830 2, /* Alt PC to Alt B */
10831 3, /* PC to Alt B */
10832 4, /* Alt IC to Alt B */
10833 5, /* IC to Alt B */
10834 6, /* Alt B to Alt PC */
10835 7, /* B to Alt PC */
10836 8, /* Alt PC to Alt PC */
10837 9, /* PC to Alt PC */
10838 10, /* Alt IC to Alt PC */
10839 11, /* IC to Alt PC */
10840 12, /* Alt B to Alt IC */
10841 13, /* B to Alt IC */
10842 14, /* Alt PC to Alt IC */
10843 15, /* PC to Alt IC */
10844 16, /* Alt IC to Alt IC */
10845 17 /* IC to Alt IC */
10846 };
10847
10848 static struct
10849 {
10850 byte mask;
10851 byte from_pc;
10852 byte to_pc;
10853 } xconnect_write_prog[] =
10854 {
10855 { LI_COEF_CH_CH, false, false },
10856 { LI_COEF_CH_PC, false, true },
10857 { LI_COEF_PC_CH, true, false },
10858 { LI_COEF_PC_PC, true, true }
10859 };
10860
10861
10862 static void xconnect_query_addresses(PLCI *plci)
10863 {
10864 DIVA_CAPI_ADAPTER *a;
10865 word w, ch;
10866 byte *p;
10867
10868 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10869 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10870 (char *)(FILE_), __LINE__));
10871
10872 a = plci->adapter;
10873 if (a->li_pri && ((plci->li_bchannel_id == 0)
10874 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10875 {
10876 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10877 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10878 (char *)(FILE_), __LINE__));
10879 return;
10880 }
10881 p = plci->internal_req_buffer;
10882 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10883 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10884 w = ch;
10885 *(p++) = (byte) w;
10886 *(p++) = (byte)(w >> 8);
10887 w = ch | XCONNECT_CHANNEL_PORT_PC;
10888 *(p++) = (byte) w;
10889 *(p++) = (byte)(w >> 8);
10890 plci->NData[0].P = plci->internal_req_buffer;
10891 plci->NData[0].PLength = p - plci->internal_req_buffer;
10892 plci->NL.X = plci->NData;
10893 plci->NL.ReqCh = 0;
10894 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10895 plci->adapter->request(&plci->NL);
10896 }
10897
10898
10899 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10900 {
10901
10902 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10903 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10904 (char *)(FILE_), __LINE__, internal_command));
10905
10906 plci->li_write_command = internal_command;
10907 plci->li_write_channel = 0;
10908 }
10909
10910
10911 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10912 {
10913 DIVA_CAPI_ADAPTER *a;
10914 word w, n, i, j, r, s, to_ch;
10915 dword d;
10916 byte *p;
10917 struct xconnect_transfer_address_s *transfer_address;
10918 byte ch_map[MIXER_CHANNELS_BRI];
10919
10920 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10921 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10922
10923 a = plci->adapter;
10924 if ((plci->li_bchannel_id == 0)
10925 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10926 {
10927 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10928 UnMapId(Id), (char *)(FILE_), __LINE__));
10929 return (true);
10930 }
10931 i = a->li_base + (plci->li_bchannel_id - 1);
10932 j = plci->li_write_channel;
10933 p = plci->internal_req_buffer;
10934 if (j != 0)
10935 {
10936 if ((Rc != OK) && (Rc != OK_FC))
10937 {
10938 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10939 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10940 return (false);
10941 }
10942 }
10943 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10944 {
10945 r = 0;
10946 s = 0;
10947 if (j < li_total_channels)
10948 {
10949 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10950 {
10951 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10952 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10953 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10954 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10955 }
10956 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10957 while ((j < li_total_channels)
10958 && ((r == 0)
10959 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10960 || (!li_config_table[j].adapter->li_pri
10961 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10962 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10963 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10964 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10965 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10966 || ((li_config_table[j].adapter->li_base != a->li_base)
10967 && !(r & s &
10968 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10969 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10970 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10971 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10972 {
10973 j++;
10974 if (j < li_total_channels)
10975 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10976 }
10977 }
10978 if (j < li_total_channels)
10979 {
10980 plci->internal_command = plci->li_write_command;
10981 if (plci_nl_busy(plci))
10982 return (true);
10983 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10984 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10985 do
10986 {
10987 if (li_config_table[j].adapter->li_base != a->li_base)
10988 {
10989 r &= s &
10990 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10991 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10992 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10993 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10994 }
10995 n = 0;
10996 do
10997 {
10998 if (r & xconnect_write_prog[n].mask)
10999 {
11000 if (xconnect_write_prog[n].from_pc)
11001 transfer_address = &(li_config_table[j].send_pc);
11002 else
11003 transfer_address = &(li_config_table[j].send_b);
11004 d = transfer_address->card_address.low;
11005 *(p++) = (byte) d;
11006 *(p++) = (byte)(d >> 8);
11007 *(p++) = (byte)(d >> 16);
11008 *(p++) = (byte)(d >> 24);
11009 d = transfer_address->card_address.high;
11010 *(p++) = (byte) d;
11011 *(p++) = (byte)(d >> 8);
11012 *(p++) = (byte)(d >> 16);
11013 *(p++) = (byte)(d >> 24);
11014 d = transfer_address->offset;
11015 *(p++) = (byte) d;
11016 *(p++) = (byte)(d >> 8);
11017 *(p++) = (byte)(d >> 16);
11018 *(p++) = (byte)(d >> 24);
11019 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11020 *(p++) = (byte) w;
11021 *(p++) = (byte)(w >> 8);
11022 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11023 (li_config_table[i].adapter->u_law ?
11024 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11025 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11026 *(p++) = (byte) w;
11027 *(p++) = (byte) 0;
11028 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11029 }
11030 n++;
11031 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11032 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11033 if (n == ARRAY_SIZE(xconnect_write_prog))
11034 {
11035 do
11036 {
11037 j++;
11038 if (j < li_total_channels)
11039 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11040 } while ((j < li_total_channels)
11041 && ((r == 0)
11042 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11043 || (!li_config_table[j].adapter->li_pri
11044 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11045 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11046 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11047 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11048 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11049 || ((li_config_table[j].adapter->li_base != a->li_base)
11050 && !(r & s &
11051 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11052 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11053 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11054 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11055 }
11056 } while ((j < li_total_channels)
11057 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11058 }
11059 else if (j == li_total_channels)
11060 {
11061 plci->internal_command = plci->li_write_command;
11062 if (plci_nl_busy(plci))
11063 return (true);
11064 if (a->li_pri)
11065 {
11066 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11067 w = 0;
11068 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11069 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11070 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11071 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11072 *(p++) = (byte) w;
11073 *(p++) = (byte)(w >> 8);
11074 }
11075 else
11076 {
11077 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11078 w = 0;
11079 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11080 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11081 {
11082 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11083 }
11084 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11085 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11086 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11087 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11088 *(p++) = (byte) w;
11089 *(p++) = (byte)(w >> 8);
11090 for (j = 0; j < sizeof(ch_map); j += 2)
11091 {
11092 if (plci->li_bchannel_id == 2)
11093 {
11094 ch_map[j] = (byte)(j + 1);
11095 ch_map[j + 1] = (byte) j;
11096 }
11097 else
11098 {
11099 ch_map[j] = (byte) j;
11100 ch_map[j + 1] = (byte)(j + 1);
11101 }
11102 }
11103 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11104 {
11105 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11106 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11107 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11108 {
11109 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11110 mixer_write_prog_bri[n].xconnect_override :
11111 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11112 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11113 {
11114 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11115 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11116 }
11117 }
11118 else
11119 {
11120 *p = 0x00;
11121 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11122 {
11123 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11124 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11125 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11126 }
11127 }
11128 p++;
11129 }
11130 }
11131 j = li_total_channels + 1;
11132 }
11133 }
11134 else
11135 {
11136 if (j <= li_total_channels)
11137 {
11138 plci->internal_command = plci->li_write_command;
11139 if (plci_nl_busy(plci))
11140 return (true);
11141 if (j < a->li_base)
11142 j = a->li_base;
11143 if (a->li_pri)
11144 {
11145 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11146 w = 0;
11147 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11148 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11149 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11150 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11151 *(p++) = (byte) w;
11152 *(p++) = (byte)(w >> 8);
11153 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11154 {
11155 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11156 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11157 {
11158 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11159 if (w & mixer_write_prog_pri[n].mask)
11160 {
11161 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11163 }
11164 else
11165 *(p++) = 0x00;
11166 }
11167 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11168 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11169 {
11170 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11171 if (w & mixer_write_prog_pri[n].mask)
11172 {
11173 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11174 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11175 }
11176 else
11177 *(p++) = 0x00;
11178 }
11179 }
11180 }
11181 else
11182 {
11183 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11184 w = 0;
11185 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11186 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11187 {
11188 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11189 }
11190 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11191 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11192 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11193 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11194 *(p++) = (byte) w;
11195 *(p++) = (byte)(w >> 8);
11196 for (j = 0; j < sizeof(ch_map); j += 2)
11197 {
11198 if (plci->li_bchannel_id == 2)
11199 {
11200 ch_map[j] = (byte)(j + 1);
11201 ch_map[j + 1] = (byte) j;
11202 }
11203 else
11204 {
11205 ch_map[j] = (byte) j;
11206 ch_map[j + 1] = (byte)(j + 1);
11207 }
11208 }
11209 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11210 {
11211 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11212 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11213 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11214 {
11215 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11216 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11217 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11218 }
11219 else
11220 {
11221 *p = 0x00;
11222 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11223 {
11224 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11225 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11226 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11227 }
11228 }
11229 p++;
11230 }
11231 }
11232 j = li_total_channels + 1;
11233 }
11234 }
11235 plci->li_write_channel = j;
11236 if (p != plci->internal_req_buffer)
11237 {
11238 plci->NData[0].P = plci->internal_req_buffer;
11239 plci->NData[0].PLength = p - plci->internal_req_buffer;
11240 plci->NL.X = plci->NData;
11241 plci->NL.ReqCh = 0;
11242 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11243 plci->adapter->request(&plci->NL);
11244 }
11245 return (true);
11246 }
11247
11248
11249 static void mixer_notify_update(PLCI *plci, byte others)
11250 {
11251 DIVA_CAPI_ADAPTER *a;
11252 word i, w;
11253 PLCI *notify_plci;
11254 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11255
11256 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11257 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11258 (char *)(FILE_), __LINE__, others));
11259
11260 a = plci->adapter;
11261 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11262 {
11263 if (others)
11264 plci->li_notify_update = true;
11265 i = 0;
11266 do
11267 {
11268 notify_plci = NULL;
11269 if (others)
11270 {
11271 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11272 i++;
11273 if (i < li_total_channels)
11274 notify_plci = li_config_table[i++].plci;
11275 }
11276 else
11277 {
11278 if ((plci->li_bchannel_id != 0)
11279 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11280 {
11281 notify_plci = plci;
11282 }
11283 }
11284 if ((notify_plci != NULL)
11285 && !notify_plci->li_notify_update
11286 && (notify_plci->appl != NULL)
11287 && (notify_plci->State)
11288 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11289 {
11290 notify_plci->li_notify_update = true;
11291 ((CAPI_MSG *) msg)->header.length = 18;
11292 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11293 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11294 ((CAPI_MSG *) msg)->header.number = 0;
11295 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11296 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11297 ((CAPI_MSG *) msg)->header.ncci = 0;
11298 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11299 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11300 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11301 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11302 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11303 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11304 if (w != _QUEUE_FULL)
11305 {
11306 if (w != 0)
11307 {
11308 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11309 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11310 (char *)(FILE_), __LINE__,
11311 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11312 }
11313 notify_plci->li_notify_update = false;
11314 }
11315 }
11316 } while (others && (notify_plci != NULL));
11317 if (others)
11318 plci->li_notify_update = false;
11319 }
11320 }
11321
11322
11323 static void mixer_clear_config(PLCI *plci)
11324 {
11325 DIVA_CAPI_ADAPTER *a;
11326 word i, j;
11327
11328 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11329 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11330 (char *)(FILE_), __LINE__));
11331
11332 plci->li_notify_update = false;
11333 plci->li_plci_b_write_pos = 0;
11334 plci->li_plci_b_read_pos = 0;
11335 plci->li_plci_b_req_pos = 0;
11336 a = plci->adapter;
11337 if ((plci->li_bchannel_id != 0)
11338 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11339 {
11340 i = a->li_base + (plci->li_bchannel_id - 1);
11341 li_config_table[i].curchnl = 0;
11342 li_config_table[i].channel = 0;
11343 li_config_table[i].chflags = 0;
11344 for (j = 0; j < li_total_channels; j++)
11345 {
11346 li_config_table[j].flag_table[i] = 0;
11347 li_config_table[i].flag_table[j] = 0;
11348 li_config_table[i].coef_table[j] = 0;
11349 li_config_table[j].coef_table[i] = 0;
11350 }
11351 if (!a->li_pri)
11352 {
11353 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11354 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11355 {
11356 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11357 li_config_table[i].curchnl = 0;
11358 li_config_table[i].channel = 0;
11359 li_config_table[i].chflags = 0;
11360 for (j = 0; j < li_total_channels; j++)
11361 {
11362 li_config_table[i].flag_table[j] = 0;
11363 li_config_table[j].flag_table[i] = 0;
11364 li_config_table[i].coef_table[j] = 0;
11365 li_config_table[j].coef_table[i] = 0;
11366 }
11367 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11368 {
11369 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11370 li_config_table[i].curchnl = 0;
11371 li_config_table[i].channel = 0;
11372 li_config_table[i].chflags = 0;
11373 for (j = 0; j < li_total_channels; j++)
11374 {
11375 li_config_table[i].flag_table[j] = 0;
11376 li_config_table[j].flag_table[i] = 0;
11377 li_config_table[i].coef_table[j] = 0;
11378 li_config_table[j].coef_table[i] = 0;
11379 }
11380 }
11381 }
11382 }
11383 }
11384 }
11385
11386
11387 static void mixer_prepare_switch(dword Id, PLCI *plci)
11388 {
11389
11390 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11391 UnMapId(Id), (char *)(FILE_), __LINE__));
11392
11393 do
11394 {
11395 mixer_indication_coefs_set(Id, plci);
11396 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11397 }
11398
11399
11400 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11401 {
11402 DIVA_CAPI_ADAPTER *a;
11403 word i, j;
11404
11405 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11406 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11407
11408 a = plci->adapter;
11409 if ((plci->li_bchannel_id != 0)
11410 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11411 {
11412 i = a->li_base + (plci->li_bchannel_id - 1);
11413 for (j = 0; j < li_total_channels; j++)
11414 {
11415 li_config_table[i].coef_table[j] &= 0xf;
11416 li_config_table[j].coef_table[i] &= 0xf;
11417 }
11418 if (!a->li_pri)
11419 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11420 }
11421 return (GOOD);
11422 }
11423
11424
11425 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11426 {
11427 DIVA_CAPI_ADAPTER *a;
11428 word Info;
11429
11430 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11431 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11432
11433 Info = GOOD;
11434 a = plci->adapter;
11435 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11436 && (plci->li_bchannel_id != 0)
11437 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11438 {
11439 switch (plci->adjust_b_state)
11440 {
11441 case ADJUST_B_RESTORE_MIXER_1:
11442 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11443 {
11444 plci->internal_command = plci->adjust_b_command;
11445 if (plci_nl_busy(plci))
11446 {
11447 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11448 break;
11449 }
11450 xconnect_query_addresses(plci);
11451 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11452 break;
11453 }
11454 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11455 Rc = OK;
11456 case ADJUST_B_RESTORE_MIXER_2:
11457 case ADJUST_B_RESTORE_MIXER_3:
11458 case ADJUST_B_RESTORE_MIXER_4:
11459 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11460 {
11461 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11462 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11463 Info = _WRONG_STATE;
11464 break;
11465 }
11466 if (Rc == OK)
11467 {
11468 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11469 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11470 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11471 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11472 }
11473 else if (Rc == 0)
11474 {
11475 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11476 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11477 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11478 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11479 }
11480 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11481 {
11482 plci->internal_command = plci->adjust_b_command;
11483 break;
11484 }
11485 case ADJUST_B_RESTORE_MIXER_5:
11486 xconnect_write_coefs(plci, plci->adjust_b_command);
11487 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11488 Rc = OK;
11489 case ADJUST_B_RESTORE_MIXER_6:
11490 if (!xconnect_write_coefs_process(Id, plci, Rc))
11491 {
11492 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11493 UnMapId(Id), (char *)(FILE_), __LINE__));
11494 Info = _FACILITY_NOT_SUPPORTED;
11495 break;
11496 }
11497 if (plci->internal_command)
11498 break;
11499 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11500 case ADJUST_B_RESTORE_MIXER_7:
11501 break;
11502 }
11503 }
11504 return (Info);
11505 }
11506
11507
11508 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11509 {
11510 DIVA_CAPI_ADAPTER *a;
11511 word i, internal_command;
11512
11513 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11514 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11515 plci->li_cmd));
11516
11517 a = plci->adapter;
11518 internal_command = plci->internal_command;
11519 plci->internal_command = 0;
11520 switch (plci->li_cmd)
11521 {
11522 case LI_REQ_CONNECT:
11523 case LI_REQ_DISCONNECT:
11524 case LI_REQ_SILENT_UPDATE:
11525 switch (internal_command)
11526 {
11527 default:
11528 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11529 {
11530 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11531 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11532 }
11533 case MIXER_COMMAND_1:
11534 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535 {
11536 if (adjust_b_process(Id, plci, Rc) != GOOD)
11537 {
11538 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11539 UnMapId(Id), (char *)(FILE_), __LINE__));
11540 break;
11541 }
11542 if (plci->internal_command)
11543 return;
11544 }
11545 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11546 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11547 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11548 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11549 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11550 {
11551 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11552 }
11553 else
11554 {
11555 do
11556 {
11557 mixer_indication_coefs_set(Id, plci);
11558 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11559 }
11560 case MIXER_COMMAND_2:
11561 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11562 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11563 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11564 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11565 {
11566 if (!xconnect_write_coefs_process(Id, plci, Rc))
11567 {
11568 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11569 UnMapId(Id), (char *)(FILE_), __LINE__));
11570 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11571 {
11572 do
11573 {
11574 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11575 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11576 i = (plci->li_plci_b_write_pos == 0) ?
11577 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11578 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11579 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11580 }
11581 break;
11582 }
11583 if (plci->internal_command)
11584 return;
11585 }
11586 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11587 {
11588 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11589 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11590 }
11591 case MIXER_COMMAND_3:
11592 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593 {
11594 if (adjust_b_process(Id, plci, Rc) != GOOD)
11595 {
11596 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11597 UnMapId(Id), (char *)(FILE_), __LINE__));
11598 break;
11599 }
11600 if (plci->internal_command)
11601 return;
11602 }
11603 break;
11604 }
11605 break;
11606 }
11607 if ((plci->li_bchannel_id == 0)
11608 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11609 {
11610 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11611 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11612 }
11613 else
11614 {
11615 i = a->li_base + (plci->li_bchannel_id - 1);
11616 li_config_table[i].curchnl = plci->li_channel_bits;
11617 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11618 {
11619 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11620 li_config_table[i].curchnl = plci->li_channel_bits;
11621 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11622 {
11623 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11624 li_config_table[i].curchnl = plci->li_channel_bits;
11625 }
11626 }
11627 }
11628 }
11629
11630
11631 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11632 dword plci_b_id, byte connect, dword li_flags)
11633 {
11634 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11635 PLCI *plci_b;
11636 DIVA_CAPI_ADAPTER *a_b;
11637
11638 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11639 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11640 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11641 if (!a->li_pri && (plci->tel == ADV_VOICE)
11642 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11643 {
11644 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11645 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11646 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11647 }
11648 else
11649 {
11650 ch_a_v = ch_a;
11651 ch_a_s = ch_a;
11652 }
11653 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11654 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11655 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11656 {
11657 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11658 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11659 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11660 }
11661 else
11662 {
11663 ch_b_v = ch_b;
11664 ch_b_s = ch_b;
11665 }
11666 if (connect)
11667 {
11668 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11669 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11670 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11671 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11672 }
11673 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677 if (ch_a_v == ch_b_v)
11678 {
11679 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11680 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11681 }
11682 else
11683 {
11684 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11685 {
11686 for (i = 0; i < li_total_channels; i++)
11687 {
11688 if (i != ch_a_v)
11689 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11690 }
11691 }
11692 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11693 {
11694 for (i = 0; i < li_total_channels; i++)
11695 {
11696 if (i != ch_a_s)
11697 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11698 }
11699 }
11700 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11701 {
11702 for (i = 0; i < li_total_channels; i++)
11703 {
11704 if (i != ch_a_v)
11705 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11706 }
11707 }
11708 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11709 {
11710 for (i = 0; i < li_total_channels; i++)
11711 {
11712 if (i != ch_a_s)
11713 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11714 }
11715 }
11716 }
11717 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11718 {
11719 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11722 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11723 }
11724 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11725 {
11726 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11727 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11728 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11729 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11730 }
11731 if (li_flags & LI_FLAG_MONITOR_A)
11732 {
11733 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11734 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11735 }
11736 if (li_flags & LI_FLAG_MONITOR_B)
11737 {
11738 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11739 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11740 }
11741 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11742 {
11743 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11744 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11745 }
11746 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11747 {
11748 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11749 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750 }
11751 if (li_flags & LI_FLAG_MIX_A)
11752 {
11753 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11754 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11755 }
11756 if (li_flags & LI_FLAG_MIX_B)
11757 {
11758 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11759 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11760 }
11761 if (ch_a_v != ch_a_s)
11762 {
11763 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11764 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11765 }
11766 if (ch_b_v != ch_b_s)
11767 {
11768 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11769 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11770 }
11771 }
11772
11773
11774 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11775 dword plci_b_id, byte connect, dword li_flags)
11776 {
11777 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11778 PLCI *plci_b;
11779 DIVA_CAPI_ADAPTER *a_b;
11780
11781 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11782 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11783 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11784 if (!a->li_pri && (plci->tel == ADV_VOICE)
11785 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11786 {
11787 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11788 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11789 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11790 }
11791 else
11792 {
11793 ch_a_v = ch_a;
11794 ch_a_s = ch_a;
11795 }
11796 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11797 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11798 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11799 {
11800 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11801 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11802 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11803 }
11804 else
11805 {
11806 ch_b_v = ch_b;
11807 ch_b_s = ch_b;
11808 }
11809 if (connect)
11810 {
11811 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11812 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11813 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11815 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11816 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11817 }
11818 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11827 {
11828 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11831 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11832 }
11833 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11834 {
11835 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11836 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11837 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11838 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11839 }
11840 if (li_flags & LI2_FLAG_MONITOR_B)
11841 {
11842 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11843 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11844 }
11845 if (li_flags & LI2_FLAG_MIX_B)
11846 {
11847 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11848 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11849 }
11850 if (li_flags & LI2_FLAG_MONITOR_X)
11851 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11852 if (li_flags & LI2_FLAG_MIX_X)
11853 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11854 if (li_flags & LI2_FLAG_LOOP_B)
11855 {
11856 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11858 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11860 }
11861 if (li_flags & LI2_FLAG_LOOP_PC)
11862 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11863 if (li_flags & LI2_FLAG_LOOP_X)
11864 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11865 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11866 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11867 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11868 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11869 if (ch_a_v != ch_a_s)
11870 {
11871 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11872 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11873 }
11874 if (ch_b_v != ch_b_s)
11875 {
11876 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11877 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11878 }
11879 }
11880
11881
11882 static word li_check_main_plci(dword Id, PLCI *plci)
11883 {
11884 if (plci == NULL)
11885 {
11886 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11887 UnMapId(Id), (char *)(FILE_), __LINE__));
11888 return (_WRONG_IDENTIFIER);
11889 }
11890 if (!plci->State
11891 || !plci->NL.Id || plci->nl_remove_id
11892 || (plci->li_bchannel_id == 0))
11893 {
11894 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11895 UnMapId(Id), (char *)(FILE_), __LINE__));
11896 return (_WRONG_STATE);
11897 }
11898 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11899 return (GOOD);
11900 }
11901
11902
11903 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11904 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11905 {
11906 byte ctlr_b;
11907 PLCI *plci_b;
11908
11909 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11910 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11911 {
11912 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11913 UnMapId(Id), (char *)(FILE_), __LINE__));
11914 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11915 return (NULL);
11916 }
11917 ctlr_b = 0;
11918 if ((plci_b_id & 0x7f) != 0)
11919 {
11920 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11921 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11922 ctlr_b = 0;
11923 }
11924 if ((ctlr_b == 0)
11925 || (((plci_b_id >> 8) & 0xff) == 0)
11926 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11927 {
11928 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11929 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11930 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11931 return (NULL);
11932 }
11933 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11934 if (!plci_b->State
11935 || !plci_b->NL.Id || plci_b->nl_remove_id
11936 || (plci_b->li_bchannel_id == 0))
11937 {
11938 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11939 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11940 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11941 return (NULL);
11942 }
11943 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11944 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11945 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11946 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11947 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11948 {
11949 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11950 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11951 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11952 return (NULL);
11953 }
11954 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11955 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11956 {
11957 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11958 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11959 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11960 return (NULL);
11961 }
11962 return (plci_b);
11963 }
11964
11965
11966 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11967 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11968 {
11969 byte ctlr_b;
11970 PLCI *plci_b;
11971
11972 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11973 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11974 {
11975 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11976 UnMapId(Id), (char *)(FILE_), __LINE__));
11977 PUT_WORD(p_result, _WRONG_STATE);
11978 return (NULL);
11979 }
11980 ctlr_b = 0;
11981 if ((plci_b_id & 0x7f) != 0)
11982 {
11983 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11984 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11985 ctlr_b = 0;
11986 }
11987 if ((ctlr_b == 0)
11988 || (((plci_b_id >> 8) & 0xff) == 0)
11989 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11990 {
11991 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11992 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11993 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11994 return (NULL);
11995 }
11996 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11997 if (!plci_b->State
11998 || !plci_b->NL.Id || plci_b->nl_remove_id
11999 || (plci_b->li_bchannel_id == 0)
12000 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12001 {
12002 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12003 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12004 PUT_WORD(p_result, _WRONG_STATE);
12005 return (NULL);
12006 }
12007 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12008 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12009 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12010 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12011 {
12012 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12013 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12014 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12015 return (NULL);
12016 }
12017 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12018 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12019 {
12020 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12021 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12022 PUT_WORD(p_result, _WRONG_STATE);
12023 return (NULL);
12024 }
12025 return (plci_b);
12026 }
12027
12028
12029 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12030 {
12031 word Info;
12032 word i;
12033 dword d, li_flags, plci_b_id;
12034 PLCI *plci_b;
12035 API_PARSE li_parms[3];
12036 API_PARSE li_req_parms[3];
12037 API_PARSE li_participant_struct[2];
12038 API_PARSE li_participant_parms[3];
12039 word participant_parms_pos;
12040 byte result_buffer[32];
12041 byte *result;
12042 word result_pos;
12043 word plci_b_write_pos;
12044
12045 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12046 UnMapId(Id), (char *)(FILE_), __LINE__));
12047
12048 Info = GOOD;
12049 result = result_buffer;
12050 result_buffer[0] = 0;
12051 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12052 {
12053 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12054 UnMapId(Id), (char *)(FILE_), __LINE__));
12055 Info = _FACILITY_NOT_SUPPORTED;
12056 }
12057 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12058 {
12059 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12060 UnMapId(Id), (char *)(FILE_), __LINE__));
12061 Info = _WRONG_MESSAGE_FORMAT;
12062 }
12063 else
12064 {
12065 result_buffer[0] = 3;
12066 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12067 result_buffer[3] = 0;
12068 switch (GET_WORD(li_parms[0].info))
12069 {
12070 case LI_GET_SUPPORTED_SERVICES:
12071 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12072 {
12073 result_buffer[0] = 17;
12074 result_buffer[3] = 14;
12075 PUT_WORD(&result_buffer[4], GOOD);
12076 d = 0;
12077 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12078 d |= LI_CONFERENCING_SUPPORTED;
12079 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12080 d |= LI_MONITORING_SUPPORTED;
12081 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12082 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12083 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12085 PUT_DWORD(&result_buffer[6], d);
12086 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12087 {
12088 d = 0;
12089 for (i = 0; i < li_total_channels; i++)
12090 {
12091 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12092 && (li_config_table[i].adapter->li_pri
12093 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12094 {
12095 d++;
12096 }
12097 }
12098 }
12099 else
12100 {
12101 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12102 }
12103 PUT_DWORD(&result_buffer[10], d / 2);
12104 PUT_DWORD(&result_buffer[14], d);
12105 }
12106 else
12107 {
12108 result_buffer[0] = 25;
12109 result_buffer[3] = 22;
12110 PUT_WORD(&result_buffer[4], GOOD);
12111 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12112 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12113 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12114 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12115 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12116 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12117 d |= LI2_PC_LOOPING_SUPPORTED;
12118 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12119 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12120 PUT_DWORD(&result_buffer[6], d);
12121 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12122 PUT_DWORD(&result_buffer[10], d / 2);
12123 PUT_DWORD(&result_buffer[14], d - 1);
12124 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12125 {
12126 d = 0;
12127 for (i = 0; i < li_total_channels; i++)
12128 {
12129 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12130 && (li_config_table[i].adapter->li_pri
12131 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12132 {
12133 d++;
12134 }
12135 }
12136 }
12137 PUT_DWORD(&result_buffer[18], d / 2);
12138 PUT_DWORD(&result_buffer[22], d - 1);
12139 }
12140 break;
12141
12142 case LI_REQ_CONNECT:
12143 if (li_parms[1].length == 8)
12144 {
12145 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12146 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12147 {
12148 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12149 UnMapId(Id), (char *)(FILE_), __LINE__));
12150 Info = _WRONG_MESSAGE_FORMAT;
12151 break;
12152 }
12153 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12154 li_flags = GET_DWORD(li_req_parms[1].info);
12155 Info = li_check_main_plci(Id, plci);
12156 result_buffer[0] = 9;
12157 result_buffer[3] = 6;
12158 PUT_DWORD(&result_buffer[4], plci_b_id);
12159 PUT_WORD(&result_buffer[8], GOOD);
12160 if (Info != GOOD)
12161 break;
12162 result = plci->saved_msg.info;
12163 for (i = 0; i <= result_buffer[0]; i++)
12164 result[i] = result_buffer[i];
12165 plci_b_write_pos = plci->li_plci_b_write_pos;
12166 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12167 if (plci_b == NULL)
12168 break;
12169 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12170 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12171 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12172 plci->li_plci_b_write_pos = plci_b_write_pos;
12173 }
12174 else
12175 {
12176 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12177 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12178 {
12179 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12180 UnMapId(Id), (char *)(FILE_), __LINE__));
12181 Info = _WRONG_MESSAGE_FORMAT;
12182 break;
12183 }
12184 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
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 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12199 while (participant_parms_pos < li_req_parms[1].length)
12200 {
12201 result[result_pos] = 6;
12202 result_pos += 7;
12203 PUT_DWORD(&result[result_pos - 6], 0);
12204 PUT_WORD(&result[result_pos - 2], GOOD);
12205 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12206 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12207 {
12208 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12209 UnMapId(Id), (char *)(FILE_), __LINE__));
12210 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12211 break;
12212 }
12213 if (api_parse(&li_participant_struct[0].info[1],
12214 li_participant_struct[0].length, "dd", li_participant_parms))
12215 {
12216 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12217 UnMapId(Id), (char *)(FILE_), __LINE__));
12218 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12219 break;
12220 }
12221 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12222 li_flags = GET_DWORD(li_participant_parms[1].info);
12223 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12224 if (sizeof(result) - result_pos < 7)
12225 {
12226 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12227 UnMapId(Id), (char *)(FILE_), __LINE__));
12228 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12229 break;
12230 }
12231 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12232 if (plci_b != NULL)
12233 {
12234 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12235 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12236 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12237 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12238 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12239 }
12240 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12241 (&li_req_parms[1].info[1]));
12242 }
12243 result[0] = (byte)(result_pos - 1);
12244 result[3] = (byte)(result_pos - 4);
12245 result[6] = (byte)(result_pos - 7);
12246 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12247 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12248 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12249 {
12250 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12251 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12252 }
12253 else
12254 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12255 plci->li_plci_b_write_pos = plci_b_write_pos;
12256 }
12257 mixer_calculate_coefs(a);
12258 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12259 mixer_notify_update(plci, true);
12260 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12261 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12262 plci->command = 0;
12263 plci->li_cmd = GET_WORD(li_parms[0].info);
12264 start_internal_command(Id, plci, mixer_command);
12265 return (false);
12266
12267 case LI_REQ_DISCONNECT:
12268 if (li_parms[1].length == 4)
12269 {
12270 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12271 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12272 {
12273 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12274 UnMapId(Id), (char *)(FILE_), __LINE__));
12275 Info = _WRONG_MESSAGE_FORMAT;
12276 break;
12277 }
12278 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12279 Info = li_check_main_plci(Id, plci);
12280 result_buffer[0] = 9;
12281 result_buffer[3] = 6;
12282 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12283 PUT_WORD(&result_buffer[8], GOOD);
12284 if (Info != GOOD)
12285 break;
12286 result = plci->saved_msg.info;
12287 for (i = 0; i <= result_buffer[0]; i++)
12288 result[i] = result_buffer[i];
12289 plci_b_write_pos = plci->li_plci_b_write_pos;
12290 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12291 if (plci_b == NULL)
12292 break;
12293 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12294 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12295 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12296 plci->li_plci_b_write_pos = plci_b_write_pos;
12297 }
12298 else
12299 {
12300 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12301 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12302 {
12303 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12304 UnMapId(Id), (char *)(FILE_), __LINE__));
12305 Info = _WRONG_MESSAGE_FORMAT;
12306 break;
12307 }
12308 Info = li_check_main_plci(Id, plci);
12309 result_buffer[0] = 7;
12310 result_buffer[3] = 4;
12311 PUT_WORD(&result_buffer[4], Info);
12312 result_buffer[6] = 0;
12313 if (Info != GOOD)
12314 break;
12315 result = plci->saved_msg.info;
12316 for (i = 0; i <= result_buffer[0]; i++)
12317 result[i] = result_buffer[i];
12318 plci_b_write_pos = plci->li_plci_b_write_pos;
12319 participant_parms_pos = 0;
12320 result_pos = 7;
12321 while (participant_parms_pos < li_req_parms[0].length)
12322 {
12323 result[result_pos] = 6;
12324 result_pos += 7;
12325 PUT_DWORD(&result[result_pos - 6], 0);
12326 PUT_WORD(&result[result_pos - 2], GOOD);
12327 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12328 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12329 {
12330 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12331 UnMapId(Id), (char *)(FILE_), __LINE__));
12332 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12333 break;
12334 }
12335 if (api_parse(&li_participant_struct[0].info[1],
12336 li_participant_struct[0].length, "d", li_participant_parms))
12337 {
12338 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12339 UnMapId(Id), (char *)(FILE_), __LINE__));
12340 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12341 break;
12342 }
12343 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12344 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12345 if (sizeof(result) - result_pos < 7)
12346 {
12347 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12348 UnMapId(Id), (char *)(FILE_), __LINE__));
12349 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12350 break;
12351 }
12352 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12353 if (plci_b != NULL)
12354 {
12355 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12356 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12357 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12358 }
12359 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12360 (&li_req_parms[0].info[1]));
12361 }
12362 result[0] = (byte)(result_pos - 1);
12363 result[3] = (byte)(result_pos - 4);
12364 result[6] = (byte)(result_pos - 7);
12365 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12366 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12367 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12368 {
12369 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12370 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12371 }
12372 else
12373 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12374 plci->li_plci_b_write_pos = plci_b_write_pos;
12375 }
12376 mixer_calculate_coefs(a);
12377 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12378 mixer_notify_update(plci, true);
12379 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12380 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12381 plci->command = 0;
12382 plci->li_cmd = GET_WORD(li_parms[0].info);
12383 start_internal_command(Id, plci, mixer_command);
12384 return (false);
12385
12386 case LI_REQ_SILENT_UPDATE:
12387 if (!plci || !plci->State
12388 || !plci->NL.Id || plci->nl_remove_id
12389 || (plci->li_bchannel_id == 0)
12390 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12391 {
12392 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12393 UnMapId(Id), (char *)(FILE_), __LINE__));
12394 return (false);
12395 }
12396 plci_b_write_pos = plci->li_plci_b_write_pos;
12397 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12398 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12399 {
12400 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12401 UnMapId(Id), (char *)(FILE_), __LINE__));
12402 return (false);
12403 }
12404 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12405 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12406 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12407 {
12408 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12409 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12410 }
12411 else
12412 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12413 plci->li_plci_b_write_pos = plci_b_write_pos;
12414 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12415 plci->command = 0;
12416 plci->li_cmd = GET_WORD(li_parms[0].info);
12417 start_internal_command(Id, plci, mixer_command);
12418 return (false);
12419
12420 default:
12421 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12422 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12423 Info = _FACILITY_NOT_SUPPORTED;
12424 }
12425 }
12426 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12427 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12428 return (false);
12429 }
12430
12431
12432 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12433 {
12434 dword d;
12435 byte result[12];
12436
12437 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12438 UnMapId(Id), (char *)(FILE_), __LINE__));
12439
12440 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12441 {
12442 do
12443 {
12444 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12445 if (!(d & LI_PLCI_B_SKIP_FLAG))
12446 {
12447 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12448 {
12449 if (d & LI_PLCI_B_DISC_FLAG)
12450 {
12451 result[0] = 5;
12452 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12453 result[3] = 2;
12454 PUT_WORD(&result[4], _LI_USER_INITIATED);
12455 }
12456 else
12457 {
12458 result[0] = 7;
12459 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12460 result[3] = 4;
12461 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12462 }
12463 }
12464 else
12465 {
12466 if (d & LI_PLCI_B_DISC_FLAG)
12467 {
12468 result[0] = 9;
12469 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12470 result[3] = 6;
12471 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12472 PUT_WORD(&result[8], _LI_USER_INITIATED);
12473 }
12474 else
12475 {
12476 result[0] = 7;
12477 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12478 result[3] = 4;
12479 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12480 }
12481 }
12482 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12483 "ws", SELECTOR_LINE_INTERCONNECT, result);
12484 }
12485 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12486 0 : plci->li_plci_b_read_pos + 1;
12487 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12488 }
12489 }
12490
12491
12492 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12493 {
12494 word i, j, ch;
12495 struct xconnect_transfer_address_s s, *p;
12496 DIVA_CAPI_ADAPTER *a;
12497
12498 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12499 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12500
12501 a = plci->adapter;
12502 i = 1;
12503 for (i = 1; i < length; i += 16)
12504 {
12505 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12506 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12507 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12508 ch = msg[i + 12] | (msg[i + 13] << 8);
12509 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12510 if (!a->li_pri && (plci->li_bchannel_id == 2))
12511 j = 1 - j;
12512 j += a->li_base;
12513 if (ch & XCONNECT_CHANNEL_PORT_PC)
12514 p = &(li_config_table[j].send_pc);
12515 else
12516 p = &(li_config_table[j].send_b);
12517 p->card_address.low = s.card_address.low;
12518 p->card_address.high = s.card_address.high;
12519 p->offset = s.offset;
12520 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12521 }
12522 if (plci->internal_command_queue[0]
12523 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12524 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12525 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12526 {
12527 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12528 if (!plci->internal_command)
12529 next_internal_command(Id, plci);
12530 }
12531 mixer_notify_update(plci, true);
12532 }
12533
12534
12535 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12536 {
12537
12538 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12539 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12540
12541 }
12542
12543
12544 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12545 {
12546 word plci_b_write_pos;
12547
12548 plci_b_write_pos = plci->li_plci_b_write_pos;
12549 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12550 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12551 {
12552 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12553 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12554 (char *)(FILE_), __LINE__));
12555 return (false);
12556 }
12557 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12558 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12559 plci->li_plci_b_write_pos = plci_b_write_pos;
12560 return (true);
12561 }
12562
12563
12564 static void mixer_remove(PLCI *plci)
12565 {
12566 DIVA_CAPI_ADAPTER *a;
12567 PLCI *notify_plci;
12568 dword plci_b_id;
12569 word i, j;
12570
12571 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12572 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12573 (char *)(FILE_), __LINE__));
12574
12575 a = plci->adapter;
12576 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12577 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12578 {
12579 if ((plci->li_bchannel_id != 0)
12580 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12581 {
12582 i = a->li_base + (plci->li_bchannel_id - 1);
12583 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12584 {
12585 for (j = 0; j < li_total_channels; j++)
12586 {
12587 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12588 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12589 {
12590 notify_plci = li_config_table[j].plci;
12591 if ((notify_plci != NULL)
12592 && (notify_plci != plci)
12593 && (notify_plci->appl != NULL)
12594 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12595 && (notify_plci->State)
12596 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12597 {
12598 mixer_notify_source_removed(notify_plci, plci_b_id);
12599 }
12600 }
12601 }
12602 mixer_clear_config(plci);
12603 mixer_calculate_coefs(a);
12604 mixer_notify_update(plci, true);
12605 }
12606 li_config_table[i].plci = NULL;
12607 plci->li_bchannel_id = 0;
12608 }
12609 }
12610 }
12611
12612
12613 /*------------------------------------------------------------------*/
12614 /* Echo canceller facilities */
12615 /*------------------------------------------------------------------*/
12616
12617
12618 static void ec_write_parameters(PLCI *plci)
12619 {
12620 word w;
12621 byte parameter_buffer[6];
12622
12623 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12624 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12625 (char *)(FILE_), __LINE__));
12626
12627 parameter_buffer[0] = 5;
12628 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12629 PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12630 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12631 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12632 PUT_WORD(&parameter_buffer[4], w);
12633 add_p(plci, FTY, parameter_buffer);
12634 sig_req(plci, TEL_CTRL, 0);
12635 send_req(plci);
12636 }
12637
12638
12639 static void ec_clear_config(PLCI *plci)
12640 {
12641
12642 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12643 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12644 (char *)(FILE_), __LINE__));
12645
12646 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12647 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12648 plci->ec_tail_length = 0;
12649 }
12650
12651
12652 static void ec_prepare_switch(dword Id, PLCI *plci)
12653 {
12654
12655 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12656 UnMapId(Id), (char *)(FILE_), __LINE__));
12657
12658 }
12659
12660
12661 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12662 {
12663
12664 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12665 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12666
12667 return (GOOD);
12668 }
12669
12670
12671 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12672 {
12673 word Info;
12674
12675 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12676 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12677
12678 Info = GOOD;
12679 if (plci->B1_facilities & B1_FACILITY_EC)
12680 {
12681 switch (plci->adjust_b_state)
12682 {
12683 case ADJUST_B_RESTORE_EC_1:
12684 plci->internal_command = plci->adjust_b_command;
12685 if (plci->sig_req)
12686 {
12687 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12688 break;
12689 }
12690 ec_write_parameters(plci);
12691 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12692 break;
12693 case ADJUST_B_RESTORE_EC_2:
12694 if ((Rc != OK) && (Rc != OK_FC))
12695 {
12696 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12697 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12698 Info = _WRONG_STATE;
12699 break;
12700 }
12701 break;
12702 }
12703 }
12704 return (Info);
12705 }
12706
12707
12708 static void ec_command(dword Id, PLCI *plci, byte Rc)
12709 {
12710 word internal_command, Info;
12711 byte result[8];
12712
12713 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12714 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12715 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12716
12717 Info = GOOD;
12718 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12719 {
12720 result[0] = 2;
12721 PUT_WORD(&result[1], EC_SUCCESS);
12722 }
12723 else
12724 {
12725 result[0] = 5;
12726 PUT_WORD(&result[1], plci->ec_cmd);
12727 result[3] = 2;
12728 PUT_WORD(&result[4], GOOD);
12729 }
12730 internal_command = plci->internal_command;
12731 plci->internal_command = 0;
12732 switch (plci->ec_cmd)
12733 {
12734 case EC_ENABLE_OPERATION:
12735 case EC_FREEZE_COEFFICIENTS:
12736 case EC_RESUME_COEFFICIENT_UPDATE:
12737 case EC_RESET_COEFFICIENTS:
12738 switch (internal_command)
12739 {
12740 default:
12741 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12742 B1_FACILITY_EC), EC_COMMAND_1);
12743 case EC_COMMAND_1:
12744 if (adjust_b_process(Id, plci, Rc) != GOOD)
12745 {
12746 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12747 UnMapId(Id), (char *)(FILE_), __LINE__));
12748 Info = _FACILITY_NOT_SUPPORTED;
12749 break;
12750 }
12751 if (plci->internal_command)
12752 return;
12753 case EC_COMMAND_2:
12754 if (plci->sig_req)
12755 {
12756 plci->internal_command = EC_COMMAND_2;
12757 return;
12758 }
12759 plci->internal_command = EC_COMMAND_3;
12760 ec_write_parameters(plci);
12761 return;
12762 case EC_COMMAND_3:
12763 if ((Rc != OK) && (Rc != OK_FC))
12764 {
12765 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12766 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12767 Info = _FACILITY_NOT_SUPPORTED;
12768 break;
12769 }
12770 break;
12771 }
12772 break;
12773
12774 case EC_DISABLE_OPERATION:
12775 switch (internal_command)
12776 {
12777 default:
12778 case EC_COMMAND_1:
12779 if (plci->B1_facilities & B1_FACILITY_EC)
12780 {
12781 if (plci->sig_req)
12782 {
12783 plci->internal_command = EC_COMMAND_1;
12784 return;
12785 }
12786 plci->internal_command = EC_COMMAND_2;
12787 ec_write_parameters(plci);
12788 return;
12789 }
12790 Rc = OK;
12791 case EC_COMMAND_2:
12792 if ((Rc != OK) && (Rc != OK_FC))
12793 {
12794 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12795 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12796 Info = _FACILITY_NOT_SUPPORTED;
12797 break;
12798 }
12799 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12800 ~B1_FACILITY_EC), EC_COMMAND_3);
12801 case EC_COMMAND_3:
12802 if (adjust_b_process(Id, plci, Rc) != GOOD)
12803 {
12804 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12805 UnMapId(Id), (char *)(FILE_), __LINE__));
12806 Info = _FACILITY_NOT_SUPPORTED;
12807 break;
12808 }
12809 if (plci->internal_command)
12810 return;
12811 break;
12812 }
12813 break;
12814 }
12815 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12816 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12817 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12818 }
12819
12820
12821 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12822 {
12823 word Info;
12824 word opt;
12825 API_PARSE ec_parms[3];
12826 byte result[16];
12827
12828 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12829 UnMapId(Id), (char *)(FILE_), __LINE__));
12830
12831 Info = GOOD;
12832 result[0] = 0;
12833 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12834 {
12835 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12836 UnMapId(Id), (char *)(FILE_), __LINE__));
12837 Info = _FACILITY_NOT_SUPPORTED;
12838 }
12839 else
12840 {
12841 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12842 {
12843 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12844 {
12845 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12846 UnMapId(Id), (char *)(FILE_), __LINE__));
12847 Info = _WRONG_MESSAGE_FORMAT;
12848 }
12849 else
12850 {
12851 if (plci == NULL)
12852 {
12853 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12854 UnMapId(Id), (char *)(FILE_), __LINE__));
12855 Info = _WRONG_IDENTIFIER;
12856 }
12857 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12858 {
12859 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12860 UnMapId(Id), (char *)(FILE_), __LINE__));
12861 Info = _WRONG_STATE;
12862 }
12863 else
12864 {
12865 plci->command = 0;
12866 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12867 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12868 result[0] = 2;
12869 PUT_WORD(&result[1], EC_SUCCESS);
12870 if (msg[1].length >= 4)
12871 {
12872 opt = GET_WORD(&ec_parms[0].info[2]);
12873 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12874 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12875 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12876 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12877 if (opt & EC_DETECT_DISABLE_TONE)
12878 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12879 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12880 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12881 if (msg[1].length >= 6)
12882 {
12883 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12884 }
12885 }
12886 switch (plci->ec_cmd)
12887 {
12888 case EC_ENABLE_OPERATION:
12889 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12890 start_internal_command(Id, plci, ec_command);
12891 return (false);
12892
12893 case EC_DISABLE_OPERATION:
12894 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12895 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12896 LEC_RESET_COEFFICIENTS;
12897 start_internal_command(Id, plci, ec_command);
12898 return (false);
12899
12900 case EC_FREEZE_COEFFICIENTS:
12901 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12902 start_internal_command(Id, plci, ec_command);
12903 return (false);
12904
12905 case EC_RESUME_COEFFICIENT_UPDATE:
12906 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12907 start_internal_command(Id, plci, ec_command);
12908 return (false);
12909
12910 case EC_RESET_COEFFICIENTS:
12911 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12912 start_internal_command(Id, plci, ec_command);
12913 return (false);
12914
12915 default:
12916 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12917 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12918 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12919 }
12920 }
12921 }
12922 }
12923 else
12924 {
12925 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12926 {
12927 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12928 UnMapId(Id), (char *)(FILE_), __LINE__));
12929 Info = _WRONG_MESSAGE_FORMAT;
12930 }
12931 else
12932 {
12933 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12934 {
12935 result[0] = 11;
12936 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12937 result[3] = 8;
12938 PUT_WORD(&result[4], GOOD);
12939 PUT_WORD(&result[6], 0x0007);
12940 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12941 PUT_WORD(&result[10], 0);
12942 }
12943 else if (plci == NULL)
12944 {
12945 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12946 UnMapId(Id), (char *)(FILE_), __LINE__));
12947 Info = _WRONG_IDENTIFIER;
12948 }
12949 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12950 {
12951 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12952 UnMapId(Id), (char *)(FILE_), __LINE__));
12953 Info = _WRONG_STATE;
12954 }
12955 else
12956 {
12957 plci->command = 0;
12958 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12959 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12960 result[0] = 5;
12961 PUT_WORD(&result[1], plci->ec_cmd);
12962 result[3] = 2;
12963 PUT_WORD(&result[4], GOOD);
12964 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12965 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12966 plci->ec_tail_length = 0;
12967 if (ec_parms[1].length >= 2)
12968 {
12969 opt = GET_WORD(&ec_parms[1].info[1]);
12970 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12971 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12972 if (opt & EC_DETECT_DISABLE_TONE)
12973 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12974 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12975 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12976 if (ec_parms[1].length >= 4)
12977 {
12978 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12979 }
12980 }
12981 switch (plci->ec_cmd)
12982 {
12983 case EC_ENABLE_OPERATION:
12984 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12985 start_internal_command(Id, plci, ec_command);
12986 return (false);
12987
12988 case EC_DISABLE_OPERATION:
12989 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12990 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12991 LEC_RESET_COEFFICIENTS;
12992 start_internal_command(Id, plci, ec_command);
12993 return (false);
12994
12995 default:
12996 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12997 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12998 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12999 }
13000 }
13001 }
13002 }
13003 }
13004 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13005 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13006 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13007 return (false);
13008 }
13009
13010
13011 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13012 {
13013 byte result[8];
13014
13015 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13016 UnMapId(Id), (char *)(FILE_), __LINE__));
13017
13018 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13019 {
13020 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13021 {
13022 result[0] = 2;
13023 PUT_WORD(&result[1], 0);
13024 switch (msg[1])
13025 {
13026 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13027 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13028 break;
13029 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13030 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13031 break;
13032 case LEC_DISABLE_RELEASED:
13033 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13034 break;
13035 }
13036 }
13037 else
13038 {
13039 result[0] = 5;
13040 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13041 result[3] = 2;
13042 PUT_WORD(&result[4], 0);
13043 switch (msg[1])
13044 {
13045 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13046 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13047 break;
13048 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13049 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13050 break;
13051 case LEC_DISABLE_RELEASED:
13052 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13053 break;
13054 }
13055 }
13056 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13057 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13058 }
13059 }
13060
13061
13062
13063 /*------------------------------------------------------------------*/
13064 /* Advanced voice */
13065 /*------------------------------------------------------------------*/
13066
13067 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13068 {
13069 DIVA_CAPI_ADAPTER *a;
13070 word i;
13071 byte *p;
13072
13073 word w, n, j, k;
13074 byte ch_map[MIXER_CHANNELS_BRI];
13075
13076 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13077
13078 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13079 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13080 (char *)(FILE_), __LINE__, write_command));
13081
13082 a = plci->adapter;
13083 p = coef_buffer + 1;
13084 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13085 i = 0;
13086 while (i + sizeof(word) <= a->adv_voice_coef_length)
13087 {
13088 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13089 p += 2;
13090 i += 2;
13091 }
13092 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13093 {
13094 PUT_WORD(p, 0x8000);
13095 p += 2;
13096 i += 2;
13097 }
13098
13099 if (!a->li_pri && (plci->li_bchannel_id == 0))
13100 {
13101 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13102 {
13103 plci->li_bchannel_id = 1;
13104 li_config_table[a->li_base].plci = plci;
13105 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13106 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13107 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13108 }
13109 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13110 {
13111 plci->li_bchannel_id = 2;
13112 li_config_table[a->li_base + 1].plci = plci;
13113 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13114 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13115 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13116 }
13117 }
13118 if (!a->li_pri && (plci->li_bchannel_id != 0)
13119 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13120 {
13121 i = a->li_base + (plci->li_bchannel_id - 1);
13122 switch (write_command)
13123 {
13124 case ADV_VOICE_WRITE_ACTIVATION:
13125 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13126 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13127 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13128 {
13129 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131 }
13132 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13133 {
13134 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13135 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13136 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13137 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13138 }
13139 mixer_calculate_coefs(a);
13140 li_config_table[i].curchnl = li_config_table[i].channel;
13141 li_config_table[j].curchnl = li_config_table[j].channel;
13142 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13143 li_config_table[k].curchnl = li_config_table[k].channel;
13144 break;
13145
13146 case ADV_VOICE_WRITE_DEACTIVATION:
13147 for (j = 0; j < li_total_channels; j++)
13148 {
13149 li_config_table[i].flag_table[j] = 0;
13150 li_config_table[j].flag_table[i] = 0;
13151 }
13152 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13153 for (j = 0; j < li_total_channels; j++)
13154 {
13155 li_config_table[k].flag_table[j] = 0;
13156 li_config_table[j].flag_table[k] = 0;
13157 }
13158 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13159 {
13160 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13161 for (j = 0; j < li_total_channels; j++)
13162 {
13163 li_config_table[k].flag_table[j] = 0;
13164 li_config_table[j].flag_table[k] = 0;
13165 }
13166 }
13167 mixer_calculate_coefs(a);
13168 break;
13169 }
13170 if (plci->B1_facilities & B1_FACILITY_MIXER)
13171 {
13172 w = 0;
13173 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13174 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13175 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13176 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13177 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13178 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13179 *(p++) = (byte) w;
13180 *(p++) = (byte)(w >> 8);
13181 for (j = 0; j < sizeof(ch_map); j += 2)
13182 {
13183 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13184 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13185 }
13186 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13187 {
13188 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13189 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13190 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13191 {
13192 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13193 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13194 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13195 }
13196 else
13197 {
13198 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13199 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13200 }
13201 }
13202 }
13203 else
13204 {
13205 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206 *(p++) = a->adv_voice_coef_buffer[i];
13207 }
13208 }
13209 else
13210
13211 {
13212 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213 *(p++) = a->adv_voice_coef_buffer[i];
13214 }
13215 coef_buffer[0] = (p - coef_buffer) - 1;
13216 add_p(plci, FTY, coef_buffer);
13217 sig_req(plci, TEL_CTRL, 0);
13218 send_req(plci);
13219 }
13220
13221
13222 static void adv_voice_clear_config(PLCI *plci)
13223 {
13224 DIVA_CAPI_ADAPTER *a;
13225
13226 word i, j;
13227
13228
13229 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13230 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13231 (char *)(FILE_), __LINE__));
13232
13233 a = plci->adapter;
13234 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13235 {
13236 a->adv_voice_coef_length = 0;
13237
13238 if (!a->li_pri && (plci->li_bchannel_id != 0)
13239 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13240 {
13241 i = a->li_base + (plci->li_bchannel_id - 1);
13242 li_config_table[i].curchnl = 0;
13243 li_config_table[i].channel = 0;
13244 li_config_table[i].chflags = 0;
13245 for (j = 0; j < li_total_channels; j++)
13246 {
13247 li_config_table[i].flag_table[j] = 0;
13248 li_config_table[j].flag_table[i] = 0;
13249 li_config_table[i].coef_table[j] = 0;
13250 li_config_table[j].coef_table[i] = 0;
13251 }
13252 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13253 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13254 li_config_table[i].curchnl = 0;
13255 li_config_table[i].channel = 0;
13256 li_config_table[i].chflags = 0;
13257 for (j = 0; j < li_total_channels; j++)
13258 {
13259 li_config_table[i].flag_table[j] = 0;
13260 li_config_table[j].flag_table[i] = 0;
13261 li_config_table[i].coef_table[j] = 0;
13262 li_config_table[j].coef_table[i] = 0;
13263 }
13264 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13265 {
13266 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13267 li_config_table[i].curchnl = 0;
13268 li_config_table[i].channel = 0;
13269 li_config_table[i].chflags = 0;
13270 for (j = 0; j < li_total_channels; j++)
13271 {
13272 li_config_table[i].flag_table[j] = 0;
13273 li_config_table[j].flag_table[i] = 0;
13274 li_config_table[i].coef_table[j] = 0;
13275 li_config_table[j].coef_table[i] = 0;
13276 }
13277 }
13278 }
13279
13280 }
13281 }
13282
13283
13284 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13285 {
13286
13287 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13288 UnMapId(Id), (char *)(FILE_), __LINE__));
13289
13290 }
13291
13292
13293 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13294 {
13295
13296 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13297 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13298
13299 return (GOOD);
13300 }
13301
13302
13303 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13304 {
13305 DIVA_CAPI_ADAPTER *a;
13306 word Info;
13307
13308 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13309 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13310
13311 Info = GOOD;
13312 a = plci->adapter;
13313 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13314 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13315 {
13316 switch (plci->adjust_b_state)
13317 {
13318 case ADJUST_B_RESTORE_VOICE_1:
13319 plci->internal_command = plci->adjust_b_command;
13320 if (plci->sig_req)
13321 {
13322 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13323 break;
13324 }
13325 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13326 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13327 break;
13328 case ADJUST_B_RESTORE_VOICE_2:
13329 if ((Rc != OK) && (Rc != OK_FC))
13330 {
13331 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13332 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13333 Info = _WRONG_STATE;
13334 break;
13335 }
13336 break;
13337 }
13338 }
13339 return (Info);
13340 }
13341
13342
13343
13344
13345 /*------------------------------------------------------------------*/
13346 /* B1 resource switching */
13347 /*------------------------------------------------------------------*/
13348
13349 static byte b1_facilities_table[] =
13350 {
13351 0x00, /* 0 No bchannel resources */
13352 0x00, /* 1 Codec (automatic law) */
13353 0x00, /* 2 Codec (A-law) */
13354 0x00, /* 3 Codec (y-law) */
13355 0x00, /* 4 HDLC for X.21 */
13356 0x00, /* 5 HDLC */
13357 0x00, /* 6 External Device 0 */
13358 0x00, /* 7 External Device 1 */
13359 0x00, /* 8 HDLC 56k */
13360 0x00, /* 9 Transparent */
13361 0x00, /* 10 Loopback to network */
13362 0x00, /* 11 Test pattern to net */
13363 0x00, /* 12 Rate adaptation sync */
13364 0x00, /* 13 Rate adaptation async */
13365 0x00, /* 14 R-Interface */
13366 0x00, /* 15 HDLC 128k leased line */
13367 0x00, /* 16 FAX */
13368 0x00, /* 17 Modem async */
13369 0x00, /* 18 Modem sync HDLC */
13370 0x00, /* 19 V.110 async HDLC */
13371 0x12, /* 20 Adv voice (Trans,mixer) */
13372 0x00, /* 21 Codec connected to IC */
13373 0x0c, /* 22 Trans,DTMF */
13374 0x1e, /* 23 Trans,DTMF+mixer */
13375 0x1f, /* 24 Trans,DTMF+mixer+local */
13376 0x13, /* 25 Trans,mixer+local */
13377 0x12, /* 26 HDLC,mixer */
13378 0x12, /* 27 HDLC 56k,mixer */
13379 0x2c, /* 28 Trans,LEC+DTMF */
13380 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13381 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13382 0x2c, /* 31 RTP,LEC+DTMF */
13383 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13384 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13385 0x00, /* 34 Signaling task */
13386 0x00, /* 35 PIAFS */
13387 0x0c, /* 36 Trans,DTMF+TONE */
13388 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13389 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13390 };
13391
13392
13393 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13394 {
13395 word b1_facilities;
13396
13397 b1_facilities = b1_facilities_table[b1_resource];
13398 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13399 {
13400
13401 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13402 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13403
13404 {
13405 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13406 b1_facilities |= B1_FACILITY_DTMFX;
13407 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13408 b1_facilities |= B1_FACILITY_DTMFR;
13409 }
13410 }
13411 if ((b1_resource == 17) || (b1_resource == 18))
13412 {
13413 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13414 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13415 }
13416 /*
13417 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13418 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13419 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13420 */
13421 return (b1_facilities);
13422 }
13423
13424
13425 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13426 {
13427 byte b;
13428
13429 switch (b1_resource)
13430 {
13431 case 5:
13432 case 26:
13433 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13434 b = 26;
13435 else
13436 b = 5;
13437 break;
13438
13439 case 8:
13440 case 27:
13441 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13442 b = 27;
13443 else
13444 b = 8;
13445 break;
13446
13447 case 9:
13448 case 20:
13449 case 22:
13450 case 23:
13451 case 24:
13452 case 25:
13453 case 28:
13454 case 29:
13455 case 30:
13456 case 36:
13457 case 37:
13458 case 38:
13459 if (b1_facilities & B1_FACILITY_EC)
13460 {
13461 if (b1_facilities & B1_FACILITY_LOCAL)
13462 b = 30;
13463 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13464 b = 29;
13465 else
13466 b = 28;
13467 }
13468
13469 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13470 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13471 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13472 {
13473 if (b1_facilities & B1_FACILITY_LOCAL)
13474 b = 38;
13475 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13476 b = 37;
13477 else
13478 b = 36;
13479 }
13480
13481 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13482 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13483 || ((b1_facilities & B1_FACILITY_DTMFR)
13484 && ((b1_facilities & B1_FACILITY_MIXER)
13485 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13486 || ((b1_facilities & B1_FACILITY_DTMFX)
13487 && ((b1_facilities & B1_FACILITY_MIXER)
13488 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13489 {
13490 if (b1_facilities & B1_FACILITY_LOCAL)
13491 b = 24;
13492 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13493 b = 23;
13494 else
13495 b = 22;
13496 }
13497 else
13498 {
13499 if (b1_facilities & B1_FACILITY_LOCAL)
13500 b = 25;
13501 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13502 b = 20;
13503 else
13504 b = 9;
13505 }
13506 break;
13507
13508 case 31:
13509 case 32:
13510 case 33:
13511 if (b1_facilities & B1_FACILITY_LOCAL)
13512 b = 33;
13513 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13514 b = 32;
13515 else
13516 b = 31;
13517 break;
13518
13519 default:
13520 b = b1_resource;
13521 }
13522 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13523 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13524 (char *)(FILE_), __LINE__,
13525 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13526 return (b);
13527 }
13528
13529
13530 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13531 {
13532 word removed_facilities;
13533
13534 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13535 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13536 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13537 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13538
13539 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13540 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13541
13542 if (removed_facilities & B1_FACILITY_EC)
13543 ec_clear_config(plci);
13544
13545
13546 if (removed_facilities & B1_FACILITY_DTMFR)
13547 {
13548 dtmf_rec_clear_config(plci);
13549 dtmf_parameter_clear_config(plci);
13550 }
13551 if (removed_facilities & B1_FACILITY_DTMFX)
13552 dtmf_send_clear_config(plci);
13553
13554
13555 if (removed_facilities & B1_FACILITY_MIXER)
13556 mixer_clear_config(plci);
13557
13558 if (removed_facilities & B1_FACILITY_VOICE)
13559 adv_voice_clear_config(plci);
13560 plci->B1_facilities = new_b1_facilities;
13561 }
13562
13563
13564 static void adjust_b_clear(PLCI *plci)
13565 {
13566
13567 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13568 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13569 (char *)(FILE_), __LINE__));
13570
13571 plci->adjust_b_restore = false;
13572 }
13573
13574
13575 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13576 {
13577 word Info;
13578 byte b1_resource;
13579 NCCI *ncci_ptr;
13580 API_PARSE bp[2];
13581
13582 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13583 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13584
13585 Info = GOOD;
13586 switch (plci->adjust_b_state)
13587 {
13588 case ADJUST_B_START:
13589 if ((plci->adjust_b_parms_msg == NULL)
13590 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13591 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13592 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13593 {
13594 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13595 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13596 if (b1_resource == plci->B1_resource)
13597 {
13598 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13599 break;
13600 }
13601 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13602 {
13603 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13604 UnMapId(Id), (char *)(FILE_), __LINE__,
13605 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13606 Info = _WRONG_STATE;
13607 break;
13608 }
13609 }
13610 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13611 {
13612
13613 mixer_prepare_switch(Id, plci);
13614
13615
13616 dtmf_prepare_switch(Id, plci);
13617 dtmf_parameter_prepare_switch(Id, plci);
13618
13619
13620 ec_prepare_switch(Id, plci);
13621
13622 adv_voice_prepare_switch(Id, plci);
13623 }
13624 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13625 Rc = OK;
13626 case ADJUST_B_SAVE_MIXER_1:
13627 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13628 {
13629
13630 Info = mixer_save_config(Id, plci, Rc);
13631 if ((Info != GOOD) || plci->internal_command)
13632 break;
13633
13634 }
13635 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13636 Rc = OK;
13637 case ADJUST_B_SAVE_DTMF_1:
13638 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13639 {
13640
13641 Info = dtmf_save_config(Id, plci, Rc);
13642 if ((Info != GOOD) || plci->internal_command)
13643 break;
13644
13645 }
13646 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13647 case ADJUST_B_REMOVE_L23_1:
13648 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13649 && plci->NL.Id && !plci->nl_remove_id)
13650 {
13651 plci->internal_command = plci->adjust_b_command;
13652 if (plci->adjust_b_ncci != 0)
13653 {
13654 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13655 while (ncci_ptr->data_pending)
13656 {
13657 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13658 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13659 }
13660 while (ncci_ptr->data_ack_pending)
13661 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13662 }
13663 nl_req_ncci(plci, REMOVE,
13664 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13665 send_req(plci);
13666 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13667 break;
13668 }
13669 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13670 Rc = OK;
13671 case ADJUST_B_REMOVE_L23_2:
13672 if ((Rc != OK) && (Rc != OK_FC))
13673 {
13674 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13675 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13676 Info = _WRONG_STATE;
13677 break;
13678 }
13679 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13680 {
13681 if (plci_nl_busy(plci))
13682 {
13683 plci->internal_command = plci->adjust_b_command;
13684 break;
13685 }
13686 }
13687 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13688 Rc = OK;
13689 case ADJUST_B_SAVE_EC_1:
13690 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13691 {
13692
13693 Info = ec_save_config(Id, plci, Rc);
13694 if ((Info != GOOD) || plci->internal_command)
13695 break;
13696
13697 }
13698 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13699 Rc = OK;
13700 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13701 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13702 {
13703
13704 Info = dtmf_parameter_save_config(Id, plci, Rc);
13705 if ((Info != GOOD) || plci->internal_command)
13706 break;
13707
13708 }
13709 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13710 Rc = OK;
13711 case ADJUST_B_SAVE_VOICE_1:
13712 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13713 {
13714 Info = adv_voice_save_config(Id, plci, Rc);
13715 if ((Info != GOOD) || plci->internal_command)
13716 break;
13717 }
13718 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13719 case ADJUST_B_SWITCH_L1_1:
13720 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13721 {
13722 if (plci->sig_req)
13723 {
13724 plci->internal_command = plci->adjust_b_command;
13725 break;
13726 }
13727 if (plci->adjust_b_parms_msg != NULL)
13728 api_load_msg(plci->adjust_b_parms_msg, bp);
13729 else
13730 api_load_msg(&plci->B_protocol, bp);
13731 Info = add_b1(plci, bp,
13732 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13733 plci->adjust_b_facilities);
13734 if (Info != GOOD)
13735 {
13736 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13737 UnMapId(Id), (char *)(FILE_), __LINE__,
13738 plci->B1_resource, plci->adjust_b_facilities));
13739 break;
13740 }
13741 plci->internal_command = plci->adjust_b_command;
13742 sig_req(plci, RESOURCES, 0);
13743 send_req(plci);
13744 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13745 break;
13746 }
13747 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13748 Rc = OK;
13749 case ADJUST_B_SWITCH_L1_2:
13750 if ((Rc != OK) && (Rc != OK_FC))
13751 {
13752 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13753 UnMapId(Id), (char *)(FILE_), __LINE__,
13754 Rc, plci->B1_resource, plci->adjust_b_facilities));
13755 Info = _WRONG_STATE;
13756 break;
13757 }
13758 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13759 Rc = OK;
13760 case ADJUST_B_RESTORE_VOICE_1:
13761 case ADJUST_B_RESTORE_VOICE_2:
13762 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13763 {
13764 Info = adv_voice_restore_config(Id, plci, Rc);
13765 if ((Info != GOOD) || plci->internal_command)
13766 break;
13767 }
13768 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13769 Rc = OK;
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13771 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13772 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13773 {
13774
13775 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13776 if ((Info != GOOD) || plci->internal_command)
13777 break;
13778
13779 }
13780 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13781 Rc = OK;
13782 case ADJUST_B_RESTORE_EC_1:
13783 case ADJUST_B_RESTORE_EC_2:
13784 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13785 {
13786
13787 Info = ec_restore_config(Id, plci, Rc);
13788 if ((Info != GOOD) || plci->internal_command)
13789 break;
13790
13791 }
13792 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13793 case ADJUST_B_ASSIGN_L23_1:
13794 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13795 {
13796 if (plci_nl_busy(plci))
13797 {
13798 plci->internal_command = plci->adjust_b_command;
13799 break;
13800 }
13801 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13802 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13803 if (plci->adjust_b_parms_msg != NULL)
13804 api_load_msg(plci->adjust_b_parms_msg, bp);
13805 else
13806 api_load_msg(&plci->B_protocol, bp);
13807 Info = add_b23(plci, bp);
13808 if (Info != GOOD)
13809 {
13810 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13811 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13812 break;
13813 }
13814 plci->internal_command = plci->adjust_b_command;
13815 nl_req_ncci(plci, ASSIGN, 0);
13816 send_req(plci);
13817 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13818 break;
13819 }
13820 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13821 Rc = ASSIGN_OK;
13822 case ADJUST_B_ASSIGN_L23_2:
13823 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13824 {
13825 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13826 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13827 Info = _WRONG_STATE;
13828 break;
13829 }
13830 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13831 {
13832 if (Rc != ASSIGN_OK)
13833 {
13834 plci->internal_command = plci->adjust_b_command;
13835 break;
13836 }
13837 }
13838 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13839 {
13840 plci->adjust_b_restore = true;
13841 break;
13842 }
13843 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13844 case ADJUST_B_CONNECT_1:
13845 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13846 {
13847 plci->internal_command = plci->adjust_b_command;
13848 if (plci_nl_busy(plci))
13849 break;
13850 nl_req_ncci(plci, N_CONNECT, 0);
13851 send_req(plci);
13852 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13853 break;
13854 }
13855 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13856 Rc = OK;
13857 case ADJUST_B_CONNECT_2:
13858 case ADJUST_B_CONNECT_3:
13859 case ADJUST_B_CONNECT_4:
13860 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13861 {
13862 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13863 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13864 Info = _WRONG_STATE;
13865 break;
13866 }
13867 if (Rc == OK)
13868 {
13869 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13870 {
13871 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13872 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13873 }
13874 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13876 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13877 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878 }
13879 else if (Rc == 0)
13880 {
13881 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13883 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13884 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13885 }
13886 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13887 {
13888 plci->internal_command = plci->adjust_b_command;
13889 break;
13890 }
13891 Rc = OK;
13892 case ADJUST_B_RESTORE_DTMF_1:
13893 case ADJUST_B_RESTORE_DTMF_2:
13894 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13895 {
13896
13897 Info = dtmf_restore_config(Id, plci, Rc);
13898 if ((Info != GOOD) || plci->internal_command)
13899 break;
13900
13901 }
13902 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13903 Rc = OK;
13904 case ADJUST_B_RESTORE_MIXER_1:
13905 case ADJUST_B_RESTORE_MIXER_2:
13906 case ADJUST_B_RESTORE_MIXER_3:
13907 case ADJUST_B_RESTORE_MIXER_4:
13908 case ADJUST_B_RESTORE_MIXER_5:
13909 case ADJUST_B_RESTORE_MIXER_6:
13910 case ADJUST_B_RESTORE_MIXER_7:
13911 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13912 {
13913
13914 Info = mixer_restore_config(Id, plci, Rc);
13915 if ((Info != GOOD) || plci->internal_command)
13916 break;
13917
13918 }
13919 plci->adjust_b_state = ADJUST_B_END;
13920 case ADJUST_B_END:
13921 break;
13922 }
13923 return (Info);
13924 }
13925
13926
13927 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13928 {
13929
13930 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13931 UnMapId(Id), (char *)(FILE_), __LINE__,
13932 plci->B1_resource, b1_facilities));
13933
13934 plci->adjust_b_parms_msg = bp_msg;
13935 plci->adjust_b_facilities = b1_facilities;
13936 plci->adjust_b_command = internal_command;
13937 plci->adjust_b_ncci = (word)(Id >> 16);
13938 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13939 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13940 else
13941 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13942 plci->adjust_b_state = ADJUST_B_START;
13943 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13944 UnMapId(Id), (char *)(FILE_), __LINE__,
13945 plci->B1_resource, b1_facilities));
13946 }
13947
13948
13949 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13950 {
13951 word internal_command;
13952
13953 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13954 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13955
13956 internal_command = plci->internal_command;
13957 plci->internal_command = 0;
13958 switch (internal_command)
13959 {
13960 default:
13961 plci->command = 0;
13962 if (plci->req_in != 0)
13963 {
13964 plci->internal_command = ADJUST_B_RESTORE_1;
13965 break;
13966 }
13967 Rc = OK;
13968 case ADJUST_B_RESTORE_1:
13969 if ((Rc != OK) && (Rc != OK_FC))
13970 {
13971 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13972 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13973 }
13974 plci->adjust_b_parms_msg = NULL;
13975 plci->adjust_b_facilities = plci->B1_facilities;
13976 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13977 plci->adjust_b_ncci = (word)(Id >> 16);
13978 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13979 plci->adjust_b_state = ADJUST_B_START;
13980 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13981 UnMapId(Id), (char *)(FILE_), __LINE__));
13982 case ADJUST_B_RESTORE_2:
13983 if (adjust_b_process(Id, plci, Rc) != GOOD)
13984 {
13985 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13986 UnMapId(Id), (char *)(FILE_), __LINE__));
13987 }
13988 if (plci->internal_command)
13989 break;
13990 break;
13991 }
13992 }
13993
13994
13995 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13996 {
13997 word Info;
13998 word internal_command;
13999
14000 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14001 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14002
14003 Info = GOOD;
14004 internal_command = plci->internal_command;
14005 plci->internal_command = 0;
14006 switch (internal_command)
14007 {
14008 default:
14009 plci->command = 0;
14010 plci->adjust_b_parms_msg = NULL;
14011 plci->adjust_b_facilities = plci->B1_facilities;
14012 plci->adjust_b_command = RESET_B3_COMMAND_1;
14013 plci->adjust_b_ncci = (word)(Id >> 16);
14014 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14015 plci->adjust_b_state = ADJUST_B_START;
14016 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14017 UnMapId(Id), (char *)(FILE_), __LINE__));
14018 case RESET_B3_COMMAND_1:
14019 Info = adjust_b_process(Id, plci, Rc);
14020 if (Info != GOOD)
14021 {
14022 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14023 UnMapId(Id), (char *)(FILE_), __LINE__));
14024 break;
14025 }
14026 if (plci->internal_command)
14027 return;
14028 break;
14029 }
14030 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14031 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14032 }
14033
14034
14035 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14036 {
14037 word Info;
14038 word internal_command;
14039 byte esc_chi[3];
14040
14041 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14042 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14043
14044 Info = GOOD;
14045 internal_command = plci->internal_command;
14046 plci->internal_command = 0;
14047 switch (internal_command)
14048 {
14049 default:
14050 plci->command = 0;
14051 plci->adjust_b_parms_msg = &plci->saved_msg;
14052 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14053 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14054 else
14055 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14056 plci->adjust_b_command = SELECT_B_COMMAND_1;
14057 plci->adjust_b_ncci = (word)(Id >> 16);
14058 if (plci->saved_msg.parms[0].length == 0)
14059 {
14060 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061 ADJUST_B_MODE_NO_RESOURCE;
14062 }
14063 else
14064 {
14065 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14066 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14067 }
14068 plci->adjust_b_state = ADJUST_B_START;
14069 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14070 UnMapId(Id), (char *)(FILE_), __LINE__));
14071 case SELECT_B_COMMAND_1:
14072 Info = adjust_b_process(Id, plci, Rc);
14073 if (Info != GOOD)
14074 {
14075 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14076 UnMapId(Id), (char *)(FILE_), __LINE__));
14077 break;
14078 }
14079 if (plci->internal_command)
14080 return;
14081 if (plci->tel == ADV_VOICE)
14082 {
14083 esc_chi[0] = 0x02;
14084 esc_chi[1] = 0x18;
14085 esc_chi[2] = plci->b_channel;
14086 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14087 }
14088 break;
14089 }
14090 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14091 }
14092
14093
14094 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14095 {
14096 word internal_command;
14097
14098 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14099 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14100
14101 internal_command = plci->internal_command;
14102 plci->internal_command = 0;
14103 switch (internal_command)
14104 {
14105 default:
14106 plci->command = 0;
14107 case FAX_CONNECT_ACK_COMMAND_1:
14108 if (plci_nl_busy(plci))
14109 {
14110 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14111 return;
14112 }
14113 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14114 plci->NData[0].P = plci->fax_connect_info_buffer;
14115 plci->NData[0].PLength = plci->fax_connect_info_length;
14116 plci->NL.X = plci->NData;
14117 plci->NL.ReqCh = 0;
14118 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14119 plci->adapter->request(&plci->NL);
14120 return;
14121 case FAX_CONNECT_ACK_COMMAND_2:
14122 if ((Rc != OK) && (Rc != OK_FC))
14123 {
14124 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14125 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14126 break;
14127 }
14128 }
14129 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14130 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14131 {
14132 if (plci->B3_prot == 4)
14133 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14134 else
14135 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14136 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14137 }
14138 }
14139
14140
14141 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14142 {
14143 word internal_command;
14144
14145 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14146 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14147
14148 internal_command = plci->internal_command;
14149 plci->internal_command = 0;
14150 switch (internal_command)
14151 {
14152 default:
14153 plci->command = 0;
14154 case FAX_EDATA_ACK_COMMAND_1:
14155 if (plci_nl_busy(plci))
14156 {
14157 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14158 return;
14159 }
14160 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14161 plci->NData[0].P = plci->fax_connect_info_buffer;
14162 plci->NData[0].PLength = plci->fax_edata_ack_length;
14163 plci->NL.X = plci->NData;
14164 plci->NL.ReqCh = 0;
14165 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14166 plci->adapter->request(&plci->NL);
14167 return;
14168 case FAX_EDATA_ACK_COMMAND_2:
14169 if ((Rc != OK) && (Rc != OK_FC))
14170 {
14171 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14172 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14173 break;
14174 }
14175 }
14176 }
14177
14178
14179 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14180 {
14181 word Info;
14182 word internal_command;
14183
14184 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14185 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14186
14187 Info = GOOD;
14188 internal_command = plci->internal_command;
14189 plci->internal_command = 0;
14190 switch (internal_command)
14191 {
14192 default:
14193 plci->command = 0;
14194 case FAX_CONNECT_INFO_COMMAND_1:
14195 if (plci_nl_busy(plci))
14196 {
14197 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14198 return;
14199 }
14200 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14201 plci->NData[0].P = plci->fax_connect_info_buffer;
14202 plci->NData[0].PLength = plci->fax_connect_info_length;
14203 plci->NL.X = plci->NData;
14204 plci->NL.ReqCh = 0;
14205 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14206 plci->adapter->request(&plci->NL);
14207 return;
14208 case FAX_CONNECT_INFO_COMMAND_2:
14209 if ((Rc != OK) && (Rc != OK_FC))
14210 {
14211 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14212 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213 Info = _WRONG_STATE;
14214 break;
14215 }
14216 if (plci_nl_busy(plci))
14217 {
14218 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14219 return;
14220 }
14221 plci->command = _CONNECT_B3_R;
14222 nl_req_ncci(plci, N_CONNECT, 0);
14223 send_req(plci);
14224 return;
14225 }
14226 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14227 }
14228
14229
14230 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14231 {
14232 word Info;
14233 word internal_command;
14234
14235 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14236 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14237
14238 Info = GOOD;
14239 internal_command = plci->internal_command;
14240 plci->internal_command = 0;
14241 switch (internal_command)
14242 {
14243 default:
14244 plci->command = 0;
14245 plci->adjust_b_parms_msg = NULL;
14246 plci->adjust_b_facilities = plci->B1_facilities;
14247 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14248 plci->adjust_b_ncci = (word)(Id >> 16);
14249 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14250 plci->adjust_b_state = ADJUST_B_START;
14251 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14252 UnMapId(Id), (char *)(FILE_), __LINE__));
14253 case FAX_ADJUST_B23_COMMAND_1:
14254 Info = adjust_b_process(Id, plci, Rc);
14255 if (Info != GOOD)
14256 {
14257 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14258 UnMapId(Id), (char *)(FILE_), __LINE__));
14259 break;
14260 }
14261 if (plci->internal_command)
14262 return;
14263 case FAX_ADJUST_B23_COMMAND_2:
14264 if (plci_nl_busy(plci))
14265 {
14266 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14267 return;
14268 }
14269 plci->command = _CONNECT_B3_R;
14270 nl_req_ncci(plci, N_CONNECT, 0);
14271 send_req(plci);
14272 return;
14273 }
14274 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14275 }
14276
14277
14278 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14279 {
14280 word internal_command;
14281
14282 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14283 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14284
14285 internal_command = plci->internal_command;
14286 plci->internal_command = 0;
14287 switch (internal_command)
14288 {
14289 default:
14290 plci->command = 0;
14291 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14292 return;
14293 case FAX_DISCONNECT_COMMAND_1:
14294 case FAX_DISCONNECT_COMMAND_2:
14295 case FAX_DISCONNECT_COMMAND_3:
14296 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14297 {
14298 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14299 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14300 break;
14301 }
14302 if (Rc == OK)
14303 {
14304 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14305 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14306 {
14307 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14308 }
14309 }
14310 else if (Rc == 0)
14311 {
14312 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14313 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14314 }
14315 return;
14316 }
14317 }
14318
14319
14320
14321 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14322 {
14323 word Info;
14324 word internal_command;
14325
14326 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14327 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14328
14329 Info = GOOD;
14330 internal_command = plci->internal_command;
14331 plci->internal_command = 0;
14332 switch (internal_command)
14333 {
14334 default:
14335 plci->command = 0;
14336 case RTP_CONNECT_B3_REQ_COMMAND_1:
14337 if (plci_nl_busy(plci))
14338 {
14339 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14340 return;
14341 }
14342 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14343 nl_req_ncci(plci, N_CONNECT, 0);
14344 send_req(plci);
14345 return;
14346 case RTP_CONNECT_B3_REQ_COMMAND_2:
14347 if ((Rc != OK) && (Rc != OK_FC))
14348 {
14349 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14350 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14351 Info = _WRONG_STATE;
14352 break;
14353 }
14354 if (plci_nl_busy(plci))
14355 {
14356 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14357 return;
14358 }
14359 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14360 plci->NData[0].PLength = plci->internal_req_buffer[0];
14361 plci->NData[0].P = plci->internal_req_buffer + 1;
14362 plci->NL.X = plci->NData;
14363 plci->NL.ReqCh = 0;
14364 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14365 plci->adapter->request(&plci->NL);
14366 break;
14367 case RTP_CONNECT_B3_REQ_COMMAND_3:
14368 return;
14369 }
14370 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14371 }
14372
14373
14374 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14375 {
14376 word internal_command;
14377
14378 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14379 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14380
14381 internal_command = plci->internal_command;
14382 plci->internal_command = 0;
14383 switch (internal_command)
14384 {
14385 default:
14386 plci->command = 0;
14387 case RTP_CONNECT_B3_RES_COMMAND_1:
14388 if (plci_nl_busy(plci))
14389 {
14390 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14391 return;
14392 }
14393 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14394 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14395 send_req(plci);
14396 return;
14397 case RTP_CONNECT_B3_RES_COMMAND_2:
14398 if ((Rc != OK) && (Rc != OK_FC))
14399 {
14400 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14401 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14402 break;
14403 }
14404 if (plci_nl_busy(plci))
14405 {
14406 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14407 return;
14408 }
14409 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14410 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14411 plci->NData[0].PLength = plci->internal_req_buffer[0];
14412 plci->NData[0].P = plci->internal_req_buffer + 1;
14413 plci->NL.X = plci->NData;
14414 plci->NL.ReqCh = 0;
14415 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14416 plci->adapter->request(&plci->NL);
14417 return;
14418 case RTP_CONNECT_B3_RES_COMMAND_3:
14419 return;
14420 }
14421 }
14422
14423
14424
14425 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14426 {
14427 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14428 word Info;
14429 word internal_command;
14430
14431 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14432 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14433
14434 Info = GOOD;
14435 internal_command = plci->internal_command;
14436 plci->internal_command = 0;
14437 switch (internal_command)
14438 {
14439 default:
14440 if (!plci->NL.Id)
14441 break;
14442 plci->command = 0;
14443 plci->adjust_b_parms_msg = NULL;
14444 plci->adjust_b_facilities = plci->B1_facilities;
14445 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14446 plci->adjust_b_ncci = (word)(Id >> 16);
14447 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14448 plci->adjust_b_state = ADJUST_B_START;
14449 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14450 UnMapId(Id), (char *)(FILE_), __LINE__));
14451 case HOLD_SAVE_COMMAND_1:
14452 Info = adjust_b_process(Id, plci, Rc);
14453 if (Info != GOOD)
14454 {
14455 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14456 UnMapId(Id), (char *)(FILE_), __LINE__));
14457 break;
14458 }
14459 if (plci->internal_command)
14460 return;
14461 }
14462 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14463 }
14464
14465
14466 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14467 {
14468 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14469 word Info;
14470 word internal_command;
14471
14472 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14473 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14474
14475 Info = GOOD;
14476 internal_command = plci->internal_command;
14477 plci->internal_command = 0;
14478 switch (internal_command)
14479 {
14480 default:
14481 plci->command = 0;
14482 plci->adjust_b_parms_msg = NULL;
14483 plci->adjust_b_facilities = plci->B1_facilities;
14484 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14485 plci->adjust_b_ncci = (word)(Id >> 16);
14486 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14487 plci->adjust_b_state = ADJUST_B_START;
14488 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14489 UnMapId(Id), (char *)(FILE_), __LINE__));
14490 case RETRIEVE_RESTORE_COMMAND_1:
14491 Info = adjust_b_process(Id, plci, Rc);
14492 if (Info != GOOD)
14493 {
14494 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14495 UnMapId(Id), (char *)(FILE_), __LINE__));
14496 break;
14497 }
14498 if (plci->internal_command)
14499 return;
14500 }
14501 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14502 }
14503
14504
14505 static void init_b1_config(PLCI *plci)
14506 {
14507
14508 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14509 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14510 (char *)(FILE_), __LINE__));
14511
14512 plci->B1_resource = 0;
14513 plci->B1_facilities = 0;
14514
14515 plci->li_bchannel_id = 0;
14516 mixer_clear_config(plci);
14517
14518
14519 ec_clear_config(plci);
14520
14521
14522 dtmf_rec_clear_config(plci);
14523 dtmf_send_clear_config(plci);
14524 dtmf_parameter_clear_config(plci);
14525
14526 adv_voice_clear_config(plci);
14527 adjust_b_clear(plci);
14528 }
14529
14530
14531 static void clear_b1_config(PLCI *plci)
14532 {
14533
14534 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14535 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14536 (char *)(FILE_), __LINE__));
14537
14538 adv_voice_clear_config(plci);
14539 adjust_b_clear(plci);
14540
14541 ec_clear_config(plci);
14542
14543
14544 dtmf_rec_clear_config(plci);
14545 dtmf_send_clear_config(plci);
14546 dtmf_parameter_clear_config(plci);
14547
14548
14549 if ((plci->li_bchannel_id != 0)
14550 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14551 {
14552 mixer_clear_config(plci);
14553 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14554 plci->li_bchannel_id = 0;
14555 }
14556
14557 plci->B1_resource = 0;
14558 plci->B1_facilities = 0;
14559 }
14560
14561
14562 /* -----------------------------------------------------------------
14563 XON protocol local helpers
14564 ----------------------------------------------------------------- */
14565 static void channel_flow_control_remove(PLCI *plci) {
14566 DIVA_CAPI_ADAPTER *a = plci->adapter;
14567 word i;
14568 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14569 if (a->ch_flow_plci[i] == plci->Id) {
14570 a->ch_flow_plci[i] = 0;
14571 a->ch_flow_control[i] = 0;
14572 }
14573 }
14574 }
14575
14576 static void channel_x_on(PLCI *plci, byte ch) {
14577 DIVA_CAPI_ADAPTER *a = plci->adapter;
14578 if (a->ch_flow_control[ch] & N_XON_SENT) {
14579 a->ch_flow_control[ch] &= ~N_XON_SENT;
14580 }
14581 }
14582
14583 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14584 DIVA_CAPI_ADAPTER *a = plci->adapter;
14585 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14586 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14587 a->ch_flow_plci[ch] = plci->Id;
14588 a->ch_flow_control_pending++;
14589 }
14590 }
14591
14592 static void channel_request_xon(PLCI *plci, byte ch) {
14593 DIVA_CAPI_ADAPTER *a = plci->adapter;
14594
14595 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14596 a->ch_flow_control[ch] |= N_XON_REQ;
14597 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14598 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14599 }
14600 }
14601
14602 static void channel_xmit_extended_xon(PLCI *plci) {
14603 DIVA_CAPI_ADAPTER *a;
14604 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14605 int i, one_requested = 0;
14606
14607 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14608 return;
14609 }
14610
14611 for (i = 0; i < max_ch; i++) {
14612 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14613 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14614 (plci->Id == a->ch_flow_plci[i])) {
14615 channel_request_xon(plci, (byte)i);
14616 one_requested = 1;
14617 }
14618 }
14619
14620 if (one_requested) {
14621 channel_xmit_xon(plci);
14622 }
14623 }
14624
14625 /*
14626 Try to xmit next X_ON
14627 */
14628 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14629 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630 int i;
14631
14632 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14633 return (0);
14634 }
14635
14636 if (a->last_flow_control_ch >= max_ch) {
14637 a->last_flow_control_ch = 1;
14638 }
14639 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14640 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14641 (plci->Id == a->ch_flow_plci[i])) {
14642 a->last_flow_control_ch = i + 1;
14643 return (i);
14644 }
14645 }
14646
14647 for (i = 1; i < a->last_flow_control_ch; i++) {
14648 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649 (plci->Id == a->ch_flow_plci[i])) {
14650 a->last_flow_control_ch = i + 1;
14651 return (i);
14652 }
14653 }
14654
14655 return (0);
14656 }
14657
14658 static void channel_xmit_xon(PLCI *plci) {
14659 DIVA_CAPI_ADAPTER *a = plci->adapter;
14660 byte ch;
14661
14662 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14663 return;
14664 }
14665 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14666 return;
14667 }
14668 a->ch_flow_control[ch] &= ~N_XON_REQ;
14669 a->ch_flow_control[ch] |= N_XON_SENT;
14670
14671 plci->NL.Req = plci->nl_req = (byte)N_XON;
14672 plci->NL.ReqCh = ch;
14673 plci->NL.X = plci->NData;
14674 plci->NL.XNum = 1;
14675 plci->NData[0].P = &plci->RBuffer[0];
14676 plci->NData[0].PLength = 0;
14677
14678 plci->adapter->request(&plci->NL);
14679 }
14680
14681 static int channel_can_xon(PLCI *plci, byte ch) {
14682 APPL *APPLptr;
14683 DIVA_CAPI_ADAPTER *a;
14684 word NCCIcode;
14685 dword count;
14686 word Num;
14687 word i;
14688
14689 APPLptr = plci->appl;
14690 a = plci->adapter;
14691
14692 if (!APPLptr)
14693 return (0);
14694
14695 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14696
14697 /* count all buffers within the Application pool */
14698 /* belonging to the same NCCI. XON if a first is */
14699 /* used. */
14700 count = 0;
14701 Num = 0xffff;
14702 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14703 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14704 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14705 }
14706 if ((count > 2) || (Num == 0xffff)) {
14707 return (0);
14708 }
14709 return (1);
14710 }
14711
14712
14713 /*------------------------------------------------------------------*/
14714
14715 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14716 {
14717 return 1;
14718 }
14719
14720
14721
14722 /**********************************************************************************/
14723 /* function groups the listening applications according to the CIP mask and the */
14724 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14725 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14726 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14727 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14728 /* OS specific part (per adapter). */
14729 /**********************************************************************************/
14730 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14731 {
14732 word i, j, k, busy, group_found;
14733 dword info_mask_group[MAX_CIP_TYPES];
14734 dword cip_mask_group[MAX_CIP_TYPES];
14735 word appl_number_group_type[MAX_APPL];
14736 PLCI *auxplci;
14737
14738 set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14739
14740 if (!a->group_optimization_enabled)
14741 {
14742 dbug(1, dprintf("No group optimization"));
14743 return;
14744 }
14745
14746 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14747
14748 for (i = 0; i < MAX_CIP_TYPES; i++)
14749 {
14750 info_mask_group[i] = 0;
14751 cip_mask_group[i] = 0;
14752 }
14753 for (i = 0; i < MAX_APPL; i++)
14754 {
14755 appl_number_group_type[i] = 0;
14756 }
14757 for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14758 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14759 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14760 {
14761 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14762 return; /* allow good application unfiltered access */
14763 }
14764 }
14765 for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14766 {
14767 if (application[i].Id && a->CIP_Mask[i])
14768 {
14769 for (k = 0, busy = false; k < a->max_plci; k++)
14770 {
14771 if (a->plci[k].Id)
14772 {
14773 auxplci = &a->plci[k];
14774 if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14775 {
14776 busy = true;
14777 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14778 }
14779 else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14780 {
14781 busy = true;
14782 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14783 }
14784 }
14785 }
14786
14787 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14788 {
14789 if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14790 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14791 appl_number_group_type[i] = MAX_CIP_TYPES;
14792 group_found = true;
14793 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14794 }
14795 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14796 { /* is group already present ? */
14797 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14798 group_found = true;
14799 dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14800 }
14801 else if (!info_mask_group[j])
14802 { /* establish a new group */
14803 appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14804 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14805 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14806 group_found = true;
14807 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]));
14808 }
14809 }
14810 }
14811 }
14812
14813 for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14814 {
14815 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14816 {
14817 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14818 {
14819 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14820 }
14821 else
14822 {
14823 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14824 for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14825 {
14826 if (appl_number_group_type[i] == appl_number_group_type[j])
14827 {
14828 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14829 clear_group_ind_mask_bit(plci, j); /* disable call on other group members */
14830 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14831 }
14832 }
14833 }
14834 }
14835 else /* application should not get a call */
14836 {
14837 clear_group_ind_mask_bit(plci, i);
14838 }
14839 }
14840
14841 }
14842
14843
14844
14845 /* OS notifies the driver about a application Capi_Register */
14846 word CapiRegister(word id)
14847 {
14848 word i, j, appls_found;
14849
14850 PLCI *plci;
14851 DIVA_CAPI_ADAPTER *a;
14852
14853 for (i = 0, appls_found = 0; i < max_appl; i++)
14854 {
14855 if (application[i].Id && (application[i].Id != id))
14856 {
14857 appls_found++; /* an application has been found */
14858 }
14859 }
14860
14861 if (appls_found) return true;
14862 for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14863 {
14864 a = &adapter[i];
14865 if (a->request)
14866 {
14867 if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14868 {
14869 if (!appls_found) /* first application does a capi register */
14870 {
14871 if ((j = get_plci(a))) /* activate L1 of all adapters */
14872 {
14873 plci = &a->plci[j - 1];
14874 plci->command = 0;
14875 add_p(plci, OAD, "\x01\xfd");
14876 add_p(plci, CAI, "\x01\x80");
14877 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14878 add_p(plci, SHIFT | 6, NULL);
14879 add_p(plci, SIN, "\x02\x00\x00");
14880 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14881 sig_req(plci, ASSIGN, DSIG_ID);
14882 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14883 sig_req(plci, SIG_CTRL, 0);
14884 send_req(plci);
14885 }
14886 }
14887 }
14888 }
14889 }
14890 return false;
14891 }
14892
14893 /*------------------------------------------------------------------*/
14894
14895 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14896
14897 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14898 {
14899 word i;
14900 /* Format of vswitch_t:
14901 0 byte length
14902 1 byte VSWITCHIE
14903 2 byte VSWITCH_REQ/VSWITCH_IND
14904 3 byte reserved
14905 4 word VSwitchcommand
14906 6 word returnerror
14907 8... Params
14908 */
14909 if (!plci ||
14910 !plci->appl ||
14911 !plci->State ||
14912 plci->Sig.Ind == NCR_FACILITY
14913 )
14914 return;
14915
14916 for (i = 0; i < MAX_MULTI_IE; i++)
14917 {
14918 if (!parms[i][0]) continue;
14919 if (parms[i][0] < 7)
14920 {
14921 parms[i][0] = 0; /* kill it */
14922 continue;
14923 }
14924 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14925 switch (parms[i][4])
14926 {
14927 case VSJOIN:
14928 if (!plci->relatedPTYPLCI ||
14929 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14930 { /* Error */
14931 break;
14932 }
14933 /* remember all necessary informations */
14934 if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14935 {
14936 break;
14937 }
14938 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14939 { /* first indication after ECT-Request on Consultation Call */
14940 plci->vswitchstate = parms[i][9];
14941 parms[i][9] = 2; /* State */
14942 /* now ask first Call to join */
14943 }
14944 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14945 { /* Answer of VSWITCH_REQ from first Call */
14946 plci->vswitchstate = parms[i][9];
14947 /* tell consultation call to join
14948 and the protocol capabilities of the first call */
14949 }
14950 else
14951 { /* Error */
14952 break;
14953 }
14954 plci->vsprot = parms[i][10]; /* protocol */
14955 plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14956 /* send join request to related PLCI */
14957 parms[i][1] = VSWITCHIE;
14958 parms[i][2] = VSWITCH_REQ;
14959
14960 plci->relatedPTYPLCI->command = 0;
14961 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14962 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14963 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14964 send_req(plci->relatedPTYPLCI);
14965 break;
14966 case VSTRANSPORT:
14967 default:
14968 if (plci->relatedPTYPLCI &&
14969 plci->vswitchstate == 3 &&
14970 plci->relatedPTYPLCI->vswitchstate == 3)
14971 {
14972 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14973 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14974 send_req(plci->relatedPTYPLCI);
14975 }
14976 break;
14977 }
14978 parms[i][0] = 0; /* kill it */
14979 }
14980 }
14981
14982
14983 /*------------------------------------------------------------------*/
14984
14985 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14986 ENTITY e;
14987 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14988
14989 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14990 return (-1);
14991 }
14992
14993 pReq->xdi_dma_descriptor_operation.Req = 0;
14994 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14995
14996 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14997 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14998 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14999 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15000
15001 e.user[0] = plci->adapter->Id - 1;
15002 plci->adapter->request((ENTITY *)pReq);
15003
15004 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15005 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15006 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15007 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15008 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15009 plci->adapter->Id,
15010 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15011 *dma_magic));
15012 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15013 } else {
15014 dbug(1, dprintf("dma_alloc failed"));
15015 return (-1);
15016 }
15017 }
15018
15019 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15020 ENTITY e;
15021 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15022
15023 if (nr < 0) {
15024 return;
15025 }
15026
15027 pReq->xdi_dma_descriptor_operation.Req = 0;
15028 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15029
15030 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15031 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15032 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15033 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15034
15035 e.user[0] = plci->adapter->Id - 1;
15036 plci->adapter->request((ENTITY *)pReq);
15037
15038 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15039 dbug(1, dprintf("dma_free(%d)", nr));
15040 } else {
15041 dbug(1, dprintf("dma_free failed (%d)", nr));
15042 }
15043 }
15044
15045 /*------------------------------------------------------------------*/