1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/bitmap.h>
27
28#include "platform.h"
29#include "di_defs.h"
30#include "pc.h"
31#include "capi20.h"
32#include "divacapi.h"
33#include "mdm_msg.h"
34#include "divasync.h"
35
36#define FILE_ "MESSAGE.C"
37#define dprintf
38
39
40
41
42
43
44
45static dword diva_xdi_extended_features = 0;
46
47#define DIVA_CAPI_USE_CMA 0x00000001
48#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
49#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
50#define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
51
52
53
54
55
56#define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
57
58
59
60
61
62static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
63void AutomaticLaw(DIVA_CAPI_ADAPTER *);
64word CapiRelease(word);
65word CapiRegister(word);
66word api_put(APPL *, CAPI_MSG *);
67static word api_parse(byte *, word, byte *, API_PARSE *);
68static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
69static void api_load_msg(API_SAVE *in, API_PARSE *out);
70
71word api_remove_start(void);
72void api_remove_complete(void);
73
74static void plci_remove(PLCI *);
75static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
76static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
77
78void callback(ENTITY *);
79
80static void control_rc(PLCI *, byte, byte, byte, byte, byte);
81static void data_rc(PLCI *, byte);
82static void data_ack(PLCI *, byte);
83static void sig_ind(PLCI *);
84static void SendInfo(PLCI *, dword, byte **, byte);
85static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
86static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
87
88static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
89
90static void nl_ind(PLCI *);
91
92static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
93static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
94static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
95static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
96static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
97static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
98static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
99static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
100static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
101static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
102static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
103static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
104static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
105static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
106static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
107static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116
117static word get_plci(DIVA_CAPI_ADAPTER *);
118static void add_p(PLCI *, byte, byte *);
119static void add_s(PLCI *plci, byte code, API_PARSE *p);
120static void add_ss(PLCI *plci, byte code, API_PARSE *p);
121static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
122static void add_d(PLCI *, word, byte *);
123static void add_ai(PLCI *, API_PARSE *);
124static word add_b1(PLCI *, API_PARSE *, word, word);
125static word add_b23(PLCI *, API_PARSE *);
126static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
127static void sig_req(PLCI *, byte, byte);
128static void nl_req_ncci(PLCI *, byte, byte);
129static void send_req(PLCI *);
130static void send_data(PLCI *);
131static word plci_remove_check(PLCI *);
132static void listen_check(DIVA_CAPI_ADAPTER *);
133static byte AddInfo(byte **, byte **, byte *, byte *);
134static byte getChannel(API_PARSE *);
135static void IndParse(PLCI *, const word *, byte **, byte);
136static byte ie_compare(byte *, byte *);
137static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
138static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
139
140
141
142
143static void channel_flow_control_remove(PLCI *plci);
144static void channel_x_off(PLCI *plci, byte ch, byte flag);
145static void channel_x_on(PLCI *plci, byte ch);
146static void channel_request_xon(PLCI *plci, byte ch);
147static void channel_xmit_xon(PLCI *plci);
148static int channel_can_xon(PLCI *plci, byte ch);
149static void channel_xmit_extended_xon(PLCI *plci);
150
151static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
152static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
153static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
154static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
155static void VoiceChannelOff(PLCI *plci);
156static void adv_voice_write_coefs(PLCI *plci, word write_command);
157static void adv_voice_clear_config(PLCI *plci);
158
159static word get_b1_facilities(PLCI *plci, byte b1_resource);
160static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
161static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
162static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
163static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
164static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
165static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
166static void select_b_command(dword Id, PLCI *plci, byte Rc);
167static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
168static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
169static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
170static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
171static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
172static void hold_save_command(dword Id, PLCI *plci, byte Rc);
173static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
174static void init_b1_config(PLCI *plci);
175static void clear_b1_config(PLCI *plci);
176
177static void dtmf_command(dword Id, PLCI *plci, byte Rc);
178static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
179static void dtmf_confirmation(dword Id, PLCI *plci);
180static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
181static void dtmf_parameter_write(PLCI *plci);
182
183
184static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
185static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
186static void mixer_clear_config(PLCI *plci);
187static void mixer_notify_update(PLCI *plci, byte others);
188static void mixer_command(dword Id, PLCI *plci, byte Rc);
189static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
190static void mixer_indication_coefs_set(dword Id, PLCI *plci);
191static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
192static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
193static void mixer_remove(PLCI *plci);
194
195
196static void ec_command(dword Id, PLCI *plci, byte Rc);
197static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
198static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
199
200
201static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
202static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
203
204
205static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
206static void diva_free_dma_descriptor(PLCI *plci, int nr);
207
208
209
210
211
212extern byte MapController(byte);
213extern byte UnMapController(byte);
214#define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
215#define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
216
217void sendf(APPL *, word, dword, word, byte *, ...);
218void *TransmitBufferSet(APPL *appl, dword ref);
219void *TransmitBufferGet(APPL *appl, void *p);
220void TransmitBufferFree(APPL *appl, void *p);
221void *ReceiveBufferGet(APPL *appl, int Num);
222
223int fax_head_line_time(char *buffer);
224
225
226
227
228
229extern byte max_adapter;
230extern byte max_appl;
231extern DIVA_CAPI_ADAPTER *adapter;
232extern APPL *application;
233
234
235
236
237
238
239
240static byte remove_started = false;
241static PLCI dummy_plci;
242
243
244static struct _ftable {
245 word command;
246 byte *format;
247 byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
248} ftable[] = {
249 {_DATA_B3_R, "dwww", data_b3_req},
250 {_DATA_B3_I | RESPONSE, "w", data_b3_res},
251 {_INFO_R, "ss", info_req},
252 {_INFO_I | RESPONSE, "", info_res},
253 {_CONNECT_R, "wsssssssss", connect_req},
254 {_CONNECT_I | RESPONSE, "wsssss", connect_res},
255 {_CONNECT_ACTIVE_I | RESPONSE, "", connect_a_res},
256 {_DISCONNECT_R, "s", disconnect_req},
257 {_DISCONNECT_I | RESPONSE, "", disconnect_res},
258 {_LISTEN_R, "dddss", listen_req},
259 {_ALERT_R, "s", alert_req},
260 {_FACILITY_R, "ws", facility_req},
261 {_FACILITY_I | RESPONSE, "ws", facility_res},
262 {_CONNECT_B3_R, "s", connect_b3_req},
263 {_CONNECT_B3_I | RESPONSE, "ws", connect_b3_res},
264 {_CONNECT_B3_ACTIVE_I | RESPONSE, "", connect_b3_a_res},
265 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
266 {_DISCONNECT_B3_I | RESPONSE, "", disconnect_b3_res},
267 {_RESET_B3_R, "s", reset_b3_req},
268 {_RESET_B3_I | RESPONSE, "", reset_b3_res},
269 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws", connect_b3_t90_a_res},
270 {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "", connect_b3_t90_a_res},
271 {_SELECT_B_REQ, "s", select_b_req},
272 {_MANUFACTURER_R, "dws", manufacturer_req},
273 {_MANUFACTURER_I | RESPONSE, "dws", manufacturer_res},
274 {_MANUFACTURER_I | RESPONSE, "", manufacturer_res}
275};
276
277static byte *cip_bc[29][2] = {
278 { "", "" },
279 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" },
280 { "\x02\x88\x90", "\x02\x88\x90" },
281 { "\x02\x89\x90", "\x02\x89\x90" },
282 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" },
283 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" },
284 { "\x02\x98\x90", "\x02\x98\x90" },
285 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" },
286 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" },
287 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" },
288 { "", "" },
289 { "", "" },
290 { "", "" },
291 { "", "" },
292 { "", "" },
293 { "", "" },
294
295 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" },
296 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" },
297 { "\x02\x88\x90", "\x02\x88\x90" },
298 { "\x02\x88\x90", "\x02\x88\x90" },
299 { "\x02\x88\x90", "\x02\x88\x90" },
300 { "\x02\x88\x90", "\x02\x88\x90" },
301 { "\x02\x88\x90", "\x02\x88\x90" },
302 { "\x02\x88\x90", "\x02\x88\x90" },
303 { "\x02\x88\x90", "\x02\x88\x90" },
304 { "\x02\x88\x90", "\x02\x88\x90" },
305 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" },
306 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" },
307 { "\x02\x88\x90", "\x02\x88\x90" }
308};
309
310static byte *cip_hlc[29] = {
311 "",
312 "",
313 "",
314 "",
315 "",
316 "",
317 "",
318 "",
319 "",
320 "",
321 "",
322 "",
323 "",
324 "",
325 "",
326 "",
327
328 "\x02\x91\x81",
329 "\x02\x91\x84",
330 "\x02\x91\xa1",
331 "\x02\x91\xa4",
332 "\x02\x91\xa8",
333 "\x02\x91\xb1",
334 "\x02\x91\xb2",
335 "\x02\x91\xb5",
336 "\x02\x91\xb8",
337 "\x02\x91\xc1",
338 "\x02\x91\x81",
339 "\x03\x91\xe0\x01",
340 "\x03\x91\xe0\x02"
341};
342
343
344
345#define V120_HEADER_LENGTH 1
346#define V120_HEADER_EXTEND_BIT 0x80
347#define V120_HEADER_BREAK_BIT 0x40
348#define V120_HEADER_C1_BIT 0x04
349#define V120_HEADER_C2_BIT 0x08
350#define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
351
352static byte v120_default_header[] =
353{
354
355 0x83
356
357};
358
359static byte v120_break_header[] =
360{
361
362 0xc3 | V120_HEADER_BREAK_BIT
363
364};
365
366
367
368
369
370
371word api_put(APPL *appl, CAPI_MSG *msg)
372{
373 word i, j, k, l, n;
374 word ret;
375 byte c;
376 byte controller;
377 DIVA_CAPI_ADAPTER *a;
378 PLCI *plci;
379 NCCI *ncci_ptr;
380 word ncci;
381 CAPI_MSG *m;
382 API_PARSE msg_parms[MAX_MSG_PARMS + 1];
383
384 if (msg->header.length < sizeof(msg->header) ||
385 msg->header.length > MAX_MSG_SIZE) {
386 dbug(1, dprintf("bad len"));
387 return _BAD_MSG;
388 }
389
390 controller = (byte)((msg->header.controller & 0x7f) - 1);
391
392
393 if (controller >= max_adapter)
394 {
395 dbug(1, dprintf("invalid ctrl"));
396 return _BAD_MSG;
397 }
398
399 a = &adapter[controller];
400 plci = NULL;
401 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
402 {
403 dbug(1, dprintf("plci=%x", msg->header.plci));
404 plci = &a->plci[msg->header.plci - 1];
405 ncci = GET_WORD(&msg->header.ncci);
406 if (plci->Id
407 && (plci->appl
408 || (plci->State == INC_CON_PENDING)
409 || (plci->State == INC_CON_ALERT)
410 || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
411 && ((ncci == 0)
412 || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
413 || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
414 {
415 i = plci->msg_in_read_pos;
416 j = plci->msg_in_write_pos;
417 if (j >= i)
418 {
419 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
420 i += MSG_IN_QUEUE_SIZE - j;
421 else
422 j = 0;
423 }
424 else
425 {
426
427 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
428
429 if (i > MSG_IN_QUEUE_SIZE - n)
430 i = MSG_IN_QUEUE_SIZE - n + 1;
431 i -= j;
432 }
433
434 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
435
436 {
437 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
438 msg->header.length, plci->msg_in_write_pos,
439 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
440
441 return _QUEUE_FULL;
442 }
443 c = false;
444 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
445 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
446 {
447 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
448 c = true;
449 }
450 if (msg->header.command == _DATA_B3_R)
451 {
452 if (msg->header.length < 20)
453 {
454 dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
455 return _BAD_MSG;
456 }
457 ncci_ptr = &(a->ncci[ncci]);
458 n = ncci_ptr->data_pending;
459 l = ncci_ptr->data_ack_pending;
460 k = plci->msg_in_read_pos;
461 while (k != plci->msg_in_write_pos)
462 {
463 if (k == plci->msg_in_wrap_pos)
464 k = 0;
465 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
466 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
467 {
468 n++;
469 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
470 l++;
471 }
472
473 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
474 MSG_IN_OVERHEAD + 3) & 0xfffc;
475
476 }
477 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
478 {
479 dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
480 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
481
482 return _QUEUE_FULL;
483 }
484 if (plci->req_in || plci->internal_command)
485 {
486 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
487 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
488 {
489 dbug(0, dprintf("Q-FULL3(requeue)"));
490
491 return _QUEUE_FULL;
492 }
493 c = true;
494 }
495 }
496 else
497 {
498 if (plci->req_in || plci->internal_command)
499 c = true;
500 else
501 {
502 plci->command = msg->header.command;
503 plci->number = msg->header.number;
504 }
505 }
506 if (c)
507 {
508 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
509 msg->header.command, plci->req_in, plci->internal_command,
510 msg->header.length, plci->msg_in_write_pos,
511 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
512 if (j == 0)
513 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
514 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
515 for (i = 0; i < msg->header.length; i++)
516 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
517 if (m->header.command == _DATA_B3_R)
518 {
519
520 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
521
522 }
523
524 j = (j + 3) & 0xfffc;
525
526 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
527 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
528 return 0;
529 }
530 }
531 else
532 {
533 plci = NULL;
534 }
535 }
536 dbug(1, dprintf("com=%x", msg->header.command));
537
538 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
539 for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
540
541 if (ftable[i].command == msg->header.command) {
542
543
544 if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
545 ret = 0;
546 break;
547 }
548 for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
549 }
550 }
551 if (ret) {
552 dbug(1, dprintf("BAD_MSG"));
553 if (plci) plci->command = 0;
554 return ret;
555 }
556
557
558 c = ftable[i].function(GET_DWORD(&msg->header.controller),
559 msg->header.number,
560 a,
561 plci,
562 appl,
563 msg_parms);
564
565 channel_xmit_extended_xon(plci);
566
567 if (c == 1) send_req(plci);
568 if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
569 if (plci && !plci->req_in) plci->command = 0;
570 return 0;
571}
572
573
574
575
576
577
578static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
579{
580 word i;
581 word p;
582
583 for (i = 0, p = 0; format[i]; i++) {
584 if (parms)
585 {
586 parms[i].info = &msg[p];
587 }
588 switch (format[i]) {
589 case 'b':
590 p += 1;
591 break;
592 case 'w':
593 p += 2;
594 break;
595 case 'd':
596 p += 4;
597 break;
598 case 's':
599 if (msg[p] == 0xff) {
600 parms[i].info += 2;
601 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
602 p += (parms[i].length + 3);
603 }
604 else {
605 parms[i].length = msg[p];
606 p += (parms[i].length + 1);
607 }
608 break;
609 }
610
611 if (p > length) return true;
612 }
613 if (parms) parms[i].info = NULL;
614 return false;
615}
616
617static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
618{
619 word i, j, n = 0;
620 byte *p;
621
622 p = out->info;
623 for (i = 0; format[i] != '\0'; i++)
624 {
625 out->parms[i].info = p;
626 out->parms[i].length = in[i].length;
627 switch (format[i])
628 {
629 case 'b':
630 n = 1;
631 break;
632 case 'w':
633 n = 2;
634 break;
635 case 'd':
636 n = 4;
637 break;
638 case 's':
639 n = in[i].length + 1;
640 break;
641 }
642 for (j = 0; j < n; j++)
643 *(p++) = in[i].info[j];
644 }
645 out->parms[i].info = NULL;
646 out->parms[i].length = 0;
647}
648
649static void api_load_msg(API_SAVE *in, API_PARSE *out)
650{
651 word i;
652
653 i = 0;
654 do
655 {
656 out[i].info = in->parms[i].info;
657 out[i].length = in->parms[i].length;
658 } while (in->parms[i++].info);
659}
660
661
662
663
664
665
666word api_remove_start(void)
667{
668 word i;
669 word j;
670
671 if (!remove_started) {
672 remove_started = true;
673 for (i = 0; i < max_adapter; i++) {
674 if (adapter[i].request) {
675 for (j = 0; j < adapter[i].max_plci; j++) {
676 if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
677 }
678 }
679 }
680 return 1;
681 }
682 else {
683 for (i = 0; i < max_adapter; i++) {
684 if (adapter[i].request) {
685 for (j = 0; j < adapter[i].max_plci; j++) {
686 if (adapter[i].plci[j].Sig.Id) return 1;
687 }
688 }
689 }
690 }
691 api_remove_complete();
692 return 0;
693}
694
695
696
697
698
699
700static void init_internal_command_queue(PLCI *plci)
701{
702 word i;
703
704 dbug(1, dprintf("%s,%d: init_internal_command_queue",
705 (char *)(FILE_), __LINE__));
706
707 plci->internal_command = 0;
708 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
709 plci->internal_command_queue[i] = NULL;
710}
711
712
713static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
714{
715 word i;
716
717 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
718 UnMapId(Id), (char *)(FILE_), __LINE__));
719
720 if (plci->internal_command == 0)
721 {
722 plci->internal_command_queue[0] = command_function;
723 (*command_function)(Id, plci, OK);
724 }
725 else
726 {
727 i = 1;
728 while (plci->internal_command_queue[i] != NULL)
729 i++;
730 plci->internal_command_queue[i] = command_function;
731 }
732}
733
734
735static void next_internal_command(dword Id, PLCI *plci)
736{
737 word i;
738
739 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
740 UnMapId(Id), (char *)(FILE_), __LINE__));
741
742 plci->internal_command = 0;
743 plci->internal_command_queue[0] = NULL;
744 while (plci->internal_command_queue[1] != NULL)
745 {
746 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
747 plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
748 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
749 (*(plci->internal_command_queue[0]))(Id, plci, OK);
750 if (plci->internal_command != 0)
751 return;
752 plci->internal_command_queue[0] = NULL;
753 }
754}
755
756
757
758
759
760
761static dword ncci_mapping_bug = 0;
762
763static word get_ncci(PLCI *plci, byte ch, word force_ncci)
764{
765 DIVA_CAPI_ADAPTER *a;
766 word ncci, i, j, k;
767
768 a = plci->adapter;
769 if (!ch || a->ch_ncci[ch])
770 {
771 ncci_mapping_bug++;
772 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
773 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
774 ncci = ch;
775 }
776 else
777 {
778 if (force_ncci)
779 ncci = force_ncci;
780 else
781 {
782 if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
783 ncci = ch;
784 else
785 {
786 ncci = 1;
787 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
788 ncci++;
789 if (ncci == MAX_NCCI + 1)
790 {
791 ncci_mapping_bug++;
792 i = 1;
793 do
794 {
795 j = 1;
796 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
797 j++;
798 k = j;
799 if (j < MAX_NCCI + 1)
800 {
801 do
802 {
803 j++;
804 } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
805 }
806 } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
807 if (i < MAX_NL_CHANNEL + 1)
808 {
809 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
810 ncci_mapping_bug, ch, force_ncci, i, k, j));
811 }
812 else
813 {
814 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
815 ncci_mapping_bug, ch, force_ncci));
816 }
817 ncci = ch;
818 }
819 }
820 a->ncci_plci[ncci] = plci->Id;
821 a->ncci_state[ncci] = IDLE;
822 if (!plci->ncci_ring_list)
823 plci->ncci_ring_list = ncci;
824 else
825 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
826 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
827 }
828 a->ncci_ch[ncci] = ch;
829 a->ch_ncci[ch] = (byte) ncci;
830 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
831 ncci_mapping_bug, ch, force_ncci, ch, ncci));
832 }
833 return (ncci);
834}
835
836
837static void ncci_free_receive_buffers(PLCI *plci, word ncci)
838{
839 DIVA_CAPI_ADAPTER *a;
840 APPL *appl;
841 word i, ncci_code;
842 dword Id;
843
844 a = plci->adapter;
845 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
846 if (ncci)
847 {
848 if (a->ncci_plci[ncci] == plci->Id)
849 {
850 if (!plci->appl)
851 {
852 ncci_mapping_bug++;
853 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
854 ncci_mapping_bug, Id));
855 }
856 else
857 {
858 appl = plci->appl;
859 ncci_code = ncci | (((word) a->Id) << 8);
860 for (i = 0; i < appl->MaxBuffer; i++)
861 {
862 if ((appl->DataNCCI[i] == ncci_code)
863 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
864 {
865 appl->DataNCCI[i] = 0;
866 }
867 }
868 }
869 }
870 }
871 else
872 {
873 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
874 {
875 if (a->ncci_plci[ncci] == plci->Id)
876 {
877 if (!plci->appl)
878 {
879 ncci_mapping_bug++;
880 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
881 ncci_mapping_bug, Id));
882 }
883 else
884 {
885 appl = plci->appl;
886 ncci_code = ncci | (((word) a->Id) << 8);
887 for (i = 0; i < appl->MaxBuffer; i++)
888 {
889 if ((appl->DataNCCI[i] == ncci_code)
890 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
891 {
892 appl->DataNCCI[i] = 0;
893 }
894 }
895 }
896 }
897 }
898 }
899}
900
901
902static void cleanup_ncci_data(PLCI *plci, word ncci)
903{
904 NCCI *ncci_ptr;
905
906 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
907 {
908 ncci_ptr = &(plci->adapter->ncci[ncci]);
909 if (plci->appl)
910 {
911 while (ncci_ptr->data_pending != 0)
912 {
913 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
914 TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
915 (ncci_ptr->data_out)++;
916 if (ncci_ptr->data_out == MAX_DATA_B3)
917 ncci_ptr->data_out = 0;
918 (ncci_ptr->data_pending)--;
919 }
920 }
921 ncci_ptr->data_out = 0;
922 ncci_ptr->data_pending = 0;
923 ncci_ptr->data_ack_out = 0;
924 ncci_ptr->data_ack_pending = 0;
925 }
926}
927
928
929static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
930{
931 DIVA_CAPI_ADAPTER *a;
932 dword Id;
933 word i;
934
935 a = plci->adapter;
936 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
937 if (!preserve_ncci)
938 ncci_free_receive_buffers(plci, ncci);
939 if (ncci)
940 {
941 if (a->ncci_plci[ncci] != plci->Id)
942 {
943 ncci_mapping_bug++;
944 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
945 ncci_mapping_bug, Id, preserve_ncci));
946 }
947 else
948 {
949 cleanup_ncci_data(plci, ncci);
950 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
951 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
952 a->ch_ncci[a->ncci_ch[ncci]] = 0;
953 if (!preserve_ncci)
954 {
955 a->ncci_ch[ncci] = 0;
956 a->ncci_plci[ncci] = 0;
957 a->ncci_state[ncci] = IDLE;
958 i = plci->ncci_ring_list;
959 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
960 i = a->ncci_next[i];
961 if ((i != 0) && (a->ncci_next[i] == ncci))
962 {
963 if (i == ncci)
964 plci->ncci_ring_list = 0;
965 else if (plci->ncci_ring_list == ncci)
966 plci->ncci_ring_list = i;
967 a->ncci_next[i] = a->ncci_next[ncci];
968 }
969 a->ncci_next[ncci] = 0;
970 }
971 }
972 }
973 else
974 {
975 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
976 {
977 if (a->ncci_plci[ncci] == plci->Id)
978 {
979 cleanup_ncci_data(plci, ncci);
980 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
981 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
982 a->ch_ncci[a->ncci_ch[ncci]] = 0;
983 if (!preserve_ncci)
984 {
985 a->ncci_ch[ncci] = 0;
986 a->ncci_plci[ncci] = 0;
987 a->ncci_state[ncci] = IDLE;
988 a->ncci_next[ncci] = 0;
989 }
990 }
991 }
992 if (!preserve_ncci)
993 plci->ncci_ring_list = 0;
994 }
995}
996
997
998
999
1000
1001
1002static void plci_free_msg_in_queue(PLCI *plci)
1003{
1004 word i;
1005
1006 if (plci->appl)
1007 {
1008 i = plci->msg_in_read_pos;
1009 while (i != plci->msg_in_write_pos)
1010 {
1011 if (i == plci->msg_in_wrap_pos)
1012 i = 0;
1013 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1014 {
1015
1016 TransmitBufferFree(plci->appl,
1017 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1018
1019 }
1020
1021 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1022 MSG_IN_OVERHEAD + 3) & 0xfffc;
1023
1024 }
1025 }
1026 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1027 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1028 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1029}
1030
1031
1032static void plci_remove(PLCI *plci)
1033{
1034
1035 if (!plci) {
1036 dbug(1, dprintf("plci_remove(no plci)"));
1037 return;
1038 }
1039 init_internal_command_queue(plci);
1040 dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1041 if (plci_remove_check(plci))
1042 {
1043 return;
1044 }
1045 if (plci->Sig.Id == 0xff)
1046 {
1047 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1048 if (plci->NL.Id && !plci->nl_remove_id)
1049 {
1050 nl_req_ncci(plci, REMOVE, 0);
1051 send_req(plci);
1052 }
1053 }
1054 else
1055 {
1056 if (!plci->sig_remove_id
1057 && (plci->Sig.Id
1058 || (plci->req_in != plci->req_out)
1059 || (plci->nl_req || plci->sig_req)))
1060 {
1061 sig_req(plci, HANGUP, 0);
1062 send_req(plci);
1063 }
1064 }
1065 ncci_remove(plci, 0, false);
1066 plci_free_msg_in_queue(plci);
1067
1068 plci->channels = 0;
1069 plci->appl = NULL;
1070 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1071 plci->State = OUTG_DIS_PENDING;
1072}
1073
1074
1075
1076
1077
1078static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1079 PLCI *plci, APPL *appl, API_PARSE *parms)
1080{
1081 word ch;
1082 word i;
1083 word Info;
1084 byte LinkLayer;
1085 API_PARSE *ai;
1086 API_PARSE *bp;
1087 API_PARSE ai_parms[5];
1088 word channel = 0;
1089 dword ch_mask;
1090 byte m;
1091 static byte esc_chi[35] = {0x02, 0x18, 0x01};
1092 static byte lli[2] = {0x01, 0x00};
1093 byte noCh = 0;
1094 word dir = 0;
1095 byte *p_chi = "";
1096
1097 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1098
1099 dbug(1, dprintf("connect_req(%d)", parms->length));
1100 Info = _WRONG_IDENTIFIER;
1101 if (a)
1102 {
1103 if (a->adapter_disabled)
1104 {
1105 dbug(1, dprintf("adapter disabled"));
1106 Id = ((word)1 << 8) | a->Id;
1107 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1108 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1109 return false;
1110 }
1111 Info = _OUT_OF_PLCI;
1112 if ((i = get_plci(a)))
1113 {
1114 Info = 0;
1115 plci = &a->plci[i - 1];
1116 plci->appl = appl;
1117 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1118
1119 if (Id & EXT_CONTROLLER)
1120 {
1121 if (AdvCodecSupport(a, plci, appl, 0))
1122 {
1123 plci->Id = 0;
1124 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1125 return 2;
1126 }
1127 }
1128 ai = &parms[9];
1129 bp = &parms[5];
1130 ch = 0;
1131 if (bp->length)LinkLayer = bp->info[3];
1132 else LinkLayer = 0;
1133 if (ai->length)
1134 {
1135 ch = 0xffff;
1136 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1137 {
1138 ch = 0;
1139 if (ai_parms[0].length)
1140 {
1141 ch = GET_WORD(ai_parms[0].info + 1);
1142 if (ch > 4) ch = 0;
1143 if (ch == 4)
1144 {
1145
1146 if ((ai_parms[0].info)[3] >= 1)
1147 {
1148 if ((ai_parms[0].info)[4] == CHI)
1149 {
1150 p_chi = &((ai_parms[0].info)[5]);
1151 }
1152 else
1153 {
1154 p_chi = &((ai_parms[0].info)[3]);
1155 }
1156 if (p_chi[0] > 35)
1157 {
1158 Info = _WRONG_MESSAGE_FORMAT;
1159 }
1160 }
1161 else Info = _WRONG_MESSAGE_FORMAT;
1162 }
1163
1164 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1165 {
1166 dir = GET_WORD(ai_parms[0].info + 3);
1167 ch_mask = 0;
1168 m = 0x3f;
1169 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1170 {
1171 if (ai_parms[0].info[i + 5] != 0)
1172 {
1173 if ((ai_parms[0].info[i + 5] | m) != 0xff)
1174 Info = _WRONG_MESSAGE_FORMAT;
1175 else
1176 {
1177 if (ch_mask == 0)
1178 channel = i;
1179 ch_mask |= 1L << i;
1180 }
1181 }
1182 m = 0;
1183 }
1184 if (ch_mask == 0)
1185 Info = _WRONG_MESSAGE_FORMAT;
1186 if (!Info)
1187 {
1188 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1189 {
1190 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1191 for (i = 0; i + 5 <= ai_parms[0].length; i++)
1192 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1193 }
1194 else
1195 esc_chi[0] = 2;
1196 esc_chi[2] = (byte)channel;
1197 plci->b_channel = (byte)channel;
1198 add_p(plci, LLI, lli);
1199 add_p(plci, ESC, esc_chi);
1200 plci->State = LOCAL_CONNECT;
1201 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
1202 }
1203 }
1204 }
1205 }
1206 else Info = _WRONG_MESSAGE_FORMAT;
1207 }
1208
1209 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1210 plci->command = _CONNECT_R;
1211 plci->number = Number;
1212
1213 if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1214 if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1215 {
1216
1217
1218 if (noCh) Info = add_b1(plci, &parms[5], 2, 0);
1219 else Info = add_b1(plci, &parms[5], ch, 0);
1220 add_s(plci, OAD, &parms[2]);
1221 add_s(plci, OSA, &parms[4]);
1222 add_s(plci, BC, &parms[6]);
1223 add_s(plci, LLC, &parms[7]);
1224 add_s(plci, HLC, &parms[8]);
1225 if (a->Info_Mask[appl->Id - 1] & 0x200)
1226 {
1227
1228 add_p(plci, LLI, "\x01\x01");
1229 }
1230 if (GET_WORD(parms[0].info) < 29) {
1231 add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1232 add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1233 }
1234 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1235 sig_req(plci, ASSIGN, DSIG_ID);
1236 }
1237 else if (ch == 1) {
1238
1239
1240 plci->Sig.Id = 0xff;
1241 Info = 0;
1242 }
1243
1244 if (!Info && ch != 2 && !noCh) {
1245 Info = add_b23(plci, &parms[5]);
1246 if (!Info) {
1247 if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1248 }
1249 }
1250
1251 if (!Info)
1252 {
1253 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1254 {
1255 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1256 {
1257 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1258 plci->spoofed_msg = CALL_REQ;
1259 plci->internal_command = BLOCK_PLCI;
1260 plci->command = 0;
1261 dbug(1, dprintf("Spoof"));
1262 send_req(plci);
1263 return false;
1264 }
1265 if (ch == 4)add_p(plci, CHI, p_chi);
1266 add_s(plci, CPN, &parms[1]);
1267 add_s(plci, DSA, &parms[3]);
1268 if (noCh) add_p(plci, ESC, "\x02\x18\xfd");
1269 add_ai(plci, &parms[9]);
1270 if (!dir)sig_req(plci, CALL_REQ, 0);
1271 else
1272 {
1273 plci->command = PERM_LIST_REQ;
1274 plci->appl = appl;
1275 sig_req(plci, LISTEN_REQ, 0);
1276 send_req(plci);
1277 return false;
1278 }
1279 }
1280 send_req(plci);
1281 return false;
1282 }
1283 plci->Id = 0;
1284 }
1285 }
1286 sendf(appl,
1287 _CONNECT_R | CONFIRM,
1288 Id,
1289 Number,
1290 "w", Info);
1291 return 2;
1292}
1293
1294static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1295 PLCI *plci, APPL *appl, API_PARSE *parms)
1296{
1297 word i, Info;
1298 word Reject;
1299 static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1300 static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1301 API_PARSE *ai;
1302 API_PARSE ai_parms[5];
1303 word ch = 0;
1304
1305 if (!plci) {
1306 dbug(1, dprintf("connect_res(no plci)"));
1307 return 0;
1308 }
1309
1310 dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1311 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1312 ai = &parms[5];
1313 dbug(1, dprintf("ai->length=%d", ai->length));
1314
1315 if (ai->length)
1316 {
1317 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1318 {
1319 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1320 ch = 0;
1321 if (ai_parms[0].length)
1322 {
1323 ch = GET_WORD(ai_parms[0].info + 1);
1324 dbug(1, dprintf("BCH-I=0x%x", ch));
1325 }
1326 }
1327 }
1328
1329 if (plci->State == INC_CON_CONNECTED_ALERT)
1330 {
1331 dbug(1, dprintf("Connected Alert Call_Res"));
1332 if (a->Info_Mask[appl->Id - 1] & 0x200)
1333 {
1334
1335 add_p(plci, LLI, "\x01\x01");
1336 }
1337 add_s(plci, CONN_NR, &parms[2]);
1338 add_s(plci, LLC, &parms[4]);
1339 add_ai(plci, &parms[5]);
1340 plci->State = INC_CON_ACCEPT;
1341 sig_req(plci, CALL_RES, 0);
1342 return 1;
1343 }
1344 else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1345 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1346 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
1347 Reject = GET_WORD(parms[0].info);
1348 dbug(1, dprintf("Reject=0x%x", Reject));
1349 if (Reject)
1350 {
1351 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
1352 {
1353 if ((Reject & 0xff00) == 0x3400)
1354 {
1355 esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1356 add_p(plci, ESC, esc_t);
1357 add_ai(plci, &parms[5]);
1358 sig_req(plci, REJECT, 0);
1359 }
1360 else if (Reject == 1 || Reject >= 9)
1361 {
1362 add_ai(plci, &parms[5]);
1363 sig_req(plci, HANGUP, 0);
1364 }
1365 else
1366 {
1367 esc_t[2] = cau_t[(Reject&0x000f)];
1368 add_p(plci, ESC, esc_t);
1369 add_ai(plci, &parms[5]);
1370 sig_req(plci, REJECT, 0);
1371 }
1372 plci->appl = appl;
1373 }
1374 else
1375 {
1376 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1377 }
1378 }
1379 else {
1380 plci->appl = appl;
1381 if (Id & EXT_CONTROLLER) {
1382 if (AdvCodecSupport(a, plci, appl, 0)) {
1383 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1384 sig_req(plci, HANGUP, 0);
1385 return 1;
1386 }
1387 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1388 {
1389 Info = add_b23(plci, &parms[1]);
1390 if (Info)
1391 {
1392 dbug(1, dprintf("connect_res(error from add_b23)"));
1393 sig_req(plci, HANGUP, 0);
1394 return 1;
1395 }
1396 if (plci->adv_nl)
1397 {
1398 nl_req_ncci(plci, ASSIGN, 0);
1399 }
1400 }
1401 }
1402 else
1403 {
1404 plci->tel = 0;
1405 if (ch != 2)
1406 {
1407 Info = add_b23(plci, &parms[1]);
1408 if (Info)
1409 {
1410 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1411 sig_req(plci, HANGUP, 0);
1412 return 1;
1413 }
1414 }
1415 nl_req_ncci(plci, ASSIGN, 0);
1416 }
1417
1418 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1419 {
1420 api_save_msg(parms, "wsssss", &plci->saved_msg);
1421 plci->spoofed_msg = CALL_RES;
1422 plci->internal_command = BLOCK_PLCI;
1423 plci->command = 0;
1424 dbug(1, dprintf("Spoof"));
1425 }
1426 else
1427 {
1428 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1429 if (a->Info_Mask[appl->Id - 1] & 0x200)
1430 {
1431
1432 add_p(plci, LLI, "\x01\x01");
1433 }
1434 add_s(plci, CONN_NR, &parms[2]);
1435 add_s(plci, LLC, &parms[4]);
1436 add_ai(plci, &parms[5]);
1437 plci->State = INC_CON_ACCEPT;
1438 sig_req(plci, CALL_RES, 0);
1439 }
1440
1441 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1442 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1443 }
1444 }
1445 return 1;
1446}
1447
1448static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1449 PLCI *plci, APPL *appl, API_PARSE *msg)
1450{
1451 dbug(1, dprintf("connect_a_res"));
1452 return false;
1453}
1454
1455static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1456 PLCI *plci, APPL *appl, API_PARSE *msg)
1457{
1458 word Info;
1459 word i;
1460
1461 dbug(1, dprintf("disconnect_req"));
1462
1463 Info = _WRONG_IDENTIFIER;
1464
1465 if (plci)
1466 {
1467 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1468 {
1469 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1470 plci->appl = appl;
1471 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1472 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1473 plci->State = OUTG_DIS_PENDING;
1474 }
1475 if (plci->Sig.Id && plci->appl)
1476 {
1477 Info = 0;
1478 if (plci->Sig.Id != 0xff)
1479 {
1480 if (plci->State != INC_DIS_PENDING)
1481 {
1482 add_ai(plci, &msg[0]);
1483 sig_req(plci, HANGUP, 0);
1484 plci->State = OUTG_DIS_PENDING;
1485 return 1;
1486 }
1487 }
1488 else
1489 {
1490 if (plci->NL.Id && !plci->nl_remove_id)
1491 {
1492 mixer_remove(plci);
1493 nl_req_ncci(plci, REMOVE, 0);
1494 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1496 plci->State = INC_DIS_PENDING;
1497 }
1498 return 1;
1499 }
1500 }
1501 }
1502
1503 if (!appl) return false;
1504 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1505 return false;
1506}
1507
1508static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1509 PLCI *plci, APPL *appl, API_PARSE *msg)
1510{
1511 dbug(1, dprintf("disconnect_res"));
1512 if (plci)
1513 {
1514
1515
1516 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1517 ncci_free_receive_buffers(plci, 0);
1518 if (plci_remove_check(plci))
1519 {
1520 return 0;
1521 }
1522 if (plci->State == INC_DIS_PENDING
1523 || plci->State == SUSPENDING) {
1524 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
1525 if (plci->State != SUSPENDING) plci->State = IDLE;
1526 dbug(1, dprintf("chs=%d", plci->channels));
1527 if (!plci->channels) {
1528 plci_remove(plci);
1529 }
1530 }
1531 }
1532 }
1533 return 0;
1534}
1535
1536static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1537 PLCI *plci, APPL *appl, API_PARSE *parms)
1538{
1539 word Info;
1540 byte i;
1541
1542 dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1543
1544 Info = _WRONG_IDENTIFIER;
1545 if (a) {
1546 Info = 0;
1547 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1548 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1549 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1550 if (a->Info_Mask[appl->Id - 1] & 0x200) {
1551 a->Info_Mask[appl->Id - 1] |= 0x10;
1552 }
1553
1554
1555 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1556 if (a->profile.Global_Options & ON_BOARD_CODEC) {
1557 dummy_plci.State = IDLE;
1558 a->codec_listen[appl->Id - 1] = &dummy_plci;
1559 a->TelOAD[0] = (byte)(parms[3].length);
1560 for (i = 1; parms[3].length >= i && i < 22; i++) {
1561 a->TelOAD[i] = parms[3].info[i];
1562 }
1563 a->TelOAD[i] = 0;
1564 a->TelOSA[0] = (byte)(parms[4].length);
1565 for (i = 1; parms[4].length >= i && i < 22; i++) {
1566 a->TelOSA[i] = parms[4].info[i];
1567 }
1568 a->TelOSA[i] = 0;
1569 }
1570 else Info = 0x2002;
1571 }
1572 else{
1573 a->codec_listen[appl->Id - 1] = (PLCI *)0;
1574 }
1575 }
1576 sendf(appl,
1577 _LISTEN_R | CONFIRM,
1578 Id,
1579 Number,
1580 "w", Info);
1581
1582 if (a) listen_check(a);
1583 return false;
1584}
1585
1586static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1587 PLCI *plci, APPL *appl, API_PARSE *msg)
1588{
1589 word i;
1590 API_PARSE *ai;
1591 PLCI *rc_plci = NULL;
1592 API_PARSE ai_parms[5];
1593 word Info = 0;
1594
1595 dbug(1, dprintf("info_req"));
1596 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1597
1598 ai = &msg[1];
1599
1600 if (ai->length)
1601 {
1602 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1603 {
1604 dbug(1, dprintf("AddInfo wrong"));
1605 Info = _WRONG_MESSAGE_FORMAT;
1606 }
1607 }
1608 if (!a) Info = _WRONG_STATE;
1609
1610 if (!Info && plci)
1611 {
1612 rc_plci = plci;
1613 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1614 {
1615
1616 dbug(1, dprintf("OvlSnd"));
1617 add_s(plci, CPN, &msg[0]);
1618 add_s(plci, KEY, &ai_parms[1]);
1619 sig_req(plci, INFO_REQ, 0);
1620 send_req(plci);
1621 return false;
1622 }
1623
1624 if (plci->State && ai_parms[2].length)
1625 {
1626
1627 dbug(1, dprintf("UUI"));
1628 add_s(plci, UUI, &ai_parms[2]);
1629 sig_req(plci, USER_DATA, 0);
1630 }
1631 else if (plci->State && ai_parms[3].length)
1632 {
1633
1634 dbug(1, dprintf("FAC"));
1635 add_s(plci, CPN, &msg[0]);
1636 add_ai(plci, &msg[1]);
1637 sig_req(plci, FACILITY_REQ, 0);
1638 }
1639 else
1640 {
1641 Info = _WRONG_STATE;
1642 }
1643 }
1644 else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1645 {
1646
1647 dbug(1, dprintf("NCR_FAC"));
1648 if ((i = get_plci(a)))
1649 {
1650 rc_plci = &a->plci[i - 1];
1651 appl->NullCREnable = true;
1652 rc_plci->internal_command = C_NCR_FAC_REQ;
1653 rc_plci->appl = appl;
1654 add_p(rc_plci, CAI, "\x01\x80");
1655 add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1656 sig_req(rc_plci, ASSIGN, DSIG_ID);
1657 send_req(rc_plci);
1658 }
1659 else
1660 {
1661 Info = _OUT_OF_PLCI;
1662 }
1663
1664 if (!Info)
1665 {
1666 add_s(rc_plci, CPN, &msg[0]);
1667 add_ai(rc_plci, &msg[1]);
1668 sig_req(rc_plci, NCR_FACILITY, 0);
1669 send_req(rc_plci);
1670 return false;
1671
1672 }
1673 }
1674
1675 if (!rc_plci)
1676 {
1677 Info = _WRONG_MESSAGE_FORMAT;
1678 }
1679
1680 if (!Info)
1681 {
1682 send_req(rc_plci);
1683 }
1684 else
1685 {
1686 dbug(1, dprintf("localInfoCon"));
1687 sendf(appl,
1688 _INFO_R | CONFIRM,
1689 Id,
1690 Number,
1691 "w", Info);
1692 }
1693 return false;
1694}
1695
1696static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1697 PLCI *plci, APPL *appl, API_PARSE *msg)
1698{
1699 dbug(1, dprintf("info_res"));
1700 return false;
1701}
1702
1703static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1704 PLCI *plci, APPL *appl, API_PARSE *msg)
1705{
1706 word Info;
1707 byte ret;
1708
1709 dbug(1, dprintf("alert_req"));
1710
1711 Info = _WRONG_IDENTIFIER;
1712 ret = false;
1713 if (plci) {
1714 Info = _ALERT_IGNORED;
1715 if (plci->State != INC_CON_ALERT) {
1716 Info = _WRONG_STATE;
1717 if (plci->State == INC_CON_PENDING) {
1718 Info = 0;
1719 plci->State = INC_CON_ALERT;
1720 add_ai(plci, &msg[0]);
1721 sig_req(plci, CALL_ALERT, 0);
1722 ret = 1;
1723 }
1724 }
1725 }
1726 sendf(appl,
1727 _ALERT_R | CONFIRM,
1728 Id,
1729 Number,
1730 "w", Info);
1731 return ret;
1732}
1733
1734static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1735 PLCI *plci, APPL *appl, API_PARSE *msg)
1736{
1737 word Info = 0;
1738 word i = 0;
1739
1740 word selector;
1741 word SSreq;
1742 long relatedPLCIvalue;
1743 DIVA_CAPI_ADAPTER *relatedadapter;
1744 byte *SSparms = "";
1745 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1746 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1747 API_PARSE *parms;
1748 API_PARSE ss_parms[11];
1749 PLCI *rplci;
1750 byte cai[15];
1751 dword d;
1752 API_PARSE dummy;
1753
1754 dbug(1, dprintf("facility_req"));
1755 for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1756
1757 parms = &msg[1];
1758
1759 if (!a)
1760 {
1761 dbug(1, dprintf("wrong Ctrl"));
1762 Info = _WRONG_IDENTIFIER;
1763 }
1764
1765 selector = GET_WORD(msg[0].info);
1766
1767 if (!Info)
1768 {
1769 switch (selector)
1770 {
1771 case SELECTOR_HANDSET:
1772 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1773 break;
1774
1775 case SELECTOR_SU_SERV:
1776 if (!msg[1].length)
1777 {
1778 Info = _WRONG_MESSAGE_FORMAT;
1779 break;
1780 }
1781 SSreq = GET_WORD(&(msg[1].info[1]));
1782 PUT_WORD(&RCparms[1], SSreq);
1783 SSparms = RCparms;
1784 switch (SSreq)
1785 {
1786 case S_GET_SUPPORTED_SERVICES:
1787 if ((i = get_plci(a)))
1788 {
1789 rplci = &a->plci[i - 1];
1790 rplci->appl = appl;
1791 add_p(rplci, CAI, "\x01\x80");
1792 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1793 sig_req(rplci, ASSIGN, DSIG_ID);
1794 send_req(rplci);
1795 }
1796 else
1797 {
1798 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1799 SSparms = (byte *)SSstruct;
1800 break;
1801 }
1802 rplci->internal_command = GETSERV_REQ_PEND;
1803 rplci->number = Number;
1804 rplci->appl = appl;
1805 sig_req(rplci, S_SUPPORTED, 0);
1806 send_req(rplci);
1807 return false;
1808 break;
1809
1810 case S_LISTEN:
1811 if (parms->length == 7)
1812 {
1813 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1814 {
1815 dbug(1, dprintf("format wrong"));
1816 Info = _WRONG_MESSAGE_FORMAT;
1817 break;
1818 }
1819 }
1820 else
1821 {
1822 Info = _WRONG_MESSAGE_FORMAT;
1823 break;
1824 }
1825 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1826 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI)
1827 {
1828 if ((i = get_plci(a)))
1829 {
1830 rplci = &a->plci[i - 1];
1831 rplci->appl = appl;
1832 add_p(rplci, CAI, "\x01\x80");
1833 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1834 sig_req(rplci, ASSIGN, DSIG_ID);
1835 send_req(rplci);
1836 }
1837 else
1838 {
1839 break;
1840 }
1841 rplci->internal_command = GET_MWI_STATE;
1842 rplci->number = Number;
1843 sig_req(rplci, MWI_POLL, 0);
1844 send_req(rplci);
1845 }
1846 break;
1847
1848 case S_HOLD:
1849 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1850 if (plci && plci->State && plci->SuppState == IDLE)
1851 {
1852 plci->SuppState = HOLD_REQUEST;
1853 plci->command = C_HOLD_REQ;
1854 add_s(plci, CAI, &ss_parms[1]);
1855 sig_req(plci, CALL_HOLD, 0);
1856 send_req(plci);
1857 return false;
1858 }
1859 else Info = 0x3010;
1860 break;
1861 case S_RETRIEVE:
1862 if (plci && plci->State && plci->SuppState == CALL_HELD)
1863 {
1864 if (Id & EXT_CONTROLLER)
1865 {
1866 if (AdvCodecSupport(a, plci, appl, 0))
1867 {
1868 Info = 0x3010;
1869 break;
1870 }
1871 }
1872 else plci->tel = 0;
1873
1874 plci->SuppState = RETRIEVE_REQUEST;
1875 plci->command = C_RETRIEVE_REQ;
1876 if (plci->spoofed_msg == SPOOFING_REQUIRED)
1877 {
1878 plci->spoofed_msg = CALL_RETRIEVE;
1879 plci->internal_command = BLOCK_PLCI;
1880 plci->command = 0;
1881 dbug(1, dprintf("Spoof"));
1882 return false;
1883 }
1884 else
1885 {
1886 sig_req(plci, CALL_RETRIEVE, 0);
1887 send_req(plci);
1888 return false;
1889 }
1890 }
1891 else Info = 0x3010;
1892 break;
1893 case S_SUSPEND:
1894 if (parms->length)
1895 {
1896 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1897 {
1898 dbug(1, dprintf("format wrong"));
1899 Info = _WRONG_MESSAGE_FORMAT;
1900 break;
1901 }
1902 }
1903 if (plci && plci->State)
1904 {
1905 add_s(plci, CAI, &ss_parms[2]);
1906 plci->command = SUSPEND_REQ;
1907 sig_req(plci, SUSPEND, 0);
1908 plci->State = SUSPENDING;
1909 send_req(plci);
1910 }
1911 else Info = 0x3010;
1912 break;
1913
1914 case S_RESUME:
1915 if (!(i = get_plci(a)))
1916 {
1917 Info = _OUT_OF_PLCI;
1918 break;
1919 }
1920 rplci = &a->plci[i - 1];
1921 rplci->appl = appl;
1922 rplci->number = Number;
1923 rplci->tel = 0;
1924 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1925
1926 if (Id & EXT_CONTROLLER)
1927 {
1928 if (AdvCodecSupport(a, rplci, appl, 0))
1929 {
1930 rplci->Id = 0;
1931 Info = 0x300A;
1932 break;
1933 }
1934 }
1935 if (parms->length)
1936 {
1937 if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1938 {
1939 dbug(1, dprintf("format wrong"));
1940 rplci->Id = 0;
1941 Info = _WRONG_MESSAGE_FORMAT;
1942 break;
1943 }
1944 }
1945 dummy.length = 0;
1946 dummy.info = "\x00";
1947 add_b1(rplci, &dummy, 0, 0);
1948 if (a->Info_Mask[appl->Id - 1] & 0x200)
1949 {
1950
1951 add_p(rplci, LLI, "\x01\x01");
1952 }
1953 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1954 sig_req(rplci, ASSIGN, DSIG_ID);
1955 send_req(rplci);
1956 add_s(rplci, CAI, &ss_parms[2]);
1957 rplci->command = RESUME_REQ;
1958 sig_req(rplci, RESUME, 0);
1959 rplci->State = RESUMING;
1960 send_req(rplci);
1961 break;
1962
1963 case S_CONF_BEGIN:
1964 case S_CONF_DROP:
1965 case S_CONF_ISOLATE:
1966 case S_CONF_REATTACH:
1967 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1968 {
1969 dbug(1, dprintf("format wrong"));
1970 Info = _WRONG_MESSAGE_FORMAT;
1971 break;
1972 }
1973 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
1974 {
1975 d = GET_DWORD(ss_parms[2].info);
1976 if (d >= 0x80)
1977 {
1978 dbug(1, dprintf("format wrong"));
1979 Info = _WRONG_MESSAGE_FORMAT;
1980 break;
1981 }
1982 plci->ptyState = (byte)SSreq;
1983 plci->command = 0;
1984 cai[0] = 2;
1985 switch (SSreq)
1986 {
1987 case S_CONF_BEGIN:
1988 cai[1] = CONF_BEGIN;
1989 plci->internal_command = CONF_BEGIN_REQ_PEND;
1990 break;
1991 case S_CONF_DROP:
1992 cai[1] = CONF_DROP;
1993 plci->internal_command = CONF_DROP_REQ_PEND;
1994 break;
1995 case S_CONF_ISOLATE:
1996 cai[1] = CONF_ISOLATE;
1997 plci->internal_command = CONF_ISOLATE_REQ_PEND;
1998 break;
1999 case S_CONF_REATTACH:
2000 cai[1] = CONF_REATTACH;
2001 plci->internal_command = CONF_REATTACH_REQ_PEND;
2002 break;
2003 }
2004 cai[2] = (byte)d;
2005 add_p(plci, CAI, cai);
2006 sig_req(plci, S_SERVICE, 0);
2007 send_req(plci);
2008 return false;
2009 }
2010 else Info = 0x3010;
2011 break;
2012
2013 case S_ECT:
2014 case S_3PTY_BEGIN:
2015 case S_3PTY_END:
2016 case S_CONF_ADD:
2017 if (parms->length == 7)
2018 {
2019 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2020 {
2021 dbug(1, dprintf("format wrong"));
2022 Info = _WRONG_MESSAGE_FORMAT;
2023 break;
2024 }
2025 }
2026 else if (parms->length == 8)
2027 {
2028 if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2029 {
2030 dbug(1, dprintf("format wrong"));
2031 Info = _WRONG_MESSAGE_FORMAT;
2032 break;
2033 }
2034 }
2035 else
2036 {
2037 Info = _WRONG_MESSAGE_FORMAT;
2038 break;
2039 }
2040 if (!msg[1].length)
2041 {
2042 Info = _WRONG_MESSAGE_FORMAT;
2043 break;
2044 }
2045 if (!plci)
2046 {
2047 Info = _WRONG_IDENTIFIER;
2048 break;
2049 }
2050 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2051 relatedPLCIvalue &= 0x0000FFFF;
2052 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2053
2054 if (((relatedPLCIvalue & 0x7f) == 0)
2055 || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2056 || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2057 {
2058 if (SSreq == S_3PTY_END)
2059 {
2060 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2061 rplci = plci;
2062 }
2063 else
2064 {
2065 Info = 0x3010;
2066 break;
2067 }
2068 }
2069 else
2070 {
2071 relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2072 relatedPLCIvalue >>= 8;
2073
2074 for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2075 {
2076 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2077 {
2078 rplci = &relatedadapter->plci[i];
2079 }
2080 }
2081 if (!rplci || !relatedPLCIvalue)
2082 {
2083 if (SSreq == S_3PTY_END)
2084 {
2085 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2086 rplci = plci;
2087 }
2088 else
2089 {
2090 Info = 0x3010;
2091 break;
2092 }
2093 }
2094 }
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106 if (!rplci->internal_command && rplci->appl)
2107 {
2108 plci->command = 0;
2109 rplci->relatedPTYPLCI = plci;
2110 plci->relatedPTYPLCI = rplci;
2111 rplci->ptyState = (byte)SSreq;
2112 if (SSreq == S_ECT)
2113 {
2114 rplci->internal_command = ECT_REQ_PEND;
2115 cai[1] = ECT_EXECUTE;
2116
2117 rplci->vswitchstate = 0;
2118 rplci->vsprot = 0;
2119 rplci->vsprotdialect = 0;
2120 plci->vswitchstate = 0;
2121 plci->vsprot = 0;
2122 plci->vsprotdialect = 0;
2123
2124 }
2125 else if (SSreq == S_CONF_ADD)
2126 {
2127 rplci->internal_command = CONF_ADD_REQ_PEND;
2128 cai[1] = CONF_ADD;
2129 }
2130 else
2131 {
2132 rplci->internal_command = PTY_REQ_PEND;
2133 cai[1] = (byte)(SSreq - 3);
2134 }
2135 rplci->number = Number;
2136 if (plci != rplci)
2137 {
2138 cai[0] = 2;
2139 cai[2] = plci->Sig.Id;
2140 dbug(1, dprintf("explicit invocation"));
2141 }
2142 else
2143 {
2144 dbug(1, dprintf("implicit invocation"));
2145 cai[0] = 1;
2146 }
2147 add_p(rplci, CAI, cai);
2148 sig_req(rplci, S_SERVICE, 0);
2149 send_req(rplci);
2150 return false;
2151 }
2152 else
2153 {
2154 dbug(0, dprintf("Wrong line"));
2155 Info = 0x3010;
2156 break;
2157 }
2158 break;
2159
2160 case S_CALL_DEFLECTION:
2161 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2162 {
2163 dbug(1, dprintf("format wrong"));
2164 Info = _WRONG_MESSAGE_FORMAT;
2165 break;
2166 }
2167 if (!plci)
2168 {
2169 Info = _WRONG_IDENTIFIER;
2170 break;
2171 }
2172
2173 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2174 plci->command = 0;
2175 plci->internal_command = CD_REQ_PEND;
2176 appl->CDEnable = true;
2177 cai[0] = 1;
2178 cai[1] = CALL_DEFLECTION;
2179 add_p(plci, CAI, cai);
2180 add_p(plci, CPN, ss_parms[3].info);
2181 sig_req(plci, S_SERVICE, 0);
2182 send_req(plci);
2183 return false;
2184 break;
2185
2186 case S_CALL_FORWARDING_START:
2187 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2188 {
2189 dbug(1, dprintf("format wrong"));
2190 Info = _WRONG_MESSAGE_FORMAT;
2191 break;
2192 }
2193
2194 if ((i = get_plci(a)))
2195 {
2196 rplci = &a->plci[i - 1];
2197 rplci->appl = appl;
2198 add_p(rplci, CAI, "\x01\x80");
2199 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2200 sig_req(rplci, ASSIGN, DSIG_ID);
2201 send_req(rplci);
2202 }
2203 else
2204 {
2205 Info = _OUT_OF_PLCI;
2206 break;
2207 }
2208
2209
2210 rplci->internal_command = CF_START_PEND;
2211 rplci->appl = appl;
2212 rplci->number = Number;
2213 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2214 cai[0] = 2;
2215 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0]));
2216 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0]));
2217 add_p(rplci, CAI, cai);
2218 add_p(rplci, OAD, ss_parms[5].info);
2219 add_p(rplci, CPN, ss_parms[6].info);
2220 sig_req(rplci, S_SERVICE, 0);
2221 send_req(rplci);
2222 return false;
2223 break;
2224
2225 case S_INTERROGATE_DIVERSION:
2226 case S_INTERROGATE_NUMBERS:
2227 case S_CALL_FORWARDING_STOP:
2228 case S_CCBS_REQUEST:
2229 case S_CCBS_DEACTIVATE:
2230 case S_CCBS_INTERROGATE:
2231 switch (SSreq)
2232 {
2233 case S_INTERROGATE_NUMBERS:
2234 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2235 {
2236 dbug(0, dprintf("format wrong"));
2237 Info = _WRONG_MESSAGE_FORMAT;
2238 }
2239 break;
2240 case S_CCBS_REQUEST:
2241 case S_CCBS_DEACTIVATE:
2242 if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2243 {
2244 dbug(0, dprintf("format wrong"));
2245 Info = _WRONG_MESSAGE_FORMAT;
2246 }
2247 break;
2248 case S_CCBS_INTERROGATE:
2249 if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2250 {
2251 dbug(0, dprintf("format wrong"));
2252 Info = _WRONG_MESSAGE_FORMAT;
2253 }
2254 break;
2255 default:
2256 if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2257 {
2258 dbug(0, dprintf("format wrong"));
2259 Info = _WRONG_MESSAGE_FORMAT;
2260 break;
2261 }
2262 break;
2263 }
2264
2265 if (Info) break;
2266 if ((i = get_plci(a)))
2267 {
2268 rplci = &a->plci[i - 1];
2269 switch (SSreq)
2270 {
2271 case S_INTERROGATE_DIVERSION:
2272 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0]));
2273 rplci->internal_command = INTERR_DIVERSION_REQ_PEND;
2274 break;
2275 case S_INTERROGATE_NUMBERS:
2276 cai[1] = DIVERSION_INTERROGATE_NUM;
2277 rplci->internal_command = INTERR_NUMBERS_REQ_PEND;
2278 break;
2279 case S_CALL_FORWARDING_STOP:
2280 rplci->internal_command = CF_STOP_PEND;
2281 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0]));
2282 break;
2283 case S_CCBS_REQUEST:
2284 cai[1] = CCBS_REQUEST;
2285 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2286 break;
2287 case S_CCBS_DEACTIVATE:
2288 cai[1] = CCBS_DEACTIVATE;
2289 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2290 break;
2291 case S_CCBS_INTERROGATE:
2292 cai[1] = CCBS_INTERROGATE;
2293 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2294 break;
2295 default:
2296 cai[1] = 0;
2297 break;
2298 }
2299 rplci->appl = appl;
2300 rplci->number = Number;
2301 add_p(rplci, CAI, "\x01\x80");
2302 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2303 sig_req(rplci, ASSIGN, DSIG_ID);
2304 send_req(rplci);
2305 }
2306 else
2307 {
2308 Info = _OUT_OF_PLCI;
2309 break;
2310 }
2311
2312 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2313 switch (SSreq)
2314 {
2315 case S_INTERROGATE_NUMBERS:
2316 cai[0] = 1;
2317 add_p(rplci, CAI, cai);
2318 break;
2319 case S_CCBS_REQUEST:
2320 case S_CCBS_DEACTIVATE:
2321 cai[0] = 3;
2322 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2323 add_p(rplci, CAI, cai);
2324 break;
2325 case S_CCBS_INTERROGATE:
2326 cai[0] = 3;
2327 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2328 add_p(rplci, CAI, cai);
2329 add_p(rplci, OAD, ss_parms[4].info);
2330 break;
2331 default:
2332 cai[0] = 2;
2333 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0]));
2334 add_p(rplci, CAI, cai);
2335 add_p(rplci, OAD, ss_parms[5].info);
2336 break;
2337 }
2338
2339 sig_req(rplci, S_SERVICE, 0);
2340 send_req(rplci);
2341 return false;
2342 break;
2343
2344 case S_MWI_ACTIVATE:
2345 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2346 {
2347 dbug(1, dprintf("format wrong"));
2348 Info = _WRONG_MESSAGE_FORMAT;
2349 break;
2350 }
2351 if (!plci)
2352 {
2353 if ((i = get_plci(a)))
2354 {
2355 rplci = &a->plci[i - 1];
2356 rplci->appl = appl;
2357 rplci->cr_enquiry = true;
2358 add_p(rplci, CAI, "\x01\x80");
2359 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2360 sig_req(rplci, ASSIGN, DSIG_ID);
2361 send_req(rplci);
2362 }
2363 else
2364 {
2365 Info = _OUT_OF_PLCI;
2366 break;
2367 }
2368 }
2369 else
2370 {
2371 rplci = plci;
2372 rplci->cr_enquiry = false;
2373 }
2374
2375 rplci->command = 0;
2376 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2377 rplci->appl = appl;
2378 rplci->number = Number;
2379
2380 cai[0] = 13;
2381 cai[1] = ACTIVATION_MWI;
2382 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0])));
2383 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0])));
2384 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0])));
2385 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0])));
2386 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0])));
2387 add_p(rplci, CAI, cai);
2388 add_p(rplci, CPN, ss_parms[7].info);
2389 add_p(rplci, OAD, ss_parms[8].info);
2390 add_p(rplci, OSA, ss_parms[9].info);
2391 add_p(rplci, UID, ss_parms[10].info);
2392 sig_req(rplci, S_SERVICE, 0);
2393 send_req(rplci);
2394 return false;
2395
2396 case S_MWI_DEACTIVATE:
2397 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2398 {
2399 dbug(1, dprintf("format wrong"));
2400 Info = _WRONG_MESSAGE_FORMAT;
2401 break;
2402 }
2403 if (!plci)
2404 {
2405 if ((i = get_plci(a)))
2406 {
2407 rplci = &a->plci[i - 1];
2408 rplci->appl = appl;
2409 rplci->cr_enquiry = true;
2410 add_p(rplci, CAI, "\x01\x80");
2411 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2412 sig_req(rplci, ASSIGN, DSIG_ID);
2413 send_req(rplci);
2414 }
2415 else
2416 {
2417 Info = _OUT_OF_PLCI;
2418 break;
2419 }
2420 }
2421 else
2422 {
2423 rplci = plci;
2424 rplci->cr_enquiry = false;
2425 }
2426
2427 rplci->command = 0;
2428 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2429 rplci->appl = appl;
2430 rplci->number = Number;
2431
2432 cai[0] = 5;
2433 cai[1] = DEACTIVATION_MWI;
2434 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0])));
2435 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0])));
2436 add_p(rplci, CAI, cai);
2437 add_p(rplci, CPN, ss_parms[4].info);
2438 add_p(rplci, OAD, ss_parms[5].info);
2439 sig_req(rplci, S_SERVICE, 0);
2440 send_req(rplci);
2441 return false;
2442
2443 default:
2444 Info = 0x300E;
2445 break;
2446 }
2447 break;
2448
2449
2450 case SELECTOR_DTMF:
2451 return (dtmf_request(Id, Number, a, plci, appl, msg));
2452
2453
2454
2455 case SELECTOR_LINE_INTERCONNECT:
2456 return (mixer_request(Id, Number, a, plci, appl, msg));
2457
2458
2459
2460 case PRIV_SELECTOR_ECHO_CANCELLER:
2461 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2462 return (ec_request(Id, Number, a, plci, appl, msg));
2463
2464 case SELECTOR_ECHO_CANCELLER:
2465 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2466 return (ec_request(Id, Number, a, plci, appl, msg));
2467
2468
2469 case SELECTOR_V42BIS:
2470 default:
2471 Info = _FACILITY_NOT_SUPPORTED;
2472 break;
2473 }
2474 }
2475
2476 dbug(1, dprintf("SendFacRc"));
2477 sendf(appl,
2478 _FACILITY_R | CONFIRM,
2479 Id,
2480 Number,
2481 "wws", Info, selector, SSparms);
2482 return false;
2483}
2484
2485static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2486 PLCI *plci, APPL *appl, API_PARSE *msg)
2487{
2488 dbug(1, dprintf("facility_res"));
2489 return false;
2490}
2491
2492static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2493 PLCI *plci, APPL *appl, API_PARSE *parms)
2494{
2495 word Info = 0;
2496 byte req;
2497 byte len;
2498 word w;
2499 word fax_control_bits, fax_feature_bits, fax_info_change;
2500 API_PARSE *ncpi;
2501 byte pvc[2];
2502
2503 API_PARSE fax_parms[9];
2504 word i;
2505
2506
2507 dbug(1, dprintf("connect_b3_req"));
2508 if (plci)
2509 {
2510 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2511 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2512 {
2513 Info = _WRONG_STATE;
2514 }
2515 else
2516 {
2517
2518
2519
2520
2521
2522 if (!plci->NL.Id
2523 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2524 && ((plci->channels != 0)
2525 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2526 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2527 {
2528 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2529 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2530 Info = _WRONG_STATE;
2531 sendf(appl,
2532 _CONNECT_B3_R | CONFIRM,
2533 Id,
2534 Number,
2535 "w", Info);
2536 return false;
2537 }
2538 plci->requested_options_conn = 0;
2539
2540 req = N_CONNECT;
2541 ncpi = &parms[0];
2542 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2543 {
2544 if (ncpi->length > 2)
2545 {
2546
2547 if (ncpi->info[2] || ncpi->info[3])
2548 {
2549 pvc[0] = ncpi->info[3];
2550 pvc[1] = ncpi->info[2];
2551 add_d(plci, 2, pvc);
2552 req = N_RESET;
2553 }
2554 else
2555 {
2556 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2557 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2558 }
2559 }
2560 }
2561 else if (plci->B3_prot == 5)
2562 {
2563 if (plci->NL.Id && !plci->nl_remove_id)
2564 {
2565 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2566 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2567 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2568 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2569 {
2570 len = offsetof(T30_INFO, universal_6);
2571 fax_info_change = false;
2572 if (ncpi->length >= 4)
2573 {
2574 w = GET_WORD(&ncpi->info[3]);
2575 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2576 {
2577 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2578 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2579 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2580 fax_info_change = true;
2581 }
2582 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2583 if (w & 0x0002)
2584 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2585 if ((w & 0x0004)
2586 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2587 {
2588 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2589 }
2590 if (ncpi->length >= 6)
2591 {
2592 w = GET_WORD(&ncpi->info[5]);
2593 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2594 {
2595 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2596 fax_info_change = true;
2597 }
2598
2599 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2600 && (GET_WORD(&ncpi->info[5]) & 0x8000))
2601 {
2602 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2603 }
2604 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2605 && (GET_WORD(&ncpi->info[5]) & 0x4000))
2606 {
2607 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2608 }
2609 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2610 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2611 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2612 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2613 {
2614 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2615 Info = _WRONG_MESSAGE_FORMAT;
2616 else
2617 {
2618 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2619 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2620 {
2621 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2622 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2623 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2624 }
2625 w = fax_parms[4].length;
2626 if (w > 20)
2627 w = 20;
2628 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2629 for (i = 0; i < w; i++)
2630 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2631 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2632 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2633 w = fax_parms[5].length;
2634 if (w > 20)
2635 w = 20;
2636 plci->fax_connect_info_buffer[len++] = (byte) w;
2637 for (i = 0; i < w; i++)
2638 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2639 w = fax_parms[6].length;
2640 if (w > 20)
2641 w = 20;
2642 plci->fax_connect_info_buffer[len++] = (byte) w;
2643 for (i = 0; i < w; i++)
2644 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2645 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2646 & (1L << PRIVATE_FAX_NONSTANDARD))
2647 {
2648 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2649 {
2650 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2651 plci->fax_connect_info_buffer[len++] = 0;
2652 }
2653 else
2654 {
2655 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2656 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2657 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2658 for (i = 0; i < fax_parms[7].length; i++)
2659 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2660 }
2661 }
2662 }
2663 }
2664 else
2665 {
2666 len = offsetof(T30_INFO, universal_6);
2667 }
2668 fax_info_change = true;
2669
2670 }
2671 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2672 {
2673 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2674 fax_info_change = true;
2675 }
2676 }
2677 if (Info == GOOD)
2678 {
2679 plci->fax_connect_info_length = len;
2680 if (fax_info_change)
2681 {
2682 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2683 {
2684 start_internal_command(Id, plci, fax_connect_info_command);
2685 return false;
2686 }
2687 else
2688 {
2689 start_internal_command(Id, plci, fax_adjust_b23_command);
2690 return false;
2691 }
2692 }
2693 }
2694 }
2695 else Info = _WRONG_STATE;
2696 }
2697 else Info = _WRONG_STATE;
2698 }
2699
2700 else if (plci->B3_prot == B3_RTP)
2701 {
2702 plci->internal_req_buffer[0] = ncpi->length + 1;
2703 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2704 for (w = 0; w < ncpi->length; w++)
2705 plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2706 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2707 return false;
2708 }
2709
2710 if (!Info)
2711 {
2712 nl_req_ncci(plci, req, 0);
2713 return 1;
2714 }
2715 }
2716 }
2717 else Info = _WRONG_IDENTIFIER;
2718
2719 sendf(appl,
2720 _CONNECT_B3_R | CONFIRM,
2721 Id,
2722 Number,
2723 "w", Info);
2724 return false;
2725}
2726
2727static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2728 PLCI *plci, APPL *appl, API_PARSE *parms)
2729{
2730 word ncci;
2731 API_PARSE *ncpi;
2732 byte req;
2733
2734 word w;
2735
2736
2737 API_PARSE fax_parms[9];
2738 word i;
2739 byte len;
2740
2741
2742 dbug(1, dprintf("connect_b3_res"));
2743
2744 ncci = (word)(Id >> 16);
2745 if (plci && ncci) {
2746 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2747 if (GET_WORD(&parms[0].info[0]) != 0)
2748 {
2749 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2750 channel_request_xon(plci, a->ncci_ch[ncci]);
2751 channel_xmit_xon(plci);
2752 cleanup_ncci_data(plci, ncci);
2753 nl_req_ncci(plci, N_DISC, (byte)ncci);
2754 return 1;
2755 }
2756 a->ncci_state[ncci] = INC_ACT_PENDING;
2757
2758 req = N_CONNECT_ACK;
2759 ncpi = &parms[1];
2760 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2761 {
2762
2763 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2764 & (1L << PRIVATE_FAX_NONSTANDARD))
2765 {
2766 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2767 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2768 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2769 {
2770 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2771 if (plci->fax_connect_info_length < len)
2772 {
2773 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2774 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2775 }
2776 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2777 {
2778 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2779 }
2780 else
2781 {
2782 if (plci->fax_connect_info_length <= len)
2783 plci->fax_connect_info_buffer[len] = 0;
2784 len += 1 + plci->fax_connect_info_buffer[len];
2785 if (plci->fax_connect_info_length <= len)
2786 plci->fax_connect_info_buffer[len] = 0;
2787 len += 1 + plci->fax_connect_info_buffer[len];
2788 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2789 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2790 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2791 for (i = 0; i < fax_parms[7].length; i++)
2792 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2793 }
2794 plci->fax_connect_info_length = len;
2795 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2796 start_internal_command(Id, plci, fax_connect_ack_command);
2797 return false;
2798 }
2799 }
2800
2801 nl_req_ncci(plci, req, (byte)ncci);
2802 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2803 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2804 {
2805 if (plci->B3_prot == 4)
2806 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2807 else
2808 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2809 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2810 }
2811 }
2812
2813 else if (plci->B3_prot == B3_RTP)
2814 {
2815 plci->internal_req_buffer[0] = ncpi->length + 1;
2816 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2817 for (w = 0; w < ncpi->length; w++)
2818 plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2819 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2820 return false;
2821 }
2822
2823 else
2824 {
2825 if (ncpi->length > 2) {
2826 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2827 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2828 }
2829 nl_req_ncci(plci, req, (byte)ncci);
2830 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2831 if (plci->adjust_b_restore)
2832 {
2833 plci->adjust_b_restore = false;
2834 start_internal_command(Id, plci, adjust_b_restore);
2835 }
2836 }
2837 return 1;
2838 }
2839 }
2840 return false;
2841}
2842
2843static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2844 PLCI *plci, APPL *appl, API_PARSE *parms)
2845{
2846 word ncci;
2847
2848 ncci = (word)(Id >> 16);
2849 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2850
2851 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2852 && (plci->State != OUTG_DIS_PENDING))
2853 {
2854 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2855 a->ncci_state[ncci] = CONNECTED;
2856 if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2857 channel_request_xon(plci, a->ncci_ch[ncci]);
2858 channel_xmit_xon(plci);
2859 }
2860 }
2861 return false;
2862}
2863
2864static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2865 PLCI *plci, APPL *appl, API_PARSE *parms)
2866{
2867 word Info;
2868 word ncci;
2869 API_PARSE *ncpi;
2870
2871 dbug(1, dprintf("disconnect_b3_req"));
2872
2873 Info = _WRONG_IDENTIFIER;
2874 ncci = (word)(Id >> 16);
2875 if (plci && ncci)
2876 {
2877 Info = _WRONG_STATE;
2878 if ((a->ncci_state[ncci] == CONNECTED)
2879 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2880 || (a->ncci_state[ncci] == INC_CON_PENDING)
2881 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2882 {
2883 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2884 channel_request_xon(plci, a->ncci_ch[ncci]);
2885 channel_xmit_xon(plci);
2886
2887 if (a->ncci[ncci].data_pending
2888 && ((plci->B3_prot == B3_TRANSPARENT)
2889 || (plci->B3_prot == B3_T30)
2890 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
2891 {
2892 plci->send_disc = (byte)ncci;
2893 plci->command = 0;
2894 return false;
2895 }
2896 else
2897 {
2898 cleanup_ncci_data(plci, ncci);
2899
2900 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2901 {
2902 ncpi = &parms[0];
2903 if (ncpi->length > 3)
2904 {
2905 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
2906 }
2907 }
2908 nl_req_ncci(plci, N_DISC, (byte)ncci);
2909 }
2910 return 1;
2911 }
2912 }
2913 sendf(appl,
2914 _DISCONNECT_B3_R | CONFIRM,
2915 Id,
2916 Number,
2917 "w", Info);
2918 return false;
2919}
2920
2921static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2922 PLCI *plci, APPL *appl, API_PARSE *parms)
2923{
2924 word ncci;
2925 word i;
2926
2927 ncci = (word)(Id >> 16);
2928 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
2929 if (plci && ncci) {
2930 plci->requested_options_conn = 0;
2931 plci->fax_connect_info_length = 0;
2932 plci->ncpi_state = 0x00;
2933 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2934 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
2935 {
2936 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
2937 }
2938 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
2939 if (i < MAX_CHANNELS_PER_PLCI) {
2940 if (plci->channels)plci->channels--;
2941 for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
2942 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
2943
2944 ncci_free_receive_buffers(plci, ncci);
2945
2946 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
2947 if (plci->State == SUSPENDING) {
2948 sendf(plci->appl,
2949 _FACILITY_I,
2950 Id & 0xffffL,
2951 0,
2952 "ws", (word)3, "\x03\x04\x00\x00");
2953 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
2954 }
2955 plci_remove(plci);
2956 plci->State = IDLE;
2957 }
2958 }
2959 else
2960 {
2961 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
2962 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
2963 && (a->ncci_state[ncci] == INC_DIS_PENDING))
2964 {
2965 ncci_free_receive_buffers(plci, ncci);
2966
2967 nl_req_ncci(plci, N_EDATA, (byte)ncci);
2968
2969 plci->adapter->ncci_state[ncci] = IDLE;
2970 start_internal_command(Id, plci, fax_disconnect_command);
2971 return 1;
2972 }
2973 }
2974 }
2975 return false;
2976}
2977
2978static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2979 PLCI *plci, APPL *appl, API_PARSE *parms)
2980{
2981 NCCI *ncci_ptr;
2982 DATA_B3_DESC *data;
2983 word Info;
2984 word ncci;
2985 word i;
2986
2987 dbug(1, dprintf("data_b3_req"));
2988
2989 Info = _WRONG_IDENTIFIER;
2990 ncci = (word)(Id >> 16);
2991 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
2992
2993 if (plci && ncci)
2994 {
2995 Info = _WRONG_STATE;
2996 if ((a->ncci_state[ncci] == CONNECTED)
2997 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2998 {
2999
3000 ncci_ptr = &(a->ncci[ncci]);
3001 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3002 if (i >= MAX_DATA_B3)
3003 i -= MAX_DATA_B3;
3004 data = &(ncci_ptr->DBuffer[i]);
3005 data->Number = Number;
3006 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3007 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3008 {
3009
3010 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3011
3012 }
3013 else
3014 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3015 data->Length = GET_WORD(parms[1].info);
3016 data->Handle = GET_WORD(parms[2].info);
3017 data->Flags = GET_WORD(parms[3].info);
3018 (ncci_ptr->data_pending)++;
3019
3020
3021 if (data->Flags & 0x0004)
3022 {
3023 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3024 if (i >= MAX_DATA_ACK)
3025 i -= MAX_DATA_ACK;
3026 ncci_ptr->DataAck[i].Number = data->Number;
3027 ncci_ptr->DataAck[i].Handle = data->Handle;
3028 (ncci_ptr->data_ack_pending)++;
3029 }
3030
3031 send_data(plci);
3032 return false;
3033 }
3034 }
3035 if (appl)
3036 {
3037 if (plci)
3038 {
3039 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3040 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3041 {
3042
3043 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3044
3045 }
3046 }
3047 sendf(appl,
3048 _DATA_B3_R | CONFIRM,
3049 Id,
3050 Number,
3051 "ww", GET_WORD(parms[2].info), Info);
3052 }
3053 return false;
3054}
3055
3056static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3057 PLCI *plci, APPL *appl, API_PARSE *parms)
3058{
3059 word n;
3060 word ncci;
3061 word NCCIcode;
3062
3063 dbug(1, dprintf("data_b3_res"));
3064
3065 ncci = (word)(Id >> 16);
3066 if (plci && ncci) {
3067 n = GET_WORD(parms[0].info);
3068 dbug(1, dprintf("free(%d)", n));
3069 NCCIcode = ncci | (((word) a->Id) << 8);
3070 if (n < appl->MaxBuffer &&
3071 appl->DataNCCI[n] == NCCIcode &&
3072 (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3073 dbug(1, dprintf("found"));
3074 appl->DataNCCI[n] = 0;
3075
3076 if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3077 channel_request_xon(plci, a->ncci_ch[ncci]);
3078 }
3079 channel_xmit_xon(plci);
3080
3081 if (appl->DataFlags[n] & 4) {
3082 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3083 return 1;
3084 }
3085 }
3086 }
3087 return false;
3088}
3089
3090static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3091 PLCI *plci, APPL *appl, API_PARSE *parms)
3092{
3093 word Info;
3094 word ncci;
3095
3096 dbug(1, dprintf("reset_b3_req"));
3097
3098 Info = _WRONG_IDENTIFIER;
3099 ncci = (word)(Id >> 16);
3100 if (plci && ncci)
3101 {
3102 Info = _WRONG_STATE;
3103 switch (plci->B3_prot)
3104 {
3105 case B3_ISO8208:
3106 case B3_X25_DCE:
3107 if (a->ncci_state[ncci] == CONNECTED)
3108 {
3109 nl_req_ncci(plci, N_RESET, (byte)ncci);
3110 send_req(plci);
3111 Info = GOOD;
3112 }
3113 break;
3114 case B3_TRANSPARENT:
3115 if (a->ncci_state[ncci] == CONNECTED)
3116 {
3117 start_internal_command(Id, plci, reset_b3_command);
3118 Info = GOOD;
3119 }
3120 break;
3121 }
3122 }
3123
3124 sendf(appl,
3125 _RESET_B3_R | CONFIRM,
3126 Id,
3127 Number,
3128 "w", Info);
3129 return false;
3130}
3131
3132static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3133 PLCI *plci, APPL *appl, API_PARSE *parms)
3134{
3135 word ncci;
3136
3137 dbug(1, dprintf("reset_b3_res"));
3138
3139 ncci = (word)(Id >> 16);
3140 if (plci && ncci) {
3141 switch (plci->B3_prot)
3142 {
3143 case B3_ISO8208:
3144 case B3_X25_DCE:
3145 if (a->ncci_state[ncci] == INC_RES_PENDING)
3146 {
3147 a->ncci_state[ncci] = CONNECTED;
3148 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3149 return true;
3150 }
3151 break;
3152 }
3153 }
3154 return false;
3155}
3156
3157static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3158 PLCI *plci, APPL *appl, API_PARSE *parms)
3159{
3160 word ncci;
3161 API_PARSE *ncpi;
3162 byte req;
3163
3164 dbug(1, dprintf("connect_b3_t90_a_res"));
3165
3166 ncci = (word)(Id >> 16);
3167 if (plci && ncci) {
3168 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3169 a->ncci_state[ncci] = CONNECTED;
3170 }
3171 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3172 a->ncci_state[ncci] = CONNECTED;
3173
3174 req = N_CONNECT_ACK;
3175
3176
3177 if (parms[0].info) {
3178 ncpi = &parms[1];
3179 if (ncpi->length > 2) {
3180 if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3181 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3182 }
3183 }
3184 nl_req_ncci(plci, req, (byte)ncci);
3185 return 1;
3186 }
3187 }
3188 return false;
3189}
3190
3191
3192static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3193 PLCI *plci, APPL *appl, API_PARSE *msg)
3194{
3195 word Info = 0;
3196 word i;
3197 byte tel;
3198 API_PARSE bp_parms[7];
3199
3200 if (!plci || !msg)
3201 {
3202 Info = _WRONG_IDENTIFIER;
3203 }
3204 else
3205 {
3206 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3207 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3208 dbug(1, dprintf("PlciState=0x%x", plci->State));
3209 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3210
3211
3212 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3213 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3214 {
3215 Info = _WRONG_STATE;
3216 }
3217
3218 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3219 {
3220 Info = _WRONG_MESSAGE_FORMAT;
3221 }
3222 else
3223 {
3224 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
3225 {
3226 if (Id & EXT_CONTROLLER)
3227 {
3228 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002);
3229 return 0;
3230 }
3231 plci->State = INC_CON_CONNECTED_ALERT;
3232 plci->appl = appl;
3233 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
3234 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
3235
3236 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
3237 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3238 }
3239
3240 api_save_msg(msg, "s", &plci->saved_msg);
3241 tel = plci->tel;
3242 if (Id & EXT_CONTROLLER)
3243 {
3244 if (tel)
3245 {
3246 if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3247 {
3248 dbug(1, dprintf("Ext_Ctrl in use 1"));
3249 Info = _WRONG_STATE;
3250 }
3251 }
3252 else
3253 {
3254 if (a->AdvSignalPLCI)
3255 {
3256 dbug(1, dprintf("Ext_Ctrl in use 2"));
3257 Info = _WRONG_STATE;
3258 }
3259 else
3260 {
3261 dbug(1, dprintf("Ext_Ctrl start"));
3262 if (AdvCodecSupport(a, plci, appl, 0))
3263 {
3264 dbug(1, dprintf("Error in codec procedures"));
3265 Info = _WRONG_STATE;
3266 }
3267 else if (plci->spoofed_msg == SPOOFING_REQUIRED)
3268 {
3269 plci->spoofed_msg = AWAITING_SELECT_B;
3270 plci->internal_command = BLOCK_PLCI;
3271 plci->command = 0;
3272 dbug(1, dprintf("continue if codec loaded"));
3273 return false;
3274 }
3275 }
3276 }
3277 }
3278 else
3279 {
3280 if (tel)
3281 {
3282 if (a->AdvSignalAppl == appl)
3283 {
3284 CodecIdCheck(a, plci);
3285 plci->tel = 0;
3286 plci->adv_nl = 0;
3287 dbug(1, dprintf("Ext_Ctrl disable"));
3288 }
3289 else
3290 {
3291 dbug(1, dprintf("Ext_Ctrl not requested"));
3292 }
3293 }
3294 }
3295 if (!Info)
3296 {
3297 if (plci->call_dir & CALL_DIR_OUT)
3298 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3299 else if (plci->call_dir & CALL_DIR_IN)
3300 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3301 start_internal_command(Id, plci, select_b_command);
3302 return false;
3303 }
3304 }
3305 }
3306 sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3307 return false;
3308}
3309
3310static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3311 PLCI *plci, APPL *appl, API_PARSE *parms)
3312{
3313 word command;
3314 word i;
3315 word ncci;
3316 API_PARSE *m;
3317 API_PARSE m_parms[5];
3318 word codec;
3319 byte req;
3320 byte ch;
3321 byte dir;
3322 static byte chi[2] = {0x01, 0x00};
3323 static byte lli[2] = {0x01, 0x00};
3324 static byte codec_cai[2] = {0x01, 0x01};
3325 static byte null_msg = {0};
3326 static API_PARSE null_parms = { 0, &null_msg };
3327 PLCI *v_plci;
3328 word Info = 0;
3329
3330 dbug(1, dprintf("manufacturer_req"));
3331 for (i = 0; i < 5; i++) m_parms[i].length = 0;
3332
3333 if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3334 Info = _WRONG_MESSAGE_FORMAT;
3335 }
3336 command = GET_WORD(parms[1].info);
3337 m = &parms[2];
3338 if (!Info)
3339 {
3340 switch (command) {
3341 case _DI_ASSIGN_PLCI:
3342 if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3343 Info = _WRONG_MESSAGE_FORMAT;
3344 break;
3345 }
3346 codec = GET_WORD(m_parms[0].info);
3347 ch = m_parms[1].info[0];
3348 dir = m_parms[2].info[0];
3349 if ((i = get_plci(a))) {
3350 plci = &a->plci[i - 1];
3351 plci->appl = appl;
3352 plci->command = _MANUFACTURER_R;
3353 plci->m_command = command;
3354 plci->number = Number;
3355 plci->State = LOCAL_CONNECT;
3356 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3357 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3358
3359 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3360 chi[1] = (byte)(0x80 | ch);
3361 lli[1] = 0;
3362 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3363 switch (codec)
3364 {
3365 case 0:
3366 Info = add_b1(plci, &m_parms[3], 0, 0);
3367 break;
3368 case 1:
3369 add_p(plci, CAI, codec_cai);
3370 break;
3371
3372
3373 case 2:
3374 if (AdvCodecSupport(a, plci, appl, 0)) {
3375 Info = _RESOURCE_ERROR;
3376 }
3377 else {
3378 Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3379 lli[1] = 0x10;
3380 }
3381 break;
3382 }
3383
3384 plci->State = LOCAL_CONNECT;
3385 plci->manufacturer = true;
3386 plci->command = _MANUFACTURER_R;
3387 plci->m_command = command;
3388 plci->number = Number;
3389
3390 if (!Info)
3391 {
3392 add_p(plci, LLI, lli);
3393 add_p(plci, CHI, chi);
3394 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3395 sig_req(plci, ASSIGN, DSIG_ID);
3396
3397 if (!codec)
3398 {
3399 Info = add_b23(plci, &m_parms[3]);
3400 if (!Info)
3401 {
3402 nl_req_ncci(plci, ASSIGN, 0);
3403 send_req(plci);
3404 }
3405 }
3406 if (!Info)
3407 {
3408 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3409 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3410 {
3411 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3412 plci->spoofed_msg = AWAITING_MANUF_CON;
3413 plci->internal_command = BLOCK_PLCI;
3414 plci->command = 0;
3415 send_req(plci);
3416 return false;
3417 }
3418 if (dir == 1) {
3419 sig_req(plci, CALL_REQ, 0);
3420 }
3421 else if (!dir) {
3422 sig_req(plci, LISTEN_REQ, 0);
3423 }
3424 send_req(plci);
3425 }
3426 else
3427 {
3428 sendf(appl,
3429 _MANUFACTURER_R | CONFIRM,
3430 Id,
3431 Number,
3432 "dww", _DI_MANU_ID, command, Info);
3433 return 2;
3434 }
3435 }
3436 }
3437 }
3438 else Info = _OUT_OF_PLCI;
3439 break;
3440
3441 case _DI_IDI_CTRL:
3442 if (!plci)
3443 {
3444 Info = _WRONG_IDENTIFIER;
3445 break;
3446 }
3447 if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3448 Info = _WRONG_MESSAGE_FORMAT;
3449 break;
3450 }
3451 req = m_parms[0].info[0];
3452 plci->command = _MANUFACTURER_R;
3453 plci->m_command = command;
3454 plci->number = Number;
3455 if (req == CALL_REQ)
3456 {
3457 plci->b_channel = getChannel(&m_parms[1]);
3458 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3459 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3460 {
3461 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3462 plci->internal_command = BLOCK_PLCI;
3463 plci->command = 0;
3464 break;
3465 }
3466 }
3467 else if (req == LAW_REQ)
3468 {
3469 plci->cr_enquiry = true;
3470 }
3471 add_ss(plci, FTY, &m_parms[1]);
3472 sig_req(plci, req, 0);
3473 send_req(plci);
3474 if (req == HANGUP)
3475 {
3476 if (plci->NL.Id && !plci->nl_remove_id)
3477 {
3478 if (plci->channels)
3479 {
3480 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3481 {
3482 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3483 {
3484 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3485 cleanup_ncci_data(plci, ncci);
3486 nl_req_ncci(plci, N_DISC, (byte)ncci);
3487 }
3488 }
3489 }
3490 mixer_remove(plci);
3491 nl_req_ncci(plci, REMOVE, 0);
3492 send_req(plci);
3493 }
3494 }
3495 break;
3496
3497 case _DI_SIG_CTRL:
3498
3499 if (!plci)
3500 {
3501 Info = _WRONG_IDENTIFIER;
3502 break;
3503 }
3504 if (m->length) {
3505 plci->command = _MANUFACTURER_R;
3506 plci->number = Number;
3507 add_ss(plci, FTY, m);
3508 sig_req(plci, SIG_CTRL, 0);
3509 send_req(plci);
3510 }
3511 else Info = _WRONG_MESSAGE_FORMAT;
3512 break;
3513
3514 case _DI_RXT_CTRL:
3515
3516 if (!plci)
3517 {
3518 Info = _WRONG_IDENTIFIER;
3519 break;
3520 }
3521 if (m->length) {
3522 plci->command = _MANUFACTURER_R;
3523 plci->number = Number;
3524 add_ss(plci, FTY, m);
3525 sig_req(plci, DSP_CTRL, 0);
3526 send_req(plci);
3527 }
3528 else Info = _WRONG_MESSAGE_FORMAT;
3529 break;
3530
3531 case _DI_ADV_CODEC:
3532 case _DI_DSP_CTRL:
3533
3534
3535
3536
3537
3538 if (command == _DI_ADV_CODEC)
3539 {
3540 if (!a->AdvCodecPLCI) {
3541 Info = _WRONG_STATE;
3542 break;
3543 }
3544 v_plci = a->AdvCodecPLCI;
3545 }
3546 else
3547 {
3548 if (plci
3549 && (m->length >= 3)
3550 && (m->info[1] == 0x1c)
3551 && (m->info[2] >= 1))
3552 {
3553 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3554 {
3555 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3556 {
3557 Info = _WRONG_STATE;
3558 break;
3559 }
3560 a->adv_voice_coef_length = m->info[2] - 1;
3561 if (a->adv_voice_coef_length > m->length - 3)
3562 a->adv_voice_coef_length = (byte)(m->length - 3);
3563 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3564 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3565 for (i = 0; i < a->adv_voice_coef_length; i++)
3566 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3567 if (plci->B1_facilities & B1_FACILITY_VOICE)
3568 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3569 break;
3570 }
3571 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3572 {
3573 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3574 {
3575 Info = _FACILITY_NOT_SUPPORTED;
3576 break;
3577 }
3578
3579 plci->dtmf_parameter_length = m->info[2] - 1;
3580 if (plci->dtmf_parameter_length > m->length - 3)
3581 plci->dtmf_parameter_length = (byte)(m->length - 3);
3582 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3583 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3584 for (i = 0; i < plci->dtmf_parameter_length; i++)
3585 plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3586 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3587 dtmf_parameter_write(plci);
3588 break;
3589
3590 }
3591 }
3592 v_plci = plci;
3593 }
3594
3595 if (!v_plci)
3596 {
3597 Info = _WRONG_IDENTIFIER;
3598 break;
3599 }
3600 if (m->length) {
3601 add_ss(v_plci, FTY, m);
3602 sig_req(v_plci, TEL_CTRL, 0);
3603 send_req(v_plci);
3604 }
3605 else Info = _WRONG_MESSAGE_FORMAT;
3606
3607 break;
3608
3609 case _DI_OPTIONS_REQUEST:
3610 if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3611 Info = _WRONG_MESSAGE_FORMAT;
3612 break;
3613 }
3614 if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3615 {
3616 Info = _FACILITY_NOT_SUPPORTED;
3617 break;
3618 }
3619 a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3620 break;
3621
3622
3623
3624 default:
3625 Info = _WRONG_MESSAGE_FORMAT;
3626 break;
3627 }
3628 }
3629
3630 sendf(appl,
3631 _MANUFACTURER_R | CONFIRM,
3632 Id,
3633 Number,
3634 "dww", _DI_MANU_ID, command, Info);
3635 return false;
3636}
3637
3638
3639static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3640 PLCI *plci, APPL *appl, API_PARSE *msg)
3641{
3642 word indication;
3643
3644 API_PARSE m_parms[3];
3645 API_PARSE *ncpi;
3646 API_PARSE fax_parms[9];
3647 word i;
3648 byte len;
3649
3650
3651 dbug(1, dprintf("manufacturer_res"));
3652
3653 if ((msg[0].length == 0)
3654 || (msg[1].length == 0)
3655 || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3656 {
3657 return false;
3658 }
3659 indication = GET_WORD(msg[1].info);
3660 switch (indication)
3661 {
3662
3663 case _DI_NEGOTIATE_B3:
3664 if (!plci)
3665 break;
3666 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3667 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3668 {
3669 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3670 break;
3671 }
3672 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3673 {
3674 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3675 break;
3676 }
3677 ncpi = &m_parms[1];
3678 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3679 if (plci->fax_connect_info_length < len)
3680 {
3681 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3682 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3683 }
3684 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3685 {
3686 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3687 }
3688 else
3689 {
3690 if (plci->fax_connect_info_length <= len)
3691 plci->fax_connect_info_buffer[len] = 0;
3692 len += 1 + plci->fax_connect_info_buffer[len];
3693 if (plci->fax_connect_info_length <= len)
3694 plci->fax_connect_info_buffer[len] = 0;
3695 len += 1 + plci->fax_connect_info_buffer[len];
3696 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3697 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3698 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3699 for (i = 0; i < fax_parms[7].length; i++)
3700 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3701 }
3702 plci->fax_connect_info_length = len;
3703 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3704 start_internal_command(Id, plci, fax_edata_ack_command);
3705 break;
3706
3707 }
3708 return false;
3709}
3710
3711
3712
3713
3714
3715void callback(ENTITY *e)
3716{
3717 DIVA_CAPI_ADAPTER *a;
3718 APPL *appl;
3719 PLCI *plci;
3720 CAPI_MSG *m;
3721 word i, j;
3722 byte rc;
3723 byte ch;
3724 byte req;
3725 byte global_req;
3726 int no_cancel_rc;
3727
3728 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3729 (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3730
3731 a = &(adapter[(byte)e->user[0]]);
3732 plci = &(a->plci[e->user[1]]);
3733 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3734
3735
3736
3737
3738
3739
3740 if (((e->complete == 0xff) && no_cancel_rc) ||
3741 (e->Rc && !no_cancel_rc)) {
3742 rc = e->Rc;
3743 ch = e->RcCh;
3744 req = e->Req;
3745 e->Rc = 0;
3746
3747 if (e->user[0] & 0x8000)
3748 {
3749
3750
3751
3752
3753
3754 if (req == REMOVE)
3755 {
3756 if (e->Id)
3757 {
3758 dbug(1, dprintf("cancel RC in REMOVE state"));
3759 return;
3760 }
3761 channel_flow_control_remove(plci);
3762 for (i = 0; i < 256; i++)
3763 {
3764 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3765 a->FlowControlIdTable[i] = 0;
3766 }
3767 plci->nl_remove_id = 0;
3768 if (plci->rx_dma_descriptor > 0) {
3769 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3770 plci->rx_dma_descriptor = 0;
3771 }
3772 }
3773 if (rc == OK_FC)
3774 {
3775 a->FlowControlIdTable[ch] = e->Id;
3776 a->FlowControlSkipTable[ch] = 0;
3777
3778 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3779 a->ch_flow_plci[ch] = plci->Id;
3780 plci->nl_req = 0;
3781 }
3782 else
3783 {
3784
3785
3786
3787 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3788 a->FlowControlIdTable[ch] = 0;
3789 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3790 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3791 return;
3792 }
3793 }
3794
3795 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3796 {
3797 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3798 if (ch == e->ReqCh)
3799 plci->nl_req = 0;
3800 }
3801 else
3802 plci->nl_req = 0;
3803 }
3804 if (plci->nl_req)
3805 control_rc(plci, 0, rc, ch, 0, true);
3806 else
3807 {
3808 if (req == N_XON)
3809 {
3810 channel_x_on(plci, ch);
3811 if (plci->internal_command)
3812 control_rc(plci, req, rc, ch, 0, true);
3813 }
3814 else
3815 {
3816 if (plci->nl_global_req)
3817 {
3818 global_req = plci->nl_global_req;
3819 plci->nl_global_req = 0;
3820 if (rc != ASSIGN_OK) {
3821 e->Id = 0;
3822 if (plci->rx_dma_descriptor > 0) {
3823 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3824 plci->rx_dma_descriptor = 0;
3825 }
3826 }
3827 channel_xmit_xon(plci);
3828 control_rc(plci, 0, rc, ch, global_req, true);
3829 }
3830 else if (plci->data_sent)
3831 {
3832 channel_xmit_xon(plci);
3833 plci->data_sent = false;
3834 plci->NL.XNum = 1;
3835 data_rc(plci, ch);
3836 if (plci->internal_command)
3837 control_rc(plci, req, rc, ch, 0, true);
3838 }
3839 else
3840 {
3841 channel_xmit_xon(plci);
3842 control_rc(plci, req, rc, ch, 0, true);
3843 }
3844 }
3845 }
3846 }
3847 else
3848 {
3849
3850
3851
3852
3853
3854 if (req == REMOVE)
3855 {
3856 if (e->Id)
3857 {
3858 dbug(1, dprintf("cancel RC in REMOVE state"));
3859 return;
3860 }
3861 plci->sig_remove_id = 0;
3862 }
3863 plci->sig_req = 0;
3864 if (plci->sig_global_req)
3865 {
3866 global_req = plci->sig_global_req;
3867 plci->sig_global_req = 0;
3868 if (rc != ASSIGN_OK)
3869 e->Id = 0;
3870 channel_xmit_xon(plci);
3871 control_rc(plci, 0, rc, ch, global_req, false);
3872 }
3873 else
3874 {
3875 channel_xmit_xon(plci);
3876 control_rc(plci, req, rc, ch, 0, false);
3877 }
3878 }
3879
3880
3881
3882
3883
3884 if (no_cancel_rc) {
3885 channel_xmit_xon(plci);
3886 goto capi_callback_suffix;
3887 }
3888 }
3889
3890 channel_xmit_xon(plci);
3891
3892 if (e->Ind) {
3893 if (e->user[0] & 0x8000) {
3894 byte Ind = e->Ind & 0x0f;
3895 byte Ch = e->IndCh;
3896 if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
3897 (a->ch_flow_plci[Ch] == plci->Id)) {
3898 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
3899 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
3900 }
3901 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3902 }
3903 nl_ind(plci);
3904 if ((e->RNR != 1) &&
3905 (a->ch_flow_plci[Ch] == plci->Id) &&
3906 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
3907 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3908 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
3909 }
3910 } else {
3911 sig_ind(plci);
3912 }
3913 e->Ind = 0;
3914 }
3915
3916capi_callback_suffix:
3917
3918 while (!plci->req_in
3919 && !plci->internal_command
3920 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
3921 {
3922 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
3923
3924 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
3925
3926 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
3927 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
3928 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
3929 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
3930 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3931 {
3932 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3933 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
3934 }
3935 else
3936 {
3937 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
3938 }
3939 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
3940 {
3941 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
3942 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3943 }
3944 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3945 {
3946 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3947 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3948 }
3949 i = api_put(appl, m);
3950 if (i != 0)
3951 {
3952 if (m->header.command == _DATA_B3_R)
3953
3954 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
3955
3956 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
3957 break;
3958 }
3959
3960 if (plci->li_notify_update)
3961 {
3962 plci->li_notify_update = false;
3963 mixer_notify_update(plci, false);
3964 }
3965
3966 }
3967 send_data(plci);
3968 send_req(plci);
3969}
3970
3971
3972static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
3973 byte nl_rc)
3974{
3975 dword Id;
3976 dword rId;
3977 word Number;
3978 word Info = 0;
3979 word i;
3980 word ncci;
3981 DIVA_CAPI_ADAPTER *a;
3982 APPL *appl;
3983 PLCI *rplci;
3984 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
3985 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
3986
3987 if (!plci) {
3988 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
3989 return;
3990 }
3991 dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
3992 if (plci->req_in != plci->req_out)
3993 {
3994 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
3995 {
3996 dbug(1, dprintf("req_1return"));
3997 return;
3998 }
3999
4000 }
4001 plci->req_in = plci->req_in_start = plci->req_out = 0;
4002 dbug(1, dprintf("control_rc"));
4003
4004 appl = plci->appl;
4005 a = plci->adapter;
4006 ncci = a->ch_ncci[ch];
4007 if (appl)
4008 {
4009 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4010 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4011 Number = plci->number;
4012 dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4013 dbug(1, dprintf("channels=0x%x", plci->channels));
4014 if (plci_remove_check(plci))
4015 return;
4016 if (req == REMOVE && rc == ASSIGN_OK)
4017 {
4018 sig_req(plci, HANGUP, 0);
4019 sig_req(plci, REMOVE, 0);
4020 send_req(plci);
4021 }
4022 if (plci->command)
4023 {
4024 switch (plci->command)
4025 {
4026 case C_HOLD_REQ:
4027 dbug(1, dprintf("HoldRC=0x%x", rc));
4028 SSparms[1] = (byte)S_HOLD;
4029 if (rc != OK)
4030 {
4031 plci->SuppState = IDLE;
4032 Info = 0x2001;
4033 }
4034 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4035 break;
4036
4037 case C_RETRIEVE_REQ:
4038 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4039 SSparms[1] = (byte)S_RETRIEVE;
4040 if (rc != OK)
4041 {
4042 plci->SuppState = CALL_HELD;
4043 Info = 0x2001;
4044 }
4045 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4046 break;
4047
4048 case _INFO_R:
4049 dbug(1, dprintf("InfoRC=0x%x", rc));
4050 if (rc != OK) Info = _WRONG_STATE;
4051 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4052 break;
4053
4054 case _CONNECT_R:
4055 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4056 if (plci->State == INC_DIS_PENDING)
4057 break;
4058 if (plci->Sig.Id != 0xff)
4059 {
4060 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4061 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4062 {
4063 dbug(1, dprintf("No more IDs/Call_Req failed"));
4064 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4065 plci_remove(plci);
4066 plci->State = IDLE;
4067 break;
4068 }
4069 if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4070 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4071 }
4072 else
4073 {
4074 if (rc != ASSIGN_OK)
4075 {
4076 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4077 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4078 plci_remove(plci);
4079 plci->State = IDLE;
4080 break;
4081 }
4082 sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4083 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4084 plci->State = INC_ACT_PENDING;
4085 }
4086 break;
4087
4088 case _CONNECT_I | RESPONSE:
4089 if (plci->State != INC_DIS_PENDING)
4090 plci->State = INC_CON_ACCEPT;
4091 break;
4092
4093 case _DISCONNECT_R:
4094 if (plci->State == INC_DIS_PENDING)
4095 break;
4096 if (plci->Sig.Id != 0xff)
4097 {
4098 plci->State = OUTG_DIS_PENDING;
4099 sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4100 }
4101 break;
4102
4103 case SUSPEND_REQ:
4104 break;
4105
4106 case RESUME_REQ:
4107 break;
4108
4109 case _CONNECT_B3_R:
4110 if (rc != OK)
4111 {
4112 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4113 break;
4114 }
4115 ncci = get_ncci(plci, ch, 0);
4116 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4117 plci->channels++;
4118 if (req == N_RESET)
4119 {
4120 a->ncci_state[ncci] = INC_ACT_PENDING;
4121 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4122 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4123 }
4124 else
4125 {
4126 a->ncci_state[ncci] = OUTG_CON_PENDING;
4127 sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4128 }
4129 break;
4130
4131 case _CONNECT_B3_I | RESPONSE:
4132 break;
4133
4134 case _RESET_B3_R:
4135
4136 break;
4137
4138 case _DISCONNECT_B3_R:
4139 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4140 break;
4141
4142 case _MANUFACTURER_R:
4143 break;
4144
4145 case PERM_LIST_REQ:
4146 if (rc != OK)
4147 {
4148 Info = _WRONG_IDENTIFIER;
4149 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4150 plci_remove(plci);
4151 }
4152 else
4153 sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4154 break;
4155
4156 default:
4157 break;
4158 }
4159 plci->command = 0;
4160 }
4161 else if (plci->internal_command)
4162 {
4163 switch (plci->internal_command)
4164 {
4165 case BLOCK_PLCI:
4166 return;
4167
4168 case GET_MWI_STATE:
4169 if (rc == OK)
4170 {
4171 return;
4172 }
4173 plci_remove(plci);
4174 break;
4175
4176
4177 case GETSERV_REQ_PEND:
4178 if (rc == OK)
4179 {
4180 break;
4181 }
4182 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4183 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4184 plci_remove(plci);
4185 break;
4186
4187 case INTERR_DIVERSION_REQ_PEND:
4188 case INTERR_NUMBERS_REQ_PEND:
4189 case CF_START_PEND:
4190 case CF_STOP_PEND:
4191 case CCBS_REQUEST_REQ_PEND:
4192 case CCBS_DEACTIVATE_REQ_PEND:
4193 case CCBS_INTERROGATE_REQ_PEND:
4194 switch (plci->internal_command)
4195 {
4196 case INTERR_DIVERSION_REQ_PEND:
4197 SSparms[1] = S_INTERROGATE_DIVERSION;
4198 break;
4199 case INTERR_NUMBERS_REQ_PEND:
4200 SSparms[1] = S_INTERROGATE_NUMBERS;
4201 break;
4202 case CF_START_PEND:
4203 SSparms[1] = S_CALL_FORWARDING_START;
4204 break;
4205 case CF_STOP_PEND:
4206 SSparms[1] = S_CALL_FORWARDING_STOP;
4207 break;
4208 case CCBS_REQUEST_REQ_PEND:
4209 SSparms[1] = S_CCBS_REQUEST;
4210 break;
4211 case CCBS_DEACTIVATE_REQ_PEND:
4212 SSparms[1] = S_CCBS_DEACTIVATE;
4213 break;
4214 case CCBS_INTERROGATE_REQ_PEND:
4215 SSparms[1] = S_CCBS_INTERROGATE;
4216 break;
4217 }
4218 if (global_req == ASSIGN)
4219 {
4220 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4221 return;
4222 }
4223 if (!plci->appl) break;
4224 if (rc == ISDN_GUARD_REJ)
4225 {
4226 Info = _CAPI_GUARD_ERROR;
4227 }
4228 else if (rc != OK)
4229 {
4230 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4231 }
4232 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4233 plci->number, "wws", Info, (word)3, SSparms);
4234 if (Info) plci_remove(plci);
4235 break;
4236
4237
4238 case PTY_REQ_PEND:
4239 if (!plci->relatedPTYPLCI) break;
4240 rplci = plci->relatedPTYPLCI;
4241 SSparms[1] = plci->ptyState;
4242 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4243 if (rplci->tel) rId |= EXT_CONTROLLER;
4244 if (rc != OK)
4245 {
4246 Info = 0x300E;
4247 plci->relatedPTYPLCI = NULL;
4248 plci->ptyState = 0;
4249 }
4250 sendf(rplci->appl,
4251 _FACILITY_R | CONFIRM,
4252 rId,
4253 plci->number,
4254 "wws", Info, (word)3, SSparms);
4255 break;
4256
4257
4258 case ECT_REQ_PEND:
4259 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4260 if (!plci->relatedPTYPLCI) break;
4261 rplci = plci->relatedPTYPLCI;
4262 SSparms[1] = S_ECT;
4263 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4264 if (rplci->tel) rId |= EXT_CONTROLLER;
4265 if (rc != OK)
4266 {
4267 Info = 0x300E;
4268 plci->relatedPTYPLCI = NULL;
4269 plci->ptyState = 0;
4270 }
4271 sendf(rplci->appl,
4272 _FACILITY_R | CONFIRM,
4273 rId,
4274 plci->number,
4275 "wws", Info, (word)3, SSparms);
4276 break;
4277
4278 case _MANUFACTURER_R:
4279 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4280 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4281 {
4282 dbug(1, dprintf("No more IDs"));
4283 sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4284 plci_remove(plci);
4285 }
4286 break;
4287
4288 case _CONNECT_R:
4289 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4290 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4291 {
4292 dbug(1, dprintf("No more IDs"));
4293 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4294 plci_remove(plci);
4295 }
4296 break;
4297
4298 case PERM_COD_HOOK:
4299 return;
4300
4301 case PERM_COD_CALL:
4302 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4303 plci->internal_command = PERM_COD_CONN_PEND;
4304 return;
4305
4306 case PERM_COD_ASSIGN:
4307 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4308 if (rc != ASSIGN_OK) break;
4309 sig_req(plci, CALL_REQ, 0);
4310 send_req(plci);
4311 plci->internal_command = PERM_COD_CALL;
4312 return;
4313
4314
4315 case C_NCR_FAC_REQ:
4316 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4317 if (global_req == ASSIGN)
4318 {
4319 if (rc == ASSIGN_OK)
4320 {
4321 return;
4322 }
4323 else
4324 {
4325 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4326 appl->NullCREnable = false;
4327 plci_remove(plci);
4328 }
4329 }
4330 else if (req == NCR_FACILITY)
4331 {
4332 if (rc == OK)
4333 {
4334 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4335 }
4336 else
4337 {
4338 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4339 appl->NullCREnable = false;
4340 }
4341 plci_remove(plci);
4342 }
4343 break;
4344
4345 case HOOK_ON_REQ:
4346 if (plci->channels)
4347 {
4348 if (a->ncci_state[ncci] == CONNECTED)
4349 {
4350 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4351 cleanup_ncci_data(plci, ncci);
4352 nl_req_ncci(plci, N_DISC, (byte)ncci);
4353 }
4354 break;
4355 }
4356 break;
4357
4358 case HOOK_OFF_REQ:
4359 if (plci->State == INC_DIS_PENDING)
4360 break;
4361 sig_req(plci, CALL_REQ, 0);
4362 send_req(plci);
4363 plci->State = OUTG_CON_PENDING;
4364 break;
4365
4366
4367 case MWI_ACTIVATE_REQ_PEND:
4368 case MWI_DEACTIVATE_REQ_PEND:
4369 if (global_req == ASSIGN && rc == ASSIGN_OK)
4370 {
4371 dbug(1, dprintf("MWI_REQ assigned"));
4372 return;
4373 }
4374 else if (rc != OK)
4375 {
4376 if (rc == WRONG_IE)
4377 {
4378 Info = 0x2007;
4379 dbug(1, dprintf("MWI_REQ invalid parameter"));
4380 }
4381 else
4382 {
4383 Info = 0x300B;
4384 dbug(1, dprintf("MWI_REQ not supported"));
4385 }
4386
4387 PUT_WORD(&SSparms[4], 0x300E);
4388
4389 }
4390 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4391 {
4392 PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4393 }
4394 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4395
4396 if (plci->cr_enquiry)
4397 {
4398 sendf(plci->appl,
4399 _FACILITY_R | CONFIRM,
4400 Id & 0xf,
4401 plci->number,
4402 "wws", Info, (word)3, SSparms);
4403 if (rc != OK) plci_remove(plci);
4404 }
4405 else
4406 {
4407 sendf(plci->appl,
4408 _FACILITY_R | CONFIRM,
4409 Id,
4410 plci->number,
4411 "wws", Info, (word)3, SSparms);
4412 }
4413 break;
4414
4415 case CONF_BEGIN_REQ_PEND:
4416 case CONF_ADD_REQ_PEND:
4417 case CONF_SPLIT_REQ_PEND:
4418 case CONF_DROP_REQ_PEND:
4419 case CONF_ISOLATE_REQ_PEND:
4420 case CONF_REATTACH_REQ_PEND:
4421 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4422 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4423 rplci = plci;
4424 rId = Id;
4425 switch (plci->internal_command)
4426 {
4427 case CONF_BEGIN_REQ_PEND:
4428 SSparms[1] = S_CONF_BEGIN;
4429 break;
4430 case CONF_ADD_REQ_PEND:
4431 SSparms[1] = S_CONF_ADD;
4432 rplci = plci->relatedPTYPLCI;
4433 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4434 break;
4435 case CONF_SPLIT_REQ_PEND:
4436 SSparms[1] = S_CONF_SPLIT;
4437 break;
4438 case CONF_DROP_REQ_PEND:
4439 SSparms[1] = S_CONF_DROP;
4440 break;
4441 case CONF_ISOLATE_REQ_PEND:
4442 SSparms[1] = S_CONF_ISOLATE;
4443 break;
4444 case CONF_REATTACH_REQ_PEND:
4445 SSparms[1] = S_CONF_REATTACH;
4446 break;
4447 }
4448
4449 if (rc != OK)
4450 {
4451 Info = 0x300E;
4452 plci->relatedPTYPLCI = NULL;
4453 plci->ptyState = 0;
4454 }
4455 sendf(rplci->appl,
4456 _FACILITY_R | CONFIRM,
4457 rId,
4458 plci->number,
4459 "wws", Info, (word)3, SSparms);
4460 break;
4461
4462 case VSWITCH_REQ_PEND:
4463 if (rc != OK)
4464 {
4465 if (plci->relatedPTYPLCI)
4466 {
4467 plci->relatedPTYPLCI->vswitchstate = 0;
4468 plci->relatedPTYPLCI->vsprot = 0;
4469 plci->relatedPTYPLCI->vsprotdialect = 0;
4470 }
4471 plci->vswitchstate = 0;
4472 plci->vsprot = 0;
4473 plci->vsprotdialect = 0;
4474 }
4475 else
4476 {
4477 if (plci->relatedPTYPLCI &&
4478 plci->vswitchstate == 1 &&
4479 plci->relatedPTYPLCI->vswitchstate == 3)
4480 plci->vswitchstate = 3;
4481 }
4482 break;
4483
4484
4485 case CD_REQ_PEND:
4486 SSparms[1] = S_CALL_DEFLECTION;
4487 if (rc != OK)
4488 {
4489 Info = 0x300E;
4490 plci->appl->CDEnable = 0;
4491 }
4492 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4493 plci->number, "wws", Info, (word)3, SSparms);
4494 break;
4495
4496 case RTP_CONNECT_B3_REQ_COMMAND_2:
4497 if (rc == OK)
4498 {
4499 ncci = get_ncci(plci, ch, 0);
4500 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4501 plci->channels++;
4502 a->ncci_state[ncci] = OUTG_CON_PENDING;
4503 }
4504
4505
4506 default:
4507 if (plci->internal_command_queue[0])
4508 {
4509 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4510 if (plci->internal_command)
4511 return;
4512 }
4513 break;
4514 }
4515 next_internal_command(Id, plci);
4516 }
4517 }
4518 else
4519 {
4520 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4521 if (plci->tel) Id |= EXT_CONTROLLER;
4522
4523 switch (plci->internal_command)
4524 {
4525 case BLOCK_PLCI:
4526 return;
4527
4528 case START_L1_SIG_ASSIGN_PEND:
4529 case REM_L1_SIG_ASSIGN_PEND:
4530 if (global_req == ASSIGN)
4531 {
4532 break;
4533 }
4534 else
4535 {
4536 dbug(1, dprintf("***L1 Req rem PLCI"));
4537 plci->internal_command = 0;
4538 sig_req(plci, REMOVE, 0);
4539 send_req(plci);
4540 }
4541 break;
4542
4543
4544 case CD_REQ_PEND:
4545 SSparms[1] = S_CALL_DEFLECTION;
4546 if (rc != OK)
4547 {
4548 Info = 0x300E;
4549 }
4550 for (i = 0; i < max_appl; i++)
4551 {
4552 if (application[i].CDEnable)
4553 {
4554 if (!application[i].Id) application[i].CDEnable = 0;
4555 else
4556 {
4557 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4558 plci->number, "wws", Info, (word)3, SSparms);
4559 if (Info) application[i].CDEnable = 0;
4560 }
4561 }
4562 }
4563 plci->internal_command = 0;
4564 break;
4565
4566 case PERM_COD_HOOK:
4567 return;
4568
4569 case PERM_COD_CALL:
4570 plci->internal_command = PERM_COD_CONN_PEND;
4571 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4572 return;
4573
4574 case PERM_COD_ASSIGN:
4575 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4576 plci->internal_command = 0;
4577 if (rc != ASSIGN_OK) break;
4578 plci->internal_command = PERM_COD_CALL;
4579 sig_req(plci, CALL_REQ, 0);
4580 send_req(plci);
4581 return;
4582
4583 case LISTEN_SIG_ASSIGN_PEND:
4584 if (rc == ASSIGN_OK)
4585 {
4586 plci->internal_command = 0;
4587 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4588 add_p(plci, ESC, "\x02\x18\x00");
4589 sig_req(plci, INDICATE_REQ, 0);
4590 send_req(plci);
4591 }
4592 else
4593 {
4594 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4595 a->listen_active--;
4596 plci_remove(plci);
4597 plci->State = IDLE;
4598 }
4599 break;
4600
4601 case USELAW_REQ:
4602 if (global_req == ASSIGN)
4603 {
4604 if (rc == ASSIGN_OK)
4605 {
4606 sig_req(plci, LAW_REQ, 0);
4607 send_req(plci);
4608 dbug(1, dprintf("Auto-Law assigned"));
4609 }
4610 else
4611 {
4612 dbug(1, dprintf("Auto-Law assign failed"));
4613 a->automatic_law = 3;
4614 plci->internal_command = 0;
4615 a->automatic_lawPLCI = NULL;
4616 }
4617 break;
4618 }
4619 else if (req == LAW_REQ && rc == OK)
4620 {
4621 dbug(1, dprintf("Auto-Law initiated"));
4622 a->automatic_law = 2;
4623 plci->internal_command = 0;
4624 }
4625 else
4626 {
4627 dbug(1, dprintf("Auto-Law not supported"));
4628 a->automatic_law = 3;
4629 plci->internal_command = 0;
4630 sig_req(plci, REMOVE, 0);
4631 send_req(plci);
4632 a->automatic_lawPLCI = NULL;
4633 }
4634 break;
4635 }
4636 plci_remove_check(plci);
4637 }
4638}
4639
4640static void data_rc(PLCI *plci, byte ch)
4641{
4642 dword Id;
4643 DIVA_CAPI_ADAPTER *a;
4644 NCCI *ncci_ptr;
4645 DATA_B3_DESC *data;
4646 word ncci;
4647
4648 if (plci->appl)
4649 {
4650 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4651 a = plci->adapter;
4652 ncci = a->ch_ncci[ch];
4653 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4654 {
4655 ncci_ptr = &(a->ncci[ncci]);
4656 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4657 if (ncci_ptr->data_pending)
4658 {
4659 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4660 if (!(data->Flags & 4) && a->ncci_state[ncci])
4661 {
4662 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4663 if (plci->tel) Id |= EXT_CONTROLLER;
4664 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4665 "ww", data->Handle, 0);
4666 }
4667 (ncci_ptr->data_out)++;
4668 if (ncci_ptr->data_out == MAX_DATA_B3)
4669 ncci_ptr->data_out = 0;
4670 (ncci_ptr->data_pending)--;
4671 }
4672 }
4673 }
4674}
4675
4676static void data_ack(PLCI *plci, byte ch)
4677{
4678 dword Id;
4679 DIVA_CAPI_ADAPTER *a;
4680 NCCI *ncci_ptr;
4681 word ncci;
4682
4683 a = plci->adapter;
4684 ncci = a->ch_ncci[ch];
4685 ncci_ptr = &(a->ncci[ncci]);
4686 if (ncci_ptr->data_ack_pending)
4687 {
4688 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4689 {
4690 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4691 if (plci->tel) Id |= EXT_CONTROLLER;
4692 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4693 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4694 }
4695 (ncci_ptr->data_ack_out)++;
4696 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4697 ncci_ptr->data_ack_out = 0;
4698 (ncci_ptr->data_ack_pending)--;
4699 }
4700}
4701
4702static void sig_ind(PLCI *plci)
4703{
4704 dword x_Id;
4705 dword Id;
4706 dword rId;
4707 word i;
4708 word cip;
4709 dword cip_mask;
4710 byte *ie;
4711 DIVA_CAPI_ADAPTER *a;
4712 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4713#define MAXPARMSIDS 31
4714 byte *parms[MAXPARMSIDS];
4715 byte *add_i[4];
4716 byte *multi_fac_parms[MAX_MULTI_IE];
4717 byte *multi_pi_parms[MAX_MULTI_IE];
4718 byte *multi_ssext_parms[MAX_MULTI_IE];
4719 byte *multi_CiPN_parms[MAX_MULTI_IE];
4720
4721 byte *multi_vswitch_parms[MAX_MULTI_IE];
4722
4723 byte ai_len;
4724 byte *esc_chi = "";
4725 byte *esc_law = "";
4726 byte *pty_cai = "";
4727 byte *esc_cr = "";
4728 byte *esc_profile = "";
4729
4730 byte facility[256];
4731 PLCI *tplci = NULL;
4732 byte chi[] = "\x02\x18\x01";
4733 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4734 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4735
4736
4737
4738
4739 static const word parms_id[] =
4740 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4741 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4742 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4743 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4744
4745
4746
4747 static const word multi_fac_id[] = {1, FTY};
4748 static const word multi_pi_id[] = {1, PI};
4749 static const word multi_CiPN_id[] = {1, OAD};
4750 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4751
4752 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4753
4754 byte *cau;
4755 word ncci;
4756 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00";
4757 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4758 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4759 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4760 byte force_mt_info = false;
4761 byte dir;
4762 dword d;
4763 word w;
4764
4765 a = plci->adapter;
4766 Id = ((word)plci->Id << 8) | a->Id;
4767 PUT_WORD(&SS_Ind[4], 0x0000);
4768
4769 if (plci->sig_remove_id)
4770 {
4771 plci->Sig.RNR = 2;
4772 dbug(1, dprintf("SIG discard while remove pending"));
4773 return;
4774 }
4775 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4776 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4777 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4778 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4779 {
4780 plci->Sig.RNR = 1;
4781 return;
4782 }
4783 if (plci->Sig.Ind == HANGUP && plci->channels)
4784 {
4785 plci->Sig.RNR = 1;
4786 plci->hangup_flow_ctrl_timer++;
4787
4788 if (plci->hangup_flow_ctrl_timer == 100)
4789 {
4790 dbug(1, dprintf("Exceptional disc"));
4791 plci->Sig.RNR = 0;
4792 plci->hangup_flow_ctrl_timer = 0;
4793 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4794 {
4795 if (a->ncci_plci[ncci] == plci->Id)
4796 {
4797 cleanup_ncci_data(plci, ncci);
4798 if (plci->channels)plci->channels--;
4799 if (plci->appl)
4800 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4801 }
4802 }
4803 if (plci->appl)
4804 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4805 plci_remove(plci);
4806 plci->State = IDLE;
4807 }
4808 return;
4809 }
4810
4811
4812
4813
4814 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4815 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4816 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4817
4818 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4819
4820 IndParse(plci, parms_id, parms, 0);
4821 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4822 esc_chi = parms[14];
4823 esc_law = parms[18];
4824 pty_cai = parms[24];
4825 esc_cr = parms[25];
4826 esc_profile = parms[27];
4827 if (esc_cr[0] && plci)
4828 {
4829 if (plci->cr_enquiry && plci->appl)
4830 {
4831 plci->cr_enquiry = false;
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841 sendf(plci->appl,
4842 _MANUFACTURER_I,
4843 Id,
4844 0,
4845 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4846 2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4847 }
4848 }
4849
4850 add_i[1] = parms[15];
4851 add_i[2] = parms[11];
4852 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4853
4854
4855
4856
4857 if (a->automatic_law < 4)
4858 {
4859 if (esc_law[0]) {
4860 if (esc_law[2]) {
4861 dbug(0, dprintf("u-Law selected"));
4862 a->u_law = 1;
4863 }
4864 else {
4865 dbug(0, dprintf("a-Law selected"));
4866 a->u_law = 0;
4867 }
4868 a->automatic_law = 4;
4869 if (plci == a->automatic_lawPLCI) {
4870 plci->internal_command = 0;
4871 sig_req(plci, REMOVE, 0);
4872 send_req(plci);
4873 a->automatic_lawPLCI = NULL;
4874 }
4875 }
4876 if (esc_profile[0])
4877 {
4878 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4879 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4880 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4881 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4882
4883 a->profile.Global_Options &= 0x000000ffL;
4884 a->profile.B1_Protocols &= 0x000003ffL;
4885 a->profile.B2_Protocols &= 0x00001fdfL;
4886 a->profile.B3_Protocols &= 0x000000b7L;
4887
4888 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4889 GL_BCHANNEL_OPERATION_SUPPORTED;
4890 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4891 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4892 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4893 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4894 a->man_profile.private_options = 0;
4895
4896 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4897 {
4898 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4899 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4900 }
4901
4902
4903 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4904 a->man_profile.private_options |= 1L << PRIVATE_RTP;
4905 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4906 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4907
4908
4909 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4910 a->man_profile.private_options |= 1L << PRIVATE_T38;
4911
4912
4913 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4914 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4915
4916
4917 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4918 a->man_profile.private_options |= 1L << PRIVATE_V18;
4919
4920
4921 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4922 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4923
4924
4925 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4926 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4927
4928
4929 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4930 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4931
4932
4933 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4934 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4935
4936
4937 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4938 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4939
4940 }
4941 else
4942 {
4943 a->profile.Global_Options &= 0x0000007fL;
4944 a->profile.B1_Protocols &= 0x000003dfL;
4945 a->profile.B2_Protocols &= 0x00001adfL;
4946 a->profile.B3_Protocols &= 0x000000b7L;
4947 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4948 }
4949 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4950 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4951 {
4952 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4953 }
4954 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4955 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4956 UnMapController(a->Id), a->profile.Global_Options,
4957 a->profile.B1_Protocols, a->profile.B2_Protocols,
4958 a->profile.B3_Protocols, a->manufacturer_features));
4959 }
4960
4961 if (plci != a->AdvCodecPLCI)
4962 {
4963 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4964 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4965 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4966 SendInfo(plci, Id, parms, force_mt_info);
4967
4968 VSwitchReqInd(plci, Id, multi_vswitch_parms);
4969
4970 }
4971
4972
4973 if (esc_chi[0] && plci && !plci->SuppState) {
4974 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4975 mixer_set_bchannel_id_esc(plci, plci->b_channel);
4976 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4977 if (plci->tel == ADV_VOICE && plci->appl) {
4978 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4979 }
4980 }
4981
4982 if (plci->appl) plci->appl->Number++;
4983
4984 switch (plci->Sig.Ind) {
4985
4986 case S_SUPPORTED:
4987 dbug(1, dprintf("S_Supported"));
4988 if (!plci->appl) break;
4989 if (pty_cai[0] == 4)
4990 {
4991 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4992 }
4993 else
4994 {
4995 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4996 }
4997 PUT_WORD(&CF_Ind[1], 0);
4998 PUT_WORD(&CF_Ind[4], 0);
4999 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5000 plci_remove(plci);
5001 break;
5002
5003
5004 case S_SERVICE_REJ:
5005 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5006 if (!pty_cai[0]) break;
5007 switch (pty_cai[5])
5008 {
5009 case ECT_EXECUTE:
5010 case THREE_PTY_END:
5011 case THREE_PTY_BEGIN:
5012 if (!plci->relatedPTYPLCI) break;
5013 tplci = plci->relatedPTYPLCI;
5014 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5015 if (tplci->tel) rId |= EXT_CONTROLLER;
5016 if (pty_cai[5] == ECT_EXECUTE)
5017 {
5018 PUT_WORD(&SS_Ind[1], S_ECT);
5019
5020 plci->vswitchstate = 0;
5021 plci->relatedPTYPLCI->vswitchstate = 0;
5022
5023 }
5024 else
5025 {
5026 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5027 }
5028 if (pty_cai[2] != 0xff)
5029 {
5030 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5031 }
5032 else
5033 {
5034 PUT_WORD(&SS_Ind[4], 0x300E);
5035 }
5036 plci->relatedPTYPLCI = NULL;
5037 plci->ptyState = 0;
5038 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5039 break;
5040
5041 case CALL_DEFLECTION:
5042 if (pty_cai[2] != 0xff)
5043 {
5044 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5045 }
5046 else
5047 {
5048 PUT_WORD(&SS_Ind[4], 0x300E);
5049 }
5050 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5051 for (i = 0; i < max_appl; i++)
5052 {
5053 if (application[i].CDEnable)
5054 {
5055 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5056 application[i].CDEnable = false;
5057 }
5058 }
5059 break;
5060
5061 case DEACTIVATION_DIVERSION:
5062 case ACTIVATION_DIVERSION:
5063 case DIVERSION_INTERROGATE_CFU:
5064 case DIVERSION_INTERROGATE_CFB:
5065 case DIVERSION_INTERROGATE_CFNR:
5066 case DIVERSION_INTERROGATE_NUM:
5067 case CCBS_REQUEST:
5068 case CCBS_DEACTIVATE:
5069 case CCBS_INTERROGATE:
5070 if (!plci->appl) break;
5071 if (pty_cai[2] != 0xff)
5072 {
5073 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5074 }
5075 else
5076 {
5077 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5078 }
5079 switch (pty_cai[5])
5080 {
5081 case DEACTIVATION_DIVERSION:
5082 dbug(1, dprintf("Deact_Div"));
5083 Interr_Err_Ind[0] = 0x9;
5084 Interr_Err_Ind[3] = 0x6;
5085 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5086 break;
5087 case ACTIVATION_DIVERSION:
5088 dbug(1, dprintf("Act_Div"));
5089 Interr_Err_Ind[0] = 0x9;
5090 Interr_Err_Ind[3] = 0x6;
5091 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5092 break;
5093 case DIVERSION_INTERROGATE_CFU:
5094 case DIVERSION_INTERROGATE_CFB:
5095 case DIVERSION_INTERROGATE_CFNR:
5096 dbug(1, dprintf("Interr_Div"));
5097 Interr_Err_Ind[0] = 0xa;
5098 Interr_Err_Ind[3] = 0x7;
5099 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5100 break;
5101 case DIVERSION_INTERROGATE_NUM:
5102 dbug(1, dprintf("Interr_Num"));
5103 Interr_Err_Ind[0] = 0xa;
5104 Interr_Err_Ind[3] = 0x7;
5105 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5106 break;
5107 case CCBS_REQUEST:
5108 dbug(1, dprintf("CCBS Request"));
5109 Interr_Err_Ind[0] = 0xd;
5110 Interr_Err_Ind[3] = 0xa;
5111 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5112 break;
5113 case CCBS_DEACTIVATE:
5114 dbug(1, dprintf("CCBS Deactivate"));
5115 Interr_Err_Ind[0] = 0x9;
5116 Interr_Err_Ind[3] = 0x6;
5117 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5118 break;
5119 case CCBS_INTERROGATE:
5120 dbug(1, dprintf("CCBS Interrogate"));
5121 Interr_Err_Ind[0] = 0xb;
5122 Interr_Err_Ind[3] = 0x8;
5123 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5124 break;
5125 }
5126 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5127 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5128 plci_remove(plci);
5129 break;
5130 case ACTIVATION_MWI:
5131 case DEACTIVATION_MWI:
5132 if (pty_cai[5] == ACTIVATION_MWI)
5133 {
5134 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5135 }
5136 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5137
5138 if (pty_cai[2] != 0xff)
5139 {
5140 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5141 }
5142 else
5143 {
5144 PUT_WORD(&SS_Ind[4], 0x300E);
5145 }
5146
5147 if (plci->cr_enquiry)
5148 {
5149 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5150 plci_remove(plci);
5151 }
5152 else
5153 {
5154 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5155 }
5156 break;
5157 case CONF_ADD:
5158 case CONF_BEGIN:
5159 case CONF_DROP:
5160 case CONF_ISOLATE:
5161 case CONF_REATTACH:
5162 CONF_Ind[0] = 9;
5163 CONF_Ind[3] = 6;
5164 switch (pty_cai[5])
5165 {
5166 case CONF_BEGIN:
5167 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5168 plci->ptyState = 0;
5169 break;
5170 case CONF_DROP:
5171 CONF_Ind[0] = 5;
5172 CONF_Ind[3] = 2;
5173 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5174 plci->ptyState = CONNECTED;
5175 break;
5176 case CONF_ISOLATE:
5177 CONF_Ind[0] = 5;
5178 CONF_Ind[3] = 2;
5179 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5180 plci->ptyState = CONNECTED;
5181 break;
5182 case CONF_REATTACH:
5183 CONF_Ind[0] = 5;
5184 CONF_Ind[3] = 2;
5185 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5186 plci->ptyState = CONNECTED;
5187 break;
5188 case CONF_ADD:
5189 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5190 plci->relatedPTYPLCI = NULL;
5191 tplci = plci->relatedPTYPLCI;
5192 if (tplci) tplci->ptyState = CONNECTED;
5193 plci->ptyState = CONNECTED;
5194 break;
5195 }
5196
5197 if (pty_cai[2] != 0xff)
5198 {
5199 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5200 }
5201 else
5202 {
5203 PUT_WORD(&CONF_Ind[4], 0x3303);
5204
5205 }
5206
5207 PUT_DWORD(&CONF_Ind[6], 0x0);
5208 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5209 break;
5210 }
5211 break;
5212
5213
5214 case S_SERVICE:
5215 dbug(1, dprintf("Service_Ind"));
5216 PUT_WORD(&CF_Ind[4], 0);
5217 switch (pty_cai[5])
5218 {
5219 case THREE_PTY_END:
5220 case THREE_PTY_BEGIN:
5221 case ECT_EXECUTE:
5222 if (!plci->relatedPTYPLCI) break;
5223 tplci = plci->relatedPTYPLCI;
5224 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5225 if (tplci->tel) rId |= EXT_CONTROLLER;
5226 if (pty_cai[5] == ECT_EXECUTE)
5227 {
5228 PUT_WORD(&SS_Ind[1], S_ECT);
5229
5230 if (plci->vswitchstate != 3)
5231 {
5232
5233 plci->ptyState = IDLE;
5234 plci->relatedPTYPLCI = NULL;
5235 plci->ptyState = 0;
5236
5237 }
5238
5239 dbug(1, dprintf("ECT OK"));
5240 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5241
5242
5243
5244 }
5245 else
5246 {
5247 switch (plci->ptyState)
5248 {
5249 case S_3PTY_BEGIN:
5250 plci->ptyState = CONNECTED;
5251 dbug(1, dprintf("3PTY ON"));
5252 break;
5253
5254 case S_3PTY_END:
5255 plci->ptyState = IDLE;
5256 plci->relatedPTYPLCI = NULL;
5257 plci->ptyState = 0;
5258 dbug(1, dprintf("3PTY OFF"));
5259 break;
5260 }
5261 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5262 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5263 }
5264 break;
5265
5266 case CALL_DEFLECTION:
5267 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5268 for (i = 0; i < max_appl; i++)
5269 {
5270 if (application[i].CDEnable)
5271 {
5272 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5273 application[i].CDEnable = false;
5274 }
5275 }
5276 break;
5277
5278 case DEACTIVATION_DIVERSION:
5279 case ACTIVATION_DIVERSION:
5280 if (!plci->appl) break;
5281 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5282 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5283 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5284 plci_remove(plci);
5285 break;
5286
5287 case DIVERSION_INTERROGATE_CFU:
5288 case DIVERSION_INTERROGATE_CFB:
5289 case DIVERSION_INTERROGATE_CFNR:
5290 case DIVERSION_INTERROGATE_NUM:
5291 case CCBS_REQUEST:
5292 case CCBS_DEACTIVATE:
5293 case CCBS_INTERROGATE:
5294 if (!plci->appl) break;
5295 switch (pty_cai[5])
5296 {
5297 case DIVERSION_INTERROGATE_CFU:
5298 case DIVERSION_INTERROGATE_CFB:
5299 case DIVERSION_INTERROGATE_CFNR:
5300 dbug(1, dprintf("Interr_Div"));
5301 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5302 pty_cai[3] = pty_cai[0] - 3;
5303 break;
5304 case DIVERSION_INTERROGATE_NUM:
5305 dbug(1, dprintf("Interr_Num"));
5306 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5307 pty_cai[3] = pty_cai[0] - 3;
5308 break;
5309 case CCBS_REQUEST:
5310 dbug(1, dprintf("CCBS Request"));
5311 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5312 pty_cai[3] = pty_cai[0] - 3;
5313 break;
5314 case CCBS_DEACTIVATE:
5315 dbug(1, dprintf("CCBS Deactivate"));
5316 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5317 pty_cai[3] = pty_cai[0] - 3;
5318 break;
5319 case CCBS_INTERROGATE:
5320 dbug(1, dprintf("CCBS Interrogate"));
5321 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5322 pty_cai[3] = pty_cai[0] - 3;
5323 break;
5324 }
5325 PUT_WORD(&pty_cai[4], 0);
5326 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5327 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5328 plci_remove(plci);
5329 break;
5330
5331 case ACTIVATION_MWI:
5332 case DEACTIVATION_MWI:
5333 if (pty_cai[5] == ACTIVATION_MWI)
5334 {
5335 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5336 }
5337 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5338 if (plci->cr_enquiry)
5339 {
5340 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5341 plci_remove(plci);
5342 }
5343 else
5344 {
5345 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5346 }
5347 break;
5348 case MWI_INDICATION:
5349 if (pty_cai[0] >= 0x12)
5350 {
5351 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5352 pty_cai[2] = pty_cai[0] - 2;
5353 pty_cai[5] = pty_cai[0] - 5;
5354 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5355 {
5356 if (plci->internal_command == GET_MWI_STATE)
5357 {
5358 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5359 plci_remove(plci);
5360 return;
5361 }
5362 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5363 pty_cai[0] = 0;
5364 }
5365 else
5366 {
5367 for (i = 0; i < max_appl; i++)
5368 {
5369 if (a->Notification_Mask[i]&SMASK_MWI)
5370 {
5371 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5372 pty_cai[0] = 0;
5373 }
5374 }
5375 }
5376
5377 if (!pty_cai[0])
5378 {
5379 facility[2] = 0;
5380 }
5381 else facility[2] = 0xff;
5382 }
5383 else
5384 {
5385
5386 facility[2] = 0xff;
5387 }
5388 facility[0] = 2;
5389 facility[1] = MWI_RESPONSE;
5390 add_p(plci, CAI, facility);
5391 add_p(plci, ESC, multi_ssext_parms[0]);
5392 sig_req(plci, S_SERVICE, 0);
5393 send_req(plci);
5394 plci->command = 0;
5395 next_internal_command(Id, plci);
5396 break;
5397 case CONF_ADD:
5398 case CONF_BEGIN:
5399 case CONF_DROP:
5400 case CONF_ISOLATE:
5401 case CONF_REATTACH:
5402 case CONF_PARTYDISC:
5403 CONF_Ind[0] = 9;
5404 CONF_Ind[3] = 6;
5405 switch (pty_cai[5])
5406 {
5407 case CONF_BEGIN:
5408 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5409 if (pty_cai[0] == 6)
5410 {
5411 d = pty_cai[6];
5412 PUT_DWORD(&CONF_Ind[6], d);
5413 }
5414 else
5415 {
5416 PUT_DWORD(&CONF_Ind[6], 0x0);
5417 }
5418 break;
5419 case CONF_ISOLATE:
5420 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5421 CONF_Ind[0] = 5;
5422 CONF_Ind[3] = 2;
5423 break;
5424 case CONF_REATTACH:
5425 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5426 CONF_Ind[0] = 5;
5427 CONF_Ind[3] = 2;
5428 break;
5429 case CONF_DROP:
5430 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5431 CONF_Ind[0] = 5;
5432 CONF_Ind[3] = 2;
5433 break;
5434 case CONF_ADD:
5435 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5436 d = pty_cai[6];
5437 PUT_DWORD(&CONF_Ind[6], d);
5438 tplci = plci->relatedPTYPLCI;
5439 if (tplci) tplci->ptyState = CONNECTED;
5440 break;
5441 case CONF_PARTYDISC:
5442 CONF_Ind[0] = 7;
5443 CONF_Ind[3] = 4;
5444 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5445 d = pty_cai[6];
5446 PUT_DWORD(&CONF_Ind[4], d);
5447 break;
5448 }
5449 plci->ptyState = CONNECTED;
5450 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5451 break;
5452 case CCBS_INFO_RETAIN:
5453 case CCBS_ERASECALLLINKAGEID:
5454 case CCBS_STOP_ALERTING:
5455 CONF_Ind[0] = 5;
5456 CONF_Ind[3] = 2;
5457 switch (pty_cai[5])
5458 {
5459 case CCBS_INFO_RETAIN:
5460 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5461 break;
5462 case CCBS_STOP_ALERTING:
5463 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5464 break;
5465 case CCBS_ERASECALLLINKAGEID:
5466 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5467 CONF_Ind[0] = 7;
5468 CONF_Ind[3] = 4;
5469 CONF_Ind[6] = 0;
5470 CONF_Ind[7] = 0;
5471 break;
5472 }
5473 w = pty_cai[6];
5474 PUT_WORD(&CONF_Ind[4], w);
5475
5476 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5477 {
5478 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5479 }
5480 else
5481 {
5482 for (i = 0; i < max_appl; i++)
5483 if (a->Notification_Mask[i] & SMASK_CCBS)
5484 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5485 }
5486 break;
5487 }
5488 break;
5489 case CALL_HOLD_REJ:
5490 cau = parms[7];
5491 if (cau)
5492 {
5493 i = _L3_CAUSE | cau[2];
5494 if (cau[2] == 0) i = 0x3603;
5495 }
5496 else
5497 {
5498 i = 0x3603;
5499 }
5500 PUT_WORD(&SS_Ind[1], S_HOLD);
5501 PUT_WORD(&SS_Ind[4], i);
5502 if (plci->SuppState == HOLD_REQUEST)
5503 {
5504 plci->SuppState = IDLE;
5505 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5506 }
5507 break;
5508
5509 case CALL_HOLD_ACK:
5510 if (plci->SuppState == HOLD_REQUEST)
5511 {
5512 plci->SuppState = CALL_HELD;
5513 CodecIdCheck(a, plci);
5514 start_internal_command(Id, plci, hold_save_command);
5515 }
5516 break;
5517
5518 case CALL_RETRIEVE_REJ:
5519 cau = parms[7];
5520 if (cau)
5521 {
5522 i = _L3_CAUSE | cau[2];
5523 if (cau[2] == 0) i = 0x3603;
5524 }
5525 else
5526 {
5527 i = 0x3603;
5528 }
5529 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5530 PUT_WORD(&SS_Ind[4], i);
5531 if (plci->SuppState == RETRIEVE_REQUEST)
5532 {
5533 plci->SuppState = CALL_HELD;
5534 CodecIdCheck(a, plci);
5535 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5536 }
5537 break;
5538
5539 case CALL_RETRIEVE_ACK:
5540 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5541 if (plci->SuppState == RETRIEVE_REQUEST)
5542 {
5543 plci->SuppState = IDLE;
5544 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5545 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5546 if (plci->tel)
5547 {
5548 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5549 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5550 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5551 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5552 {
5553 dbug(1, dprintf("Get B-ch"));
5554 start_internal_command(Id, plci, retrieve_restore_command);
5555 }
5556 else
5557 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5558 }
5559 else
5560 start_internal_command(Id, plci, retrieve_restore_command);
5561 }
5562 break;
5563
5564 case INDICATE_IND:
5565 if (plci->State != LISTENING) {
5566 sig_req(plci, HANGUP, 0);
5567 send_req(plci);
5568 break;
5569 }
5570 cip = find_cip(a, parms[4], parms[6]);
5571 cip_mask = 1L << cip;
5572 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5573 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5574 if (!remove_started && !a->adapter_disabled)
5575 {
5576 group_optimization(a, plci);
5577 for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5578 if (application[i].Id
5579 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5580 && CPN_filter_ok(parms[0], a, i)) {
5581 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5582 __set_bit(i, plci->c_ind_mask_table);
5583 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5584 plci->State = INC_CON_PENDING;
5585 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5586 CALL_DIR_IN | CALL_DIR_ANSWER;
5587 if (esc_chi[0]) {
5588 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5589 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5590 }
5591
5592
5593 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5594 if (a->profile.Global_Options & HANDSET)
5595 plci->tel = ADV_VOICE;
5596 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5597 plci->tel = CODEC;
5598 if (plci->tel) Id |= EXT_CONTROLLER;
5599 a->codec_listen[i] = plci;
5600 }
5601
5602 sendf(&application[i], _CONNECT_I, Id, 0,
5603 "wSSSSSSSbSSSSS", cip,
5604 parms[0],
5605 multi_CiPN_parms[0],
5606 parms[2],
5607 parms[3],
5608 parms[4],
5609 parms[5],
5610 parms[6],
5611 ai_len,
5612 add_i[0],
5613 add_i[1],
5614 add_i[2],
5615 add_i[3],
5616 multi_CiPN_parms[1]
5617 );
5618 SendSSExtInd(&application[i],
5619 plci,
5620 Id,
5621 multi_ssext_parms);
5622 SendSetupInfo(&application[i],
5623 plci,
5624 Id,
5625 parms,
5626 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5627 }
5628 }
5629 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5630 }
5631 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5632 sig_req(plci, HANGUP, 0);
5633 send_req(plci);
5634 plci->State = IDLE;
5635 }
5636 plci->notifiedcall = 0;
5637 a->listen_active--;
5638 listen_check(a);
5639 break;
5640
5641 case CALL_PEND_NOTIFY:
5642 plci->notifiedcall = 1;
5643 listen_check(a);
5644 break;
5645
5646 case CALL_IND:
5647 case CALL_CON:
5648 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5649 {
5650 if (plci->internal_command == PERM_COD_CONN_PEND)
5651 {
5652 if (plci->State == ADVANCED_VOICE_NOSIG)
5653 {
5654 dbug(1, dprintf("***Codec OK"));
5655 if (a->AdvSignalPLCI)
5656 {
5657 tplci = a->AdvSignalPLCI;
5658 if (tplci->spoofed_msg)
5659 {
5660 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5661 tplci->command = 0;
5662 tplci->internal_command = 0;
5663 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5664 switch (tplci->spoofed_msg)
5665 {
5666 case CALL_RES:
5667 tplci->command = _CONNECT_I | RESPONSE;
5668 api_load_msg(&tplci->saved_msg, saved_parms);
5669 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5670 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5671 {
5672
5673 add_p(tplci, LLI, "\x01\x01");
5674 }
5675 add_s(tplci, CONN_NR, &saved_parms[2]);
5676 add_s(tplci, LLC, &saved_parms[4]);
5677 add_ai(tplci, &saved_parms[5]);
5678 tplci->State = INC_CON_ACCEPT;
5679 sig_req(tplci, CALL_RES, 0);
5680 send_req(tplci);
5681 break;
5682
5683 case AWAITING_SELECT_B:
5684 dbug(1, dprintf("Select_B continue"));
5685 start_internal_command(x_Id, tplci, select_b_command);
5686 break;
5687
5688 case AWAITING_MANUF_CON:
5689 if (!tplci->Sig.Id)
5690 {
5691 dbug(1, dprintf("No SigID!"));
5692 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5693 plci_remove(tplci);
5694 break;
5695 }
5696 tplci->command = _MANUFACTURER_R;
5697 api_load_msg(&tplci->saved_msg, saved_parms);
5698 dir = saved_parms[2].info[0];
5699 if (dir == 1) {
5700 sig_req(tplci, CALL_REQ, 0);
5701 }
5702 else if (!dir) {
5703 sig_req(tplci, LISTEN_REQ, 0);
5704 }
5705 send_req(tplci);
5706 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5707 break;
5708
5709 case (CALL_REQ | AWAITING_MANUF_CON):
5710 sig_req(tplci, CALL_REQ, 0);
5711 send_req(tplci);
5712 break;
5713
5714 case CALL_REQ:
5715 if (!tplci->Sig.Id)
5716 {
5717 dbug(1, dprintf("No SigID!"));
5718 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5719 plci_remove(tplci);
5720 break;
5721 }
5722 tplci->command = _CONNECT_R;
5723 api_load_msg(&tplci->saved_msg, saved_parms);
5724 add_s(tplci, CPN, &saved_parms[1]);
5725 add_s(tplci, DSA, &saved_parms[3]);
5726 add_ai(tplci, &saved_parms[9]);
5727 sig_req(tplci, CALL_REQ, 0);
5728 send_req(tplci);
5729 break;
5730
5731 case CALL_RETRIEVE:
5732 tplci->command = C_RETRIEVE_REQ;
5733 sig_req(tplci, CALL_RETRIEVE, 0);
5734 send_req(tplci);
5735 break;
5736 }
5737 tplci->spoofed_msg = 0;
5738 if (tplci->internal_command == 0)
5739 next_internal_command(x_Id, tplci);
5740 }
5741 }
5742 next_internal_command(Id, plci);
5743 break;
5744 }
5745 dbug(1, dprintf("***Codec Hook Init Req"));
5746 plci->internal_command = PERM_COD_HOOK;
5747 add_p(plci, FTY, "\x01\x09");
5748 sig_req(plci, TEL_CTRL, 0);
5749 send_req(plci);
5750 }
5751 }
5752 else if (plci->command != _MANUFACTURER_R
5753 && plci->State != INC_ACT_PENDING)
5754 {
5755 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5756 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE)
5757 {
5758 chi[2] = plci->b_channel;
5759 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5760 }
5761 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5762 plci->State = INC_ACT_PENDING;
5763 }
5764 break;
5765
5766 case TEL_CTRL:
5767 ie = multi_fac_parms[0];
5768 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5769 switch (ie[1] & 0x91) {
5770 case 0x80:
5771 case 0x81:
5772 if (plci->internal_command == PERM_COD_HOOK)
5773 {
5774 dbug(1, dprintf("init:hook_off"));
5775 plci->hook_state = ie[1];
5776 next_internal_command(Id, plci);
5777 break;
5778 }
5779 else
5780 {
5781 if (((plci->hook_state) & 0xf0) == 0x80)
5782 {
5783 dbug(1, dprintf("ignore hook"));
5784 break;
5785 }
5786 plci->hook_state = ie[1]&0x91;
5787 }
5788
5789
5790
5791
5792 for (i = 0, tplci = NULL; i < max_appl; i++) {
5793 if (a->codec_listen[i]
5794 && (a->codec_listen[i]->State == INC_CON_PENDING
5795 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5796 tplci = a->codec_listen[i];
5797 tplci->appl = &application[i];
5798 }
5799 }
5800
5801
5802 if (!a->AdvSignalPLCI && !tplci) {
5803 if ((i = get_plci(a))) {
5804 a->AdvSignalPLCI = &a->plci[i - 1];
5805 tplci = a->AdvSignalPLCI;
5806 tplci->tel = ADV_VOICE;
5807 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5808 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5809
5810 add_p(tplci, LLI, "\x01\x01");
5811 }
5812 add_p(tplci, CAI, voice_cai);
5813 add_p(tplci, OAD, a->TelOAD);
5814 add_p(tplci, OSA, a->TelOSA);
5815 add_p(tplci, SHIFT | 6, NULL);
5816 add_p(tplci, SIN, "\x02\x01\x00");
5817 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5818 sig_req(tplci, ASSIGN, DSIG_ID);
5819 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5820 a->AdvSignalPLCI->command = 0;
5821 tplci->appl = a->AdvSignalAppl;
5822 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5823 send_req(tplci);
5824 }
5825
5826 }
5827
5828 if (!tplci) break;
5829 Id = ((word)tplci->Id << 8) | a->Id;
5830 Id |= EXT_CONTROLLER;
5831 sendf(tplci->appl,
5832 _FACILITY_I,
5833 Id,
5834 0,
5835 "ws", (word)0, "\x01+");
5836 break;
5837
5838 case 0x90:
5839 case 0x91:
5840 if (plci->internal_command == PERM_COD_HOOK)
5841 {
5842 dbug(1, dprintf("init:hook_on"));
5843 plci->hook_state = ie[1] & 0x91;
5844 next_internal_command(Id, plci);
5845 break;
5846 }
5847 else
5848 {
5849 if (((plci->hook_state) & 0xf0) == 0x90) break;
5850 plci->hook_state = ie[1] & 0x91;
5851 }
5852
5853 if (a->AdvSignalPLCI) {
5854 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5855 if (plci->tel) Id |= EXT_CONTROLLER;
5856 sendf(a->AdvSignalAppl,
5857 _FACILITY_I,
5858 Id,
5859 0,
5860 "ws", (word)0, "\x01-");
5861 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5862 a->AdvSignalPLCI->command = 0;
5863 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5864 send_req(a->AdvSignalPLCI);
5865 }
5866 break;
5867 }
5868 }
5869 break;
5870
5871 case RESUME:
5872 __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5873 PUT_WORD(&resume_cau[4], GOOD);
5874 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5875 break;
5876
5877 case SUSPEND:
5878 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5879
5880 if (plci->NL.Id && !plci->nl_remove_id) {
5881 mixer_remove(plci);
5882 nl_req_ncci(plci, REMOVE, 0);
5883 }
5884 if (!plci->sig_remove_id) {
5885 plci->internal_command = 0;
5886 sig_req(plci, REMOVE, 0);
5887 }
5888 send_req(plci);
5889 if (!plci->channels) {
5890 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5891 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5892 }
5893 break;
5894
5895 case SUSPEND_REJ:
5896 break;
5897
5898 case HANGUP:
5899 plci->hangup_flow_ctrl_timer = 0;
5900 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5901 cau = parms[7];
5902 if (cau) {
5903 i = _L3_CAUSE | cau[2];
5904 if (cau[2] == 0) i = 0;
5905 else if (cau[2] == 8) i = _L1_ERROR;
5906 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5907 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5908 }
5909 else {
5910 i = _L3_ERROR;
5911 }
5912
5913 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5914 {
5915 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5916 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5917 }
5918 else
5919 {
5920 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5921 }
5922 if (!plci->appl)
5923 {
5924 if (plci->State == LISTENING)
5925 {
5926 plci->notifiedcall = 0;
5927 a->listen_active--;
5928 }
5929 plci->State = INC_DIS_PENDING;
5930 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5931 {
5932 plci->State = IDLE;
5933 if (plci->NL.Id && !plci->nl_remove_id)
5934 {
5935 mixer_remove(plci);
5936 nl_req_ncci(plci, REMOVE, 0);
5937 }
5938 if (!plci->sig_remove_id)
5939 {
5940 plci->internal_command = 0;
5941 sig_req(plci, REMOVE, 0);
5942 }
5943 send_req(plci);
5944 }
5945 }
5946 else
5947 {
5948
5949
5950
5951 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5952 {
5953 if (plci->State == RESUMING)
5954 {
5955 PUT_WORD(&resume_cau[4], i);
5956 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5957 }
5958 plci->State = INC_DIS_PENDING;
5959 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5960 }
5961 }
5962 break;
5963
5964 case SSEXT_IND:
5965 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5966 break;
5967
5968 case VSWITCH_REQ:
5969 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5970 break;
5971 case VSWITCH_IND:
5972 if (plci->relatedPTYPLCI &&
5973 plci->vswitchstate == 3 &&
5974 plci->relatedPTYPLCI->vswitchstate == 3 &&
5975 parms[MAXPARMSIDS - 1][0])
5976 {
5977 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5978 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5979 send_req(plci->relatedPTYPLCI);
5980 }
5981 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5982 break;
5983
5984 }
5985}
5986
5987
5988static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5989{
5990 word i;
5991 byte *ie;
5992 word Info_Number;
5993 byte *Info_Element;
5994 word Info_Mask = 0;
5995
5996 dbug(1, dprintf("SetupInfo"));
5997
5998 for (i = 0; i < MAXPARMSIDS; i++) {
5999 ie = parms[i];
6000 Info_Number = 0;
6001 Info_Element = ie;
6002 if (ie[0]) {
6003 switch (i) {
6004 case 0:
6005 dbug(1, dprintf("CPN "));
6006 Info_Number = 0x0070;
6007 Info_Mask = 0x80;
6008 Info_Sent_Flag = true;
6009 break;
6010 case 8:
6011 dbug(1, dprintf("display(%d)", i));
6012 Info_Number = 0x0028;
6013 Info_Mask = 0x04;
6014 Info_Sent_Flag = true;
6015 break;
6016 case 16:
6017 dbug(1, dprintf("CHI"));
6018 Info_Number = 0x0018;
6019 Info_Mask = 0x100;
6020 Info_Sent_Flag = true;
6021 mixer_set_bchannel_id(plci, Info_Element);
6022 break;
6023 case 19:
6024 dbug(1, dprintf("RDN"));
6025 Info_Number = 0x0074;
6026 Info_Mask = 0x400;
6027 Info_Sent_Flag = true;
6028 break;
6029 case 20:
6030 dbug(1, dprintf("RDX"));
6031 Info_Number = 0x0073;
6032 Info_Mask = 0x400;
6033 Info_Sent_Flag = true;
6034 break;
6035 case 22:
6036 dbug(1, dprintf("RIN"));
6037 Info_Number = 0x0076;
6038 Info_Mask = 0x400;
6039 Info_Sent_Flag = true;
6040 break;
6041 default:
6042 Info_Number = 0;
6043 break;
6044 }
6045 }
6046
6047 if (i == MAXPARMSIDS - 2) {
6048 Info_Number = 0x8000 | 5;
6049 Info_Mask = 0x10;
6050 Info_Element = "";
6051 }
6052
6053 if (Info_Sent_Flag && Info_Number) {
6054 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6055 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6056 }
6057 }
6058 }
6059}
6060
6061
6062static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6063{
6064 word i;
6065 word j;
6066 word k;
6067 byte *ie;
6068 word Info_Number;
6069 byte *Info_Element;
6070 word Info_Mask = 0;
6071 static byte charges[5] = {4, 0, 0, 0, 0};
6072 static byte cause[] = {0x02, 0x80, 0x00};
6073 APPL *appl;
6074
6075 dbug(1, dprintf("InfoParse "));
6076
6077 if (
6078 !plci->appl
6079 && !plci->State
6080 && plci->Sig.Ind != NCR_FACILITY
6081 )
6082 {
6083 dbug(1, dprintf("NoParse "));
6084 return;
6085 }
6086 cause[2] = 0;
6087 for (i = 0; i < MAXPARMSIDS; i++) {
6088 ie = parms[i];
6089 Info_Number = 0;
6090 Info_Element = ie;
6091 if (ie[0]) {
6092 switch (i) {
6093 case 0:
6094 dbug(1, dprintf("CPN "));
6095 Info_Number = 0x0070;
6096 Info_Mask = 0x80;
6097 break;
6098 case 7:
6099 dbug(1, dprintf("cau(0x%x)", ie[2]));
6100 Info_Number = 0x0008;
6101 Info_Mask = 0x00;
6102 cause[2] = ie[2];
6103 Info_Element = NULL;
6104 break;
6105 case 8:
6106 dbug(1, dprintf("display(%d)", i));
6107 Info_Number = 0x0028;
6108 Info_Mask = 0x04;
6109 break;
6110 case 9:
6111 dbug(1, dprintf("date(%d)", i));
6112 Info_Number = 0x0029;
6113 Info_Mask = 0x02;
6114 break;
6115 case 10:
6116 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6117 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6118 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6119 Info_Number = 0x4000;
6120 Info_Mask = 0x40;
6121 Info_Element = charges;
6122 break;
6123 case 11:
6124 dbug(1, dprintf("uui"));
6125 Info_Number = 0x007E;
6126 Info_Mask = 0x08;
6127 break;
6128 case 12:
6129 dbug(1, dprintf("clRDY"));
6130 Info_Number = 0x00B0;
6131 Info_Mask = 0x08;
6132 Info_Element = "";
6133 break;
6134 case 13:
6135 dbug(1, dprintf("clNRDY"));
6136 Info_Number = 0x00BF;
6137 Info_Mask = 0x08;
6138 Info_Element = "";
6139 break;
6140 case 15:
6141 dbug(1, dprintf("KEY"));
6142 Info_Number = 0x002C;
6143 Info_Mask = 0x20;
6144 break;
6145 case 16:
6146 dbug(1, dprintf("CHI"));
6147 Info_Number = 0x0018;
6148 Info_Mask = 0x100;
6149 mixer_set_bchannel_id(plci, Info_Element);
6150 break;
6151 case 17:
6152 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6153 if (!cause[2] || cause[2] < 0x80) break;
6154 Info_Number = 0x0008;
6155 Info_Mask = 0x01;
6156 if (cause[2] != ie[2]) Info_Element = cause;
6157 break;
6158 case 19:
6159 dbug(1, dprintf("RDN"));
6160 Info_Number = 0x0074;
6161 Info_Mask = 0x400;
6162 break;
6163 case 22:
6164 dbug(1, dprintf("RIN"));
6165 Info_Number = 0x0076;
6166 Info_Mask = 0x400;
6167 break;
6168 case 23:
6169 dbug(1, dprintf("NI"));
6170 Info_Number = (word)NI;
6171 Info_Mask = 0x210;
6172 break;
6173 case 26:
6174 dbug(1, dprintf("CST"));
6175 Info_Number = (word)CST;
6176 Info_Mask = 0x01;
6177 break;
6178 case MAXPARMSIDS - 2:
6179 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6180 Info_Number = 0x8000 | ie[3];
6181 if (iesent) Info_Mask = 0xffff;
6182 else Info_Mask = 0x10;
6183 Info_Element = "";
6184 break;
6185 default:
6186 Info_Number = 0;
6187 Info_Mask = 0;
6188 Info_Element = "";
6189 break;
6190 }
6191 }
6192
6193 if (plci->Sig.Ind == NCR_FACILITY)
6194 {
6195 for (j = 0; j < max_appl; j++)
6196 {
6197 appl = &application[j];
6198 if (Info_Number
6199 && appl->Id
6200 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6201 {
6202 dbug(1, dprintf("NCR_Ind"));
6203 iesent = true;
6204 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6205 }
6206 }
6207 }
6208 else if (!plci->appl)
6209 {
6210 if (Info_Number == CPN
6211 || Info_Number == KEY
6212 || Info_Number == NI
6213 || Info_Number == DSP
6214 || Info_Number == UUI)
6215 {
6216 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6217 dbug(1, dprintf("Ovl_Ind"));
6218 iesent = true;
6219 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6220 }
6221 }
6222 }
6223 else if (Info_Number
6224 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6225 {
6226 dbug(1, dprintf("Std_Ind"));
6227 iesent = true;
6228 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6229 }
6230 }
6231}
6232
6233
6234static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6235 dword info_mask, byte setupParse)
6236{
6237 word i;
6238 word j;
6239 byte *ie;
6240 word Info_Number;
6241 byte *Info_Element;
6242 APPL *appl;
6243 word Info_Mask = 0;
6244 byte iesent = 0;
6245
6246 if (
6247 !plci->appl
6248 && !plci->State
6249 && plci->Sig.Ind != NCR_FACILITY
6250 && !setupParse
6251 )
6252 {
6253 dbug(1, dprintf("NoM-IEParse "));
6254 return 0;
6255 }
6256 dbug(1, dprintf("M-IEParse "));
6257
6258 for (i = 0; i < MAX_MULTI_IE; i++)
6259 {
6260 ie = parms[i];
6261 Info_Number = 0;
6262 Info_Element = ie;
6263 if (ie[0])
6264 {
6265 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6266 Info_Number = (word)ie_type;
6267 Info_Mask = (word)info_mask;
6268 }
6269
6270 if (plci->Sig.Ind == NCR_FACILITY)
6271 {
6272 for (j = 0; j < max_appl; j++)
6273 {
6274 appl = &application[j];
6275 if (Info_Number
6276 && appl->Id
6277 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6278 {
6279 iesent = true;
6280 dbug(1, dprintf("Mlt_NCR_Ind"));
6281 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6282 }
6283 }
6284 }
6285 else if (!plci->appl && Info_Number)
6286 {
6287 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6288 iesent = true;
6289 dbug(1, dprintf("Mlt_Ovl_Ind"));
6290 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6291 }
6292 }
6293 else if (Info_Number
6294 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6295 {
6296 iesent = true;
6297 dbug(1, dprintf("Mlt_Std_Ind"));
6298 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6299 }
6300 }
6301 return iesent;
6302}
6303
6304static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6305{
6306 word i;
6307
6308
6309
6310
6311
6312
6313
6314
6315 if (
6316 plci
6317 && plci->State
6318 && plci->Sig.Ind != NCR_FACILITY
6319 )
6320 for (i = 0; i < MAX_MULTI_IE; i++)
6321 {
6322 if (parms[i][0] < 6) continue;
6323 if (parms[i][2] == SSEXT_REQ) continue;
6324
6325 if (appl)
6326 {
6327 parms[i][0] = 0;
6328 sendf(appl, _MANUFACTURER_I,
6329 Id,
6330 0,
6331 "dwS",
6332 _DI_MANU_ID,
6333 _DI_SSEXT_CTRL,
6334 &parms[i][3]);
6335 }
6336 else if (plci->appl)
6337 {
6338 parms[i][0] = 0;
6339 sendf(plci->appl, _MANUFACTURER_I,
6340 Id,
6341 0,
6342 "dwS",
6343 _DI_MANU_ID,
6344 _DI_SSEXT_CTRL,
6345 &parms[i][3]);
6346 }
6347 }
6348};
6349
6350static void nl_ind(PLCI *plci)
6351{
6352 byte ch;
6353 word ncci;
6354 dword Id;
6355 DIVA_CAPI_ADAPTER *a;
6356 word NCCIcode;
6357 APPL *APPLptr;
6358 word count;
6359 word Num;
6360 word i, ncpi_state;
6361 byte len, ncci_state;
6362 word msg;
6363 word info = 0;
6364 word fax_feature_bits;
6365 byte fax_send_edata_ack;
6366 static byte v120_header_buffer[2 + 3];
6367 static word fax_info[] = {
6368 0,
6369 _FAX_NO_CONNECTION,
6370 _FAX_PROTOCOL_ERROR,
6371 _FAX_PROTOCOL_ERROR,
6372 _FAX_PROTOCOL_ERROR,
6373 _FAX_PROTOCOL_ERROR,
6374 _FAX_REMOTE_ABORT,
6375 _FAX_LOCAL_ABORT,
6376 _FAX_TRAINING_ERROR,
6377 _FAX_TRAINING_ERROR,
6378 _FAX_PARAMETER_ERROR,
6379 _FAX_REMOTE_ABORT,
6380 _FAX_LOCAL_ABORT,
6381 _FAX_REMOTE_REJECT,
6382 _FAX_LOCAL_ABORT,
6383 _FAX_PROTOCOL_ERROR,
6384 _FAX_PROTOCOL_ERROR,
6385 _FAX_PROTOCOL_ERROR,
6386 _FAX_PROTOCOL_ERROR,
6387 _FAX_NO_CONNECTION,
6388 _FAX_PROTOCOL_ERROR,
6389 _FAX_PARAMETER_ERROR,
6390 _FAX_PROTOCOL_ERROR,
6391 _FAX_PROTOCOL_ERROR,
6392 _FAX_PROTOCOL_ERROR,
6393 _FAX_PROTOCOL_ERROR,
6394 _FAX_PROTOCOL_ERROR,
6395 _FAX_PROTOCOL_ERROR,
6396 _FAX_PROTOCOL_ERROR,
6397 _FAX_PROTOCOL_ERROR,
6398 _FAX_PROTOCOL_ERROR,
6399 _FAX_PROTOCOL_ERROR,
6400 _FAX_PROTOCOL_ERROR,
6401 0x331d,
6402 0x331e,
6403 0x331f,
6404 _FAX_PROTOCOL_ERROR,
6405 _FAX_PARAMETER_ERROR,
6406 _FAX_PARAMETER_ERROR,
6407 _FAX_REMOTE_REJECT,
6408 _FAX_LOCAL_ABORT,
6409 _FAX_PROTOCOL_ERROR,
6410 _FAX_PROTOCOL_ERROR,
6411 _FAX_PROTOCOL_ERROR,
6412 _FAX_PROTOCOL_ERROR,
6413 _FAX_LOCAL_ABORT,
6414 _FAX_LOCAL_ABORT
6415 };
6416
6417 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6418
6419
6420 static word rtp_info[] = {
6421 GOOD,
6422 0x3600
6423 };
6424
6425 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6426 {
6427 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6428 0x00000000, 0x00000000, 0x00000000, 0x00000000
6429 };
6430
6431 ch = plci->NL.IndCh;
6432 a = plci->adapter;
6433 ncci = a->ch_ncci[ch];
6434 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6435 if (plci->tel) Id |= EXT_CONTROLLER;
6436 APPLptr = plci->appl;
6437 dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6438 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6439
6440
6441
6442 if (plci->nl_remove_id)
6443 {
6444 plci->NL.RNR = 2;
6445 dbug(1, dprintf("NL discard while remove pending"));
6446 return;
6447 }
6448 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6449 {
6450 if (plci->State == INC_DIS_PENDING
6451 || plci->State == OUTG_DIS_PENDING
6452 || plci->State == IDLE)
6453 {
6454 plci->NL.RNR = 2;
6455 dbug(1, dprintf("discard n_connect"));
6456 return;
6457 }
6458 if (plci->State < INC_ACT_PENDING)
6459 {
6460 plci->NL.RNR = 1;
6461 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6462 return;
6463 }
6464 }
6465
6466 if (!APPLptr)
6467 {
6468 dbug(1, dprintf("discard1"));
6469 plci->NL.RNR = 2;
6470 return;
6471 }
6472
6473 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6474 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6475 || (plci->B2_prot == 7)
6476 || (plci->B3_prot == 7)))
6477 {
6478 plci->ncpi_buffer[0] = 0;
6479
6480 ncpi_state = plci->ncpi_state;
6481 if (plci->NL.complete == 1)
6482 {
6483 byte *data = &plci->NL.RBuffer->P[0];
6484
6485 if ((plci->NL.RBuffer->length >= 12)
6486 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6487 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6488 {
6489 word conn_opt, ncpi_opt = 0x00;
6490
6491
6492 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6493 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6494 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6495 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6496
6497 data++;
6498 data += 2;
6499 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6500 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6501 data++;
6502 conn_opt = GET_WORD(data);
6503 data += 2;
6504
6505 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6506
6507 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6508 {
6509 ncpi_opt |= MDM_NCPI_ECM_V42;
6510 }
6511 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6512 {
6513 ncpi_opt |= MDM_NCPI_ECM_MNP;
6514 }
6515 else
6516 {
6517 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6518 }
6519 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6520 {
6521 ncpi_opt |= MDM_NCPI_COMPRESSED;
6522 }
6523 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6524 plci->ncpi_buffer[0] = 4;
6525
6526 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6527 }
6528 }
6529 if (plci->B3_prot == 7)
6530 {
6531 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6532 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6533 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6534 {
6535 a->ncci_state[ncci] = INC_ACT_PENDING;
6536 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6537 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6538 }
6539 }
6540
6541 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6542 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6543 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6544 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6545
6546 {
6547 plci->NL.RNR = 2;
6548 return;
6549 }
6550 }
6551
6552 if (plci->NL.complete == 2)
6553 {
6554 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6555 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6556 {
6557 switch (plci->RData[0].P[0])
6558 {
6559
6560 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6561 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6562 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6563 break;
6564 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6565 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6566 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6567 break;
6568 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6569 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6570 break;
6571 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6572 dtmf_confirmation(Id, plci);
6573 break;
6574
6575
6576 case UDATA_INDICATION_MIXER_TAP_DATA:
6577 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6578 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6579 if (i != 0)
6580 {
6581 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6582 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6583 }
6584 break;
6585
6586
6587 case UDATA_INDICATION_MIXER_COEFS_SET:
6588 mixer_indication_coefs_set(Id, plci);
6589 break;
6590 case UDATA_INDICATION_XCONNECT_FROM:
6591 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6592 break;
6593 case UDATA_INDICATION_XCONNECT_TO:
6594 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6595 break;
6596
6597
6598 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6599 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6600 break;
6601
6602
6603
6604 default:
6605 break;
6606 }
6607 }
6608 else
6609 {
6610 if ((plci->RData[0].PLength != 0)
6611 && ((plci->B2_prot == B2_V120_ASYNC)
6612 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6613 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6614 {
6615
6616 sendf(plci->appl, _DATA_B3_I, Id, 0,
6617 "dwww",
6618 plci->RData[1].P,
6619 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6620 plci->RNum,
6621 plci->RFlags);
6622
6623 }
6624 else
6625 {
6626
6627 sendf(plci->appl, _DATA_B3_I, Id, 0,
6628 "dwww",
6629 plci->RData[0].P,
6630 plci->RData[0].PLength,
6631 plci->RNum,
6632 plci->RFlags);
6633
6634 }
6635 }
6636 return;
6637 }
6638
6639 fax_feature_bits = 0;
6640 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6641 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6642 (plci->NL.Ind & 0x0f) == N_DISC ||
6643 (plci->NL.Ind & 0x0f) == N_EDATA ||
6644 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6645 {
6646 info = 0;
6647 plci->ncpi_buffer[0] = 0;
6648 switch (plci->B3_prot) {
6649 case 0:
6650 case 1:
6651 break;
6652 case 2:
6653 case 3:
6654 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6655 plci->ncpi_buffer[0] = (byte)(i + 3);
6656 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6657 plci->ncpi_buffer[2] = 0;
6658 plci->ncpi_buffer[3] = 0;
6659 break;
6660 case 4:
6661 case 5:
6662 if (plci->NL.RLength >= sizeof(T30_INFO))
6663 {
6664 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6665 len = 9;
6666 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6667 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6668 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6669 if (plci->B3_prot == 5)
6670 {
6671 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6672 i |= 0x8000;
6673 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6674 i |= 0x4000;
6675 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6676 i |= 0x2000;
6677 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6678 i |= 0x0004;
6679 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6680 i |= 0x0002;
6681 }
6682 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6683 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6684 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6685 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6686 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6687 plci->ncpi_buffer[len] = 0;
6688 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6689 {
6690 plci->ncpi_buffer[len] = 20;
6691 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6692 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6693 }
6694 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6695 {
6696 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6697 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6698 else
6699 info = _FAX_PROTOCOL_ERROR;
6700 }
6701
6702 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6703 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6704 {
6705 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6706 while (i < plci->NL.RBuffer->length)
6707 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6708 }
6709
6710 plci->ncpi_buffer[0] = len;
6711 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6712 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6713
6714 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6715 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6716 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6717 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6718 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6719 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6720 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6721 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6722 {
6723 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6724 }
6725 if (((plci->NL.Ind & 0x0f) == N_DISC)
6726 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6727 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6728 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6729 {
6730 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6731 }
6732 }
6733 break;
6734
6735 case B3_RTP:
6736 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6737 {
6738 if (plci->NL.RLength != 0)
6739 {
6740 info = rtp_info[plci->NL.RBuffer->P[0]];
6741 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6742 for (i = 1; i < plci->NL.RLength; i++)
6743 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6744 }
6745 }
6746 break;
6747
6748 }
6749 plci->NL.RNR = 2;
6750 }
6751 switch (plci->NL.Ind & 0x0f) {
6752 case N_EDATA:
6753 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6754 {
6755 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6756 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6757 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6758
6759 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6760 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6761 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6762 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6763 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6764 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6765 {
6766 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6767 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6768 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6769 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6770 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6771 fax_send_edata_ack = false;
6772 }
6773
6774 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6775 {
6776 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6777 {
6778 case EDATA_T30_DIS:
6779 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6780 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6781 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6782 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6783 {
6784 a->ncci_state[ncci] = INC_ACT_PENDING;
6785 if (plci->B3_prot == 4)
6786 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6787 else
6788 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6789 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6790 }
6791 break;
6792
6793 case EDATA_T30_TRAIN_OK:
6794 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6795 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6796 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6797 {
6798 if (plci->B3_prot == 4)
6799 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6800 else
6801 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6802 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6803 }
6804 break;
6805
6806 case EDATA_T30_EOP_CAPI:
6807 if (a->ncci_state[ncci] == CONNECTED)
6808 {
6809 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6810 a->ncci_state[ncci] = INC_DIS_PENDING;
6811 plci->ncpi_state = 0;
6812 fax_send_edata_ack = false;
6813 }
6814 break;
6815 }
6816 }
6817 else
6818 {
6819 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6820 {
6821 case EDATA_T30_TRAIN_OK:
6822 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6823 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6824 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6825 {
6826 if (plci->B3_prot == 4)
6827 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6828 else
6829 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6830 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6831 }
6832 break;
6833 }
6834 }
6835 if (fax_send_edata_ack)
6836 {
6837 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6838 plci->fax_edata_ack_length = 1;
6839 start_internal_command(Id, plci, fax_edata_ack_command);
6840 }
6841 }
6842 else
6843 {
6844 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6845 }
6846 break;
6847 case N_CONNECT:
6848 if (!a->ch_ncci[ch])
6849 {
6850 ncci = get_ncci(plci, ch, 0);
6851 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6852 }
6853 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6854 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6855
6856 msg = _CONNECT_B3_I;
6857 if (a->ncci_state[ncci] == IDLE)
6858 plci->channels++;
6859 else if (plci->B3_prot == 1)
6860 msg = _CONNECT_B3_T90_ACTIVE_I;
6861
6862 a->ncci_state[ncci] = INC_CON_PENDING;
6863 if (plci->B3_prot == 4)
6864 sendf(plci->appl, msg, Id, 0, "s", "");
6865 else
6866 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6867 break;
6868 case N_CONNECT_ACK:
6869 dbug(1, dprintf("N_connect_Ack"));
6870 if (plci->internal_command_queue[0]
6871 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6872 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6873 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6874 {
6875 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6876 if (!plci->internal_command)
6877 next_internal_command(Id, plci);
6878 break;
6879 }
6880 msg = _CONNECT_B3_ACTIVE_I;
6881 if (plci->B3_prot == 1)
6882 {
6883 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6884 msg = _CONNECT_B3_T90_ACTIVE_I;
6885 a->ncci_state[ncci] = INC_ACT_PENDING;
6886 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6887 }
6888 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6889 {
6890 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6891 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6892 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6893 {
6894 a->ncci_state[ncci] = INC_ACT_PENDING;
6895 if (plci->B3_prot == 4)
6896 sendf(plci->appl, msg, Id, 0, "s", "");
6897 else
6898 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6899 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6900 }
6901 }
6902 else
6903 {
6904 a->ncci_state[ncci] = INC_ACT_PENDING;
6905 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6906 }
6907 if (plci->adjust_b_restore)
6908 {
6909 plci->adjust_b_restore = false;
6910 start_internal_command(Id, plci, adjust_b_restore);
6911 }
6912 break;
6913 case N_DISC:
6914 case N_DISC_ACK:
6915 if (plci->internal_command_queue[0]
6916 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6917 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6918 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6919 {
6920 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6921 if (!plci->internal_command)
6922 next_internal_command(Id, plci);
6923 }
6924 ncci_state = a->ncci_state[ncci];
6925 ncci_remove(plci, ncci, false);
6926
6927
6928
6929
6930
6931 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6932 plci->inc_dis_ncci_table[i] = (byte) ncci;
6933
6934
6935 if (!plci->channels
6936 && (plci->B1_resource == 16)
6937 && (plci->State <= CONNECTED))
6938 {
6939 len = 9;
6940 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6941 PUT_WORD(&plci->ncpi_buffer[1], i);
6942 PUT_WORD(&plci->ncpi_buffer[3], 0);
6943 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6944 PUT_WORD(&plci->ncpi_buffer[5], i);
6945 PUT_WORD(&plci->ncpi_buffer[7], 0);
6946 plci->ncpi_buffer[len] = 0;
6947 plci->ncpi_buffer[0] = len;
6948 if (plci->B3_prot == 4)
6949 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6950 else
6951 {
6952
6953 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6954 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6955 {
6956 plci->ncpi_buffer[++len] = 0;
6957 plci->ncpi_buffer[++len] = 0;
6958 plci->ncpi_buffer[++len] = 0;
6959 plci->ncpi_buffer[0] = len;
6960 }
6961
6962 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6963 }
6964 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6965 plci->ncpi_state = 0;
6966 sig_req(plci, HANGUP, 0);
6967 send_req(plci);
6968 plci->State = OUTG_DIS_PENDING;
6969
6970 }
6971 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6972 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6973 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6974 {
6975 if (ncci_state == IDLE)
6976 {
6977 if (plci->channels)
6978 plci->channels--;
6979 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6980 if (plci->State == SUSPENDING) {
6981 sendf(plci->appl,
6982 _FACILITY_I,
6983 Id & 0xffffL,
6984 0,
6985 "ws", (word)3, "\x03\x04\x00\x00");
6986 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6987 }
6988 plci_remove(plci);
6989 plci->State = IDLE;
6990 }
6991 }
6992 }
6993 else if (plci->channels)
6994 {
6995 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6996 plci->ncpi_state = 0;
6997 if ((ncci_state == OUTG_REJ_PENDING)
6998 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6999 {
7000 sig_req(plci, HANGUP, 0);
7001 send_req(plci);
7002 plci->State = OUTG_DIS_PENDING;
7003 }
7004 }
7005 break;
7006 case N_RESET:
7007 a->ncci_state[ncci] = INC_RES_PENDING;
7008 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7009 break;
7010 case N_RESET_ACK:
7011 a->ncci_state[ncci] = CONNECTED;
7012 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7013 break;
7014
7015 case N_UDATA:
7016 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7017 {
7018 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7019 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7020 plci->NL.R = plci->RData;
7021 plci->NL.RNum = 1;
7022 return;
7023 }
7024
7025 case N_BDATA:
7026 case N_DATA:
7027 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1))
7028 || (a->ncci_state[ncci] == IDLE)
7029 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7030 {
7031 plci->NL.RNR = 2;
7032 break;
7033 }
7034 if ((a->ncci_state[ncci] != CONNECTED)
7035 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7036 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7037 {
7038 dbug(1, dprintf("flow control"));
7039 plci->NL.RNR = 1;
7040 channel_x_off(plci, ch, 0);
7041 break;
7042 }
7043
7044 NCCIcode = ncci | (((word)a->Id) << 8);
7045
7046
7047
7048
7049
7050 count = 0;
7051 Num = 0xffff;
7052 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7053 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7054 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7055 }
7056
7057 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7058 {
7059 dbug(3, dprintf("Flow-Control"));
7060 plci->NL.RNR = 1;
7061 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7062 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7063 {
7064 plci->NL.RNR = 2;
7065 dbug(3, dprintf("DiscardData"));
7066 } else {
7067 channel_x_off(plci, ch, 0);
7068 }
7069 break;
7070 }
7071 else
7072 {
7073 APPLptr->NCCIDataFlowCtrlTimer = 0;
7074 }
7075
7076 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7077 if (!plci->RData[0].P) {
7078 plci->NL.RNR = 1;
7079 channel_x_off(plci, ch, 0);
7080 break;
7081 }
7082
7083 APPLptr->DataNCCI[Num] = NCCIcode;
7084 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7085 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7086
7087 plci->RNum = Num;
7088 plci->RFlags = plci->NL.Ind >> 4;
7089 plci->RData[0].PLength = APPLptr->MaxDataLength;
7090 plci->NL.R = plci->RData;
7091 if ((plci->NL.RLength != 0)
7092 && ((plci->B2_prot == B2_V120_ASYNC)
7093 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7094 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7095 {
7096 plci->RData[1].P = plci->RData[0].P;
7097 plci->RData[1].PLength = plci->RData[0].PLength;
7098 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7099 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7100 plci->RData[0].PLength = 1;
7101 else
7102 plci->RData[0].PLength = 2;
7103 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7104 plci->RFlags |= 0x0010;
7105 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7106 plci->RFlags |= 0x8000;
7107 plci->NL.RNum = 2;
7108 }
7109 else
7110 {
7111 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7112 plci->RFlags |= 0x0010;
7113
7114 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7115 plci->RFlags |= 0x0001;
7116
7117 plci->NL.RNum = 1;
7118 }
7119 break;
7120 case N_DATA_ACK:
7121 data_ack(plci, ch);
7122 break;
7123 default:
7124 plci->NL.RNR = 2;
7125 break;
7126 }
7127}
7128
7129
7130
7131
7132
7133static word get_plci(DIVA_CAPI_ADAPTER *a)
7134{
7135 word i, j;
7136 PLCI *plci;
7137
7138 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7139 if (i == a->max_plci) {
7140 dbug(1, dprintf("get_plci: out of PLCIs"));
7141 return 0;
7142 }
7143 plci = &a->plci[i];
7144 plci->Id = (byte)(i + 1);
7145
7146 plci->Sig.Id = 0;
7147 plci->NL.Id = 0;
7148 plci->sig_req = 0;
7149 plci->nl_req = 0;
7150
7151 plci->appl = NULL;
7152 plci->relatedPTYPLCI = NULL;
7153 plci->State = IDLE;
7154 plci->SuppState = IDLE;
7155 plci->channels = 0;
7156 plci->tel = 0;
7157 plci->B1_resource = 0;
7158 plci->B2_prot = 0;
7159 plci->B3_prot = 0;
7160
7161 plci->command = 0;
7162 plci->m_command = 0;
7163 init_internal_command_queue(plci);
7164 plci->number = 0;
7165 plci->req_in_start = 0;
7166 plci->req_in = 0;
7167 plci->req_out = 0;
7168 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7169 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7170 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7171
7172 plci->data_sent = false;
7173 plci->send_disc = 0;
7174 plci->sig_global_req = 0;
7175 plci->sig_remove_id = 0;
7176 plci->nl_global_req = 0;
7177 plci->nl_remove_id = 0;
7178 plci->adv_nl = 0;
7179 plci->manufacturer = false;
7180 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7181 plci->spoofed_msg = 0;
7182 plci->ptyState = 0;
7183 plci->cr_enquiry = false;
7184 plci->hangup_flow_ctrl_timer = 0;
7185
7186 plci->ncci_ring_list = 0;
7187 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7188 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7189 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7190 plci->fax_connect_info_length = 0;
7191 plci->nsf_control_bits = 0;
7192 plci->ncpi_state = 0x00;
7193 plci->ncpi_buffer[0] = 0;
7194
7195 plci->requested_options_conn = 0;
7196 plci->requested_options = 0;
7197 plci->notifiedcall = 0;
7198 plci->vswitchstate = 0;
7199 plci->vsprot = 0;
7200 plci->vsprotdialect = 0;
7201 init_b1_config(plci);
7202 dbug(1, dprintf("get_plci(%x)", plci->Id));
7203 return i + 1;
7204}
7205
7206
7207
7208
7209
7210static void add_p(PLCI *plci, byte code, byte *p)
7211{
7212 word p_length;
7213
7214 p_length = 0;
7215 if (p) p_length = p[0];
7216 add_ie(plci, code, p, p_length);
7217}
7218
7219
7220
7221
7222static void add_s(PLCI *plci, byte code, API_PARSE *p)
7223{
7224 if (p) add_ie(plci, code, p->info, (word)p->length);
7225}
7226
7227
7228
7229
7230static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7231{
7232 byte i;
7233
7234 if (p) {
7235 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7236 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7237 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7238 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7239 }
7240 }
7241}
7242
7243
7244
7245
7246static byte getChannel(API_PARSE *p)
7247{
7248 byte i;
7249
7250 if (p) {
7251 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7252 if (p->info[i] == 2) {
7253 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7254 }
7255 }
7256 }
7257 return 0;
7258}
7259
7260
7261
7262
7263
7264
7265static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7266{
7267 word i;
7268
7269 if (!(code & 0x80) && !p_length) return;
7270
7271 if (plci->req_in == plci->req_in_start) {
7272 plci->req_in += 2;
7273 }
7274 else {
7275 plci->req_in--;
7276 }
7277 plci->RBuffer[plci->req_in++] = code;
7278
7279 if (p) {
7280 plci->RBuffer[plci->req_in++] = (byte)p_length;
7281 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7282 }
7283
7284 plci->RBuffer[plci->req_in++] = 0;
7285}
7286
7287
7288
7289
7290
7291static void add_d(PLCI *plci, word length, byte *p)
7292{
7293 word i;
7294
7295 if (plci->req_in == plci->req_in_start) {
7296 plci->req_in += 2;
7297 }
7298 else {
7299 plci->req_in--;
7300 }
7301 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7302}
7303
7304
7305
7306
7307
7308
7309static void add_ai(PLCI *plci, API_PARSE *ai)
7310{
7311 word i;
7312 API_PARSE ai_parms[5];
7313
7314 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7315
7316 if (!ai->length)
7317 return;
7318 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7319 return;
7320
7321 add_s(plci, KEY, &ai_parms[1]);
7322 add_s(plci, UUI, &ai_parms[2]);
7323 add_ss(plci, FTY, &ai_parms[3]);
7324}
7325
7326
7327
7328
7329
7330static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7331 word b1_facilities)
7332{
7333 API_PARSE bp_parms[8];
7334 API_PARSE mdm_cfg[9];
7335 API_PARSE global_config[2];
7336 byte cai[256];
7337 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7338 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7339 word i;
7340
7341 API_PARSE mdm_cfg_v18[4];
7342 word j, n, w;
7343 dword d;
7344
7345
7346 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7347 for (i = 0; i < 2; i++) global_config[i].length = 0;
7348
7349 dbug(1, dprintf("add_b1"));
7350 api_save_msg(bp, "s", &plci->B_protocol);
7351
7352 if (b_channel_info == 2) {
7353 plci->B1_resource = 0;
7354 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7355 add_p(plci, CAI, "\x01\x00");
7356 dbug(1, dprintf("Cai=1,0 (no resource)"));
7357 return 0;
7358 }
7359
7360 if (plci->tel == CODEC_PERMANENT) return 0;
7361 else if (plci->tel == CODEC) {
7362 plci->B1_resource = 1;
7363 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7364 add_p(plci, CAI, "\x01\x01");
7365 dbug(1, dprintf("Cai=1,1 (Codec)"));
7366 return 0;
7367 }
7368 else if (plci->tel == ADV_VOICE) {
7369 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7370 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7371 voice_cai[1] = plci->B1_resource;
7372 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7373 add_p(plci, CAI, voice_cai);
7374 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7375 return 0;
7376 }
7377 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7378 if (plci->call_dir & CALL_DIR_OUT)
7379 plci->call_dir |= CALL_DIR_ORIGINATE;
7380 else if (plci->call_dir & CALL_DIR_IN)
7381 plci->call_dir |= CALL_DIR_ANSWER;
7382
7383 if (!bp->length) {
7384 plci->B1_resource = 0x5;
7385 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7386 add_p(plci, CAI, "\x01\x05");
7387 return 0;
7388 }
7389
7390 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7391 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7392 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7393 {
7394 bp_parms[6].length = 0;
7395 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7396 {
7397 dbug(1, dprintf("b-form.!"));
7398 return _WRONG_MESSAGE_FORMAT;
7399 }
7400 }
7401 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7402 {
7403 dbug(1, dprintf("b-form.!"));
7404 return _WRONG_MESSAGE_FORMAT;
7405 }
7406
7407 if (bp_parms[6].length)
7408 {
7409 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7410 {
7411 return _WRONG_MESSAGE_FORMAT;
7412 }
7413 switch (GET_WORD(global_config[0].info))
7414 {
7415 case 1:
7416 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7417 break;
7418 case 2:
7419 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7420 break;
7421 }
7422 }
7423 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7424
7425
7426 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7427 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7428 {
7429 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7430 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7431 cai[1] = plci->B1_resource;
7432 cai[2] = 0;
7433 cai[3] = 0;
7434 cai[4] = 0;
7435 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7436 for (i = 0; i < bp_parms[3].length; i++)
7437 cai[7 + i] = bp_parms[3].info[1 + i];
7438 cai[0] = 6 + bp_parms[3].length;
7439 add_p(plci, CAI, cai);
7440 return 0;
7441 }
7442
7443
7444 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7445 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7446 {
7447 plci->B1_resource = add_b1_facilities(plci, 35, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7448 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7449 cai[1] = plci->B1_resource;
7450 cai[2] = 0;
7451 cai[3] = 0;
7452 cai[4] = 0;
7453 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7454 cai[0] = 6;
7455 add_p(plci, CAI, cai);
7456 return 0;
7457 }
7458
7459
7460 if ((GET_WORD(bp_parms[0].info) >= 32)
7461 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7462 && ((GET_WORD(bp_parms[0].info) != 3)
7463 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7464 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7465 {
7466 return _B1_NOT_SUPPORTED;
7467 }
7468 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7469 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7470 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7471 cai[0] = 6;
7472 cai[1] = plci->B1_resource;
7473 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7474
7475 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7476 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7477 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7478 {
7479 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7480
7481 if (bp_parms[3].length)
7482 {
7483 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7484 {
7485 return (_WRONG_MESSAGE_FORMAT);
7486 }
7487
7488 cai[2] = 0;
7489
7490 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7491
7492 PUT_WORD(&cai[13], 0);
7493 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info));
7494 PUT_WORD(&cai[17], 0);
7495 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info));
7496
7497 cai[3] = 0;
7498 switch (GET_WORD(mdm_cfg[2].info))
7499 {
7500 case 1:
7501 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7502 dbug(1, dprintf("MDM: odd parity"));
7503 break;
7504
7505 case 2:
7506 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7507 dbug(1, dprintf("MDM: even parity"));
7508 break;
7509
7510 default:
7511 dbug(1, dprintf("MDM: no parity"));
7512 break;
7513 }
7514
7515 switch (GET_WORD(mdm_cfg[3].info))
7516 {
7517 case 1:
7518 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7519 dbug(1, dprintf("MDM: 2 stop bits"));
7520 break;
7521
7522 default:
7523 dbug(1, dprintf("MDM: 1 stop bit"));
7524 break;
7525 }
7526
7527 switch (GET_WORD(mdm_cfg[1].info))
7528 {
7529 case 5:
7530 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7531 dbug(1, dprintf("MDM: 5 bits"));
7532 break;
7533
7534 case 6:
7535 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7536 dbug(1, dprintf("MDM: 6 bits"));
7537 break;
7538
7539 case 7:
7540 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7541 dbug(1, dprintf("MDM: 7 bits"));
7542 break;
7543
7544 default:
7545 dbug(1, dprintf("MDM: 8 bits"));
7546 break;
7547 }
7548
7549 cai[7] = 0;
7550 cai[8] = 0;
7551 cai[9] = 0;
7552
7553 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7554 {
7555 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7556 dbug(1, dprintf("MDM: Reverse direction"));
7557 }
7558
7559 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7560 {
7561 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7562 dbug(1, dprintf("MDM: Disable retrain"));
7563 }
7564
7565 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7566 {
7567 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7568 dbug(1, dprintf("MDM: Disable ring tone"));
7569 }
7570
7571 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7572 {
7573 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7574 dbug(1, dprintf("MDM: 1800 guard tone"));
7575 }
7576 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7577 {
7578 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7579 dbug(1, dprintf("MDM: 550 guard tone"));
7580 }
7581
7582 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7583 {
7584 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7585 dbug(1, dprintf("MDM: V100"));
7586 }
7587 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7588 {
7589 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7590 dbug(1, dprintf("MDM: IN CLASS"));
7591 }
7592 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7593 {
7594 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7595 dbug(1, dprintf("MDM: DISABLED"));
7596 }
7597 cai[0] = 20;
7598
7599 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7600 && (GET_WORD(mdm_cfg[5].info) & 0x8000))
7601 {
7602 plci->requested_options |= 1L << PRIVATE_V18;
7603 }
7604 if (GET_WORD(mdm_cfg[5].info) & 0x4000)
7605 plci->requested_options |= 1L << PRIVATE_VOWN;
7606
7607 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7608 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7609 {
7610 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7611 {
7612 i = 27;
7613 if (mdm_cfg[6].length >= 4)
7614 {
7615 d = GET_DWORD(&mdm_cfg[6].info[1]);
7616 cai[7] |= (byte) d;
7617 cai[9] |= (byte)(d >> 8);
7618 cai[++i] = (byte)(d >> 16);
7619 cai[++i] = (byte)(d >> 24);
7620 if (mdm_cfg[6].length >= 8)
7621 {
7622 d = GET_DWORD(&mdm_cfg[6].info[5]);
7623 cai[10] |= (byte) d;
7624 cai[11] |= (byte)(d >> 8);
7625 if (mdm_cfg[6].length >= 12)
7626 {
7627 d = GET_DWORD(&mdm_cfg[6].info[9]);
7628 cai[12] = (byte) d;
7629 cai[++i] = (byte)(d >> 8);
7630 cai[++i] = (byte)(d >> 16);
7631 cai[++i] = (byte)(d >> 24);
7632 cai[++i] = 0;
7633 if (mdm_cfg[6].length >= 14)
7634 {
7635 w = GET_WORD(&mdm_cfg[6].info[13]);
7636 if (w != 0)
7637 PUT_WORD(&cai[13], w);
7638 if (mdm_cfg[6].length >= 16)
7639 {
7640 w = GET_WORD(&mdm_cfg[6].info[15]);
7641 if (w != 0)
7642 PUT_WORD(&cai[15], w);
7643 if (mdm_cfg[6].length >= 18)
7644 {
7645 w = GET_WORD(&mdm_cfg[6].info[17]);
7646 if (w != 0)
7647 PUT_WORD(&cai[17], w);
7648 if (mdm_cfg[6].length >= 20)
7649 {
7650 w = GET_WORD(&mdm_cfg[6].info[19]);
7651 if (w != 0)
7652 PUT_WORD(&cai[19], w);
7653 if (mdm_cfg[6].length >= 22)
7654 {
7655 w = GET_WORD(&mdm_cfg[6].info[21]);
7656 cai[23] = (byte)(-((short) w));
7657 if (mdm_cfg[6].length >= 24)
7658 {
7659 w = GET_WORD(&mdm_cfg[6].info[23]);
7660 cai[22] |= (byte) w;
7661 cai[21] |= (byte)(w >> 8);
7662 }
7663 }
7664 }
7665 }
7666 }
7667 }
7668 }
7669 }
7670 }
7671 cai[27] = i - 27;
7672 i++;
7673 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7674 {
7675 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7676 {
7677 for (n = 0; n < 3; n++)
7678 {
7679 cai[i] = (byte)(mdm_cfg_v18[n].length);
7680 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7681 cai[i + j] = mdm_cfg_v18[n].info[j];
7682 i += cai[i] + 1;
7683 }
7684 }
7685 }
7686 cai[0] = (byte)(i - 1);
7687 }
7688 }
7689
7690 }
7691 }
7692 if (GET_WORD(bp_parms[0].info) == 2 ||
7693 GET_WORD(bp_parms[0].info) == 3)
7694 {
7695 if (bp_parms[3].length) {
7696 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7697 switch (GET_WORD(&bp_parms[3].info[1])) {
7698 case 0:
7699 case 56000:
7700 if (GET_WORD(bp_parms[0].info) == 3) {
7701 dbug(1, dprintf("56k sync HSCX"));
7702 cai[1] = 8;
7703 cai[2] = 0;
7704 cai[3] = 0;
7705 }
7706 else if (GET_WORD(bp_parms[0].info) == 2) {
7707 dbug(1, dprintf("56k async DSP"));
7708 cai[2] = 9;
7709 }
7710 break;
7711 case 50: cai[2] = 1; break;
7712 case 75: cai[2] = 1; break;
7713 case 110: cai[2] = 1; break;
7714 case 150: cai[2] = 1; break;
7715 case 200: cai[2] = 1; break;
7716 case 300: cai[2] = 1; break;
7717 case 600: cai[2] = 1; break;
7718 case 1200: cai[2] = 2; break;
7719 case 2400: cai[2] = 3; break;
7720 case 4800: cai[2] = 4; break;
7721 case 7200: cai[2] = 10; break;
7722 case 9600: cai[2] = 5; break;
7723 case 12000: cai[2] = 13; break;
7724 case 24000: cai[2] = 0; break;
7725 case 14400: cai[2] = 11; break;
7726 case 19200: cai[2] = 6; break;
7727 case 28800: cai[2] = 12; break;
7728 case 38400: cai[2] = 7; break;
7729 case 48000: cai[2] = 8; break;
7730 case 76: cai[2] = 15; break;
7731 case 1201: cai[2] = 14; break;
7732 case 56001: cai[2] = 9; break;
7733
7734 default:
7735 return _B1_PARM_NOT_SUPPORTED;
7736 }
7737 cai[3] = 0;
7738 if (cai[1] == 13)
7739 {
7740 if (bp_parms[3].length >= 8)
7741 {
7742 switch (GET_WORD(&bp_parms[3].info[3]))
7743 {
7744 case 5:
7745 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7746 break;
7747 case 6:
7748 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7749 break;
7750 case 7:
7751 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7752 break;
7753 }
7754 switch (GET_WORD(&bp_parms[3].info[5]))
7755 {
7756 case 1:
7757 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7758 break;
7759 case 2:
7760 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7761 break;
7762 }
7763 switch (GET_WORD(&bp_parms[3].info[7]))
7764 {
7765 case 1:
7766 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7767 break;
7768 }
7769 }
7770 }
7771 }
7772 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7773 dbug(1, dprintf("V.110 default 56k sync"));
7774 cai[1] = 8;
7775 cai[2] = 0;
7776 cai[3] = 0;
7777 }
7778 else {
7779 dbug(1, dprintf("V.110 default 9600 async"));
7780 cai[2] = 5;
7781 }
7782 }
7783 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7784 dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7785
7786
7787 add_p(plci, CAI, cai);
7788 return 0;
7789}
7790
7791
7792
7793
7794
7795static word add_b23(PLCI *plci, API_PARSE *bp)
7796{
7797 word i, fax_control_bits;
7798 byte pos, len;
7799 byte SAPI = 0x40;
7800 API_PARSE bp_parms[8];
7801 API_PARSE *b1_config;
7802 API_PARSE *b2_config;
7803 API_PARSE b2_config_parms[8];
7804 API_PARSE *b3_config;
7805 API_PARSE b3_config_parms[6];
7806 API_PARSE global_config[2];
7807
7808 static byte llc[3] = {2,0,0};
7809 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7810 static byte nlc[256];
7811 static byte lli[12] = {1,1};
7812
7813 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7814 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7815
7816 const byte llc3[] = {4,3,2,2,6,6,0};
7817 const byte header[] = {0,2,3,3,0,0,0};
7818
7819 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7820 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7821 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7822
7823 lli[0] = 1;
7824 lli[1] = 1;
7825 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7826 lli[1] |= 2;
7827 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7828 lli[1] |= 4;
7829
7830 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7831 lli[1] |= 0x10;
7832 if (plci->rx_dma_descriptor <= 0) {
7833 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7834 if (plci->rx_dma_descriptor >= 0)
7835 plci->rx_dma_descriptor++;
7836 }
7837 if (plci->rx_dma_descriptor > 0) {
7838 lli[0] = 6;
7839 lli[1] |= 0x40;
7840 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7841 lli[3] = (byte)plci->rx_dma_magic;
7842 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7843 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7844 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7845 }
7846 }
7847
7848 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7849 lli[1] |= 0x20;
7850 }
7851
7852 dbug(1, dprintf("add_b23"));
7853 api_save_msg(bp, "s", &plci->B_protocol);
7854
7855 if (!bp->length && plci->tel)
7856 {
7857 plci->adv_nl = true;
7858 dbug(1, dprintf("Default adv.Nl"));
7859 add_p(plci, LLI, lli);
7860 plci->B2_prot = 1 ;
7861 plci->B3_prot = 0 ;
7862 llc[1] = 2;
7863 llc[2] = 4;
7864 add_p(plci, LLC, llc);
7865 dlc[0] = 2;
7866 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7867 add_p(plci, DLC, dlc);
7868 return 0;
7869 }
7870
7871 if (!bp->length)
7872 {
7873 dbug(1, dprintf("ret default"));
7874 add_p(plci, LLI, lli);
7875 plci->B2_prot = 0 ;
7876 plci->B3_prot = 0 ;
7877 llc[1] = 1;
7878 llc[2] = 4;
7879 add_p(plci, LLC, llc);
7880 dlc[0] = 2;
7881 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7882 add_p(plci, DLC, dlc);
7883 return 0;
7884 }
7885 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7886 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7887
7888 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7889 {
7890 bp_parms[6].length = 0;
7891 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7892 {
7893 dbug(1, dprintf("b-form.!"));
7894 return _WRONG_MESSAGE_FORMAT;
7895 }
7896 }
7897 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7898 {
7899 dbug(1, dprintf("b-form.!"));
7900 return _WRONG_MESSAGE_FORMAT;
7901 }
7902
7903 if (plci->tel == ADV_VOICE)
7904 {
7905 if (GET_WORD(bp_parms[1].info) != 1
7906 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7907 plci->adv_nl = true;
7908 }
7909 else if (plci->tel) return _B2_NOT_SUPPORTED;
7910
7911
7912 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7913 && (GET_WORD(bp_parms[2].info) == B3_RTP)
7914 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7915 {
7916 add_p(plci, LLI, lli);
7917 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7918 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7919 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7920 llc[2] = 4;
7921 add_p(plci, LLC, llc);
7922 dlc[0] = 2;
7923 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7924 dlc[3] = 3;
7925 dlc[4] = 1;
7926 dlc[5] = 7;
7927 dlc[6] = 7;
7928 dlc[7] = 0;
7929 dlc[8] = 0;
7930 for (i = 0; i < bp_parms[4].length; i++)
7931 dlc[9 + i] = bp_parms[4].info[1 + i];
7932 dlc[0] = (byte)(8 + bp_parms[4].length);
7933 add_p(plci, DLC, dlc);
7934 for (i = 0; i < bp_parms[5].length; i++)
7935 nlc[1 + i] = bp_parms[5].info[1 + i];
7936 nlc[0] = (byte)(bp_parms[5].length);
7937 add_p(plci, NLC, nlc);
7938 return 0;
7939 }
7940
7941
7942
7943 if ((GET_WORD(bp_parms[1].info) >= 32)
7944 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7945 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7946 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7947
7948 {
7949 return _B2_NOT_SUPPORTED;
7950 }
7951 if ((GET_WORD(bp_parms[2].info) >= 32)
7952 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7953 {
7954 return _B3_NOT_SUPPORTED;
7955 }
7956 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7957 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7958 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7959 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7960 {
7961 return (add_modem_b23(plci, bp_parms));
7962 }
7963
7964 add_p(plci, LLI, lli);
7965
7966 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7967 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7968 if (plci->B2_prot == 12) SAPI = 0;
7969
7970 if (bp_parms[6].length)
7971 {
7972 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7973 {
7974 return _WRONG_MESSAGE_FORMAT;
7975 }
7976 switch (GET_WORD(global_config[0].info))
7977 {
7978 case 1:
7979 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7980 break;
7981 case 2:
7982 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7983 break;
7984 }
7985 }
7986 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7987
7988
7989 if (plci->B2_prot == B2_PIAFS)
7990 llc[1] = PIAFS_CRC;
7991 else
7992
7993 {
7994 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7995 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7996 }
7997 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7998
7999 add_p(plci, LLC, llc);
8000
8001 dlc[0] = 2;
8002 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8003 header[GET_WORD(bp_parms[2].info)]);
8004
8005 b1_config = &bp_parms[3];
8006 nlc[0] = 0;
8007 if (plci->B3_prot == 4
8008 || plci->B3_prot == 5)
8009 {
8010 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8011 nlc[0] = sizeof(T30_INFO);
8012 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8013 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8014 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8015 if (b1_config->length >= 2)
8016 {
8017 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8018 }
8019 }
8020 b2_config = &bp_parms[4];
8021
8022
8023 if (llc[1] == PIAFS_CRC)
8024 {
8025 if (plci->B3_prot != B3_TRANSPARENT)
8026 {
8027 return _B_STACK_NOT_SUPPORTED;
8028 }
8029 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8030 return _WRONG_MESSAGE_FORMAT;
8031 }
8032 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8033 dlc[3] = 0;
8034 dlc[4] = 0;
8035 dlc[5] = 0;
8036 dlc[6] = 0;
8037 if (b2_config->length >= 7) {
8038 dlc[7] = 7;
8039 dlc[8] = 0;
8040 dlc[9] = b2_config_parms[0].info[0];
8041 dlc[10] = b2_config_parms[1].info[0];
8042 dlc[11] = b2_config_parms[1].info[1];
8043 dlc[12] = b2_config_parms[2].info[0];
8044 dlc[13] = b2_config_parms[2].info[1];
8045 dlc[14] = b2_config_parms[3].info[0];
8046 dlc[15] = b2_config_parms[3].info[1];
8047 dlc[0] = 15;
8048 if (b2_config->length >= 8) {
8049 dlc[7] = 10;
8050 dlc[16] = 2;
8051 dlc[17] = PIAFS_UDATA_ABILITIES;
8052 dlc[18] = b2_config_parms[4].info[0];
8053 dlc[0] = 18;
8054 }
8055 }
8056 else
8057 {
8058 dlc[7] = 7;
8059 dlc[8] = 0;
8060 dlc[9] = 0x03;
8061 dlc[10] = 0x03;
8062 dlc[11] = 0;
8063 dlc[12] = 0;
8064 dlc[13] = 0;
8065 dlc[14] = 0;
8066 dlc[15] = 0;
8067 dlc[0] = 15;
8068 }
8069 add_p(plci, DLC, dlc);
8070 }
8071 else
8072
8073 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8074 {
8075 if (plci->B3_prot != B3_TRANSPARENT)
8076 return _B_STACK_NOT_SUPPORTED;
8077
8078 dlc[0] = 6;
8079 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8080 dlc[3] = 0x08;
8081 dlc[4] = 0x01;
8082 dlc[5] = 127;
8083 dlc[6] = 7;
8084 if (b2_config->length != 0)
8085 {
8086 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8087 return _WRONG_MESSAGE_FORMAT;
8088 }
8089 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8090 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8091 if (b2_config->info[3] != 128)
8092 {
8093 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8094 return _B2_PARM_NOT_SUPPORTED;
8095 }
8096 dlc[5] = (byte)(b2_config->info[3] - 1);
8097 dlc[6] = b2_config->info[4];
8098 if (llc[1] == V120_V42BIS) {
8099 if (b2_config->length >= 10) {
8100 dlc[7] = 6;
8101 dlc[8] = 0;
8102 dlc[9] = b2_config_parms[4].info[0];
8103 dlc[10] = b2_config_parms[4].info[1];
8104 dlc[11] = b2_config_parms[5].info[0];
8105 dlc[12] = b2_config_parms[5].info[1];
8106 dlc[13] = b2_config_parms[6].info[0];
8107 dlc[14] = b2_config_parms[6].info[1];
8108 dlc[0] = 14;
8109 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8110 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8111 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8112 }
8113 else {
8114 dlc[6] = 14;
8115 }
8116 }
8117 }
8118 }
8119 else
8120 {
8121 if (b2_config->length)
8122 {
8123 dbug(1, dprintf("B2-Config"));
8124 if (llc[1] == X75_V42BIS) {
8125 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8126 {
8127 return _WRONG_MESSAGE_FORMAT;
8128 }
8129 }
8130 else {
8131 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8132 {
8133 return _WRONG_MESSAGE_FORMAT;
8134 }
8135 }
8136
8137 if (llc[1] == 6)
8138 {
8139 dlc[0] = 4;
8140 if (b2_config->length >= 1) dlc[2] = b2_config->info[1];
8141 else dlc[2] = 0x01;
8142 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8143 {
8144 SAPI = b2_config->info[2];
8145 }
8146 dlc[1] = SAPI;
8147 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8148 {
8149 dlc[3] = 127;
8150 }
8151 else
8152 {
8153 dlc[3] = 7;
8154 }
8155
8156 if (b2_config->length >= 4) dlc[4] = b2_config->info[4];
8157 else dlc[4] = 1;
8158 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8159 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8160 }
8161 else
8162 {
8163 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8164 dlc[3] = b2_config->info[1];
8165 dlc[4] = b2_config->info[2];
8166 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8167 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8168 return _B2_PARM_NOT_SUPPORTED;
8169 }
8170
8171 dlc[5] = (byte)(b2_config->info[3] - 1);
8172 dlc[6] = b2_config->info[4];
8173 if (dlc[6] > dlc[5]) {
8174 dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8175 return _B2_PARM_NOT_SUPPORTED;
8176 }
8177
8178 if (llc[1] == X75_V42BIS) {
8179 if (b2_config->length >= 10) {
8180 dlc[7] = 6;
8181 dlc[8] = 0;
8182 dlc[9] = b2_config_parms[4].info[0];
8183 dlc[10] = b2_config_parms[4].info[1];
8184 dlc[11] = b2_config_parms[5].info[0];
8185 dlc[12] = b2_config_parms[5].info[1];
8186 dlc[13] = b2_config_parms[6].info[0];
8187 dlc[14] = b2_config_parms[6].info[1];
8188 dlc[0] = 14;
8189 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8190 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8191 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8192 }
8193 else {
8194 dlc[6] = 14;
8195 }
8196
8197 }
8198 else {
8199 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8200 for (i = 0; i < b2_config_parms[4].length; i++)
8201 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8202 }
8203 }
8204 }
8205 }
8206 add_p(plci, DLC, dlc);
8207
8208 b3_config = &bp_parms[5];
8209 if (b3_config->length)
8210 {
8211 if (plci->B3_prot == 4
8212 || plci->B3_prot == 5)
8213 {
8214 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8215 {
8216 return _WRONG_MESSAGE_FORMAT;
8217 }
8218 i = GET_WORD((byte *)(b3_config_parms[0].info));
8219 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8220 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8221 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8222 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8223 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8224 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8225 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8226 {
8227
8228 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8229 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8230 {
8231 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8232 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8233 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8234 }
8235
8236 ((T30_INFO *)&nlc[1])->recording_properties =
8237 T30_RECORDING_WIDTH_ISO_A3 |
8238 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8239 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8240 }
8241 if (plci->B3_prot == 5)
8242 {
8243 if (i & 0x0002)
8244 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8245 if (i & 0x2000)
8246 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8247 if (i & 0x4000)
8248 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8249 if (i & 0x8000)
8250 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8251 if (plci->fax_connect_info_length != 0)
8252 {
8253 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8254 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8255 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8256 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8257 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8258 }
8259 }
8260
8261 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8262 {
8263 if (i < b3_config_parms[2].length)
8264 {
8265 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8266 }
8267 else
8268 {
8269 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8270 }
8271 }
8272 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8273
8274 if (b3_config_parms[3].length)
8275 {
8276
8277 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8278 if (pos != 0)
8279 {
8280 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8281 pos = 0;
8282 else
8283 {
8284 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8285 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8286 len = (byte)b3_config_parms[2].length;
8287 if (len > 20)
8288 len = 20;
8289 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8290 {
8291 for (i = 0; i < len; i++)
8292 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8293 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8294 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8295 }
8296 }
8297 }
8298
8299 len = (byte)b3_config_parms[3].length;
8300 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8301 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8302 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8303 nlc[0] += (byte)(pos + len);
8304 for (i = 0; i < len; i++)
8305 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8306 } else
8307 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8308
8309 plci->nsf_control_bits = 0;
8310 if (plci->B3_prot == 5)
8311 {
8312 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8313 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000))
8314 {
8315 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8316 }
8317 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8318 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000))
8319 {
8320 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8321 }
8322 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8323 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8324 {
8325 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8326 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8327 {
8328 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8329 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8330 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8331 }
8332 len = nlc[0];
8333 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8334 if (pos < plci->fax_connect_info_length)
8335 {
8336 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8337 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8338 }
8339 else
8340 nlc[++len] = 0;
8341 if (pos < plci->fax_connect_info_length)
8342 {
8343 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8344 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8345 }
8346 else
8347 nlc[++len] = 0;
8348 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8349 & (1L << PRIVATE_FAX_NONSTANDARD))
8350 {
8351 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8352 {
8353 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8354 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8355 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8356 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8357 }
8358 else
8359 {
8360 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8361 {
8362 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8363 nlc[++len] = 0;
8364 }
8365 else
8366 {
8367 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8368 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8369 nlc[++len] = (byte)(b3_config_parms[4].length);
8370 for (i = 0; i < b3_config_parms[4].length; i++)
8371 nlc[++len] = b3_config_parms[4].info[1 + i];
8372 }
8373 }
8374 }
8375 nlc[0] = len;
8376 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8377 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8378 {
8379 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8380 }
8381 }
8382 }
8383
8384 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8385 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8386 for (i = 0; i < len; i++)
8387 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8388 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8389 i += ((T30_INFO *)&nlc[1])->head_line_len;
8390 while (i < nlc[0])
8391 plci->fax_connect_info_buffer[len++] = nlc[++i];
8392 plci->fax_connect_info_length = len;
8393 }
8394 else
8395 {
8396 nlc[0] = 14;
8397 if (b3_config->length != 16)
8398 return _B3_PARM_NOT_SUPPORTED;
8399 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8400 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8401 return _B3_PARM_NOT_SUPPORTED;
8402 nlc[13] = b3_config->info[13];
8403 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8404 return _B3_PARM_NOT_SUPPORTED;
8405 nlc[14] = b3_config->info[15];
8406 }
8407 }
8408 else
8409 {
8410 if (plci->B3_prot == 4
8411 || plci->B3_prot == 5 ) return _B3_PARM_NOT_SUPPORTED;
8412 }
8413 add_p(plci, NLC, nlc);
8414 return 0;
8415}
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8433{
8434 static byte lli[12] = {1,1};
8435 static byte llc[3] = {2,0,0};
8436 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8437 API_PARSE mdm_config[2];
8438 word i;
8439 word b2_config = 0;
8440
8441 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8442 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8443
8444 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8445 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8446 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8447 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8448 {
8449 return (_B_STACK_NOT_SUPPORTED);
8450 }
8451 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8452 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8453 {
8454 return (_B_STACK_NOT_SUPPORTED);
8455 }
8456
8457 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8458 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8459
8460 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8461 {
8462 if (api_parse(&bp_parms[4].info[1],
8463 (word)bp_parms[4].length, "w",
8464 mdm_config))
8465 {
8466 return (_WRONG_MESSAGE_FORMAT);
8467 }
8468 b2_config = GET_WORD(mdm_config[0].info);
8469 }
8470
8471
8472
8473 lli[0] = 1;
8474 lli[1] = 1;
8475 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8476 lli[1] |= 2;
8477 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8478 lli[1] |= 4;
8479
8480 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8481 lli[1] |= 0x10;
8482 if (plci->rx_dma_descriptor <= 0) {
8483 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8484 if (plci->rx_dma_descriptor >= 0)
8485 plci->rx_dma_descriptor++;
8486 }
8487 if (plci->rx_dma_descriptor > 0) {
8488 lli[1] |= 0x40;
8489 lli[0] = 6;
8490 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8491 lli[3] = (byte)plci->rx_dma_magic;
8492 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8493 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8494 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8495 }
8496 }
8497
8498 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8499 lli[1] |= 0x20;
8500 }
8501
8502 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8503 10 : 9;
8504 llc[2] = 4;
8505 add_p(plci, LLI, lli);
8506 add_p(plci, LLC, llc);
8507 i = 1;
8508 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8509 i += 2;
8510 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8511 {
8512 if (bp_parms[4].length)
8513 {
8514 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8515 dlc[i++] = 3;
8516 dlc[i++] = 1;
8517 dlc[i++] = 7;
8518 dlc[i++] = 7;
8519 dlc[i++] = 0;
8520 dlc[i++] = 0;
8521
8522 if (b2_config & MDM_B2_DISABLE_V42bis)
8523 {
8524 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8525 }
8526 if (b2_config & MDM_B2_DISABLE_MNP)
8527 {
8528 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8529 }
8530 if (b2_config & MDM_B2_DISABLE_TRANS)
8531 {
8532 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8533 }
8534 if (b2_config & MDM_B2_DISABLE_V42)
8535 {
8536 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8537 }
8538 if (b2_config & MDM_B2_DISABLE_COMP)
8539 {
8540 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8541 }
8542 i++;
8543 }
8544 }
8545 else
8546 {
8547 dlc[i++] = 3;
8548 dlc[i++] = 1;
8549 dlc[i++] = 7;
8550 dlc[i++] = 7;
8551 dlc[i++] = 0;
8552 dlc[i++] = 0;
8553 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8554 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8555 DLC_MODEMPROT_DISABLE_V42_DETECT |
8556 DLC_MODEMPROT_DISABLE_COMPRESSION;
8557 }
8558 dlc[0] = (byte)(i - 1);
8559
8560 add_p(plci, DLC, dlc);
8561 return (0);
8562}
8563
8564
8565
8566
8567
8568
8569static void sig_req(PLCI *plci, byte req, byte Id)
8570{
8571 if (!plci) return;
8572 if (plci->adapter->adapter_disabled) return;
8573 dbug(1, dprintf("sig_req(%x)", req));
8574 if (req == REMOVE)
8575 plci->sig_remove_id = plci->Sig.Id;
8576 if (plci->req_in == plci->req_in_start) {
8577 plci->req_in += 2;
8578 plci->RBuffer[plci->req_in++] = 0;
8579 }
8580 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8581 plci->RBuffer[plci->req_in++] = Id;
8582 plci->RBuffer[plci->req_in++] = req;
8583 plci->RBuffer[plci->req_in++] = 0;
8584 plci->req_in_start = plci->req_in;
8585}
8586
8587
8588
8589
8590
8591static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8592{
8593 if (!plci) return;
8594 if (plci->adapter->adapter_disabled) return;
8595 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8596 if (req == REMOVE)
8597 {
8598 plci->nl_remove_id = plci->NL.Id;
8599 ncci_remove(plci, 0, (byte)(ncci != 0));
8600 ncci = 0;
8601 }
8602 if (plci->req_in == plci->req_in_start) {
8603 plci->req_in += 2;
8604 plci->RBuffer[plci->req_in++] = 0;
8605 }
8606 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8607 plci->RBuffer[plci->req_in++] = 1;
8608 plci->RBuffer[plci->req_in++] = req;
8609 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];
8610 plci->req_in_start = plci->req_in;
8611}
8612
8613static void send_req(PLCI *plci)
8614{
8615 ENTITY *e;
8616 word l;
8617
8618
8619 if (!plci) return;
8620 if (plci->adapter->adapter_disabled) return;
8621 channel_xmit_xon(plci);
8622
8623
8624 if (plci->req_in == plci->req_out) return;
8625 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8626
8627 if (plci->nl_req || plci->sig_req) return;
8628
8629 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8630 plci->req_out += 2;
8631 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8632 plci->req_out += l;
8633 if (plci->RBuffer[plci->req_out] == 1)
8634 {
8635 e = &plci->NL;
8636 plci->req_out++;
8637 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8638 e->ReqCh = plci->RBuffer[plci->req_out++];
8639 if (!(e->Id & 0x1f))
8640 {
8641 e->Id = NL_ID;
8642 plci->RBuffer[plci->req_out - 4] = CAI;
8643 plci->RBuffer[plci->req_out - 3] = 1;
8644 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8645 plci->RBuffer[plci->req_out - 1] = 0;
8646 l += 3;
8647 plci->nl_global_req = plci->nl_req;
8648 }
8649 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8650 }
8651 else
8652 {
8653 e = &plci->Sig;
8654 if (plci->RBuffer[plci->req_out])
8655 e->Id = plci->RBuffer[plci->req_out];
8656 plci->req_out++;
8657 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8658 e->ReqCh = plci->RBuffer[plci->req_out++];
8659 if (!(e->Id & 0x1f))
8660 plci->sig_global_req = plci->sig_req;
8661 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8662 }
8663 plci->XData[0].PLength = l;
8664 e->X = plci->XData;
8665 plci->adapter->request(e);
8666 dbug(1, dprintf("send_ok"));
8667}
8668
8669static void send_data(PLCI *plci)
8670{
8671 DIVA_CAPI_ADAPTER *a;
8672 DATA_B3_DESC *data;
8673 NCCI *ncci_ptr;
8674 word ncci;
8675
8676 if (!plci->nl_req && plci->ncci_ring_list)
8677 {
8678 a = plci->adapter;
8679 ncci = plci->ncci_ring_list;
8680 do
8681 {
8682 ncci = a->ncci_next[ncci];
8683 ncci_ptr = &(a->ncci[ncci]);
8684 if (!(a->ncci_ch[ncci]
8685 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8686 {
8687 if (ncci_ptr->data_pending)
8688 {
8689 if ((a->ncci_state[ncci] == CONNECTED)
8690 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8691 || (plci->send_disc == ncci))
8692 {
8693 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8694 if ((plci->B2_prot == B2_V120_ASYNC)
8695 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8696 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8697 {
8698 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8699 plci->NData[1].PLength = data->Length;
8700 if (data->Flags & 0x10)
8701 plci->NData[0].P = v120_break_header;
8702 else
8703 plci->NData[0].P = v120_default_header;
8704 plci->NData[0].PLength = 1;
8705 plci->NL.XNum = 2;
8706 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8707 }
8708 else
8709 {
8710 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8711 plci->NData[0].PLength = data->Length;
8712 if (data->Flags & 0x10)
8713 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8714
8715 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8716 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8717
8718 else
8719 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8720 }
8721 plci->NL.X = plci->NData;
8722 plci->NL.ReqCh = a->ncci_ch[ncci];
8723 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8724 plci->data_sent = true;
8725 plci->data_sent_ptr = data->P;
8726 a->request(&plci->NL);
8727 }
8728 else {
8729 cleanup_ncci_data(plci, ncci);
8730 }
8731 }
8732 else if (plci->send_disc == ncci)
8733 {
8734
8735 plci->NData[0].PLength = 0;
8736 plci->NL.ReqCh = a->ncci_ch[ncci];
8737 plci->NL.Req = plci->nl_req = N_DISC;
8738 a->request(&plci->NL);
8739 plci->command = _DISCONNECT_B3_R;
8740 plci->send_disc = 0;
8741 }
8742 }
8743 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8744 plci->ncci_ring_list = ncci;
8745 }
8746}
8747
8748static void listen_check(DIVA_CAPI_ADAPTER *a)
8749{
8750 word i, j;
8751 PLCI *plci;
8752 byte activnotifiedcalls = 0;
8753
8754 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8755 if (!remove_started && !a->adapter_disabled)
8756 {
8757 for (i = 0; i < a->max_plci; i++)
8758 {
8759 plci = &(a->plci[i]);
8760 if (plci->notifiedcall) activnotifiedcalls++;
8761 }
8762 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8763
8764 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8765 if ((j = get_plci(a))) {
8766 a->listen_active++;
8767 plci = &a->plci[j - 1];
8768 plci->State = LISTENING;
8769
8770 add_p(plci, OAD, "\x01\xfd");
8771
8772 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8773
8774 add_p(plci, CAI, "\x01\xc0");
8775 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8776 add_p(plci, LLI, "\x01\xc4");
8777 add_p(plci, SHIFT | 6, NULL);
8778 add_p(plci, SIN, "\x02\x00\x00");
8779 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;
8780 sig_req(plci, ASSIGN, DSIG_ID);
8781 send_req(plci);
8782 }
8783 }
8784 }
8785}
8786
8787
8788
8789
8790
8791static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8792{
8793 word ploc;
8794 byte w;
8795 byte wlen;
8796 byte codeset, lock;
8797 byte *in;
8798 word i;
8799 word code;
8800 word mIEindex = 0;
8801 ploc = 0;
8802 codeset = 0;
8803 lock = 0;
8804
8805 in = plci->Sig.RBuffer->P;
8806 for (i = 0; i < parms_id[0]; i++)
8807 {
8808 parms[i] = (byte *)"";
8809 }
8810 for (i = 0; i < multiIEsize; i++)
8811 {
8812 parms[i] = (byte *)"";
8813 }
8814
8815 while (ploc < plci->Sig.RBuffer->length - 1) {
8816
8817
8818 w = in[ploc];
8819
8820 if (w & 0x80) {
8821
8822
8823 wlen = 0;
8824 }
8825 else {
8826 wlen = (byte)(in[ploc + 1] + 1);
8827 }
8828
8829 if ((ploc + wlen) > 270) return;
8830 if (lock & 0x80) lock &= 0x7f;
8831 else codeset = lock;
8832
8833 if ((w & 0xf0) == SHIFT) {
8834 codeset = in[ploc];
8835 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8836 codeset &= 7;
8837 lock |= 0x80;
8838 }
8839 else {
8840 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8841 else code = w;
8842 code |= (codeset << 8);
8843
8844 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8845
8846 if (i < parms_id[0] + 1) {
8847 if (!multiIEsize) {
8848 mIEindex = i - 1;
8849 }
8850
8851 parms[mIEindex] = &in[ploc + 1];
8852 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8853 if (parms_id[i] == OAD
8854 || parms_id[i] == CONN_NR
8855 || parms_id[i] == CAD) {
8856 if (in[ploc + 2] & 0x80) {
8857 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8858 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8859 in[ploc + 2] = 0x80;
8860 parms[mIEindex] = &in[ploc];
8861 }
8862 }
8863 mIEindex++;
8864 }
8865 }
8866
8867 ploc += (wlen + 1);
8868 }
8869 return;
8870}
8871
8872
8873
8874
8875
8876static byte ie_compare(byte *ie1, byte *ie2)
8877{
8878 word i;
8879 if (!ie1 || !ie2) return false;
8880 if (!ie1[0]) return false;
8881 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8882 return true;
8883}
8884
8885static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8886{
8887 word i;
8888 word j;
8889
8890 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8891
8892 for (j = 16; j < 29 &&
8893 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8894 if (j == 29) return i;
8895 return j;
8896}
8897
8898
8899static byte AddInfo(byte **add_i,
8900 byte **fty_i,
8901 byte *esc_chi,
8902 byte *facility)
8903{
8904 byte i;
8905 byte j;
8906 byte k;
8907 byte flen;
8908 byte len = 0;
8909
8910
8911
8912 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8913 {
8914 add_i[0] = (byte *)"\x02\x02\x00";
8915 }
8916
8917 else
8918 {
8919 add_i[0] = (byte *)"";
8920 }
8921 if (!fty_i[0][0])
8922 {
8923 add_i[3] = (byte *)"";
8924 }
8925 else
8926 {
8927 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8928 {
8929 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8930 len += fty_i[i][0];
8931 len += 2;
8932 flen = fty_i[i][0];
8933 facility[j++] = 0x1c;
8934 for (k = 0; k <= flen; k++, j++)
8935 {
8936 facility[j] = fty_i[i][k];
8937
8938 }
8939 }
8940 facility[0] = len;
8941 add_i[3] = facility;
8942 }
8943
8944 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8945 len += 4;
8946 return (len);
8947}
8948
8949
8950
8951
8952
8953static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8954{
8955 byte voice_chi[] = "\x02\x18\x01";
8956 byte channel;
8957
8958 channel = chi[chi[0]] & 0x3;
8959 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8960 voice_chi[2] = (channel) ? channel : 1;
8961 add_p(plci, FTY, "\x02\x01\x07");
8962 add_p(plci, ESC, voice_chi);
8963 sig_req(plci, TEL_CTRL, 0);
8964 send_req(plci);
8965 if (a->AdvSignalPLCI)
8966 {
8967 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8968 }
8969}
8970
8971static void VoiceChannelOff(PLCI *plci)
8972{
8973 dbug(1, dprintf("ExtDevOFF"));
8974 add_p(plci, FTY, "\x02\x01\x08");
8975 sig_req(plci, TEL_CTRL, 0);
8976 send_req(plci);
8977 if (plci->adapter->AdvSignalPLCI)
8978 {
8979 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8980 }
8981}
8982
8983
8984static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8985 byte hook_listen)
8986{
8987 word j;
8988 PLCI *splci;
8989
8990
8991
8992
8993
8994
8995 if (a->profile.Global_Options & HANDSET)
8996 {
8997
8998 if (a->AdvCodecFLAG)
8999 {
9000 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9001 {
9002 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9003 return 0x2001;
9004 }
9005 if (plci != NULL)
9006 {
9007 a->AdvSignalPLCI = plci;
9008 plci->tel = ADV_VOICE;
9009 }
9010 return 0;
9011 }
9012 if ((j = get_plci(a)))
9013 {
9014 splci = &a->plci[j - 1];
9015 splci->tel = CODEC_PERMANENT;
9016
9017
9018
9019
9020 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9021 else
9022 {
9023 splci->State = ADVANCED_VOICE_NOSIG;
9024 if (plci)
9025 {
9026 plci->spoofed_msg = SPOOFING_REQUIRED;
9027 }
9028
9029 }
9030 if (plci != NULL)
9031 {
9032 a->AdvSignalPLCI = plci;
9033 plci->tel = ADV_VOICE;
9034 }
9035 a->AdvSignalAppl = appl;
9036 a->AdvCodecFLAG = true;
9037 a->AdvCodecPLCI = splci;
9038 add_p(splci, CAI, "\x01\x15");
9039 add_p(splci, LLI, "\x01\x00");
9040 add_p(splci, ESC, "\x02\x18\x00");
9041 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9042 splci->internal_command = PERM_COD_ASSIGN;
9043 dbug(1, dprintf("Codec Assign"));
9044 sig_req(splci, ASSIGN, DSIG_ID);
9045 send_req(splci);
9046 }
9047 else
9048 {
9049 return 0x2001;
9050 }
9051 }
9052 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9053 {
9054 if (hook_listen) return 0x300B;
9055
9056 if (plci != NULL) plci->tel = CODEC;
9057 dbug(1, dprintf("S/SCOM codec"));
9058
9059
9060
9061 if (!a->scom_appl_disable) {
9062 if ((j = get_plci(a))) {
9063 splci = &a->plci[j - 1];
9064 add_p(splci, CAI, "\x01\x80");
9065 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9066 sig_req(splci, ASSIGN, 0xC0);
9067 send_req(splci);
9068 a->scom_appl_disable = true;
9069 }
9070 else{
9071 return 0x2001;
9072 }
9073 }
9074 }
9075 else return 0x300B;
9076
9077 return 0;
9078}
9079
9080
9081static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9082{
9083
9084 dbug(1, dprintf("CodecIdCheck"));
9085
9086 if (a->AdvSignalPLCI == plci)
9087 {
9088 dbug(1, dprintf("PLCI owns codec"));
9089 VoiceChannelOff(a->AdvCodecPLCI);
9090 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9091 {
9092 dbug(1, dprintf("remove temp codec PLCI"));
9093 plci_remove(a->AdvCodecPLCI);
9094 a->AdvCodecFLAG = 0;
9095 a->AdvCodecPLCI = NULL;
9096 a->AdvSignalAppl = NULL;
9097 }
9098 a->AdvSignalPLCI = NULL;
9099 }
9100}
9101
9102
9103
9104
9105static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9106 IDI_SYNC_REQ *preq) {
9107 a->sdram_bar = 0;
9108 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9109 ENTITY *e = (ENTITY *)preq;
9110
9111 e->user[0] = a->Id - 1;
9112 preq->xdi_sdram_bar.info.bar = 0;
9113 preq->xdi_sdram_bar.Req = 0;
9114 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9115
9116 (*(a->request))(e);
9117
9118 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9119 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9120 }
9121}
9122
9123
9124
9125
9126static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9127 IDI_SYNC_REQ *preq;
9128 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9129
9130 char features[4];
9131 preq = (IDI_SYNC_REQ *)&buffer[0];
9132
9133 if (!diva_xdi_extended_features) {
9134 ENTITY *e = (ENTITY *)preq;
9135 diva_xdi_extended_features |= 0x80000000;
9136
9137 e->user[0] = a->Id - 1;
9138 preq->xdi_extended_features.Req = 0;
9139 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9140 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9141 preq->xdi_extended_features.info.features = &features[0];
9142
9143 (*(a->request))(e);
9144
9145 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9146
9147
9148
9149 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9150 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9151 }
9152 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9153 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9154 dbug(1, dprintf("XDI provides RxDMA"));
9155 }
9156 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9157 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9158 }
9159 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9160 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9161 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9162 }
9163
9164 }
9165 }
9166
9167 diva_ask_for_xdi_sdram_bar(a, preq);
9168}
9169
9170
9171
9172
9173
9174
9175void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9176{
9177 word j;
9178 PLCI *splci;
9179
9180 if (a->automatic_law) {
9181 return;
9182 }
9183 if ((j = get_plci(a))) {
9184 diva_get_extended_adapter_features(a);
9185 splci = &a->plci[j - 1];
9186 a->automatic_lawPLCI = splci;
9187 a->automatic_law = 1;
9188 add_p(splci, CAI, "\x01\x80");
9189 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9190 splci->internal_command = USELAW_REQ;
9191 splci->command = 0;
9192 splci->number = 0;
9193 sig_req(splci, ASSIGN, DSIG_ID);
9194 send_req(splci);
9195 }
9196}
9197
9198
9199word CapiRelease(word Id)
9200{
9201 word i, j, appls_found;
9202 PLCI *plci;
9203 APPL *this;
9204 DIVA_CAPI_ADAPTER *a;
9205
9206 if (!Id)
9207 {
9208 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9209 return (_WRONG_APPL_ID);
9210 }
9211
9212 this = &application[Id - 1];
9213
9214 for (i = 0, appls_found = 0; i < max_appl; i++)
9215 {
9216 if (application[i].Id)
9217 {
9218 appls_found++;
9219 }
9220 }
9221
9222 for (i = 0; i < max_adapter; i++)
9223 {
9224 a = &adapter[i];
9225 if (a->request)
9226 {
9227 a->Info_Mask[Id - 1] = 0;
9228 a->CIP_Mask[Id - 1] = 0;
9229 a->Notification_Mask[Id - 1] = 0;
9230 a->codec_listen[Id - 1] = NULL;
9231 a->requested_options_table[Id - 1] = 0;
9232 for (j = 0; j < a->max_plci; j++)
9233 {
9234 plci = &a->plci[j];
9235 if (plci->Id)
9236 {
9237 if (plci->State == INC_CON_PENDING
9238 || plci->State == INC_CON_ALERT)
9239 {
9240 if (test_bit(Id - 1, plci->c_ind_mask_table))
9241 {
9242 __clear_bit(Id - 1, plci->c_ind_mask_table);
9243 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9244 {
9245 sig_req(plci, HANGUP, 0);
9246 send_req(plci);
9247 plci->State = OUTG_DIS_PENDING;
9248 }
9249 }
9250 }
9251 if (test_bit(Id - 1, plci->c_ind_mask_table))
9252 {
9253 __clear_bit(Id - 1, plci->c_ind_mask_table);
9254 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9255 {
9256 if (!plci->appl)
9257 {
9258 plci_remove(plci);
9259 plci->State = IDLE;
9260 }
9261 }
9262 }
9263 if (plci->appl == this)
9264 {
9265 plci->appl = NULL;
9266 plci_remove(plci);
9267 plci->State = IDLE;
9268 }
9269 }
9270 }
9271 listen_check(a);
9272
9273 if (a->flag_dynamic_l1_down)
9274 {
9275 if (appls_found == 1)
9276 {
9277 if ((j = get_plci(a)))
9278 {
9279 plci = &a->plci[j - 1];
9280 plci->command = 0;
9281 add_p(plci, OAD, "\x01\xfd");
9282 add_p(plci, CAI, "\x01\x80");
9283 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9284 add_p(plci, SHIFT | 6, NULL);
9285 add_p(plci, SIN, "\x02\x00\x00");
9286 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9287 sig_req(plci, ASSIGN, DSIG_ID);
9288 add_p(plci, FTY, "\x02\xff\x06");
9289 sig_req(plci, SIG_CTRL, 0);
9290 send_req(plci);
9291 }
9292 }
9293 }
9294 if (a->AdvSignalAppl == this)
9295 {
9296 this->NullCREnable = false;
9297 if (a->AdvCodecPLCI)
9298 {
9299 plci_remove(a->AdvCodecPLCI);
9300 a->AdvCodecPLCI->tel = 0;
9301 a->AdvCodecPLCI->adv_nl = 0;
9302 }
9303 a->AdvSignalAppl = NULL;
9304 a->AdvSignalPLCI = NULL;
9305 a->AdvCodecFLAG = 0;
9306 a->AdvCodecPLCI = NULL;
9307 }
9308 }
9309 }
9310
9311 this->Id = 0;
9312
9313 return GOOD;
9314}
9315
9316static word plci_remove_check(PLCI *plci)
9317{
9318 if (!plci) return true;
9319 if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9320 {
9321 if (plci->Sig.Id == 0xff)
9322 plci->Sig.Id = 0;
9323 if (!plci->Sig.Id)
9324 {
9325 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9326 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9327 if (plci->Id)
9328 {
9329 CodecIdCheck(plci->adapter, plci);
9330 clear_b1_config(plci);
9331 ncci_remove(plci, 0, false);
9332 plci_free_msg_in_queue(plci);
9333 channel_flow_control_remove(plci);
9334 plci->Id = 0;
9335 plci->State = IDLE;
9336 plci->channels = 0;
9337 plci->appl = NULL;
9338 plci->notifiedcall = 0;
9339 }
9340 listen_check(plci->adapter);
9341 return true;
9342 }
9343 }
9344 return false;
9345}
9346
9347
9348
9349
9350static byte plci_nl_busy(PLCI *plci)
9351{
9352
9353 return (plci->nl_req
9354 || (plci->ncci_ring_list
9355 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9356 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9357}
9358
9359
9360
9361
9362
9363
9364
9365static struct
9366{
9367 byte send_mask;
9368 byte listen_mask;
9369 byte character;
9370 byte code;
9371} dtmf_digit_map[] =
9372{
9373 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9374 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9375 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9376 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9377 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9378 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9379 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9380 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9381 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9382 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9383 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9384 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9385 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9386 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9387 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9388 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9389 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9390 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9391 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9392 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9393
9394 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9395 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9396 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9397 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9398 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9399 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9400 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9401 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9402 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9403 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9404 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9405 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9406 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9407 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9408 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9409 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9410 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9411 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9412 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9413 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9414 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9415 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9416 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9417 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9418 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9419 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9420 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9421 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9422 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9423 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9424 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9425 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9426 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9427 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9428 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9429 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9430 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9431 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9432 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9433 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9434 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9435 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9436 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9437 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9438 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9439 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9440 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9441 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9442 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9443 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9444 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9445 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9446
9447};
9448
9449#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9450
9451
9452static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9453{
9454 word min_digit_duration, min_gap_duration;
9455
9456 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9457 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9458 (char *)(FILE_), __LINE__, enable_mask));
9459
9460 if (enable_mask != 0)
9461 {
9462 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9463 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9464 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9465 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9466 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9467 plci->NData[0].PLength = 5;
9468
9469 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9470 plci->NData[0].PLength += 2;
9471 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9472
9473 }
9474 else
9475 {
9476 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9477 plci->NData[0].PLength = 1;
9478
9479 capidtmf_recv_disable(&(plci->capidtmf_state));
9480
9481 }
9482 plci->NData[0].P = plci->internal_req_buffer;
9483 plci->NL.X = plci->NData;
9484 plci->NL.ReqCh = 0;
9485 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9486 plci->adapter->request(&plci->NL);
9487}
9488
9489
9490static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9491{
9492 word w, i;
9493
9494 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9495 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9496 (char *)(FILE_), __LINE__, digit_count));
9497
9498 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9499 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9500 PUT_WORD(&plci->internal_req_buffer[1], w);
9501 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9502 PUT_WORD(&plci->internal_req_buffer[3], w);
9503 for (i = 0; i < digit_count; i++)
9504 {
9505 w = 0;
9506 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9507 && (digit_buffer[i] != dtmf_digit_map[w].character))
9508 {
9509 w++;
9510 }
9511 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9512 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9513 }
9514 plci->NData[0].PLength = 5 + digit_count;
9515 plci->NData[0].P = plci->internal_req_buffer;
9516 plci->NL.X = plci->NData;
9517 plci->NL.ReqCh = 0;
9518 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9519 plci->adapter->request(&plci->NL);
9520}
9521
9522
9523static void dtmf_rec_clear_config(PLCI *plci)
9524{
9525
9526 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9527 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9528 (char *)(FILE_), __LINE__));
9529
9530 plci->dtmf_rec_active = 0;
9531 plci->dtmf_rec_pulse_ms = 0;
9532 plci->dtmf_rec_pause_ms = 0;
9533
9534 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9535
9536}
9537
9538
9539static void dtmf_send_clear_config(PLCI *plci)
9540{
9541
9542 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9543 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9544 (char *)(FILE_), __LINE__));
9545
9546 plci->dtmf_send_requests = 0;
9547 plci->dtmf_send_pulse_ms = 0;
9548 plci->dtmf_send_pause_ms = 0;
9549}
9550
9551
9552static void dtmf_prepare_switch(dword Id, PLCI *plci)
9553{
9554
9555 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9556 UnMapId(Id), (char *)(FILE_), __LINE__));
9557
9558 while (plci->dtmf_send_requests != 0)
9559 dtmf_confirmation(Id, plci);
9560}
9561
9562
9563static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9564{
9565
9566 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9567 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9568
9569 return (GOOD);
9570}
9571
9572
9573static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9574{
9575 word Info;
9576
9577 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9578 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9579
9580 Info = GOOD;
9581 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9582 {
9583 switch (plci->adjust_b_state)
9584 {
9585 case ADJUST_B_RESTORE_DTMF_1:
9586 plci->internal_command = plci->adjust_b_command;
9587 if (plci_nl_busy(plci))
9588 {
9589 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9590 break;
9591 }
9592 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9593 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9594 break;
9595 case ADJUST_B_RESTORE_DTMF_2:
9596 if ((Rc != OK) && (Rc != OK_FC))
9597 {
9598 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9599 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9600 Info = _WRONG_STATE;
9601 break;
9602 }
9603 break;
9604 }
9605 }
9606 return (Info);
9607}
9608
9609
9610static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9611{
9612 word internal_command, Info;
9613 byte mask;
9614 byte result[4];
9615
9616 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9617 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9618 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9619 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9620
9621 Info = GOOD;
9622 result[0] = 2;
9623 PUT_WORD(&result[1], DTMF_SUCCESS);
9624 internal_command = plci->internal_command;
9625 plci->internal_command = 0;
9626 mask = 0x01;
9627 switch (plci->dtmf_cmd)
9628 {
9629
9630 case DTMF_LISTEN_TONE_START:
9631 mask <<= 1;
9632 case DTMF_LISTEN_MF_START:
9633 mask <<= 1;
9634
9635 case DTMF_LISTEN_START:
9636 switch (internal_command)
9637 {
9638 default:
9639 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9640 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9641
9642 case DTMF_COMMAND_1:
9643 if (adjust_b_process(Id, plci, Rc) != GOOD)
9644 {
9645 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9646 UnMapId(Id), (char *)(FILE_), __LINE__));
9647 Info = _FACILITY_NOT_SUPPORTED;
9648 break;
9649 }
9650 if (plci->internal_command)
9651 return;
9652
9653 case DTMF_COMMAND_2:
9654 if (plci_nl_busy(plci))
9655 {
9656 plci->internal_command = DTMF_COMMAND_2;
9657 return;
9658 }
9659 plci->internal_command = DTMF_COMMAND_3;
9660 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9661 return;
9662 case DTMF_COMMAND_3:
9663 if ((Rc != OK) && (Rc != OK_FC))
9664 {
9665 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9666 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9667 Info = _FACILITY_NOT_SUPPORTED;
9668 break;
9669 }
9670
9671 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9672
9673 plci->dtmf_rec_active |= mask;
9674 break;
9675 }
9676 break;
9677
9678
9679 case DTMF_LISTEN_TONE_STOP:
9680 mask <<= 1;
9681 case DTMF_LISTEN_MF_STOP:
9682 mask <<= 1;
9683
9684 case DTMF_LISTEN_STOP:
9685 switch (internal_command)
9686 {
9687 default:
9688 plci->dtmf_rec_active &= ~mask;
9689 if (plci->dtmf_rec_active)
9690 break;
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9716 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9717
9718 case DTMF_COMMAND_3:
9719 if (adjust_b_process(Id, plci, Rc) != GOOD)
9720 {
9721 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9722 UnMapId(Id), (char *)(FILE_), __LINE__));
9723 Info = _FACILITY_NOT_SUPPORTED;
9724 break;
9725 }
9726 if (plci->internal_command)
9727 return;
9728 break;
9729 }
9730 break;
9731
9732
9733 case DTMF_SEND_TONE:
9734 mask <<= 1;
9735 case DTMF_SEND_MF:
9736 mask <<= 1;
9737
9738 case DTMF_DIGITS_SEND:
9739 switch (internal_command)
9740 {
9741 default:
9742 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9743 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9744 DTMF_COMMAND_1);
9745
9746 case DTMF_COMMAND_1:
9747 if (adjust_b_process(Id, plci, Rc) != GOOD)
9748 {
9749 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9750 UnMapId(Id), (char *)(FILE_), __LINE__));
9751 Info = _FACILITY_NOT_SUPPORTED;
9752 break;
9753 }
9754 if (plci->internal_command)
9755 return;
9756
9757 case DTMF_COMMAND_2:
9758 if (plci_nl_busy(plci))
9759 {
9760 plci->internal_command = DTMF_COMMAND_2;
9761 return;
9762 }
9763 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9764 plci->internal_command = DTMF_COMMAND_3;
9765 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9766 return;
9767 case DTMF_COMMAND_3:
9768 if ((Rc != OK) && (Rc != OK_FC))
9769 {
9770 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9771 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9772 if (plci->dtmf_send_requests != 0)
9773 (plci->dtmf_send_requests)--;
9774 Info = _FACILITY_NOT_SUPPORTED;
9775 break;
9776 }
9777 return;
9778 }
9779 break;
9780 }
9781 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9782 "wws", Info, SELECTOR_DTMF, result);
9783}
9784
9785
9786static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9787{
9788 word Info;
9789 word i, j;
9790 byte mask;
9791 API_PARSE dtmf_parms[5];
9792 byte result[40];
9793
9794 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9795 UnMapId(Id), (char *)(FILE_), __LINE__));
9796
9797 Info = GOOD;
9798 result[0] = 2;
9799 PUT_WORD(&result[1], DTMF_SUCCESS);
9800 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9801 {
9802 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9803 UnMapId(Id), (char *)(FILE_), __LINE__));
9804 Info = _FACILITY_NOT_SUPPORTED;
9805 }
9806 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9807 {
9808 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9809 UnMapId(Id), (char *)(FILE_), __LINE__));
9810 Info = _WRONG_MESSAGE_FORMAT;
9811 }
9812
9813 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9814 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9815 {
9816 if (!((a->requested_options_table[appl->Id - 1])
9817 & (1L << PRIVATE_DTMF_TONE)))
9818 {
9819 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9820 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9821 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9822 }
9823 else
9824 {
9825 for (i = 0; i < 32; i++)
9826 result[4 + i] = 0;
9827 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9828 {
9829 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9830 {
9831 if (dtmf_digit_map[i].listen_mask != 0)
9832 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9833 }
9834 }
9835 else
9836 {
9837 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9838 {
9839 if (dtmf_digit_map[i].send_mask != 0)
9840 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9841 }
9842 }
9843 result[0] = 3 + 32;
9844 result[3] = 32;
9845 }
9846 }
9847
9848 else if (plci == NULL)
9849 {
9850 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9851 UnMapId(Id), (char *)(FILE_), __LINE__));
9852 Info = _WRONG_IDENTIFIER;
9853 }
9854 else
9855 {
9856 if (!plci->State
9857 || !plci->NL.Id || plci->nl_remove_id)
9858 {
9859 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9860 UnMapId(Id), (char *)(FILE_), __LINE__));
9861 Info = _WRONG_STATE;
9862 }
9863 else
9864 {
9865 plci->command = 0;
9866 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9867 mask = 0x01;
9868 switch (plci->dtmf_cmd)
9869 {
9870
9871 case DTMF_LISTEN_TONE_START:
9872 case DTMF_LISTEN_TONE_STOP:
9873 mask <<= 1;
9874 case DTMF_LISTEN_MF_START:
9875 case DTMF_LISTEN_MF_STOP:
9876 mask <<= 1;
9877 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9878 & (1L << PRIVATE_DTMF_TONE)))
9879 {
9880 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9881 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9882 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9883 break;
9884 }
9885
9886
9887 case DTMF_LISTEN_START:
9888 case DTMF_LISTEN_STOP:
9889 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9890 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9891 {
9892 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9893 UnMapId(Id), (char *)(FILE_), __LINE__));
9894 Info = _FACILITY_NOT_SUPPORTED;
9895 break;
9896 }
9897 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9898 {
9899 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9900 {
9901 plci->dtmf_rec_pulse_ms = 0;
9902 plci->dtmf_rec_pause_ms = 0;
9903 }
9904 else
9905 {
9906 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9907 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9908 }
9909 }
9910 start_internal_command(Id, plci, dtmf_command);
9911 return (false);
9912
9913
9914 case DTMF_SEND_TONE:
9915 mask <<= 1;
9916 case DTMF_SEND_MF:
9917 mask <<= 1;
9918 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9919 & (1L << PRIVATE_DTMF_TONE)))
9920 {
9921 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9922 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9923 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9924 break;
9925 }
9926
9927
9928 case DTMF_DIGITS_SEND:
9929 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9930 {
9931 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9932 UnMapId(Id), (char *)(FILE_), __LINE__));
9933 Info = _WRONG_MESSAGE_FORMAT;
9934 break;
9935 }
9936 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9937 {
9938 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9939 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9940 }
9941 i = 0;
9942 j = 0;
9943 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9944 {
9945 j = 0;
9946 while ((j < DTMF_DIGIT_MAP_ENTRIES)
9947 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9948 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9949 {
9950 j++;
9951 }
9952 i++;
9953 }
9954 if (j == DTMF_DIGIT_MAP_ENTRIES)
9955 {
9956 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9957 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9958 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9959 break;
9960 }
9961 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9962 {
9963 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9964 UnMapId(Id), (char *)(FILE_), __LINE__));
9965 Info = _WRONG_STATE;
9966 break;
9967 }
9968 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9969 start_internal_command(Id, plci, dtmf_command);
9970 return (false);
9971
9972 default:
9973 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9974 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9975 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9976 }
9977 }
9978 }
9979 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9980 "wws", Info, SELECTOR_DTMF, result);
9981 return (false);
9982}
9983
9984
9985static void dtmf_confirmation(dword Id, PLCI *plci)
9986{
9987 word i;
9988 byte result[4];
9989
9990 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9991 UnMapId(Id), (char *)(FILE_), __LINE__));
9992
9993 result[0] = 2;
9994 PUT_WORD(&result[1], DTMF_SUCCESS);
9995 if (plci->dtmf_send_requests != 0)
9996 {
9997 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9998 "wws", GOOD, SELECTOR_DTMF, result);
9999 (plci->dtmf_send_requests)--;
10000 for (i = 0; i < plci->dtmf_send_requests; i++)
10001 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10002 }
10003}
10004
10005
10006static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10007{
10008 word i, j, n;
10009
10010 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10011 UnMapId(Id), (char *)(FILE_), __LINE__));
10012
10013 n = 0;
10014 for (i = 1; i < length; i++)
10015 {
10016 j = 0;
10017 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10018 && ((msg[i] != dtmf_digit_map[j].code)
10019 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10020 {
10021 j++;
10022 }
10023 if (j < DTMF_DIGIT_MAP_ENTRIES)
10024 {
10025
10026 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10027 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10028 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10029 {
10030 if (n + 1 == i)
10031 {
10032 for (i = length; i > n + 1; i--)
10033 msg[i] = msg[i - 1];
10034 length++;
10035 i++;
10036 }
10037 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10038 }
10039 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10040
10041 msg[++n] = dtmf_digit_map[j].character;
10042 }
10043 }
10044 if (n != 0)
10045 {
10046 msg[0] = (byte) n;
10047 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10048 }
10049}
10050
10051
10052
10053
10054
10055
10056static void dtmf_parameter_write(PLCI *plci)
10057{
10058 word i;
10059 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10060
10061 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10062 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10063 (char *)(FILE_), __LINE__));
10064
10065 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10066 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10067 for (i = 0; i < plci->dtmf_parameter_length; i++)
10068 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10069 add_p(plci, FTY, parameter_buffer);
10070 sig_req(plci, TEL_CTRL, 0);
10071 send_req(plci);
10072}
10073
10074
10075static void dtmf_parameter_clear_config(PLCI *plci)
10076{
10077
10078 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10079 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10080 (char *)(FILE_), __LINE__));
10081
10082 plci->dtmf_parameter_length = 0;
10083}
10084
10085
10086static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10087{
10088
10089 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10090 UnMapId(Id), (char *)(FILE_), __LINE__));
10091
10092}
10093
10094
10095static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10096{
10097
10098 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10099 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10100
10101 return (GOOD);
10102}
10103
10104
10105static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10106{
10107 word Info;
10108
10109 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10110 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10111
10112 Info = GOOD;
10113 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10114 && (plci->dtmf_parameter_length != 0))
10115 {
10116 switch (plci->adjust_b_state)
10117 {
10118 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10119 plci->internal_command = plci->adjust_b_command;
10120 if (plci->sig_req)
10121 {
10122 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10123 break;
10124 }
10125 dtmf_parameter_write(plci);
10126 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10127 break;
10128 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10129 if ((Rc != OK) && (Rc != OK_FC))
10130 {
10131 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10132 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10133 Info = _WRONG_STATE;
10134 break;
10135 }
10136 break;
10137 }
10138 }
10139 return (Info);
10140}
10141
10142
10143
10144
10145
10146
10147
10148LI_CONFIG *li_config_table;
10149word li_total_channels;
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162static byte chi_to_channel(byte *chi, dword *pchannelmap)
10163{
10164 int p;
10165 int i;
10166 dword map;
10167 byte excl;
10168 byte ofs;
10169 byte ch;
10170
10171 if (pchannelmap) *pchannelmap = 0;
10172 if (!chi[0]) return 0xff;
10173 excl = 0;
10174
10175 if (chi[1] & 0x20) {
10176 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd;
10177 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10178 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10179 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10180 if (chi[1] & 0x08) excl = 0x40;
10181
10182
10183 if (chi[1] & 0x40) {
10184 p = i + 1;
10185 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10186 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10187 }
10188
10189
10190 p = i + 1;
10191 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10192 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10193 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10194
10195
10196 if (chi[p] & 0x10) {
10197
10198
10199 if ((chi[0] - p) == 4) ofs = 0;
10200 else if ((chi[0] - p) == 3) ofs = 1;
10201 else return 0xfe;
10202 ch = 0;
10203 map = 0;
10204 for (i = 0; i < 4 && p < chi[0]; i++) {
10205 p++;
10206 ch += 8;
10207 map <<= 8;
10208 if (chi[p]) {
10209 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10210 map |= chi[p];
10211 }
10212 }
10213 ch += ofs;
10214 map <<= ofs;
10215 }
10216 else {
10217
10218
10219 p = i + 1;
10220 ch = chi[p] & 0x3f;
10221 if (pchannelmap) {
10222 if ((byte)(chi[0] - p) > 30) return 0xfe;
10223 map = 0;
10224 for (i = p; i <= chi[0]; i++) {
10225 if ((chi[i] & 0x7f) > 31) return 0xfe;
10226 map |= (1L << (chi[i] & 0x7f));
10227 }
10228 }
10229 else {
10230 if (p != chi[0]) return 0xfe;
10231 if (ch > 31) return 0xfe;
10232 map = (1L << ch);
10233 }
10234 if (chi[p] & 0x40) return 0xfe;
10235 }
10236 if (pchannelmap) *pchannelmap = map;
10237 else if (map != ((dword)(1L << ch))) return 0xfe;
10238 return (byte)(excl | ch);
10239 }
10240 else {
10241 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10242 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10243 if (chi[1] & 0x08) excl = 0x40;
10244
10245 switch (chi[1] | 0x98) {
10246 case 0x98: return 0;
10247 case 0x99:
10248 if (pchannelmap) *pchannelmap = 2;
10249 return excl | 1;
10250 case 0x9a:
10251 if (pchannelmap) *pchannelmap = 4;
10252 return excl | 2;
10253 case 0x9b: return 0xff;
10254 case 0x9c: return 0xfd;
10255 default: return 0xfe;
10256 }
10257 }
10258}
10259
10260
10261static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10262{
10263 DIVA_CAPI_ADAPTER *a;
10264 PLCI *splci;
10265 byte old_id;
10266
10267 a = plci->adapter;
10268 old_id = plci->li_bchannel_id;
10269 if (a->li_pri)
10270 {
10271 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10272 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10273 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10274 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10275 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10276 }
10277 else
10278 {
10279 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10280 {
10281 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10282 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10283 plci->li_bchannel_id = bchannel_id & 0x03;
10284 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10285 {
10286 splci = a->AdvSignalPLCI;
10287 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10288 {
10289 if ((splci->li_bchannel_id != 0)
10290 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10291 {
10292 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10293 }
10294 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10295 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10296 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10297 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10298 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10299 }
10300 }
10301 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10302 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10303 }
10304 }
10305 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10306 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10307 {
10308 mixer_clear_config(plci);
10309 }
10310 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10311 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10312 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10313}
10314
10315
10316static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10317{
10318 DIVA_CAPI_ADAPTER *a;
10319 PLCI *splci;
10320 byte ch, old_id;
10321
10322 a = plci->adapter;
10323 old_id = plci->li_bchannel_id;
10324 ch = chi_to_channel(chi, NULL);
10325 if (!(ch & 0x80))
10326 {
10327 if (a->li_pri)
10328 {
10329 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10330 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10331 plci->li_bchannel_id = (ch & 0x1f) + 1;
10332 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10333 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10334 }
10335 else
10336 {
10337 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10338 {
10339 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10340 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10341 plci->li_bchannel_id = ch & 0x1f;
10342 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10343 {
10344 splci = a->AdvSignalPLCI;
10345 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10346 {
10347 if ((splci->li_bchannel_id != 0)
10348 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10349 {
10350 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10351 }
10352 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10353 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10354 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10355 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10356 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10357 }
10358 }
10359 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10360 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10361 }
10362 }
10363 }
10364 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10365 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10366 {
10367 mixer_clear_config(plci);
10368 }
10369 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10370 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10371 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10372}
10373
10374
10375#define MIXER_MAX_DUMP_CHANNELS 34
10376
10377static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10378{
10379 word n, i, j;
10380 char *p;
10381 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10382
10383 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10384 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10385
10386 for (i = 0; i < li_total_channels; i++)
10387 {
10388 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10389 if (li_config_table[i].chflags != 0)
10390 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10391 else
10392 {
10393 for (j = 0; j < li_total_channels; j++)
10394 {
10395 if (((li_config_table[i].flag_table[j]) != 0)
10396 || ((li_config_table[j].flag_table[i]) != 0))
10397 {
10398 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10399 }
10400 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10401 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10402 {
10403 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10404 }
10405 }
10406 }
10407 }
10408 for (i = 0; i < li_total_channels; i++)
10409 {
10410 for (j = 0; j < li_total_channels; j++)
10411 {
10412 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10413 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10414 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10415 }
10416 }
10417 for (n = 0; n < li_total_channels; n++)
10418 {
10419 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10420 {
10421 for (i = 0; i < li_total_channels; i++)
10422 {
10423 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10424 {
10425 for (j = 0; j < li_total_channels; j++)
10426 {
10427 li_config_table[i].coef_table[j] |=
10428 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10429 }
10430 }
10431 }
10432 }
10433 }
10434 for (i = 0; i < li_total_channels; i++)
10435 {
10436 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10437 {
10438 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10439 for (j = 0; j < li_total_channels; j++)
10440 {
10441 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10442 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10443 }
10444 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10445 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10446 }
10447 }
10448 for (i = 0; i < li_total_channels; i++)
10449 {
10450 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10451 {
10452 for (j = 0; j < li_total_channels; j++)
10453 {
10454 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10455 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10456 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10457 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10458 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10459 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10460 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10461 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10462 }
10463 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10464 {
10465 for (j = 0; j < li_total_channels; j++)
10466 {
10467 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10468 {
10469 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10470 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10471 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10472 }
10473 }
10474 }
10475 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10476 {
10477 for (j = 0; j < li_total_channels; j++)
10478 {
10479 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10480 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10481 }
10482 }
10483 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10484 {
10485 for (j = 0; j < li_total_channels; j++)
10486 {
10487 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10488 {
10489 for (n = 0; n < li_total_channels; n++)
10490 {
10491 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10492 {
10493 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10494 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10495 {
10496 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10497 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10498 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10499 }
10500 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10501 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10502 }
10503 }
10504 }
10505 }
10506 }
10507 }
10508 }
10509 for (i = 0; i < li_total_channels; i++)
10510 {
10511 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10512 {
10513 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10514 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10515 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10516 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10517 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10518 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10519 for (j = 0; j < li_total_channels; j++)
10520 {
10521 if ((li_config_table[i].flag_table[j] &
10522 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10523 || (li_config_table[j].flag_table[i] &
10524 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10525 {
10526 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10527 }
10528 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10529 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10530 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10531 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10532 }
10533 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10534 {
10535 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10536 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10537 }
10538 }
10539 }
10540 for (i = 0; i < li_total_channels; i++)
10541 {
10542 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10543 {
10544 j = 0;
10545 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10546 j++;
10547 if (j < li_total_channels)
10548 {
10549 for (j = 0; j < li_total_channels; j++)
10550 {
10551 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10552 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10553 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10554 }
10555 }
10556 }
10557 }
10558 n = li_total_channels;
10559 if (n > MIXER_MAX_DUMP_CHANNELS)
10560 n = MIXER_MAX_DUMP_CHANNELS;
10561
10562 p = hex_line;
10563 for (j = 0; j < n; j++)
10564 {
10565 if ((j & 0x7) == 0)
10566 *(p++) = ' ';
10567 p = hex_byte_pack(p, li_config_table[j].curchnl);
10568 }
10569 *p = '\0';
10570 dbug(1, dprintf("[%06lx] CURRENT %s",
10571 (dword)(UnMapController(a->Id)), (char *)hex_line));
10572 p = hex_line;
10573 for (j = 0; j < n; j++)
10574 {
10575 if ((j & 0x7) == 0)
10576 *(p++) = ' ';
10577 p = hex_byte_pack(p, li_config_table[j].channel);
10578 }
10579 *p = '\0';
10580 dbug(1, dprintf("[%06lx] CHANNEL %s",
10581 (dword)(UnMapController(a->Id)), (char *)hex_line));
10582 p = hex_line;
10583 for (j = 0; j < n; j++)
10584 {
10585 if ((j & 0x7) == 0)
10586 *(p++) = ' ';
10587 p = hex_byte_pack(p, li_config_table[j].chflags);
10588 }
10589 *p = '\0';
10590 dbug(1, dprintf("[%06lx] CHFLAG %s",
10591 (dword)(UnMapController(a->Id)), (char *)hex_line));
10592 for (i = 0; i < n; i++)
10593 {
10594 p = hex_line;
10595 for (j = 0; j < n; j++)
10596 {
10597 if ((j & 0x7) == 0)
10598 *(p++) = ' ';
10599 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10600 }
10601 *p = '\0';
10602 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10603 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10604 }
10605 for (i = 0; i < n; i++)
10606 {
10607 p = hex_line;
10608 for (j = 0; j < n; j++)
10609 {
10610 if ((j & 0x7) == 0)
10611 *(p++) = ' ';
10612 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10613 }
10614 *p = '\0';
10615 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10616 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10617 }
10618}
10619
10620
10621static struct
10622{
10623 byte mask;
10624 byte line_flags;
10625} mixer_write_prog_pri[] =
10626{
10627 { LI_COEF_CH_CH, 0 },
10628 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10629 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10630 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10631};
10632
10633static struct
10634{
10635 byte from_ch;
10636 byte to_ch;
10637 byte mask;
10638 byte xconnect_override;
10639} mixer_write_prog_bri[] =
10640{
10641 { 0, 0, LI_COEF_CH_CH, 0x01 },
10642 { 1, 0, LI_COEF_CH_CH, 0x01 },
10643 { 0, 0, LI_COEF_PC_CH, 0x80 },
10644 { 1, 0, LI_COEF_PC_CH, 0x01 },
10645 { 2, 0, LI_COEF_CH_CH, 0x00 },
10646 { 3, 0, LI_COEF_CH_CH, 0x00 },
10647 { 0, 0, LI_COEF_CH_PC, 0x80 },
10648 { 1, 0, LI_COEF_CH_PC, 0x01 },
10649 { 0, 0, LI_COEF_PC_PC, 0x01 },
10650 { 1, 0, LI_COEF_PC_PC, 0x01 },
10651 { 2, 0, LI_COEF_CH_PC, 0x00 },
10652 { 3, 0, LI_COEF_CH_PC, 0x00 },
10653 { 0, 2, LI_COEF_CH_CH, 0x00 },
10654 { 1, 2, LI_COEF_CH_CH, 0x00 },
10655 { 0, 2, LI_COEF_PC_CH, 0x00 },
10656 { 1, 2, LI_COEF_PC_CH, 0x00 },
10657 { 2, 2, LI_COEF_CH_CH, 0x00 },
10658 { 3, 2, LI_COEF_CH_CH, 0x00 },
10659 { 1, 1, LI_COEF_CH_CH, 0x01 },
10660 { 0, 1, LI_COEF_CH_CH, 0x01 },
10661 { 1, 1, LI_COEF_PC_CH, 0x80 },
10662 { 0, 1, LI_COEF_PC_CH, 0x01 },
10663 { 3, 1, LI_COEF_CH_CH, 0x00 },
10664 { 2, 1, LI_COEF_CH_CH, 0x00 },
10665 { 1, 1, LI_COEF_CH_PC, 0x80 },
10666 { 0, 1, LI_COEF_CH_PC, 0x01 },
10667 { 1, 1, LI_COEF_PC_PC, 0x01 },
10668 { 0, 1, LI_COEF_PC_PC, 0x01 },
10669 { 3, 1, LI_COEF_CH_PC, 0x00 },
10670 { 2, 1, LI_COEF_CH_PC, 0x00 },
10671 { 1, 3, LI_COEF_CH_CH, 0x00 },
10672 { 0, 3, LI_COEF_CH_CH, 0x00 },
10673 { 1, 3, LI_COEF_PC_CH, 0x00 },
10674 { 0, 3, LI_COEF_PC_CH, 0x00 },
10675 { 3, 3, LI_COEF_CH_CH, 0x00 },
10676 { 2, 3, LI_COEF_CH_CH, 0x00 }
10677};
10678
10679static byte mixer_swapped_index_bri[] =
10680{
10681 18,
10682 19,
10683 20,
10684 21,
10685 22,
10686 23,
10687 24,
10688 25,
10689 26,
10690 27,
10691 28,
10692 29,
10693 30,
10694 31,
10695 32,
10696 33,
10697 34,
10698 35,
10699 0,
10700 1,
10701 2,
10702 3,
10703 4,
10704 5,
10705 6,
10706 7,
10707 8,
10708 9,
10709 10,
10710 11,
10711 12,
10712 13,
10713 14,
10714 15,
10715 16,
10716 17
10717};
10718
10719static struct
10720{
10721 byte mask;
10722 byte from_pc;
10723 byte to_pc;
10724} xconnect_write_prog[] =
10725{
10726 { LI_COEF_CH_CH, false, false },
10727 { LI_COEF_CH_PC, false, true },
10728 { LI_COEF_PC_CH, true, false },
10729 { LI_COEF_PC_PC, true, true }
10730};
10731
10732
10733static void xconnect_query_addresses(PLCI *plci)
10734{
10735 DIVA_CAPI_ADAPTER *a;
10736 word w, ch;
10737 byte *p;
10738
10739 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10740 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10741 (char *)(FILE_), __LINE__));
10742
10743 a = plci->adapter;
10744 if (a->li_pri && ((plci->li_bchannel_id == 0)
10745 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10746 {
10747 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10748 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10749 (char *)(FILE_), __LINE__));
10750 return;
10751 }
10752 p = plci->internal_req_buffer;
10753 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10754 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10755 w = ch;
10756 *(p++) = (byte) w;
10757 *(p++) = (byte)(w >> 8);
10758 w = ch | XCONNECT_CHANNEL_PORT_PC;
10759 *(p++) = (byte) w;
10760 *(p++) = (byte)(w >> 8);
10761 plci->NData[0].P = plci->internal_req_buffer;
10762 plci->NData[0].PLength = p - plci->internal_req_buffer;
10763 plci->NL.X = plci->NData;
10764 plci->NL.ReqCh = 0;
10765 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10766 plci->adapter->request(&plci->NL);
10767}
10768
10769
10770static void xconnect_write_coefs(PLCI *plci, word internal_command)
10771{
10772
10773 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10774 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10775 (char *)(FILE_), __LINE__, internal_command));
10776
10777 plci->li_write_command = internal_command;
10778 plci->li_write_channel = 0;
10779}
10780
10781
10782static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10783{
10784 DIVA_CAPI_ADAPTER *a;
10785 word w, n, i, j, r, s, to_ch;
10786 dword d;
10787 byte *p;
10788 struct xconnect_transfer_address_s *transfer_address;
10789 byte ch_map[MIXER_CHANNELS_BRI];
10790
10791 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10792 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10793
10794 a = plci->adapter;
10795 if ((plci->li_bchannel_id == 0)
10796 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10797 {
10798 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10799 UnMapId(Id), (char *)(FILE_), __LINE__));
10800 return (true);
10801 }
10802 i = a->li_base + (plci->li_bchannel_id - 1);
10803 j = plci->li_write_channel;
10804 p = plci->internal_req_buffer;
10805 if (j != 0)
10806 {
10807 if ((Rc != OK) && (Rc != OK_FC))
10808 {
10809 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10810 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10811 return (false);
10812 }
10813 }
10814 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10815 {
10816 r = 0;
10817 s = 0;
10818 if (j < li_total_channels)
10819 {
10820 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10821 {
10822 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10823 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10824 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10825 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10826 }
10827 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10828 while ((j < li_total_channels)
10829 && ((r == 0)
10830 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10831 || (!li_config_table[j].adapter->li_pri
10832 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10833 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10834 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10835 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10836 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10837 || ((li_config_table[j].adapter->li_base != a->li_base)
10838 && !(r & s &
10839 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10840 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10841 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10842 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10843 {
10844 j++;
10845 if (j < li_total_channels)
10846 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10847 }
10848 }
10849 if (j < li_total_channels)
10850 {
10851 plci->internal_command = plci->li_write_command;
10852 if (plci_nl_busy(plci))
10853 return (true);
10854 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10855 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10856 do
10857 {
10858 if (li_config_table[j].adapter->li_base != a->li_base)
10859 {
10860 r &= s &
10861 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10862 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10863 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10864 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10865 }
10866 n = 0;
10867 do
10868 {
10869 if (r & xconnect_write_prog[n].mask)
10870 {
10871 if (xconnect_write_prog[n].from_pc)
10872 transfer_address = &(li_config_table[j].send_pc);
10873 else
10874 transfer_address = &(li_config_table[j].send_b);
10875 d = transfer_address->card_address.low;
10876 *(p++) = (byte) d;
10877 *(p++) = (byte)(d >> 8);
10878 *(p++) = (byte)(d >> 16);
10879 *(p++) = (byte)(d >> 24);
10880 d = transfer_address->card_address.high;
10881 *(p++) = (byte) d;
10882 *(p++) = (byte)(d >> 8);
10883 *(p++) = (byte)(d >> 16);
10884 *(p++) = (byte)(d >> 24);
10885 d = transfer_address->offset;
10886 *(p++) = (byte) d;
10887 *(p++) = (byte)(d >> 8);
10888 *(p++) = (byte)(d >> 16);
10889 *(p++) = (byte)(d >> 24);
10890 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10891 *(p++) = (byte) w;
10892 *(p++) = (byte)(w >> 8);
10893 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10894 (li_config_table[i].adapter->u_law ?
10895 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10896 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10897 *(p++) = (byte) w;
10898 *(p++) = (byte) 0;
10899 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10900 }
10901 n++;
10902 } while ((n < ARRAY_SIZE(xconnect_write_prog))
10903 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10904 if (n == ARRAY_SIZE(xconnect_write_prog))
10905 {
10906 do
10907 {
10908 j++;
10909 if (j < li_total_channels)
10910 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10911 } while ((j < li_total_channels)
10912 && ((r == 0)
10913 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10914 || (!li_config_table[j].adapter->li_pri
10915 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10916 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10917 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10918 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10919 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10920 || ((li_config_table[j].adapter->li_base != a->li_base)
10921 && !(r & s &
10922 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10923 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10924 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10925 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10926 }
10927 } while ((j < li_total_channels)
10928 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10929 }
10930 else if (j == li_total_channels)
10931 {
10932 plci->internal_command = plci->li_write_command;
10933 if (plci_nl_busy(plci))
10934 return (true);
10935 if (a->li_pri)
10936 {
10937 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10938 w = 0;
10939 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10940 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10941 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10942 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10943 *(p++) = (byte) w;
10944 *(p++) = (byte)(w >> 8);
10945 }
10946 else
10947 {
10948 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10949 w = 0;
10950 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10951 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10952 {
10953 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10954 }
10955 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10956 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10957 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10958 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10959 *(p++) = (byte) w;
10960 *(p++) = (byte)(w >> 8);
10961 for (j = 0; j < sizeof(ch_map); j += 2)
10962 {
10963 if (plci->li_bchannel_id == 2)
10964 {
10965 ch_map[j] = (byte)(j + 1);
10966 ch_map[j + 1] = (byte) j;
10967 }
10968 else
10969 {
10970 ch_map[j] = (byte) j;
10971 ch_map[j + 1] = (byte)(j + 1);
10972 }
10973 }
10974 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10975 {
10976 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10977 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10978 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10979 {
10980 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10981 mixer_write_prog_bri[n].xconnect_override :
10982 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10983 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10984 {
10985 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10986 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10987 }
10988 }
10989 else
10990 {
10991 *p = 0x00;
10992 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10993 {
10994 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10995 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10996 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10997 }
10998 }
10999 p++;
11000 }
11001 }
11002 j = li_total_channels + 1;
11003 }
11004 }
11005 else
11006 {
11007 if (j <= li_total_channels)
11008 {
11009 plci->internal_command = plci->li_write_command;
11010 if (plci_nl_busy(plci))
11011 return (true);
11012 if (j < a->li_base)
11013 j = a->li_base;
11014 if (a->li_pri)
11015 {
11016 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11017 w = 0;
11018 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11019 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11020 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11021 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11022 *(p++) = (byte) w;
11023 *(p++) = (byte)(w >> 8);
11024 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11025 {
11026 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11027 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11028 {
11029 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030 if (w & mixer_write_prog_pri[n].mask)
11031 {
11032 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11033 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11034 }
11035 else
11036 *(p++) = 0x00;
11037 }
11038 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11039 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11040 {
11041 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11042 if (w & mixer_write_prog_pri[n].mask)
11043 {
11044 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11045 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11046 }
11047 else
11048 *(p++) = 0x00;
11049 }
11050 }
11051 }
11052 else
11053 {
11054 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11055 w = 0;
11056 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11057 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11058 {
11059 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11060 }
11061 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11062 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11063 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11064 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11065 *(p++) = (byte) w;
11066 *(p++) = (byte)(w >> 8);
11067 for (j = 0; j < sizeof(ch_map); j += 2)
11068 {
11069 if (plci->li_bchannel_id == 2)
11070 {
11071 ch_map[j] = (byte)(j + 1);
11072 ch_map[j + 1] = (byte) j;
11073 }
11074 else
11075 {
11076 ch_map[j] = (byte) j;
11077 ch_map[j + 1] = (byte)(j + 1);
11078 }
11079 }
11080 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11081 {
11082 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11083 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11084 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11085 {
11086 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11087 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11088 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11089 }
11090 else
11091 {
11092 *p = 0x00;
11093 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11094 {
11095 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11096 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11097 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11098 }
11099 }
11100 p++;
11101 }
11102 }
11103 j = li_total_channels + 1;
11104 }
11105 }
11106 plci->li_write_channel = j;
11107 if (p != plci->internal_req_buffer)
11108 {
11109 plci->NData[0].P = plci->internal_req_buffer;
11110 plci->NData[0].PLength = p - plci->internal_req_buffer;
11111 plci->NL.X = plci->NData;
11112 plci->NL.ReqCh = 0;
11113 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11114 plci->adapter->request(&plci->NL);
11115 }
11116 return (true);
11117}
11118
11119
11120static void mixer_notify_update(PLCI *plci, byte others)
11121{
11122 DIVA_CAPI_ADAPTER *a;
11123 word i, w;
11124 PLCI *notify_plci;
11125 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11126
11127 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11128 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11129 (char *)(FILE_), __LINE__, others));
11130
11131 a = plci->adapter;
11132 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11133 {
11134 if (others)
11135 plci->li_notify_update = true;
11136 i = 0;
11137 do
11138 {
11139 notify_plci = NULL;
11140 if (others)
11141 {
11142 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11143 i++;
11144 if (i < li_total_channels)
11145 notify_plci = li_config_table[i++].plci;
11146 }
11147 else
11148 {
11149 if ((plci->li_bchannel_id != 0)
11150 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11151 {
11152 notify_plci = plci;
11153 }
11154 }
11155 if ((notify_plci != NULL)
11156 && !notify_plci->li_notify_update
11157 && (notify_plci->appl != NULL)
11158 && (notify_plci->State)
11159 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11160 {
11161 notify_plci->li_notify_update = true;
11162 ((CAPI_MSG *) msg)->header.length = 18;
11163 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11164 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11165 ((CAPI_MSG *) msg)->header.number = 0;
11166 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11167 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11168 ((CAPI_MSG *) msg)->header.ncci = 0;
11169 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11170 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11171 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11172 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11173 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11174 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11175 if (w != _QUEUE_FULL)
11176 {
11177 if (w != 0)
11178 {
11179 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11180 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11181 (char *)(FILE_), __LINE__,
11182 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11183 }
11184 notify_plci->li_notify_update = false;
11185 }
11186 }
11187 } while (others && (notify_plci != NULL));
11188 if (others)
11189 plci->li_notify_update = false;
11190 }
11191}
11192
11193
11194static void mixer_clear_config(PLCI *plci)
11195{
11196 DIVA_CAPI_ADAPTER *a;
11197 word i, j;
11198
11199 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11200 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11201 (char *)(FILE_), __LINE__));
11202
11203 plci->li_notify_update = false;
11204 plci->li_plci_b_write_pos = 0;
11205 plci->li_plci_b_read_pos = 0;
11206 plci->li_plci_b_req_pos = 0;
11207 a = plci->adapter;
11208 if ((plci->li_bchannel_id != 0)
11209 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11210 {
11211 i = a->li_base + (plci->li_bchannel_id - 1);
11212 li_config_table[i].curchnl = 0;
11213 li_config_table[i].channel = 0;
11214 li_config_table[i].chflags = 0;
11215 for (j = 0; j < li_total_channels; j++)
11216 {
11217 li_config_table[j].flag_table[i] = 0;
11218 li_config_table[i].flag_table[j] = 0;
11219 li_config_table[i].coef_table[j] = 0;
11220 li_config_table[j].coef_table[i] = 0;
11221 }
11222 if (!a->li_pri)
11223 {
11224 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11225 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11226 {
11227 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11228 li_config_table[i].curchnl = 0;
11229 li_config_table[i].channel = 0;
11230 li_config_table[i].chflags = 0;
11231 for (j = 0; j < li_total_channels; j++)
11232 {
11233 li_config_table[i].flag_table[j] = 0;
11234 li_config_table[j].flag_table[i] = 0;
11235 li_config_table[i].coef_table[j] = 0;
11236 li_config_table[j].coef_table[i] = 0;
11237 }
11238 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11239 {
11240 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11241 li_config_table[i].curchnl = 0;
11242 li_config_table[i].channel = 0;
11243 li_config_table[i].chflags = 0;
11244 for (j = 0; j < li_total_channels; j++)
11245 {
11246 li_config_table[i].flag_table[j] = 0;
11247 li_config_table[j].flag_table[i] = 0;
11248 li_config_table[i].coef_table[j] = 0;
11249 li_config_table[j].coef_table[i] = 0;
11250 }
11251 }
11252 }
11253 }
11254 }
11255}
11256
11257
11258static void mixer_prepare_switch(dword Id, PLCI *plci)
11259{
11260
11261 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11262 UnMapId(Id), (char *)(FILE_), __LINE__));
11263
11264 do
11265 {
11266 mixer_indication_coefs_set(Id, plci);
11267 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11268}
11269
11270
11271static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11272{
11273 DIVA_CAPI_ADAPTER *a;
11274 word i, j;
11275
11276 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11277 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11278
11279 a = plci->adapter;
11280 if ((plci->li_bchannel_id != 0)
11281 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11282 {
11283 i = a->li_base + (plci->li_bchannel_id - 1);
11284 for (j = 0; j < li_total_channels; j++)
11285 {
11286 li_config_table[i].coef_table[j] &= 0xf;
11287 li_config_table[j].coef_table[i] &= 0xf;
11288 }
11289 if (!a->li_pri)
11290 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11291 }
11292 return (GOOD);
11293}
11294
11295
11296static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11297{
11298 DIVA_CAPI_ADAPTER *a;
11299 word Info;
11300
11301 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11302 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11303
11304 Info = GOOD;
11305 a = plci->adapter;
11306 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11307 && (plci->li_bchannel_id != 0)
11308 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11309 {
11310 switch (plci->adjust_b_state)
11311 {
11312 case ADJUST_B_RESTORE_MIXER_1:
11313 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11314 {
11315 plci->internal_command = plci->adjust_b_command;
11316 if (plci_nl_busy(plci))
11317 {
11318 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11319 break;
11320 }
11321 xconnect_query_addresses(plci);
11322 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11323 break;
11324 }
11325 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11326 Rc = OK;
11327
11328 case ADJUST_B_RESTORE_MIXER_2:
11329 case ADJUST_B_RESTORE_MIXER_3:
11330 case ADJUST_B_RESTORE_MIXER_4:
11331 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11332 {
11333 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11334 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11335 Info = _WRONG_STATE;
11336 break;
11337 }
11338 if (Rc == OK)
11339 {
11340 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11341 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11342 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11343 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11344 }
11345 else if (Rc == 0)
11346 {
11347 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11348 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11349 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11350 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11351 }
11352 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11353 {
11354 plci->internal_command = plci->adjust_b_command;
11355 break;
11356 }
11357
11358 case ADJUST_B_RESTORE_MIXER_5:
11359 xconnect_write_coefs(plci, plci->adjust_b_command);
11360 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11361 Rc = OK;
11362
11363 case ADJUST_B_RESTORE_MIXER_6:
11364 if (!xconnect_write_coefs_process(Id, plci, Rc))
11365 {
11366 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11367 UnMapId(Id), (char *)(FILE_), __LINE__));
11368 Info = _FACILITY_NOT_SUPPORTED;
11369 break;
11370 }
11371 if (plci->internal_command)
11372 break;
11373 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11374 case ADJUST_B_RESTORE_MIXER_7:
11375 break;
11376 }
11377 }
11378 return (Info);
11379}
11380
11381
11382static void mixer_command(dword Id, PLCI *plci, byte Rc)
11383{
11384 DIVA_CAPI_ADAPTER *a;
11385 word i, internal_command;
11386
11387 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11388 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11389 plci->li_cmd));
11390
11391 a = plci->adapter;
11392 internal_command = plci->internal_command;
11393 plci->internal_command = 0;
11394 switch (plci->li_cmd)
11395 {
11396 case LI_REQ_CONNECT:
11397 case LI_REQ_DISCONNECT:
11398 case LI_REQ_SILENT_UPDATE:
11399 switch (internal_command)
11400 {
11401 default:
11402 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11403 {
11404 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11405 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11406 }
11407
11408 case MIXER_COMMAND_1:
11409 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11410 {
11411 if (adjust_b_process(Id, plci, Rc) != GOOD)
11412 {
11413 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11414 UnMapId(Id), (char *)(FILE_), __LINE__));
11415 break;
11416 }
11417 if (plci->internal_command)
11418 return;
11419 }
11420 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11421 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11422 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11423 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11424 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11425 {
11426 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11427 }
11428 else
11429 {
11430 do
11431 {
11432 mixer_indication_coefs_set(Id, plci);
11433 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11434 }
11435
11436 case MIXER_COMMAND_2:
11437 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11438 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11439 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11440 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11441 {
11442 if (!xconnect_write_coefs_process(Id, plci, Rc))
11443 {
11444 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11445 UnMapId(Id), (char *)(FILE_), __LINE__));
11446 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11447 {
11448 do
11449 {
11450 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11451 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11452 i = (plci->li_plci_b_write_pos == 0) ?
11453 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11454 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11455 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11456 }
11457 break;
11458 }
11459 if (plci->internal_command)
11460 return;
11461 }
11462 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11463 {
11464 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11465 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11466 }
11467
11468 case MIXER_COMMAND_3:
11469 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11470 {
11471 if (adjust_b_process(Id, plci, Rc) != GOOD)
11472 {
11473 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11474 UnMapId(Id), (char *)(FILE_), __LINE__));
11475 break;
11476 }
11477 if (plci->internal_command)
11478 return;
11479 }
11480 break;
11481 }
11482 break;
11483 }
11484 if ((plci->li_bchannel_id == 0)
11485 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11486 {
11487 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11488 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11489 }
11490 else
11491 {
11492 i = a->li_base + (plci->li_bchannel_id - 1);
11493 li_config_table[i].curchnl = plci->li_channel_bits;
11494 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11495 {
11496 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11497 li_config_table[i].curchnl = plci->li_channel_bits;
11498 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11499 {
11500 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11501 li_config_table[i].curchnl = plci->li_channel_bits;
11502 }
11503 }
11504 }
11505}
11506
11507
11508static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11509 dword plci_b_id, byte connect, dword li_flags)
11510{
11511 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11512 PLCI *plci_b;
11513 DIVA_CAPI_ADAPTER *a_b;
11514
11515 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11516 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11517 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11518 if (!a->li_pri && (plci->tel == ADV_VOICE)
11519 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11520 {
11521 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11522 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11523 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11524 }
11525 else
11526 {
11527 ch_a_v = ch_a;
11528 ch_a_s = ch_a;
11529 }
11530 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11531 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11532 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11533 {
11534 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11535 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11536 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11537 }
11538 else
11539 {
11540 ch_b_v = ch_b;
11541 ch_b_s = ch_b;
11542 }
11543 if (connect)
11544 {
11545 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11546 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11547 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11548 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11549 }
11550 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11551 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11552 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11553 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11554 if (ch_a_v == ch_b_v)
11555 {
11556 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11557 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11558 }
11559 else
11560 {
11561 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11562 {
11563 for (i = 0; i < li_total_channels; i++)
11564 {
11565 if (i != ch_a_v)
11566 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11567 }
11568 }
11569 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11570 {
11571 for (i = 0; i < li_total_channels; i++)
11572 {
11573 if (i != ch_a_s)
11574 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11575 }
11576 }
11577 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11578 {
11579 for (i = 0; i < li_total_channels; i++)
11580 {
11581 if (i != ch_a_v)
11582 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11583 }
11584 }
11585 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11586 {
11587 for (i = 0; i < li_total_channels; i++)
11588 {
11589 if (i != ch_a_s)
11590 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11591 }
11592 }
11593 }
11594 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11595 {
11596 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11597 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11598 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11599 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11600 }
11601 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11602 {
11603 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11604 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11605 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11606 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11607 }
11608 if (li_flags & LI_FLAG_MONITOR_A)
11609 {
11610 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11611 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11612 }
11613 if (li_flags & LI_FLAG_MONITOR_B)
11614 {
11615 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11616 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11617 }
11618 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11619 {
11620 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11621 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11622 }
11623 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11624 {
11625 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11626 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11627 }
11628 if (li_flags & LI_FLAG_MIX_A)
11629 {
11630 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11631 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11632 }
11633 if (li_flags & LI_FLAG_MIX_B)
11634 {
11635 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11636 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11637 }
11638 if (ch_a_v != ch_a_s)
11639 {
11640 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11641 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11642 }
11643 if (ch_b_v != ch_b_s)
11644 {
11645 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11646 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11647 }
11648}
11649
11650
11651static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11652 dword plci_b_id, byte connect, dword li_flags)
11653{
11654 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11655 PLCI *plci_b;
11656 DIVA_CAPI_ADAPTER *a_b;
11657
11658 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11659 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11660 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11661 if (!a->li_pri && (plci->tel == ADV_VOICE)
11662 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11663 {
11664 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11665 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11667 }
11668 else
11669 {
11670 ch_a_v = ch_a;
11671 ch_a_s = ch_a;
11672 }
11673 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11674 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11675 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11676 {
11677 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11678 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11679 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11680 }
11681 else
11682 {
11683 ch_b_v = ch_b;
11684 ch_b_s = ch_b;
11685 }
11686 if (connect)
11687 {
11688 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11689 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11690 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11691 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11692 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11693 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11694 }
11695 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11696 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11697 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11698 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11699 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11700 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11701 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11702 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11703 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11704 {
11705 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11706 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11707 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11708 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11709 }
11710 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11711 {
11712 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11713 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11714 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11715 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11716 }
11717 if (li_flags & LI2_FLAG_MONITOR_B)
11718 {
11719 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11720 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11721 }
11722 if (li_flags & LI2_FLAG_MIX_B)
11723 {
11724 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11725 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11726 }
11727 if (li_flags & LI2_FLAG_MONITOR_X)
11728 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11729 if (li_flags & LI2_FLAG_MIX_X)
11730 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11731 if (li_flags & LI2_FLAG_LOOP_B)
11732 {
11733 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11734 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11735 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11736 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11737 }
11738 if (li_flags & LI2_FLAG_LOOP_PC)
11739 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11740 if (li_flags & LI2_FLAG_LOOP_X)
11741 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11742 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11743 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11744 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11745 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11746 if (ch_a_v != ch_a_s)
11747 {
11748 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11749 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11750 }
11751 if (ch_b_v != ch_b_s)
11752 {
11753 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11754 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11755 }
11756}
11757
11758
11759static word li_check_main_plci(dword Id, PLCI *plci)
11760{
11761 if (plci == NULL)
11762 {
11763 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11764 UnMapId(Id), (char *)(FILE_), __LINE__));
11765 return (_WRONG_IDENTIFIER);
11766 }
11767 if (!plci->State
11768 || !plci->NL.Id || plci->nl_remove_id
11769 || (plci->li_bchannel_id == 0))
11770 {
11771 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11772 UnMapId(Id), (char *)(FILE_), __LINE__));
11773 return (_WRONG_STATE);
11774 }
11775 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11776 return (GOOD);
11777}
11778
11779
11780static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11781 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11782{
11783 byte ctlr_b;
11784 PLCI *plci_b;
11785
11786 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11787 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11788 {
11789 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11790 UnMapId(Id), (char *)(FILE_), __LINE__));
11791 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11792 return (NULL);
11793 }
11794 ctlr_b = 0;
11795 if ((plci_b_id & 0x7f) != 0)
11796 {
11797 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11798 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11799 ctlr_b = 0;
11800 }
11801 if ((ctlr_b == 0)
11802 || (((plci_b_id >> 8) & 0xff) == 0)
11803 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11804 {
11805 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11806 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11807 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11808 return (NULL);
11809 }
11810 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11811 if (!plci_b->State
11812 || !plci_b->NL.Id || plci_b->nl_remove_id
11813 || (plci_b->li_bchannel_id == 0))
11814 {
11815 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11816 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11817 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11818 return (NULL);
11819 }
11820 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11821 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11822 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11823 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11824 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11825 {
11826 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11827 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11828 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11829 return (NULL);
11830 }
11831 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11832 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11833 {
11834 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11835 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11836 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11837 return (NULL);
11838 }
11839 return (plci_b);
11840}
11841
11842
11843static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11844 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11845{
11846 byte ctlr_b;
11847 PLCI *plci_b;
11848
11849 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11850 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11851 {
11852 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11853 UnMapId(Id), (char *)(FILE_), __LINE__));
11854 PUT_WORD(p_result, _WRONG_STATE);
11855 return (NULL);
11856 }
11857 ctlr_b = 0;
11858 if ((plci_b_id & 0x7f) != 0)
11859 {
11860 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11861 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11862 ctlr_b = 0;
11863 }
11864 if ((ctlr_b == 0)
11865 || (((plci_b_id >> 8) & 0xff) == 0)
11866 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11867 {
11868 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11869 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11870 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11871 return (NULL);
11872 }
11873 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11874 if (!plci_b->State
11875 || !plci_b->NL.Id || plci_b->nl_remove_id
11876 || (plci_b->li_bchannel_id == 0)
11877 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11878 {
11879 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11880 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11881 PUT_WORD(p_result, _WRONG_STATE);
11882 return (NULL);
11883 }
11884 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11885 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11886 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11887 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11888 {
11889 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11890 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11891 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11892 return (NULL);
11893 }
11894 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11895 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11896 {
11897 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11898 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11899 PUT_WORD(p_result, _WRONG_STATE);
11900 return (NULL);
11901 }
11902 return (plci_b);
11903}
11904
11905
11906static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
11907{
11908 word Info;
11909 word i;
11910 dword d, li_flags, plci_b_id;
11911 PLCI *plci_b;
11912 API_PARSE li_parms[3];
11913 API_PARSE li_req_parms[3];
11914 API_PARSE li_participant_struct[2];
11915 API_PARSE li_participant_parms[3];
11916 word participant_parms_pos;
11917 byte result_buffer[32];
11918 byte *result;
11919 word result_pos;
11920 word plci_b_write_pos;
11921
11922 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11923 UnMapId(Id), (char *)(FILE_), __LINE__));
11924
11925 Info = GOOD;
11926 result = result_buffer;
11927 result_buffer[0] = 0;
11928 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11929 {
11930 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11931 UnMapId(Id), (char *)(FILE_), __LINE__));
11932 Info = _FACILITY_NOT_SUPPORTED;
11933 }
11934 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11935 {
11936 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11937 UnMapId(Id), (char *)(FILE_), __LINE__));
11938 Info = _WRONG_MESSAGE_FORMAT;
11939 }
11940 else
11941 {
11942 result_buffer[0] = 3;
11943 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11944 result_buffer[3] = 0;
11945 switch (GET_WORD(li_parms[0].info))
11946 {
11947 case LI_GET_SUPPORTED_SERVICES:
11948 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11949 {
11950 result_buffer[0] = 17;
11951 result_buffer[3] = 14;
11952 PUT_WORD(&result_buffer[4], GOOD);
11953 d = 0;
11954 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11955 d |= LI_CONFERENCING_SUPPORTED;
11956 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11957 d |= LI_MONITORING_SUPPORTED;
11958 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11959 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11960 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11961 d |= LI_CROSS_CONTROLLER_SUPPORTED;
11962 PUT_DWORD(&result_buffer[6], d);
11963 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11964 {
11965 d = 0;
11966 for (i = 0; i < li_total_channels; i++)
11967 {
11968 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11969 && (li_config_table[i].adapter->li_pri
11970 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11971 {
11972 d++;
11973 }
11974 }
11975 }
11976 else
11977 {
11978 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11979 }
11980 PUT_DWORD(&result_buffer[10], d / 2);
11981 PUT_DWORD(&result_buffer[14], d);
11982 }
11983 else
11984 {
11985 result_buffer[0] = 25;
11986 result_buffer[3] = 22;
11987 PUT_WORD(&result_buffer[4], GOOD);
11988 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11989 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11990 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11991 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11992 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11993 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11994 d |= LI2_PC_LOOPING_SUPPORTED;
11995 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11996 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11997 PUT_DWORD(&result_buffer[6], d);
11998 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11999 PUT_DWORD(&result_buffer[10], d / 2);
12000 PUT_DWORD(&result_buffer[14], d - 1);
12001 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12002 {
12003 d = 0;
12004 for (i = 0; i < li_total_channels; i++)
12005 {
12006 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007 && (li_config_table[i].adapter->li_pri
12008 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12009 {
12010 d++;
12011 }
12012 }
12013 }
12014 PUT_DWORD(&result_buffer[18], d / 2);
12015 PUT_DWORD(&result_buffer[22], d - 1);
12016 }
12017 break;
12018
12019 case LI_REQ_CONNECT:
12020 if (li_parms[1].length == 8)
12021 {
12022 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12023 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12024 {
12025 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12026 UnMapId(Id), (char *)(FILE_), __LINE__));
12027 Info = _WRONG_MESSAGE_FORMAT;
12028 break;
12029 }
12030 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12031 li_flags = GET_DWORD(li_req_parms[1].info);
12032 Info = li_check_main_plci(Id, plci);
12033 result_buffer[0] = 9;
12034 result_buffer[3] = 6;
12035 PUT_DWORD(&result_buffer[4], plci_b_id);
12036 PUT_WORD(&result_buffer[8], GOOD);
12037 if (Info != GOOD)
12038 break;
12039 result = plci->saved_msg.info;
12040 for (i = 0; i <= result_buffer[0]; i++)
12041 result[i] = result_buffer[i];
12042 plci_b_write_pos = plci->li_plci_b_write_pos;
12043 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12044 if (plci_b == NULL)
12045 break;
12046 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12047 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12048 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12049 plci->li_plci_b_write_pos = plci_b_write_pos;
12050 }
12051 else
12052 {
12053 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12054 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12055 {
12056 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12057 UnMapId(Id), (char *)(FILE_), __LINE__));
12058 Info = _WRONG_MESSAGE_FORMAT;
12059 break;
12060 }
12061 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12062 Info = li_check_main_plci(Id, plci);
12063 result_buffer[0] = 7;
12064 result_buffer[3] = 4;
12065 PUT_WORD(&result_buffer[4], Info);
12066 result_buffer[6] = 0;
12067 if (Info != GOOD)
12068 break;
12069 result = plci->saved_msg.info;
12070 for (i = 0; i <= result_buffer[0]; i++)
12071 result[i] = result_buffer[i];
12072 plci_b_write_pos = plci->li_plci_b_write_pos;
12073 participant_parms_pos = 0;
12074 result_pos = 7;
12075 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12076 while (participant_parms_pos < li_req_parms[1].length)
12077 {
12078 result[result_pos] = 6;
12079 result_pos += 7;
12080 PUT_DWORD(&result[result_pos - 6], 0);
12081 PUT_WORD(&result[result_pos - 2], GOOD);
12082 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12083 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12084 {
12085 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12086 UnMapId(Id), (char *)(FILE_), __LINE__));
12087 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12088 break;
12089 }
12090 if (api_parse(&li_participant_struct[0].info[1],
12091 li_participant_struct[0].length, "dd", li_participant_parms))
12092 {
12093 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12094 UnMapId(Id), (char *)(FILE_), __LINE__));
12095 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12096 break;
12097 }
12098 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12099 li_flags = GET_DWORD(li_participant_parms[1].info);
12100 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12101 if (sizeof(result) - result_pos < 7)
12102 {
12103 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12104 UnMapId(Id), (char *)(FILE_), __LINE__));
12105 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12106 break;
12107 }
12108 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12109 if (plci_b != NULL)
12110 {
12111 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12112 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12113 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12114 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12115 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12116 }
12117 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12118 (&li_req_parms[1].info[1]));
12119 }
12120 result[0] = (byte)(result_pos - 1);
12121 result[3] = (byte)(result_pos - 4);
12122 result[6] = (byte)(result_pos - 7);
12123 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12124 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12125 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12126 {
12127 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12128 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12129 }
12130 else
12131 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12132 plci->li_plci_b_write_pos = plci_b_write_pos;
12133 }
12134 mixer_calculate_coefs(a);
12135 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12136 mixer_notify_update(plci, true);
12137 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12138 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12139 plci->command = 0;
12140 plci->li_cmd = GET_WORD(li_parms[0].info);
12141 start_internal_command(Id, plci, mixer_command);
12142 return (false);
12143
12144 case LI_REQ_DISCONNECT:
12145 if (li_parms[1].length == 4)
12146 {
12147 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12148 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12149 {
12150 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12151 UnMapId(Id), (char *)(FILE_), __LINE__));
12152 Info = _WRONG_MESSAGE_FORMAT;
12153 break;
12154 }
12155 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12156 Info = li_check_main_plci(Id, plci);
12157 result_buffer[0] = 9;
12158 result_buffer[3] = 6;
12159 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12160 PUT_WORD(&result_buffer[8], GOOD);
12161 if (Info != GOOD)
12162 break;
12163 result = plci->saved_msg.info;
12164 for (i = 0; i <= result_buffer[0]; i++)
12165 result[i] = result_buffer[i];
12166 plci_b_write_pos = plci->li_plci_b_write_pos;
12167 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12168 if (plci_b == NULL)
12169 break;
12170 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12171 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12172 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12173 plci->li_plci_b_write_pos = plci_b_write_pos;
12174 }
12175 else
12176 {
12177 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12178 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12179 {
12180 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12181 UnMapId(Id), (char *)(FILE_), __LINE__));
12182 Info = _WRONG_MESSAGE_FORMAT;
12183 break;
12184 }
12185 Info = li_check_main_plci(Id, plci);
12186 result_buffer[0] = 7;
12187 result_buffer[3] = 4;
12188 PUT_WORD(&result_buffer[4], Info);
12189 result_buffer[6] = 0;
12190 if (Info != GOOD)
12191 break;
12192 result = plci->saved_msg.info;
12193 for (i = 0; i <= result_buffer[0]; i++)
12194 result[i] = result_buffer[i];
12195 plci_b_write_pos = plci->li_plci_b_write_pos;
12196 participant_parms_pos = 0;
12197 result_pos = 7;
12198 while (participant_parms_pos < li_req_parms[0].length)
12199 {
12200 result[result_pos] = 6;
12201 result_pos += 7;
12202 PUT_DWORD(&result[result_pos - 6], 0);
12203 PUT_WORD(&result[result_pos - 2], GOOD);
12204 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12205 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206 {
12207 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208 UnMapId(Id), (char *)(FILE_), __LINE__));
12209 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210 break;
12211 }
12212 if (api_parse(&li_participant_struct[0].info[1],
12213 li_participant_struct[0].length, "d", li_participant_parms))
12214 {
12215 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 UnMapId(Id), (char *)(FILE_), __LINE__));
12217 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218 break;
12219 }
12220 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12222 if (sizeof(result) - result_pos < 7)
12223 {
12224 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12225 UnMapId(Id), (char *)(FILE_), __LINE__));
12226 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12227 break;
12228 }
12229 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12230 if (plci_b != NULL)
12231 {
12232 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12233 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12234 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12235 }
12236 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12237 (&li_req_parms[0].info[1]));
12238 }
12239 result[0] = (byte)(result_pos - 1);
12240 result[3] = (byte)(result_pos - 4);
12241 result[6] = (byte)(result_pos - 7);
12242 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12243 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12244 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12245 {
12246 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12247 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12248 }
12249 else
12250 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12251 plci->li_plci_b_write_pos = plci_b_write_pos;
12252 }
12253 mixer_calculate_coefs(a);
12254 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12255 mixer_notify_update(plci, true);
12256 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12257 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12258 plci->command = 0;
12259 plci->li_cmd = GET_WORD(li_parms[0].info);
12260 start_internal_command(Id, plci, mixer_command);
12261 return (false);
12262
12263 case LI_REQ_SILENT_UPDATE:
12264 if (!plci || !plci->State
12265 || !plci->NL.Id || plci->nl_remove_id
12266 || (plci->li_bchannel_id == 0)
12267 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12268 {
12269 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12270 UnMapId(Id), (char *)(FILE_), __LINE__));
12271 return (false);
12272 }
12273 plci_b_write_pos = plci->li_plci_b_write_pos;
12274 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12275 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12276 {
12277 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12278 UnMapId(Id), (char *)(FILE_), __LINE__));
12279 return (false);
12280 }
12281 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12282 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12283 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12284 {
12285 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12286 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12287 }
12288 else
12289 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12290 plci->li_plci_b_write_pos = plci_b_write_pos;
12291 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12292 plci->command = 0;
12293 plci->li_cmd = GET_WORD(li_parms[0].info);
12294 start_internal_command(Id, plci, mixer_command);
12295 return (false);
12296
12297 default:
12298 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12299 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12300 Info = _FACILITY_NOT_SUPPORTED;
12301 }
12302 }
12303 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12304 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12305 return (false);
12306}
12307
12308
12309static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12310{
12311 dword d;
12312 byte result[12];
12313
12314 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12315 UnMapId(Id), (char *)(FILE_), __LINE__));
12316
12317 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12318 {
12319 do
12320 {
12321 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12322 if (!(d & LI_PLCI_B_SKIP_FLAG))
12323 {
12324 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12325 {
12326 if (d & LI_PLCI_B_DISC_FLAG)
12327 {
12328 result[0] = 5;
12329 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12330 result[3] = 2;
12331 PUT_WORD(&result[4], _LI_USER_INITIATED);
12332 }
12333 else
12334 {
12335 result[0] = 7;
12336 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12337 result[3] = 4;
12338 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12339 }
12340 }
12341 else
12342 {
12343 if (d & LI_PLCI_B_DISC_FLAG)
12344 {
12345 result[0] = 9;
12346 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12347 result[3] = 6;
12348 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12349 PUT_WORD(&result[8], _LI_USER_INITIATED);
12350 }
12351 else
12352 {
12353 result[0] = 7;
12354 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12355 result[3] = 4;
12356 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12357 }
12358 }
12359 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12360 "ws", SELECTOR_LINE_INTERCONNECT, result);
12361 }
12362 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12363 0 : plci->li_plci_b_read_pos + 1;
12364 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12365 }
12366}
12367
12368
12369static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12370{
12371 word i, j, ch;
12372 struct xconnect_transfer_address_s s, *p;
12373 DIVA_CAPI_ADAPTER *a;
12374
12375 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12376 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12377
12378 a = plci->adapter;
12379 i = 1;
12380 for (i = 1; i < length; i += 16)
12381 {
12382 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12383 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12384 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12385 ch = msg[i + 12] | (msg[i + 13] << 8);
12386 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12387 if (!a->li_pri && (plci->li_bchannel_id == 2))
12388 j = 1 - j;
12389 j += a->li_base;
12390 if (ch & XCONNECT_CHANNEL_PORT_PC)
12391 p = &(li_config_table[j].send_pc);
12392 else
12393 p = &(li_config_table[j].send_b);
12394 p->card_address.low = s.card_address.low;
12395 p->card_address.high = s.card_address.high;
12396 p->offset = s.offset;
12397 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12398 }
12399 if (plci->internal_command_queue[0]
12400 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12401 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12402 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12403 {
12404 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12405 if (!plci->internal_command)
12406 next_internal_command(Id, plci);
12407 }
12408 mixer_notify_update(plci, true);
12409}
12410
12411
12412static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12413{
12414
12415 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12416 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12417
12418}
12419
12420
12421static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12422{
12423 word plci_b_write_pos;
12424
12425 plci_b_write_pos = plci->li_plci_b_write_pos;
12426 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12427 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12428 {
12429 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12430 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12431 (char *)(FILE_), __LINE__));
12432 return (false);
12433 }
12434 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12435 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12436 plci->li_plci_b_write_pos = plci_b_write_pos;
12437 return (true);
12438}
12439
12440
12441static void mixer_remove(PLCI *plci)
12442{
12443 DIVA_CAPI_ADAPTER *a;
12444 PLCI *notify_plci;
12445 dword plci_b_id;
12446 word i, j;
12447
12448 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12449 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12450 (char *)(FILE_), __LINE__));
12451
12452 a = plci->adapter;
12453 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12454 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12455 {
12456 if ((plci->li_bchannel_id != 0)
12457 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12458 {
12459 i = a->li_base + (plci->li_bchannel_id - 1);
12460 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12461 {
12462 for (j = 0; j < li_total_channels; j++)
12463 {
12464 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12465 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12466 {
12467 notify_plci = li_config_table[j].plci;
12468 if ((notify_plci != NULL)
12469 && (notify_plci != plci)
12470 && (notify_plci->appl != NULL)
12471 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12472 && (notify_plci->State)
12473 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12474 {
12475 mixer_notify_source_removed(notify_plci, plci_b_id);
12476 }
12477 }
12478 }
12479 mixer_clear_config(plci);
12480 mixer_calculate_coefs(a);
12481 mixer_notify_update(plci, true);
12482 }
12483 li_config_table[i].plci = NULL;
12484 plci->li_bchannel_id = 0;
12485 }
12486 }
12487}
12488
12489
12490
12491
12492
12493
12494
12495static void ec_write_parameters(PLCI *plci)
12496{
12497 word w;
12498 byte parameter_buffer[6];
12499
12500 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12501 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12502 (char *)(FILE_), __LINE__));
12503
12504 parameter_buffer[0] = 5;
12505 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12506 PUT_WORD(¶meter_buffer[2], plci->ec_idi_options);
12507 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12508 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12509 PUT_WORD(¶meter_buffer[4], w);
12510 add_p(plci, FTY, parameter_buffer);
12511 sig_req(plci, TEL_CTRL, 0);
12512 send_req(plci);
12513}
12514
12515
12516static void ec_clear_config(PLCI *plci)
12517{
12518
12519 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12520 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12521 (char *)(FILE_), __LINE__));
12522
12523 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12524 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12525 plci->ec_tail_length = 0;
12526}
12527
12528
12529static void ec_prepare_switch(dword Id, PLCI *plci)
12530{
12531
12532 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12533 UnMapId(Id), (char *)(FILE_), __LINE__));
12534
12535}
12536
12537
12538static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12539{
12540
12541 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12542 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12543
12544 return (GOOD);
12545}
12546
12547
12548static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12549{
12550 word Info;
12551
12552 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12553 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12554
12555 Info = GOOD;
12556 if (plci->B1_facilities & B1_FACILITY_EC)
12557 {
12558 switch (plci->adjust_b_state)
12559 {
12560 case ADJUST_B_RESTORE_EC_1:
12561 plci->internal_command = plci->adjust_b_command;
12562 if (plci->sig_req)
12563 {
12564 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12565 break;
12566 }
12567 ec_write_parameters(plci);
12568 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12569 break;
12570 case ADJUST_B_RESTORE_EC_2:
12571 if ((Rc != OK) && (Rc != OK_FC))
12572 {
12573 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12574 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12575 Info = _WRONG_STATE;
12576 break;
12577 }
12578 break;
12579 }
12580 }
12581 return (Info);
12582}
12583
12584
12585static void ec_command(dword Id, PLCI *plci, byte Rc)
12586{
12587 word internal_command, Info;
12588 byte result[8];
12589
12590 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12591 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12592 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12593
12594 Info = GOOD;
12595 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12596 {
12597 result[0] = 2;
12598 PUT_WORD(&result[1], EC_SUCCESS);
12599 }
12600 else
12601 {
12602 result[0] = 5;
12603 PUT_WORD(&result[1], plci->ec_cmd);
12604 result[3] = 2;
12605 PUT_WORD(&result[4], GOOD);
12606 }
12607 internal_command = plci->internal_command;
12608 plci->internal_command = 0;
12609 switch (plci->ec_cmd)
12610 {
12611 case EC_ENABLE_OPERATION:
12612 case EC_FREEZE_COEFFICIENTS:
12613 case EC_RESUME_COEFFICIENT_UPDATE:
12614 case EC_RESET_COEFFICIENTS:
12615 switch (internal_command)
12616 {
12617 default:
12618 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12619 B1_FACILITY_EC), EC_COMMAND_1);
12620
12621 case EC_COMMAND_1:
12622 if (adjust_b_process(Id, plci, Rc) != GOOD)
12623 {
12624 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12625 UnMapId(Id), (char *)(FILE_), __LINE__));
12626 Info = _FACILITY_NOT_SUPPORTED;
12627 break;
12628 }
12629 if (plci->internal_command)
12630 return;
12631
12632 case EC_COMMAND_2:
12633 if (plci->sig_req)
12634 {
12635 plci->internal_command = EC_COMMAND_2;
12636 return;
12637 }
12638 plci->internal_command = EC_COMMAND_3;
12639 ec_write_parameters(plci);
12640 return;
12641 case EC_COMMAND_3:
12642 if ((Rc != OK) && (Rc != OK_FC))
12643 {
12644 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12645 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12646 Info = _FACILITY_NOT_SUPPORTED;
12647 break;
12648 }
12649 break;
12650 }
12651 break;
12652
12653 case EC_DISABLE_OPERATION:
12654 switch (internal_command)
12655 {
12656 default:
12657 case EC_COMMAND_1:
12658 if (plci->B1_facilities & B1_FACILITY_EC)
12659 {
12660 if (plci->sig_req)
12661 {
12662 plci->internal_command = EC_COMMAND_1;
12663 return;
12664 }
12665 plci->internal_command = EC_COMMAND_2;
12666 ec_write_parameters(plci);
12667 return;
12668 }
12669 Rc = OK;
12670
12671 case EC_COMMAND_2:
12672 if ((Rc != OK) && (Rc != OK_FC))
12673 {
12674 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12675 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12676 Info = _FACILITY_NOT_SUPPORTED;
12677 break;
12678 }
12679 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12680 ~B1_FACILITY_EC), EC_COMMAND_3);
12681
12682 case EC_COMMAND_3:
12683 if (adjust_b_process(Id, plci, Rc) != GOOD)
12684 {
12685 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12686 UnMapId(Id), (char *)(FILE_), __LINE__));
12687 Info = _FACILITY_NOT_SUPPORTED;
12688 break;
12689 }
12690 if (plci->internal_command)
12691 return;
12692 break;
12693 }
12694 break;
12695 }
12696 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12697 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12698 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12699}
12700
12701
12702static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12703{
12704 word Info;
12705 word opt;
12706 API_PARSE ec_parms[3];
12707 byte result[16];
12708
12709 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12710 UnMapId(Id), (char *)(FILE_), __LINE__));
12711
12712 Info = GOOD;
12713 result[0] = 0;
12714 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12715 {
12716 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12717 UnMapId(Id), (char *)(FILE_), __LINE__));
12718 Info = _FACILITY_NOT_SUPPORTED;
12719 }
12720 else
12721 {
12722 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12723 {
12724 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12725 {
12726 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12727 UnMapId(Id), (char *)(FILE_), __LINE__));
12728 Info = _WRONG_MESSAGE_FORMAT;
12729 }
12730 else
12731 {
12732 if (plci == NULL)
12733 {
12734 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12735 UnMapId(Id), (char *)(FILE_), __LINE__));
12736 Info = _WRONG_IDENTIFIER;
12737 }
12738 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12739 {
12740 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12741 UnMapId(Id), (char *)(FILE_), __LINE__));
12742 Info = _WRONG_STATE;
12743 }
12744 else
12745 {
12746 plci->command = 0;
12747 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12748 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12749 result[0] = 2;
12750 PUT_WORD(&result[1], EC_SUCCESS);
12751 if (msg[1].length >= 4)
12752 {
12753 opt = GET_WORD(&ec_parms[0].info[2]);
12754 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12755 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12756 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12757 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12758 if (opt & EC_DETECT_DISABLE_TONE)
12759 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12760 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12761 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12762 if (msg[1].length >= 6)
12763 {
12764 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12765 }
12766 }
12767 switch (plci->ec_cmd)
12768 {
12769 case EC_ENABLE_OPERATION:
12770 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12771 start_internal_command(Id, plci, ec_command);
12772 return (false);
12773
12774 case EC_DISABLE_OPERATION:
12775 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12776 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12777 LEC_RESET_COEFFICIENTS;
12778 start_internal_command(Id, plci, ec_command);
12779 return (false);
12780
12781 case EC_FREEZE_COEFFICIENTS:
12782 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12783 start_internal_command(Id, plci, ec_command);
12784 return (false);
12785
12786 case EC_RESUME_COEFFICIENT_UPDATE:
12787 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12788 start_internal_command(Id, plci, ec_command);
12789 return (false);
12790
12791 case EC_RESET_COEFFICIENTS:
12792 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12793 start_internal_command(Id, plci, ec_command);
12794 return (false);
12795
12796 default:
12797 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12798 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12799 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12800 }
12801 }
12802 }
12803 }
12804 else
12805 {
12806 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12807 {
12808 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12809 UnMapId(Id), (char *)(FILE_), __LINE__));
12810 Info = _WRONG_MESSAGE_FORMAT;
12811 }
12812 else
12813 {
12814 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12815 {
12816 result[0] = 11;
12817 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12818 result[3] = 8;
12819 PUT_WORD(&result[4], GOOD);
12820 PUT_WORD(&result[6], 0x0007);
12821 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12822 PUT_WORD(&result[10], 0);
12823 }
12824 else if (plci == NULL)
12825 {
12826 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12827 UnMapId(Id), (char *)(FILE_), __LINE__));
12828 Info = _WRONG_IDENTIFIER;
12829 }
12830 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12831 {
12832 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12833 UnMapId(Id), (char *)(FILE_), __LINE__));
12834 Info = _WRONG_STATE;
12835 }
12836 else
12837 {
12838 plci->command = 0;
12839 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12840 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12841 result[0] = 5;
12842 PUT_WORD(&result[1], plci->ec_cmd);
12843 result[3] = 2;
12844 PUT_WORD(&result[4], GOOD);
12845 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12846 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12847 plci->ec_tail_length = 0;
12848 if (ec_parms[1].length >= 2)
12849 {
12850 opt = GET_WORD(&ec_parms[1].info[1]);
12851 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12852 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12853 if (opt & EC_DETECT_DISABLE_TONE)
12854 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12855 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12856 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12857 if (ec_parms[1].length >= 4)
12858 {
12859 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12860 }
12861 }
12862 switch (plci->ec_cmd)
12863 {
12864 case EC_ENABLE_OPERATION:
12865 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12866 start_internal_command(Id, plci, ec_command);
12867 return (false);
12868
12869 case EC_DISABLE_OPERATION:
12870 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12871 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12872 LEC_RESET_COEFFICIENTS;
12873 start_internal_command(Id, plci, ec_command);
12874 return (false);
12875
12876 default:
12877 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12878 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12879 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12880 }
12881 }
12882 }
12883 }
12884 }
12885 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12886 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12887 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12888 return (false);
12889}
12890
12891
12892static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12893{
12894 byte result[8];
12895
12896 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12897 UnMapId(Id), (char *)(FILE_), __LINE__));
12898
12899 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12900 {
12901 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12902 {
12903 result[0] = 2;
12904 PUT_WORD(&result[1], 0);
12905 switch (msg[1])
12906 {
12907 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909 break;
12910 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912 break;
12913 case LEC_DISABLE_RELEASED:
12914 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12915 break;
12916 }
12917 }
12918 else
12919 {
12920 result[0] = 5;
12921 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12922 result[3] = 2;
12923 PUT_WORD(&result[4], 0);
12924 switch (msg[1])
12925 {
12926 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12927 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12928 break;
12929 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12930 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12931 break;
12932 case LEC_DISABLE_RELEASED:
12933 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12934 break;
12935 }
12936 }
12937 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12938 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12939 }
12940}
12941
12942
12943
12944
12945
12946
12947
12948static void adv_voice_write_coefs(PLCI *plci, word write_command)
12949{
12950 DIVA_CAPI_ADAPTER *a;
12951 word i;
12952 byte *p;
12953
12954 word w, n, j, k;
12955 byte ch_map[MIXER_CHANNELS_BRI];
12956
12957 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12958
12959 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12960 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12961 (char *)(FILE_), __LINE__, write_command));
12962
12963 a = plci->adapter;
12964 p = coef_buffer + 1;
12965 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12966 i = 0;
12967 while (i + sizeof(word) <= a->adv_voice_coef_length)
12968 {
12969 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12970 p += 2;
12971 i += 2;
12972 }
12973 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12974 {
12975 PUT_WORD(p, 0x8000);
12976 p += 2;
12977 i += 2;
12978 }
12979
12980 if (!a->li_pri && (plci->li_bchannel_id == 0))
12981 {
12982 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12983 {
12984 plci->li_bchannel_id = 1;
12985 li_config_table[a->li_base].plci = plci;
12986 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12987 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12988 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12989 }
12990 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12991 {
12992 plci->li_bchannel_id = 2;
12993 li_config_table[a->li_base + 1].plci = plci;
12994 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12995 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12996 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12997 }
12998 }
12999 if (!a->li_pri && (plci->li_bchannel_id != 0)
13000 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13001 {
13002 i = a->li_base + (plci->li_bchannel_id - 1);
13003 switch (write_command)
13004 {
13005 case ADV_VOICE_WRITE_ACTIVATION:
13006 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13007 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13008 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13009 {
13010 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13011 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13012 }
13013 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13014 {
13015 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13016 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13017 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13018 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13019 }
13020 mixer_calculate_coefs(a);
13021 li_config_table[i].curchnl = li_config_table[i].channel;
13022 li_config_table[j].curchnl = li_config_table[j].channel;
13023 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13024 li_config_table[k].curchnl = li_config_table[k].channel;
13025 break;
13026
13027 case ADV_VOICE_WRITE_DEACTIVATION:
13028 for (j = 0; j < li_total_channels; j++)
13029 {
13030 li_config_table[i].flag_table[j] = 0;
13031 li_config_table[j].flag_table[i] = 0;
13032 }
13033 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13034 for (j = 0; j < li_total_channels; j++)
13035 {
13036 li_config_table[k].flag_table[j] = 0;
13037 li_config_table[j].flag_table[k] = 0;
13038 }
13039 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13040 {
13041 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13042 for (j = 0; j < li_total_channels; j++)
13043 {
13044 li_config_table[k].flag_table[j] = 0;
13045 li_config_table[j].flag_table[k] = 0;
13046 }
13047 }
13048 mixer_calculate_coefs(a);
13049 break;
13050 }
13051 if (plci->B1_facilities & B1_FACILITY_MIXER)
13052 {
13053 w = 0;
13054 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13055 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13056 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13057 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13058 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13059 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13060 *(p++) = (byte) w;
13061 *(p++) = (byte)(w >> 8);
13062 for (j = 0; j < sizeof(ch_map); j += 2)
13063 {
13064 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13065 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13066 }
13067 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13068 {
13069 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13070 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13071 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13072 {
13073 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13074 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13075 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13076 }
13077 else
13078 {
13079 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13080 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13081 }
13082 }
13083 }
13084 else
13085 {
13086 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13087 *(p++) = a->adv_voice_coef_buffer[i];
13088 }
13089 }
13090 else
13091
13092 {
13093 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13094 *(p++) = a->adv_voice_coef_buffer[i];
13095 }
13096 coef_buffer[0] = (p - coef_buffer) - 1;
13097 add_p(plci, FTY, coef_buffer);
13098 sig_req(plci, TEL_CTRL, 0);
13099 send_req(plci);
13100}
13101
13102
13103static void adv_voice_clear_config(PLCI *plci)
13104{
13105 DIVA_CAPI_ADAPTER *a;
13106
13107 word i, j;
13108
13109
13110 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13111 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13112 (char *)(FILE_), __LINE__));
13113
13114 a = plci->adapter;
13115 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13116 {
13117 a->adv_voice_coef_length = 0;
13118
13119 if (!a->li_pri && (plci->li_bchannel_id != 0)
13120 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121 {
13122 i = a->li_base + (plci->li_bchannel_id - 1);
13123 li_config_table[i].curchnl = 0;
13124 li_config_table[i].channel = 0;
13125 li_config_table[i].chflags = 0;
13126 for (j = 0; j < li_total_channels; j++)
13127 {
13128 li_config_table[i].flag_table[j] = 0;
13129 li_config_table[j].flag_table[i] = 0;
13130 li_config_table[i].coef_table[j] = 0;
13131 li_config_table[j].coef_table[i] = 0;
13132 }
13133 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13134 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13135 li_config_table[i].curchnl = 0;
13136 li_config_table[i].channel = 0;
13137 li_config_table[i].chflags = 0;
13138 for (j = 0; j < li_total_channels; j++)
13139 {
13140 li_config_table[i].flag_table[j] = 0;
13141 li_config_table[j].flag_table[i] = 0;
13142 li_config_table[i].coef_table[j] = 0;
13143 li_config_table[j].coef_table[i] = 0;
13144 }
13145 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13146 {
13147 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148 li_config_table[i].curchnl = 0;
13149 li_config_table[i].channel = 0;
13150 li_config_table[i].chflags = 0;
13151 for (j = 0; j < li_total_channels; j++)
13152 {
13153 li_config_table[i].flag_table[j] = 0;
13154 li_config_table[j].flag_table[i] = 0;
13155 li_config_table[i].coef_table[j] = 0;
13156 li_config_table[j].coef_table[i] = 0;
13157 }
13158 }
13159 }
13160
13161 }
13162}
13163
13164
13165static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13166{
13167
13168 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13169 UnMapId(Id), (char *)(FILE_), __LINE__));
13170
13171}
13172
13173
13174static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13175{
13176
13177 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13178 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13179
13180 return (GOOD);
13181}
13182
13183
13184static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13185{
13186 DIVA_CAPI_ADAPTER *a;
13187 word Info;
13188
13189 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13190 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13191
13192 Info = GOOD;
13193 a = plci->adapter;
13194 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13195 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13196 {
13197 switch (plci->adjust_b_state)
13198 {
13199 case ADJUST_B_RESTORE_VOICE_1:
13200 plci->internal_command = plci->adjust_b_command;
13201 if (plci->sig_req)
13202 {
13203 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13204 break;
13205 }
13206 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13207 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13208 break;
13209 case ADJUST_B_RESTORE_VOICE_2:
13210 if ((Rc != OK) && (Rc != OK_FC))
13211 {
13212 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13213 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13214 Info = _WRONG_STATE;
13215 break;
13216 }
13217 break;
13218 }
13219 }
13220 return (Info);
13221}
13222
13223
13224
13225
13226
13227
13228
13229
13230static byte b1_facilities_table[] =
13231{
13232 0x00,
13233 0x00,
13234 0x00,
13235 0x00,
13236 0x00,
13237 0x00,
13238 0x00,
13239 0x00,
13240 0x00,
13241 0x00,
13242 0x00,
13243 0x00,
13244 0x00,
13245 0x00,
13246 0x00,
13247 0x00,
13248 0x00,
13249 0x00,
13250 0x00,
13251 0x00,
13252 0x12,
13253 0x00,
13254 0x0c,
13255 0x1e,
13256 0x1f,
13257 0x13,
13258 0x12,
13259 0x12,
13260 0x2c,
13261 0x3e,
13262 0x3f,
13263 0x2c,
13264 0x3e,
13265 0x3f,
13266 0x00,
13267 0x00,
13268 0x0c,
13269 0x1e,
13270 0x1f
13271};
13272
13273
13274static word get_b1_facilities(PLCI *plci, byte b1_resource)
13275{
13276 word b1_facilities;
13277
13278 b1_facilities = b1_facilities_table[b1_resource];
13279 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13280 {
13281
13282 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13283 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13284
13285 {
13286 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13287 b1_facilities |= B1_FACILITY_DTMFX;
13288 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13289 b1_facilities |= B1_FACILITY_DTMFR;
13290 }
13291 }
13292 if ((b1_resource == 17) || (b1_resource == 18))
13293 {
13294 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13295 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13296 }
13297
13298
13299
13300
13301
13302 return (b1_facilities);
13303}
13304
13305
13306static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13307{
13308 byte b;
13309
13310 switch (b1_resource)
13311 {
13312 case 5:
13313 case 26:
13314 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13315 b = 26;
13316 else
13317 b = 5;
13318 break;
13319
13320 case 8:
13321 case 27:
13322 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13323 b = 27;
13324 else
13325 b = 8;
13326 break;
13327
13328 case 9:
13329 case 20:
13330 case 22:
13331 case 23:
13332 case 24:
13333 case 25:
13334 case 28:
13335 case 29:
13336 case 30:
13337 case 36:
13338 case 37:
13339 case 38:
13340 if (b1_facilities & B1_FACILITY_EC)
13341 {
13342 if (b1_facilities & B1_FACILITY_LOCAL)
13343 b = 30;
13344 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13345 b = 29;
13346 else
13347 b = 28;
13348 }
13349
13350 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13351 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13352 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13353 {
13354 if (b1_facilities & B1_FACILITY_LOCAL)
13355 b = 38;
13356 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13357 b = 37;
13358 else
13359 b = 36;
13360 }
13361
13362 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13363 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13364 || ((b1_facilities & B1_FACILITY_DTMFR)
13365 && ((b1_facilities & B1_FACILITY_MIXER)
13366 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13367 || ((b1_facilities & B1_FACILITY_DTMFX)
13368 && ((b1_facilities & B1_FACILITY_MIXER)
13369 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13370 {
13371 if (b1_facilities & B1_FACILITY_LOCAL)
13372 b = 24;
13373 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13374 b = 23;
13375 else
13376 b = 22;
13377 }
13378 else
13379 {
13380 if (b1_facilities & B1_FACILITY_LOCAL)
13381 b = 25;
13382 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13383 b = 20;
13384 else
13385 b = 9;
13386 }
13387 break;
13388
13389 case 31:
13390 case 32:
13391 case 33:
13392 if (b1_facilities & B1_FACILITY_LOCAL)
13393 b = 33;
13394 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13395 b = 32;
13396 else
13397 b = 31;
13398 break;
13399
13400 default:
13401 b = b1_resource;
13402 }
13403 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13404 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13405 (char *)(FILE_), __LINE__,
13406 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13407 return (b);
13408}
13409
13410
13411static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13412{
13413 word removed_facilities;
13414
13415 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13416 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13417 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13418 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13419
13420 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13421 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13422
13423 if (removed_facilities & B1_FACILITY_EC)
13424 ec_clear_config(plci);
13425
13426
13427 if (removed_facilities & B1_FACILITY_DTMFR)
13428 {
13429 dtmf_rec_clear_config(plci);
13430 dtmf_parameter_clear_config(plci);
13431 }
13432 if (removed_facilities & B1_FACILITY_DTMFX)
13433 dtmf_send_clear_config(plci);
13434
13435
13436 if (removed_facilities & B1_FACILITY_MIXER)
13437 mixer_clear_config(plci);
13438
13439 if (removed_facilities & B1_FACILITY_VOICE)
13440 adv_voice_clear_config(plci);
13441 plci->B1_facilities = new_b1_facilities;
13442}
13443
13444
13445static void adjust_b_clear(PLCI *plci)
13446{
13447
13448 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13449 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13450 (char *)(FILE_), __LINE__));
13451
13452 plci->adjust_b_restore = false;
13453}
13454
13455
13456static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13457{
13458 word Info;
13459 byte b1_resource;
13460 NCCI *ncci_ptr;
13461 API_PARSE bp[2];
13462
13463 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13464 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13465
13466 Info = GOOD;
13467 switch (plci->adjust_b_state)
13468 {
13469 case ADJUST_B_START:
13470 if ((plci->adjust_b_parms_msg == NULL)
13471 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13472 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13473 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13474 {
13475 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13476 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13477 if (b1_resource == plci->B1_resource)
13478 {
13479 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13480 break;
13481 }
13482 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13483 {
13484 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13485 UnMapId(Id), (char *)(FILE_), __LINE__,
13486 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13487 Info = _WRONG_STATE;
13488 break;
13489 }
13490 }
13491 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13492 {
13493
13494 mixer_prepare_switch(Id, plci);
13495
13496
13497 dtmf_prepare_switch(Id, plci);
13498 dtmf_parameter_prepare_switch(Id, plci);
13499
13500
13501 ec_prepare_switch(Id, plci);
13502
13503 adv_voice_prepare_switch(Id, plci);
13504 }
13505 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13506 Rc = OK;
13507
13508 case ADJUST_B_SAVE_MIXER_1:
13509 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13510 {
13511
13512 Info = mixer_save_config(Id, plci, Rc);
13513 if ((Info != GOOD) || plci->internal_command)
13514 break;
13515
13516 }
13517 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13518 Rc = OK;
13519
13520 case ADJUST_B_SAVE_DTMF_1:
13521 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13522 {
13523
13524 Info = dtmf_save_config(Id, plci, Rc);
13525 if ((Info != GOOD) || plci->internal_command)
13526 break;
13527
13528 }
13529 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13530
13531 case ADJUST_B_REMOVE_L23_1:
13532 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13533 && plci->NL.Id && !plci->nl_remove_id)
13534 {
13535 plci->internal_command = plci->adjust_b_command;
13536 if (plci->adjust_b_ncci != 0)
13537 {
13538 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13539 while (ncci_ptr->data_pending)
13540 {
13541 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13542 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13543 }
13544 while (ncci_ptr->data_ack_pending)
13545 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13546 }
13547 nl_req_ncci(plci, REMOVE,
13548 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13549 send_req(plci);
13550 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13551 break;
13552 }
13553 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13554 Rc = OK;
13555
13556 case ADJUST_B_REMOVE_L23_2:
13557 if ((Rc != OK) && (Rc != OK_FC))
13558 {
13559 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13560 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13561 Info = _WRONG_STATE;
13562 break;
13563 }
13564 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13565 {
13566 if (plci_nl_busy(plci))
13567 {
13568 plci->internal_command = plci->adjust_b_command;
13569 break;
13570 }
13571 }
13572 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13573 Rc = OK;
13574
13575 case ADJUST_B_SAVE_EC_1:
13576 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13577 {
13578
13579 Info = ec_save_config(Id, plci, Rc);
13580 if ((Info != GOOD) || plci->internal_command)
13581 break;
13582
13583 }
13584 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13585 Rc = OK;
13586
13587 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13588 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13589 {
13590
13591 Info = dtmf_parameter_save_config(Id, plci, Rc);
13592 if ((Info != GOOD) || plci->internal_command)
13593 break;
13594
13595 }
13596 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13597 Rc = OK;
13598
13599 case ADJUST_B_SAVE_VOICE_1:
13600 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13601 {
13602 Info = adv_voice_save_config(Id, plci, Rc);
13603 if ((Info != GOOD) || plci->internal_command)
13604 break;
13605 }
13606 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13607
13608 case ADJUST_B_SWITCH_L1_1:
13609 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13610 {
13611 if (plci->sig_req)
13612 {
13613 plci->internal_command = plci->adjust_b_command;
13614 break;
13615 }
13616 if (plci->adjust_b_parms_msg != NULL)
13617 api_load_msg(plci->adjust_b_parms_msg, bp);
13618 else
13619 api_load_msg(&plci->B_protocol, bp);
13620 Info = add_b1(plci, bp,
13621 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13622 plci->adjust_b_facilities);
13623 if (Info != GOOD)
13624 {
13625 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13626 UnMapId(Id), (char *)(FILE_), __LINE__,
13627 plci->B1_resource, plci->adjust_b_facilities));
13628 break;
13629 }
13630 plci->internal_command = plci->adjust_b_command;
13631 sig_req(plci, RESOURCES, 0);
13632 send_req(plci);
13633 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13634 break;
13635 }
13636 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13637 Rc = OK;
13638
13639 case ADJUST_B_SWITCH_L1_2:
13640 if ((Rc != OK) && (Rc != OK_FC))
13641 {
13642 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13643 UnMapId(Id), (char *)(FILE_), __LINE__,
13644 Rc, plci->B1_resource, plci->adjust_b_facilities));
13645 Info = _WRONG_STATE;
13646 break;
13647 }
13648 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13649 Rc = OK;
13650
13651 case ADJUST_B_RESTORE_VOICE_1:
13652 case ADJUST_B_RESTORE_VOICE_2:
13653 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13654 {
13655 Info = adv_voice_restore_config(Id, plci, Rc);
13656 if ((Info != GOOD) || plci->internal_command)
13657 break;
13658 }
13659 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13660 Rc = OK;
13661
13662 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13663 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13664 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13665 {
13666
13667 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13668 if ((Info != GOOD) || plci->internal_command)
13669 break;
13670
13671 }
13672 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13673 Rc = OK;
13674
13675 case ADJUST_B_RESTORE_EC_1:
13676 case ADJUST_B_RESTORE_EC_2:
13677 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13678 {
13679
13680 Info = ec_restore_config(Id, plci, Rc);
13681 if ((Info != GOOD) || plci->internal_command)
13682 break;
13683
13684 }
13685 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13686
13687 case ADJUST_B_ASSIGN_L23_1:
13688 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13689 {
13690 if (plci_nl_busy(plci))
13691 {
13692 plci->internal_command = plci->adjust_b_command;
13693 break;
13694 }
13695 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13696 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13697 if (plci->adjust_b_parms_msg != NULL)
13698 api_load_msg(plci->adjust_b_parms_msg, bp);
13699 else
13700 api_load_msg(&plci->B_protocol, bp);
13701 Info = add_b23(plci, bp);
13702 if (Info != GOOD)
13703 {
13704 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13705 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13706 break;
13707 }
13708 plci->internal_command = plci->adjust_b_command;
13709 nl_req_ncci(plci, ASSIGN, 0);
13710 send_req(plci);
13711 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13712 break;
13713 }
13714 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13715 Rc = ASSIGN_OK;
13716
13717 case ADJUST_B_ASSIGN_L23_2:
13718 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13719 {
13720 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13721 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13722 Info = _WRONG_STATE;
13723 break;
13724 }
13725 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13726 {
13727 if (Rc != ASSIGN_OK)
13728 {
13729 plci->internal_command = plci->adjust_b_command;
13730 break;
13731 }
13732 }
13733 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13734 {
13735 plci->adjust_b_restore = true;
13736 break;
13737 }
13738 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13739
13740 case ADJUST_B_CONNECT_1:
13741 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13742 {
13743 plci->internal_command = plci->adjust_b_command;
13744 if (plci_nl_busy(plci))
13745 break;
13746 nl_req_ncci(plci, N_CONNECT, 0);
13747 send_req(plci);
13748 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13749 break;
13750 }
13751 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13752 Rc = OK;
13753
13754 case ADJUST_B_CONNECT_2:
13755 case ADJUST_B_CONNECT_3:
13756 case ADJUST_B_CONNECT_4:
13757 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13758 {
13759 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13760 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13761 Info = _WRONG_STATE;
13762 break;
13763 }
13764 if (Rc == OK)
13765 {
13766 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13767 {
13768 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13769 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13770 }
13771 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13772 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13773 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13774 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13775 }
13776 else if (Rc == 0)
13777 {
13778 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13779 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13780 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13781 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13782 }
13783 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13784 {
13785 plci->internal_command = plci->adjust_b_command;
13786 break;
13787 }
13788 Rc = OK;
13789
13790 case ADJUST_B_RESTORE_DTMF_1:
13791 case ADJUST_B_RESTORE_DTMF_2:
13792 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13793 {
13794
13795 Info = dtmf_restore_config(Id, plci, Rc);
13796 if ((Info != GOOD) || plci->internal_command)
13797 break;
13798
13799 }
13800 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13801 Rc = OK;
13802
13803 case ADJUST_B_RESTORE_MIXER_1:
13804 case ADJUST_B_RESTORE_MIXER_2:
13805 case ADJUST_B_RESTORE_MIXER_3:
13806 case ADJUST_B_RESTORE_MIXER_4:
13807 case ADJUST_B_RESTORE_MIXER_5:
13808 case ADJUST_B_RESTORE_MIXER_6:
13809 case ADJUST_B_RESTORE_MIXER_7:
13810 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13811 {
13812
13813 Info = mixer_restore_config(Id, plci, Rc);
13814 if ((Info != GOOD) || plci->internal_command)
13815 break;
13816
13817 }
13818 plci->adjust_b_state = ADJUST_B_END;
13819 case ADJUST_B_END:
13820 break;
13821 }
13822 return (Info);
13823}
13824
13825
13826static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13827{
13828
13829 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13830 UnMapId(Id), (char *)(FILE_), __LINE__,
13831 plci->B1_resource, b1_facilities));
13832
13833 plci->adjust_b_parms_msg = bp_msg;
13834 plci->adjust_b_facilities = b1_facilities;
13835 plci->adjust_b_command = internal_command;
13836 plci->adjust_b_ncci = (word)(Id >> 16);
13837 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13838 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13839 else
13840 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13841 plci->adjust_b_state = ADJUST_B_START;
13842 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13843 UnMapId(Id), (char *)(FILE_), __LINE__,
13844 plci->B1_resource, b1_facilities));
13845}
13846
13847
13848static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13849{
13850 word internal_command;
13851
13852 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13853 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13854
13855 internal_command = plci->internal_command;
13856 plci->internal_command = 0;
13857 switch (internal_command)
13858 {
13859 default:
13860 plci->command = 0;
13861 if (plci->req_in != 0)
13862 {
13863 plci->internal_command = ADJUST_B_RESTORE_1;
13864 break;
13865 }
13866 Rc = OK;
13867
13868 case ADJUST_B_RESTORE_1:
13869 if ((Rc != OK) && (Rc != OK_FC))
13870 {
13871 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13872 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13873 }
13874 plci->adjust_b_parms_msg = NULL;
13875 plci->adjust_b_facilities = plci->B1_facilities;
13876 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13877 plci->adjust_b_ncci = (word)(Id >> 16);
13878 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13879 plci->adjust_b_state = ADJUST_B_START;
13880 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13881 UnMapId(Id), (char *)(FILE_), __LINE__));
13882
13883 case ADJUST_B_RESTORE_2:
13884 if (adjust_b_process(Id, plci, Rc) != GOOD)
13885 {
13886 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13887 UnMapId(Id), (char *)(FILE_), __LINE__));
13888 }
13889 if (plci->internal_command)
13890 break;
13891 break;
13892 }
13893}
13894
13895
13896static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13897{
13898 word Info;
13899 word internal_command;
13900
13901 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13902 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13903
13904 Info = GOOD;
13905 internal_command = plci->internal_command;
13906 plci->internal_command = 0;
13907 switch (internal_command)
13908 {
13909 default:
13910 plci->command = 0;
13911 plci->adjust_b_parms_msg = NULL;
13912 plci->adjust_b_facilities = plci->B1_facilities;
13913 plci->adjust_b_command = RESET_B3_COMMAND_1;
13914 plci->adjust_b_ncci = (word)(Id >> 16);
13915 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13916 plci->adjust_b_state = ADJUST_B_START;
13917 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13918 UnMapId(Id), (char *)(FILE_), __LINE__));
13919
13920 case RESET_B3_COMMAND_1:
13921 Info = adjust_b_process(Id, plci, Rc);
13922 if (Info != GOOD)
13923 {
13924 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13925 UnMapId(Id), (char *)(FILE_), __LINE__));
13926 break;
13927 }
13928 if (plci->internal_command)
13929 return;
13930 break;
13931 }
13932
13933 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13934}
13935
13936
13937static void select_b_command(dword Id, PLCI *plci, byte Rc)
13938{
13939 word Info;
13940 word internal_command;
13941 byte esc_chi[3];
13942
13943 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13944 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13945
13946 Info = GOOD;
13947 internal_command = plci->internal_command;
13948 plci->internal_command = 0;
13949 switch (internal_command)
13950 {
13951 default:
13952 plci->command = 0;
13953 plci->adjust_b_parms_msg = &plci->saved_msg;
13954 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13955 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13956 else
13957 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13958 plci->adjust_b_command = SELECT_B_COMMAND_1;
13959 plci->adjust_b_ncci = (word)(Id >> 16);
13960 if (plci->saved_msg.parms[0].length == 0)
13961 {
13962 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13963 ADJUST_B_MODE_NO_RESOURCE;
13964 }
13965 else
13966 {
13967 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13968 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13969 }
13970 plci->adjust_b_state = ADJUST_B_START;
13971 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13972 UnMapId(Id), (char *)(FILE_), __LINE__));
13973
13974 case SELECT_B_COMMAND_1:
13975 Info = adjust_b_process(Id, plci, Rc);
13976 if (Info != GOOD)
13977 {
13978 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13979 UnMapId(Id), (char *)(FILE_), __LINE__));
13980 break;
13981 }
13982 if (plci->internal_command)
13983 return;
13984 if (plci->tel == ADV_VOICE)
13985 {
13986 esc_chi[0] = 0x02;
13987 esc_chi[1] = 0x18;
13988 esc_chi[2] = plci->b_channel;
13989 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13990 }
13991 break;
13992 }
13993 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13994}
13995
13996
13997static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13998{
13999 word internal_command;
14000
14001 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14002 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14003
14004 internal_command = plci->internal_command;
14005 plci->internal_command = 0;
14006 switch (internal_command)
14007 {
14008 default:
14009 plci->command = 0;
14010 case FAX_CONNECT_ACK_COMMAND_1:
14011 if (plci_nl_busy(plci))
14012 {
14013 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14014 return;
14015 }
14016 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14017 plci->NData[0].P = plci->fax_connect_info_buffer;
14018 plci->NData[0].PLength = plci->fax_connect_info_length;
14019 plci->NL.X = plci->NData;
14020 plci->NL.ReqCh = 0;
14021 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14022 plci->adapter->request(&plci->NL);
14023 return;
14024 case FAX_CONNECT_ACK_COMMAND_2:
14025 if ((Rc != OK) && (Rc != OK_FC))
14026 {
14027 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14028 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14029 break;
14030 }
14031 }
14032 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14033 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14034 {
14035 if (plci->B3_prot == 4)
14036 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14037 else
14038 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14039 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14040 }
14041}
14042
14043
14044static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14045{
14046 word internal_command;
14047
14048 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14049 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050
14051 internal_command = plci->internal_command;
14052 plci->internal_command = 0;
14053 switch (internal_command)
14054 {
14055 default:
14056 plci->command = 0;
14057
14058 case FAX_EDATA_ACK_COMMAND_1:
14059 if (plci_nl_busy(plci))
14060 {
14061 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14062 return;
14063 }
14064 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14065 plci->NData[0].P = plci->fax_connect_info_buffer;
14066 plci->NData[0].PLength = plci->fax_edata_ack_length;
14067 plci->NL.X = plci->NData;
14068 plci->NL.ReqCh = 0;
14069 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14070 plci->adapter->request(&plci->NL);
14071 return;
14072 case FAX_EDATA_ACK_COMMAND_2:
14073 if ((Rc != OK) && (Rc != OK_FC))
14074 {
14075 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14076 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14077 break;
14078 }
14079 }
14080}
14081
14082
14083static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14084{
14085 word Info;
14086 word internal_command;
14087
14088 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14089 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14090
14091 Info = GOOD;
14092 internal_command = plci->internal_command;
14093 plci->internal_command = 0;
14094 switch (internal_command)
14095 {
14096 default:
14097 plci->command = 0;
14098 case FAX_CONNECT_INFO_COMMAND_1:
14099 if (plci_nl_busy(plci))
14100 {
14101 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14102 return;
14103 }
14104 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14105 plci->NData[0].P = plci->fax_connect_info_buffer;
14106 plci->NData[0].PLength = plci->fax_connect_info_length;
14107 plci->NL.X = plci->NData;
14108 plci->NL.ReqCh = 0;
14109 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14110 plci->adapter->request(&plci->NL);
14111 return;
14112 case FAX_CONNECT_INFO_COMMAND_2:
14113 if ((Rc != OK) && (Rc != OK_FC))
14114 {
14115 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14116 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14117 Info = _WRONG_STATE;
14118 break;
14119 }
14120 if (plci_nl_busy(plci))
14121 {
14122 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14123 return;
14124 }
14125 plci->command = _CONNECT_B3_R;
14126 nl_req_ncci(plci, N_CONNECT, 0);
14127 send_req(plci);
14128 return;
14129 }
14130 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14131}
14132
14133
14134static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14135{
14136 word Info;
14137 word internal_command;
14138
14139 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14140 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14141
14142 Info = GOOD;
14143 internal_command = plci->internal_command;
14144 plci->internal_command = 0;
14145 switch (internal_command)
14146 {
14147 default:
14148 plci->command = 0;
14149 plci->adjust_b_parms_msg = NULL;
14150 plci->adjust_b_facilities = plci->B1_facilities;
14151 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14152 plci->adjust_b_ncci = (word)(Id >> 16);
14153 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14154 plci->adjust_b_state = ADJUST_B_START;
14155 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14156 UnMapId(Id), (char *)(FILE_), __LINE__));
14157
14158 case FAX_ADJUST_B23_COMMAND_1:
14159 Info = adjust_b_process(Id, plci, Rc);
14160 if (Info != GOOD)
14161 {
14162 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14163 UnMapId(Id), (char *)(FILE_), __LINE__));
14164 break;
14165 }
14166 if (plci->internal_command)
14167 return;
14168
14169 case FAX_ADJUST_B23_COMMAND_2:
14170 if (plci_nl_busy(plci))
14171 {
14172 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14173 return;
14174 }
14175 plci->command = _CONNECT_B3_R;
14176 nl_req_ncci(plci, N_CONNECT, 0);
14177 send_req(plci);
14178 return;
14179 }
14180 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14181}
14182
14183
14184static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14185{
14186 word internal_command;
14187
14188 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14189 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190
14191 internal_command = plci->internal_command;
14192 plci->internal_command = 0;
14193 switch (internal_command)
14194 {
14195 default:
14196 plci->command = 0;
14197 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14198 return;
14199 case FAX_DISCONNECT_COMMAND_1:
14200 case FAX_DISCONNECT_COMMAND_2:
14201 case FAX_DISCONNECT_COMMAND_3:
14202 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14203 {
14204 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14205 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14206 break;
14207 }
14208 if (Rc == OK)
14209 {
14210 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14211 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14212 {
14213 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14214 }
14215 }
14216 else if (Rc == 0)
14217 {
14218 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14219 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14220 }
14221 return;
14222 }
14223}
14224
14225
14226
14227static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14228{
14229 word Info;
14230 word internal_command;
14231
14232 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14233 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14234
14235 Info = GOOD;
14236 internal_command = plci->internal_command;
14237 plci->internal_command = 0;
14238 switch (internal_command)
14239 {
14240 default:
14241 plci->command = 0;
14242 case RTP_CONNECT_B3_REQ_COMMAND_1:
14243 if (plci_nl_busy(plci))
14244 {
14245 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14246 return;
14247 }
14248 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14249 nl_req_ncci(plci, N_CONNECT, 0);
14250 send_req(plci);
14251 return;
14252 case RTP_CONNECT_B3_REQ_COMMAND_2:
14253 if ((Rc != OK) && (Rc != OK_FC))
14254 {
14255 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14256 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14257 Info = _WRONG_STATE;
14258 break;
14259 }
14260 if (plci_nl_busy(plci))
14261 {
14262 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14263 return;
14264 }
14265 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14266 plci->NData[0].PLength = plci->internal_req_buffer[0];
14267 plci->NData[0].P = plci->internal_req_buffer + 1;
14268 plci->NL.X = plci->NData;
14269 plci->NL.ReqCh = 0;
14270 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14271 plci->adapter->request(&plci->NL);
14272 break;
14273 case RTP_CONNECT_B3_REQ_COMMAND_3:
14274 return;
14275 }
14276 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14277}
14278
14279
14280static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14281{
14282 word internal_command;
14283
14284 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14285 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14286
14287 internal_command = plci->internal_command;
14288 plci->internal_command = 0;
14289 switch (internal_command)
14290 {
14291 default:
14292 plci->command = 0;
14293 case RTP_CONNECT_B3_RES_COMMAND_1:
14294 if (plci_nl_busy(plci))
14295 {
14296 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14297 return;
14298 }
14299 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14300 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14301 send_req(plci);
14302 return;
14303 case RTP_CONNECT_B3_RES_COMMAND_2:
14304 if ((Rc != OK) && (Rc != OK_FC))
14305 {
14306 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14307 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14308 break;
14309 }
14310 if (plci_nl_busy(plci))
14311 {
14312 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14313 return;
14314 }
14315 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14316 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14317 plci->NData[0].PLength = plci->internal_req_buffer[0];
14318 plci->NData[0].P = plci->internal_req_buffer + 1;
14319 plci->NL.X = plci->NData;
14320 plci->NL.ReqCh = 0;
14321 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14322 plci->adapter->request(&plci->NL);
14323 return;
14324 case RTP_CONNECT_B3_RES_COMMAND_3:
14325 return;
14326 }
14327}
14328
14329
14330
14331static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14332{
14333 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00";
14334 word Info;
14335 word internal_command;
14336
14337 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14338 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14339
14340 Info = GOOD;
14341 internal_command = plci->internal_command;
14342 plci->internal_command = 0;
14343 switch (internal_command)
14344 {
14345 default:
14346 if (!plci->NL.Id)
14347 break;
14348 plci->command = 0;
14349 plci->adjust_b_parms_msg = NULL;
14350 plci->adjust_b_facilities = plci->B1_facilities;
14351 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14352 plci->adjust_b_ncci = (word)(Id >> 16);
14353 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14354 plci->adjust_b_state = ADJUST_B_START;
14355 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14356 UnMapId(Id), (char *)(FILE_), __LINE__));
14357
14358 case HOLD_SAVE_COMMAND_1:
14359 Info = adjust_b_process(Id, plci, Rc);
14360 if (Info != GOOD)
14361 {
14362 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14363 UnMapId(Id), (char *)(FILE_), __LINE__));
14364 break;
14365 }
14366 if (plci->internal_command)
14367 return;
14368 }
14369 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14370}
14371
14372
14373static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14374{
14375 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00";
14376 word Info;
14377 word internal_command;
14378
14379 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14380 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14381
14382 Info = GOOD;
14383 internal_command = plci->internal_command;
14384 plci->internal_command = 0;
14385 switch (internal_command)
14386 {
14387 default:
14388 plci->command = 0;
14389 plci->adjust_b_parms_msg = NULL;
14390 plci->adjust_b_facilities = plci->B1_facilities;
14391 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14392 plci->adjust_b_ncci = (word)(Id >> 16);
14393 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14394 plci->adjust_b_state = ADJUST_B_START;
14395 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14396 UnMapId(Id), (char *)(FILE_), __LINE__));
14397
14398 case RETRIEVE_RESTORE_COMMAND_1:
14399 Info = adjust_b_process(Id, plci, Rc);
14400 if (Info != GOOD)
14401 {
14402 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14403 UnMapId(Id), (char *)(FILE_), __LINE__));
14404 break;
14405 }
14406 if (plci->internal_command)
14407 return;
14408 }
14409 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14410}
14411
14412
14413static void init_b1_config(PLCI *plci)
14414{
14415
14416 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14417 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14418 (char *)(FILE_), __LINE__));
14419
14420 plci->B1_resource = 0;
14421 plci->B1_facilities = 0;
14422
14423 plci->li_bchannel_id = 0;
14424 mixer_clear_config(plci);
14425
14426
14427 ec_clear_config(plci);
14428
14429
14430 dtmf_rec_clear_config(plci);
14431 dtmf_send_clear_config(plci);
14432 dtmf_parameter_clear_config(plci);
14433
14434 adv_voice_clear_config(plci);
14435 adjust_b_clear(plci);
14436}
14437
14438
14439static void clear_b1_config(PLCI *plci)
14440{
14441
14442 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14443 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14444 (char *)(FILE_), __LINE__));
14445
14446 adv_voice_clear_config(plci);
14447 adjust_b_clear(plci);
14448
14449 ec_clear_config(plci);
14450
14451
14452 dtmf_rec_clear_config(plci);
14453 dtmf_send_clear_config(plci);
14454 dtmf_parameter_clear_config(plci);
14455
14456
14457 if ((plci->li_bchannel_id != 0)
14458 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14459 {
14460 mixer_clear_config(plci);
14461 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14462 plci->li_bchannel_id = 0;
14463 }
14464
14465 plci->B1_resource = 0;
14466 plci->B1_facilities = 0;
14467}
14468
14469
14470
14471
14472
14473static void channel_flow_control_remove(PLCI *plci) {
14474 DIVA_CAPI_ADAPTER *a = plci->adapter;
14475 word i;
14476 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14477 if (a->ch_flow_plci[i] == plci->Id) {
14478 a->ch_flow_plci[i] = 0;
14479 a->ch_flow_control[i] = 0;
14480 }
14481 }
14482}
14483
14484static void channel_x_on(PLCI *plci, byte ch) {
14485 DIVA_CAPI_ADAPTER *a = plci->adapter;
14486 if (a->ch_flow_control[ch] & N_XON_SENT) {
14487 a->ch_flow_control[ch] &= ~N_XON_SENT;
14488 }
14489}
14490
14491static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14492 DIVA_CAPI_ADAPTER *a = plci->adapter;
14493 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14494 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14495 a->ch_flow_plci[ch] = plci->Id;
14496 a->ch_flow_control_pending++;
14497 }
14498}
14499
14500static void channel_request_xon(PLCI *plci, byte ch) {
14501 DIVA_CAPI_ADAPTER *a = plci->adapter;
14502
14503 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14504 a->ch_flow_control[ch] |= N_XON_REQ;
14505 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14506 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14507 }
14508}
14509
14510static void channel_xmit_extended_xon(PLCI *plci) {
14511 DIVA_CAPI_ADAPTER *a;
14512 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14513 int i, one_requested = 0;
14514
14515 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14516 return;
14517 }
14518
14519 for (i = 0; i < max_ch; i++) {
14520 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14521 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14522 (plci->Id == a->ch_flow_plci[i])) {
14523 channel_request_xon(plci, (byte)i);
14524 one_requested = 1;
14525 }
14526 }
14527
14528 if (one_requested) {
14529 channel_xmit_xon(plci);
14530 }
14531}
14532
14533
14534
14535
14536static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14537 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14538 int i;
14539
14540 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14541 return (0);
14542 }
14543
14544 if (a->last_flow_control_ch >= max_ch) {
14545 a->last_flow_control_ch = 1;
14546 }
14547 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14548 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14549 (plci->Id == a->ch_flow_plci[i])) {
14550 a->last_flow_control_ch = i + 1;
14551 return (i);
14552 }
14553 }
14554
14555 for (i = 1; i < a->last_flow_control_ch; i++) {
14556 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14557 (plci->Id == a->ch_flow_plci[i])) {
14558 a->last_flow_control_ch = i + 1;
14559 return (i);
14560 }
14561 }
14562
14563 return (0);
14564}
14565
14566static void channel_xmit_xon(PLCI *plci) {
14567 DIVA_CAPI_ADAPTER *a = plci->adapter;
14568 byte ch;
14569
14570 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14571 return;
14572 }
14573 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14574 return;
14575 }
14576 a->ch_flow_control[ch] &= ~N_XON_REQ;
14577 a->ch_flow_control[ch] |= N_XON_SENT;
14578
14579 plci->NL.Req = plci->nl_req = (byte)N_XON;
14580 plci->NL.ReqCh = ch;
14581 plci->NL.X = plci->NData;
14582 plci->NL.XNum = 1;
14583 plci->NData[0].P = &plci->RBuffer[0];
14584 plci->NData[0].PLength = 0;
14585
14586 plci->adapter->request(&plci->NL);
14587}
14588
14589static int channel_can_xon(PLCI *plci, byte ch) {
14590 APPL *APPLptr;
14591 DIVA_CAPI_ADAPTER *a;
14592 word NCCIcode;
14593 dword count;
14594 word Num;
14595 word i;
14596
14597 APPLptr = plci->appl;
14598 a = plci->adapter;
14599
14600 if (!APPLptr)
14601 return (0);
14602
14603 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14604
14605
14606
14607
14608 count = 0;
14609 Num = 0xffff;
14610 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14611 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14612 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14613 }
14614 if ((count > 2) || (Num == 0xffff)) {
14615 return (0);
14616 }
14617 return (1);
14618}
14619
14620
14621
14622
14623static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14624{
14625 return 1;
14626}
14627
14628
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14639{
14640 word i, j, k, busy, group_found;
14641 dword info_mask_group[MAX_CIP_TYPES];
14642 dword cip_mask_group[MAX_CIP_TYPES];
14643 word appl_number_group_type[MAX_APPL];
14644 PLCI *auxplci;
14645
14646
14647 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14648
14649 if (!a->group_optimization_enabled)
14650 {
14651 dbug(1, dprintf("No group optimization"));
14652 return;
14653 }
14654
14655 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14656
14657 for (i = 0; i < MAX_CIP_TYPES; i++)
14658 {
14659 info_mask_group[i] = 0;
14660 cip_mask_group[i] = 0;
14661 }
14662 for (i = 0; i < MAX_APPL; i++)
14663 {
14664 appl_number_group_type[i] = 0;
14665 }
14666 for (i = 0; i < max_appl; i++)
14667 {
14668 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14669 {
14670 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14671 return;
14672 }
14673 }
14674 for (i = 0; i < max_appl; i++)
14675 {
14676 if (application[i].Id && a->CIP_Mask[i])
14677 {
14678 for (k = 0, busy = false; k < a->max_plci; k++)
14679 {
14680 if (a->plci[k].Id)
14681 {
14682 auxplci = &a->plci[k];
14683 if (auxplci->appl == &application[i]) {
14684
14685 busy = true;
14686 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14687 } else if (test_bit(i, plci->c_ind_mask_table)) {
14688
14689 busy = true;
14690 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14691 }
14692 }
14693 }
14694
14695 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)
14696 {
14697 if (j == MAX_CIP_TYPES)
14698 {
14699 appl_number_group_type[i] = MAX_CIP_TYPES;
14700 group_found = true;
14701 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14702 }
14703 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14704 {
14705 appl_number_group_type[i] = j | 0x80;
14706 group_found = true;
14707 dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14708 }
14709 else if (!info_mask_group[j])
14710 {
14711 appl_number_group_type[i] = j | 0x80;
14712 info_mask_group[j] = a->CIP_Mask[i];
14713 cip_mask_group[j] = a->Info_Mask[i];
14714 group_found = true;
14715 dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14716 }
14717 }
14718 }
14719 }
14720
14721 for (i = 0; i < max_appl; i++)
14722 {
14723 if (appl_number_group_type[i])
14724 {
14725 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14726 {
14727 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14728 }
14729 else
14730 {
14731 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14732 for (j = i + 1; j < max_appl; j++)
14733 {
14734 if (appl_number_group_type[i] == appl_number_group_type[j])
14735 {
14736 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14737
14738 __clear_bit(j, plci->group_optimization_mask_table);
14739 appl_number_group_type[j] = 0;
14740 }
14741 }
14742 }
14743 }
14744 else
14745 {
14746 __clear_bit(i, plci->group_optimization_mask_table);
14747 }
14748 }
14749
14750}
14751
14752
14753
14754
14755word CapiRegister(word id)
14756{
14757 word i, j, appls_found;
14758
14759 PLCI *plci;
14760 DIVA_CAPI_ADAPTER *a;
14761
14762 for (i = 0, appls_found = 0; i < max_appl; i++)
14763 {
14764 if (application[i].Id && (application[i].Id != id))
14765 {
14766 appls_found++;
14767 }
14768 }
14769
14770 if (appls_found) return true;
14771 for (i = 0; i < max_adapter; i++)
14772 {
14773 a = &adapter[i];
14774 if (a->request)
14775 {
14776 if (a->flag_dynamic_l1_down)
14777 {
14778 if (!appls_found)
14779 {
14780 if ((j = get_plci(a)))
14781 {
14782 plci = &a->plci[j - 1];
14783 plci->command = 0;
14784 add_p(plci, OAD, "\x01\xfd");
14785 add_p(plci, CAI, "\x01\x80");
14786 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14787 add_p(plci, SHIFT | 6, NULL);
14788 add_p(plci, SIN, "\x02\x00\x00");
14789 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14790 sig_req(plci, ASSIGN, DSIG_ID);
14791 add_p(plci, FTY, "\x02\xff\x07");
14792 sig_req(plci, SIG_CTRL, 0);
14793 send_req(plci);
14794 }
14795 }
14796 }
14797 }
14798 }
14799 return false;
14800}
14801
14802
14803
14804
14805
14806static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14807{
14808 word i;
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818 if (!plci ||
14819 !plci->appl ||
14820 !plci->State ||
14821 plci->Sig.Ind == NCR_FACILITY
14822 )
14823 return;
14824
14825 for (i = 0; i < MAX_MULTI_IE; i++)
14826 {
14827 if (!parms[i][0]) continue;
14828 if (parms[i][0] < 7)
14829 {
14830 parms[i][0] = 0;
14831 continue;
14832 }
14833 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14834 switch (parms[i][4])
14835 {
14836 case VSJOIN:
14837 if (!plci->relatedPTYPLCI ||
14838 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14839 {
14840 break;
14841 }
14842
14843 if (parms[i][0] != 11 || parms[i][8] != 3)
14844 {
14845 break;
14846 }
14847 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14848 {
14849 plci->vswitchstate = parms[i][9];
14850 parms[i][9] = 2;
14851
14852 }
14853 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14854 {
14855 plci->vswitchstate = parms[i][9];
14856
14857
14858 }
14859 else
14860 {
14861 break;
14862 }
14863 plci->vsprot = parms[i][10];
14864 plci->vsprotdialect = parms[i][11];
14865
14866 parms[i][1] = VSWITCHIE;
14867 parms[i][2] = VSWITCH_REQ;
14868
14869 plci->relatedPTYPLCI->command = 0;
14870 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14871 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14872 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14873 send_req(plci->relatedPTYPLCI);
14874 break;
14875 case VSTRANSPORT:
14876 default:
14877 if (plci->relatedPTYPLCI &&
14878 plci->vswitchstate == 3 &&
14879 plci->relatedPTYPLCI->vswitchstate == 3)
14880 {
14881 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14882 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14883 send_req(plci->relatedPTYPLCI);
14884 }
14885 break;
14886 }
14887 parms[i][0] = 0;
14888 }
14889}
14890
14891
14892
14893
14894static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14895 ENTITY e;
14896 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14897
14898 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14899 return (-1);
14900 }
14901
14902 pReq->xdi_dma_descriptor_operation.Req = 0;
14903 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14904
14905 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14906 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14907 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14908 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14909
14910 e.user[0] = plci->adapter->Id - 1;
14911 plci->adapter->request((ENTITY *)pReq);
14912
14913 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14914 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14915 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14916 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14917 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14918 plci->adapter->Id,
14919 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14920 *dma_magic));
14921 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14922 } else {
14923 dbug(1, dprintf("dma_alloc failed"));
14924 return (-1);
14925 }
14926}
14927
14928static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14929 ENTITY e;
14930 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14931
14932 if (nr < 0) {
14933 return;
14934 }
14935
14936 pReq->xdi_dma_descriptor_operation.Req = 0;
14937 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14938
14939 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14940 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
14941 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14942 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14943
14944 e.user[0] = plci->adapter->Id - 1;
14945 plci->adapter->request((ENTITY *)pReq);
14946
14947 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14948 dbug(1, dprintf("dma_free(%d)", nr));
14949 } else {
14950 dbug(1, dprintf("dma_free failed (%d)", nr));
14951 }
14952}
14953
14954
14955