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 default:
4506 if (plci->internal_command_queue[0])
4507 {
4508 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4509 if (plci->internal_command)
4510 return;
4511 }
4512 break;
4513 }
4514 next_internal_command(Id, plci);
4515 }
4516 }
4517 else
4518 {
4519 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4520 if (plci->tel) Id |= EXT_CONTROLLER;
4521
4522 switch (plci->internal_command)
4523 {
4524 case BLOCK_PLCI:
4525 return;
4526
4527 case START_L1_SIG_ASSIGN_PEND:
4528 case REM_L1_SIG_ASSIGN_PEND:
4529 if (global_req == ASSIGN)
4530 {
4531 break;
4532 }
4533 else
4534 {
4535 dbug(1, dprintf("***L1 Req rem PLCI"));
4536 plci->internal_command = 0;
4537 sig_req(plci, REMOVE, 0);
4538 send_req(plci);
4539 }
4540 break;
4541
4542
4543 case CD_REQ_PEND:
4544 SSparms[1] = S_CALL_DEFLECTION;
4545 if (rc != OK)
4546 {
4547 Info = 0x300E;
4548 }
4549 for (i = 0; i < max_appl; i++)
4550 {
4551 if (application[i].CDEnable)
4552 {
4553 if (!application[i].Id) application[i].CDEnable = 0;
4554 else
4555 {
4556 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4557 plci->number, "wws", Info, (word)3, SSparms);
4558 if (Info) application[i].CDEnable = 0;
4559 }
4560 }
4561 }
4562 plci->internal_command = 0;
4563 break;
4564
4565 case PERM_COD_HOOK:
4566 return;
4567
4568 case PERM_COD_CALL:
4569 plci->internal_command = PERM_COD_CONN_PEND;
4570 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4571 return;
4572
4573 case PERM_COD_ASSIGN:
4574 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4575 plci->internal_command = 0;
4576 if (rc != ASSIGN_OK) break;
4577 plci->internal_command = PERM_COD_CALL;
4578 sig_req(plci, CALL_REQ, 0);
4579 send_req(plci);
4580 return;
4581
4582 case LISTEN_SIG_ASSIGN_PEND:
4583 if (rc == ASSIGN_OK)
4584 {
4585 plci->internal_command = 0;
4586 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4587 add_p(plci, ESC, "\x02\x18\x00");
4588 sig_req(plci, INDICATE_REQ, 0);
4589 send_req(plci);
4590 }
4591 else
4592 {
4593 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4594 a->listen_active--;
4595 plci_remove(plci);
4596 plci->State = IDLE;
4597 }
4598 break;
4599
4600 case USELAW_REQ:
4601 if (global_req == ASSIGN)
4602 {
4603 if (rc == ASSIGN_OK)
4604 {
4605 sig_req(plci, LAW_REQ, 0);
4606 send_req(plci);
4607 dbug(1, dprintf("Auto-Law assigned"));
4608 }
4609 else
4610 {
4611 dbug(1, dprintf("Auto-Law assign failed"));
4612 a->automatic_law = 3;
4613 plci->internal_command = 0;
4614 a->automatic_lawPLCI = NULL;
4615 }
4616 break;
4617 }
4618 else if (req == LAW_REQ && rc == OK)
4619 {
4620 dbug(1, dprintf("Auto-Law initiated"));
4621 a->automatic_law = 2;
4622 plci->internal_command = 0;
4623 }
4624 else
4625 {
4626 dbug(1, dprintf("Auto-Law not supported"));
4627 a->automatic_law = 3;
4628 plci->internal_command = 0;
4629 sig_req(plci, REMOVE, 0);
4630 send_req(plci);
4631 a->automatic_lawPLCI = NULL;
4632 }
4633 break;
4634 }
4635 plci_remove_check(plci);
4636 }
4637}
4638
4639static void data_rc(PLCI *plci, byte ch)
4640{
4641 dword Id;
4642 DIVA_CAPI_ADAPTER *a;
4643 NCCI *ncci_ptr;
4644 DATA_B3_DESC *data;
4645 word ncci;
4646
4647 if (plci->appl)
4648 {
4649 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4650 a = plci->adapter;
4651 ncci = a->ch_ncci[ch];
4652 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4653 {
4654 ncci_ptr = &(a->ncci[ncci]);
4655 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4656 if (ncci_ptr->data_pending)
4657 {
4658 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4659 if (!(data->Flags & 4) && a->ncci_state[ncci])
4660 {
4661 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4662 if (plci->tel) Id |= EXT_CONTROLLER;
4663 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4664 "ww", data->Handle, 0);
4665 }
4666 (ncci_ptr->data_out)++;
4667 if (ncci_ptr->data_out == MAX_DATA_B3)
4668 ncci_ptr->data_out = 0;
4669 (ncci_ptr->data_pending)--;
4670 }
4671 }
4672 }
4673}
4674
4675static void data_ack(PLCI *plci, byte ch)
4676{
4677 dword Id;
4678 DIVA_CAPI_ADAPTER *a;
4679 NCCI *ncci_ptr;
4680 word ncci;
4681
4682 a = plci->adapter;
4683 ncci = a->ch_ncci[ch];
4684 ncci_ptr = &(a->ncci[ncci]);
4685 if (ncci_ptr->data_ack_pending)
4686 {
4687 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4688 {
4689 Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4690 if (plci->tel) Id |= EXT_CONTROLLER;
4691 sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4692 "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4693 }
4694 (ncci_ptr->data_ack_out)++;
4695 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4696 ncci_ptr->data_ack_out = 0;
4697 (ncci_ptr->data_ack_pending)--;
4698 }
4699}
4700
4701static void sig_ind(PLCI *plci)
4702{
4703 dword x_Id;
4704 dword Id;
4705 dword rId;
4706 word i;
4707 word cip;
4708 dword cip_mask;
4709 byte *ie;
4710 DIVA_CAPI_ADAPTER *a;
4711 API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4712#define MAXPARMSIDS 31
4713 byte *parms[MAXPARMSIDS];
4714 byte *add_i[4];
4715 byte *multi_fac_parms[MAX_MULTI_IE];
4716 byte *multi_pi_parms[MAX_MULTI_IE];
4717 byte *multi_ssext_parms[MAX_MULTI_IE];
4718 byte *multi_CiPN_parms[MAX_MULTI_IE];
4719
4720 byte *multi_vswitch_parms[MAX_MULTI_IE];
4721
4722 byte ai_len;
4723 byte *esc_chi = "";
4724 byte *esc_law = "";
4725 byte *pty_cai = "";
4726 byte *esc_cr = "";
4727 byte *esc_profile = "";
4728
4729 byte facility[256];
4730 PLCI *tplci = NULL;
4731 byte chi[] = "\x02\x18\x01";
4732 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4733 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4734
4735
4736
4737
4738 static const word parms_id[] =
4739 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4740 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4741 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4742 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4743
4744
4745
4746 static const word multi_fac_id[] = {1, FTY};
4747 static const word multi_pi_id[] = {1, PI};
4748 static const word multi_CiPN_id[] = {1, OAD};
4749 static const word multi_ssext_id[] = {1, ESC_SSEXT};
4750
4751 static const word multi_vswitch_id[] = {1, ESC_VSWITCH};
4752
4753 byte *cau;
4754 word ncci;
4755 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00";
4756 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4757 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4758 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4759 byte force_mt_info = false;
4760 byte dir;
4761 dword d;
4762 word w;
4763
4764 a = plci->adapter;
4765 Id = ((word)plci->Id << 8) | a->Id;
4766 PUT_WORD(&SS_Ind[4], 0x0000);
4767
4768 if (plci->sig_remove_id)
4769 {
4770 plci->Sig.RNR = 2;
4771 dbug(1, dprintf("SIG discard while remove pending"));
4772 return;
4773 }
4774 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4775 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4776 Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4777 if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4778 {
4779 plci->Sig.RNR = 1;
4780 return;
4781 }
4782 if (plci->Sig.Ind == HANGUP && plci->channels)
4783 {
4784 plci->Sig.RNR = 1;
4785 plci->hangup_flow_ctrl_timer++;
4786
4787 if (plci->hangup_flow_ctrl_timer == 100)
4788 {
4789 dbug(1, dprintf("Exceptional disc"));
4790 plci->Sig.RNR = 0;
4791 plci->hangup_flow_ctrl_timer = 0;
4792 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4793 {
4794 if (a->ncci_plci[ncci] == plci->Id)
4795 {
4796 cleanup_ncci_data(plci, ncci);
4797 if (plci->channels)plci->channels--;
4798 if (plci->appl)
4799 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4800 }
4801 }
4802 if (plci->appl)
4803 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4804 plci_remove(plci);
4805 plci->State = IDLE;
4806 }
4807 return;
4808 }
4809
4810
4811
4812
4813 IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4814 IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4815 IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4816
4817 IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4818
4819 IndParse(plci, parms_id, parms, 0);
4820 IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4821 esc_chi = parms[14];
4822 esc_law = parms[18];
4823 pty_cai = parms[24];
4824 esc_cr = parms[25];
4825 esc_profile = parms[27];
4826 if (esc_cr[0] && plci)
4827 {
4828 if (plci->cr_enquiry && plci->appl)
4829 {
4830 plci->cr_enquiry = false;
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840 sendf(plci->appl,
4841 _MANUFACTURER_I,
4842 Id,
4843 0,
4844 "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4845 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);
4846 }
4847 }
4848
4849 add_i[1] = parms[15];
4850 add_i[2] = parms[11];
4851 ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4852
4853
4854
4855
4856 if (a->automatic_law < 4)
4857 {
4858 if (esc_law[0]) {
4859 if (esc_law[2]) {
4860 dbug(0, dprintf("u-Law selected"));
4861 a->u_law = 1;
4862 }
4863 else {
4864 dbug(0, dprintf("a-Law selected"));
4865 a->u_law = 0;
4866 }
4867 a->automatic_law = 4;
4868 if (plci == a->automatic_lawPLCI) {
4869 plci->internal_command = 0;
4870 sig_req(plci, REMOVE, 0);
4871 send_req(plci);
4872 a->automatic_lawPLCI = NULL;
4873 }
4874 }
4875 if (esc_profile[0])
4876 {
4877 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4878 UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4879 GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4880 GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4881
4882 a->profile.Global_Options &= 0x000000ffL;
4883 a->profile.B1_Protocols &= 0x000003ffL;
4884 a->profile.B2_Protocols &= 0x00001fdfL;
4885 a->profile.B3_Protocols &= 0x000000b7L;
4886
4887 a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4888 GL_BCHANNEL_OPERATION_SUPPORTED;
4889 a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4890 a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4891 a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4892 a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4893 a->man_profile.private_options = 0;
4894
4895 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4896 {
4897 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4898 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4899 }
4900
4901
4902 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4903 a->man_profile.private_options |= 1L << PRIVATE_RTP;
4904 a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4905 a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4906
4907
4908 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4909 a->man_profile.private_options |= 1L << PRIVATE_T38;
4910
4911
4912 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4913 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4914
4915
4916 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4917 a->man_profile.private_options |= 1L << PRIVATE_V18;
4918
4919
4920 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4921 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4922
4923
4924 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4925 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4926
4927
4928 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4929 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4930
4931
4932 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4933 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4934
4935
4936 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4937 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4938
4939 }
4940 else
4941 {
4942 a->profile.Global_Options &= 0x0000007fL;
4943 a->profile.B1_Protocols &= 0x000003dfL;
4944 a->profile.B2_Protocols &= 0x00001adfL;
4945 a->profile.B3_Protocols &= 0x000000b7L;
4946 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4947 }
4948 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4949 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4950 {
4951 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4952 }
4953 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4954 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4955 UnMapController(a->Id), a->profile.Global_Options,
4956 a->profile.B1_Protocols, a->profile.B2_Protocols,
4957 a->profile.B3_Protocols, a->manufacturer_features));
4958 }
4959
4960 if (plci != a->AdvCodecPLCI)
4961 {
4962 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4963 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4964 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4965 SendInfo(plci, Id, parms, force_mt_info);
4966
4967 VSwitchReqInd(plci, Id, multi_vswitch_parms);
4968
4969 }
4970
4971
4972 if (esc_chi[0] && plci && !plci->SuppState) {
4973 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4974 mixer_set_bchannel_id_esc(plci, plci->b_channel);
4975 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4976 if (plci->tel == ADV_VOICE && plci->appl) {
4977 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4978 }
4979 }
4980
4981 if (plci->appl) plci->appl->Number++;
4982
4983 switch (plci->Sig.Ind) {
4984
4985 case S_SUPPORTED:
4986 dbug(1, dprintf("S_Supported"));
4987 if (!plci->appl) break;
4988 if (pty_cai[0] == 4)
4989 {
4990 PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4991 }
4992 else
4993 {
4994 PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4995 }
4996 PUT_WORD(&CF_Ind[1], 0);
4997 PUT_WORD(&CF_Ind[4], 0);
4998 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
4999 plci_remove(plci);
5000 break;
5001
5002
5003 case S_SERVICE_REJ:
5004 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5005 if (!pty_cai[0]) break;
5006 switch (pty_cai[5])
5007 {
5008 case ECT_EXECUTE:
5009 case THREE_PTY_END:
5010 case THREE_PTY_BEGIN:
5011 if (!plci->relatedPTYPLCI) break;
5012 tplci = plci->relatedPTYPLCI;
5013 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5014 if (tplci->tel) rId |= EXT_CONTROLLER;
5015 if (pty_cai[5] == ECT_EXECUTE)
5016 {
5017 PUT_WORD(&SS_Ind[1], S_ECT);
5018
5019 plci->vswitchstate = 0;
5020 plci->relatedPTYPLCI->vswitchstate = 0;
5021
5022 }
5023 else
5024 {
5025 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5026 }
5027 if (pty_cai[2] != 0xff)
5028 {
5029 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5030 }
5031 else
5032 {
5033 PUT_WORD(&SS_Ind[4], 0x300E);
5034 }
5035 plci->relatedPTYPLCI = NULL;
5036 plci->ptyState = 0;
5037 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5038 break;
5039
5040 case CALL_DEFLECTION:
5041 if (pty_cai[2] != 0xff)
5042 {
5043 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5044 }
5045 else
5046 {
5047 PUT_WORD(&SS_Ind[4], 0x300E);
5048 }
5049 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5050 for (i = 0; i < max_appl; i++)
5051 {
5052 if (application[i].CDEnable)
5053 {
5054 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5055 application[i].CDEnable = false;
5056 }
5057 }
5058 break;
5059
5060 case DEACTIVATION_DIVERSION:
5061 case ACTIVATION_DIVERSION:
5062 case DIVERSION_INTERROGATE_CFU:
5063 case DIVERSION_INTERROGATE_CFB:
5064 case DIVERSION_INTERROGATE_CFNR:
5065 case DIVERSION_INTERROGATE_NUM:
5066 case CCBS_REQUEST:
5067 case CCBS_DEACTIVATE:
5068 case CCBS_INTERROGATE:
5069 if (!plci->appl) break;
5070 if (pty_cai[2] != 0xff)
5071 {
5072 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5073 }
5074 else
5075 {
5076 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5077 }
5078 switch (pty_cai[5])
5079 {
5080 case DEACTIVATION_DIVERSION:
5081 dbug(1, dprintf("Deact_Div"));
5082 Interr_Err_Ind[0] = 0x9;
5083 Interr_Err_Ind[3] = 0x6;
5084 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5085 break;
5086 case ACTIVATION_DIVERSION:
5087 dbug(1, dprintf("Act_Div"));
5088 Interr_Err_Ind[0] = 0x9;
5089 Interr_Err_Ind[3] = 0x6;
5090 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5091 break;
5092 case DIVERSION_INTERROGATE_CFU:
5093 case DIVERSION_INTERROGATE_CFB:
5094 case DIVERSION_INTERROGATE_CFNR:
5095 dbug(1, dprintf("Interr_Div"));
5096 Interr_Err_Ind[0] = 0xa;
5097 Interr_Err_Ind[3] = 0x7;
5098 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5099 break;
5100 case DIVERSION_INTERROGATE_NUM:
5101 dbug(1, dprintf("Interr_Num"));
5102 Interr_Err_Ind[0] = 0xa;
5103 Interr_Err_Ind[3] = 0x7;
5104 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5105 break;
5106 case CCBS_REQUEST:
5107 dbug(1, dprintf("CCBS Request"));
5108 Interr_Err_Ind[0] = 0xd;
5109 Interr_Err_Ind[3] = 0xa;
5110 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5111 break;
5112 case CCBS_DEACTIVATE:
5113 dbug(1, dprintf("CCBS Deactivate"));
5114 Interr_Err_Ind[0] = 0x9;
5115 Interr_Err_Ind[3] = 0x6;
5116 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5117 break;
5118 case CCBS_INTERROGATE:
5119 dbug(1, dprintf("CCBS Interrogate"));
5120 Interr_Err_Ind[0] = 0xb;
5121 Interr_Err_Ind[3] = 0x8;
5122 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5123 break;
5124 }
5125 PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5126 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5127 plci_remove(plci);
5128 break;
5129 case ACTIVATION_MWI:
5130 case DEACTIVATION_MWI:
5131 if (pty_cai[5] == ACTIVATION_MWI)
5132 {
5133 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5134 }
5135 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5136
5137 if (pty_cai[2] != 0xff)
5138 {
5139 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5140 }
5141 else
5142 {
5143 PUT_WORD(&SS_Ind[4], 0x300E);
5144 }
5145
5146 if (plci->cr_enquiry)
5147 {
5148 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5149 plci_remove(plci);
5150 }
5151 else
5152 {
5153 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5154 }
5155 break;
5156 case CONF_ADD:
5157 case CONF_BEGIN:
5158 case CONF_DROP:
5159 case CONF_ISOLATE:
5160 case CONF_REATTACH:
5161 CONF_Ind[0] = 9;
5162 CONF_Ind[3] = 6;
5163 switch (pty_cai[5])
5164 {
5165 case CONF_BEGIN:
5166 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5167 plci->ptyState = 0;
5168 break;
5169 case CONF_DROP:
5170 CONF_Ind[0] = 5;
5171 CONF_Ind[3] = 2;
5172 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5173 plci->ptyState = CONNECTED;
5174 break;
5175 case CONF_ISOLATE:
5176 CONF_Ind[0] = 5;
5177 CONF_Ind[3] = 2;
5178 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5179 plci->ptyState = CONNECTED;
5180 break;
5181 case CONF_REATTACH:
5182 CONF_Ind[0] = 5;
5183 CONF_Ind[3] = 2;
5184 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5185 plci->ptyState = CONNECTED;
5186 break;
5187 case CONF_ADD:
5188 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5189 plci->relatedPTYPLCI = NULL;
5190 tplci = plci->relatedPTYPLCI;
5191 if (tplci) tplci->ptyState = CONNECTED;
5192 plci->ptyState = CONNECTED;
5193 break;
5194 }
5195
5196 if (pty_cai[2] != 0xff)
5197 {
5198 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5199 }
5200 else
5201 {
5202 PUT_WORD(&CONF_Ind[4], 0x3303);
5203
5204 }
5205
5206 PUT_DWORD(&CONF_Ind[6], 0x0);
5207 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5208 break;
5209 }
5210 break;
5211
5212
5213 case S_SERVICE:
5214 dbug(1, dprintf("Service_Ind"));
5215 PUT_WORD(&CF_Ind[4], 0);
5216 switch (pty_cai[5])
5217 {
5218 case THREE_PTY_END:
5219 case THREE_PTY_BEGIN:
5220 case ECT_EXECUTE:
5221 if (!plci->relatedPTYPLCI) break;
5222 tplci = plci->relatedPTYPLCI;
5223 rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5224 if (tplci->tel) rId |= EXT_CONTROLLER;
5225 if (pty_cai[5] == ECT_EXECUTE)
5226 {
5227 PUT_WORD(&SS_Ind[1], S_ECT);
5228
5229 if (plci->vswitchstate != 3)
5230 {
5231
5232 plci->ptyState = IDLE;
5233 plci->relatedPTYPLCI = NULL;
5234 plci->ptyState = 0;
5235
5236 }
5237
5238 dbug(1, dprintf("ECT OK"));
5239 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5240
5241
5242
5243 }
5244 else
5245 {
5246 switch (plci->ptyState)
5247 {
5248 case S_3PTY_BEGIN:
5249 plci->ptyState = CONNECTED;
5250 dbug(1, dprintf("3PTY ON"));
5251 break;
5252
5253 case S_3PTY_END:
5254 plci->ptyState = IDLE;
5255 plci->relatedPTYPLCI = NULL;
5256 plci->ptyState = 0;
5257 dbug(1, dprintf("3PTY OFF"));
5258 break;
5259 }
5260 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5261 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5262 }
5263 break;
5264
5265 case CALL_DEFLECTION:
5266 PUT_WORD(&SS_Ind[1], pty_cai[5]);
5267 for (i = 0; i < max_appl; i++)
5268 {
5269 if (application[i].CDEnable)
5270 {
5271 if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5272 application[i].CDEnable = false;
5273 }
5274 }
5275 break;
5276
5277 case DEACTIVATION_DIVERSION:
5278 case ACTIVATION_DIVERSION:
5279 if (!plci->appl) break;
5280 PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5281 PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5282 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5283 plci_remove(plci);
5284 break;
5285
5286 case DIVERSION_INTERROGATE_CFU:
5287 case DIVERSION_INTERROGATE_CFB:
5288 case DIVERSION_INTERROGATE_CFNR:
5289 case DIVERSION_INTERROGATE_NUM:
5290 case CCBS_REQUEST:
5291 case CCBS_DEACTIVATE:
5292 case CCBS_INTERROGATE:
5293 if (!plci->appl) break;
5294 switch (pty_cai[5])
5295 {
5296 case DIVERSION_INTERROGATE_CFU:
5297 case DIVERSION_INTERROGATE_CFB:
5298 case DIVERSION_INTERROGATE_CFNR:
5299 dbug(1, dprintf("Interr_Div"));
5300 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5301 pty_cai[3] = pty_cai[0] - 3;
5302 break;
5303 case DIVERSION_INTERROGATE_NUM:
5304 dbug(1, dprintf("Interr_Num"));
5305 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5306 pty_cai[3] = pty_cai[0] - 3;
5307 break;
5308 case CCBS_REQUEST:
5309 dbug(1, dprintf("CCBS Request"));
5310 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5311 pty_cai[3] = pty_cai[0] - 3;
5312 break;
5313 case CCBS_DEACTIVATE:
5314 dbug(1, dprintf("CCBS Deactivate"));
5315 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5316 pty_cai[3] = pty_cai[0] - 3;
5317 break;
5318 case CCBS_INTERROGATE:
5319 dbug(1, dprintf("CCBS Interrogate"));
5320 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5321 pty_cai[3] = pty_cai[0] - 3;
5322 break;
5323 }
5324 PUT_WORD(&pty_cai[4], 0);
5325 PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5326 sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5327 plci_remove(plci);
5328 break;
5329
5330 case ACTIVATION_MWI:
5331 case DEACTIVATION_MWI:
5332 if (pty_cai[5] == ACTIVATION_MWI)
5333 {
5334 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5335 }
5336 else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5337 if (plci->cr_enquiry)
5338 {
5339 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5340 plci_remove(plci);
5341 }
5342 else
5343 {
5344 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5345 }
5346 break;
5347 case MWI_INDICATION:
5348 if (pty_cai[0] >= 0x12)
5349 {
5350 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5351 pty_cai[2] = pty_cai[0] - 2;
5352 pty_cai[5] = pty_cai[0] - 5;
5353 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5354 {
5355 if (plci->internal_command == GET_MWI_STATE)
5356 {
5357 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5358 plci_remove(plci);
5359 return;
5360 }
5361 else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5362 pty_cai[0] = 0;
5363 }
5364 else
5365 {
5366 for (i = 0; i < max_appl; i++)
5367 {
5368 if (a->Notification_Mask[i]&SMASK_MWI)
5369 {
5370 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5371 pty_cai[0] = 0;
5372 }
5373 }
5374 }
5375
5376 if (!pty_cai[0])
5377 {
5378 facility[2] = 0;
5379 }
5380 else facility[2] = 0xff;
5381 }
5382 else
5383 {
5384
5385 facility[2] = 0xff;
5386 }
5387 facility[0] = 2;
5388 facility[1] = MWI_RESPONSE;
5389 add_p(plci, CAI, facility);
5390 add_p(plci, ESC, multi_ssext_parms[0]);
5391 sig_req(plci, S_SERVICE, 0);
5392 send_req(plci);
5393 plci->command = 0;
5394 next_internal_command(Id, plci);
5395 break;
5396 case CONF_ADD:
5397 case CONF_BEGIN:
5398 case CONF_DROP:
5399 case CONF_ISOLATE:
5400 case CONF_REATTACH:
5401 case CONF_PARTYDISC:
5402 CONF_Ind[0] = 9;
5403 CONF_Ind[3] = 6;
5404 switch (pty_cai[5])
5405 {
5406 case CONF_BEGIN:
5407 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5408 if (pty_cai[0] == 6)
5409 {
5410 d = pty_cai[6];
5411 PUT_DWORD(&CONF_Ind[6], d);
5412 }
5413 else
5414 {
5415 PUT_DWORD(&CONF_Ind[6], 0x0);
5416 }
5417 break;
5418 case CONF_ISOLATE:
5419 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5420 CONF_Ind[0] = 5;
5421 CONF_Ind[3] = 2;
5422 break;
5423 case CONF_REATTACH:
5424 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5425 CONF_Ind[0] = 5;
5426 CONF_Ind[3] = 2;
5427 break;
5428 case CONF_DROP:
5429 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5430 CONF_Ind[0] = 5;
5431 CONF_Ind[3] = 2;
5432 break;
5433 case CONF_ADD:
5434 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5435 d = pty_cai[6];
5436 PUT_DWORD(&CONF_Ind[6], d);
5437 tplci = plci->relatedPTYPLCI;
5438 if (tplci) tplci->ptyState = CONNECTED;
5439 break;
5440 case CONF_PARTYDISC:
5441 CONF_Ind[0] = 7;
5442 CONF_Ind[3] = 4;
5443 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5444 d = pty_cai[6];
5445 PUT_DWORD(&CONF_Ind[4], d);
5446 break;
5447 }
5448 plci->ptyState = CONNECTED;
5449 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5450 break;
5451 case CCBS_INFO_RETAIN:
5452 case CCBS_ERASECALLLINKAGEID:
5453 case CCBS_STOP_ALERTING:
5454 CONF_Ind[0] = 5;
5455 CONF_Ind[3] = 2;
5456 switch (pty_cai[5])
5457 {
5458 case CCBS_INFO_RETAIN:
5459 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5460 break;
5461 case CCBS_STOP_ALERTING:
5462 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5463 break;
5464 case CCBS_ERASECALLLINKAGEID:
5465 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5466 CONF_Ind[0] = 7;
5467 CONF_Ind[3] = 4;
5468 CONF_Ind[6] = 0;
5469 CONF_Ind[7] = 0;
5470 break;
5471 }
5472 w = pty_cai[6];
5473 PUT_WORD(&CONF_Ind[4], w);
5474
5475 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5476 {
5477 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5478 }
5479 else
5480 {
5481 for (i = 0; i < max_appl; i++)
5482 if (a->Notification_Mask[i] & SMASK_CCBS)
5483 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5484 }
5485 break;
5486 }
5487 break;
5488 case CALL_HOLD_REJ:
5489 cau = parms[7];
5490 if (cau)
5491 {
5492 i = _L3_CAUSE | cau[2];
5493 if (cau[2] == 0) i = 0x3603;
5494 }
5495 else
5496 {
5497 i = 0x3603;
5498 }
5499 PUT_WORD(&SS_Ind[1], S_HOLD);
5500 PUT_WORD(&SS_Ind[4], i);
5501 if (plci->SuppState == HOLD_REQUEST)
5502 {
5503 plci->SuppState = IDLE;
5504 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5505 }
5506 break;
5507
5508 case CALL_HOLD_ACK:
5509 if (plci->SuppState == HOLD_REQUEST)
5510 {
5511 plci->SuppState = CALL_HELD;
5512 CodecIdCheck(a, plci);
5513 start_internal_command(Id, plci, hold_save_command);
5514 }
5515 break;
5516
5517 case CALL_RETRIEVE_REJ:
5518 cau = parms[7];
5519 if (cau)
5520 {
5521 i = _L3_CAUSE | cau[2];
5522 if (cau[2] == 0) i = 0x3603;
5523 }
5524 else
5525 {
5526 i = 0x3603;
5527 }
5528 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5529 PUT_WORD(&SS_Ind[4], i);
5530 if (plci->SuppState == RETRIEVE_REQUEST)
5531 {
5532 plci->SuppState = CALL_HELD;
5533 CodecIdCheck(a, plci);
5534 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5535 }
5536 break;
5537
5538 case CALL_RETRIEVE_ACK:
5539 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5540 if (plci->SuppState == RETRIEVE_REQUEST)
5541 {
5542 plci->SuppState = IDLE;
5543 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5544 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5545 if (plci->tel)
5546 {
5547 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5548 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5549 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5550 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5551 {
5552 dbug(1, dprintf("Get B-ch"));
5553 start_internal_command(Id, plci, retrieve_restore_command);
5554 }
5555 else
5556 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5557 }
5558 else
5559 start_internal_command(Id, plci, retrieve_restore_command);
5560 }
5561 break;
5562
5563 case INDICATE_IND:
5564 if (plci->State != LISTENING) {
5565 sig_req(plci, HANGUP, 0);
5566 send_req(plci);
5567 break;
5568 }
5569 cip = find_cip(a, parms[4], parms[6]);
5570 cip_mask = 1L << cip;
5571 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5572 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5573 if (!remove_started && !a->adapter_disabled)
5574 {
5575 group_optimization(a, plci);
5576 for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5577 if (application[i].Id
5578 && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5579 && CPN_filter_ok(parms[0], a, i)) {
5580 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5581 __set_bit(i, plci->c_ind_mask_table);
5582 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5583 plci->State = INC_CON_PENDING;
5584 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5585 CALL_DIR_IN | CALL_DIR_ANSWER;
5586 if (esc_chi[0]) {
5587 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5588 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5589 }
5590
5591
5592 if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5593 if (a->profile.Global_Options & HANDSET)
5594 plci->tel = ADV_VOICE;
5595 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5596 plci->tel = CODEC;
5597 if (plci->tel) Id |= EXT_CONTROLLER;
5598 a->codec_listen[i] = plci;
5599 }
5600
5601 sendf(&application[i], _CONNECT_I, Id, 0,
5602 "wSSSSSSSbSSSSS", cip,
5603 parms[0],
5604 multi_CiPN_parms[0],
5605 parms[2],
5606 parms[3],
5607 parms[4],
5608 parms[5],
5609 parms[6],
5610 ai_len,
5611 add_i[0],
5612 add_i[1],
5613 add_i[2],
5614 add_i[3],
5615 multi_CiPN_parms[1]
5616 );
5617 SendSSExtInd(&application[i],
5618 plci,
5619 Id,
5620 multi_ssext_parms);
5621 SendSetupInfo(&application[i],
5622 plci,
5623 Id,
5624 parms,
5625 SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5626 }
5627 }
5628 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5629 }
5630 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5631 sig_req(plci, HANGUP, 0);
5632 send_req(plci);
5633 plci->State = IDLE;
5634 }
5635 plci->notifiedcall = 0;
5636 a->listen_active--;
5637 listen_check(a);
5638 break;
5639
5640 case CALL_PEND_NOTIFY:
5641 plci->notifiedcall = 1;
5642 listen_check(a);
5643 break;
5644
5645 case CALL_IND:
5646 case CALL_CON:
5647 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5648 {
5649 if (plci->internal_command == PERM_COD_CONN_PEND)
5650 {
5651 if (plci->State == ADVANCED_VOICE_NOSIG)
5652 {
5653 dbug(1, dprintf("***Codec OK"));
5654 if (a->AdvSignalPLCI)
5655 {
5656 tplci = a->AdvSignalPLCI;
5657 if (tplci->spoofed_msg)
5658 {
5659 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5660 tplci->command = 0;
5661 tplci->internal_command = 0;
5662 x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5663 switch (tplci->spoofed_msg)
5664 {
5665 case CALL_RES:
5666 tplci->command = _CONNECT_I | RESPONSE;
5667 api_load_msg(&tplci->saved_msg, saved_parms);
5668 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5669 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5670 {
5671
5672 add_p(tplci, LLI, "\x01\x01");
5673 }
5674 add_s(tplci, CONN_NR, &saved_parms[2]);
5675 add_s(tplci, LLC, &saved_parms[4]);
5676 add_ai(tplci, &saved_parms[5]);
5677 tplci->State = INC_CON_ACCEPT;
5678 sig_req(tplci, CALL_RES, 0);
5679 send_req(tplci);
5680 break;
5681
5682 case AWAITING_SELECT_B:
5683 dbug(1, dprintf("Select_B continue"));
5684 start_internal_command(x_Id, tplci, select_b_command);
5685 break;
5686
5687 case AWAITING_MANUF_CON:
5688 if (!tplci->Sig.Id)
5689 {
5690 dbug(1, dprintf("No SigID!"));
5691 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5692 plci_remove(tplci);
5693 break;
5694 }
5695 tplci->command = _MANUFACTURER_R;
5696 api_load_msg(&tplci->saved_msg, saved_parms);
5697 dir = saved_parms[2].info[0];
5698 if (dir == 1) {
5699 sig_req(tplci, CALL_REQ, 0);
5700 }
5701 else if (!dir) {
5702 sig_req(tplci, LISTEN_REQ, 0);
5703 }
5704 send_req(tplci);
5705 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5706 break;
5707
5708 case (CALL_REQ | AWAITING_MANUF_CON):
5709 sig_req(tplci, CALL_REQ, 0);
5710 send_req(tplci);
5711 break;
5712
5713 case CALL_REQ:
5714 if (!tplci->Sig.Id)
5715 {
5716 dbug(1, dprintf("No SigID!"));
5717 sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5718 plci_remove(tplci);
5719 break;
5720 }
5721 tplci->command = _CONNECT_R;
5722 api_load_msg(&tplci->saved_msg, saved_parms);
5723 add_s(tplci, CPN, &saved_parms[1]);
5724 add_s(tplci, DSA, &saved_parms[3]);
5725 add_ai(tplci, &saved_parms[9]);
5726 sig_req(tplci, CALL_REQ, 0);
5727 send_req(tplci);
5728 break;
5729
5730 case CALL_RETRIEVE:
5731 tplci->command = C_RETRIEVE_REQ;
5732 sig_req(tplci, CALL_RETRIEVE, 0);
5733 send_req(tplci);
5734 break;
5735 }
5736 tplci->spoofed_msg = 0;
5737 if (tplci->internal_command == 0)
5738 next_internal_command(x_Id, tplci);
5739 }
5740 }
5741 next_internal_command(Id, plci);
5742 break;
5743 }
5744 dbug(1, dprintf("***Codec Hook Init Req"));
5745 plci->internal_command = PERM_COD_HOOK;
5746 add_p(plci, FTY, "\x01\x09");
5747 sig_req(plci, TEL_CTRL, 0);
5748 send_req(plci);
5749 }
5750 }
5751 else if (plci->command != _MANUFACTURER_R
5752 && plci->State != INC_ACT_PENDING)
5753 {
5754 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5755 if (plci->tel == ADV_VOICE && plci->SuppState == IDLE)
5756 {
5757 chi[2] = plci->b_channel;
5758 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5759 }
5760 sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5761 plci->State = INC_ACT_PENDING;
5762 }
5763 break;
5764
5765 case TEL_CTRL:
5766 ie = multi_fac_parms[0];
5767 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5768 switch (ie[1] & 0x91) {
5769 case 0x80:
5770 case 0x81:
5771 if (plci->internal_command == PERM_COD_HOOK)
5772 {
5773 dbug(1, dprintf("init:hook_off"));
5774 plci->hook_state = ie[1];
5775 next_internal_command(Id, plci);
5776 break;
5777 }
5778 else
5779 {
5780 if (((plci->hook_state) & 0xf0) == 0x80)
5781 {
5782 dbug(1, dprintf("ignore hook"));
5783 break;
5784 }
5785 plci->hook_state = ie[1]&0x91;
5786 }
5787
5788
5789
5790
5791 for (i = 0, tplci = NULL; i < max_appl; i++) {
5792 if (a->codec_listen[i]
5793 && (a->codec_listen[i]->State == INC_CON_PENDING
5794 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5795 tplci = a->codec_listen[i];
5796 tplci->appl = &application[i];
5797 }
5798 }
5799
5800
5801 if (!a->AdvSignalPLCI && !tplci) {
5802 if ((i = get_plci(a))) {
5803 a->AdvSignalPLCI = &a->plci[i - 1];
5804 tplci = a->AdvSignalPLCI;
5805 tplci->tel = ADV_VOICE;
5806 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5807 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5808
5809 add_p(tplci, LLI, "\x01\x01");
5810 }
5811 add_p(tplci, CAI, voice_cai);
5812 add_p(tplci, OAD, a->TelOAD);
5813 add_p(tplci, OSA, a->TelOSA);
5814 add_p(tplci, SHIFT | 6, NULL);
5815 add_p(tplci, SIN, "\x02\x01\x00");
5816 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5817 sig_req(tplci, ASSIGN, DSIG_ID);
5818 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5819 a->AdvSignalPLCI->command = 0;
5820 tplci->appl = a->AdvSignalAppl;
5821 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5822 send_req(tplci);
5823 }
5824
5825 }
5826
5827 if (!tplci) break;
5828 Id = ((word)tplci->Id << 8) | a->Id;
5829 Id |= EXT_CONTROLLER;
5830 sendf(tplci->appl,
5831 _FACILITY_I,
5832 Id,
5833 0,
5834 "ws", (word)0, "\x01+");
5835 break;
5836
5837 case 0x90:
5838 case 0x91:
5839 if (plci->internal_command == PERM_COD_HOOK)
5840 {
5841 dbug(1, dprintf("init:hook_on"));
5842 plci->hook_state = ie[1] & 0x91;
5843 next_internal_command(Id, plci);
5844 break;
5845 }
5846 else
5847 {
5848 if (((plci->hook_state) & 0xf0) == 0x90) break;
5849 plci->hook_state = ie[1] & 0x91;
5850 }
5851
5852 if (a->AdvSignalPLCI) {
5853 Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5854 if (plci->tel) Id |= EXT_CONTROLLER;
5855 sendf(a->AdvSignalAppl,
5856 _FACILITY_I,
5857 Id,
5858 0,
5859 "ws", (word)0, "\x01-");
5860 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5861 a->AdvSignalPLCI->command = 0;
5862 sig_req(a->AdvSignalPLCI, HANGUP, 0);
5863 send_req(a->AdvSignalPLCI);
5864 }
5865 break;
5866 }
5867 }
5868 break;
5869
5870 case RESUME:
5871 __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5872 PUT_WORD(&resume_cau[4], GOOD);
5873 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5874 break;
5875
5876 case SUSPEND:
5877 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5878
5879 if (plci->NL.Id && !plci->nl_remove_id) {
5880 mixer_remove(plci);
5881 nl_req_ncci(plci, REMOVE, 0);
5882 }
5883 if (!plci->sig_remove_id) {
5884 plci->internal_command = 0;
5885 sig_req(plci, REMOVE, 0);
5886 }
5887 send_req(plci);
5888 if (!plci->channels) {
5889 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5890 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5891 }
5892 break;
5893
5894 case SUSPEND_REJ:
5895 break;
5896
5897 case HANGUP:
5898 plci->hangup_flow_ctrl_timer = 0;
5899 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5900 cau = parms[7];
5901 if (cau) {
5902 i = _L3_CAUSE | cau[2];
5903 if (cau[2] == 0) i = 0;
5904 else if (cau[2] == 8) i = _L1_ERROR;
5905 else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5906 else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5907 }
5908 else {
5909 i = _L3_ERROR;
5910 }
5911
5912 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5913 {
5914 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5915 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5916 }
5917 else
5918 {
5919 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5920 }
5921 if (!plci->appl)
5922 {
5923 if (plci->State == LISTENING)
5924 {
5925 plci->notifiedcall = 0;
5926 a->listen_active--;
5927 }
5928 plci->State = INC_DIS_PENDING;
5929 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5930 {
5931 plci->State = IDLE;
5932 if (plci->NL.Id && !plci->nl_remove_id)
5933 {
5934 mixer_remove(plci);
5935 nl_req_ncci(plci, REMOVE, 0);
5936 }
5937 if (!plci->sig_remove_id)
5938 {
5939 plci->internal_command = 0;
5940 sig_req(plci, REMOVE, 0);
5941 }
5942 send_req(plci);
5943 }
5944 }
5945 else
5946 {
5947
5948
5949
5950 if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5951 {
5952 if (plci->State == RESUMING)
5953 {
5954 PUT_WORD(&resume_cau[4], i);
5955 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5956 }
5957 plci->State = INC_DIS_PENDING;
5958 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5959 }
5960 }
5961 break;
5962
5963 case SSEXT_IND:
5964 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5965 break;
5966
5967 case VSWITCH_REQ:
5968 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5969 break;
5970 case VSWITCH_IND:
5971 if (plci->relatedPTYPLCI &&
5972 plci->vswitchstate == 3 &&
5973 plci->relatedPTYPLCI->vswitchstate == 3 &&
5974 parms[MAXPARMSIDS - 1][0])
5975 {
5976 add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5977 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5978 send_req(plci->relatedPTYPLCI);
5979 }
5980 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5981 break;
5982
5983 }
5984}
5985
5986
5987static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5988{
5989 word i;
5990 byte *ie;
5991 word Info_Number;
5992 byte *Info_Element;
5993 word Info_Mask = 0;
5994
5995 dbug(1, dprintf("SetupInfo"));
5996
5997 for (i = 0; i < MAXPARMSIDS; i++) {
5998 ie = parms[i];
5999 Info_Number = 0;
6000 Info_Element = ie;
6001 if (ie[0]) {
6002 switch (i) {
6003 case 0:
6004 dbug(1, dprintf("CPN "));
6005 Info_Number = 0x0070;
6006 Info_Mask = 0x80;
6007 Info_Sent_Flag = true;
6008 break;
6009 case 8:
6010 dbug(1, dprintf("display(%d)", i));
6011 Info_Number = 0x0028;
6012 Info_Mask = 0x04;
6013 Info_Sent_Flag = true;
6014 break;
6015 case 16:
6016 dbug(1, dprintf("CHI"));
6017 Info_Number = 0x0018;
6018 Info_Mask = 0x100;
6019 Info_Sent_Flag = true;
6020 mixer_set_bchannel_id(plci, Info_Element);
6021 break;
6022 case 19:
6023 dbug(1, dprintf("RDN"));
6024 Info_Number = 0x0074;
6025 Info_Mask = 0x400;
6026 Info_Sent_Flag = true;
6027 break;
6028 case 20:
6029 dbug(1, dprintf("RDX"));
6030 Info_Number = 0x0073;
6031 Info_Mask = 0x400;
6032 Info_Sent_Flag = true;
6033 break;
6034 case 22:
6035 dbug(1, dprintf("RIN"));
6036 Info_Number = 0x0076;
6037 Info_Mask = 0x400;
6038 Info_Sent_Flag = true;
6039 break;
6040 default:
6041 Info_Number = 0;
6042 break;
6043 }
6044 }
6045
6046 if (i == MAXPARMSIDS - 2) {
6047 Info_Number = 0x8000 | 5;
6048 Info_Mask = 0x10;
6049 Info_Element = "";
6050 }
6051
6052 if (Info_Sent_Flag && Info_Number) {
6053 if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6054 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6055 }
6056 }
6057 }
6058}
6059
6060
6061static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6062{
6063 word i;
6064 word j;
6065 word k;
6066 byte *ie;
6067 word Info_Number;
6068 byte *Info_Element;
6069 word Info_Mask = 0;
6070 static byte charges[5] = {4, 0, 0, 0, 0};
6071 static byte cause[] = {0x02, 0x80, 0x00};
6072 APPL *appl;
6073
6074 dbug(1, dprintf("InfoParse "));
6075
6076 if (
6077 !plci->appl
6078 && !plci->State
6079 && plci->Sig.Ind != NCR_FACILITY
6080 )
6081 {
6082 dbug(1, dprintf("NoParse "));
6083 return;
6084 }
6085 cause[2] = 0;
6086 for (i = 0; i < MAXPARMSIDS; i++) {
6087 ie = parms[i];
6088 Info_Number = 0;
6089 Info_Element = ie;
6090 if (ie[0]) {
6091 switch (i) {
6092 case 0:
6093 dbug(1, dprintf("CPN "));
6094 Info_Number = 0x0070;
6095 Info_Mask = 0x80;
6096 break;
6097 case 7:
6098 dbug(1, dprintf("cau(0x%x)", ie[2]));
6099 Info_Number = 0x0008;
6100 Info_Mask = 0x00;
6101 cause[2] = ie[2];
6102 Info_Element = NULL;
6103 break;
6104 case 8:
6105 dbug(1, dprintf("display(%d)", i));
6106 Info_Number = 0x0028;
6107 Info_Mask = 0x04;
6108 break;
6109 case 9:
6110 dbug(1, dprintf("date(%d)", i));
6111 Info_Number = 0x0029;
6112 Info_Mask = 0x02;
6113 break;
6114 case 10:
6115 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6116 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6117 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6118 Info_Number = 0x4000;
6119 Info_Mask = 0x40;
6120 Info_Element = charges;
6121 break;
6122 case 11:
6123 dbug(1, dprintf("uui"));
6124 Info_Number = 0x007E;
6125 Info_Mask = 0x08;
6126 break;
6127 case 12:
6128 dbug(1, dprintf("clRDY"));
6129 Info_Number = 0x00B0;
6130 Info_Mask = 0x08;
6131 Info_Element = "";
6132 break;
6133 case 13:
6134 dbug(1, dprintf("clNRDY"));
6135 Info_Number = 0x00BF;
6136 Info_Mask = 0x08;
6137 Info_Element = "";
6138 break;
6139 case 15:
6140 dbug(1, dprintf("KEY"));
6141 Info_Number = 0x002C;
6142 Info_Mask = 0x20;
6143 break;
6144 case 16:
6145 dbug(1, dprintf("CHI"));
6146 Info_Number = 0x0018;
6147 Info_Mask = 0x100;
6148 mixer_set_bchannel_id(plci, Info_Element);
6149 break;
6150 case 17:
6151 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6152 if (!cause[2] || cause[2] < 0x80) break;
6153 Info_Number = 0x0008;
6154 Info_Mask = 0x01;
6155 if (cause[2] != ie[2]) Info_Element = cause;
6156 break;
6157 case 19:
6158 dbug(1, dprintf("RDN"));
6159 Info_Number = 0x0074;
6160 Info_Mask = 0x400;
6161 break;
6162 case 22:
6163 dbug(1, dprintf("RIN"));
6164 Info_Number = 0x0076;
6165 Info_Mask = 0x400;
6166 break;
6167 case 23:
6168 dbug(1, dprintf("NI"));
6169 Info_Number = (word)NI;
6170 Info_Mask = 0x210;
6171 break;
6172 case 26:
6173 dbug(1, dprintf("CST"));
6174 Info_Number = (word)CST;
6175 Info_Mask = 0x01;
6176 break;
6177 case MAXPARMSIDS - 2:
6178 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6179 Info_Number = 0x8000 | ie[3];
6180 if (iesent) Info_Mask = 0xffff;
6181 else Info_Mask = 0x10;
6182 Info_Element = "";
6183 break;
6184 default:
6185 Info_Number = 0;
6186 Info_Mask = 0;
6187 Info_Element = "";
6188 break;
6189 }
6190 }
6191
6192 if (plci->Sig.Ind == NCR_FACILITY)
6193 {
6194 for (j = 0; j < max_appl; j++)
6195 {
6196 appl = &application[j];
6197 if (Info_Number
6198 && appl->Id
6199 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6200 {
6201 dbug(1, dprintf("NCR_Ind"));
6202 iesent = true;
6203 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6204 }
6205 }
6206 }
6207 else if (!plci->appl)
6208 {
6209 if (Info_Number == CPN
6210 || Info_Number == KEY
6211 || Info_Number == NI
6212 || Info_Number == DSP
6213 || Info_Number == UUI)
6214 {
6215 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6216 dbug(1, dprintf("Ovl_Ind"));
6217 iesent = true;
6218 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6219 }
6220 }
6221 }
6222 else if (Info_Number
6223 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6224 {
6225 dbug(1, dprintf("Std_Ind"));
6226 iesent = true;
6227 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6228 }
6229 }
6230}
6231
6232
6233static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6234 dword info_mask, byte setupParse)
6235{
6236 word i;
6237 word j;
6238 byte *ie;
6239 word Info_Number;
6240 byte *Info_Element;
6241 APPL *appl;
6242 word Info_Mask = 0;
6243 byte iesent = 0;
6244
6245 if (
6246 !plci->appl
6247 && !plci->State
6248 && plci->Sig.Ind != NCR_FACILITY
6249 && !setupParse
6250 )
6251 {
6252 dbug(1, dprintf("NoM-IEParse "));
6253 return 0;
6254 }
6255 dbug(1, dprintf("M-IEParse "));
6256
6257 for (i = 0; i < MAX_MULTI_IE; i++)
6258 {
6259 ie = parms[i];
6260 Info_Number = 0;
6261 Info_Element = ie;
6262 if (ie[0])
6263 {
6264 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6265 Info_Number = (word)ie_type;
6266 Info_Mask = (word)info_mask;
6267 }
6268
6269 if (plci->Sig.Ind == NCR_FACILITY)
6270 {
6271 for (j = 0; j < max_appl; j++)
6272 {
6273 appl = &application[j];
6274 if (Info_Number
6275 && appl->Id
6276 && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6277 {
6278 iesent = true;
6279 dbug(1, dprintf("Mlt_NCR_Ind"));
6280 sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6281 }
6282 }
6283 }
6284 else if (!plci->appl && Info_Number)
6285 {
6286 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6287 iesent = true;
6288 dbug(1, dprintf("Mlt_Ovl_Ind"));
6289 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6290 }
6291 }
6292 else if (Info_Number
6293 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6294 {
6295 iesent = true;
6296 dbug(1, dprintf("Mlt_Std_Ind"));
6297 sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6298 }
6299 }
6300 return iesent;
6301}
6302
6303static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6304{
6305 word i;
6306
6307
6308
6309
6310
6311
6312
6313
6314 if (
6315 plci
6316 && plci->State
6317 && plci->Sig.Ind != NCR_FACILITY
6318 )
6319 for (i = 0; i < MAX_MULTI_IE; i++)
6320 {
6321 if (parms[i][0] < 6) continue;
6322 if (parms[i][2] == SSEXT_REQ) continue;
6323
6324 if (appl)
6325 {
6326 parms[i][0] = 0;
6327 sendf(appl, _MANUFACTURER_I,
6328 Id,
6329 0,
6330 "dwS",
6331 _DI_MANU_ID,
6332 _DI_SSEXT_CTRL,
6333 &parms[i][3]);
6334 }
6335 else if (plci->appl)
6336 {
6337 parms[i][0] = 0;
6338 sendf(plci->appl, _MANUFACTURER_I,
6339 Id,
6340 0,
6341 "dwS",
6342 _DI_MANU_ID,
6343 _DI_SSEXT_CTRL,
6344 &parms[i][3]);
6345 }
6346 }
6347};
6348
6349static void nl_ind(PLCI *plci)
6350{
6351 byte ch;
6352 word ncci;
6353 dword Id;
6354 DIVA_CAPI_ADAPTER *a;
6355 word NCCIcode;
6356 APPL *APPLptr;
6357 word count;
6358 word Num;
6359 word i, ncpi_state;
6360 byte len, ncci_state;
6361 word msg;
6362 word info = 0;
6363 word fax_feature_bits;
6364 byte fax_send_edata_ack;
6365 static byte v120_header_buffer[2 + 3];
6366 static word fax_info[] = {
6367 0,
6368 _FAX_NO_CONNECTION,
6369 _FAX_PROTOCOL_ERROR,
6370 _FAX_PROTOCOL_ERROR,
6371 _FAX_PROTOCOL_ERROR,
6372 _FAX_PROTOCOL_ERROR,
6373 _FAX_REMOTE_ABORT,
6374 _FAX_LOCAL_ABORT,
6375 _FAX_TRAINING_ERROR,
6376 _FAX_TRAINING_ERROR,
6377 _FAX_PARAMETER_ERROR,
6378 _FAX_REMOTE_ABORT,
6379 _FAX_LOCAL_ABORT,
6380 _FAX_REMOTE_REJECT,
6381 _FAX_LOCAL_ABORT,
6382 _FAX_PROTOCOL_ERROR,
6383 _FAX_PROTOCOL_ERROR,
6384 _FAX_PROTOCOL_ERROR,
6385 _FAX_PROTOCOL_ERROR,
6386 _FAX_NO_CONNECTION,
6387 _FAX_PROTOCOL_ERROR,
6388 _FAX_PARAMETER_ERROR,
6389 _FAX_PROTOCOL_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 0x331d,
6401 0x331e,
6402 0x331f,
6403 _FAX_PROTOCOL_ERROR,
6404 _FAX_PARAMETER_ERROR,
6405 _FAX_PARAMETER_ERROR,
6406 _FAX_REMOTE_REJECT,
6407 _FAX_LOCAL_ABORT,
6408 _FAX_PROTOCOL_ERROR,
6409 _FAX_PROTOCOL_ERROR,
6410 _FAX_PROTOCOL_ERROR,
6411 _FAX_PROTOCOL_ERROR,
6412 _FAX_LOCAL_ABORT,
6413 _FAX_LOCAL_ABORT
6414 };
6415
6416 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6417
6418
6419 static word rtp_info[] = {
6420 GOOD,
6421 0x3600
6422 };
6423
6424 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6425 {
6426 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6427 0x00000000, 0x00000000, 0x00000000, 0x00000000
6428 };
6429
6430 ch = plci->NL.IndCh;
6431 a = plci->adapter;
6432 ncci = a->ch_ncci[ch];
6433 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6434 if (plci->tel) Id |= EXT_CONTROLLER;
6435 APPLptr = plci->appl;
6436 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",
6437 plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6438
6439
6440
6441 if (plci->nl_remove_id)
6442 {
6443 plci->NL.RNR = 2;
6444 dbug(1, dprintf("NL discard while remove pending"));
6445 return;
6446 }
6447 if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6448 {
6449 if (plci->State == INC_DIS_PENDING
6450 || plci->State == OUTG_DIS_PENDING
6451 || plci->State == IDLE)
6452 {
6453 plci->NL.RNR = 2;
6454 dbug(1, dprintf("discard n_connect"));
6455 return;
6456 }
6457 if (plci->State < INC_ACT_PENDING)
6458 {
6459 plci->NL.RNR = 1;
6460 channel_x_off(plci, ch, N_XON_CONNECT_IND);
6461 return;
6462 }
6463 }
6464
6465 if (!APPLptr)
6466 {
6467 dbug(1, dprintf("discard1"));
6468 plci->NL.RNR = 2;
6469 return;
6470 }
6471
6472 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6473 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6474 || (plci->B2_prot == 7)
6475 || (plci->B3_prot == 7)))
6476 {
6477 plci->ncpi_buffer[0] = 0;
6478
6479 ncpi_state = plci->ncpi_state;
6480 if (plci->NL.complete == 1)
6481 {
6482 byte *data = &plci->NL.RBuffer->P[0];
6483
6484 if ((plci->NL.RBuffer->length >= 12)
6485 && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6486 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6487 {
6488 word conn_opt, ncpi_opt = 0x00;
6489
6490
6491 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6492 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6493 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6494 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6495
6496 data++;
6497 data += 2;
6498 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6499 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6500 data++;
6501 conn_opt = GET_WORD(data);
6502 data += 2;
6503
6504 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6505
6506 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6507 {
6508 ncpi_opt |= MDM_NCPI_ECM_V42;
6509 }
6510 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6511 {
6512 ncpi_opt |= MDM_NCPI_ECM_MNP;
6513 }
6514 else
6515 {
6516 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6517 }
6518 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6519 {
6520 ncpi_opt |= MDM_NCPI_COMPRESSED;
6521 }
6522 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6523 plci->ncpi_buffer[0] = 4;
6524
6525 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6526 }
6527 }
6528 if (plci->B3_prot == 7)
6529 {
6530 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6531 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6532 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6533 {
6534 a->ncci_state[ncci] = INC_ACT_PENDING;
6535 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6536 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6537 }
6538 }
6539
6540 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6541 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6542 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6543 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6544
6545 {
6546 plci->NL.RNR = 2;
6547 return;
6548 }
6549 }
6550
6551 if (plci->NL.complete == 2)
6552 {
6553 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6554 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6555 {
6556 switch (plci->RData[0].P[0])
6557 {
6558
6559 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6560 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6561 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6562 break;
6563 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6564 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6565 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6566 break;
6567 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6568 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6569 break;
6570 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6571 dtmf_confirmation(Id, plci);
6572 break;
6573
6574
6575 case UDATA_INDICATION_MIXER_TAP_DATA:
6576 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6577 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6578 if (i != 0)
6579 {
6580 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6581 dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6582 }
6583 break;
6584
6585
6586 case UDATA_INDICATION_MIXER_COEFS_SET:
6587 mixer_indication_coefs_set(Id, plci);
6588 break;
6589 case UDATA_INDICATION_XCONNECT_FROM:
6590 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6591 break;
6592 case UDATA_INDICATION_XCONNECT_TO:
6593 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6594 break;
6595
6596
6597 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6598 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6599 break;
6600
6601
6602
6603 default:
6604 break;
6605 }
6606 }
6607 else
6608 {
6609 if ((plci->RData[0].PLength != 0)
6610 && ((plci->B2_prot == B2_V120_ASYNC)
6611 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6612 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6613 {
6614
6615 sendf(plci->appl, _DATA_B3_I, Id, 0,
6616 "dwww",
6617 plci->RData[1].P,
6618 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6619 plci->RNum,
6620 plci->RFlags);
6621
6622 }
6623 else
6624 {
6625
6626 sendf(plci->appl, _DATA_B3_I, Id, 0,
6627 "dwww",
6628 plci->RData[0].P,
6629 plci->RData[0].PLength,
6630 plci->RNum,
6631 plci->RFlags);
6632
6633 }
6634 }
6635 return;
6636 }
6637
6638 fax_feature_bits = 0;
6639 if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6640 (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6641 (plci->NL.Ind & 0x0f) == N_DISC ||
6642 (plci->NL.Ind & 0x0f) == N_EDATA ||
6643 (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6644 {
6645 info = 0;
6646 plci->ncpi_buffer[0] = 0;
6647 switch (plci->B3_prot) {
6648 case 0:
6649 case 1:
6650 break;
6651 case 2:
6652 case 3:
6653 for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6654 plci->ncpi_buffer[0] = (byte)(i + 3);
6655 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6656 plci->ncpi_buffer[2] = 0;
6657 plci->ncpi_buffer[3] = 0;
6658 break;
6659 case 4:
6660 case 5:
6661 if (plci->NL.RLength >= sizeof(T30_INFO))
6662 {
6663 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6664 len = 9;
6665 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6666 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6667 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6668 if (plci->B3_prot == 5)
6669 {
6670 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6671 i |= 0x8000;
6672 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6673 i |= 0x4000;
6674 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6675 i |= 0x2000;
6676 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6677 i |= 0x0004;
6678 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6679 i |= 0x0002;
6680 }
6681 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6682 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6683 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6684 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6685 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6686 plci->ncpi_buffer[len] = 0;
6687 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6688 {
6689 plci->ncpi_buffer[len] = 20;
6690 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6691 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6692 }
6693 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6694 {
6695 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6696 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6697 else
6698 info = _FAX_PROTOCOL_ERROR;
6699 }
6700
6701 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6702 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6703 {
6704 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6705 while (i < plci->NL.RBuffer->length)
6706 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6707 }
6708
6709 plci->ncpi_buffer[0] = len;
6710 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6711 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6712
6713 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6714 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6715 || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6716 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6717 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6718 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6719 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6720 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6721 {
6722 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6723 }
6724 if (((plci->NL.Ind & 0x0f) == N_DISC)
6725 || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6726 || (((plci->NL.Ind & 0x0f) == N_EDATA)
6727 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6728 {
6729 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6730 }
6731 }
6732 break;
6733
6734 case B3_RTP:
6735 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6736 {
6737 if (plci->NL.RLength != 0)
6738 {
6739 info = rtp_info[plci->NL.RBuffer->P[0]];
6740 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6741 for (i = 1; i < plci->NL.RLength; i++)
6742 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6743 }
6744 }
6745 break;
6746
6747 }
6748 plci->NL.RNR = 2;
6749 }
6750 switch (plci->NL.Ind & 0x0f) {
6751 case N_EDATA:
6752 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6753 {
6754 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6755 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6756 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6757
6758 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6759 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6760 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6761 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6762 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6763 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6764 {
6765 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6766 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6767 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6768 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6769 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6770 fax_send_edata_ack = false;
6771 }
6772
6773 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6774 {
6775 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6776 {
6777 case EDATA_T30_DIS:
6778 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6779 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6780 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6781 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6782 {
6783 a->ncci_state[ncci] = INC_ACT_PENDING;
6784 if (plci->B3_prot == 4)
6785 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6786 else
6787 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6788 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6789 }
6790 break;
6791
6792 case EDATA_T30_TRAIN_OK:
6793 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6794 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6795 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6796 {
6797 if (plci->B3_prot == 4)
6798 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6799 else
6800 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6801 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6802 }
6803 break;
6804
6805 case EDATA_T30_EOP_CAPI:
6806 if (a->ncci_state[ncci] == CONNECTED)
6807 {
6808 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6809 a->ncci_state[ncci] = INC_DIS_PENDING;
6810 plci->ncpi_state = 0;
6811 fax_send_edata_ack = false;
6812 }
6813 break;
6814 }
6815 }
6816 else
6817 {
6818 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6819 {
6820 case EDATA_T30_TRAIN_OK:
6821 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6822 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6823 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6824 {
6825 if (plci->B3_prot == 4)
6826 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6827 else
6828 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6829 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6830 }
6831 break;
6832 }
6833 }
6834 if (fax_send_edata_ack)
6835 {
6836 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6837 plci->fax_edata_ack_length = 1;
6838 start_internal_command(Id, plci, fax_edata_ack_command);
6839 }
6840 }
6841 else
6842 {
6843 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6844 }
6845 break;
6846 case N_CONNECT:
6847 if (!a->ch_ncci[ch])
6848 {
6849 ncci = get_ncci(plci, ch, 0);
6850 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6851 }
6852 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6853 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6854
6855 msg = _CONNECT_B3_I;
6856 if (a->ncci_state[ncci] == IDLE)
6857 plci->channels++;
6858 else if (plci->B3_prot == 1)
6859 msg = _CONNECT_B3_T90_ACTIVE_I;
6860
6861 a->ncci_state[ncci] = INC_CON_PENDING;
6862 if (plci->B3_prot == 4)
6863 sendf(plci->appl, msg, Id, 0, "s", "");
6864 else
6865 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6866 break;
6867 case N_CONNECT_ACK:
6868 dbug(1, dprintf("N_connect_Ack"));
6869 if (plci->internal_command_queue[0]
6870 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6871 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6872 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6873 {
6874 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6875 if (!plci->internal_command)
6876 next_internal_command(Id, plci);
6877 break;
6878 }
6879 msg = _CONNECT_B3_ACTIVE_I;
6880 if (plci->B3_prot == 1)
6881 {
6882 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6883 msg = _CONNECT_B3_T90_ACTIVE_I;
6884 a->ncci_state[ncci] = INC_ACT_PENDING;
6885 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6886 }
6887 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6888 {
6889 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6890 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6891 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6892 {
6893 a->ncci_state[ncci] = INC_ACT_PENDING;
6894 if (plci->B3_prot == 4)
6895 sendf(plci->appl, msg, Id, 0, "s", "");
6896 else
6897 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6898 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6899 }
6900 }
6901 else
6902 {
6903 a->ncci_state[ncci] = INC_ACT_PENDING;
6904 sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6905 }
6906 if (plci->adjust_b_restore)
6907 {
6908 plci->adjust_b_restore = false;
6909 start_internal_command(Id, plci, adjust_b_restore);
6910 }
6911 break;
6912 case N_DISC:
6913 case N_DISC_ACK:
6914 if (plci->internal_command_queue[0]
6915 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6916 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6917 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6918 {
6919 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6920 if (!plci->internal_command)
6921 next_internal_command(Id, plci);
6922 }
6923 ncci_state = a->ncci_state[ncci];
6924 ncci_remove(plci, ncci, false);
6925
6926
6927
6928
6929
6930 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6931 plci->inc_dis_ncci_table[i] = (byte) ncci;
6932
6933
6934 if (!plci->channels
6935 && (plci->B1_resource == 16)
6936 && (plci->State <= CONNECTED))
6937 {
6938 len = 9;
6939 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6940 PUT_WORD(&plci->ncpi_buffer[1], i);
6941 PUT_WORD(&plci->ncpi_buffer[3], 0);
6942 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6943 PUT_WORD(&plci->ncpi_buffer[5], i);
6944 PUT_WORD(&plci->ncpi_buffer[7], 0);
6945 plci->ncpi_buffer[len] = 0;
6946 plci->ncpi_buffer[0] = len;
6947 if (plci->B3_prot == 4)
6948 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6949 else
6950 {
6951
6952 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6953 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6954 {
6955 plci->ncpi_buffer[++len] = 0;
6956 plci->ncpi_buffer[++len] = 0;
6957 plci->ncpi_buffer[++len] = 0;
6958 plci->ncpi_buffer[0] = len;
6959 }
6960
6961 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6962 }
6963 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6964 plci->ncpi_state = 0;
6965 sig_req(plci, HANGUP, 0);
6966 send_req(plci);
6967 plci->State = OUTG_DIS_PENDING;
6968
6969 }
6970 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6971 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6972 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6973 {
6974 if (ncci_state == IDLE)
6975 {
6976 if (plci->channels)
6977 plci->channels--;
6978 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6979 if (plci->State == SUSPENDING) {
6980 sendf(plci->appl,
6981 _FACILITY_I,
6982 Id & 0xffffL,
6983 0,
6984 "ws", (word)3, "\x03\x04\x00\x00");
6985 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6986 }
6987 plci_remove(plci);
6988 plci->State = IDLE;
6989 }
6990 }
6991 }
6992 else if (plci->channels)
6993 {
6994 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6995 plci->ncpi_state = 0;
6996 if ((ncci_state == OUTG_REJ_PENDING)
6997 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6998 {
6999 sig_req(plci, HANGUP, 0);
7000 send_req(plci);
7001 plci->State = OUTG_DIS_PENDING;
7002 }
7003 }
7004 break;
7005 case N_RESET:
7006 a->ncci_state[ncci] = INC_RES_PENDING;
7007 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7008 break;
7009 case N_RESET_ACK:
7010 a->ncci_state[ncci] = CONNECTED;
7011 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7012 break;
7013
7014 case N_UDATA:
7015 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7016 {
7017 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7018 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7019 plci->NL.R = plci->RData;
7020 plci->NL.RNum = 1;
7021 return;
7022 }
7023 case N_BDATA:
7024 case N_DATA:
7025 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1))
7026 || (a->ncci_state[ncci] == IDLE)
7027 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7028 {
7029 plci->NL.RNR = 2;
7030 break;
7031 }
7032 if ((a->ncci_state[ncci] != CONNECTED)
7033 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7034 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7035 {
7036 dbug(1, dprintf("flow control"));
7037 plci->NL.RNR = 1;
7038 channel_x_off(plci, ch, 0);
7039 break;
7040 }
7041
7042 NCCIcode = ncci | (((word)a->Id) << 8);
7043
7044
7045
7046
7047
7048 count = 0;
7049 Num = 0xffff;
7050 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7051 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7052 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7053 }
7054
7055 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7056 {
7057 dbug(3, dprintf("Flow-Control"));
7058 plci->NL.RNR = 1;
7059 if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7060 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7061 {
7062 plci->NL.RNR = 2;
7063 dbug(3, dprintf("DiscardData"));
7064 } else {
7065 channel_x_off(plci, ch, 0);
7066 }
7067 break;
7068 }
7069 else
7070 {
7071 APPLptr->NCCIDataFlowCtrlTimer = 0;
7072 }
7073
7074 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7075 if (!plci->RData[0].P) {
7076 plci->NL.RNR = 1;
7077 channel_x_off(plci, ch, 0);
7078 break;
7079 }
7080
7081 APPLptr->DataNCCI[Num] = NCCIcode;
7082 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7083 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7084
7085 plci->RNum = Num;
7086 plci->RFlags = plci->NL.Ind >> 4;
7087 plci->RData[0].PLength = APPLptr->MaxDataLength;
7088 plci->NL.R = plci->RData;
7089 if ((plci->NL.RLength != 0)
7090 && ((plci->B2_prot == B2_V120_ASYNC)
7091 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7092 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7093 {
7094 plci->RData[1].P = plci->RData[0].P;
7095 plci->RData[1].PLength = plci->RData[0].PLength;
7096 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7097 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7098 plci->RData[0].PLength = 1;
7099 else
7100 plci->RData[0].PLength = 2;
7101 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7102 plci->RFlags |= 0x0010;
7103 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7104 plci->RFlags |= 0x8000;
7105 plci->NL.RNum = 2;
7106 }
7107 else
7108 {
7109 if ((plci->NL.Ind & 0x0f) == N_UDATA)
7110 plci->RFlags |= 0x0010;
7111
7112 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7113 plci->RFlags |= 0x0001;
7114
7115 plci->NL.RNum = 1;
7116 }
7117 break;
7118 case N_DATA_ACK:
7119 data_ack(plci, ch);
7120 break;
7121 default:
7122 plci->NL.RNR = 2;
7123 break;
7124 }
7125}
7126
7127
7128
7129
7130
7131static word get_plci(DIVA_CAPI_ADAPTER *a)
7132{
7133 word i, j;
7134 PLCI *plci;
7135
7136 for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7137 if (i == a->max_plci) {
7138 dbug(1, dprintf("get_plci: out of PLCIs"));
7139 return 0;
7140 }
7141 plci = &a->plci[i];
7142 plci->Id = (byte)(i + 1);
7143
7144 plci->Sig.Id = 0;
7145 plci->NL.Id = 0;
7146 plci->sig_req = 0;
7147 plci->nl_req = 0;
7148
7149 plci->appl = NULL;
7150 plci->relatedPTYPLCI = NULL;
7151 plci->State = IDLE;
7152 plci->SuppState = IDLE;
7153 plci->channels = 0;
7154 plci->tel = 0;
7155 plci->B1_resource = 0;
7156 plci->B2_prot = 0;
7157 plci->B3_prot = 0;
7158
7159 plci->command = 0;
7160 plci->m_command = 0;
7161 init_internal_command_queue(plci);
7162 plci->number = 0;
7163 plci->req_in_start = 0;
7164 plci->req_in = 0;
7165 plci->req_out = 0;
7166 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7167 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7168 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7169
7170 plci->data_sent = false;
7171 plci->send_disc = 0;
7172 plci->sig_global_req = 0;
7173 plci->sig_remove_id = 0;
7174 plci->nl_global_req = 0;
7175 plci->nl_remove_id = 0;
7176 plci->adv_nl = 0;
7177 plci->manufacturer = false;
7178 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7179 plci->spoofed_msg = 0;
7180 plci->ptyState = 0;
7181 plci->cr_enquiry = false;
7182 plci->hangup_flow_ctrl_timer = 0;
7183
7184 plci->ncci_ring_list = 0;
7185 for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7186 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7187 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7188 plci->fax_connect_info_length = 0;
7189 plci->nsf_control_bits = 0;
7190 plci->ncpi_state = 0x00;
7191 plci->ncpi_buffer[0] = 0;
7192
7193 plci->requested_options_conn = 0;
7194 plci->requested_options = 0;
7195 plci->notifiedcall = 0;
7196 plci->vswitchstate = 0;
7197 plci->vsprot = 0;
7198 plci->vsprotdialect = 0;
7199 init_b1_config(plci);
7200 dbug(1, dprintf("get_plci(%x)", plci->Id));
7201 return i + 1;
7202}
7203
7204
7205
7206
7207
7208static void add_p(PLCI *plci, byte code, byte *p)
7209{
7210 word p_length;
7211
7212 p_length = 0;
7213 if (p) p_length = p[0];
7214 add_ie(plci, code, p, p_length);
7215}
7216
7217
7218
7219
7220static void add_s(PLCI *plci, byte code, API_PARSE *p)
7221{
7222 if (p) add_ie(plci, code, p->info, (word)p->length);
7223}
7224
7225
7226
7227
7228static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7229{
7230 byte i;
7231
7232 if (p) {
7233 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7234 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7235 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7236 add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7237 }
7238 }
7239}
7240
7241
7242
7243
7244static byte getChannel(API_PARSE *p)
7245{
7246 byte i;
7247
7248 if (p) {
7249 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7250 if (p->info[i] == 2) {
7251 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7252 }
7253 }
7254 }
7255 return 0;
7256}
7257
7258
7259
7260
7261
7262
7263static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7264{
7265 word i;
7266
7267 if (!(code & 0x80) && !p_length) return;
7268
7269 if (plci->req_in == plci->req_in_start) {
7270 plci->req_in += 2;
7271 }
7272 else {
7273 plci->req_in--;
7274 }
7275 plci->RBuffer[plci->req_in++] = code;
7276
7277 if (p) {
7278 plci->RBuffer[plci->req_in++] = (byte)p_length;
7279 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7280 }
7281
7282 plci->RBuffer[plci->req_in++] = 0;
7283}
7284
7285
7286
7287
7288
7289static void add_d(PLCI *plci, word length, byte *p)
7290{
7291 word i;
7292
7293 if (plci->req_in == plci->req_in_start) {
7294 plci->req_in += 2;
7295 }
7296 else {
7297 plci->req_in--;
7298 }
7299 for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7300}
7301
7302
7303
7304
7305
7306
7307static void add_ai(PLCI *plci, API_PARSE *ai)
7308{
7309 word i;
7310 API_PARSE ai_parms[5];
7311
7312 for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7313
7314 if (!ai->length)
7315 return;
7316 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7317 return;
7318
7319 add_s(plci, KEY, &ai_parms[1]);
7320 add_s(plci, UUI, &ai_parms[2]);
7321 add_ss(plci, FTY, &ai_parms[3]);
7322}
7323
7324
7325
7326
7327
7328static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7329 word b1_facilities)
7330{
7331 API_PARSE bp_parms[8];
7332 API_PARSE mdm_cfg[9];
7333 API_PARSE global_config[2];
7334 byte cai[256];
7335 byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7336 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7337 word i;
7338
7339 API_PARSE mdm_cfg_v18[4];
7340 word j, n, w;
7341 dword d;
7342
7343
7344 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7345 for (i = 0; i < 2; i++) global_config[i].length = 0;
7346
7347 dbug(1, dprintf("add_b1"));
7348 api_save_msg(bp, "s", &plci->B_protocol);
7349
7350 if (b_channel_info == 2) {
7351 plci->B1_resource = 0;
7352 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7353 add_p(plci, CAI, "\x01\x00");
7354 dbug(1, dprintf("Cai=1,0 (no resource)"));
7355 return 0;
7356 }
7357
7358 if (plci->tel == CODEC_PERMANENT) return 0;
7359 else if (plci->tel == CODEC) {
7360 plci->B1_resource = 1;
7361 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7362 add_p(plci, CAI, "\x01\x01");
7363 dbug(1, dprintf("Cai=1,1 (Codec)"));
7364 return 0;
7365 }
7366 else if (plci->tel == ADV_VOICE) {
7367 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7368 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7369 voice_cai[1] = plci->B1_resource;
7370 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7371 add_p(plci, CAI, voice_cai);
7372 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7373 return 0;
7374 }
7375 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7376 if (plci->call_dir & CALL_DIR_OUT)
7377 plci->call_dir |= CALL_DIR_ORIGINATE;
7378 else if (plci->call_dir & CALL_DIR_IN)
7379 plci->call_dir |= CALL_DIR_ANSWER;
7380
7381 if (!bp->length) {
7382 plci->B1_resource = 0x5;
7383 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7384 add_p(plci, CAI, "\x01\x05");
7385 return 0;
7386 }
7387
7388 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7389 if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7390 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7391 {
7392 bp_parms[6].length = 0;
7393 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7394 {
7395 dbug(1, dprintf("b-form.!"));
7396 return _WRONG_MESSAGE_FORMAT;
7397 }
7398 }
7399 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7400 {
7401 dbug(1, dprintf("b-form.!"));
7402 return _WRONG_MESSAGE_FORMAT;
7403 }
7404
7405 if (bp_parms[6].length)
7406 {
7407 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7408 {
7409 return _WRONG_MESSAGE_FORMAT;
7410 }
7411 switch (GET_WORD(global_config[0].info))
7412 {
7413 case 1:
7414 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7415 break;
7416 case 2:
7417 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7418 break;
7419 }
7420 }
7421 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7422
7423
7424 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7425 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7426 {
7427 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7428 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7429 cai[1] = plci->B1_resource;
7430 cai[2] = 0;
7431 cai[3] = 0;
7432 cai[4] = 0;
7433 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7434 for (i = 0; i < bp_parms[3].length; i++)
7435 cai[7 + i] = bp_parms[3].info[1 + i];
7436 cai[0] = 6 + bp_parms[3].length;
7437 add_p(plci, CAI, cai);
7438 return 0;
7439 }
7440
7441
7442 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7443 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7444 {
7445 plci->B1_resource = add_b1_facilities(plci, 35, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7446 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7447 cai[1] = plci->B1_resource;
7448 cai[2] = 0;
7449 cai[3] = 0;
7450 cai[4] = 0;
7451 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7452 cai[0] = 6;
7453 add_p(plci, CAI, cai);
7454 return 0;
7455 }
7456
7457
7458 if ((GET_WORD(bp_parms[0].info) >= 32)
7459 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7460 && ((GET_WORD(bp_parms[0].info) != 3)
7461 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7462 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7463 {
7464 return _B1_NOT_SUPPORTED;
7465 }
7466 plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7467 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7468 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7469 cai[0] = 6;
7470 cai[1] = plci->B1_resource;
7471 for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7472
7473 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7474 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7475 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7476 {
7477 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7478
7479 if (bp_parms[3].length)
7480 {
7481 if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7482 {
7483 return (_WRONG_MESSAGE_FORMAT);
7484 }
7485
7486 cai[2] = 0;
7487
7488 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7489
7490 PUT_WORD(&cai[13], 0);
7491 PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info));
7492 PUT_WORD(&cai[17], 0);
7493 PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info));
7494
7495 cai[3] = 0;
7496 switch (GET_WORD(mdm_cfg[2].info))
7497 {
7498 case 1:
7499 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7500 dbug(1, dprintf("MDM: odd parity"));
7501 break;
7502
7503 case 2:
7504 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7505 dbug(1, dprintf("MDM: even parity"));
7506 break;
7507
7508 default:
7509 dbug(1, dprintf("MDM: no parity"));
7510 break;
7511 }
7512
7513 switch (GET_WORD(mdm_cfg[3].info))
7514 {
7515 case 1:
7516 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7517 dbug(1, dprintf("MDM: 2 stop bits"));
7518 break;
7519
7520 default:
7521 dbug(1, dprintf("MDM: 1 stop bit"));
7522 break;
7523 }
7524
7525 switch (GET_WORD(mdm_cfg[1].info))
7526 {
7527 case 5:
7528 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7529 dbug(1, dprintf("MDM: 5 bits"));
7530 break;
7531
7532 case 6:
7533 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7534 dbug(1, dprintf("MDM: 6 bits"));
7535 break;
7536
7537 case 7:
7538 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7539 dbug(1, dprintf("MDM: 7 bits"));
7540 break;
7541
7542 default:
7543 dbug(1, dprintf("MDM: 8 bits"));
7544 break;
7545 }
7546
7547 cai[7] = 0;
7548 cai[8] = 0;
7549 cai[9] = 0;
7550
7551 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7552 {
7553 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7554 dbug(1, dprintf("MDM: Reverse direction"));
7555 }
7556
7557 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7558 {
7559 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7560 dbug(1, dprintf("MDM: Disable retrain"));
7561 }
7562
7563 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7564 {
7565 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7566 dbug(1, dprintf("MDM: Disable ring tone"));
7567 }
7568
7569 if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7570 {
7571 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7572 dbug(1, dprintf("MDM: 1800 guard tone"));
7573 }
7574 else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7575 {
7576 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7577 dbug(1, dprintf("MDM: 550 guard tone"));
7578 }
7579
7580 if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7581 {
7582 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7583 dbug(1, dprintf("MDM: V100"));
7584 }
7585 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7586 {
7587 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7588 dbug(1, dprintf("MDM: IN CLASS"));
7589 }
7590 else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7591 {
7592 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7593 dbug(1, dprintf("MDM: DISABLED"));
7594 }
7595 cai[0] = 20;
7596
7597 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7598 && (GET_WORD(mdm_cfg[5].info) & 0x8000))
7599 {
7600 plci->requested_options |= 1L << PRIVATE_V18;
7601 }
7602 if (GET_WORD(mdm_cfg[5].info) & 0x4000)
7603 plci->requested_options |= 1L << PRIVATE_VOWN;
7604
7605 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7606 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7607 {
7608 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7609 {
7610 i = 27;
7611 if (mdm_cfg[6].length >= 4)
7612 {
7613 d = GET_DWORD(&mdm_cfg[6].info[1]);
7614 cai[7] |= (byte) d;
7615 cai[9] |= (byte)(d >> 8);
7616 cai[++i] = (byte)(d >> 16);
7617 cai[++i] = (byte)(d >> 24);
7618 if (mdm_cfg[6].length >= 8)
7619 {
7620 d = GET_DWORD(&mdm_cfg[6].info[5]);
7621 cai[10] |= (byte) d;
7622 cai[11] |= (byte)(d >> 8);
7623 if (mdm_cfg[6].length >= 12)
7624 {
7625 d = GET_DWORD(&mdm_cfg[6].info[9]);
7626 cai[12] = (byte) d;
7627 cai[++i] = (byte)(d >> 8);
7628 cai[++i] = (byte)(d >> 16);
7629 cai[++i] = (byte)(d >> 24);
7630 cai[++i] = 0;
7631 if (mdm_cfg[6].length >= 14)
7632 {
7633 w = GET_WORD(&mdm_cfg[6].info[13]);
7634 if (w != 0)
7635 PUT_WORD(&cai[13], w);
7636 if (mdm_cfg[6].length >= 16)
7637 {
7638 w = GET_WORD(&mdm_cfg[6].info[15]);
7639 if (w != 0)
7640 PUT_WORD(&cai[15], w);
7641 if (mdm_cfg[6].length >= 18)
7642 {
7643 w = GET_WORD(&mdm_cfg[6].info[17]);
7644 if (w != 0)
7645 PUT_WORD(&cai[17], w);
7646 if (mdm_cfg[6].length >= 20)
7647 {
7648 w = GET_WORD(&mdm_cfg[6].info[19]);
7649 if (w != 0)
7650 PUT_WORD(&cai[19], w);
7651 if (mdm_cfg[6].length >= 22)
7652 {
7653 w = GET_WORD(&mdm_cfg[6].info[21]);
7654 cai[23] = (byte)(-((short) w));
7655 if (mdm_cfg[6].length >= 24)
7656 {
7657 w = GET_WORD(&mdm_cfg[6].info[23]);
7658 cai[22] |= (byte) w;
7659 cai[21] |= (byte)(w >> 8);
7660 }
7661 }
7662 }
7663 }
7664 }
7665 }
7666 }
7667 }
7668 }
7669 cai[27] = i - 27;
7670 i++;
7671 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7672 {
7673 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7674 {
7675 for (n = 0; n < 3; n++)
7676 {
7677 cai[i] = (byte)(mdm_cfg_v18[n].length);
7678 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7679 cai[i + j] = mdm_cfg_v18[n].info[j];
7680 i += cai[i] + 1;
7681 }
7682 }
7683 }
7684 cai[0] = (byte)(i - 1);
7685 }
7686 }
7687
7688 }
7689 }
7690 if (GET_WORD(bp_parms[0].info) == 2 ||
7691 GET_WORD(bp_parms[0].info) == 3)
7692 {
7693 if (bp_parms[3].length) {
7694 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7695 switch (GET_WORD(&bp_parms[3].info[1])) {
7696 case 0:
7697 case 56000:
7698 if (GET_WORD(bp_parms[0].info) == 3) {
7699 dbug(1, dprintf("56k sync HSCX"));
7700 cai[1] = 8;
7701 cai[2] = 0;
7702 cai[3] = 0;
7703 }
7704 else if (GET_WORD(bp_parms[0].info) == 2) {
7705 dbug(1, dprintf("56k async DSP"));
7706 cai[2] = 9;
7707 }
7708 break;
7709 case 50: cai[2] = 1; break;
7710 case 75: cai[2] = 1; break;
7711 case 110: cai[2] = 1; break;
7712 case 150: cai[2] = 1; break;
7713 case 200: cai[2] = 1; break;
7714 case 300: cai[2] = 1; break;
7715 case 600: cai[2] = 1; break;
7716 case 1200: cai[2] = 2; break;
7717 case 2400: cai[2] = 3; break;
7718 case 4800: cai[2] = 4; break;
7719 case 7200: cai[2] = 10; break;
7720 case 9600: cai[2] = 5; break;
7721 case 12000: cai[2] = 13; break;
7722 case 24000: cai[2] = 0; break;
7723 case 14400: cai[2] = 11; break;
7724 case 19200: cai[2] = 6; break;
7725 case 28800: cai[2] = 12; break;
7726 case 38400: cai[2] = 7; break;
7727 case 48000: cai[2] = 8; break;
7728 case 76: cai[2] = 15; break;
7729 case 1201: cai[2] = 14; break;
7730 case 56001: cai[2] = 9; break;
7731
7732 default:
7733 return _B1_PARM_NOT_SUPPORTED;
7734 }
7735 cai[3] = 0;
7736 if (cai[1] == 13)
7737 {
7738 if (bp_parms[3].length >= 8)
7739 {
7740 switch (GET_WORD(&bp_parms[3].info[3]))
7741 {
7742 case 5:
7743 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7744 break;
7745 case 6:
7746 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7747 break;
7748 case 7:
7749 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7750 break;
7751 }
7752 switch (GET_WORD(&bp_parms[3].info[5]))
7753 {
7754 case 1:
7755 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7756 break;
7757 case 2:
7758 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7759 break;
7760 }
7761 switch (GET_WORD(&bp_parms[3].info[7]))
7762 {
7763 case 1:
7764 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7765 break;
7766 }
7767 }
7768 }
7769 }
7770 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7771 dbug(1, dprintf("V.110 default 56k sync"));
7772 cai[1] = 8;
7773 cai[2] = 0;
7774 cai[3] = 0;
7775 }
7776 else {
7777 dbug(1, dprintf("V.110 default 9600 async"));
7778 cai[2] = 5;
7779 }
7780 }
7781 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7782 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]));
7783
7784
7785 add_p(plci, CAI, cai);
7786 return 0;
7787}
7788
7789
7790
7791
7792
7793static word add_b23(PLCI *plci, API_PARSE *bp)
7794{
7795 word i, fax_control_bits;
7796 byte pos, len;
7797 byte SAPI = 0x40;
7798 API_PARSE bp_parms[8];
7799 API_PARSE *b1_config;
7800 API_PARSE *b2_config;
7801 API_PARSE b2_config_parms[8];
7802 API_PARSE *b3_config;
7803 API_PARSE b3_config_parms[6];
7804 API_PARSE global_config[2];
7805
7806 static byte llc[3] = {2,0,0};
7807 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7808 static byte nlc[256];
7809 static byte lli[12] = {1,1};
7810
7811 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7812 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7813
7814 const byte llc3[] = {4,3,2,2,6,6,0};
7815 const byte header[] = {0,2,3,3,0,0,0};
7816
7817 for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7818 for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7819 for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7820
7821 lli[0] = 1;
7822 lli[1] = 1;
7823 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7824 lli[1] |= 2;
7825 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7826 lli[1] |= 4;
7827
7828 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7829 lli[1] |= 0x10;
7830 if (plci->rx_dma_descriptor <= 0) {
7831 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7832 if (plci->rx_dma_descriptor >= 0)
7833 plci->rx_dma_descriptor++;
7834 }
7835 if (plci->rx_dma_descriptor > 0) {
7836 lli[0] = 6;
7837 lli[1] |= 0x40;
7838 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7839 lli[3] = (byte)plci->rx_dma_magic;
7840 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7841 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7842 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7843 }
7844 }
7845
7846 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7847 lli[1] |= 0x20;
7848 }
7849
7850 dbug(1, dprintf("add_b23"));
7851 api_save_msg(bp, "s", &plci->B_protocol);
7852
7853 if (!bp->length && plci->tel)
7854 {
7855 plci->adv_nl = true;
7856 dbug(1, dprintf("Default adv.Nl"));
7857 add_p(plci, LLI, lli);
7858 plci->B2_prot = 1 ;
7859 plci->B3_prot = 0 ;
7860 llc[1] = 2;
7861 llc[2] = 4;
7862 add_p(plci, LLC, llc);
7863 dlc[0] = 2;
7864 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7865 add_p(plci, DLC, dlc);
7866 return 0;
7867 }
7868
7869 if (!bp->length)
7870 {
7871 dbug(1, dprintf("ret default"));
7872 add_p(plci, LLI, lli);
7873 plci->B2_prot = 0 ;
7874 plci->B3_prot = 0 ;
7875 llc[1] = 1;
7876 llc[2] = 4;
7877 add_p(plci, LLC, llc);
7878 dlc[0] = 2;
7879 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7880 add_p(plci, DLC, dlc);
7881 return 0;
7882 }
7883 dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7884 if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7885
7886 if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7887 {
7888 bp_parms[6].length = 0;
7889 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7890 {
7891 dbug(1, dprintf("b-form.!"));
7892 return _WRONG_MESSAGE_FORMAT;
7893 }
7894 }
7895 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7896 {
7897 dbug(1, dprintf("b-form.!"));
7898 return _WRONG_MESSAGE_FORMAT;
7899 }
7900
7901 if (plci->tel == ADV_VOICE)
7902 {
7903 if (GET_WORD(bp_parms[1].info) != 1
7904 || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7905 plci->adv_nl = true;
7906 }
7907 else if (plci->tel) return _B2_NOT_SUPPORTED;
7908
7909
7910 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7911 && (GET_WORD(bp_parms[2].info) == B3_RTP)
7912 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7913 {
7914 add_p(plci, LLI, lli);
7915 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7916 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7917 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7918 llc[2] = 4;
7919 add_p(plci, LLC, llc);
7920 dlc[0] = 2;
7921 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7922 dlc[3] = 3;
7923 dlc[4] = 1;
7924 dlc[5] = 7;
7925 dlc[6] = 7;
7926 dlc[7] = 0;
7927 dlc[8] = 0;
7928 for (i = 0; i < bp_parms[4].length; i++)
7929 dlc[9 + i] = bp_parms[4].info[1 + i];
7930 dlc[0] = (byte)(8 + bp_parms[4].length);
7931 add_p(plci, DLC, dlc);
7932 for (i = 0; i < bp_parms[5].length; i++)
7933 nlc[1 + i] = bp_parms[5].info[1 + i];
7934 nlc[0] = (byte)(bp_parms[5].length);
7935 add_p(plci, NLC, nlc);
7936 return 0;
7937 }
7938
7939
7940
7941 if ((GET_WORD(bp_parms[1].info) >= 32)
7942 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7943 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7944 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7945
7946 {
7947 return _B2_NOT_SUPPORTED;
7948 }
7949 if ((GET_WORD(bp_parms[2].info) >= 32)
7950 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7951 {
7952 return _B3_NOT_SUPPORTED;
7953 }
7954 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7955 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7956 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7957 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7958 {
7959 return (add_modem_b23(plci, bp_parms));
7960 }
7961
7962 add_p(plci, LLI, lli);
7963
7964 plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7965 plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7966 if (plci->B2_prot == 12) SAPI = 0;
7967
7968 if (bp_parms[6].length)
7969 {
7970 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7971 {
7972 return _WRONG_MESSAGE_FORMAT;
7973 }
7974 switch (GET_WORD(global_config[0].info))
7975 {
7976 case 1:
7977 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7978 break;
7979 case 2:
7980 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7981 break;
7982 }
7983 }
7984 dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7985
7986
7987 if (plci->B2_prot == B2_PIAFS)
7988 llc[1] = PIAFS_CRC;
7989 else
7990
7991 {
7992 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7993 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7994 }
7995 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7996
7997 add_p(plci, LLC, llc);
7998
7999 dlc[0] = 2;
8000 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8001 header[GET_WORD(bp_parms[2].info)]);
8002
8003 b1_config = &bp_parms[3];
8004 nlc[0] = 0;
8005 if (plci->B3_prot == 4
8006 || plci->B3_prot == 5)
8007 {
8008 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8009 nlc[0] = sizeof(T30_INFO);
8010 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8011 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8012 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8013 if (b1_config->length >= 2)
8014 {
8015 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8016 }
8017 }
8018 b2_config = &bp_parms[4];
8019
8020
8021 if (llc[1] == PIAFS_CRC)
8022 {
8023 if (plci->B3_prot != B3_TRANSPARENT)
8024 {
8025 return _B_STACK_NOT_SUPPORTED;
8026 }
8027 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8028 return _WRONG_MESSAGE_FORMAT;
8029 }
8030 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8031 dlc[3] = 0;
8032 dlc[4] = 0;
8033 dlc[5] = 0;
8034 dlc[6] = 0;
8035 if (b2_config->length >= 7) {
8036 dlc[7] = 7;
8037 dlc[8] = 0;
8038 dlc[9] = b2_config_parms[0].info[0];
8039 dlc[10] = b2_config_parms[1].info[0];
8040 dlc[11] = b2_config_parms[1].info[1];
8041 dlc[12] = b2_config_parms[2].info[0];
8042 dlc[13] = b2_config_parms[2].info[1];
8043 dlc[14] = b2_config_parms[3].info[0];
8044 dlc[15] = b2_config_parms[3].info[1];
8045 dlc[0] = 15;
8046 if (b2_config->length >= 8) {
8047 dlc[7] = 10;
8048 dlc[16] = 2;
8049 dlc[17] = PIAFS_UDATA_ABILITIES;
8050 dlc[18] = b2_config_parms[4].info[0];
8051 dlc[0] = 18;
8052 }
8053 }
8054 else
8055 {
8056 dlc[7] = 7;
8057 dlc[8] = 0;
8058 dlc[9] = 0x03;
8059 dlc[10] = 0x03;
8060 dlc[11] = 0;
8061 dlc[12] = 0;
8062 dlc[13] = 0;
8063 dlc[14] = 0;
8064 dlc[15] = 0;
8065 dlc[0] = 15;
8066 }
8067 add_p(plci, DLC, dlc);
8068 }
8069 else
8070
8071 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8072 {
8073 if (plci->B3_prot != B3_TRANSPARENT)
8074 return _B_STACK_NOT_SUPPORTED;
8075
8076 dlc[0] = 6;
8077 PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8078 dlc[3] = 0x08;
8079 dlc[4] = 0x01;
8080 dlc[5] = 127;
8081 dlc[6] = 7;
8082 if (b2_config->length != 0)
8083 {
8084 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8085 return _WRONG_MESSAGE_FORMAT;
8086 }
8087 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8088 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8089 if (b2_config->info[3] != 128)
8090 {
8091 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8092 return _B2_PARM_NOT_SUPPORTED;
8093 }
8094 dlc[5] = (byte)(b2_config->info[3] - 1);
8095 dlc[6] = b2_config->info[4];
8096 if (llc[1] == V120_V42BIS) {
8097 if (b2_config->length >= 10) {
8098 dlc[7] = 6;
8099 dlc[8] = 0;
8100 dlc[9] = b2_config_parms[4].info[0];
8101 dlc[10] = b2_config_parms[4].info[1];
8102 dlc[11] = b2_config_parms[5].info[0];
8103 dlc[12] = b2_config_parms[5].info[1];
8104 dlc[13] = b2_config_parms[6].info[0];
8105 dlc[14] = b2_config_parms[6].info[1];
8106 dlc[0] = 14;
8107 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8108 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8109 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8110 }
8111 else {
8112 dlc[6] = 14;
8113 }
8114 }
8115 }
8116 }
8117 else
8118 {
8119 if (b2_config->length)
8120 {
8121 dbug(1, dprintf("B2-Config"));
8122 if (llc[1] == X75_V42BIS) {
8123 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8124 {
8125 return _WRONG_MESSAGE_FORMAT;
8126 }
8127 }
8128 else {
8129 if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8130 {
8131 return _WRONG_MESSAGE_FORMAT;
8132 }
8133 }
8134
8135 if (llc[1] == 6)
8136 {
8137 dlc[0] = 4;
8138 if (b2_config->length >= 1) dlc[2] = b2_config->info[1];
8139 else dlc[2] = 0x01;
8140 if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8141 {
8142 SAPI = b2_config->info[2];
8143 }
8144 dlc[1] = SAPI;
8145 if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8146 {
8147 dlc[3] = 127;
8148 }
8149 else
8150 {
8151 dlc[3] = 7;
8152 }
8153
8154 if (b2_config->length >= 4) dlc[4] = b2_config->info[4];
8155 else dlc[4] = 1;
8156 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8157 if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8158 }
8159 else
8160 {
8161 dlc[0] = (byte)(b2_config_parms[4].length + 6);
8162 dlc[3] = b2_config->info[1];
8163 dlc[4] = b2_config->info[2];
8164 if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8165 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8166 return _B2_PARM_NOT_SUPPORTED;
8167 }
8168
8169 dlc[5] = (byte)(b2_config->info[3] - 1);
8170 dlc[6] = b2_config->info[4];
8171 if (dlc[6] > dlc[5]) {
8172 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]));
8173 return _B2_PARM_NOT_SUPPORTED;
8174 }
8175
8176 if (llc[1] == X75_V42BIS) {
8177 if (b2_config->length >= 10) {
8178 dlc[7] = 6;
8179 dlc[8] = 0;
8180 dlc[9] = b2_config_parms[4].info[0];
8181 dlc[10] = b2_config_parms[4].info[1];
8182 dlc[11] = b2_config_parms[5].info[0];
8183 dlc[12] = b2_config_parms[5].info[1];
8184 dlc[13] = b2_config_parms[6].info[0];
8185 dlc[14] = b2_config_parms[6].info[1];
8186 dlc[0] = 14;
8187 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8188 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8189 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8190 }
8191 else {
8192 dlc[6] = 14;
8193 }
8194
8195 }
8196 else {
8197 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8198 for (i = 0; i < b2_config_parms[4].length; i++)
8199 dlc[11 + i] = b2_config_parms[4].info[1 + i];
8200 }
8201 }
8202 }
8203 }
8204 add_p(plci, DLC, dlc);
8205
8206 b3_config = &bp_parms[5];
8207 if (b3_config->length)
8208 {
8209 if (plci->B3_prot == 4
8210 || plci->B3_prot == 5)
8211 {
8212 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8213 {
8214 return _WRONG_MESSAGE_FORMAT;
8215 }
8216 i = GET_WORD((byte *)(b3_config_parms[0].info));
8217 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8218 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8219 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8220 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8221 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8222 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8223 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8224 {
8225
8226 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8227 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8228 {
8229 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8230 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8231 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8232 }
8233
8234 ((T30_INFO *)&nlc[1])->recording_properties =
8235 T30_RECORDING_WIDTH_ISO_A3 |
8236 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8237 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8238 }
8239 if (plci->B3_prot == 5)
8240 {
8241 if (i & 0x0002)
8242 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8243 if (i & 0x2000)
8244 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8245 if (i & 0x4000)
8246 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8247 if (i & 0x8000)
8248 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8249 if (plci->fax_connect_info_length != 0)
8250 {
8251 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8252 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8253 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8254 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8255 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8256 }
8257 }
8258
8259 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8260 {
8261 if (i < b3_config_parms[2].length)
8262 {
8263 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8264 }
8265 else
8266 {
8267 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8268 }
8269 }
8270 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8271
8272 if (b3_config_parms[3].length)
8273 {
8274
8275 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8276 if (pos != 0)
8277 {
8278 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8279 pos = 0;
8280 else
8281 {
8282 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8283 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8284 len = (byte)b3_config_parms[2].length;
8285 if (len > 20)
8286 len = 20;
8287 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8288 {
8289 for (i = 0; i < len; i++)
8290 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8291 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8292 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8293 }
8294 }
8295 }
8296
8297 len = (byte)b3_config_parms[3].length;
8298 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8299 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8300 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8301 nlc[0] += (byte)(pos + len);
8302 for (i = 0; i < len; i++)
8303 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8304 } else
8305 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8306
8307 plci->nsf_control_bits = 0;
8308 if (plci->B3_prot == 5)
8309 {
8310 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8311 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000))
8312 {
8313 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8314 }
8315 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8316 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000))
8317 {
8318 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8319 }
8320 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8321 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8322 {
8323 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8324 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8325 {
8326 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8327 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8328 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8329 }
8330 len = nlc[0];
8331 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8332 if (pos < plci->fax_connect_info_length)
8333 {
8334 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8335 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8336 }
8337 else
8338 nlc[++len] = 0;
8339 if (pos < plci->fax_connect_info_length)
8340 {
8341 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8342 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8343 }
8344 else
8345 nlc[++len] = 0;
8346 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8347 & (1L << PRIVATE_FAX_NONSTANDARD))
8348 {
8349 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8350 {
8351 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8352 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8353 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8354 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8355 }
8356 else
8357 {
8358 if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8359 {
8360 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8361 nlc[++len] = 0;
8362 }
8363 else
8364 {
8365 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8366 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8367 nlc[++len] = (byte)(b3_config_parms[4].length);
8368 for (i = 0; i < b3_config_parms[4].length; i++)
8369 nlc[++len] = b3_config_parms[4].info[1 + i];
8370 }
8371 }
8372 }
8373 nlc[0] = len;
8374 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8375 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8376 {
8377 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8378 }
8379 }
8380 }
8381
8382 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8383 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8384 for (i = 0; i < len; i++)
8385 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8386 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8387 i += ((T30_INFO *)&nlc[1])->head_line_len;
8388 while (i < nlc[0])
8389 plci->fax_connect_info_buffer[len++] = nlc[++i];
8390 plci->fax_connect_info_length = len;
8391 }
8392 else
8393 {
8394 nlc[0] = 14;
8395 if (b3_config->length != 16)
8396 return _B3_PARM_NOT_SUPPORTED;
8397 for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8398 if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8399 return _B3_PARM_NOT_SUPPORTED;
8400 nlc[13] = b3_config->info[13];
8401 if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8402 return _B3_PARM_NOT_SUPPORTED;
8403 nlc[14] = b3_config->info[15];
8404 }
8405 }
8406 else
8407 {
8408 if (plci->B3_prot == 4
8409 || plci->B3_prot == 5 ) return _B3_PARM_NOT_SUPPORTED;
8410 }
8411 add_p(plci, NLC, nlc);
8412 return 0;
8413}
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8431{
8432 static byte lli[12] = {1,1};
8433 static byte llc[3] = {2,0,0};
8434 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8435 API_PARSE mdm_config[2];
8436 word i;
8437 word b2_config = 0;
8438
8439 for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8440 for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8441
8442 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8443 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8444 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8445 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8446 {
8447 return (_B_STACK_NOT_SUPPORTED);
8448 }
8449 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8450 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8451 {
8452 return (_B_STACK_NOT_SUPPORTED);
8453 }
8454
8455 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8456 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8457
8458 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8459 {
8460 if (api_parse(&bp_parms[4].info[1],
8461 (word)bp_parms[4].length, "w",
8462 mdm_config))
8463 {
8464 return (_WRONG_MESSAGE_FORMAT);
8465 }
8466 b2_config = GET_WORD(mdm_config[0].info);
8467 }
8468
8469
8470
8471 lli[0] = 1;
8472 lli[1] = 1;
8473 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8474 lli[1] |= 2;
8475 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8476 lli[1] |= 4;
8477
8478 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8479 lli[1] |= 0x10;
8480 if (plci->rx_dma_descriptor <= 0) {
8481 plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8482 if (plci->rx_dma_descriptor >= 0)
8483 plci->rx_dma_descriptor++;
8484 }
8485 if (plci->rx_dma_descriptor > 0) {
8486 lli[1] |= 0x40;
8487 lli[0] = 6;
8488 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8489 lli[3] = (byte)plci->rx_dma_magic;
8490 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8491 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8492 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8493 }
8494 }
8495
8496 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8497 lli[1] |= 0x20;
8498 }
8499
8500 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8501 10 : 9;
8502 llc[2] = 4;
8503 add_p(plci, LLI, lli);
8504 add_p(plci, LLC, llc);
8505 i = 1;
8506 PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8507 i += 2;
8508 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8509 {
8510 if (bp_parms[4].length)
8511 {
8512 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8513 dlc[i++] = 3;
8514 dlc[i++] = 1;
8515 dlc[i++] = 7;
8516 dlc[i++] = 7;
8517 dlc[i++] = 0;
8518 dlc[i++] = 0;
8519
8520 if (b2_config & MDM_B2_DISABLE_V42bis)
8521 {
8522 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8523 }
8524 if (b2_config & MDM_B2_DISABLE_MNP)
8525 {
8526 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8527 }
8528 if (b2_config & MDM_B2_DISABLE_TRANS)
8529 {
8530 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8531 }
8532 if (b2_config & MDM_B2_DISABLE_V42)
8533 {
8534 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8535 }
8536 if (b2_config & MDM_B2_DISABLE_COMP)
8537 {
8538 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8539 }
8540 i++;
8541 }
8542 }
8543 else
8544 {
8545 dlc[i++] = 3;
8546 dlc[i++] = 1;
8547 dlc[i++] = 7;
8548 dlc[i++] = 7;
8549 dlc[i++] = 0;
8550 dlc[i++] = 0;
8551 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8552 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8553 DLC_MODEMPROT_DISABLE_V42_DETECT |
8554 DLC_MODEMPROT_DISABLE_COMPRESSION;
8555 }
8556 dlc[0] = (byte)(i - 1);
8557
8558 add_p(plci, DLC, dlc);
8559 return (0);
8560}
8561
8562
8563
8564
8565
8566
8567static void sig_req(PLCI *plci, byte req, byte Id)
8568{
8569 if (!plci) return;
8570 if (plci->adapter->adapter_disabled) return;
8571 dbug(1, dprintf("sig_req(%x)", req));
8572 if (req == REMOVE)
8573 plci->sig_remove_id = plci->Sig.Id;
8574 if (plci->req_in == plci->req_in_start) {
8575 plci->req_in += 2;
8576 plci->RBuffer[plci->req_in++] = 0;
8577 }
8578 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8579 plci->RBuffer[plci->req_in++] = Id;
8580 plci->RBuffer[plci->req_in++] = req;
8581 plci->RBuffer[plci->req_in++] = 0;
8582 plci->req_in_start = plci->req_in;
8583}
8584
8585
8586
8587
8588
8589static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8590{
8591 if (!plci) return;
8592 if (plci->adapter->adapter_disabled) return;
8593 dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8594 if (req == REMOVE)
8595 {
8596 plci->nl_remove_id = plci->NL.Id;
8597 ncci_remove(plci, 0, (byte)(ncci != 0));
8598 ncci = 0;
8599 }
8600 if (plci->req_in == plci->req_in_start) {
8601 plci->req_in += 2;
8602 plci->RBuffer[plci->req_in++] = 0;
8603 }
8604 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8605 plci->RBuffer[plci->req_in++] = 1;
8606 plci->RBuffer[plci->req_in++] = req;
8607 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];
8608 plci->req_in_start = plci->req_in;
8609}
8610
8611static void send_req(PLCI *plci)
8612{
8613 ENTITY *e;
8614 word l;
8615
8616
8617 if (!plci) return;
8618 if (plci->adapter->adapter_disabled) return;
8619 channel_xmit_xon(plci);
8620
8621
8622 if (plci->req_in == plci->req_out) return;
8623 dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8624
8625 if (plci->nl_req || plci->sig_req) return;
8626
8627 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8628 plci->req_out += 2;
8629 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8630 plci->req_out += l;
8631 if (plci->RBuffer[plci->req_out] == 1)
8632 {
8633 e = &plci->NL;
8634 plci->req_out++;
8635 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8636 e->ReqCh = plci->RBuffer[plci->req_out++];
8637 if (!(e->Id & 0x1f))
8638 {
8639 e->Id = NL_ID;
8640 plci->RBuffer[plci->req_out - 4] = CAI;
8641 plci->RBuffer[plci->req_out - 3] = 1;
8642 plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8643 plci->RBuffer[plci->req_out - 1] = 0;
8644 l += 3;
8645 plci->nl_global_req = plci->nl_req;
8646 }
8647 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8648 }
8649 else
8650 {
8651 e = &plci->Sig;
8652 if (plci->RBuffer[plci->req_out])
8653 e->Id = plci->RBuffer[plci->req_out];
8654 plci->req_out++;
8655 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8656 e->ReqCh = plci->RBuffer[plci->req_out++];
8657 if (!(e->Id & 0x1f))
8658 plci->sig_global_req = plci->sig_req;
8659 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8660 }
8661 plci->XData[0].PLength = l;
8662 e->X = plci->XData;
8663 plci->adapter->request(e);
8664 dbug(1, dprintf("send_ok"));
8665}
8666
8667static void send_data(PLCI *plci)
8668{
8669 DIVA_CAPI_ADAPTER *a;
8670 DATA_B3_DESC *data;
8671 NCCI *ncci_ptr;
8672 word ncci;
8673
8674 if (!plci->nl_req && plci->ncci_ring_list)
8675 {
8676 a = plci->adapter;
8677 ncci = plci->ncci_ring_list;
8678 do
8679 {
8680 ncci = a->ncci_next[ncci];
8681 ncci_ptr = &(a->ncci[ncci]);
8682 if (!(a->ncci_ch[ncci]
8683 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8684 {
8685 if (ncci_ptr->data_pending)
8686 {
8687 if ((a->ncci_state[ncci] == CONNECTED)
8688 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8689 || (plci->send_disc == ncci))
8690 {
8691 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8692 if ((plci->B2_prot == B2_V120_ASYNC)
8693 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8694 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8695 {
8696 plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8697 plci->NData[1].PLength = data->Length;
8698 if (data->Flags & 0x10)
8699 plci->NData[0].P = v120_break_header;
8700 else
8701 plci->NData[0].P = v120_default_header;
8702 plci->NData[0].PLength = 1;
8703 plci->NL.XNum = 2;
8704 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8705 }
8706 else
8707 {
8708 plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8709 plci->NData[0].PLength = data->Length;
8710 if (data->Flags & 0x10)
8711 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8712
8713 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8714 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8715
8716 else
8717 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8718 }
8719 plci->NL.X = plci->NData;
8720 plci->NL.ReqCh = a->ncci_ch[ncci];
8721 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8722 plci->data_sent = true;
8723 plci->data_sent_ptr = data->P;
8724 a->request(&plci->NL);
8725 }
8726 else {
8727 cleanup_ncci_data(plci, ncci);
8728 }
8729 }
8730 else if (plci->send_disc == ncci)
8731 {
8732
8733 plci->NData[0].PLength = 0;
8734 plci->NL.ReqCh = a->ncci_ch[ncci];
8735 plci->NL.Req = plci->nl_req = N_DISC;
8736 a->request(&plci->NL);
8737 plci->command = _DISCONNECT_B3_R;
8738 plci->send_disc = 0;
8739 }
8740 }
8741 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8742 plci->ncci_ring_list = ncci;
8743 }
8744}
8745
8746static void listen_check(DIVA_CAPI_ADAPTER *a)
8747{
8748 word i, j;
8749 PLCI *plci;
8750 byte activnotifiedcalls = 0;
8751
8752 dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8753 if (!remove_started && !a->adapter_disabled)
8754 {
8755 for (i = 0; i < a->max_plci; i++)
8756 {
8757 plci = &(a->plci[i]);
8758 if (plci->notifiedcall) activnotifiedcalls++;
8759 }
8760 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8761
8762 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8763 if ((j = get_plci(a))) {
8764 a->listen_active++;
8765 plci = &a->plci[j - 1];
8766 plci->State = LISTENING;
8767
8768 add_p(plci, OAD, "\x01\xfd");
8769
8770 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8771
8772 add_p(plci, CAI, "\x01\xc0");
8773 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8774 add_p(plci, LLI, "\x01\xc4");
8775 add_p(plci, SHIFT | 6, NULL);
8776 add_p(plci, SIN, "\x02\x00\x00");
8777 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;
8778 sig_req(plci, ASSIGN, DSIG_ID);
8779 send_req(plci);
8780 }
8781 }
8782 }
8783}
8784
8785
8786
8787
8788
8789static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8790{
8791 word ploc;
8792 byte w;
8793 byte wlen;
8794 byte codeset, lock;
8795 byte *in;
8796 word i;
8797 word code;
8798 word mIEindex = 0;
8799 ploc = 0;
8800 codeset = 0;
8801 lock = 0;
8802
8803 in = plci->Sig.RBuffer->P;
8804 for (i = 0; i < parms_id[0]; i++)
8805 {
8806 parms[i] = (byte *)"";
8807 }
8808 for (i = 0; i < multiIEsize; i++)
8809 {
8810 parms[i] = (byte *)"";
8811 }
8812
8813 while (ploc < plci->Sig.RBuffer->length - 1) {
8814
8815
8816 w = in[ploc];
8817
8818 if (w & 0x80) {
8819
8820
8821 wlen = 0;
8822 }
8823 else {
8824 wlen = (byte)(in[ploc + 1] + 1);
8825 }
8826
8827 if ((ploc + wlen) > 270) return;
8828 if (lock & 0x80) lock &= 0x7f;
8829 else codeset = lock;
8830
8831 if ((w & 0xf0) == SHIFT) {
8832 codeset = in[ploc];
8833 if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8834 codeset &= 7;
8835 lock |= 0x80;
8836 }
8837 else {
8838 if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8839 else code = w;
8840 code |= (codeset << 8);
8841
8842 for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8843
8844 if (i < parms_id[0] + 1) {
8845 if (!multiIEsize) {
8846 mIEindex = i - 1;
8847 }
8848
8849 parms[mIEindex] = &in[ploc + 1];
8850 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8851 if (parms_id[i] == OAD
8852 || parms_id[i] == CONN_NR
8853 || parms_id[i] == CAD) {
8854 if (in[ploc + 2] & 0x80) {
8855 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8856 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8857 in[ploc + 2] = 0x80;
8858 parms[mIEindex] = &in[ploc];
8859 }
8860 }
8861 mIEindex++;
8862 }
8863 }
8864
8865 ploc += (wlen + 1);
8866 }
8867 return;
8868}
8869
8870
8871
8872
8873
8874static byte ie_compare(byte *ie1, byte *ie2)
8875{
8876 word i;
8877 if (!ie1 || !ie2) return false;
8878 if (!ie1[0]) return false;
8879 for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8880 return true;
8881}
8882
8883static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8884{
8885 word i;
8886 word j;
8887
8888 for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8889
8890 for (j = 16; j < 29 &&
8891 (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8892 if (j == 29) return i;
8893 return j;
8894}
8895
8896
8897static byte AddInfo(byte **add_i,
8898 byte **fty_i,
8899 byte *esc_chi,
8900 byte *facility)
8901{
8902 byte i;
8903 byte j;
8904 byte k;
8905 byte flen;
8906 byte len = 0;
8907
8908
8909
8910 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8911 {
8912 add_i[0] = (byte *)"\x02\x02\x00";
8913 }
8914
8915 else
8916 {
8917 add_i[0] = (byte *)"";
8918 }
8919 if (!fty_i[0][0])
8920 {
8921 add_i[3] = (byte *)"";
8922 }
8923 else
8924 {
8925 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8926 {
8927 dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8928 len += fty_i[i][0];
8929 len += 2;
8930 flen = fty_i[i][0];
8931 facility[j++] = 0x1c;
8932 for (k = 0; k <= flen; k++, j++)
8933 {
8934 facility[j] = fty_i[i][k];
8935
8936 }
8937 }
8938 facility[0] = len;
8939 add_i[3] = facility;
8940 }
8941
8942 len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8943 len += 4;
8944 return (len);
8945}
8946
8947
8948
8949
8950
8951static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8952{
8953 byte voice_chi[] = "\x02\x18\x01";
8954 byte channel;
8955
8956 channel = chi[chi[0]] & 0x3;
8957 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8958 voice_chi[2] = (channel) ? channel : 1;
8959 add_p(plci, FTY, "\x02\x01\x07");
8960 add_p(plci, ESC, voice_chi);
8961 sig_req(plci, TEL_CTRL, 0);
8962 send_req(plci);
8963 if (a->AdvSignalPLCI)
8964 {
8965 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8966 }
8967}
8968
8969static void VoiceChannelOff(PLCI *plci)
8970{
8971 dbug(1, dprintf("ExtDevOFF"));
8972 add_p(plci, FTY, "\x02\x01\x08");
8973 sig_req(plci, TEL_CTRL, 0);
8974 send_req(plci);
8975 if (plci->adapter->AdvSignalPLCI)
8976 {
8977 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8978 }
8979}
8980
8981
8982static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8983 byte hook_listen)
8984{
8985 word j;
8986 PLCI *splci;
8987
8988
8989
8990
8991
8992
8993 if (a->profile.Global_Options & HANDSET)
8994 {
8995
8996 if (a->AdvCodecFLAG)
8997 {
8998 if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
8999 {
9000 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9001 return 0x2001;
9002 }
9003 if (plci != NULL)
9004 {
9005 a->AdvSignalPLCI = plci;
9006 plci->tel = ADV_VOICE;
9007 }
9008 return 0;
9009 }
9010 if ((j = get_plci(a)))
9011 {
9012 splci = &a->plci[j - 1];
9013 splci->tel = CODEC_PERMANENT;
9014
9015
9016
9017
9018 if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9019 else
9020 {
9021 splci->State = ADVANCED_VOICE_NOSIG;
9022 if (plci)
9023 {
9024 plci->spoofed_msg = SPOOFING_REQUIRED;
9025 }
9026
9027 }
9028 if (plci != NULL)
9029 {
9030 a->AdvSignalPLCI = plci;
9031 plci->tel = ADV_VOICE;
9032 }
9033 a->AdvSignalAppl = appl;
9034 a->AdvCodecFLAG = true;
9035 a->AdvCodecPLCI = splci;
9036 add_p(splci, CAI, "\x01\x15");
9037 add_p(splci, LLI, "\x01\x00");
9038 add_p(splci, ESC, "\x02\x18\x00");
9039 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9040 splci->internal_command = PERM_COD_ASSIGN;
9041 dbug(1, dprintf("Codec Assign"));
9042 sig_req(splci, ASSIGN, DSIG_ID);
9043 send_req(splci);
9044 }
9045 else
9046 {
9047 return 0x2001;
9048 }
9049 }
9050 else if (a->profile.Global_Options & ON_BOARD_CODEC)
9051 {
9052 if (hook_listen) return 0x300B;
9053
9054 if (plci != NULL) plci->tel = CODEC;
9055 dbug(1, dprintf("S/SCOM codec"));
9056
9057
9058
9059 if (!a->scom_appl_disable) {
9060 if ((j = get_plci(a))) {
9061 splci = &a->plci[j - 1];
9062 add_p(splci, CAI, "\x01\x80");
9063 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9064 sig_req(splci, ASSIGN, 0xC0);
9065 send_req(splci);
9066 a->scom_appl_disable = true;
9067 }
9068 else{
9069 return 0x2001;
9070 }
9071 }
9072 }
9073 else return 0x300B;
9074
9075 return 0;
9076}
9077
9078
9079static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9080{
9081
9082 dbug(1, dprintf("CodecIdCheck"));
9083
9084 if (a->AdvSignalPLCI == plci)
9085 {
9086 dbug(1, dprintf("PLCI owns codec"));
9087 VoiceChannelOff(a->AdvCodecPLCI);
9088 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9089 {
9090 dbug(1, dprintf("remove temp codec PLCI"));
9091 plci_remove(a->AdvCodecPLCI);
9092 a->AdvCodecFLAG = 0;
9093 a->AdvCodecPLCI = NULL;
9094 a->AdvSignalAppl = NULL;
9095 }
9096 a->AdvSignalPLCI = NULL;
9097 }
9098}
9099
9100
9101
9102
9103static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9104 IDI_SYNC_REQ *preq) {
9105 a->sdram_bar = 0;
9106 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9107 ENTITY *e = (ENTITY *)preq;
9108
9109 e->user[0] = a->Id - 1;
9110 preq->xdi_sdram_bar.info.bar = 0;
9111 preq->xdi_sdram_bar.Req = 0;
9112 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9113
9114 (*(a->request))(e);
9115
9116 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9117 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9118 }
9119}
9120
9121
9122
9123
9124static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9125 IDI_SYNC_REQ *preq;
9126 char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9127
9128 char features[4];
9129 preq = (IDI_SYNC_REQ *)&buffer[0];
9130
9131 if (!diva_xdi_extended_features) {
9132 ENTITY *e = (ENTITY *)preq;
9133 diva_xdi_extended_features |= 0x80000000;
9134
9135 e->user[0] = a->Id - 1;
9136 preq->xdi_extended_features.Req = 0;
9137 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9138 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9139 preq->xdi_extended_features.info.features = &features[0];
9140
9141 (*(a->request))(e);
9142
9143 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9144
9145
9146
9147 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9148 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9149 }
9150 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9151 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9152 dbug(1, dprintf("XDI provides RxDMA"));
9153 }
9154 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9155 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9156 }
9157 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9158 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9159 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9160 }
9161
9162 }
9163 }
9164
9165 diva_ask_for_xdi_sdram_bar(a, preq);
9166}
9167
9168
9169
9170
9171
9172
9173void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9174{
9175 word j;
9176 PLCI *splci;
9177
9178 if (a->automatic_law) {
9179 return;
9180 }
9181 if ((j = get_plci(a))) {
9182 diva_get_extended_adapter_features(a);
9183 splci = &a->plci[j - 1];
9184 a->automatic_lawPLCI = splci;
9185 a->automatic_law = 1;
9186 add_p(splci, CAI, "\x01\x80");
9187 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9188 splci->internal_command = USELAW_REQ;
9189 splci->command = 0;
9190 splci->number = 0;
9191 sig_req(splci, ASSIGN, DSIG_ID);
9192 send_req(splci);
9193 }
9194}
9195
9196
9197word CapiRelease(word Id)
9198{
9199 word i, j, appls_found;
9200 PLCI *plci;
9201 APPL *this;
9202 DIVA_CAPI_ADAPTER *a;
9203
9204 if (!Id)
9205 {
9206 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9207 return (_WRONG_APPL_ID);
9208 }
9209
9210 this = &application[Id - 1];
9211
9212 for (i = 0, appls_found = 0; i < max_appl; i++)
9213 {
9214 if (application[i].Id)
9215 {
9216 appls_found++;
9217 }
9218 }
9219
9220 for (i = 0; i < max_adapter; i++)
9221 {
9222 a = &adapter[i];
9223 if (a->request)
9224 {
9225 a->Info_Mask[Id - 1] = 0;
9226 a->CIP_Mask[Id - 1] = 0;
9227 a->Notification_Mask[Id - 1] = 0;
9228 a->codec_listen[Id - 1] = NULL;
9229 a->requested_options_table[Id - 1] = 0;
9230 for (j = 0; j < a->max_plci; j++)
9231 {
9232 plci = &a->plci[j];
9233 if (plci->Id)
9234 {
9235 if (plci->State == INC_CON_PENDING
9236 || plci->State == INC_CON_ALERT)
9237 {
9238 if (test_bit(Id - 1, plci->c_ind_mask_table))
9239 {
9240 __clear_bit(Id - 1, plci->c_ind_mask_table);
9241 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9242 {
9243 sig_req(plci, HANGUP, 0);
9244 send_req(plci);
9245 plci->State = OUTG_DIS_PENDING;
9246 }
9247 }
9248 }
9249 if (test_bit(Id - 1, plci->c_ind_mask_table))
9250 {
9251 __clear_bit(Id - 1, plci->c_ind_mask_table);
9252 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9253 {
9254 if (!plci->appl)
9255 {
9256 plci_remove(plci);
9257 plci->State = IDLE;
9258 }
9259 }
9260 }
9261 if (plci->appl == this)
9262 {
9263 plci->appl = NULL;
9264 plci_remove(plci);
9265 plci->State = IDLE;
9266 }
9267 }
9268 }
9269 listen_check(a);
9270
9271 if (a->flag_dynamic_l1_down)
9272 {
9273 if (appls_found == 1)
9274 {
9275 if ((j = get_plci(a)))
9276 {
9277 plci = &a->plci[j - 1];
9278 plci->command = 0;
9279 add_p(plci, OAD, "\x01\xfd");
9280 add_p(plci, CAI, "\x01\x80");
9281 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9282 add_p(plci, SHIFT | 6, NULL);
9283 add_p(plci, SIN, "\x02\x00\x00");
9284 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9285 sig_req(plci, ASSIGN, DSIG_ID);
9286 add_p(plci, FTY, "\x02\xff\x06");
9287 sig_req(plci, SIG_CTRL, 0);
9288 send_req(plci);
9289 }
9290 }
9291 }
9292 if (a->AdvSignalAppl == this)
9293 {
9294 this->NullCREnable = false;
9295 if (a->AdvCodecPLCI)
9296 {
9297 plci_remove(a->AdvCodecPLCI);
9298 a->AdvCodecPLCI->tel = 0;
9299 a->AdvCodecPLCI->adv_nl = 0;
9300 }
9301 a->AdvSignalAppl = NULL;
9302 a->AdvSignalPLCI = NULL;
9303 a->AdvCodecFLAG = 0;
9304 a->AdvCodecPLCI = NULL;
9305 }
9306 }
9307 }
9308
9309 this->Id = 0;
9310
9311 return GOOD;
9312}
9313
9314static word plci_remove_check(PLCI *plci)
9315{
9316 if (!plci) return true;
9317 if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9318 {
9319 if (plci->Sig.Id == 0xff)
9320 plci->Sig.Id = 0;
9321 if (!plci->Sig.Id)
9322 {
9323 dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9324 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9325 if (plci->Id)
9326 {
9327 CodecIdCheck(plci->adapter, plci);
9328 clear_b1_config(plci);
9329 ncci_remove(plci, 0, false);
9330 plci_free_msg_in_queue(plci);
9331 channel_flow_control_remove(plci);
9332 plci->Id = 0;
9333 plci->State = IDLE;
9334 plci->channels = 0;
9335 plci->appl = NULL;
9336 plci->notifiedcall = 0;
9337 }
9338 listen_check(plci->adapter);
9339 return true;
9340 }
9341 }
9342 return false;
9343}
9344
9345
9346
9347
9348static byte plci_nl_busy(PLCI *plci)
9349{
9350
9351 return (plci->nl_req
9352 || (plci->ncci_ring_list
9353 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9354 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9355}
9356
9357
9358
9359
9360
9361
9362
9363static struct
9364{
9365 byte send_mask;
9366 byte listen_mask;
9367 byte character;
9368 byte code;
9369} dtmf_digit_map[] =
9370{
9371 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9372 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9373 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9374 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9375 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9376 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9377 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9378 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9379 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9380 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9381 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9382 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9383 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9384 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9385 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9386 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9387 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9388 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9389 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9390 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9391
9392 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9393 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9394 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9395 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9396 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9397 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9398 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9399 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9400 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9401 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9402 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9403 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9404 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9405 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9406 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9407 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9408 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9409 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9410 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9411 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9412 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9413 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9414 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9415 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9416 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9417 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9418 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9419 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9420 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9421 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9422 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9423 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9424 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9425 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9426 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9427 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9428 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9429 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9430 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9431 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9432 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9433 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9434 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9435 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9436 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9437 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9438 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9439 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9440 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9441 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9442 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9443 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9444
9445};
9446
9447#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9448
9449
9450static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9451{
9452 word min_digit_duration, min_gap_duration;
9453
9454 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9455 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9456 (char *)(FILE_), __LINE__, enable_mask));
9457
9458 if (enable_mask != 0)
9459 {
9460 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9461 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9462 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9463 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9464 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9465 plci->NData[0].PLength = 5;
9466
9467 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9468 plci->NData[0].PLength += 2;
9469 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9470
9471 }
9472 else
9473 {
9474 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9475 plci->NData[0].PLength = 1;
9476
9477 capidtmf_recv_disable(&(plci->capidtmf_state));
9478
9479 }
9480 plci->NData[0].P = plci->internal_req_buffer;
9481 plci->NL.X = plci->NData;
9482 plci->NL.ReqCh = 0;
9483 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9484 plci->adapter->request(&plci->NL);
9485}
9486
9487
9488static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9489{
9490 word w, i;
9491
9492 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9493 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9494 (char *)(FILE_), __LINE__, digit_count));
9495
9496 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9497 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9498 PUT_WORD(&plci->internal_req_buffer[1], w);
9499 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9500 PUT_WORD(&plci->internal_req_buffer[3], w);
9501 for (i = 0; i < digit_count; i++)
9502 {
9503 w = 0;
9504 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9505 && (digit_buffer[i] != dtmf_digit_map[w].character))
9506 {
9507 w++;
9508 }
9509 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9510 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9511 }
9512 plci->NData[0].PLength = 5 + digit_count;
9513 plci->NData[0].P = plci->internal_req_buffer;
9514 plci->NL.X = plci->NData;
9515 plci->NL.ReqCh = 0;
9516 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9517 plci->adapter->request(&plci->NL);
9518}
9519
9520
9521static void dtmf_rec_clear_config(PLCI *plci)
9522{
9523
9524 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9525 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9526 (char *)(FILE_), __LINE__));
9527
9528 plci->dtmf_rec_active = 0;
9529 plci->dtmf_rec_pulse_ms = 0;
9530 plci->dtmf_rec_pause_ms = 0;
9531
9532 capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9533
9534}
9535
9536
9537static void dtmf_send_clear_config(PLCI *plci)
9538{
9539
9540 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9541 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9542 (char *)(FILE_), __LINE__));
9543
9544 plci->dtmf_send_requests = 0;
9545 plci->dtmf_send_pulse_ms = 0;
9546 plci->dtmf_send_pause_ms = 0;
9547}
9548
9549
9550static void dtmf_prepare_switch(dword Id, PLCI *plci)
9551{
9552
9553 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9554 UnMapId(Id), (char *)(FILE_), __LINE__));
9555
9556 while (plci->dtmf_send_requests != 0)
9557 dtmf_confirmation(Id, plci);
9558}
9559
9560
9561static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9562{
9563
9564 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9565 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9566
9567 return (GOOD);
9568}
9569
9570
9571static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9572{
9573 word Info;
9574
9575 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9576 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9577
9578 Info = GOOD;
9579 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9580 {
9581 switch (plci->adjust_b_state)
9582 {
9583 case ADJUST_B_RESTORE_DTMF_1:
9584 plci->internal_command = plci->adjust_b_command;
9585 if (plci_nl_busy(plci))
9586 {
9587 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9588 break;
9589 }
9590 dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9591 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9592 break;
9593 case ADJUST_B_RESTORE_DTMF_2:
9594 if ((Rc != OK) && (Rc != OK_FC))
9595 {
9596 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9597 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9598 Info = _WRONG_STATE;
9599 break;
9600 }
9601 break;
9602 }
9603 }
9604 return (Info);
9605}
9606
9607
9608static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9609{
9610 word internal_command, Info;
9611 byte mask;
9612 byte result[4];
9613
9614 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9615 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9616 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9617 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9618
9619 Info = GOOD;
9620 result[0] = 2;
9621 PUT_WORD(&result[1], DTMF_SUCCESS);
9622 internal_command = plci->internal_command;
9623 plci->internal_command = 0;
9624 mask = 0x01;
9625 switch (plci->dtmf_cmd)
9626 {
9627
9628 case DTMF_LISTEN_TONE_START:
9629 mask <<= 1;
9630 case DTMF_LISTEN_MF_START:
9631 mask <<= 1;
9632
9633 case DTMF_LISTEN_START:
9634 switch (internal_command)
9635 {
9636 default:
9637 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9638 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9639 case DTMF_COMMAND_1:
9640 if (adjust_b_process(Id, plci, Rc) != GOOD)
9641 {
9642 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9643 UnMapId(Id), (char *)(FILE_), __LINE__));
9644 Info = _FACILITY_NOT_SUPPORTED;
9645 break;
9646 }
9647 if (plci->internal_command)
9648 return;
9649 case DTMF_COMMAND_2:
9650 if (plci_nl_busy(plci))
9651 {
9652 plci->internal_command = DTMF_COMMAND_2;
9653 return;
9654 }
9655 plci->internal_command = DTMF_COMMAND_3;
9656 dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9657 return;
9658 case DTMF_COMMAND_3:
9659 if ((Rc != OK) && (Rc != OK_FC))
9660 {
9661 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9662 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9663 Info = _FACILITY_NOT_SUPPORTED;
9664 break;
9665 }
9666
9667 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9668
9669 plci->dtmf_rec_active |= mask;
9670 break;
9671 }
9672 break;
9673
9674
9675 case DTMF_LISTEN_TONE_STOP:
9676 mask <<= 1;
9677 case DTMF_LISTEN_MF_STOP:
9678 mask <<= 1;
9679
9680 case DTMF_LISTEN_STOP:
9681 switch (internal_command)
9682 {
9683 default:
9684 plci->dtmf_rec_active &= ~mask;
9685 if (plci->dtmf_rec_active)
9686 break;
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9712 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9713 case DTMF_COMMAND_3:
9714 if (adjust_b_process(Id, plci, Rc) != GOOD)
9715 {
9716 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9717 UnMapId(Id), (char *)(FILE_), __LINE__));
9718 Info = _FACILITY_NOT_SUPPORTED;
9719 break;
9720 }
9721 if (plci->internal_command)
9722 return;
9723 break;
9724 }
9725 break;
9726
9727
9728 case DTMF_SEND_TONE:
9729 mask <<= 1;
9730 case DTMF_SEND_MF:
9731 mask <<= 1;
9732
9733 case DTMF_DIGITS_SEND:
9734 switch (internal_command)
9735 {
9736 default:
9737 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9738 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9739 DTMF_COMMAND_1);
9740 case DTMF_COMMAND_1:
9741 if (adjust_b_process(Id, plci, Rc) != GOOD)
9742 {
9743 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9744 UnMapId(Id), (char *)(FILE_), __LINE__));
9745 Info = _FACILITY_NOT_SUPPORTED;
9746 break;
9747 }
9748 if (plci->internal_command)
9749 return;
9750 case DTMF_COMMAND_2:
9751 if (plci_nl_busy(plci))
9752 {
9753 plci->internal_command = DTMF_COMMAND_2;
9754 return;
9755 }
9756 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9757 plci->internal_command = DTMF_COMMAND_3;
9758 dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9759 return;
9760 case DTMF_COMMAND_3:
9761 if ((Rc != OK) && (Rc != OK_FC))
9762 {
9763 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9764 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9765 if (plci->dtmf_send_requests != 0)
9766 (plci->dtmf_send_requests)--;
9767 Info = _FACILITY_NOT_SUPPORTED;
9768 break;
9769 }
9770 return;
9771 }
9772 break;
9773 }
9774 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9775 "wws", Info, SELECTOR_DTMF, result);
9776}
9777
9778
9779static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9780{
9781 word Info;
9782 word i, j;
9783 byte mask;
9784 API_PARSE dtmf_parms[5];
9785 byte result[40];
9786
9787 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9788 UnMapId(Id), (char *)(FILE_), __LINE__));
9789
9790 Info = GOOD;
9791 result[0] = 2;
9792 PUT_WORD(&result[1], DTMF_SUCCESS);
9793 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9794 {
9795 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9796 UnMapId(Id), (char *)(FILE_), __LINE__));
9797 Info = _FACILITY_NOT_SUPPORTED;
9798 }
9799 else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9800 {
9801 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9802 UnMapId(Id), (char *)(FILE_), __LINE__));
9803 Info = _WRONG_MESSAGE_FORMAT;
9804 }
9805
9806 else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9807 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9808 {
9809 if (!((a->requested_options_table[appl->Id - 1])
9810 & (1L << PRIVATE_DTMF_TONE)))
9811 {
9812 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9813 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9814 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9815 }
9816 else
9817 {
9818 for (i = 0; i < 32; i++)
9819 result[4 + i] = 0;
9820 if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9821 {
9822 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9823 {
9824 if (dtmf_digit_map[i].listen_mask != 0)
9825 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9826 }
9827 }
9828 else
9829 {
9830 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9831 {
9832 if (dtmf_digit_map[i].send_mask != 0)
9833 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9834 }
9835 }
9836 result[0] = 3 + 32;
9837 result[3] = 32;
9838 }
9839 }
9840
9841 else if (plci == NULL)
9842 {
9843 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9844 UnMapId(Id), (char *)(FILE_), __LINE__));
9845 Info = _WRONG_IDENTIFIER;
9846 }
9847 else
9848 {
9849 if (!plci->State
9850 || !plci->NL.Id || plci->nl_remove_id)
9851 {
9852 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9853 UnMapId(Id), (char *)(FILE_), __LINE__));
9854 Info = _WRONG_STATE;
9855 }
9856 else
9857 {
9858 plci->command = 0;
9859 plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9860 mask = 0x01;
9861 switch (plci->dtmf_cmd)
9862 {
9863
9864 case DTMF_LISTEN_TONE_START:
9865 case DTMF_LISTEN_TONE_STOP:
9866 mask <<= 1;
9867 case DTMF_LISTEN_MF_START:
9868 case DTMF_LISTEN_MF_STOP:
9869 mask <<= 1;
9870 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9871 & (1L << PRIVATE_DTMF_TONE)))
9872 {
9873 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9874 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9875 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9876 break;
9877 }
9878
9879 case DTMF_LISTEN_START:
9880 case DTMF_LISTEN_STOP:
9881 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9882 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9883 {
9884 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9885 UnMapId(Id), (char *)(FILE_), __LINE__));
9886 Info = _FACILITY_NOT_SUPPORTED;
9887 break;
9888 }
9889 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9890 {
9891 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9892 {
9893 plci->dtmf_rec_pulse_ms = 0;
9894 plci->dtmf_rec_pause_ms = 0;
9895 }
9896 else
9897 {
9898 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9899 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9900 }
9901 }
9902 start_internal_command(Id, plci, dtmf_command);
9903 return (false);
9904
9905
9906 case DTMF_SEND_TONE:
9907 mask <<= 1;
9908 case DTMF_SEND_MF:
9909 mask <<= 1;
9910 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9911 & (1L << PRIVATE_DTMF_TONE)))
9912 {
9913 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9914 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9915 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9916 break;
9917 }
9918
9919 case DTMF_DIGITS_SEND:
9920 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9921 {
9922 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9923 UnMapId(Id), (char *)(FILE_), __LINE__));
9924 Info = _WRONG_MESSAGE_FORMAT;
9925 break;
9926 }
9927 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9928 {
9929 plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9930 plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9931 }
9932 i = 0;
9933 j = 0;
9934 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9935 {
9936 j = 0;
9937 while ((j < DTMF_DIGIT_MAP_ENTRIES)
9938 && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9939 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9940 {
9941 j++;
9942 }
9943 i++;
9944 }
9945 if (j == DTMF_DIGIT_MAP_ENTRIES)
9946 {
9947 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9948 UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9949 PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9950 break;
9951 }
9952 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9953 {
9954 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9955 UnMapId(Id), (char *)(FILE_), __LINE__));
9956 Info = _WRONG_STATE;
9957 break;
9958 }
9959 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9960 start_internal_command(Id, plci, dtmf_command);
9961 return (false);
9962
9963 default:
9964 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9965 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9966 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9967 }
9968 }
9969 }
9970 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9971 "wws", Info, SELECTOR_DTMF, result);
9972 return (false);
9973}
9974
9975
9976static void dtmf_confirmation(dword Id, PLCI *plci)
9977{
9978 word i;
9979 byte result[4];
9980
9981 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9982 UnMapId(Id), (char *)(FILE_), __LINE__));
9983
9984 result[0] = 2;
9985 PUT_WORD(&result[1], DTMF_SUCCESS);
9986 if (plci->dtmf_send_requests != 0)
9987 {
9988 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9989 "wws", GOOD, SELECTOR_DTMF, result);
9990 (plci->dtmf_send_requests)--;
9991 for (i = 0; i < plci->dtmf_send_requests; i++)
9992 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
9993 }
9994}
9995
9996
9997static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
9998{
9999 word i, j, n;
10000
10001 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10002 UnMapId(Id), (char *)(FILE_), __LINE__));
10003
10004 n = 0;
10005 for (i = 1; i < length; i++)
10006 {
10007 j = 0;
10008 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10009 && ((msg[i] != dtmf_digit_map[j].code)
10010 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10011 {
10012 j++;
10013 }
10014 if (j < DTMF_DIGIT_MAP_ENTRIES)
10015 {
10016
10017 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10018 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10019 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10020 {
10021 if (n + 1 == i)
10022 {
10023 for (i = length; i > n + 1; i--)
10024 msg[i] = msg[i - 1];
10025 length++;
10026 i++;
10027 }
10028 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10029 }
10030 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10031
10032 msg[++n] = dtmf_digit_map[j].character;
10033 }
10034 }
10035 if (n != 0)
10036 {
10037 msg[0] = (byte) n;
10038 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10039 }
10040}
10041
10042
10043
10044
10045
10046
10047static void dtmf_parameter_write(PLCI *plci)
10048{
10049 word i;
10050 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10051
10052 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10053 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10054 (char *)(FILE_), __LINE__));
10055
10056 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10057 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10058 for (i = 0; i < plci->dtmf_parameter_length; i++)
10059 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10060 add_p(plci, FTY, parameter_buffer);
10061 sig_req(plci, TEL_CTRL, 0);
10062 send_req(plci);
10063}
10064
10065
10066static void dtmf_parameter_clear_config(PLCI *plci)
10067{
10068
10069 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10070 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10071 (char *)(FILE_), __LINE__));
10072
10073 plci->dtmf_parameter_length = 0;
10074}
10075
10076
10077static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10078{
10079
10080 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10081 UnMapId(Id), (char *)(FILE_), __LINE__));
10082
10083}
10084
10085
10086static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10087{
10088
10089 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10090 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10091
10092 return (GOOD);
10093}
10094
10095
10096static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10097{
10098 word Info;
10099
10100 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10101 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10102
10103 Info = GOOD;
10104 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10105 && (plci->dtmf_parameter_length != 0))
10106 {
10107 switch (plci->adjust_b_state)
10108 {
10109 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10110 plci->internal_command = plci->adjust_b_command;
10111 if (plci->sig_req)
10112 {
10113 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10114 break;
10115 }
10116 dtmf_parameter_write(plci);
10117 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10118 break;
10119 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10120 if ((Rc != OK) && (Rc != OK_FC))
10121 {
10122 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10123 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10124 Info = _WRONG_STATE;
10125 break;
10126 }
10127 break;
10128 }
10129 }
10130 return (Info);
10131}
10132
10133
10134
10135
10136
10137
10138
10139LI_CONFIG *li_config_table;
10140word li_total_channels;
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153static byte chi_to_channel(byte *chi, dword *pchannelmap)
10154{
10155 int p;
10156 int i;
10157 dword map;
10158 byte excl;
10159 byte ofs;
10160 byte ch;
10161
10162 if (pchannelmap) *pchannelmap = 0;
10163 if (!chi[0]) return 0xff;
10164 excl = 0;
10165
10166 if (chi[1] & 0x20) {
10167 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd;
10168 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10169 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10170 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10171 if (chi[1] & 0x08) excl = 0x40;
10172
10173
10174 if (chi[1] & 0x40) {
10175 p = i + 1;
10176 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10177 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10178 }
10179
10180
10181 p = i + 1;
10182 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10183 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10184 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10185
10186
10187 if (chi[p] & 0x10) {
10188
10189
10190 if ((chi[0] - p) == 4) ofs = 0;
10191 else if ((chi[0] - p) == 3) ofs = 1;
10192 else return 0xfe;
10193 ch = 0;
10194 map = 0;
10195 for (i = 0; i < 4 && p < chi[0]; i++) {
10196 p++;
10197 ch += 8;
10198 map <<= 8;
10199 if (chi[p]) {
10200 for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10201 map |= chi[p];
10202 }
10203 }
10204 ch += ofs;
10205 map <<= ofs;
10206 }
10207 else {
10208
10209
10210 p = i + 1;
10211 ch = chi[p] & 0x3f;
10212 if (pchannelmap) {
10213 if ((byte)(chi[0] - p) > 30) return 0xfe;
10214 map = 0;
10215 for (i = p; i <= chi[0]; i++) {
10216 if ((chi[i] & 0x7f) > 31) return 0xfe;
10217 map |= (1L << (chi[i] & 0x7f));
10218 }
10219 }
10220 else {
10221 if (p != chi[0]) return 0xfe;
10222 if (ch > 31) return 0xfe;
10223 map = (1L << ch);
10224 }
10225 if (chi[p] & 0x40) return 0xfe;
10226 }
10227 if (pchannelmap) *pchannelmap = map;
10228 else if (map != ((dword)(1L << ch))) return 0xfe;
10229 return (byte)(excl | ch);
10230 }
10231 else {
10232 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10233 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10234 if (chi[1] & 0x08) excl = 0x40;
10235
10236 switch (chi[1] | 0x98) {
10237 case 0x98: return 0;
10238 case 0x99:
10239 if (pchannelmap) *pchannelmap = 2;
10240 return excl | 1;
10241 case 0x9a:
10242 if (pchannelmap) *pchannelmap = 4;
10243 return excl | 2;
10244 case 0x9b: return 0xff;
10245 case 0x9c: return 0xfd;
10246 default: return 0xfe;
10247 }
10248 }
10249}
10250
10251
10252static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10253{
10254 DIVA_CAPI_ADAPTER *a;
10255 PLCI *splci;
10256 byte old_id;
10257
10258 a = plci->adapter;
10259 old_id = plci->li_bchannel_id;
10260 if (a->li_pri)
10261 {
10262 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10263 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10264 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10265 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10266 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10267 }
10268 else
10269 {
10270 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10271 {
10272 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10273 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10274 plci->li_bchannel_id = bchannel_id & 0x03;
10275 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10276 {
10277 splci = a->AdvSignalPLCI;
10278 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10279 {
10280 if ((splci->li_bchannel_id != 0)
10281 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10282 {
10283 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10284 }
10285 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10286 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10287 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10288 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10289 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10290 }
10291 }
10292 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10293 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10294 }
10295 }
10296 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10297 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10298 {
10299 mixer_clear_config(plci);
10300 }
10301 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10302 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10303 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10304}
10305
10306
10307static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10308{
10309 DIVA_CAPI_ADAPTER *a;
10310 PLCI *splci;
10311 byte ch, old_id;
10312
10313 a = plci->adapter;
10314 old_id = plci->li_bchannel_id;
10315 ch = chi_to_channel(chi, NULL);
10316 if (!(ch & 0x80))
10317 {
10318 if (a->li_pri)
10319 {
10320 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10321 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10322 plci->li_bchannel_id = (ch & 0x1f) + 1;
10323 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10324 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10325 }
10326 else
10327 {
10328 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10329 {
10330 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10331 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10332 plci->li_bchannel_id = ch & 0x1f;
10333 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10334 {
10335 splci = a->AdvSignalPLCI;
10336 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10337 {
10338 if ((splci->li_bchannel_id != 0)
10339 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10340 {
10341 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10342 }
10343 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10344 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10345 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10346 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10347 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10348 }
10349 }
10350 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10351 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10352 }
10353 }
10354 }
10355 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10356 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10357 {
10358 mixer_clear_config(plci);
10359 }
10360 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10361 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10362 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10363}
10364
10365
10366#define MIXER_MAX_DUMP_CHANNELS 34
10367
10368static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10369{
10370 word n, i, j;
10371 char *p;
10372 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10373
10374 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10375 (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10376
10377 for (i = 0; i < li_total_channels; i++)
10378 {
10379 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10380 if (li_config_table[i].chflags != 0)
10381 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10382 else
10383 {
10384 for (j = 0; j < li_total_channels; j++)
10385 {
10386 if (((li_config_table[i].flag_table[j]) != 0)
10387 || ((li_config_table[j].flag_table[i]) != 0))
10388 {
10389 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10390 }
10391 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10392 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10393 {
10394 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10395 }
10396 }
10397 }
10398 }
10399 for (i = 0; i < li_total_channels; i++)
10400 {
10401 for (j = 0; j < li_total_channels; j++)
10402 {
10403 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10404 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10405 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10406 }
10407 }
10408 for (n = 0; n < li_total_channels; n++)
10409 {
10410 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10411 {
10412 for (i = 0; i < li_total_channels; i++)
10413 {
10414 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10415 {
10416 for (j = 0; j < li_total_channels; j++)
10417 {
10418 li_config_table[i].coef_table[j] |=
10419 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10420 }
10421 }
10422 }
10423 }
10424 }
10425 for (i = 0; i < li_total_channels; i++)
10426 {
10427 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10428 {
10429 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10430 for (j = 0; j < li_total_channels; j++)
10431 {
10432 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10433 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10434 }
10435 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10436 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10437 }
10438 }
10439 for (i = 0; i < li_total_channels; i++)
10440 {
10441 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10442 {
10443 for (j = 0; j < li_total_channels; j++)
10444 {
10445 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10446 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10447 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10448 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10449 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10450 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10451 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10452 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10453 }
10454 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10455 {
10456 for (j = 0; j < li_total_channels; j++)
10457 {
10458 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10459 {
10460 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10461 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10462 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10463 }
10464 }
10465 }
10466 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10467 {
10468 for (j = 0; j < li_total_channels; j++)
10469 {
10470 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10471 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10472 }
10473 }
10474 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10475 {
10476 for (j = 0; j < li_total_channels; j++)
10477 {
10478 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10479 {
10480 for (n = 0; n < li_total_channels; n++)
10481 {
10482 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10483 {
10484 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10485 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10486 {
10487 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10488 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10489 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10490 }
10491 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10492 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10493 }
10494 }
10495 }
10496 }
10497 }
10498 }
10499 }
10500 for (i = 0; i < li_total_channels; i++)
10501 {
10502 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10503 {
10504 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10505 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10506 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10507 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10508 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10509 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10510 for (j = 0; j < li_total_channels; j++)
10511 {
10512 if ((li_config_table[i].flag_table[j] &
10513 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10514 || (li_config_table[j].flag_table[i] &
10515 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10516 {
10517 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10518 }
10519 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10520 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10521 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10522 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10523 }
10524 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10525 {
10526 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10527 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10528 }
10529 }
10530 }
10531 for (i = 0; i < li_total_channels; i++)
10532 {
10533 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10534 {
10535 j = 0;
10536 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10537 j++;
10538 if (j < li_total_channels)
10539 {
10540 for (j = 0; j < li_total_channels; j++)
10541 {
10542 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10543 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10544 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10545 }
10546 }
10547 }
10548 }
10549 n = li_total_channels;
10550 if (n > MIXER_MAX_DUMP_CHANNELS)
10551 n = MIXER_MAX_DUMP_CHANNELS;
10552
10553 p = hex_line;
10554 for (j = 0; j < n; j++)
10555 {
10556 if ((j & 0x7) == 0)
10557 *(p++) = ' ';
10558 p = hex_byte_pack(p, li_config_table[j].curchnl);
10559 }
10560 *p = '\0';
10561 dbug(1, dprintf("[%06lx] CURRENT %s",
10562 (dword)(UnMapController(a->Id)), (char *)hex_line));
10563 p = hex_line;
10564 for (j = 0; j < n; j++)
10565 {
10566 if ((j & 0x7) == 0)
10567 *(p++) = ' ';
10568 p = hex_byte_pack(p, li_config_table[j].channel);
10569 }
10570 *p = '\0';
10571 dbug(1, dprintf("[%06lx] CHANNEL %s",
10572 (dword)(UnMapController(a->Id)), (char *)hex_line));
10573 p = hex_line;
10574 for (j = 0; j < n; j++)
10575 {
10576 if ((j & 0x7) == 0)
10577 *(p++) = ' ';
10578 p = hex_byte_pack(p, li_config_table[j].chflags);
10579 }
10580 *p = '\0';
10581 dbug(1, dprintf("[%06lx] CHFLAG %s",
10582 (dword)(UnMapController(a->Id)), (char *)hex_line));
10583 for (i = 0; i < n; i++)
10584 {
10585 p = hex_line;
10586 for (j = 0; j < n; j++)
10587 {
10588 if ((j & 0x7) == 0)
10589 *(p++) = ' ';
10590 p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10591 }
10592 *p = '\0';
10593 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10594 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10595 }
10596 for (i = 0; i < n; i++)
10597 {
10598 p = hex_line;
10599 for (j = 0; j < n; j++)
10600 {
10601 if ((j & 0x7) == 0)
10602 *(p++) = ' ';
10603 p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10604 }
10605 *p = '\0';
10606 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10607 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10608 }
10609}
10610
10611
10612static struct
10613{
10614 byte mask;
10615 byte line_flags;
10616} mixer_write_prog_pri[] =
10617{
10618 { LI_COEF_CH_CH, 0 },
10619 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10620 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10621 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10622};
10623
10624static struct
10625{
10626 byte from_ch;
10627 byte to_ch;
10628 byte mask;
10629 byte xconnect_override;
10630} mixer_write_prog_bri[] =
10631{
10632 { 0, 0, LI_COEF_CH_CH, 0x01 },
10633 { 1, 0, LI_COEF_CH_CH, 0x01 },
10634 { 0, 0, LI_COEF_PC_CH, 0x80 },
10635 { 1, 0, LI_COEF_PC_CH, 0x01 },
10636 { 2, 0, LI_COEF_CH_CH, 0x00 },
10637 { 3, 0, LI_COEF_CH_CH, 0x00 },
10638 { 0, 0, LI_COEF_CH_PC, 0x80 },
10639 { 1, 0, LI_COEF_CH_PC, 0x01 },
10640 { 0, 0, LI_COEF_PC_PC, 0x01 },
10641 { 1, 0, LI_COEF_PC_PC, 0x01 },
10642 { 2, 0, LI_COEF_CH_PC, 0x00 },
10643 { 3, 0, LI_COEF_CH_PC, 0x00 },
10644 { 0, 2, LI_COEF_CH_CH, 0x00 },
10645 { 1, 2, LI_COEF_CH_CH, 0x00 },
10646 { 0, 2, LI_COEF_PC_CH, 0x00 },
10647 { 1, 2, LI_COEF_PC_CH, 0x00 },
10648 { 2, 2, LI_COEF_CH_CH, 0x00 },
10649 { 3, 2, LI_COEF_CH_CH, 0x00 },
10650 { 1, 1, LI_COEF_CH_CH, 0x01 },
10651 { 0, 1, LI_COEF_CH_CH, 0x01 },
10652 { 1, 1, LI_COEF_PC_CH, 0x80 },
10653 { 0, 1, LI_COEF_PC_CH, 0x01 },
10654 { 3, 1, LI_COEF_CH_CH, 0x00 },
10655 { 2, 1, LI_COEF_CH_CH, 0x00 },
10656 { 1, 1, LI_COEF_CH_PC, 0x80 },
10657 { 0, 1, LI_COEF_CH_PC, 0x01 },
10658 { 1, 1, LI_COEF_PC_PC, 0x01 },
10659 { 0, 1, LI_COEF_PC_PC, 0x01 },
10660 { 3, 1, LI_COEF_CH_PC, 0x00 },
10661 { 2, 1, LI_COEF_CH_PC, 0x00 },
10662 { 1, 3, LI_COEF_CH_CH, 0x00 },
10663 { 0, 3, LI_COEF_CH_CH, 0x00 },
10664 { 1, 3, LI_COEF_PC_CH, 0x00 },
10665 { 0, 3, LI_COEF_PC_CH, 0x00 },
10666 { 3, 3, LI_COEF_CH_CH, 0x00 },
10667 { 2, 3, LI_COEF_CH_CH, 0x00 }
10668};
10669
10670static byte mixer_swapped_index_bri[] =
10671{
10672 18,
10673 19,
10674 20,
10675 21,
10676 22,
10677 23,
10678 24,
10679 25,
10680 26,
10681 27,
10682 28,
10683 29,
10684 30,
10685 31,
10686 32,
10687 33,
10688 34,
10689 35,
10690 0,
10691 1,
10692 2,
10693 3,
10694 4,
10695 5,
10696 6,
10697 7,
10698 8,
10699 9,
10700 10,
10701 11,
10702 12,
10703 13,
10704 14,
10705 15,
10706 16,
10707 17
10708};
10709
10710static struct
10711{
10712 byte mask;
10713 byte from_pc;
10714 byte to_pc;
10715} xconnect_write_prog[] =
10716{
10717 { LI_COEF_CH_CH, false, false },
10718 { LI_COEF_CH_PC, false, true },
10719 { LI_COEF_PC_CH, true, false },
10720 { LI_COEF_PC_PC, true, true }
10721};
10722
10723
10724static void xconnect_query_addresses(PLCI *plci)
10725{
10726 DIVA_CAPI_ADAPTER *a;
10727 word w, ch;
10728 byte *p;
10729
10730 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10731 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10732 (char *)(FILE_), __LINE__));
10733
10734 a = plci->adapter;
10735 if (a->li_pri && ((plci->li_bchannel_id == 0)
10736 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10737 {
10738 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10739 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10740 (char *)(FILE_), __LINE__));
10741 return;
10742 }
10743 p = plci->internal_req_buffer;
10744 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10745 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10746 w = ch;
10747 *(p++) = (byte) w;
10748 *(p++) = (byte)(w >> 8);
10749 w = ch | XCONNECT_CHANNEL_PORT_PC;
10750 *(p++) = (byte) w;
10751 *(p++) = (byte)(w >> 8);
10752 plci->NData[0].P = plci->internal_req_buffer;
10753 plci->NData[0].PLength = p - plci->internal_req_buffer;
10754 plci->NL.X = plci->NData;
10755 plci->NL.ReqCh = 0;
10756 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10757 plci->adapter->request(&plci->NL);
10758}
10759
10760
10761static void xconnect_write_coefs(PLCI *plci, word internal_command)
10762{
10763
10764 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10765 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10766 (char *)(FILE_), __LINE__, internal_command));
10767
10768 plci->li_write_command = internal_command;
10769 plci->li_write_channel = 0;
10770}
10771
10772
10773static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10774{
10775 DIVA_CAPI_ADAPTER *a;
10776 word w, n, i, j, r, s, to_ch;
10777 dword d;
10778 byte *p;
10779 struct xconnect_transfer_address_s *transfer_address;
10780 byte ch_map[MIXER_CHANNELS_BRI];
10781
10782 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10783 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10784
10785 a = plci->adapter;
10786 if ((plci->li_bchannel_id == 0)
10787 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10788 {
10789 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10790 UnMapId(Id), (char *)(FILE_), __LINE__));
10791 return (true);
10792 }
10793 i = a->li_base + (plci->li_bchannel_id - 1);
10794 j = plci->li_write_channel;
10795 p = plci->internal_req_buffer;
10796 if (j != 0)
10797 {
10798 if ((Rc != OK) && (Rc != OK_FC))
10799 {
10800 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10801 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10802 return (false);
10803 }
10804 }
10805 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10806 {
10807 r = 0;
10808 s = 0;
10809 if (j < li_total_channels)
10810 {
10811 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10812 {
10813 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10814 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10815 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10816 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10817 }
10818 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10819 while ((j < li_total_channels)
10820 && ((r == 0)
10821 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10822 || (!li_config_table[j].adapter->li_pri
10823 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10824 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10825 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10826 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10827 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10828 || ((li_config_table[j].adapter->li_base != a->li_base)
10829 && !(r & s &
10830 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10831 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10832 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10833 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10834 {
10835 j++;
10836 if (j < li_total_channels)
10837 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10838 }
10839 }
10840 if (j < li_total_channels)
10841 {
10842 plci->internal_command = plci->li_write_command;
10843 if (plci_nl_busy(plci))
10844 return (true);
10845 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10846 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10847 do
10848 {
10849 if (li_config_table[j].adapter->li_base != a->li_base)
10850 {
10851 r &= s &
10852 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10853 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10854 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10855 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10856 }
10857 n = 0;
10858 do
10859 {
10860 if (r & xconnect_write_prog[n].mask)
10861 {
10862 if (xconnect_write_prog[n].from_pc)
10863 transfer_address = &(li_config_table[j].send_pc);
10864 else
10865 transfer_address = &(li_config_table[j].send_b);
10866 d = transfer_address->card_address.low;
10867 *(p++) = (byte) d;
10868 *(p++) = (byte)(d >> 8);
10869 *(p++) = (byte)(d >> 16);
10870 *(p++) = (byte)(d >> 24);
10871 d = transfer_address->card_address.high;
10872 *(p++) = (byte) d;
10873 *(p++) = (byte)(d >> 8);
10874 *(p++) = (byte)(d >> 16);
10875 *(p++) = (byte)(d >> 24);
10876 d = transfer_address->offset;
10877 *(p++) = (byte) d;
10878 *(p++) = (byte)(d >> 8);
10879 *(p++) = (byte)(d >> 16);
10880 *(p++) = (byte)(d >> 24);
10881 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10882 *(p++) = (byte) w;
10883 *(p++) = (byte)(w >> 8);
10884 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10885 (li_config_table[i].adapter->u_law ?
10886 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10887 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10888 *(p++) = (byte) w;
10889 *(p++) = (byte) 0;
10890 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10891 }
10892 n++;
10893 } while ((n < ARRAY_SIZE(xconnect_write_prog))
10894 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10895 if (n == ARRAY_SIZE(xconnect_write_prog))
10896 {
10897 do
10898 {
10899 j++;
10900 if (j < li_total_channels)
10901 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10902 } while ((j < li_total_channels)
10903 && ((r == 0)
10904 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10905 || (!li_config_table[j].adapter->li_pri
10906 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10907 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10908 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10909 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10910 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10911 || ((li_config_table[j].adapter->li_base != a->li_base)
10912 && !(r & s &
10913 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10914 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10915 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10916 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10917 }
10918 } while ((j < li_total_channels)
10919 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10920 }
10921 else if (j == li_total_channels)
10922 {
10923 plci->internal_command = plci->li_write_command;
10924 if (plci_nl_busy(plci))
10925 return (true);
10926 if (a->li_pri)
10927 {
10928 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10929 w = 0;
10930 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10931 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10932 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10933 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10934 *(p++) = (byte) w;
10935 *(p++) = (byte)(w >> 8);
10936 }
10937 else
10938 {
10939 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10940 w = 0;
10941 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10942 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10943 {
10944 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10945 }
10946 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10947 w |= MIXER_FEATURE_ENABLE_TX_DATA;
10948 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10949 w |= MIXER_FEATURE_ENABLE_RX_DATA;
10950 *(p++) = (byte) w;
10951 *(p++) = (byte)(w >> 8);
10952 for (j = 0; j < sizeof(ch_map); j += 2)
10953 {
10954 if (plci->li_bchannel_id == 2)
10955 {
10956 ch_map[j] = (byte)(j + 1);
10957 ch_map[j + 1] = (byte) j;
10958 }
10959 else
10960 {
10961 ch_map[j] = (byte) j;
10962 ch_map[j + 1] = (byte)(j + 1);
10963 }
10964 }
10965 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10966 {
10967 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10968 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10969 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10970 {
10971 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10972 mixer_write_prog_bri[n].xconnect_override :
10973 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10974 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10975 {
10976 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10977 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10978 }
10979 }
10980 else
10981 {
10982 *p = 0x00;
10983 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10984 {
10985 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10986 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10987 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10988 }
10989 }
10990 p++;
10991 }
10992 }
10993 j = li_total_channels + 1;
10994 }
10995 }
10996 else
10997 {
10998 if (j <= li_total_channels)
10999 {
11000 plci->internal_command = plci->li_write_command;
11001 if (plci_nl_busy(plci))
11002 return (true);
11003 if (j < a->li_base)
11004 j = a->li_base;
11005 if (a->li_pri)
11006 {
11007 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11008 w = 0;
11009 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11010 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11011 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11012 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11013 *(p++) = (byte) w;
11014 *(p++) = (byte)(w >> 8);
11015 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11016 {
11017 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11018 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11019 {
11020 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11021 if (w & mixer_write_prog_pri[n].mask)
11022 {
11023 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11024 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11025 }
11026 else
11027 *(p++) = 0x00;
11028 }
11029 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11030 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11031 {
11032 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11033 if (w & mixer_write_prog_pri[n].mask)
11034 {
11035 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11036 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11037 }
11038 else
11039 *(p++) = 0x00;
11040 }
11041 }
11042 }
11043 else
11044 {
11045 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11046 w = 0;
11047 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11048 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11049 {
11050 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11051 }
11052 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11053 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11054 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11055 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11056 *(p++) = (byte) w;
11057 *(p++) = (byte)(w >> 8);
11058 for (j = 0; j < sizeof(ch_map); j += 2)
11059 {
11060 if (plci->li_bchannel_id == 2)
11061 {
11062 ch_map[j] = (byte)(j + 1);
11063 ch_map[j + 1] = (byte) j;
11064 }
11065 else
11066 {
11067 ch_map[j] = (byte) j;
11068 ch_map[j + 1] = (byte)(j + 1);
11069 }
11070 }
11071 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11072 {
11073 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11074 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11075 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11076 {
11077 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11078 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11079 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11080 }
11081 else
11082 {
11083 *p = 0x00;
11084 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11085 {
11086 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11087 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11088 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11089 }
11090 }
11091 p++;
11092 }
11093 }
11094 j = li_total_channels + 1;
11095 }
11096 }
11097 plci->li_write_channel = j;
11098 if (p != plci->internal_req_buffer)
11099 {
11100 plci->NData[0].P = plci->internal_req_buffer;
11101 plci->NData[0].PLength = p - plci->internal_req_buffer;
11102 plci->NL.X = plci->NData;
11103 plci->NL.ReqCh = 0;
11104 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11105 plci->adapter->request(&plci->NL);
11106 }
11107 return (true);
11108}
11109
11110
11111static void mixer_notify_update(PLCI *plci, byte others)
11112{
11113 DIVA_CAPI_ADAPTER *a;
11114 word i, w;
11115 PLCI *notify_plci;
11116 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11117
11118 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11119 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11120 (char *)(FILE_), __LINE__, others));
11121
11122 a = plci->adapter;
11123 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11124 {
11125 if (others)
11126 plci->li_notify_update = true;
11127 i = 0;
11128 do
11129 {
11130 notify_plci = NULL;
11131 if (others)
11132 {
11133 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11134 i++;
11135 if (i < li_total_channels)
11136 notify_plci = li_config_table[i++].plci;
11137 }
11138 else
11139 {
11140 if ((plci->li_bchannel_id != 0)
11141 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11142 {
11143 notify_plci = plci;
11144 }
11145 }
11146 if ((notify_plci != NULL)
11147 && !notify_plci->li_notify_update
11148 && (notify_plci->appl != NULL)
11149 && (notify_plci->State)
11150 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11151 {
11152 notify_plci->li_notify_update = true;
11153 ((CAPI_MSG *) msg)->header.length = 18;
11154 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11155 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11156 ((CAPI_MSG *) msg)->header.number = 0;
11157 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11158 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11159 ((CAPI_MSG *) msg)->header.ncci = 0;
11160 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11161 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11162 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11163 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11164 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11165 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11166 if (w != _QUEUE_FULL)
11167 {
11168 if (w != 0)
11169 {
11170 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11171 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11172 (char *)(FILE_), __LINE__,
11173 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11174 }
11175 notify_plci->li_notify_update = false;
11176 }
11177 }
11178 } while (others && (notify_plci != NULL));
11179 if (others)
11180 plci->li_notify_update = false;
11181 }
11182}
11183
11184
11185static void mixer_clear_config(PLCI *plci)
11186{
11187 DIVA_CAPI_ADAPTER *a;
11188 word i, j;
11189
11190 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11191 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11192 (char *)(FILE_), __LINE__));
11193
11194 plci->li_notify_update = false;
11195 plci->li_plci_b_write_pos = 0;
11196 plci->li_plci_b_read_pos = 0;
11197 plci->li_plci_b_req_pos = 0;
11198 a = plci->adapter;
11199 if ((plci->li_bchannel_id != 0)
11200 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11201 {
11202 i = a->li_base + (plci->li_bchannel_id - 1);
11203 li_config_table[i].curchnl = 0;
11204 li_config_table[i].channel = 0;
11205 li_config_table[i].chflags = 0;
11206 for (j = 0; j < li_total_channels; j++)
11207 {
11208 li_config_table[j].flag_table[i] = 0;
11209 li_config_table[i].flag_table[j] = 0;
11210 li_config_table[i].coef_table[j] = 0;
11211 li_config_table[j].coef_table[i] = 0;
11212 }
11213 if (!a->li_pri)
11214 {
11215 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11216 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11217 {
11218 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11219 li_config_table[i].curchnl = 0;
11220 li_config_table[i].channel = 0;
11221 li_config_table[i].chflags = 0;
11222 for (j = 0; j < li_total_channels; j++)
11223 {
11224 li_config_table[i].flag_table[j] = 0;
11225 li_config_table[j].flag_table[i] = 0;
11226 li_config_table[i].coef_table[j] = 0;
11227 li_config_table[j].coef_table[i] = 0;
11228 }
11229 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11230 {
11231 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11232 li_config_table[i].curchnl = 0;
11233 li_config_table[i].channel = 0;
11234 li_config_table[i].chflags = 0;
11235 for (j = 0; j < li_total_channels; j++)
11236 {
11237 li_config_table[i].flag_table[j] = 0;
11238 li_config_table[j].flag_table[i] = 0;
11239 li_config_table[i].coef_table[j] = 0;
11240 li_config_table[j].coef_table[i] = 0;
11241 }
11242 }
11243 }
11244 }
11245 }
11246}
11247
11248
11249static void mixer_prepare_switch(dword Id, PLCI *plci)
11250{
11251
11252 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11253 UnMapId(Id), (char *)(FILE_), __LINE__));
11254
11255 do
11256 {
11257 mixer_indication_coefs_set(Id, plci);
11258 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11259}
11260
11261
11262static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11263{
11264 DIVA_CAPI_ADAPTER *a;
11265 word i, j;
11266
11267 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11268 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11269
11270 a = plci->adapter;
11271 if ((plci->li_bchannel_id != 0)
11272 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11273 {
11274 i = a->li_base + (plci->li_bchannel_id - 1);
11275 for (j = 0; j < li_total_channels; j++)
11276 {
11277 li_config_table[i].coef_table[j] &= 0xf;
11278 li_config_table[j].coef_table[i] &= 0xf;
11279 }
11280 if (!a->li_pri)
11281 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11282 }
11283 return (GOOD);
11284}
11285
11286
11287static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11288{
11289 DIVA_CAPI_ADAPTER *a;
11290 word Info;
11291
11292 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11293 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11294
11295 Info = GOOD;
11296 a = plci->adapter;
11297 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11298 && (plci->li_bchannel_id != 0)
11299 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11300 {
11301 switch (plci->adjust_b_state)
11302 {
11303 case ADJUST_B_RESTORE_MIXER_1:
11304 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11305 {
11306 plci->internal_command = plci->adjust_b_command;
11307 if (plci_nl_busy(plci))
11308 {
11309 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11310 break;
11311 }
11312 xconnect_query_addresses(plci);
11313 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11314 break;
11315 }
11316 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11317 Rc = OK;
11318 case ADJUST_B_RESTORE_MIXER_2:
11319 case ADJUST_B_RESTORE_MIXER_3:
11320 case ADJUST_B_RESTORE_MIXER_4:
11321 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11322 {
11323 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11324 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11325 Info = _WRONG_STATE;
11326 break;
11327 }
11328 if (Rc == OK)
11329 {
11330 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11331 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11332 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11333 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11334 }
11335 else if (Rc == 0)
11336 {
11337 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11338 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11339 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11340 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11341 }
11342 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11343 {
11344 plci->internal_command = plci->adjust_b_command;
11345 break;
11346 }
11347 case ADJUST_B_RESTORE_MIXER_5:
11348 xconnect_write_coefs(plci, plci->adjust_b_command);
11349 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11350 Rc = OK;
11351 case ADJUST_B_RESTORE_MIXER_6:
11352 if (!xconnect_write_coefs_process(Id, plci, Rc))
11353 {
11354 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11355 UnMapId(Id), (char *)(FILE_), __LINE__));
11356 Info = _FACILITY_NOT_SUPPORTED;
11357 break;
11358 }
11359 if (plci->internal_command)
11360 break;
11361 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11362 case ADJUST_B_RESTORE_MIXER_7:
11363 break;
11364 }
11365 }
11366 return (Info);
11367}
11368
11369
11370static void mixer_command(dword Id, PLCI *plci, byte Rc)
11371{
11372 DIVA_CAPI_ADAPTER *a;
11373 word i, internal_command;
11374
11375 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11376 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11377 plci->li_cmd));
11378
11379 a = plci->adapter;
11380 internal_command = plci->internal_command;
11381 plci->internal_command = 0;
11382 switch (plci->li_cmd)
11383 {
11384 case LI_REQ_CONNECT:
11385 case LI_REQ_DISCONNECT:
11386 case LI_REQ_SILENT_UPDATE:
11387 switch (internal_command)
11388 {
11389 default:
11390 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11391 {
11392 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11393 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11394 }
11395 case MIXER_COMMAND_1:
11396 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11397 {
11398 if (adjust_b_process(Id, plci, Rc) != GOOD)
11399 {
11400 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11401 UnMapId(Id), (char *)(FILE_), __LINE__));
11402 break;
11403 }
11404 if (plci->internal_command)
11405 return;
11406 }
11407 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11408 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11409 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11410 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11411 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11412 {
11413 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11414 }
11415 else
11416 {
11417 do
11418 {
11419 mixer_indication_coefs_set(Id, plci);
11420 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11421 }
11422 case MIXER_COMMAND_2:
11423 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11424 || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11425 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11426 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11427 {
11428 if (!xconnect_write_coefs_process(Id, plci, Rc))
11429 {
11430 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11431 UnMapId(Id), (char *)(FILE_), __LINE__));
11432 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11433 {
11434 do
11435 {
11436 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11437 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11438 i = (plci->li_plci_b_write_pos == 0) ?
11439 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11440 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11441 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11442 }
11443 break;
11444 }
11445 if (plci->internal_command)
11446 return;
11447 }
11448 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11449 {
11450 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11451 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11452 }
11453 case MIXER_COMMAND_3:
11454 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11455 {
11456 if (adjust_b_process(Id, plci, Rc) != GOOD)
11457 {
11458 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11459 UnMapId(Id), (char *)(FILE_), __LINE__));
11460 break;
11461 }
11462 if (plci->internal_command)
11463 return;
11464 }
11465 break;
11466 }
11467 break;
11468 }
11469 if ((plci->li_bchannel_id == 0)
11470 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11471 {
11472 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11473 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11474 }
11475 else
11476 {
11477 i = a->li_base + (plci->li_bchannel_id - 1);
11478 li_config_table[i].curchnl = plci->li_channel_bits;
11479 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11480 {
11481 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11482 li_config_table[i].curchnl = plci->li_channel_bits;
11483 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11484 {
11485 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11486 li_config_table[i].curchnl = plci->li_channel_bits;
11487 }
11488 }
11489 }
11490}
11491
11492
11493static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11494 dword plci_b_id, byte connect, dword li_flags)
11495{
11496 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11497 PLCI *plci_b;
11498 DIVA_CAPI_ADAPTER *a_b;
11499
11500 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11501 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11502 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11503 if (!a->li_pri && (plci->tel == ADV_VOICE)
11504 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11505 {
11506 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11507 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11508 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11509 }
11510 else
11511 {
11512 ch_a_v = ch_a;
11513 ch_a_s = ch_a;
11514 }
11515 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11516 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11517 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11518 {
11519 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11520 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11521 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11522 }
11523 else
11524 {
11525 ch_b_v = ch_b;
11526 ch_b_s = ch_b;
11527 }
11528 if (connect)
11529 {
11530 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11531 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11532 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11533 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11534 }
11535 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11536 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11537 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11538 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11539 if (ch_a_v == ch_b_v)
11540 {
11541 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11542 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11543 }
11544 else
11545 {
11546 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11547 {
11548 for (i = 0; i < li_total_channels; i++)
11549 {
11550 if (i != ch_a_v)
11551 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11552 }
11553 }
11554 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11555 {
11556 for (i = 0; i < li_total_channels; i++)
11557 {
11558 if (i != ch_a_s)
11559 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11560 }
11561 }
11562 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11563 {
11564 for (i = 0; i < li_total_channels; i++)
11565 {
11566 if (i != ch_a_v)
11567 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11568 }
11569 }
11570 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11571 {
11572 for (i = 0; i < li_total_channels; i++)
11573 {
11574 if (i != ch_a_s)
11575 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11576 }
11577 }
11578 }
11579 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11580 {
11581 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11582 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11583 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11584 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11585 }
11586 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11587 {
11588 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11589 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11590 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11591 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11592 }
11593 if (li_flags & LI_FLAG_MONITOR_A)
11594 {
11595 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11596 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11597 }
11598 if (li_flags & LI_FLAG_MONITOR_B)
11599 {
11600 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11601 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11602 }
11603 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11604 {
11605 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11606 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11607 }
11608 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11609 {
11610 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11611 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11612 }
11613 if (li_flags & LI_FLAG_MIX_A)
11614 {
11615 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11616 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11617 }
11618 if (li_flags & LI_FLAG_MIX_B)
11619 {
11620 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11621 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11622 }
11623 if (ch_a_v != ch_a_s)
11624 {
11625 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11626 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11627 }
11628 if (ch_b_v != ch_b_s)
11629 {
11630 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11631 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11632 }
11633}
11634
11635
11636static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11637 dword plci_b_id, byte connect, dword li_flags)
11638{
11639 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11640 PLCI *plci_b;
11641 DIVA_CAPI_ADAPTER *a_b;
11642
11643 a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11644 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11645 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11646 if (!a->li_pri && (plci->tel == ADV_VOICE)
11647 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11648 {
11649 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11650 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11651 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11652 }
11653 else
11654 {
11655 ch_a_v = ch_a;
11656 ch_a_s = ch_a;
11657 }
11658 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11659 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11660 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11661 {
11662 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11663 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11664 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11665 }
11666 else
11667 {
11668 ch_b_v = ch_b;
11669 ch_b_s = ch_b;
11670 }
11671 if (connect)
11672 {
11673 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11676 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11677 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11678 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11679 }
11680 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11681 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11682 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11683 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11684 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11685 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11686 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11687 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11688 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11689 {
11690 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11691 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11692 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11693 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11694 }
11695 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11696 {
11697 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11698 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11699 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11700 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11701 }
11702 if (li_flags & LI2_FLAG_MONITOR_B)
11703 {
11704 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11705 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11706 }
11707 if (li_flags & LI2_FLAG_MIX_B)
11708 {
11709 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11710 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11711 }
11712 if (li_flags & LI2_FLAG_MONITOR_X)
11713 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11714 if (li_flags & LI2_FLAG_MIX_X)
11715 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11716 if (li_flags & LI2_FLAG_LOOP_B)
11717 {
11718 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11719 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11720 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11721 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11722 }
11723 if (li_flags & LI2_FLAG_LOOP_PC)
11724 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11725 if (li_flags & LI2_FLAG_LOOP_X)
11726 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11727 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11728 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11729 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11730 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11731 if (ch_a_v != ch_a_s)
11732 {
11733 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11734 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11735 }
11736 if (ch_b_v != ch_b_s)
11737 {
11738 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11739 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11740 }
11741}
11742
11743
11744static word li_check_main_plci(dword Id, PLCI *plci)
11745{
11746 if (plci == NULL)
11747 {
11748 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11749 UnMapId(Id), (char *)(FILE_), __LINE__));
11750 return (_WRONG_IDENTIFIER);
11751 }
11752 if (!plci->State
11753 || !plci->NL.Id || plci->nl_remove_id
11754 || (plci->li_bchannel_id == 0))
11755 {
11756 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11757 UnMapId(Id), (char *)(FILE_), __LINE__));
11758 return (_WRONG_STATE);
11759 }
11760 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11761 return (GOOD);
11762}
11763
11764
11765static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11766 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11767{
11768 byte ctlr_b;
11769 PLCI *plci_b;
11770
11771 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11772 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11773 {
11774 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11775 UnMapId(Id), (char *)(FILE_), __LINE__));
11776 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11777 return (NULL);
11778 }
11779 ctlr_b = 0;
11780 if ((plci_b_id & 0x7f) != 0)
11781 {
11782 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11783 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11784 ctlr_b = 0;
11785 }
11786 if ((ctlr_b == 0)
11787 || (((plci_b_id >> 8) & 0xff) == 0)
11788 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11789 {
11790 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11791 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11792 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11793 return (NULL);
11794 }
11795 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11796 if (!plci_b->State
11797 || !plci_b->NL.Id || plci_b->nl_remove_id
11798 || (plci_b->li_bchannel_id == 0))
11799 {
11800 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11801 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11802 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11803 return (NULL);
11804 }
11805 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11806 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11807 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11808 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11809 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11810 {
11811 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11812 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11813 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11814 return (NULL);
11815 }
11816 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11817 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11818 {
11819 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11820 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11821 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11822 return (NULL);
11823 }
11824 return (plci_b);
11825}
11826
11827
11828static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11829 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11830{
11831 byte ctlr_b;
11832 PLCI *plci_b;
11833
11834 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11835 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11836 {
11837 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11838 UnMapId(Id), (char *)(FILE_), __LINE__));
11839 PUT_WORD(p_result, _WRONG_STATE);
11840 return (NULL);
11841 }
11842 ctlr_b = 0;
11843 if ((plci_b_id & 0x7f) != 0)
11844 {
11845 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11846 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11847 ctlr_b = 0;
11848 }
11849 if ((ctlr_b == 0)
11850 || (((plci_b_id >> 8) & 0xff) == 0)
11851 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11852 {
11853 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11854 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11855 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11856 return (NULL);
11857 }
11858 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11859 if (!plci_b->State
11860 || !plci_b->NL.Id || plci_b->nl_remove_id
11861 || (plci_b->li_bchannel_id == 0)
11862 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11863 {
11864 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11865 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11866 PUT_WORD(p_result, _WRONG_STATE);
11867 return (NULL);
11868 }
11869 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11870 ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11871 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11872 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11873 {
11874 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11875 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11876 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11877 return (NULL);
11878 }
11879 if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11880 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11881 {
11882 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11883 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11884 PUT_WORD(p_result, _WRONG_STATE);
11885 return (NULL);
11886 }
11887 return (plci_b);
11888}
11889
11890
11891static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
11892{
11893 word Info;
11894 word i;
11895 dword d, li_flags, plci_b_id;
11896 PLCI *plci_b;
11897 API_PARSE li_parms[3];
11898 API_PARSE li_req_parms[3];
11899 API_PARSE li_participant_struct[2];
11900 API_PARSE li_participant_parms[3];
11901 word participant_parms_pos;
11902 byte result_buffer[32];
11903 byte *result;
11904 word result_pos;
11905 word plci_b_write_pos;
11906
11907 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11908 UnMapId(Id), (char *)(FILE_), __LINE__));
11909
11910 Info = GOOD;
11911 result = result_buffer;
11912 result_buffer[0] = 0;
11913 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11914 {
11915 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11916 UnMapId(Id), (char *)(FILE_), __LINE__));
11917 Info = _FACILITY_NOT_SUPPORTED;
11918 }
11919 else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11920 {
11921 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11922 UnMapId(Id), (char *)(FILE_), __LINE__));
11923 Info = _WRONG_MESSAGE_FORMAT;
11924 }
11925 else
11926 {
11927 result_buffer[0] = 3;
11928 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11929 result_buffer[3] = 0;
11930 switch (GET_WORD(li_parms[0].info))
11931 {
11932 case LI_GET_SUPPORTED_SERVICES:
11933 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11934 {
11935 result_buffer[0] = 17;
11936 result_buffer[3] = 14;
11937 PUT_WORD(&result_buffer[4], GOOD);
11938 d = 0;
11939 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11940 d |= LI_CONFERENCING_SUPPORTED;
11941 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11942 d |= LI_MONITORING_SUPPORTED;
11943 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11944 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11945 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946 d |= LI_CROSS_CONTROLLER_SUPPORTED;
11947 PUT_DWORD(&result_buffer[6], d);
11948 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11949 {
11950 d = 0;
11951 for (i = 0; i < li_total_channels; i++)
11952 {
11953 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954 && (li_config_table[i].adapter->li_pri
11955 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11956 {
11957 d++;
11958 }
11959 }
11960 }
11961 else
11962 {
11963 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11964 }
11965 PUT_DWORD(&result_buffer[10], d / 2);
11966 PUT_DWORD(&result_buffer[14], d);
11967 }
11968 else
11969 {
11970 result_buffer[0] = 25;
11971 result_buffer[3] = 22;
11972 PUT_WORD(&result_buffer[4], GOOD);
11973 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11974 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11975 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11976 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11977 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11978 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11979 d |= LI2_PC_LOOPING_SUPPORTED;
11980 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11981 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11982 PUT_DWORD(&result_buffer[6], d);
11983 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11984 PUT_DWORD(&result_buffer[10], d / 2);
11985 PUT_DWORD(&result_buffer[14], d - 1);
11986 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11987 {
11988 d = 0;
11989 for (i = 0; i < li_total_channels; i++)
11990 {
11991 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11992 && (li_config_table[i].adapter->li_pri
11993 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11994 {
11995 d++;
11996 }
11997 }
11998 }
11999 PUT_DWORD(&result_buffer[18], d / 2);
12000 PUT_DWORD(&result_buffer[22], d - 1);
12001 }
12002 break;
12003
12004 case LI_REQ_CONNECT:
12005 if (li_parms[1].length == 8)
12006 {
12007 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12008 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12009 {
12010 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12011 UnMapId(Id), (char *)(FILE_), __LINE__));
12012 Info = _WRONG_MESSAGE_FORMAT;
12013 break;
12014 }
12015 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12016 li_flags = GET_DWORD(li_req_parms[1].info);
12017 Info = li_check_main_plci(Id, plci);
12018 result_buffer[0] = 9;
12019 result_buffer[3] = 6;
12020 PUT_DWORD(&result_buffer[4], plci_b_id);
12021 PUT_WORD(&result_buffer[8], GOOD);
12022 if (Info != GOOD)
12023 break;
12024 result = plci->saved_msg.info;
12025 for (i = 0; i <= result_buffer[0]; i++)
12026 result[i] = result_buffer[i];
12027 plci_b_write_pos = plci->li_plci_b_write_pos;
12028 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12029 if (plci_b == NULL)
12030 break;
12031 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12032 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12033 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12034 plci->li_plci_b_write_pos = plci_b_write_pos;
12035 }
12036 else
12037 {
12038 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12039 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12040 {
12041 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12042 UnMapId(Id), (char *)(FILE_), __LINE__));
12043 Info = _WRONG_MESSAGE_FORMAT;
12044 break;
12045 }
12046 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12047 Info = li_check_main_plci(Id, plci);
12048 result_buffer[0] = 7;
12049 result_buffer[3] = 4;
12050 PUT_WORD(&result_buffer[4], Info);
12051 result_buffer[6] = 0;
12052 if (Info != GOOD)
12053 break;
12054 result = plci->saved_msg.info;
12055 for (i = 0; i <= result_buffer[0]; i++)
12056 result[i] = result_buffer[i];
12057 plci_b_write_pos = plci->li_plci_b_write_pos;
12058 participant_parms_pos = 0;
12059 result_pos = 7;
12060 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12061 while (participant_parms_pos < li_req_parms[1].length)
12062 {
12063 result[result_pos] = 6;
12064 result_pos += 7;
12065 PUT_DWORD(&result[result_pos - 6], 0);
12066 PUT_WORD(&result[result_pos - 2], GOOD);
12067 if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12068 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12069 {
12070 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12071 UnMapId(Id), (char *)(FILE_), __LINE__));
12072 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12073 break;
12074 }
12075 if (api_parse(&li_participant_struct[0].info[1],
12076 li_participant_struct[0].length, "dd", li_participant_parms))
12077 {
12078 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12079 UnMapId(Id), (char *)(FILE_), __LINE__));
12080 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12081 break;
12082 }
12083 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12084 li_flags = GET_DWORD(li_participant_parms[1].info);
12085 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12086 if (sizeof(result) - result_pos < 7)
12087 {
12088 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12089 UnMapId(Id), (char *)(FILE_), __LINE__));
12090 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12091 break;
12092 }
12093 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12094 if (plci_b != NULL)
12095 {
12096 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12097 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12098 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12099 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12100 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12101 }
12102 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12103 (&li_req_parms[1].info[1]));
12104 }
12105 result[0] = (byte)(result_pos - 1);
12106 result[3] = (byte)(result_pos - 4);
12107 result[6] = (byte)(result_pos - 7);
12108 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12109 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12110 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12111 {
12112 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12113 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12114 }
12115 else
12116 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12117 plci->li_plci_b_write_pos = plci_b_write_pos;
12118 }
12119 mixer_calculate_coefs(a);
12120 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12121 mixer_notify_update(plci, true);
12122 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12123 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12124 plci->command = 0;
12125 plci->li_cmd = GET_WORD(li_parms[0].info);
12126 start_internal_command(Id, plci, mixer_command);
12127 return (false);
12128
12129 case LI_REQ_DISCONNECT:
12130 if (li_parms[1].length == 4)
12131 {
12132 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12133 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12134 {
12135 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12136 UnMapId(Id), (char *)(FILE_), __LINE__));
12137 Info = _WRONG_MESSAGE_FORMAT;
12138 break;
12139 }
12140 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12141 Info = li_check_main_plci(Id, plci);
12142 result_buffer[0] = 9;
12143 result_buffer[3] = 6;
12144 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12145 PUT_WORD(&result_buffer[8], GOOD);
12146 if (Info != GOOD)
12147 break;
12148 result = plci->saved_msg.info;
12149 for (i = 0; i <= result_buffer[0]; i++)
12150 result[i] = result_buffer[i];
12151 plci_b_write_pos = plci->li_plci_b_write_pos;
12152 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12153 if (plci_b == NULL)
12154 break;
12155 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12156 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12157 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12158 plci->li_plci_b_write_pos = plci_b_write_pos;
12159 }
12160 else
12161 {
12162 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12163 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12164 {
12165 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12166 UnMapId(Id), (char *)(FILE_), __LINE__));
12167 Info = _WRONG_MESSAGE_FORMAT;
12168 break;
12169 }
12170 Info = li_check_main_plci(Id, plci);
12171 result_buffer[0] = 7;
12172 result_buffer[3] = 4;
12173 PUT_WORD(&result_buffer[4], Info);
12174 result_buffer[6] = 0;
12175 if (Info != GOOD)
12176 break;
12177 result = plci->saved_msg.info;
12178 for (i = 0; i <= result_buffer[0]; i++)
12179 result[i] = result_buffer[i];
12180 plci_b_write_pos = plci->li_plci_b_write_pos;
12181 participant_parms_pos = 0;
12182 result_pos = 7;
12183 while (participant_parms_pos < li_req_parms[0].length)
12184 {
12185 result[result_pos] = 6;
12186 result_pos += 7;
12187 PUT_DWORD(&result[result_pos - 6], 0);
12188 PUT_WORD(&result[result_pos - 2], GOOD);
12189 if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12190 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12191 {
12192 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12193 UnMapId(Id), (char *)(FILE_), __LINE__));
12194 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12195 break;
12196 }
12197 if (api_parse(&li_participant_struct[0].info[1],
12198 li_participant_struct[0].length, "d", li_participant_parms))
12199 {
12200 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12201 UnMapId(Id), (char *)(FILE_), __LINE__));
12202 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12203 break;
12204 }
12205 plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12206 PUT_DWORD(&result[result_pos - 6], plci_b_id);
12207 if (sizeof(result) - result_pos < 7)
12208 {
12209 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12210 UnMapId(Id), (char *)(FILE_), __LINE__));
12211 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12212 break;
12213 }
12214 plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12215 if (plci_b != NULL)
12216 {
12217 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12218 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12219 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12220 }
12221 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12222 (&li_req_parms[0].info[1]));
12223 }
12224 result[0] = (byte)(result_pos - 1);
12225 result[3] = (byte)(result_pos - 4);
12226 result[6] = (byte)(result_pos - 7);
12227 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12228 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12229 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12230 {
12231 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12232 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12233 }
12234 else
12235 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12236 plci->li_plci_b_write_pos = plci_b_write_pos;
12237 }
12238 mixer_calculate_coefs(a);
12239 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12240 mixer_notify_update(plci, true);
12241 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12242 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12243 plci->command = 0;
12244 plci->li_cmd = GET_WORD(li_parms[0].info);
12245 start_internal_command(Id, plci, mixer_command);
12246 return (false);
12247
12248 case LI_REQ_SILENT_UPDATE:
12249 if (!plci || !plci->State
12250 || !plci->NL.Id || plci->nl_remove_id
12251 || (plci->li_bchannel_id == 0)
12252 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12253 {
12254 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12255 UnMapId(Id), (char *)(FILE_), __LINE__));
12256 return (false);
12257 }
12258 plci_b_write_pos = plci->li_plci_b_write_pos;
12259 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12260 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12261 {
12262 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12263 UnMapId(Id), (char *)(FILE_), __LINE__));
12264 return (false);
12265 }
12266 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12267 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12268 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12269 {
12270 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12271 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12272 }
12273 else
12274 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12275 plci->li_plci_b_write_pos = plci_b_write_pos;
12276 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12277 plci->command = 0;
12278 plci->li_cmd = GET_WORD(li_parms[0].info);
12279 start_internal_command(Id, plci, mixer_command);
12280 return (false);
12281
12282 default:
12283 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12284 UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12285 Info = _FACILITY_NOT_SUPPORTED;
12286 }
12287 }
12288 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12289 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12290 return (false);
12291}
12292
12293
12294static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12295{
12296 dword d;
12297 byte result[12];
12298
12299 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12300 UnMapId(Id), (char *)(FILE_), __LINE__));
12301
12302 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12303 {
12304 do
12305 {
12306 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12307 if (!(d & LI_PLCI_B_SKIP_FLAG))
12308 {
12309 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12310 {
12311 if (d & LI_PLCI_B_DISC_FLAG)
12312 {
12313 result[0] = 5;
12314 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12315 result[3] = 2;
12316 PUT_WORD(&result[4], _LI_USER_INITIATED);
12317 }
12318 else
12319 {
12320 result[0] = 7;
12321 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12322 result[3] = 4;
12323 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12324 }
12325 }
12326 else
12327 {
12328 if (d & LI_PLCI_B_DISC_FLAG)
12329 {
12330 result[0] = 9;
12331 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12332 result[3] = 6;
12333 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12334 PUT_WORD(&result[8], _LI_USER_INITIATED);
12335 }
12336 else
12337 {
12338 result[0] = 7;
12339 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12340 result[3] = 4;
12341 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12342 }
12343 }
12344 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12345 "ws", SELECTOR_LINE_INTERCONNECT, result);
12346 }
12347 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12348 0 : plci->li_plci_b_read_pos + 1;
12349 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12350 }
12351}
12352
12353
12354static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12355{
12356 word i, j, ch;
12357 struct xconnect_transfer_address_s s, *p;
12358 DIVA_CAPI_ADAPTER *a;
12359
12360 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12361 UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12362
12363 a = plci->adapter;
12364 i = 1;
12365 for (i = 1; i < length; i += 16)
12366 {
12367 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12368 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12369 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12370 ch = msg[i + 12] | (msg[i + 13] << 8);
12371 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12372 if (!a->li_pri && (plci->li_bchannel_id == 2))
12373 j = 1 - j;
12374 j += a->li_base;
12375 if (ch & XCONNECT_CHANNEL_PORT_PC)
12376 p = &(li_config_table[j].send_pc);
12377 else
12378 p = &(li_config_table[j].send_b);
12379 p->card_address.low = s.card_address.low;
12380 p->card_address.high = s.card_address.high;
12381 p->offset = s.offset;
12382 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12383 }
12384 if (plci->internal_command_queue[0]
12385 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12386 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12387 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12388 {
12389 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12390 if (!plci->internal_command)
12391 next_internal_command(Id, plci);
12392 }
12393 mixer_notify_update(plci, true);
12394}
12395
12396
12397static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12398{
12399
12400 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12401 UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12402
12403}
12404
12405
12406static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12407{
12408 word plci_b_write_pos;
12409
12410 plci_b_write_pos = plci->li_plci_b_write_pos;
12411 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12412 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12413 {
12414 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12415 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12416 (char *)(FILE_), __LINE__));
12417 return (false);
12418 }
12419 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12420 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12421 plci->li_plci_b_write_pos = plci_b_write_pos;
12422 return (true);
12423}
12424
12425
12426static void mixer_remove(PLCI *plci)
12427{
12428 DIVA_CAPI_ADAPTER *a;
12429 PLCI *notify_plci;
12430 dword plci_b_id;
12431 word i, j;
12432
12433 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12434 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12435 (char *)(FILE_), __LINE__));
12436
12437 a = plci->adapter;
12438 plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12439 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12440 {
12441 if ((plci->li_bchannel_id != 0)
12442 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12443 {
12444 i = a->li_base + (plci->li_bchannel_id - 1);
12445 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12446 {
12447 for (j = 0; j < li_total_channels; j++)
12448 {
12449 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12450 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12451 {
12452 notify_plci = li_config_table[j].plci;
12453 if ((notify_plci != NULL)
12454 && (notify_plci != plci)
12455 && (notify_plci->appl != NULL)
12456 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12457 && (notify_plci->State)
12458 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12459 {
12460 mixer_notify_source_removed(notify_plci, plci_b_id);
12461 }
12462 }
12463 }
12464 mixer_clear_config(plci);
12465 mixer_calculate_coefs(a);
12466 mixer_notify_update(plci, true);
12467 }
12468 li_config_table[i].plci = NULL;
12469 plci->li_bchannel_id = 0;
12470 }
12471 }
12472}
12473
12474
12475
12476
12477
12478
12479
12480static void ec_write_parameters(PLCI *plci)
12481{
12482 word w;
12483 byte parameter_buffer[6];
12484
12485 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12486 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12487 (char *)(FILE_), __LINE__));
12488
12489 parameter_buffer[0] = 5;
12490 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12491 PUT_WORD(¶meter_buffer[2], plci->ec_idi_options);
12492 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12493 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12494 PUT_WORD(¶meter_buffer[4], w);
12495 add_p(plci, FTY, parameter_buffer);
12496 sig_req(plci, TEL_CTRL, 0);
12497 send_req(plci);
12498}
12499
12500
12501static void ec_clear_config(PLCI *plci)
12502{
12503
12504 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12505 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12506 (char *)(FILE_), __LINE__));
12507
12508 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12509 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12510 plci->ec_tail_length = 0;
12511}
12512
12513
12514static void ec_prepare_switch(dword Id, PLCI *plci)
12515{
12516
12517 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12518 UnMapId(Id), (char *)(FILE_), __LINE__));
12519
12520}
12521
12522
12523static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12524{
12525
12526 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12527 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12528
12529 return (GOOD);
12530}
12531
12532
12533static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12534{
12535 word Info;
12536
12537 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12538 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12539
12540 Info = GOOD;
12541 if (plci->B1_facilities & B1_FACILITY_EC)
12542 {
12543 switch (plci->adjust_b_state)
12544 {
12545 case ADJUST_B_RESTORE_EC_1:
12546 plci->internal_command = plci->adjust_b_command;
12547 if (plci->sig_req)
12548 {
12549 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12550 break;
12551 }
12552 ec_write_parameters(plci);
12553 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12554 break;
12555 case ADJUST_B_RESTORE_EC_2:
12556 if ((Rc != OK) && (Rc != OK_FC))
12557 {
12558 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12559 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12560 Info = _WRONG_STATE;
12561 break;
12562 }
12563 break;
12564 }
12565 }
12566 return (Info);
12567}
12568
12569
12570static void ec_command(dword Id, PLCI *plci, byte Rc)
12571{
12572 word internal_command, Info;
12573 byte result[8];
12574
12575 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12576 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12577 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12578
12579 Info = GOOD;
12580 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12581 {
12582 result[0] = 2;
12583 PUT_WORD(&result[1], EC_SUCCESS);
12584 }
12585 else
12586 {
12587 result[0] = 5;
12588 PUT_WORD(&result[1], plci->ec_cmd);
12589 result[3] = 2;
12590 PUT_WORD(&result[4], GOOD);
12591 }
12592 internal_command = plci->internal_command;
12593 plci->internal_command = 0;
12594 switch (plci->ec_cmd)
12595 {
12596 case EC_ENABLE_OPERATION:
12597 case EC_FREEZE_COEFFICIENTS:
12598 case EC_RESUME_COEFFICIENT_UPDATE:
12599 case EC_RESET_COEFFICIENTS:
12600 switch (internal_command)
12601 {
12602 default:
12603 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12604 B1_FACILITY_EC), EC_COMMAND_1);
12605 case EC_COMMAND_1:
12606 if (adjust_b_process(Id, plci, Rc) != GOOD)
12607 {
12608 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12609 UnMapId(Id), (char *)(FILE_), __LINE__));
12610 Info = _FACILITY_NOT_SUPPORTED;
12611 break;
12612 }
12613 if (plci->internal_command)
12614 return;
12615 case EC_COMMAND_2:
12616 if (plci->sig_req)
12617 {
12618 plci->internal_command = EC_COMMAND_2;
12619 return;
12620 }
12621 plci->internal_command = EC_COMMAND_3;
12622 ec_write_parameters(plci);
12623 return;
12624 case EC_COMMAND_3:
12625 if ((Rc != OK) && (Rc != OK_FC))
12626 {
12627 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12628 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12629 Info = _FACILITY_NOT_SUPPORTED;
12630 break;
12631 }
12632 break;
12633 }
12634 break;
12635
12636 case EC_DISABLE_OPERATION:
12637 switch (internal_command)
12638 {
12639 default:
12640 case EC_COMMAND_1:
12641 if (plci->B1_facilities & B1_FACILITY_EC)
12642 {
12643 if (plci->sig_req)
12644 {
12645 plci->internal_command = EC_COMMAND_1;
12646 return;
12647 }
12648 plci->internal_command = EC_COMMAND_2;
12649 ec_write_parameters(plci);
12650 return;
12651 }
12652 Rc = OK;
12653 case EC_COMMAND_2:
12654 if ((Rc != OK) && (Rc != OK_FC))
12655 {
12656 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12657 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12658 Info = _FACILITY_NOT_SUPPORTED;
12659 break;
12660 }
12661 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12662 ~B1_FACILITY_EC), EC_COMMAND_3);
12663 case EC_COMMAND_3:
12664 if (adjust_b_process(Id, plci, Rc) != GOOD)
12665 {
12666 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12667 UnMapId(Id), (char *)(FILE_), __LINE__));
12668 Info = _FACILITY_NOT_SUPPORTED;
12669 break;
12670 }
12671 if (plci->internal_command)
12672 return;
12673 break;
12674 }
12675 break;
12676 }
12677 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12678 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12679 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12680}
12681
12682
12683static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12684{
12685 word Info;
12686 word opt;
12687 API_PARSE ec_parms[3];
12688 byte result[16];
12689
12690 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12691 UnMapId(Id), (char *)(FILE_), __LINE__));
12692
12693 Info = GOOD;
12694 result[0] = 0;
12695 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12696 {
12697 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12698 UnMapId(Id), (char *)(FILE_), __LINE__));
12699 Info = _FACILITY_NOT_SUPPORTED;
12700 }
12701 else
12702 {
12703 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12704 {
12705 if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12706 {
12707 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12708 UnMapId(Id), (char *)(FILE_), __LINE__));
12709 Info = _WRONG_MESSAGE_FORMAT;
12710 }
12711 else
12712 {
12713 if (plci == NULL)
12714 {
12715 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12716 UnMapId(Id), (char *)(FILE_), __LINE__));
12717 Info = _WRONG_IDENTIFIER;
12718 }
12719 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12720 {
12721 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12722 UnMapId(Id), (char *)(FILE_), __LINE__));
12723 Info = _WRONG_STATE;
12724 }
12725 else
12726 {
12727 plci->command = 0;
12728 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12729 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12730 result[0] = 2;
12731 PUT_WORD(&result[1], EC_SUCCESS);
12732 if (msg[1].length >= 4)
12733 {
12734 opt = GET_WORD(&ec_parms[0].info[2]);
12735 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12736 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12737 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12738 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12739 if (opt & EC_DETECT_DISABLE_TONE)
12740 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12741 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12742 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12743 if (msg[1].length >= 6)
12744 {
12745 plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12746 }
12747 }
12748 switch (plci->ec_cmd)
12749 {
12750 case EC_ENABLE_OPERATION:
12751 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12752 start_internal_command(Id, plci, ec_command);
12753 return (false);
12754
12755 case EC_DISABLE_OPERATION:
12756 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12757 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12758 LEC_RESET_COEFFICIENTS;
12759 start_internal_command(Id, plci, ec_command);
12760 return (false);
12761
12762 case EC_FREEZE_COEFFICIENTS:
12763 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12764 start_internal_command(Id, plci, ec_command);
12765 return (false);
12766
12767 case EC_RESUME_COEFFICIENT_UPDATE:
12768 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12769 start_internal_command(Id, plci, ec_command);
12770 return (false);
12771
12772 case EC_RESET_COEFFICIENTS:
12773 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12774 start_internal_command(Id, plci, ec_command);
12775 return (false);
12776
12777 default:
12778 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12779 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12780 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12781 }
12782 }
12783 }
12784 }
12785 else
12786 {
12787 if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12788 {
12789 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12790 UnMapId(Id), (char *)(FILE_), __LINE__));
12791 Info = _WRONG_MESSAGE_FORMAT;
12792 }
12793 else
12794 {
12795 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12796 {
12797 result[0] = 11;
12798 PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12799 result[3] = 8;
12800 PUT_WORD(&result[4], GOOD);
12801 PUT_WORD(&result[6], 0x0007);
12802 PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12803 PUT_WORD(&result[10], 0);
12804 }
12805 else if (plci == NULL)
12806 {
12807 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12808 UnMapId(Id), (char *)(FILE_), __LINE__));
12809 Info = _WRONG_IDENTIFIER;
12810 }
12811 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12812 {
12813 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12814 UnMapId(Id), (char *)(FILE_), __LINE__));
12815 Info = _WRONG_STATE;
12816 }
12817 else
12818 {
12819 plci->command = 0;
12820 plci->ec_cmd = GET_WORD(ec_parms[0].info);
12821 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12822 result[0] = 5;
12823 PUT_WORD(&result[1], plci->ec_cmd);
12824 result[3] = 2;
12825 PUT_WORD(&result[4], GOOD);
12826 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12827 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12828 plci->ec_tail_length = 0;
12829 if (ec_parms[1].length >= 2)
12830 {
12831 opt = GET_WORD(&ec_parms[1].info[1]);
12832 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12833 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12834 if (opt & EC_DETECT_DISABLE_TONE)
12835 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12836 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12837 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12838 if (ec_parms[1].length >= 4)
12839 {
12840 plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12841 }
12842 }
12843 switch (plci->ec_cmd)
12844 {
12845 case EC_ENABLE_OPERATION:
12846 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12847 start_internal_command(Id, plci, ec_command);
12848 return (false);
12849
12850 case EC_DISABLE_OPERATION:
12851 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12852 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12853 LEC_RESET_COEFFICIENTS;
12854 start_internal_command(Id, plci, ec_command);
12855 return (false);
12856
12857 default:
12858 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12859 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12860 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12861 }
12862 }
12863 }
12864 }
12865 }
12866 sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12867 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12868 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12869 return (false);
12870}
12871
12872
12873static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12874{
12875 byte result[8];
12876
12877 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12878 UnMapId(Id), (char *)(FILE_), __LINE__));
12879
12880 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12881 {
12882 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12883 {
12884 result[0] = 2;
12885 PUT_WORD(&result[1], 0);
12886 switch (msg[1])
12887 {
12888 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12889 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12890 break;
12891 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12892 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12893 break;
12894 case LEC_DISABLE_RELEASED:
12895 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12896 break;
12897 }
12898 }
12899 else
12900 {
12901 result[0] = 5;
12902 PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12903 result[3] = 2;
12904 PUT_WORD(&result[4], 0);
12905 switch (msg[1])
12906 {
12907 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909 break;
12910 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912 break;
12913 case LEC_DISABLE_RELEASED:
12914 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12915 break;
12916 }
12917 }
12918 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12919 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12920 }
12921}
12922
12923
12924
12925
12926
12927
12928
12929static void adv_voice_write_coefs(PLCI *plci, word write_command)
12930{
12931 DIVA_CAPI_ADAPTER *a;
12932 word i;
12933 byte *p;
12934
12935 word w, n, j, k;
12936 byte ch_map[MIXER_CHANNELS_BRI];
12937
12938 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12939
12940 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12941 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12942 (char *)(FILE_), __LINE__, write_command));
12943
12944 a = plci->adapter;
12945 p = coef_buffer + 1;
12946 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12947 i = 0;
12948 while (i + sizeof(word) <= a->adv_voice_coef_length)
12949 {
12950 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12951 p += 2;
12952 i += 2;
12953 }
12954 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12955 {
12956 PUT_WORD(p, 0x8000);
12957 p += 2;
12958 i += 2;
12959 }
12960
12961 if (!a->li_pri && (plci->li_bchannel_id == 0))
12962 {
12963 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12964 {
12965 plci->li_bchannel_id = 1;
12966 li_config_table[a->li_base].plci = plci;
12967 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12968 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12969 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12970 }
12971 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12972 {
12973 plci->li_bchannel_id = 2;
12974 li_config_table[a->li_base + 1].plci = plci;
12975 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12976 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12977 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12978 }
12979 }
12980 if (!a->li_pri && (plci->li_bchannel_id != 0)
12981 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12982 {
12983 i = a->li_base + (plci->li_bchannel_id - 1);
12984 switch (write_command)
12985 {
12986 case ADV_VOICE_WRITE_ACTIVATION:
12987 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
12988 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
12989 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
12990 {
12991 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12992 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12993 }
12994 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
12995 {
12996 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12997 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12998 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
12999 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13000 }
13001 mixer_calculate_coefs(a);
13002 li_config_table[i].curchnl = li_config_table[i].channel;
13003 li_config_table[j].curchnl = li_config_table[j].channel;
13004 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13005 li_config_table[k].curchnl = li_config_table[k].channel;
13006 break;
13007
13008 case ADV_VOICE_WRITE_DEACTIVATION:
13009 for (j = 0; j < li_total_channels; j++)
13010 {
13011 li_config_table[i].flag_table[j] = 0;
13012 li_config_table[j].flag_table[i] = 0;
13013 }
13014 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13015 for (j = 0; j < li_total_channels; j++)
13016 {
13017 li_config_table[k].flag_table[j] = 0;
13018 li_config_table[j].flag_table[k] = 0;
13019 }
13020 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13021 {
13022 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13023 for (j = 0; j < li_total_channels; j++)
13024 {
13025 li_config_table[k].flag_table[j] = 0;
13026 li_config_table[j].flag_table[k] = 0;
13027 }
13028 }
13029 mixer_calculate_coefs(a);
13030 break;
13031 }
13032 if (plci->B1_facilities & B1_FACILITY_MIXER)
13033 {
13034 w = 0;
13035 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13036 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13037 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13038 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13039 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13040 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13041 *(p++) = (byte) w;
13042 *(p++) = (byte)(w >> 8);
13043 for (j = 0; j < sizeof(ch_map); j += 2)
13044 {
13045 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13046 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13047 }
13048 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13049 {
13050 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13051 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13052 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13053 {
13054 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13055 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13056 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13057 }
13058 else
13059 {
13060 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13061 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13062 }
13063 }
13064 }
13065 else
13066 {
13067 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13068 *(p++) = a->adv_voice_coef_buffer[i];
13069 }
13070 }
13071 else
13072
13073 {
13074 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13075 *(p++) = a->adv_voice_coef_buffer[i];
13076 }
13077 coef_buffer[0] = (p - coef_buffer) - 1;
13078 add_p(plci, FTY, coef_buffer);
13079 sig_req(plci, TEL_CTRL, 0);
13080 send_req(plci);
13081}
13082
13083
13084static void adv_voice_clear_config(PLCI *plci)
13085{
13086 DIVA_CAPI_ADAPTER *a;
13087
13088 word i, j;
13089
13090
13091 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13092 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13093 (char *)(FILE_), __LINE__));
13094
13095 a = plci->adapter;
13096 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13097 {
13098 a->adv_voice_coef_length = 0;
13099
13100 if (!a->li_pri && (plci->li_bchannel_id != 0)
13101 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13102 {
13103 i = a->li_base + (plci->li_bchannel_id - 1);
13104 li_config_table[i].curchnl = 0;
13105 li_config_table[i].channel = 0;
13106 li_config_table[i].chflags = 0;
13107 for (j = 0; j < li_total_channels; j++)
13108 {
13109 li_config_table[i].flag_table[j] = 0;
13110 li_config_table[j].flag_table[i] = 0;
13111 li_config_table[i].coef_table[j] = 0;
13112 li_config_table[j].coef_table[i] = 0;
13113 }
13114 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13115 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13116 li_config_table[i].curchnl = 0;
13117 li_config_table[i].channel = 0;
13118 li_config_table[i].chflags = 0;
13119 for (j = 0; j < li_total_channels; j++)
13120 {
13121 li_config_table[i].flag_table[j] = 0;
13122 li_config_table[j].flag_table[i] = 0;
13123 li_config_table[i].coef_table[j] = 0;
13124 li_config_table[j].coef_table[i] = 0;
13125 }
13126 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13127 {
13128 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13129 li_config_table[i].curchnl = 0;
13130 li_config_table[i].channel = 0;
13131 li_config_table[i].chflags = 0;
13132 for (j = 0; j < li_total_channels; j++)
13133 {
13134 li_config_table[i].flag_table[j] = 0;
13135 li_config_table[j].flag_table[i] = 0;
13136 li_config_table[i].coef_table[j] = 0;
13137 li_config_table[j].coef_table[i] = 0;
13138 }
13139 }
13140 }
13141
13142 }
13143}
13144
13145
13146static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13147{
13148
13149 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13150 UnMapId(Id), (char *)(FILE_), __LINE__));
13151
13152}
13153
13154
13155static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13156{
13157
13158 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13159 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13160
13161 return (GOOD);
13162}
13163
13164
13165static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13166{
13167 DIVA_CAPI_ADAPTER *a;
13168 word Info;
13169
13170 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13171 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13172
13173 Info = GOOD;
13174 a = plci->adapter;
13175 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13176 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13177 {
13178 switch (plci->adjust_b_state)
13179 {
13180 case ADJUST_B_RESTORE_VOICE_1:
13181 plci->internal_command = plci->adjust_b_command;
13182 if (plci->sig_req)
13183 {
13184 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13185 break;
13186 }
13187 adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13188 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13189 break;
13190 case ADJUST_B_RESTORE_VOICE_2:
13191 if ((Rc != OK) && (Rc != OK_FC))
13192 {
13193 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13194 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13195 Info = _WRONG_STATE;
13196 break;
13197 }
13198 break;
13199 }
13200 }
13201 return (Info);
13202}
13203
13204
13205
13206
13207
13208
13209
13210
13211static byte b1_facilities_table[] =
13212{
13213 0x00,
13214 0x00,
13215 0x00,
13216 0x00,
13217 0x00,
13218 0x00,
13219 0x00,
13220 0x00,
13221 0x00,
13222 0x00,
13223 0x00,
13224 0x00,
13225 0x00,
13226 0x00,
13227 0x00,
13228 0x00,
13229 0x00,
13230 0x00,
13231 0x00,
13232 0x00,
13233 0x12,
13234 0x00,
13235 0x0c,
13236 0x1e,
13237 0x1f,
13238 0x13,
13239 0x12,
13240 0x12,
13241 0x2c,
13242 0x3e,
13243 0x3f,
13244 0x2c,
13245 0x3e,
13246 0x3f,
13247 0x00,
13248 0x00,
13249 0x0c,
13250 0x1e,
13251 0x1f
13252};
13253
13254
13255static word get_b1_facilities(PLCI *plci, byte b1_resource)
13256{
13257 word b1_facilities;
13258
13259 b1_facilities = b1_facilities_table[b1_resource];
13260 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13261 {
13262
13263 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13264 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13265
13266 {
13267 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13268 b1_facilities |= B1_FACILITY_DTMFX;
13269 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13270 b1_facilities |= B1_FACILITY_DTMFR;
13271 }
13272 }
13273 if ((b1_resource == 17) || (b1_resource == 18))
13274 {
13275 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13276 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13277 }
13278
13279
13280
13281
13282
13283 return (b1_facilities);
13284}
13285
13286
13287static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13288{
13289 byte b;
13290
13291 switch (b1_resource)
13292 {
13293 case 5:
13294 case 26:
13295 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13296 b = 26;
13297 else
13298 b = 5;
13299 break;
13300
13301 case 8:
13302 case 27:
13303 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13304 b = 27;
13305 else
13306 b = 8;
13307 break;
13308
13309 case 9:
13310 case 20:
13311 case 22:
13312 case 23:
13313 case 24:
13314 case 25:
13315 case 28:
13316 case 29:
13317 case 30:
13318 case 36:
13319 case 37:
13320 case 38:
13321 if (b1_facilities & B1_FACILITY_EC)
13322 {
13323 if (b1_facilities & B1_FACILITY_LOCAL)
13324 b = 30;
13325 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13326 b = 29;
13327 else
13328 b = 28;
13329 }
13330
13331 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13332 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13333 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13334 {
13335 if (b1_facilities & B1_FACILITY_LOCAL)
13336 b = 38;
13337 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13338 b = 37;
13339 else
13340 b = 36;
13341 }
13342
13343 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13344 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13345 || ((b1_facilities & B1_FACILITY_DTMFR)
13346 && ((b1_facilities & B1_FACILITY_MIXER)
13347 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13348 || ((b1_facilities & B1_FACILITY_DTMFX)
13349 && ((b1_facilities & B1_FACILITY_MIXER)
13350 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13351 {
13352 if (b1_facilities & B1_FACILITY_LOCAL)
13353 b = 24;
13354 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13355 b = 23;
13356 else
13357 b = 22;
13358 }
13359 else
13360 {
13361 if (b1_facilities & B1_FACILITY_LOCAL)
13362 b = 25;
13363 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13364 b = 20;
13365 else
13366 b = 9;
13367 }
13368 break;
13369
13370 case 31:
13371 case 32:
13372 case 33:
13373 if (b1_facilities & B1_FACILITY_LOCAL)
13374 b = 33;
13375 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13376 b = 32;
13377 else
13378 b = 31;
13379 break;
13380
13381 default:
13382 b = b1_resource;
13383 }
13384 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13385 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13386 (char *)(FILE_), __LINE__,
13387 b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13388 return (b);
13389}
13390
13391
13392static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13393{
13394 word removed_facilities;
13395
13396 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13397 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13398 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13399 new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13400
13401 new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13402 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13403
13404 if (removed_facilities & B1_FACILITY_EC)
13405 ec_clear_config(plci);
13406
13407
13408 if (removed_facilities & B1_FACILITY_DTMFR)
13409 {
13410 dtmf_rec_clear_config(plci);
13411 dtmf_parameter_clear_config(plci);
13412 }
13413 if (removed_facilities & B1_FACILITY_DTMFX)
13414 dtmf_send_clear_config(plci);
13415
13416
13417 if (removed_facilities & B1_FACILITY_MIXER)
13418 mixer_clear_config(plci);
13419
13420 if (removed_facilities & B1_FACILITY_VOICE)
13421 adv_voice_clear_config(plci);
13422 plci->B1_facilities = new_b1_facilities;
13423}
13424
13425
13426static void adjust_b_clear(PLCI *plci)
13427{
13428
13429 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13430 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13431 (char *)(FILE_), __LINE__));
13432
13433 plci->adjust_b_restore = false;
13434}
13435
13436
13437static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13438{
13439 word Info;
13440 byte b1_resource;
13441 NCCI *ncci_ptr;
13442 API_PARSE bp[2];
13443
13444 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13445 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13446
13447 Info = GOOD;
13448 switch (plci->adjust_b_state)
13449 {
13450 case ADJUST_B_START:
13451 if ((plci->adjust_b_parms_msg == NULL)
13452 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13453 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13454 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13455 {
13456 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13457 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13458 if (b1_resource == plci->B1_resource)
13459 {
13460 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13461 break;
13462 }
13463 if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13464 {
13465 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13466 UnMapId(Id), (char *)(FILE_), __LINE__,
13467 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13468 Info = _WRONG_STATE;
13469 break;
13470 }
13471 }
13472 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13473 {
13474
13475 mixer_prepare_switch(Id, plci);
13476
13477
13478 dtmf_prepare_switch(Id, plci);
13479 dtmf_parameter_prepare_switch(Id, plci);
13480
13481
13482 ec_prepare_switch(Id, plci);
13483
13484 adv_voice_prepare_switch(Id, plci);
13485 }
13486 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13487 Rc = OK;
13488 case ADJUST_B_SAVE_MIXER_1:
13489 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13490 {
13491
13492 Info = mixer_save_config(Id, plci, Rc);
13493 if ((Info != GOOD) || plci->internal_command)
13494 break;
13495
13496 }
13497 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13498 Rc = OK;
13499 case ADJUST_B_SAVE_DTMF_1:
13500 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13501 {
13502
13503 Info = dtmf_save_config(Id, plci, Rc);
13504 if ((Info != GOOD) || plci->internal_command)
13505 break;
13506
13507 }
13508 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13509 case ADJUST_B_REMOVE_L23_1:
13510 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13511 && plci->NL.Id && !plci->nl_remove_id)
13512 {
13513 plci->internal_command = plci->adjust_b_command;
13514 if (plci->adjust_b_ncci != 0)
13515 {
13516 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13517 while (ncci_ptr->data_pending)
13518 {
13519 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13520 data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13521 }
13522 while (ncci_ptr->data_ack_pending)
13523 data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13524 }
13525 nl_req_ncci(plci, REMOVE,
13526 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13527 send_req(plci);
13528 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13529 break;
13530 }
13531 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13532 Rc = OK;
13533 case ADJUST_B_REMOVE_L23_2:
13534 if ((Rc != OK) && (Rc != OK_FC))
13535 {
13536 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13537 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13538 Info = _WRONG_STATE;
13539 break;
13540 }
13541 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13542 {
13543 if (plci_nl_busy(plci))
13544 {
13545 plci->internal_command = plci->adjust_b_command;
13546 break;
13547 }
13548 }
13549 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13550 Rc = OK;
13551 case ADJUST_B_SAVE_EC_1:
13552 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13553 {
13554
13555 Info = ec_save_config(Id, plci, Rc);
13556 if ((Info != GOOD) || plci->internal_command)
13557 break;
13558
13559 }
13560 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13561 Rc = OK;
13562 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13563 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13564 {
13565
13566 Info = dtmf_parameter_save_config(Id, plci, Rc);
13567 if ((Info != GOOD) || plci->internal_command)
13568 break;
13569
13570 }
13571 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13572 Rc = OK;
13573 case ADJUST_B_SAVE_VOICE_1:
13574 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13575 {
13576 Info = adv_voice_save_config(Id, plci, Rc);
13577 if ((Info != GOOD) || plci->internal_command)
13578 break;
13579 }
13580 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13581 case ADJUST_B_SWITCH_L1_1:
13582 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13583 {
13584 if (plci->sig_req)
13585 {
13586 plci->internal_command = plci->adjust_b_command;
13587 break;
13588 }
13589 if (plci->adjust_b_parms_msg != NULL)
13590 api_load_msg(plci->adjust_b_parms_msg, bp);
13591 else
13592 api_load_msg(&plci->B_protocol, bp);
13593 Info = add_b1(plci, bp,
13594 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13595 plci->adjust_b_facilities);
13596 if (Info != GOOD)
13597 {
13598 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13599 UnMapId(Id), (char *)(FILE_), __LINE__,
13600 plci->B1_resource, plci->adjust_b_facilities));
13601 break;
13602 }
13603 plci->internal_command = plci->adjust_b_command;
13604 sig_req(plci, RESOURCES, 0);
13605 send_req(plci);
13606 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13607 break;
13608 }
13609 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13610 Rc = OK;
13611 case ADJUST_B_SWITCH_L1_2:
13612 if ((Rc != OK) && (Rc != OK_FC))
13613 {
13614 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13615 UnMapId(Id), (char *)(FILE_), __LINE__,
13616 Rc, plci->B1_resource, plci->adjust_b_facilities));
13617 Info = _WRONG_STATE;
13618 break;
13619 }
13620 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13621 Rc = OK;
13622 case ADJUST_B_RESTORE_VOICE_1:
13623 case ADJUST_B_RESTORE_VOICE_2:
13624 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13625 {
13626 Info = adv_voice_restore_config(Id, plci, Rc);
13627 if ((Info != GOOD) || plci->internal_command)
13628 break;
13629 }
13630 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13631 Rc = OK;
13632 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13633 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13634 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13635 {
13636
13637 Info = dtmf_parameter_restore_config(Id, plci, Rc);
13638 if ((Info != GOOD) || plci->internal_command)
13639 break;
13640
13641 }
13642 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13643 Rc = OK;
13644 case ADJUST_B_RESTORE_EC_1:
13645 case ADJUST_B_RESTORE_EC_2:
13646 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13647 {
13648
13649 Info = ec_restore_config(Id, plci, Rc);
13650 if ((Info != GOOD) || plci->internal_command)
13651 break;
13652
13653 }
13654 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13655 case ADJUST_B_ASSIGN_L23_1:
13656 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13657 {
13658 if (plci_nl_busy(plci))
13659 {
13660 plci->internal_command = plci->adjust_b_command;
13661 break;
13662 }
13663 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13664 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13665 if (plci->adjust_b_parms_msg != NULL)
13666 api_load_msg(plci->adjust_b_parms_msg, bp);
13667 else
13668 api_load_msg(&plci->B_protocol, bp);
13669 Info = add_b23(plci, bp);
13670 if (Info != GOOD)
13671 {
13672 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13673 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13674 break;
13675 }
13676 plci->internal_command = plci->adjust_b_command;
13677 nl_req_ncci(plci, ASSIGN, 0);
13678 send_req(plci);
13679 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13680 break;
13681 }
13682 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13683 Rc = ASSIGN_OK;
13684 case ADJUST_B_ASSIGN_L23_2:
13685 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13686 {
13687 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13688 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13689 Info = _WRONG_STATE;
13690 break;
13691 }
13692 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13693 {
13694 if (Rc != ASSIGN_OK)
13695 {
13696 plci->internal_command = plci->adjust_b_command;
13697 break;
13698 }
13699 }
13700 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13701 {
13702 plci->adjust_b_restore = true;
13703 break;
13704 }
13705 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13706 case ADJUST_B_CONNECT_1:
13707 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13708 {
13709 plci->internal_command = plci->adjust_b_command;
13710 if (plci_nl_busy(plci))
13711 break;
13712 nl_req_ncci(plci, N_CONNECT, 0);
13713 send_req(plci);
13714 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13715 break;
13716 }
13717 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13718 Rc = OK;
13719 case ADJUST_B_CONNECT_2:
13720 case ADJUST_B_CONNECT_3:
13721 case ADJUST_B_CONNECT_4:
13722 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13723 {
13724 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13725 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13726 Info = _WRONG_STATE;
13727 break;
13728 }
13729 if (Rc == OK)
13730 {
13731 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13732 {
13733 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13734 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13735 }
13736 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13737 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13738 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13739 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13740 }
13741 else if (Rc == 0)
13742 {
13743 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13744 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13745 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13746 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13747 }
13748 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13749 {
13750 plci->internal_command = plci->adjust_b_command;
13751 break;
13752 }
13753 Rc = OK;
13754 case ADJUST_B_RESTORE_DTMF_1:
13755 case ADJUST_B_RESTORE_DTMF_2:
13756 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13757 {
13758
13759 Info = dtmf_restore_config(Id, plci, Rc);
13760 if ((Info != GOOD) || plci->internal_command)
13761 break;
13762
13763 }
13764 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13765 Rc = OK;
13766 case ADJUST_B_RESTORE_MIXER_1:
13767 case ADJUST_B_RESTORE_MIXER_2:
13768 case ADJUST_B_RESTORE_MIXER_3:
13769 case ADJUST_B_RESTORE_MIXER_4:
13770 case ADJUST_B_RESTORE_MIXER_5:
13771 case ADJUST_B_RESTORE_MIXER_6:
13772 case ADJUST_B_RESTORE_MIXER_7:
13773 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13774 {
13775
13776 Info = mixer_restore_config(Id, plci, Rc);
13777 if ((Info != GOOD) || plci->internal_command)
13778 break;
13779
13780 }
13781 plci->adjust_b_state = ADJUST_B_END;
13782 case ADJUST_B_END:
13783 break;
13784 }
13785 return (Info);
13786}
13787
13788
13789static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13790{
13791
13792 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13793 UnMapId(Id), (char *)(FILE_), __LINE__,
13794 plci->B1_resource, b1_facilities));
13795
13796 plci->adjust_b_parms_msg = bp_msg;
13797 plci->adjust_b_facilities = b1_facilities;
13798 plci->adjust_b_command = internal_command;
13799 plci->adjust_b_ncci = (word)(Id >> 16);
13800 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13801 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13802 else
13803 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13804 plci->adjust_b_state = ADJUST_B_START;
13805 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13806 UnMapId(Id), (char *)(FILE_), __LINE__,
13807 plci->B1_resource, b1_facilities));
13808}
13809
13810
13811static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13812{
13813 word internal_command;
13814
13815 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13816 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13817
13818 internal_command = plci->internal_command;
13819 plci->internal_command = 0;
13820 switch (internal_command)
13821 {
13822 default:
13823 plci->command = 0;
13824 if (plci->req_in != 0)
13825 {
13826 plci->internal_command = ADJUST_B_RESTORE_1;
13827 break;
13828 }
13829 Rc = OK;
13830 case ADJUST_B_RESTORE_1:
13831 if ((Rc != OK) && (Rc != OK_FC))
13832 {
13833 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13834 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13835 }
13836 plci->adjust_b_parms_msg = NULL;
13837 plci->adjust_b_facilities = plci->B1_facilities;
13838 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13839 plci->adjust_b_ncci = (word)(Id >> 16);
13840 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13841 plci->adjust_b_state = ADJUST_B_START;
13842 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13843 UnMapId(Id), (char *)(FILE_), __LINE__));
13844 case ADJUST_B_RESTORE_2:
13845 if (adjust_b_process(Id, plci, Rc) != GOOD)
13846 {
13847 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13848 UnMapId(Id), (char *)(FILE_), __LINE__));
13849 }
13850 if (plci->internal_command)
13851 break;
13852 break;
13853 }
13854}
13855
13856
13857static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13858{
13859 word Info;
13860 word internal_command;
13861
13862 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13863 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13864
13865 Info = GOOD;
13866 internal_command = plci->internal_command;
13867 plci->internal_command = 0;
13868 switch (internal_command)
13869 {
13870 default:
13871 plci->command = 0;
13872 plci->adjust_b_parms_msg = NULL;
13873 plci->adjust_b_facilities = plci->B1_facilities;
13874 plci->adjust_b_command = RESET_B3_COMMAND_1;
13875 plci->adjust_b_ncci = (word)(Id >> 16);
13876 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13877 plci->adjust_b_state = ADJUST_B_START;
13878 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13879 UnMapId(Id), (char *)(FILE_), __LINE__));
13880 case RESET_B3_COMMAND_1:
13881 Info = adjust_b_process(Id, plci, Rc);
13882 if (Info != GOOD)
13883 {
13884 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13885 UnMapId(Id), (char *)(FILE_), __LINE__));
13886 break;
13887 }
13888 if (plci->internal_command)
13889 return;
13890 break;
13891 }
13892
13893 sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13894}
13895
13896
13897static void select_b_command(dword Id, PLCI *plci, byte Rc)
13898{
13899 word Info;
13900 word internal_command;
13901 byte esc_chi[3];
13902
13903 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13904 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13905
13906 Info = GOOD;
13907 internal_command = plci->internal_command;
13908 plci->internal_command = 0;
13909 switch (internal_command)
13910 {
13911 default:
13912 plci->command = 0;
13913 plci->adjust_b_parms_msg = &plci->saved_msg;
13914 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13915 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13916 else
13917 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13918 plci->adjust_b_command = SELECT_B_COMMAND_1;
13919 plci->adjust_b_ncci = (word)(Id >> 16);
13920 if (plci->saved_msg.parms[0].length == 0)
13921 {
13922 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13923 ADJUST_B_MODE_NO_RESOURCE;
13924 }
13925 else
13926 {
13927 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13928 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13929 }
13930 plci->adjust_b_state = ADJUST_B_START;
13931 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13932 UnMapId(Id), (char *)(FILE_), __LINE__));
13933 case SELECT_B_COMMAND_1:
13934 Info = adjust_b_process(Id, plci, Rc);
13935 if (Info != GOOD)
13936 {
13937 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13938 UnMapId(Id), (char *)(FILE_), __LINE__));
13939 break;
13940 }
13941 if (plci->internal_command)
13942 return;
13943 if (plci->tel == ADV_VOICE)
13944 {
13945 esc_chi[0] = 0x02;
13946 esc_chi[1] = 0x18;
13947 esc_chi[2] = plci->b_channel;
13948 SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13949 }
13950 break;
13951 }
13952 sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13953}
13954
13955
13956static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13957{
13958 word internal_command;
13959
13960 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
13961 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13962
13963 internal_command = plci->internal_command;
13964 plci->internal_command = 0;
13965 switch (internal_command)
13966 {
13967 default:
13968 plci->command = 0;
13969 case FAX_CONNECT_ACK_COMMAND_1:
13970 if (plci_nl_busy(plci))
13971 {
13972 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
13973 return;
13974 }
13975 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
13976 plci->NData[0].P = plci->fax_connect_info_buffer;
13977 plci->NData[0].PLength = plci->fax_connect_info_length;
13978 plci->NL.X = plci->NData;
13979 plci->NL.ReqCh = 0;
13980 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
13981 plci->adapter->request(&plci->NL);
13982 return;
13983 case FAX_CONNECT_ACK_COMMAND_2:
13984 if ((Rc != OK) && (Rc != OK_FC))
13985 {
13986 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
13987 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13988 break;
13989 }
13990 }
13991 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
13992 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
13993 {
13994 if (plci->B3_prot == 4)
13995 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
13996 else
13997 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
13998 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
13999 }
14000}
14001
14002
14003static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14004{
14005 word internal_command;
14006
14007 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14008 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14009
14010 internal_command = plci->internal_command;
14011 plci->internal_command = 0;
14012 switch (internal_command)
14013 {
14014 default:
14015 plci->command = 0;
14016 case FAX_EDATA_ACK_COMMAND_1:
14017 if (plci_nl_busy(plci))
14018 {
14019 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14020 return;
14021 }
14022 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14023 plci->NData[0].P = plci->fax_connect_info_buffer;
14024 plci->NData[0].PLength = plci->fax_edata_ack_length;
14025 plci->NL.X = plci->NData;
14026 plci->NL.ReqCh = 0;
14027 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14028 plci->adapter->request(&plci->NL);
14029 return;
14030 case FAX_EDATA_ACK_COMMAND_2:
14031 if ((Rc != OK) && (Rc != OK_FC))
14032 {
14033 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14034 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14035 break;
14036 }
14037 }
14038}
14039
14040
14041static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14042{
14043 word Info;
14044 word internal_command;
14045
14046 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14047 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14048
14049 Info = GOOD;
14050 internal_command = plci->internal_command;
14051 plci->internal_command = 0;
14052 switch (internal_command)
14053 {
14054 default:
14055 plci->command = 0;
14056 case FAX_CONNECT_INFO_COMMAND_1:
14057 if (plci_nl_busy(plci))
14058 {
14059 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14060 return;
14061 }
14062 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14063 plci->NData[0].P = plci->fax_connect_info_buffer;
14064 plci->NData[0].PLength = plci->fax_connect_info_length;
14065 plci->NL.X = plci->NData;
14066 plci->NL.ReqCh = 0;
14067 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14068 plci->adapter->request(&plci->NL);
14069 return;
14070 case FAX_CONNECT_INFO_COMMAND_2:
14071 if ((Rc != OK) && (Rc != OK_FC))
14072 {
14073 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14074 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14075 Info = _WRONG_STATE;
14076 break;
14077 }
14078 if (plci_nl_busy(plci))
14079 {
14080 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14081 return;
14082 }
14083 plci->command = _CONNECT_B3_R;
14084 nl_req_ncci(plci, N_CONNECT, 0);
14085 send_req(plci);
14086 return;
14087 }
14088 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14089}
14090
14091
14092static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14093{
14094 word Info;
14095 word internal_command;
14096
14097 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14098 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14099
14100 Info = GOOD;
14101 internal_command = plci->internal_command;
14102 plci->internal_command = 0;
14103 switch (internal_command)
14104 {
14105 default:
14106 plci->command = 0;
14107 plci->adjust_b_parms_msg = NULL;
14108 plci->adjust_b_facilities = plci->B1_facilities;
14109 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14110 plci->adjust_b_ncci = (word)(Id >> 16);
14111 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14112 plci->adjust_b_state = ADJUST_B_START;
14113 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14114 UnMapId(Id), (char *)(FILE_), __LINE__));
14115 case FAX_ADJUST_B23_COMMAND_1:
14116 Info = adjust_b_process(Id, plci, Rc);
14117 if (Info != GOOD)
14118 {
14119 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14120 UnMapId(Id), (char *)(FILE_), __LINE__));
14121 break;
14122 }
14123 if (plci->internal_command)
14124 return;
14125 case FAX_ADJUST_B23_COMMAND_2:
14126 if (plci_nl_busy(plci))
14127 {
14128 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14129 return;
14130 }
14131 plci->command = _CONNECT_B3_R;
14132 nl_req_ncci(plci, N_CONNECT, 0);
14133 send_req(plci);
14134 return;
14135 }
14136 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14137}
14138
14139
14140static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14141{
14142 word internal_command;
14143
14144 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14145 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14146
14147 internal_command = plci->internal_command;
14148 plci->internal_command = 0;
14149 switch (internal_command)
14150 {
14151 default:
14152 plci->command = 0;
14153 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14154 return;
14155 case FAX_DISCONNECT_COMMAND_1:
14156 case FAX_DISCONNECT_COMMAND_2:
14157 case FAX_DISCONNECT_COMMAND_3:
14158 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14159 {
14160 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14161 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14162 break;
14163 }
14164 if (Rc == OK)
14165 {
14166 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14167 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14168 {
14169 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14170 }
14171 }
14172 else if (Rc == 0)
14173 {
14174 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14175 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14176 }
14177 return;
14178 }
14179}
14180
14181
14182
14183static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14184{
14185 word Info;
14186 word internal_command;
14187
14188 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14189 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190
14191 Info = GOOD;
14192 internal_command = plci->internal_command;
14193 plci->internal_command = 0;
14194 switch (internal_command)
14195 {
14196 default:
14197 plci->command = 0;
14198 case RTP_CONNECT_B3_REQ_COMMAND_1:
14199 if (plci_nl_busy(plci))
14200 {
14201 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14202 return;
14203 }
14204 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14205 nl_req_ncci(plci, N_CONNECT, 0);
14206 send_req(plci);
14207 return;
14208 case RTP_CONNECT_B3_REQ_COMMAND_2:
14209 if ((Rc != OK) && (Rc != OK_FC))
14210 {
14211 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14212 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213 Info = _WRONG_STATE;
14214 break;
14215 }
14216 if (plci_nl_busy(plci))
14217 {
14218 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14219 return;
14220 }
14221 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14222 plci->NData[0].PLength = plci->internal_req_buffer[0];
14223 plci->NData[0].P = plci->internal_req_buffer + 1;
14224 plci->NL.X = plci->NData;
14225 plci->NL.ReqCh = 0;
14226 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14227 plci->adapter->request(&plci->NL);
14228 break;
14229 case RTP_CONNECT_B3_REQ_COMMAND_3:
14230 return;
14231 }
14232 sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233}
14234
14235
14236static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14237{
14238 word internal_command;
14239
14240 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14241 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14242
14243 internal_command = plci->internal_command;
14244 plci->internal_command = 0;
14245 switch (internal_command)
14246 {
14247 default:
14248 plci->command = 0;
14249 case RTP_CONNECT_B3_RES_COMMAND_1:
14250 if (plci_nl_busy(plci))
14251 {
14252 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14253 return;
14254 }
14255 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14256 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14257 send_req(plci);
14258 return;
14259 case RTP_CONNECT_B3_RES_COMMAND_2:
14260 if ((Rc != OK) && (Rc != OK_FC))
14261 {
14262 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14263 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14264 break;
14265 }
14266 if (plci_nl_busy(plci))
14267 {
14268 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14269 return;
14270 }
14271 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14272 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14273 plci->NData[0].PLength = plci->internal_req_buffer[0];
14274 plci->NData[0].P = plci->internal_req_buffer + 1;
14275 plci->NL.X = plci->NData;
14276 plci->NL.ReqCh = 0;
14277 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14278 plci->adapter->request(&plci->NL);
14279 return;
14280 case RTP_CONNECT_B3_RES_COMMAND_3:
14281 return;
14282 }
14283}
14284
14285
14286
14287static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14288{
14289 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00";
14290 word Info;
14291 word internal_command;
14292
14293 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14294 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14295
14296 Info = GOOD;
14297 internal_command = plci->internal_command;
14298 plci->internal_command = 0;
14299 switch (internal_command)
14300 {
14301 default:
14302 if (!plci->NL.Id)
14303 break;
14304 plci->command = 0;
14305 plci->adjust_b_parms_msg = NULL;
14306 plci->adjust_b_facilities = plci->B1_facilities;
14307 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14308 plci->adjust_b_ncci = (word)(Id >> 16);
14309 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14310 plci->adjust_b_state = ADJUST_B_START;
14311 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14312 UnMapId(Id), (char *)(FILE_), __LINE__));
14313 case HOLD_SAVE_COMMAND_1:
14314 Info = adjust_b_process(Id, plci, Rc);
14315 if (Info != GOOD)
14316 {
14317 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14318 UnMapId(Id), (char *)(FILE_), __LINE__));
14319 break;
14320 }
14321 if (plci->internal_command)
14322 return;
14323 }
14324 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14325}
14326
14327
14328static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14329{
14330 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00";
14331 word Info;
14332 word internal_command;
14333
14334 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14335 UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14336
14337 Info = GOOD;
14338 internal_command = plci->internal_command;
14339 plci->internal_command = 0;
14340 switch (internal_command)
14341 {
14342 default:
14343 plci->command = 0;
14344 plci->adjust_b_parms_msg = NULL;
14345 plci->adjust_b_facilities = plci->B1_facilities;
14346 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14347 plci->adjust_b_ncci = (word)(Id >> 16);
14348 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14349 plci->adjust_b_state = ADJUST_B_START;
14350 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14351 UnMapId(Id), (char *)(FILE_), __LINE__));
14352 case RETRIEVE_RESTORE_COMMAND_1:
14353 Info = adjust_b_process(Id, plci, Rc);
14354 if (Info != GOOD)
14355 {
14356 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14357 UnMapId(Id), (char *)(FILE_), __LINE__));
14358 break;
14359 }
14360 if (plci->internal_command)
14361 return;
14362 }
14363 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14364}
14365
14366
14367static void init_b1_config(PLCI *plci)
14368{
14369
14370 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14371 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14372 (char *)(FILE_), __LINE__));
14373
14374 plci->B1_resource = 0;
14375 plci->B1_facilities = 0;
14376
14377 plci->li_bchannel_id = 0;
14378 mixer_clear_config(plci);
14379
14380
14381 ec_clear_config(plci);
14382
14383
14384 dtmf_rec_clear_config(plci);
14385 dtmf_send_clear_config(plci);
14386 dtmf_parameter_clear_config(plci);
14387
14388 adv_voice_clear_config(plci);
14389 adjust_b_clear(plci);
14390}
14391
14392
14393static void clear_b1_config(PLCI *plci)
14394{
14395
14396 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14397 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14398 (char *)(FILE_), __LINE__));
14399
14400 adv_voice_clear_config(plci);
14401 adjust_b_clear(plci);
14402
14403 ec_clear_config(plci);
14404
14405
14406 dtmf_rec_clear_config(plci);
14407 dtmf_send_clear_config(plci);
14408 dtmf_parameter_clear_config(plci);
14409
14410
14411 if ((plci->li_bchannel_id != 0)
14412 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14413 {
14414 mixer_clear_config(plci);
14415 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14416 plci->li_bchannel_id = 0;
14417 }
14418
14419 plci->B1_resource = 0;
14420 plci->B1_facilities = 0;
14421}
14422
14423
14424
14425
14426
14427static void channel_flow_control_remove(PLCI *plci) {
14428 DIVA_CAPI_ADAPTER *a = plci->adapter;
14429 word i;
14430 for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14431 if (a->ch_flow_plci[i] == plci->Id) {
14432 a->ch_flow_plci[i] = 0;
14433 a->ch_flow_control[i] = 0;
14434 }
14435 }
14436}
14437
14438static void channel_x_on(PLCI *plci, byte ch) {
14439 DIVA_CAPI_ADAPTER *a = plci->adapter;
14440 if (a->ch_flow_control[ch] & N_XON_SENT) {
14441 a->ch_flow_control[ch] &= ~N_XON_SENT;
14442 }
14443}
14444
14445static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14446 DIVA_CAPI_ADAPTER *a = plci->adapter;
14447 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14448 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14449 a->ch_flow_plci[ch] = plci->Id;
14450 a->ch_flow_control_pending++;
14451 }
14452}
14453
14454static void channel_request_xon(PLCI *plci, byte ch) {
14455 DIVA_CAPI_ADAPTER *a = plci->adapter;
14456
14457 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14458 a->ch_flow_control[ch] |= N_XON_REQ;
14459 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14460 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14461 }
14462}
14463
14464static void channel_xmit_extended_xon(PLCI *plci) {
14465 DIVA_CAPI_ADAPTER *a;
14466 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14467 int i, one_requested = 0;
14468
14469 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14470 return;
14471 }
14472
14473 for (i = 0; i < max_ch; i++) {
14474 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14475 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14476 (plci->Id == a->ch_flow_plci[i])) {
14477 channel_request_xon(plci, (byte)i);
14478 one_requested = 1;
14479 }
14480 }
14481
14482 if (one_requested) {
14483 channel_xmit_xon(plci);
14484 }
14485}
14486
14487
14488
14489
14490static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14491 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14492 int i;
14493
14494 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14495 return (0);
14496 }
14497
14498 if (a->last_flow_control_ch >= max_ch) {
14499 a->last_flow_control_ch = 1;
14500 }
14501 for (i = a->last_flow_control_ch; i < max_ch; i++) {
14502 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14503 (plci->Id == a->ch_flow_plci[i])) {
14504 a->last_flow_control_ch = i + 1;
14505 return (i);
14506 }
14507 }
14508
14509 for (i = 1; i < a->last_flow_control_ch; i++) {
14510 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14511 (plci->Id == a->ch_flow_plci[i])) {
14512 a->last_flow_control_ch = i + 1;
14513 return (i);
14514 }
14515 }
14516
14517 return (0);
14518}
14519
14520static void channel_xmit_xon(PLCI *plci) {
14521 DIVA_CAPI_ADAPTER *a = plci->adapter;
14522 byte ch;
14523
14524 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14525 return;
14526 }
14527 if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14528 return;
14529 }
14530 a->ch_flow_control[ch] &= ~N_XON_REQ;
14531 a->ch_flow_control[ch] |= N_XON_SENT;
14532
14533 plci->NL.Req = plci->nl_req = (byte)N_XON;
14534 plci->NL.ReqCh = ch;
14535 plci->NL.X = plci->NData;
14536 plci->NL.XNum = 1;
14537 plci->NData[0].P = &plci->RBuffer[0];
14538 plci->NData[0].PLength = 0;
14539
14540 plci->adapter->request(&plci->NL);
14541}
14542
14543static int channel_can_xon(PLCI *plci, byte ch) {
14544 APPL *APPLptr;
14545 DIVA_CAPI_ADAPTER *a;
14546 word NCCIcode;
14547 dword count;
14548 word Num;
14549 word i;
14550
14551 APPLptr = plci->appl;
14552 a = plci->adapter;
14553
14554 if (!APPLptr)
14555 return (0);
14556
14557 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14558
14559
14560
14561
14562 count = 0;
14563 Num = 0xffff;
14564 for (i = 0; i < APPLptr->MaxBuffer; i++) {
14565 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14566 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14567 }
14568 if ((count > 2) || (Num == 0xffff)) {
14569 return (0);
14570 }
14571 return (1);
14572}
14573
14574
14575
14576
14577static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14578{
14579 return 1;
14580}
14581
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14593{
14594 word i, j, k, busy, group_found;
14595 dword info_mask_group[MAX_CIP_TYPES];
14596 dword cip_mask_group[MAX_CIP_TYPES];
14597 word appl_number_group_type[MAX_APPL];
14598 PLCI *auxplci;
14599
14600
14601 bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14602
14603 if (!a->group_optimization_enabled)
14604 {
14605 dbug(1, dprintf("No group optimization"));
14606 return;
14607 }
14608
14609 dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14610
14611 for (i = 0; i < MAX_CIP_TYPES; i++)
14612 {
14613 info_mask_group[i] = 0;
14614 cip_mask_group[i] = 0;
14615 }
14616 for (i = 0; i < MAX_APPL; i++)
14617 {
14618 appl_number_group_type[i] = 0;
14619 }
14620 for (i = 0; i < max_appl; i++)
14621 {
14622 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14623 {
14624 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14625 return;
14626 }
14627 }
14628 for (i = 0; i < max_appl; i++)
14629 {
14630 if (application[i].Id && a->CIP_Mask[i])
14631 {
14632 for (k = 0, busy = false; k < a->max_plci; k++)
14633 {
14634 if (a->plci[k].Id)
14635 {
14636 auxplci = &a->plci[k];
14637 if (auxplci->appl == &application[i]) {
14638
14639 busy = true;
14640 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14641 } else if (test_bit(i, plci->c_ind_mask_table)) {
14642
14643 busy = true;
14644 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14645 }
14646 }
14647 }
14648
14649 for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)
14650 {
14651 if (j == MAX_CIP_TYPES)
14652 {
14653 appl_number_group_type[i] = MAX_CIP_TYPES;
14654 group_found = true;
14655 dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14656 }
14657 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14658 {
14659 appl_number_group_type[i] = j | 0x80;
14660 group_found = true;
14661 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]));
14662 }
14663 else if (!info_mask_group[j])
14664 {
14665 appl_number_group_type[i] = j | 0x80;
14666 info_mask_group[j] = a->CIP_Mask[i];
14667 cip_mask_group[j] = a->Info_Mask[i];
14668 group_found = true;
14669 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]));
14670 }
14671 }
14672 }
14673 }
14674
14675 for (i = 0; i < max_appl; i++)
14676 {
14677 if (appl_number_group_type[i])
14678 {
14679 if (appl_number_group_type[i] == MAX_CIP_TYPES)
14680 {
14681 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14682 }
14683 else
14684 {
14685 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14686 for (j = i + 1; j < max_appl; j++)
14687 {
14688 if (appl_number_group_type[i] == appl_number_group_type[j])
14689 {
14690 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14691
14692 __clear_bit(j, plci->group_optimization_mask_table);
14693 appl_number_group_type[j] = 0;
14694 }
14695 }
14696 }
14697 }
14698 else
14699 {
14700 __clear_bit(i, plci->group_optimization_mask_table);
14701 }
14702 }
14703
14704}
14705
14706
14707
14708
14709word CapiRegister(word id)
14710{
14711 word i, j, appls_found;
14712
14713 PLCI *plci;
14714 DIVA_CAPI_ADAPTER *a;
14715
14716 for (i = 0, appls_found = 0; i < max_appl; i++)
14717 {
14718 if (application[i].Id && (application[i].Id != id))
14719 {
14720 appls_found++;
14721 }
14722 }
14723
14724 if (appls_found) return true;
14725 for (i = 0; i < max_adapter; i++)
14726 {
14727 a = &adapter[i];
14728 if (a->request)
14729 {
14730 if (a->flag_dynamic_l1_down)
14731 {
14732 if (!appls_found)
14733 {
14734 if ((j = get_plci(a)))
14735 {
14736 plci = &a->plci[j - 1];
14737 plci->command = 0;
14738 add_p(plci, OAD, "\x01\xfd");
14739 add_p(plci, CAI, "\x01\x80");
14740 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14741 add_p(plci, SHIFT | 6, NULL);
14742 add_p(plci, SIN, "\x02\x00\x00");
14743 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14744 sig_req(plci, ASSIGN, DSIG_ID);
14745 add_p(plci, FTY, "\x02\xff\x07");
14746 sig_req(plci, SIG_CTRL, 0);
14747 send_req(plci);
14748 }
14749 }
14750 }
14751 }
14752 }
14753 return false;
14754}
14755
14756
14757
14758
14759
14760static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14761{
14762 word i;
14763
14764
14765
14766
14767
14768
14769
14770
14771
14772 if (!plci ||
14773 !plci->appl ||
14774 !plci->State ||
14775 plci->Sig.Ind == NCR_FACILITY
14776 )
14777 return;
14778
14779 for (i = 0; i < MAX_MULTI_IE; i++)
14780 {
14781 if (!parms[i][0]) continue;
14782 if (parms[i][0] < 7)
14783 {
14784 parms[i][0] = 0;
14785 continue;
14786 }
14787 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14788 switch (parms[i][4])
14789 {
14790 case VSJOIN:
14791 if (!plci->relatedPTYPLCI ||
14792 (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14793 {
14794 break;
14795 }
14796
14797 if (parms[i][0] != 11 || parms[i][8] != 3)
14798 {
14799 break;
14800 }
14801 if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14802 {
14803 plci->vswitchstate = parms[i][9];
14804 parms[i][9] = 2;
14805
14806 }
14807 else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14808 {
14809 plci->vswitchstate = parms[i][9];
14810
14811
14812 }
14813 else
14814 {
14815 break;
14816 }
14817 plci->vsprot = parms[i][10];
14818 plci->vsprotdialect = parms[i][11];
14819
14820 parms[i][1] = VSWITCHIE;
14821 parms[i][2] = VSWITCH_REQ;
14822
14823 plci->relatedPTYPLCI->command = 0;
14824 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14825 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14826 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14827 send_req(plci->relatedPTYPLCI);
14828 break;
14829 case VSTRANSPORT:
14830 default:
14831 if (plci->relatedPTYPLCI &&
14832 plci->vswitchstate == 3 &&
14833 plci->relatedPTYPLCI->vswitchstate == 3)
14834 {
14835 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14836 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14837 send_req(plci->relatedPTYPLCI);
14838 }
14839 break;
14840 }
14841 parms[i][0] = 0;
14842 }
14843}
14844
14845
14846
14847
14848static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14849 ENTITY e;
14850 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14851
14852 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14853 return (-1);
14854 }
14855
14856 pReq->xdi_dma_descriptor_operation.Req = 0;
14857 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14858
14859 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14860 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14861 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14862 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14863
14864 e.user[0] = plci->adapter->Id - 1;
14865 plci->adapter->request((ENTITY *)pReq);
14866
14867 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14868 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14869 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14870 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14871 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14872 plci->adapter->Id,
14873 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14874 *dma_magic));
14875 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14876 } else {
14877 dbug(1, dprintf("dma_alloc failed"));
14878 return (-1);
14879 }
14880}
14881
14882static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14883 ENTITY e;
14884 IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14885
14886 if (nr < 0) {
14887 return;
14888 }
14889
14890 pReq->xdi_dma_descriptor_operation.Req = 0;
14891 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14892
14893 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14894 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
14895 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14896 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
14897
14898 e.user[0] = plci->adapter->Id - 1;
14899 plci->adapter->request((ENTITY *)pReq);
14900
14901 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14902 dbug(1, dprintf("dma_free(%d)", nr));
14903 } else {
14904 dbug(1, dprintf("dma_free failed (%d)", nr));
14905 }
14906}
14907
14908
14909