Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
message.c
Go to the documentation of this file.
1 /*
2  *
3  Copyright (c) Eicon Networks, 2002.
4  *
5  This source file is supplied for the use with
6  Eicon Networks range of DIVA Server Adapters.
7  *
8  Eicon File Revision : 2.1
9  *
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2, or (at your option)
13  any later version.
14  *
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  See the GNU General Public License for more details.
19  *
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 
27 
28 
29 
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37 
38 
39 
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter */
55 /* Macrose defined here have only local meaning */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58 
59 #define DIVA_CAPI_USE_CMA 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
63 
64 /*
65  CAPI can request to process all return codes self only if:
66  protocol code supports this && xdi supports this
67 */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69 
70 /*------------------------------------------------------------------*/
71 /* local function prototypes */
72 /*------------------------------------------------------------------*/
73 
74 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
75 static void set_group_ind_mask(PLCI *plci);
76 static void clear_group_ind_mask_bit(PLCI *plci, word b);
77 static byte test_group_ind_mask_bit(PLCI *plci, word b);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
85 
87 void api_remove_complete(void);
88 
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
92 
93 void callback(ENTITY *);
94 
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte **, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
101 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
102 
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
104 
105 static void nl_ind(PLCI *);
106 
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131 
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI *plci, byte code, API_PARSE *p);
135 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
136 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
154 
155 /*
156  XON protocol helpers
157 */
158 static void channel_flow_control_remove(PLCI *plci);
159 static void channel_x_off(PLCI *plci, byte ch, byte flag);
160 static void channel_x_on(PLCI *plci, byte ch);
161 static void channel_request_xon(PLCI *plci, byte ch);
162 static void channel_xmit_xon(PLCI *plci);
163 static int channel_can_xon(PLCI *plci, byte ch);
164 static void channel_xmit_extended_xon(PLCI *plci);
165 
166 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs(PLCI *plci, word write_command);
172 static void adv_voice_clear_config(PLCI *plci);
173 
174 static word get_b1_facilities(PLCI *plci, byte b1_resource);
175 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
181 static void select_b_command(dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config(PLCI *plci);
190 static void clear_b1_config(PLCI *plci);
191 
192 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation(dword Id, PLCI *plci);
195 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write(PLCI *plci);
197 
198 
199 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
201 static void mixer_clear_config(PLCI *plci);
202 static void mixer_notify_update(PLCI *plci, byte others);
203 static void mixer_command(dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove(PLCI *plci);
209 
210 
211 static void ec_command(dword Id, PLCI *plci, byte Rc);
212 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
214 
215 
216 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
218 
219 
220 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor(PLCI *plci, int nr);
222 
223 /*------------------------------------------------------------------*/
224 /* external function prototypes */
225 /*------------------------------------------------------------------*/
226 
227 extern byte MapController(byte);
228 extern byte UnMapController(byte);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
231 
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void *TransmitBufferSet(APPL *appl, dword ref);
234 void *TransmitBufferGet(APPL *appl, void *p);
235 void TransmitBufferFree(APPL *appl, void *p);
236 void *ReceiveBufferGet(APPL *appl, int Num);
237 
238 int fax_head_line_time(char *buffer);
239 
240 
241 /*------------------------------------------------------------------*/
242 /* Global data definitions */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER *adapter;
247 extern APPL *application;
248 
249 
250 
251 
252 
253 
254 
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257 
258 
259 static struct _ftable {
260  word command;
261  byte *format;
262  byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263 } ftable[] = {
264  {_DATA_B3_R, "dwww", data_b3_req},
265  {_DATA_B3_I | RESPONSE, "w", data_b3_res},
266  {_INFO_R, "ss", info_req},
267  {_INFO_I | RESPONSE, "", info_res},
268  {_CONNECT_R, "wsssssssss", connect_req},
269  {_CONNECT_I | RESPONSE, "wsssss", connect_res},
270  {_CONNECT_ACTIVE_I | RESPONSE, "", connect_a_res},
272  {_DISCONNECT_I | RESPONSE, "", disconnect_res},
273  {_LISTEN_R, "dddss", listen_req},
274  {_ALERT_R, "s", alert_req},
275  {_FACILITY_R, "ws", facility_req},
276  {_FACILITY_I | RESPONSE, "ws", facility_res},
277  {_CONNECT_B3_R, "s", connect_b3_req},
278  {_CONNECT_B3_I | RESPONSE, "ws", connect_b3_res},
279  {_CONNECT_B3_ACTIVE_I | RESPONSE, "", connect_b3_a_res},
280  {_DISCONNECT_B3_R, "s", disconnect_b3_req},
281  {_DISCONNECT_B3_I | RESPONSE, "", disconnect_b3_res},
282  {_RESET_B3_R, "s", reset_b3_req},
283  {_RESET_B3_I | RESPONSE, "", reset_b3_res},
284  {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws", connect_b3_t90_a_res},
285  {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "", connect_b3_t90_a_res},
286  {_SELECT_B_REQ, "s", select_b_req},
287  {_MANUFACTURER_R, "dws", manufacturer_req},
288  {_MANUFACTURER_I | RESPONSE, "dws", manufacturer_res},
289  {_MANUFACTURER_I | RESPONSE, "", manufacturer_res}
290 };
291 
292 static byte *cip_bc[29][2] = {
293  { "", "" }, /* 0 */
294  { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
295  { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
296  { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
297  { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
298  { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
299  { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
300  { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301  { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302  { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
303  { "", "" }, /* 10 */
304  { "", "" }, /* 11 */
305  { "", "" }, /* 12 */
306  { "", "" }, /* 13 */
307  { "", "" }, /* 14 */
308  { "", "" }, /* 15 */
309 
310  { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
311  { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
312  { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
313  { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
314  { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
315  { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
316  { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
317  { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
318  { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
319  { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
320  { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
321  { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
322  { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
323 };
324 
325 static byte *cip_hlc[29] = {
326  "", /* 0 */
327  "", /* 1 */
328  "", /* 2 */
329  "", /* 3 */
330  "", /* 4 */
331  "", /* 5 */
332  "", /* 6 */
333  "", /* 7 */
334  "", /* 8 */
335  "", /* 9 */
336  "", /* 10 */
337  "", /* 11 */
338  "", /* 12 */
339  "", /* 13 */
340  "", /* 14 */
341  "", /* 15 */
342 
343  "\x02\x91\x81", /* 16 */
344  "\x02\x91\x84", /* 17 */
345  "\x02\x91\xa1", /* 18 */
346  "\x02\x91\xa4", /* 19 */
347  "\x02\x91\xa8", /* 20 */
348  "\x02\x91\xb1", /* 21 */
349  "\x02\x91\xb2", /* 22 */
350  "\x02\x91\xb5", /* 23 */
351  "\x02\x91\xb8", /* 24 */
352  "\x02\x91\xc1", /* 25 */
353  "\x02\x91\x81", /* 26 */
354  "\x03\x91\xe0\x01", /* 27 */
355  "\x03\x91\xe0\x02" /* 28 */
356 };
357 
358 /*------------------------------------------------------------------*/
359 
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT 0x80
362 #define V120_HEADER_BREAK_BIT 0x40
363 #define V120_HEADER_C1_BIT 0x04
364 #define V120_HEADER_C2_BIT 0x08
365 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366 
367 static byte v120_default_header[] =
368 {
369 
370  0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
371 
372 };
373 
374 static byte v120_break_header[] =
375 {
376 
377  0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
378 
379 };
380 
381 
382 /*------------------------------------------------------------------*/
383 /* API_PUT function */
384 /*------------------------------------------------------------------*/
385 
387 {
388  word i, j, k, l, n;
389  word ret;
390  byte c;
393  PLCI *plci;
394  NCCI *ncci_ptr;
395  word ncci;
396  CAPI_MSG *m;
397  API_PARSE msg_parms[MAX_MSG_PARMS + 1];
398 
399  if (msg->header.length < sizeof(msg->header) ||
400  msg->header.length > MAX_MSG_SIZE) {
401  dbug(1, dprintf("bad len"));
402  return _BAD_MSG;
403  }
404 
405  controller = (byte)((msg->header.controller & 0x7f) - 1);
406 
407  /* controller starts with 0 up to (max_adapter - 1) */
408  if (controller >= max_adapter)
409  {
410  dbug(1, dprintf("invalid ctrl"));
411  return _BAD_MSG;
412  }
413 
414  a = &adapter[controller];
415  plci = NULL;
416  if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417  {
418  dbug(1, dprintf("plci=%x", msg->header.plci));
419  plci = &a->plci[msg->header.plci - 1];
420  ncci = GET_WORD(&msg->header.ncci);
421  if (plci->Id
422  && (plci->appl
423  || (plci->State == INC_CON_PENDING)
424  || (plci->State == INC_CON_ALERT)
425  || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
426  && ((ncci == 0)
427  || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
428  || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
429  {
430  i = plci->msg_in_read_pos;
431  j = plci->msg_in_write_pos;
432  if (j >= i)
433  {
434  if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435  i += MSG_IN_QUEUE_SIZE - j;
436  else
437  j = 0;
438  }
439  else
440  {
441 
442  n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443 
444  if (i > MSG_IN_QUEUE_SIZE - n)
445  i = MSG_IN_QUEUE_SIZE - n + 1;
446  i -= j;
447  }
448 
449  if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450 
451  {
452  dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453  msg->header.length, plci->msg_in_write_pos,
454  plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455 
456  return _QUEUE_FULL;
457  }
458  c = false;
459  if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460  || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461  {
462  if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463  c = true;
464  }
465  if (msg->header.command == _DATA_B3_R)
466  {
467  if (msg->header.length < 20)
468  {
469  dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470  return _BAD_MSG;
471  }
472  ncci_ptr = &(a->ncci[ncci]);
473  n = ncci_ptr->data_pending;
474  l = ncci_ptr->data_ack_pending;
475  k = plci->msg_in_read_pos;
476  while (k != plci->msg_in_write_pos)
477  {
478  if (k == plci->msg_in_wrap_pos)
479  k = 0;
480  if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481  && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482  {
483  n++;
484  if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485  l++;
486  }
487 
488  k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489  MSG_IN_OVERHEAD + 3) & 0xfffc;
490 
491  }
492  if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493  {
494  dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495  ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496 
497  return _QUEUE_FULL;
498  }
499  if (plci->req_in || plci->internal_command)
500  {
501  if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502  && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503  {
504  dbug(0, dprintf("Q-FULL3(requeue)"));
505 
506  return _QUEUE_FULL;
507  }
508  c = true;
509  }
510  }
511  else
512  {
513  if (plci->req_in || plci->internal_command)
514  c = true;
515  else
516  {
517  plci->command = msg->header.command;
518  plci->number = msg->header.number;
519  }
520  }
521  if (c)
522  {
523  dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524  msg->header.command, plci->req_in, plci->internal_command,
525  msg->header.length, plci->msg_in_write_pos,
526  plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527  if (j == 0)
528  plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529  m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530  for (i = 0; i < msg->header.length; i++)
531  ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532  if (m->header.command == _DATA_B3_R)
533  {
534 
536 
537  }
538 
539  j = (j + 3) & 0xfffc;
540 
541  *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542  plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543  return 0;
544  }
545  }
546  else
547  {
548  plci = NULL;
549  }
550  }
551  dbug(1, dprintf("com=%x", msg->header.command));
552 
553  for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
554  for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555 
556  if (ftable[i].command == msg->header.command) {
557  /* break loop if the message is correct, otherwise continue scan */
558  /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
559  if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
560  ret = 0;
561  break;
562  }
563  for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
564  }
565  }
566  if (ret) {
567  dbug(1, dprintf("BAD_MSG"));
568  if (plci) plci->command = 0;
569  return ret;
570  }
571 
572 
573  c = ftable[i].function(GET_DWORD(&msg->header.controller),
574  msg->header.number,
575  a,
576  plci,
577  appl,
578  msg_parms);
579 
580  channel_xmit_extended_xon(plci);
581 
582  if (c == 1) send_req(plci);
583  if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584  if (plci && !plci->req_in) plci->command = 0;
585  return 0;
586 }
587 
588 
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages */
591 /*------------------------------------------------------------------*/
592 
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595  word i;
596  word p;
597 
598  for (i = 0, p = 0; format[i]; i++) {
599  if (parms)
600  {
601  parms[i].info = &msg[p];
602  }
603  switch (format[i]) {
604  case 'b':
605  p += 1;
606  break;
607  case 'w':
608  p += 2;
609  break;
610  case 'd':
611  p += 4;
612  break;
613  case 's':
614  if (msg[p] == 0xff) {
615  parms[i].info += 2;
616  parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617  p += (parms[i].length + 3);
618  }
619  else {
620  parms[i].length = msg[p];
621  p += (parms[i].length + 1);
622  }
623  break;
624  }
625 
626  if (p > length) return true;
627  }
628  if (parms) parms[i].info = NULL;
629  return false;
630 }
631 
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634  word i, j, n = 0;
635  byte *p;
636 
637  p = out->info;
638  for (i = 0; format[i] != '\0'; i++)
639  {
640  out->parms[i].info = p;
641  out->parms[i].length = in[i].length;
642  switch (format[i])
643  {
644  case 'b':
645  n = 1;
646  break;
647  case 'w':
648  n = 2;
649  break;
650  case 'd':
651  n = 4;
652  break;
653  case 's':
654  n = in[i].length + 1;
655  break;
656  }
657  for (j = 0; j < n; j++)
658  *(p++) = in[i].info[j];
659  }
660  out->parms[i].info = NULL;
661  out->parms[i].length = 0;
662 }
663 
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666  word i;
667 
668  i = 0;
669  do
670  {
671  out[i].info = in->parms[i].info;
672  out[i].length = in->parms[i].length;
673  } while (in->parms[i++].info);
674 }
675 
676 
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function */
679 /*------------------------------------------------------------------*/
680 
682 {
683  word i;
684  word j;
685 
686  if (!remove_started) {
687  remove_started = true;
688  for (i = 0; i < max_adapter; i++) {
689  if (adapter[i].request) {
690  for (j = 0; j < adapter[i].max_plci; j++) {
691  if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692  }
693  }
694  }
695  return 1;
696  }
697  else {
698  for (i = 0; i < max_adapter; i++) {
699  if (adapter[i].request) {
700  for (j = 0; j < adapter[i].max_plci; j++) {
701  if (adapter[i].plci[j].Sig.Id) return 1;
702  }
703  }
704  }
705  }
707  return 0;
708 }
709 
710 
711 /*------------------------------------------------------------------*/
712 /* internal command queue */
713 /*------------------------------------------------------------------*/
714 
715 static void init_internal_command_queue(PLCI *plci)
716 {
717  word i;
718 
719  dbug(1, dprintf("%s,%d: init_internal_command_queue",
720  (char *)(FILE_), __LINE__));
721 
722  plci->internal_command = 0;
723  for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724  plci->internal_command_queue[i] = NULL;
725 }
726 
727 
728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
729 {
730  word i;
731 
732  dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733  UnMapId(Id), (char *)(FILE_), __LINE__));
734 
735  if (plci->internal_command == 0)
736  {
737  plci->internal_command_queue[0] = command_function;
738  (*command_function)(Id, plci, OK);
739  }
740  else
741  {
742  i = 1;
743  while (plci->internal_command_queue[i] != NULL)
744  i++;
745  plci->internal_command_queue[i] = command_function;
746  }
747 }
748 
749 
750 static void next_internal_command(dword Id, PLCI *plci)
751 {
752  word i;
753 
754  dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755  UnMapId(Id), (char *)(FILE_), __LINE__));
756 
757  plci->internal_command = 0;
758  plci->internal_command_queue[0] = NULL;
759  while (plci->internal_command_queue[1] != NULL)
760  {
761  for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762  plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763  plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764  (*(plci->internal_command_queue[0]))(Id, plci, OK);
765  if (plci->internal_command != 0)
766  return;
767  plci->internal_command_queue[0] = NULL;
768  }
769 }
770 
771 
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function */
774 /*------------------------------------------------------------------*/
775 
776 static dword ncci_mapping_bug = 0;
777 
778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
779 {
781  word ncci, i, j, k;
782 
783  a = plci->adapter;
784  if (!ch || a->ch_ncci[ch])
785  {
786  ncci_mapping_bug++;
787  dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788  ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789  ncci = ch;
790  }
791  else
792  {
793  if (force_ncci)
794  ncci = force_ncci;
795  else
796  {
797  if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
798  ncci = ch;
799  else
800  {
801  ncci = 1;
802  while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
803  ncci++;
804  if (ncci == MAX_NCCI + 1)
805  {
806  ncci_mapping_bug++;
807  i = 1;
808  do
809  {
810  j = 1;
811  while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
812  j++;
813  k = j;
814  if (j < MAX_NCCI + 1)
815  {
816  do
817  {
818  j++;
819  } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
820  }
821  } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822  if (i < MAX_NL_CHANNEL + 1)
823  {
824  dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825  ncci_mapping_bug, ch, force_ncci, i, k, j));
826  }
827  else
828  {
829  dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830  ncci_mapping_bug, ch, force_ncci));
831  }
832  ncci = ch;
833  }
834  }
835  a->ncci_plci[ncci] = plci->Id;
836  a->ncci_state[ncci] = IDLE;
837  if (!plci->ncci_ring_list)
838  plci->ncci_ring_list = ncci;
839  else
840  a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841  a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842  }
843  a->ncci_ch[ncci] = ch;
844  a->ch_ncci[ch] = (byte) ncci;
845  dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846  ncci_mapping_bug, ch, force_ncci, ch, ncci));
847  }
848  return (ncci);
849 }
850 
851 
852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
853 {
855  APPL *appl;
856  word i, ncci_code;
857  dword Id;
858 
859  a = plci->adapter;
860  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861  if (ncci)
862  {
863  if (a->ncci_plci[ncci] == plci->Id)
864  {
865  if (!plci->appl)
866  {
867  ncci_mapping_bug++;
868  dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869  ncci_mapping_bug, Id));
870  }
871  else
872  {
873  appl = plci->appl;
874  ncci_code = ncci | (((word) a->Id) << 8);
875  for (i = 0; i < appl->MaxBuffer; i++)
876  {
877  if ((appl->DataNCCI[i] == ncci_code)
878  && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879  {
880  appl->DataNCCI[i] = 0;
881  }
882  }
883  }
884  }
885  }
886  else
887  {
888  for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
889  {
890  if (a->ncci_plci[ncci] == plci->Id)
891  {
892  if (!plci->appl)
893  {
894  ncci_mapping_bug++;
895  dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896  ncci_mapping_bug, Id));
897  }
898  else
899  {
900  appl = plci->appl;
901  ncci_code = ncci | (((word) a->Id) << 8);
902  for (i = 0; i < appl->MaxBuffer; i++)
903  {
904  if ((appl->DataNCCI[i] == ncci_code)
905  && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906  {
907  appl->DataNCCI[i] = 0;
908  }
909  }
910  }
911  }
912  }
913  }
914 }
915 
916 
917 static void cleanup_ncci_data(PLCI *plci, word ncci)
918 {
919  NCCI *ncci_ptr;
920 
921  if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922  {
923  ncci_ptr = &(plci->adapter->ncci[ncci]);
924  if (plci->appl)
925  {
926  while (ncci_ptr->data_pending != 0)
927  {
928  if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929  TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930  (ncci_ptr->data_out)++;
931  if (ncci_ptr->data_out == MAX_DATA_B3)
932  ncci_ptr->data_out = 0;
933  (ncci_ptr->data_pending)--;
934  }
935  }
936  ncci_ptr->data_out = 0;
937  ncci_ptr->data_pending = 0;
938  ncci_ptr->data_ack_out = 0;
939  ncci_ptr->data_ack_pending = 0;
940  }
941 }
942 
943 
944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
945 {
947  dword Id;
948  word i;
949 
950  a = plci->adapter;
951  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952  if (!preserve_ncci)
953  ncci_free_receive_buffers(plci, ncci);
954  if (ncci)
955  {
956  if (a->ncci_plci[ncci] != plci->Id)
957  {
958  ncci_mapping_bug++;
959  dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960  ncci_mapping_bug, Id, preserve_ncci));
961  }
962  else
963  {
964  cleanup_ncci_data(plci, ncci);
965  dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966  ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967  a->ch_ncci[a->ncci_ch[ncci]] = 0;
968  if (!preserve_ncci)
969  {
970  a->ncci_ch[ncci] = 0;
971  a->ncci_plci[ncci] = 0;
972  a->ncci_state[ncci] = IDLE;
973  i = plci->ncci_ring_list;
974  while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975  i = a->ncci_next[i];
976  if ((i != 0) && (a->ncci_next[i] == ncci))
977  {
978  if (i == ncci)
979  plci->ncci_ring_list = 0;
980  else if (plci->ncci_ring_list == ncci)
981  plci->ncci_ring_list = i;
982  a->ncci_next[i] = a->ncci_next[ncci];
983  }
984  a->ncci_next[ncci] = 0;
985  }
986  }
987  }
988  else
989  {
990  for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
991  {
992  if (a->ncci_plci[ncci] == plci->Id)
993  {
994  cleanup_ncci_data(plci, ncci);
995  dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996  ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997  a->ch_ncci[a->ncci_ch[ncci]] = 0;
998  if (!preserve_ncci)
999  {
1000  a->ncci_ch[ncci] = 0;
1001  a->ncci_plci[ncci] = 0;
1002  a->ncci_state[ncci] = IDLE;
1003  a->ncci_next[ncci] = 0;
1004  }
1005  }
1006  }
1007  if (!preserve_ncci)
1008  plci->ncci_ring_list = 0;
1009  }
1010 }
1011 
1012 
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function */
1015 /*------------------------------------------------------------------*/
1016 
1017 static void plci_free_msg_in_queue(PLCI *plci)
1018 {
1019  word i;
1020 
1021  if (plci->appl)
1022  {
1023  i = plci->msg_in_read_pos;
1024  while (i != plci->msg_in_write_pos)
1025  {
1026  if (i == plci->msg_in_wrap_pos)
1027  i = 0;
1028  if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029  {
1030 
1031  TransmitBufferFree(plci->appl,
1032  (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033 
1034  }
1035 
1036  i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037  MSG_IN_OVERHEAD + 3) & 0xfffc;
1038 
1039  }
1040  }
1044 }
1045 
1046 
1047 static void plci_remove(PLCI *plci)
1048 {
1049 
1050  if (!plci) {
1051  dbug(1, dprintf("plci_remove(no plci)"));
1052  return;
1053  }
1054  init_internal_command_queue(plci);
1055  dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056  if (plci_remove_check(plci))
1057  {
1058  return;
1059  }
1060  if (plci->Sig.Id == 0xff)
1061  {
1062  dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063  if (plci->NL.Id && !plci->nl_remove_id)
1064  {
1065  nl_req_ncci(plci, REMOVE, 0);
1066  send_req(plci);
1067  }
1068  }
1069  else
1070  {
1071  if (!plci->sig_remove_id
1072  && (plci->Sig.Id
1073  || (plci->req_in != plci->req_out)
1074  || (plci->nl_req || plci->sig_req)))
1075  {
1076  sig_req(plci, HANGUP, 0);
1077  send_req(plci);
1078  }
1079  }
1080  ncci_remove(plci, 0, false);
1081  plci_free_msg_in_queue(plci);
1082 
1083  plci->channels = 0;
1084  plci->appl = NULL;
1085  if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086  plci->State = OUTG_DIS_PENDING;
1087 }
1088 
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers */
1091 /*------------------------------------------------------------------*/
1092 
1093 static void set_group_ind_mask(PLCI *plci)
1094 {
1095  word i;
1096 
1097  for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098  plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100 
1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1102 {
1103  plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105 
1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1107 {
1108  return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110 
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL */
1113 /*------------------------------------------------------------------*/
1114 
1115 static void clear_c_ind_mask(PLCI *plci)
1116 {
1117  word i;
1118 
1119  for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120  plci->c_ind_mask_table[i] = 0;
1121 }
1122 
1123 static byte c_ind_mask_empty(PLCI *plci)
1124 {
1125  word i;
1126 
1127  i = 0;
1128  while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129  i++;
1130  return (i == C_IND_MASK_DWORDS);
1131 }
1132 
1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1134 {
1135  plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137 
1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1139 {
1140  plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142 
1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1144 {
1145  return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147 
1148 static void dump_c_ind_mask(PLCI *plci)
1149 {
1150  static char hex_digit_table[0x10] =
1151  {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1152  word i, j, k;
1153  dword d;
1154  char *p;
1155  char buf[40];
1156 
1157  for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158  {
1159  p = buf + 36;
1160  *p = '\0';
1161  for (j = 0; j < 4; j++)
1162  {
1163  if (i + j < C_IND_MASK_DWORDS)
1164  {
1165  d = plci->c_ind_mask_table[i + j];
1166  for (k = 0; k < 8; k++)
1167  {
1168  *(--p) = hex_digit_table[d & 0xf];
1169  d >>= 4;
1170  }
1171  }
1172  else if (i != 0)
1173  {
1174  for (k = 0; k < 8; k++)
1175  *(--p) = ' ';
1176  }
1177  *(--p) = ' ';
1178  }
1179  dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1180  }
1181 }
1182 
1183 
1184 
1185 
1186 
1187 #define dump_plcis(a)
1188 
1189 
1190 
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message */
1193 /*------------------------------------------------------------------*/
1194 
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196  PLCI *plci, APPL *appl, API_PARSE *parms)
1197 {
1198  word ch;
1199  word i;
1200  word Info;
1201  byte LinkLayer;
1202  API_PARSE *ai;
1203  API_PARSE *bp;
1204  API_PARSE ai_parms[5];
1205  word channel = 0;
1206  dword ch_mask;
1207  byte m;
1208  static byte esc_chi[35] = {0x02, 0x18, 0x01};
1209  static byte lli[2] = {0x01, 0x00};
1210  byte noCh = 0;
1211  word dir = 0;
1212  byte *p_chi = "";
1213 
1214  for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1215 
1216  dbug(1, dprintf("connect_req(%d)", parms->length));
1217  Info = _WRONG_IDENTIFIER;
1218  if (a)
1219  {
1220  if (a->adapter_disabled)
1221  {
1222  dbug(1, dprintf("adapter disabled"));
1223  Id = ((word)1 << 8) | a->Id;
1224  sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1225  sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1226  return false;
1227  }
1228  Info = _OUT_OF_PLCI;
1229  if ((i = get_plci(a)))
1230  {
1231  Info = 0;
1232  plci = &a->plci[i - 1];
1233  plci->appl = appl;
1235  /* check 'external controller' bit for codec support */
1236  if (Id & EXT_CONTROLLER)
1237  {
1238  if (AdvCodecSupport(a, plci, appl, 0))
1239  {
1240  plci->Id = 0;
1241  sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1242  return 2;
1243  }
1244  }
1245  ai = &parms[9];
1246  bp = &parms[5];
1247  ch = 0;
1248  if (bp->length)LinkLayer = bp->info[3];
1249  else LinkLayer = 0;
1250  if (ai->length)
1251  {
1252  ch = 0xffff;
1253  if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1254  {
1255  ch = 0;
1256  if (ai_parms[0].length)
1257  {
1258  ch = GET_WORD(ai_parms[0].info + 1);
1259  if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1260  if (ch == 4) /* explizit CHI in message */
1261  {
1262  /* check length of B-CH struct */
1263  if ((ai_parms[0].info)[3] >= 1)
1264  {
1265  if ((ai_parms[0].info)[4] == CHI)
1266  {
1267  p_chi = &((ai_parms[0].info)[5]);
1268  }
1269  else
1270  {
1271  p_chi = &((ai_parms[0].info)[3]);
1272  }
1273  if (p_chi[0] > 35) /* check length of channel ID */
1274  {
1275  Info = _WRONG_MESSAGE_FORMAT;
1276  }
1277  }
1278  else Info = _WRONG_MESSAGE_FORMAT;
1279  }
1280 
1281  if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1282  {
1283  dir = GET_WORD(ai_parms[0].info + 3);
1284  ch_mask = 0;
1285  m = 0x3f;
1286  for (i = 0; i + 5 <= ai_parms[0].length; i++)
1287  {
1288  if (ai_parms[0].info[i + 5] != 0)
1289  {
1290  if ((ai_parms[0].info[i + 5] | m) != 0xff)
1291  Info = _WRONG_MESSAGE_FORMAT;
1292  else
1293  {
1294  if (ch_mask == 0)
1295  channel = i;
1296  ch_mask |= 1L << i;
1297  }
1298  }
1299  m = 0;
1300  }
1301  if (ch_mask == 0)
1302  Info = _WRONG_MESSAGE_FORMAT;
1303  if (!Info)
1304  {
1305  if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1306  {
1307  esc_chi[0] = (byte)(ai_parms[0].length - 2);
1308  for (i = 0; i + 5 <= ai_parms[0].length; i++)
1309  esc_chi[i + 3] = ai_parms[0].info[i + 5];
1310  }
1311  else
1312  esc_chi[0] = 2;
1313  esc_chi[2] = (byte)channel;
1314  plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1315  add_p(plci, LLI, lli);
1316  add_p(plci, ESC, esc_chi);
1317  plci->State = LOCAL_CONNECT;
1318  if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1319  }
1320  }
1321  }
1322  }
1323  else Info = _WRONG_MESSAGE_FORMAT;
1324  }
1325 
1326  dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1327  plci->command = _CONNECT_R;
1328  plci->number = Number;
1329  /* x.31 or D-ch free SAPI in LinkLayer? */
1330  if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1331  if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1332  {
1333  /* B-channel used for B3 connections (ch==0), or no B channel */
1334  /* is used (ch==2) or perm. connection (3) is used do a CALL */
1335  if (noCh) Info = add_b1(plci, &parms[5], 2, 0); /* no resource */
1336  else Info = add_b1(plci, &parms[5], ch, 0);
1337  add_s(plci, OAD, &parms[2]);
1338  add_s(plci, OSA, &parms[4]);
1339  add_s(plci, BC, &parms[6]);
1340  add_s(plci, LLC, &parms[7]);
1341  add_s(plci, HLC, &parms[8]);
1342  if (a->Info_Mask[appl->Id - 1] & 0x200)
1343  {
1344  /* early B3 connect (CIP mask bit 9) no release after a disc */
1345  add_p(plci, LLI, "\x01\x01");
1346  }
1347  if (GET_WORD(parms[0].info) < 29) {
1348  add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1349  add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1350  }
1351  add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1352  sig_req(plci, ASSIGN, DSIG_ID);
1353  }
1354  else if (ch == 1) {
1355 
1356  /* D-Channel used for B3 connections */
1357  plci->Sig.Id = 0xff;
1358  Info = 0;
1359  }
1360 
1361  if (!Info && ch != 2 && !noCh) {
1362  Info = add_b23(plci, &parms[5]);
1363  if (!Info) {
1364  if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1365  }
1366  }
1367 
1368  if (!Info)
1369  {
1370  if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1371  {
1372  if (plci->spoofed_msg == SPOOFING_REQUIRED)
1373  {
1374  api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1375  plci->spoofed_msg = CALL_REQ;
1376  plci->internal_command = BLOCK_PLCI;
1377  plci->command = 0;
1378  dbug(1, dprintf("Spoof"));
1379  send_req(plci);
1380  return false;
1381  }
1382  if (ch == 4)add_p(plci, CHI, p_chi);
1383  add_s(plci, CPN, &parms[1]);
1384  add_s(plci, DSA, &parms[3]);
1385  if (noCh) add_p(plci, ESC, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1386  add_ai(plci, &parms[9]);
1387  if (!dir)sig_req(plci, CALL_REQ, 0);
1388  else
1389  {
1390  plci->command = PERM_LIST_REQ;
1391  plci->appl = appl;
1392  sig_req(plci, LISTEN_REQ, 0);
1393  send_req(plci);
1394  return false;
1395  }
1396  }
1397  send_req(plci);
1398  return false;
1399  }
1400  plci->Id = 0;
1401  }
1402  }
1403  sendf(appl,
1404  _CONNECT_R | CONFIRM,
1405  Id,
1406  Number,
1407  "w", Info);
1408  return 2;
1409 }
1410 
1411 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1412  PLCI *plci, APPL *appl, API_PARSE *parms)
1413 {
1414  word i, Info;
1415  word Reject;
1416  static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1417  static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1418  API_PARSE *ai;
1419  API_PARSE ai_parms[5];
1420  word ch = 0;
1421 
1422  if (!plci) {
1423  dbug(1, dprintf("connect_res(no plci)"));
1424  return 0; /* no plci, no send */
1425  }
1426 
1427  dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1428  for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1429  ai = &parms[5];
1430  dbug(1, dprintf("ai->length=%d", ai->length));
1431 
1432  if (ai->length)
1433  {
1434  if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1435  {
1436  dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1437  ch = 0;
1438  if (ai_parms[0].length)
1439  {
1440  ch = GET_WORD(ai_parms[0].info + 1);
1441  dbug(1, dprintf("BCH-I=0x%x", ch));
1442  }
1443  }
1444  }
1445 
1446  if (plci->State == INC_CON_CONNECTED_ALERT)
1447  {
1448  dbug(1, dprintf("Connected Alert Call_Res"));
1449  if (a->Info_Mask[appl->Id - 1] & 0x200)
1450  {
1451  /* early B3 connect (CIP mask bit 9) no release after a disc */
1452  add_p(plci, LLI, "\x01\x01");
1453  }
1454  add_s(plci, CONN_NR, &parms[2]);
1455  add_s(plci, LLC, &parms[4]);
1456  add_ai(plci, &parms[5]);
1457  plci->State = INC_CON_ACCEPT;
1458  sig_req(plci, CALL_RES, 0);
1459  return 1;
1460  }
1461  else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1462  clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1463  dump_c_ind_mask(plci);
1464  Reject = GET_WORD(parms[0].info);
1465  dbug(1, dprintf("Reject=0x%x", Reject));
1466  if (Reject)
1467  {
1468  if (c_ind_mask_empty(plci))
1469  {
1470  if ((Reject & 0xff00) == 0x3400)
1471  {
1472  esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1473  add_p(plci, ESC, esc_t);
1474  add_ai(plci, &parms[5]);
1475  sig_req(plci, REJECT, 0);
1476  }
1477  else if (Reject == 1 || Reject > 9)
1478  {
1479  add_ai(plci, &parms[5]);
1480  sig_req(plci, HANGUP, 0);
1481  }
1482  else
1483  {
1484  esc_t[2] = cau_t[(Reject&0x000f)];
1485  add_p(plci, ESC, esc_t);
1486  add_ai(plci, &parms[5]);
1487  sig_req(plci, REJECT, 0);
1488  }
1489  plci->appl = appl;
1490  }
1491  else
1492  {
1493  sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1494  }
1495  }
1496  else {
1497  plci->appl = appl;
1498  if (Id & EXT_CONTROLLER) {
1499  if (AdvCodecSupport(a, plci, appl, 0)) {
1500  dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1501  sig_req(plci, HANGUP, 0);
1502  return 1;
1503  }
1504  if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1505  {
1506  Info = add_b23(plci, &parms[1]);
1507  if (Info)
1508  {
1509  dbug(1, dprintf("connect_res(error from add_b23)"));
1510  sig_req(plci, HANGUP, 0);
1511  return 1;
1512  }
1513  if (plci->adv_nl)
1514  {
1515  nl_req_ncci(plci, ASSIGN, 0);
1516  }
1517  }
1518  }
1519  else
1520  {
1521  plci->tel = 0;
1522  if (ch != 2)
1523  {
1524  Info = add_b23(plci, &parms[1]);
1525  if (Info)
1526  {
1527  dbug(1, dprintf("connect_res(error from add_b23 2)"));
1528  sig_req(plci, HANGUP, 0);
1529  return 1;
1530  }
1531  }
1532  nl_req_ncci(plci, ASSIGN, 0);
1533  }
1534 
1535  if (plci->spoofed_msg == SPOOFING_REQUIRED)
1536  {
1537  api_save_msg(parms, "wsssss", &plci->saved_msg);
1538  plci->spoofed_msg = CALL_RES;
1539  plci->internal_command = BLOCK_PLCI;
1540  plci->command = 0;
1541  dbug(1, dprintf("Spoof"));
1542  }
1543  else
1544  {
1545  add_b1(plci, &parms[1], ch, plci->B1_facilities);
1546  if (a->Info_Mask[appl->Id - 1] & 0x200)
1547  {
1548  /* early B3 connect (CIP mask bit 9) no release after a disc */
1549  add_p(plci, LLI, "\x01\x01");
1550  }
1551  add_s(plci, CONN_NR, &parms[2]);
1552  add_s(plci, LLC, &parms[4]);
1553  add_ai(plci, &parms[5]);
1554  plci->State = INC_CON_ACCEPT;
1555  sig_req(plci, CALL_RES, 0);
1556  }
1557 
1558  for (i = 0; i < max_appl; i++) {
1559  if (test_c_ind_mask_bit(plci, i)) {
1560  sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1561  }
1562  }
1563  }
1564  }
1565  return 1;
1566 }
1567 
1568 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1569  PLCI *plci, APPL *appl, API_PARSE *msg)
1570 {
1571  dbug(1, dprintf("connect_a_res"));
1572  return false;
1573 }
1574 
1576  PLCI *plci, APPL *appl, API_PARSE *msg)
1577 {
1578  word Info;
1579  word i;
1580 
1581  dbug(1, dprintf("disconnect_req"));
1582 
1583  Info = _WRONG_IDENTIFIER;
1584 
1585  if (plci)
1586  {
1587  if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1588  {
1589  clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1590  plci->appl = appl;
1591  for (i = 0; i < max_appl; i++)
1592  {
1593  if (test_c_ind_mask_bit(plci, i))
1594  sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595  }
1596  plci->State = OUTG_DIS_PENDING;
1597  }
1598  if (plci->Sig.Id && plci->appl)
1599  {
1600  Info = 0;
1601  if (plci->Sig.Id != 0xff)
1602  {
1603  if (plci->State != INC_DIS_PENDING)
1604  {
1605  add_ai(plci, &msg[0]);
1606  sig_req(plci, HANGUP, 0);
1607  plci->State = OUTG_DIS_PENDING;
1608  return 1;
1609  }
1610  }
1611  else
1612  {
1613  if (plci->NL.Id && !plci->nl_remove_id)
1614  {
1615  mixer_remove(plci);
1616  nl_req_ncci(plci, REMOVE, 0);
1617  sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1618  sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619  plci->State = INC_DIS_PENDING;
1620  }
1621  return 1;
1622  }
1623  }
1624  }
1625 
1626  if (!appl) return false;
1627  sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1628  return false;
1629 }
1630 
1631 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1632  PLCI *plci, APPL *appl, API_PARSE *msg)
1633 {
1634  dbug(1, dprintf("disconnect_res"));
1635  if (plci)
1636  {
1637  /* clear ind mask bit, just in case of collsion of */
1638  /* DISCONNECT_IND and CONNECT_RES */
1639  clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1640  ncci_free_receive_buffers(plci, 0);
1641  if (plci_remove_check(plci))
1642  {
1643  return 0;
1644  }
1645  if (plci->State == INC_DIS_PENDING
1646  || plci->State == SUSPENDING) {
1647  if (c_ind_mask_empty(plci)) {
1648  if (plci->State != SUSPENDING) plci->State = IDLE;
1649  dbug(1, dprintf("chs=%d", plci->channels));
1650  if (!plci->channels) {
1651  plci_remove(plci);
1652  }
1653  }
1654  }
1655  }
1656  return 0;
1657 }
1658 
1659 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1660  PLCI *plci, APPL *appl, API_PARSE *parms)
1661 {
1662  word Info;
1663  byte i;
1664 
1665  dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1666 
1667  Info = _WRONG_IDENTIFIER;
1668  if (a) {
1669  Info = 0;
1670  a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1671  a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1672  dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1673  if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1674  a->Info_Mask[appl->Id - 1] |= 0x10; /* call progression infos */
1675  }
1676 
1677  /* check if external controller listen and switch listen on or off*/
1678  if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1680  dummy_plci.State = IDLE;
1681  a->codec_listen[appl->Id - 1] = &dummy_plci;
1682  a->TelOAD[0] = (byte)(parms[3].length);
1683  for (i = 1; parms[3].length >= i && i < 22; i++) {
1684  a->TelOAD[i] = parms[3].info[i];
1685  }
1686  a->TelOAD[i] = 0;
1687  a->TelOSA[0] = (byte)(parms[4].length);
1688  for (i = 1; parms[4].length >= i && i < 22; i++) {
1689  a->TelOSA[i] = parms[4].info[i];
1690  }
1691  a->TelOSA[i] = 0;
1692  }
1693  else Info = 0x2002; /* wrong controller, codec not supported */
1694  }
1695  else{ /* clear listen */
1696  a->codec_listen[appl->Id - 1] = (PLCI *)0;
1697  }
1698  }
1699  sendf(appl,
1700  _LISTEN_R | CONFIRM,
1701  Id,
1702  Number,
1703  "w", Info);
1704 
1705  if (a) listen_check(a);
1706  return false;
1707 }
1708 
1709 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1710  PLCI *plci, APPL *appl, API_PARSE *msg)
1711 {
1712  word i;
1713  API_PARSE *ai;
1714  PLCI *rc_plci = NULL;
1715  API_PARSE ai_parms[5];
1716  word Info = 0;
1717 
1718  dbug(1, dprintf("info_req"));
1719  for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1720 
1721  ai = &msg[1];
1722 
1723  if (ai->length)
1724  {
1725  if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1726  {
1727  dbug(1, dprintf("AddInfo wrong"));
1728  Info = _WRONG_MESSAGE_FORMAT;
1729  }
1730  }
1731  if (!a) Info = _WRONG_STATE;
1732 
1733  if (!Info && plci)
1734  { /* no fac, with CPN, or KEY */
1735  rc_plci = plci;
1736  if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1737  {
1738  /* overlap sending option */
1739  dbug(1, dprintf("OvlSnd"));
1740  add_s(plci, CPN, &msg[0]);
1741  add_s(plci, KEY, &ai_parms[1]);
1742  sig_req(plci, INFO_REQ, 0);
1743  send_req(plci);
1744  return false;
1745  }
1746 
1747  if (plci->State && ai_parms[2].length)
1748  {
1749  /* User_Info option */
1750  dbug(1, dprintf("UUI"));
1751  add_s(plci, UUI, &ai_parms[2]);
1752  sig_req(plci, USER_DATA, 0);
1753  }
1754  else if (plci->State && ai_parms[3].length)
1755  {
1756  /* Facility option */
1757  dbug(1, dprintf("FAC"));
1758  add_s(plci, CPN, &msg[0]);
1759  add_ai(plci, &msg[1]);
1760  sig_req(plci, FACILITY_REQ, 0);
1761  }
1762  else
1763  {
1764  Info = _WRONG_STATE;
1765  }
1766  }
1767  else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1768  {
1769  /* NCR_Facility option -> send UUI and Keypad too */
1770  dbug(1, dprintf("NCR_FAC"));
1771  if ((i = get_plci(a)))
1772  {
1773  rc_plci = &a->plci[i - 1];
1774  appl->NullCREnable = true;
1775  rc_plci->internal_command = C_NCR_FAC_REQ;
1776  rc_plci->appl = appl;
1777  add_p(rc_plci, CAI, "\x01\x80");
1778  add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1779  sig_req(rc_plci, ASSIGN, DSIG_ID);
1780  send_req(rc_plci);
1781  }
1782  else
1783  {
1784  Info = _OUT_OF_PLCI;
1785  }
1786 
1787  if (!Info)
1788  {
1789  add_s(rc_plci, CPN, &msg[0]);
1790  add_ai(rc_plci, &msg[1]);
1791  sig_req(rc_plci, NCR_FACILITY, 0);
1792  send_req(rc_plci);
1793  return false;
1794  /* for application controlled supplementary services */
1795  }
1796  }
1797 
1798  if (!rc_plci)
1799  {
1800  Info = _WRONG_MESSAGE_FORMAT;
1801  }
1802 
1803  if (!Info)
1804  {
1805  send_req(rc_plci);
1806  }
1807  else
1808  { /* appl is not assigned to a PLCI or error condition */
1809  dbug(1, dprintf("localInfoCon"));
1810  sendf(appl,
1811  _INFO_R | CONFIRM,
1812  Id,
1813  Number,
1814  "w", Info);
1815  }
1816  return false;
1817 }
1818 
1819 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1820  PLCI *plci, APPL *appl, API_PARSE *msg)
1821 {
1822  dbug(1, dprintf("info_res"));
1823  return false;
1824 }
1825 
1826 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1827  PLCI *plci, APPL *appl, API_PARSE *msg)
1828 {
1829  word Info;
1830  byte ret;
1831 
1832  dbug(1, dprintf("alert_req"));
1833 
1834  Info = _WRONG_IDENTIFIER;
1835  ret = false;
1836  if (plci) {
1837  Info = _ALERT_IGNORED;
1838  if (plci->State != INC_CON_ALERT) {
1839  Info = _WRONG_STATE;
1840  if (plci->State == INC_CON_PENDING) {
1841  Info = 0;
1842  plci->State = INC_CON_ALERT;
1843  add_ai(plci, &msg[0]);
1844  sig_req(plci, CALL_ALERT, 0);
1845  ret = 1;
1846  }
1847  }
1848  }
1849  sendf(appl,
1850  _ALERT_R | CONFIRM,
1851  Id,
1852  Number,
1853  "w", Info);
1854  return ret;
1855 }
1856 
1857 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1858  PLCI *plci, APPL *appl, API_PARSE *msg)
1859 {
1860  word Info = 0;
1861  word i = 0;
1862 
1863  word selector;
1864  word SSreq;
1865  long relatedPLCIvalue;
1866  DIVA_CAPI_ADAPTER *relatedadapter;
1867  byte *SSparms = "";
1868  byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1869  byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1870  API_PARSE *parms;
1871  API_PARSE ss_parms[11];
1872  PLCI *rplci;
1873  byte cai[15];
1874  dword d;
1875  API_PARSE dummy;
1876 
1877  dbug(1, dprintf("facility_req"));
1878  for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1879 
1880  parms = &msg[1];
1881 
1882  if (!a)
1883  {
1884  dbug(1, dprintf("wrong Ctrl"));
1885  Info = _WRONG_IDENTIFIER;
1886  }
1887 
1888  selector = GET_WORD(msg[0].info);
1889 
1890  if (!Info)
1891  {
1892  switch (selector)
1893  {
1894  case SELECTOR_HANDSET:
1895  Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1896  break;
1897 
1898  case SELECTOR_SU_SERV:
1899  if (!msg[1].length)
1900  {
1901  Info = _WRONG_MESSAGE_FORMAT;
1902  break;
1903  }
1904  SSreq = GET_WORD(&(msg[1].info[1]));
1905  PUT_WORD(&RCparms[1], SSreq);
1906  SSparms = RCparms;
1907  switch (SSreq)
1908  {
1910  if ((i = get_plci(a)))
1911  {
1912  rplci = &a->plci[i - 1];
1913  rplci->appl = appl;
1914  add_p(rplci, CAI, "\x01\x80");
1915  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1916  sig_req(rplci, ASSIGN, DSIG_ID);
1917  send_req(rplci);
1918  }
1919  else
1920  {
1921  PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1922  SSparms = (byte *)SSstruct;
1923  break;
1924  }
1926  rplci->number = Number;
1927  rplci->appl = appl;
1928  sig_req(rplci, S_SUPPORTED, 0);
1929  send_req(rplci);
1930  return false;
1931  break;
1932 
1933  case S_LISTEN:
1934  if (parms->length == 7)
1935  {
1936  if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1937  {
1938  dbug(1, dprintf("format wrong"));
1939  Info = _WRONG_MESSAGE_FORMAT;
1940  break;
1941  }
1942  }
1943  else
1944  {
1945  Info = _WRONG_MESSAGE_FORMAT;
1946  break;
1947  }
1948  a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1949  if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1950  {
1951  if ((i = get_plci(a)))
1952  {
1953  rplci = &a->plci[i - 1];
1954  rplci->appl = appl;
1955  add_p(rplci, CAI, "\x01\x80");
1956  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1957  sig_req(rplci, ASSIGN, DSIG_ID);
1958  send_req(rplci);
1959  }
1960  else
1961  {
1962  break;
1963  }
1965  rplci->number = Number;
1966  sig_req(rplci, MWI_POLL, 0);
1967  send_req(rplci);
1968  }
1969  break;
1970 
1971  case S_HOLD:
1972  api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1973  if (plci && plci->State && plci->SuppState == IDLE)
1974  {
1975  plci->SuppState = HOLD_REQUEST;
1976  plci->command = C_HOLD_REQ;
1977  add_s(plci, CAI, &ss_parms[1]);
1978  sig_req(plci, CALL_HOLD, 0);
1979  send_req(plci);
1980  return false;
1981  }
1982  else Info = 0x3010; /* wrong state */
1983  break;
1984  case S_RETRIEVE:
1985  if (plci && plci->State && plci->SuppState == CALL_HELD)
1986  {
1987  if (Id & EXT_CONTROLLER)
1988  {
1989  if (AdvCodecSupport(a, plci, appl, 0))
1990  {
1991  Info = 0x3010; /* wrong state */
1992  break;
1993  }
1994  }
1995  else plci->tel = 0;
1996 
1997  plci->SuppState = RETRIEVE_REQUEST;
1998  plci->command = C_RETRIEVE_REQ;
1999  if (plci->spoofed_msg == SPOOFING_REQUIRED)
2000  {
2001  plci->spoofed_msg = CALL_RETRIEVE;
2002  plci->internal_command = BLOCK_PLCI;
2003  plci->command = 0;
2004  dbug(1, dprintf("Spoof"));
2005  return false;
2006  }
2007  else
2008  {
2009  sig_req(plci, CALL_RETRIEVE, 0);
2010  send_req(plci);
2011  return false;
2012  }
2013  }
2014  else Info = 0x3010; /* wrong state */
2015  break;
2016  case S_SUSPEND:
2017  if (parms->length)
2018  {
2019  if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2020  {
2021  dbug(1, dprintf("format wrong"));
2022  Info = _WRONG_MESSAGE_FORMAT;
2023  break;
2024  }
2025  }
2026  if (plci && plci->State)
2027  {
2028  add_s(plci, CAI, &ss_parms[2]);
2029  plci->command = SUSPEND_REQ;
2030  sig_req(plci, SUSPEND, 0);
2031  plci->State = SUSPENDING;
2032  send_req(plci);
2033  }
2034  else Info = 0x3010; /* wrong state */
2035  break;
2036 
2037  case S_RESUME:
2038  if (!(i = get_plci(a)))
2039  {
2040  Info = _OUT_OF_PLCI;
2041  break;
2042  }
2043  rplci = &a->plci[i - 1];
2044  rplci->appl = appl;
2045  rplci->number = Number;
2046  rplci->tel = 0;
2048  /* check 'external controller' bit for codec support */
2049  if (Id & EXT_CONTROLLER)
2050  {
2051  if (AdvCodecSupport(a, rplci, appl, 0))
2052  {
2053  rplci->Id = 0;
2054  Info = 0x300A;
2055  break;
2056  }
2057  }
2058  if (parms->length)
2059  {
2060  if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2061  {
2062  dbug(1, dprintf("format wrong"));
2063  rplci->Id = 0;
2064  Info = _WRONG_MESSAGE_FORMAT;
2065  break;
2066  }
2067  }
2068  dummy.length = 0;
2069  dummy.info = "\x00";
2070  add_b1(rplci, &dummy, 0, 0);
2071  if (a->Info_Mask[appl->Id - 1] & 0x200)
2072  {
2073  /* early B3 connect (CIP mask bit 9) no release after a disc */
2074  add_p(rplci, LLI, "\x01\x01");
2075  }
2076  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2077  sig_req(rplci, ASSIGN, DSIG_ID);
2078  send_req(rplci);
2079  add_s(rplci, CAI, &ss_parms[2]);
2080  rplci->command = RESUME_REQ;
2081  sig_req(rplci, RESUME, 0);
2082  rplci->State = RESUMING;
2083  send_req(rplci);
2084  break;
2085 
2086  case S_CONF_BEGIN: /* Request */
2087  case S_CONF_DROP:
2088  case S_CONF_ISOLATE:
2089  case S_CONF_REATTACH:
2090  if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2091  {
2092  dbug(1, dprintf("format wrong"));
2093  Info = _WRONG_MESSAGE_FORMAT;
2094  break;
2095  }
2096  if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2097  {
2098  d = GET_DWORD(ss_parms[2].info);
2099  if (d >= 0x80)
2100  {
2101  dbug(1, dprintf("format wrong"));
2102  Info = _WRONG_MESSAGE_FORMAT;
2103  break;
2104  }
2105  plci->ptyState = (byte)SSreq;
2106  plci->command = 0;
2107  cai[0] = 2;
2108  switch (SSreq)
2109  {
2110  case S_CONF_BEGIN:
2111  cai[1] = CONF_BEGIN;
2113  break;
2114  case S_CONF_DROP:
2115  cai[1] = CONF_DROP;
2117  break;
2118  case S_CONF_ISOLATE:
2119  cai[1] = CONF_ISOLATE;
2121  break;
2122  case S_CONF_REATTACH:
2123  cai[1] = CONF_REATTACH;
2125  break;
2126  }
2127  cai[2] = (byte)d; /* Conference Size resp. PartyId */
2128  add_p(plci, CAI, cai);
2129  sig_req(plci, S_SERVICE, 0);
2130  send_req(plci);
2131  return false;
2132  }
2133  else Info = 0x3010; /* wrong state */
2134  break;
2135 
2136  case S_ECT:
2137  case S_3PTY_BEGIN:
2138  case S_3PTY_END:
2139  case S_CONF_ADD:
2140  if (parms->length == 7)
2141  {
2142  if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2143  {
2144  dbug(1, dprintf("format wrong"));
2145  Info = _WRONG_MESSAGE_FORMAT;
2146  break;
2147  }
2148  }
2149  else if (parms->length == 8) /* workaround for the T-View-S */
2150  {
2151  if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2152  {
2153  dbug(1, dprintf("format wrong"));
2154  Info = _WRONG_MESSAGE_FORMAT;
2155  break;
2156  }
2157  }
2158  else
2159  {
2160  Info = _WRONG_MESSAGE_FORMAT;
2161  break;
2162  }
2163  if (!msg[1].length)
2164  {
2165  Info = _WRONG_MESSAGE_FORMAT;
2166  break;
2167  }
2168  if (!plci)
2169  {
2170  Info = _WRONG_IDENTIFIER;
2171  break;
2172  }
2173  relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2174  relatedPLCIvalue &= 0x0000FFFF;
2175  dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2176  /* controller starts with 0 up to (max_adapter - 1) */
2177  if (((relatedPLCIvalue & 0x7f) == 0)
2178  || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2179  || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2180  {
2181  if (SSreq == S_3PTY_END)
2182  {
2183  dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2184  rplci = plci;
2185  }
2186  else
2187  {
2188  Info = 0x3010; /* wrong state */
2189  break;
2190  }
2191  }
2192  else
2193  {
2194  relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2195  relatedPLCIvalue >>= 8;
2196  /* find PLCI PTR*/
2197  for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2198  {
2199  if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2200  {
2201  rplci = &relatedadapter->plci[i];
2202  }
2203  }
2204  if (!rplci || !relatedPLCIvalue)
2205  {
2206  if (SSreq == S_3PTY_END)
2207  {
2208  dbug(1, dprintf("use 2nd PLCI=PLCI"));
2209  rplci = plci;
2210  }
2211  else
2212  {
2213  Info = 0x3010; /* wrong state */
2214  break;
2215  }
2216  }
2217  }
2218 /*
2219  dbug(1, dprintf("rplci:%x", rplci));
2220  dbug(1, dprintf("plci:%x", plci));
2221  dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2222  dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2223  dbug(1, dprintf("SSreq:%x", SSreq));
2224  dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2225  dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2226  dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2227 */
2228  /* send PTY/ECT req, cannot check all states because of US stuff */
2229  if (!rplci->internal_command && rplci->appl)
2230  {
2231  plci->command = 0;
2232  rplci->relatedPTYPLCI = plci;
2233  plci->relatedPTYPLCI = rplci;
2234  rplci->ptyState = (byte)SSreq;
2235  if (SSreq == S_ECT)
2236  {
2237  rplci->internal_command = ECT_REQ_PEND;
2238  cai[1] = ECT_EXECUTE;
2239 
2240  rplci->vswitchstate = 0;
2241  rplci->vsprot = 0;
2242  rplci->vsprotdialect = 0;
2243  plci->vswitchstate = 0;
2244  plci->vsprot = 0;
2245  plci->vsprotdialect = 0;
2246 
2247  }
2248  else if (SSreq == S_CONF_ADD)
2249  {
2251  cai[1] = CONF_ADD;
2252  }
2253  else
2254  {
2255  rplci->internal_command = PTY_REQ_PEND;
2256  cai[1] = (byte)(SSreq - 3);
2257  }
2258  rplci->number = Number;
2259  if (plci != rplci) /* explicit invocation */
2260  {
2261  cai[0] = 2;
2262  cai[2] = plci->Sig.Id;
2263  dbug(1, dprintf("explicit invocation"));
2264  }
2265  else
2266  {
2267  dbug(1, dprintf("implicit invocation"));
2268  cai[0] = 1;
2269  }
2270  add_p(rplci, CAI, cai);
2271  sig_req(rplci, S_SERVICE, 0);
2272  send_req(rplci);
2273  return false;
2274  }
2275  else
2276  {
2277  dbug(0, dprintf("Wrong line"));
2278  Info = 0x3010; /* wrong state */
2279  break;
2280  }
2281  break;
2282 
2283  case S_CALL_DEFLECTION:
2284  if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2285  {
2286  dbug(1, dprintf("format wrong"));
2287  Info = _WRONG_MESSAGE_FORMAT;
2288  break;
2289  }
2290  if (!plci)
2291  {
2292  Info = _WRONG_IDENTIFIER;
2293  break;
2294  }
2295  /* reuse unused screening indicator */
2296  ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2297  plci->command = 0;
2298  plci->internal_command = CD_REQ_PEND;
2299  appl->CDEnable = true;
2300  cai[0] = 1;
2301  cai[1] = CALL_DEFLECTION;
2302  add_p(plci, CAI, cai);
2303  add_p(plci, CPN, ss_parms[3].info);
2304  sig_req(plci, S_SERVICE, 0);
2305  send_req(plci);
2306  return false;
2307  break;
2308 
2310  if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2311  {
2312  dbug(1, dprintf("format wrong"));
2313  Info = _WRONG_MESSAGE_FORMAT;
2314  break;
2315  }
2316 
2317  if ((i = get_plci(a)))
2318  {
2319  rplci = &a->plci[i - 1];
2320  rplci->appl = appl;
2321  add_p(rplci, CAI, "\x01\x80");
2322  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2323  sig_req(rplci, ASSIGN, DSIG_ID);
2324  send_req(rplci);
2325  }
2326  else
2327  {
2328  Info = _OUT_OF_PLCI;
2329  break;
2330  }
2331 
2332  /* reuse unused screening indicator */
2334  rplci->appl = appl;
2335  rplci->number = Number;
2336  appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2337  cai[0] = 2;
2338  cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2339  cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2340  add_p(rplci, CAI, cai);
2341  add_p(rplci, OAD, ss_parms[5].info);
2342  add_p(rplci, CPN, ss_parms[6].info);
2343  sig_req(rplci, S_SERVICE, 0);
2344  send_req(rplci);
2345  return false;
2346  break;
2347 
2349  case S_INTERROGATE_NUMBERS:
2351  case S_CCBS_REQUEST:
2352  case S_CCBS_DEACTIVATE:
2353  case S_CCBS_INTERROGATE:
2354  switch (SSreq)
2355  {
2356  case S_INTERROGATE_NUMBERS:
2357  if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2358  {
2359  dbug(0, dprintf("format wrong"));
2360  Info = _WRONG_MESSAGE_FORMAT;
2361  }
2362  break;
2363  case S_CCBS_REQUEST:
2364  case S_CCBS_DEACTIVATE:
2365  if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2366  {
2367  dbug(0, dprintf("format wrong"));
2368  Info = _WRONG_MESSAGE_FORMAT;
2369  }
2370  break;
2371  case S_CCBS_INTERROGATE:
2372  if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2373  {
2374  dbug(0, dprintf("format wrong"));
2375  Info = _WRONG_MESSAGE_FORMAT;
2376  }
2377  break;
2378  default:
2379  if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2380  {
2381  dbug(0, dprintf("format wrong"));
2382  Info = _WRONG_MESSAGE_FORMAT;
2383  break;
2384  }
2385  break;
2386  }
2387 
2388  if (Info) break;
2389  if ((i = get_plci(a)))
2390  {
2391  rplci = &a->plci[i - 1];
2392  switch (SSreq)
2393  {
2394  case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2395  cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2396  rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2397  break;
2398  case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2399  cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2400  rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2401  break;
2403  rplci->internal_command = CF_STOP_PEND;
2404  cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2405  break;
2406  case S_CCBS_REQUEST:
2407  cai[1] = CCBS_REQUEST;
2409  break;
2410  case S_CCBS_DEACTIVATE:
2411  cai[1] = CCBS_DEACTIVATE;
2413  break;
2414  case S_CCBS_INTERROGATE:
2415  cai[1] = CCBS_INTERROGATE;
2417  break;
2418  default:
2419  cai[1] = 0;
2420  break;
2421  }
2422  rplci->appl = appl;
2423  rplci->number = Number;
2424  add_p(rplci, CAI, "\x01\x80");
2425  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2426  sig_req(rplci, ASSIGN, DSIG_ID);
2427  send_req(rplci);
2428  }
2429  else
2430  {
2431  Info = _OUT_OF_PLCI;
2432  break;
2433  }
2434 
2435  appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2436  switch (SSreq)
2437  {
2438  case S_INTERROGATE_NUMBERS:
2439  cai[0] = 1;
2440  add_p(rplci, CAI, cai);
2441  break;
2442  case S_CCBS_REQUEST:
2443  case S_CCBS_DEACTIVATE:
2444  cai[0] = 3;
2445  PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2446  add_p(rplci, CAI, cai);
2447  break;
2448  case S_CCBS_INTERROGATE:
2449  cai[0] = 3;
2450  PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2451  add_p(rplci, CAI, cai);
2452  add_p(rplci, OAD, ss_parms[4].info);
2453  break;
2454  default:
2455  cai[0] = 2;
2456  cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2457  add_p(rplci, CAI, cai);
2458  add_p(rplci, OAD, ss_parms[5].info);
2459  break;
2460  }
2461 
2462  sig_req(rplci, S_SERVICE, 0);
2463  send_req(rplci);
2464  return false;
2465  break;
2466 
2467  case S_MWI_ACTIVATE:
2468  if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2469  {
2470  dbug(1, dprintf("format wrong"));
2471  Info = _WRONG_MESSAGE_FORMAT;
2472  break;
2473  }
2474  if (!plci)
2475  {
2476  if ((i = get_plci(a)))
2477  {
2478  rplci = &a->plci[i - 1];
2479  rplci->appl = appl;
2480  rplci->cr_enquiry = true;
2481  add_p(rplci, CAI, "\x01\x80");
2482  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2483  sig_req(rplci, ASSIGN, DSIG_ID);
2484  send_req(rplci);
2485  }
2486  else
2487  {
2488  Info = _OUT_OF_PLCI;
2489  break;
2490  }
2491  }
2492  else
2493  {
2494  rplci = plci;
2495  rplci->cr_enquiry = false;
2496  }
2497 
2498  rplci->command = 0;
2500  rplci->appl = appl;
2501  rplci->number = Number;
2502 
2503  cai[0] = 13;
2504  cai[1] = ACTIVATION_MWI; /* Function */
2505  PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2506  PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2507  PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2508  PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2509  PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2510  add_p(rplci, CAI, cai);
2511  add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2512  add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2513  add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2514  add_p(rplci, UID, ss_parms[10].info); /* Time */
2515  sig_req(rplci, S_SERVICE, 0);
2516  send_req(rplci);
2517  return false;
2518 
2519  case S_MWI_DEACTIVATE:
2520  if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2521  {
2522  dbug(1, dprintf("format wrong"));
2523  Info = _WRONG_MESSAGE_FORMAT;
2524  break;
2525  }
2526  if (!plci)
2527  {
2528  if ((i = get_plci(a)))
2529  {
2530  rplci = &a->plci[i - 1];
2531  rplci->appl = appl;
2532  rplci->cr_enquiry = true;
2533  add_p(rplci, CAI, "\x01\x80");
2534  add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2535  sig_req(rplci, ASSIGN, DSIG_ID);
2536  send_req(rplci);
2537  }
2538  else
2539  {
2540  Info = _OUT_OF_PLCI;
2541  break;
2542  }
2543  }
2544  else
2545  {
2546  rplci = plci;
2547  rplci->cr_enquiry = false;
2548  }
2549 
2550  rplci->command = 0;
2552  rplci->appl = appl;
2553  rplci->number = Number;
2554 
2555  cai[0] = 5;
2556  cai[1] = DEACTIVATION_MWI; /* Function */
2557  PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2558  PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2559  add_p(rplci, CAI, cai);
2560  add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2561  add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2562  sig_req(rplci, S_SERVICE, 0);
2563  send_req(rplci);
2564  return false;
2565 
2566  default:
2567  Info = 0x300E; /* not supported */
2568  break;
2569  }
2570  break; /* case SELECTOR_SU_SERV: end */
2571 
2572 
2573  case SELECTOR_DTMF:
2574  return (dtmf_request(Id, Number, a, plci, appl, msg));
2575 
2576 
2577 
2579  return (mixer_request(Id, Number, a, plci, appl, msg));
2580 
2581 
2582 
2585  return (ec_request(Id, Number, a, plci, appl, msg));
2586 
2589  return (ec_request(Id, Number, a, plci, appl, msg));
2590 
2591 
2592  case SELECTOR_V42BIS:
2593  default:
2594  Info = _FACILITY_NOT_SUPPORTED;
2595  break;
2596  } /* end of switch (selector) */
2597  }
2598 
2599  dbug(1, dprintf("SendFacRc"));
2600  sendf(appl,
2601  _FACILITY_R | CONFIRM,
2602  Id,
2603  Number,
2604  "wws", Info, selector, SSparms);
2605  return false;
2606 }
2607 
2608 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2609  PLCI *plci, APPL *appl, API_PARSE *msg)
2610 {
2611  dbug(1, dprintf("facility_res"));
2612  return false;
2613 }
2614 
2615 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2616  PLCI *plci, APPL *appl, API_PARSE *parms)
2617 {
2618  word Info = 0;
2619  byte req;
2620  byte len;
2621  word w;
2622  word fax_control_bits, fax_feature_bits, fax_info_change;
2623  API_PARSE *ncpi;
2624  byte pvc[2];
2625 
2626  API_PARSE fax_parms[9];
2627  word i;
2628 
2629 
2630  dbug(1, dprintf("connect_b3_req"));
2631  if (plci)
2632  {
2633  if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2634  || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2635  {
2636  Info = _WRONG_STATE;
2637  }
2638  else
2639  {
2640  /* local reply if assign unsuccessful
2641  or B3 protocol allows only one layer 3 connection
2642  and already connected
2643  or B2 protocol not any LAPD
2644  and connect_b3_req contradicts originate/answer direction */
2645  if (!plci->NL.Id
2646  || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2647  && ((plci->channels != 0)
2648  || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2649  && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2650  {
2651  dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2652  plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2653  Info = _WRONG_STATE;
2654  sendf(appl,
2656  Id,
2657  Number,
2658  "w", Info);
2659  return false;
2660  }
2661  plci->requested_options_conn = 0;
2662 
2663  req = N_CONNECT;
2664  ncpi = &parms[0];
2665  if (plci->B3_prot == 2 || plci->B3_prot == 3)
2666  {
2667  if (ncpi->length > 2)
2668  {
2669  /* check for PVC */
2670  if (ncpi->info[2] || ncpi->info[3])
2671  {
2672  pvc[0] = ncpi->info[3];
2673  pvc[1] = ncpi->info[2];
2674  add_d(plci, 2, pvc);
2675  req = N_RESET;
2676  }
2677  else
2678  {
2679  if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2680  add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2681  }
2682  }
2683  }
2684  else if (plci->B3_prot == 5)
2685  {
2686  if (plci->NL.Id && !plci->nl_remove_id)
2687  {
2688  fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2689  fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2690  if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2691  || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2692  {
2693  len = offsetof(T30_INFO, universal_6);
2694  fax_info_change = false;
2695  if (ncpi->length >= 4)
2696  {
2697  w = GET_WORD(&ncpi->info[3]);
2698  if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2699  {
2700  ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2701  (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2702  ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2703  fax_info_change = true;
2704  }
2706  if (w & 0x0002) /* Fax-polling request */
2707  fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2708  if ((w & 0x0004) /* Request to send / poll another document */
2710  {
2711  fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2712  }
2713  if (ncpi->length >= 6)
2714  {
2715  w = GET_WORD(&ncpi->info[5]);
2716  if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2717  {
2719  fax_info_change = true;
2720  }
2721 
2723  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2724  {
2726  }
2728  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2729  {
2731  }
2734  if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2736  {
2737  if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2738  Info = _WRONG_MESSAGE_FORMAT;
2739  else
2740  {
2741  if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2742  & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2743  {
2745  if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2746  fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2747  }
2748  w = fax_parms[4].length;
2749  if (w > 20)
2750  w = 20;
2751  ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2752  for (i = 0; i < w; i++)
2753  ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2754  ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2755  len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2756  w = fax_parms[5].length;
2757  if (w > 20)
2758  w = 20;
2759  plci->fax_connect_info_buffer[len++] = (byte) w;
2760  for (i = 0; i < w; i++)
2761  plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2762  w = fax_parms[6].length;
2763  if (w > 20)
2764  w = 20;
2765  plci->fax_connect_info_buffer[len++] = (byte) w;
2766  for (i = 0; i < w; i++)
2767  plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2768  if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2769  & (1L << PRIVATE_FAX_NONSTANDARD))
2770  {
2771  if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2772  {
2773  dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2774  plci->fax_connect_info_buffer[len++] = 0;
2775  }
2776  else
2777  {
2778  if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2779  plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2780  plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2781  for (i = 0; i < fax_parms[7].length; i++)
2782  plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2783  }
2784  }
2785  }
2786  }
2787  else
2788  {
2789  len = offsetof(T30_INFO, universal_6);
2790  }
2791  fax_info_change = true;
2792 
2793  }
2794  if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2795  {
2796  PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2797  fax_info_change = true;
2798  }
2799  }
2800  if (Info == GOOD)
2801  {
2802  plci->fax_connect_info_length = len;
2803  if (fax_info_change)
2804  {
2805  if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2806  {
2807  start_internal_command(Id, plci, fax_connect_info_command);
2808  return false;
2809  }
2810  else
2811  {
2812  start_internal_command(Id, plci, fax_adjust_b23_command);
2813  return false;
2814  }
2815  }
2816  }
2817  }
2818  else Info = _WRONG_STATE;
2819  }
2820  else Info = _WRONG_STATE;
2821  }
2822 
2823  else if (plci->B3_prot == B3_RTP)
2824  {
2825  plci->internal_req_buffer[0] = ncpi->length + 1;
2827  for (w = 0; w < ncpi->length; w++)
2828  plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2829  start_internal_command(Id, plci, rtp_connect_b3_req_command);
2830  return false;
2831  }
2832 
2833  if (!Info)
2834  {
2835  nl_req_ncci(plci, req, 0);
2836  return 1;
2837  }
2838  }
2839  }
2840  else Info = _WRONG_IDENTIFIER;
2841 
2842  sendf(appl,
2844  Id,
2845  Number,
2846  "w", Info);
2847  return false;
2848 }
2849 
2850 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2851  PLCI *plci, APPL *appl, API_PARSE *parms)
2852 {
2853  word ncci;
2854  API_PARSE *ncpi;
2855  byte req;
2856 
2857  word w;
2858 
2859 
2860  API_PARSE fax_parms[9];
2861  word i;
2862  byte len;
2863 
2864 
2865  dbug(1, dprintf("connect_b3_res"));
2866 
2867  ncci = (word)(Id >> 16);
2868  if (plci && ncci) {
2869  if (a->ncci_state[ncci] == INC_CON_PENDING) {
2870  if (GET_WORD(&parms[0].info[0]) != 0)
2871  {
2873  channel_request_xon(plci, a->ncci_ch[ncci]);
2874  channel_xmit_xon(plci);
2875  cleanup_ncci_data(plci, ncci);
2876  nl_req_ncci(plci, N_DISC, (byte)ncci);
2877  return 1;
2878  }
2880 
2881  req = N_CONNECT_ACK;
2882  ncpi = &parms[1];
2883  if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884  {
2885 
2886  if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2887  & (1L << PRIVATE_FAX_NONSTANDARD))
2888  {
2889  if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2892  {
2893  len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2894  if (plci->fax_connect_info_length < len)
2895  {
2896  ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2897  ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2898  }
2899  if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2900  {
2901  dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2902  }
2903  else
2904  {
2905  if (plci->fax_connect_info_length <= len)
2906  plci->fax_connect_info_buffer[len] = 0;
2907  len += 1 + plci->fax_connect_info_buffer[len];
2908  if (plci->fax_connect_info_length <= len)
2909  plci->fax_connect_info_buffer[len] = 0;
2910  len += 1 + plci->fax_connect_info_buffer[len];
2911  if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2912  plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2913  plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2914  for (i = 0; i < fax_parms[7].length; i++)
2915  plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2916  }
2917  plci->fax_connect_info_length = len;
2918  ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2919  start_internal_command(Id, plci, fax_connect_ack_command);
2920  return false;
2921  }
2922  }
2923 
2924  nl_req_ncci(plci, req, (byte)ncci);
2926  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2927  {
2928  if (plci->B3_prot == 4)
2929  sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2930  else
2931  sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2933  }
2934  }
2935 
2936  else if (plci->B3_prot == B3_RTP)
2937  {
2938  plci->internal_req_buffer[0] = ncpi->length + 1;
2940  for (w = 0; w < ncpi->length; w++)
2941  plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2942  start_internal_command(Id, plci, rtp_connect_b3_res_command);
2943  return false;
2944  }
2945 
2946  else
2947  {
2948  if (ncpi->length > 2) {
2949  if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2950  add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2951  }
2952  nl_req_ncci(plci, req, (byte)ncci);
2953  sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2954  if (plci->adjust_b_restore)
2955  {
2956  plci->adjust_b_restore = false;
2957  start_internal_command(Id, plci, adjust_b_restore);
2958  }
2959  }
2960  return 1;
2961  }
2962  }
2963  return false;
2964 }
2965 
2966 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2967  PLCI *plci, APPL *appl, API_PARSE *parms)
2968 {
2969  word ncci;
2970 
2971  ncci = (word)(Id >> 16);
2972  dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2973 
2974  if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2975  && (plci->State != OUTG_DIS_PENDING))
2976  {
2977  if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2978  a->ncci_state[ncci] = CONNECTED;
2979  if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2980  channel_request_xon(plci, a->ncci_ch[ncci]);
2981  channel_xmit_xon(plci);
2982  }
2983  }
2984  return false;
2985 }
2986 
2987 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2988  PLCI *plci, APPL *appl, API_PARSE *parms)
2989 {
2990  word Info;
2991  word ncci;
2992  API_PARSE *ncpi;
2993 
2994  dbug(1, dprintf("disconnect_b3_req"));
2995 
2996  Info = _WRONG_IDENTIFIER;
2997  ncci = (word)(Id >> 16);
2998  if (plci && ncci)
2999  {
3000  Info = _WRONG_STATE;
3001  if ((a->ncci_state[ncci] == CONNECTED)
3002  || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3003  || (a->ncci_state[ncci] == INC_CON_PENDING)
3004  || (a->ncci_state[ncci] == INC_ACT_PENDING))
3005  {
3007  channel_request_xon(plci, a->ncci_ch[ncci]);
3008  channel_xmit_xon(plci);
3009 
3010  if (a->ncci[ncci].data_pending
3011  && ((plci->B3_prot == B3_TRANSPARENT)
3012  || (plci->B3_prot == B3_T30)
3013  || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3014  {
3015  plci->send_disc = (byte)ncci;
3016  plci->command = 0;
3017  return false;
3018  }
3019  else
3020  {
3021  cleanup_ncci_data(plci, ncci);
3022 
3023  if (plci->B3_prot == 2 || plci->B3_prot == 3)
3024  {
3025  ncpi = &parms[0];
3026  if (ncpi->length > 3)
3027  {
3028  add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029  }
3030  }
3031  nl_req_ncci(plci, N_DISC, (byte)ncci);
3032  }
3033  return 1;
3034  }
3035  }
3036  sendf(appl,
3038  Id,
3039  Number,
3040  "w", Info);
3041  return false;
3042 }
3043 
3044 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3045  PLCI *plci, APPL *appl, API_PARSE *parms)
3046 {
3047  word ncci;
3048  word i;
3049 
3050  ncci = (word)(Id >> 16);
3051  dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3052  if (plci && ncci) {
3053  plci->requested_options_conn = 0;
3054  plci->fax_connect_info_length = 0;
3055  plci->ncpi_state = 0x00;
3056  if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3057  && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3058  {
3060  }
3061  for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3062  if (i < MAX_CHANNELS_PER_PLCI) {
3063  if (plci->channels)plci->channels--;
3064  for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3065  plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3066 
3067  ncci_free_receive_buffers(plci, ncci);
3068 
3069  if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3070  if (plci->State == SUSPENDING) {
3071  sendf(plci->appl,
3072  _FACILITY_I,
3073  Id & 0xffffL,
3074  0,
3075  "ws", (word)3, "\x03\x04\x00\x00");
3076  sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3077  }
3078  plci_remove(plci);
3079  plci->State = IDLE;
3080  }
3081  }
3082  else
3083  {
3085  && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3086  && (a->ncci_state[ncci] == INC_DIS_PENDING))
3087  {
3088  ncci_free_receive_buffers(plci, ncci);
3089 
3090  nl_req_ncci(plci, N_EDATA, (byte)ncci);
3091 
3092  plci->adapter->ncci_state[ncci] = IDLE;
3093  start_internal_command(Id, plci, fax_disconnect_command);
3094  return 1;
3095  }
3096  }
3097  }
3098  return false;
3099 }
3100 
3101 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3102  PLCI *plci, APPL *appl, API_PARSE *parms)
3103 {
3104  NCCI *ncci_ptr;
3105  DATA_B3_DESC *data;
3106  word Info;
3107  word ncci;
3108  word i;
3109 
3110  dbug(1, dprintf("data_b3_req"));
3111 
3112  Info = _WRONG_IDENTIFIER;
3113  ncci = (word)(Id >> 16);
3114  dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3115 
3116  if (plci && ncci)
3117  {
3118  Info = _WRONG_STATE;
3119  if ((a->ncci_state[ncci] == CONNECTED)
3120  || (a->ncci_state[ncci] == INC_ACT_PENDING))
3121  {
3122  /* queue data */
3123  ncci_ptr = &(a->ncci[ncci]);
3124  i = ncci_ptr->data_out + ncci_ptr->data_pending;
3125  if (i >= MAX_DATA_B3)
3126  i -= MAX_DATA_B3;
3127  data = &(ncci_ptr->DBuffer[i]);
3128  data->Number = Number;
3129  if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3130  && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131  {
3132 
3133  data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3134 
3135  }
3136  else
3137  data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3138  data->Length = GET_WORD(parms[1].info);
3139  data->Handle = GET_WORD(parms[2].info);
3140  data->Flags = GET_WORD(parms[3].info);
3141  (ncci_ptr->data_pending)++;
3142 
3143  /* check for delivery confirmation */
3144  if (data->Flags & 0x0004)
3145  {
3146  i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3147  if (i >= MAX_DATA_ACK)
3148  i -= MAX_DATA_ACK;
3149  ncci_ptr->DataAck[i].Number = data->Number;
3150  ncci_ptr->DataAck[i].Handle = data->Handle;
3151  (ncci_ptr->data_ack_pending)++;
3152  }
3153 
3154  send_data(plci);
3155  return false;
3156  }
3157  }
3158  if (appl)
3159  {
3160  if (plci)
3161  {
3162  if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3163  && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164  {
3165 
3166  TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3167 
3168  }
3169  }
3170  sendf(appl,
3171  _DATA_B3_R | CONFIRM,
3172  Id,
3173  Number,
3174  "ww", GET_WORD(parms[2].info), Info);
3175  }
3176  return false;
3177 }
3178 
3179 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3180  PLCI *plci, APPL *appl, API_PARSE *parms)
3181 {
3182  word n;
3183  word ncci;
3184  word NCCIcode;
3185 
3186  dbug(1, dprintf("data_b3_res"));
3187 
3188  ncci = (word)(Id >> 16);
3189  if (plci && ncci) {
3190  n = GET_WORD(parms[0].info);
3191  dbug(1, dprintf("free(%d)", n));
3192  NCCIcode = ncci | (((word) a->Id) << 8);
3193  if (n < appl->MaxBuffer &&
3194  appl->DataNCCI[n] == NCCIcode &&
3195  (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3196  dbug(1, dprintf("found"));
3197  appl->DataNCCI[n] = 0;
3198 
3199  if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3200  channel_request_xon(plci, a->ncci_ch[ncci]);
3201  }
3202  channel_xmit_xon(plci);
3203 
3204  if (appl->DataFlags[n] & 4) {
3205  nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3206  return 1;
3207  }
3208  }
3209  }
3210  return false;
3211 }
3212 
3213 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3214  PLCI *plci, APPL *appl, API_PARSE *parms)
3215 {
3216  word Info;
3217  word ncci;
3218 
3219  dbug(1, dprintf("reset_b3_req"));
3220 
3221  Info = _WRONG_IDENTIFIER;
3222  ncci = (word)(Id >> 16);
3223  if (plci && ncci)
3224  {
3225  Info = _WRONG_STATE;
3226  switch (plci->B3_prot)
3227  {
3228  case B3_ISO8208:
3229  case B3_X25_DCE:
3230  if (a->ncci_state[ncci] == CONNECTED)
3231  {
3232  nl_req_ncci(plci, N_RESET, (byte)ncci);
3233  send_req(plci);
3234  Info = GOOD;
3235  }
3236  break;
3237  case B3_TRANSPARENT:
3238  if (a->ncci_state[ncci] == CONNECTED)
3239  {
3240  start_internal_command(Id, plci, reset_b3_command);
3241  Info = GOOD;
3242  }
3243  break;
3244  }
3245  }
3246  /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3247  sendf(appl,
3248  _RESET_B3_R | CONFIRM,
3249  Id,
3250  Number,
3251  "w", Info);
3252  return false;
3253 }
3254 
3255 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3256  PLCI *plci, APPL *appl, API_PARSE *parms)
3257 {
3258  word ncci;
3259 
3260  dbug(1, dprintf("reset_b3_res"));
3261 
3262  ncci = (word)(Id >> 16);
3263  if (plci && ncci) {
3264  switch (plci->B3_prot)
3265  {
3266  case B3_ISO8208:
3267  case B3_X25_DCE:
3268  if (a->ncci_state[ncci] == INC_RES_PENDING)
3269  {
3270  a->ncci_state[ncci] = CONNECTED;
3271  nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3272  return true;
3273  }
3274  break;
3275  }
3276  }
3277  return false;
3278 }
3279 
3280 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3281  PLCI *plci, APPL *appl, API_PARSE *parms)
3282 {
3283  word ncci;
3284  API_PARSE *ncpi;
3285  byte req;
3286 
3287  dbug(1, dprintf("connect_b3_t90_a_res"));
3288 
3289  ncci = (word)(Id >> 16);
3290  if (plci && ncci) {
3291  if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3292  a->ncci_state[ncci] = CONNECTED;
3293  }
3294  else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3295  a->ncci_state[ncci] = CONNECTED;
3296 
3297  req = N_CONNECT_ACK;
3298 
3299  /* parms[0]==0 for CAPI original message definition! */
3300  if (parms[0].info) {
3301  ncpi = &parms[1];
3302  if (ncpi->length > 2) {
3303  if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3304  add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305  }
3306  }
3307  nl_req_ncci(plci, req, (byte)ncci);
3308  return 1;
3309  }
3310  }
3311  return false;
3312 }
3313 
3314 
3315 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3316  PLCI *plci, APPL *appl, API_PARSE *msg)
3317 {
3318  word Info = 0;
3319  word i;
3320  byte tel;
3321  API_PARSE bp_parms[7];
3322 
3323  if (!plci || !msg)
3324  {
3325  Info = _WRONG_IDENTIFIER;
3326  }
3327  else
3328  {
3329  dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3330  msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3331  dbug(1, dprintf("PlciState=0x%x", plci->State));
3332  for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3333 
3334  /* check if no channel is open, no B3 connected only */
3335  if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3336  || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3337  {
3338  Info = _WRONG_STATE;
3339  }
3340  /* check message format and fill bp_parms pointer */
3341  else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3342  {
3343  Info = _WRONG_MESSAGE_FORMAT;
3344  }
3345  else
3346  {
3347  if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3348  { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3349  if (Id & EXT_CONTROLLER)
3350  {
3351  sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3352  return 0;
3353  }
3355  plci->appl = appl;
3356  clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3357  dump_c_ind_mask(plci);
3358  for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3359  { /* its quasi a connect */
3360  if (test_c_ind_mask_bit(plci, i))
3361  sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3362  }
3363  }
3364 
3365  api_save_msg(msg, "s", &plci->saved_msg);
3366  tel = plci->tel;
3367  if (Id & EXT_CONTROLLER)
3368  {
3369  if (tel) /* external controller in use by this PLCI */
3370  {
3371  if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3372  {
3373  dbug(1, dprintf("Ext_Ctrl in use 1"));
3374  Info = _WRONG_STATE;
3375  }
3376  }
3377  else /* external controller NOT in use by this PLCI ? */
3378  {
3379  if (a->AdvSignalPLCI)
3380  {
3381  dbug(1, dprintf("Ext_Ctrl in use 2"));
3382  Info = _WRONG_STATE;
3383  }
3384  else /* activate the codec */
3385  {
3386  dbug(1, dprintf("Ext_Ctrl start"));
3387  if (AdvCodecSupport(a, plci, appl, 0))
3388  {
3389  dbug(1, dprintf("Error in codec procedures"));
3390  Info = _WRONG_STATE;
3391  }
3392  else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3393  {
3395  plci->internal_command = BLOCK_PLCI; /* lock other commands */
3396  plci->command = 0;
3397  dbug(1, dprintf("continue if codec loaded"));
3398  return false;
3399  }
3400  }
3401  }
3402  }
3403  else /* external controller bit is OFF */
3404  {
3405  if (tel) /* external controller in use, need to switch off */
3406  {
3407  if (a->AdvSignalAppl == appl)
3408  {
3409  CodecIdCheck(a, plci);
3410  plci->tel = 0;
3411  plci->adv_nl = 0;
3412  dbug(1, dprintf("Ext_Ctrl disable"));
3413  }
3414  else
3415  {
3416  dbug(1, dprintf("Ext_Ctrl not requested"));
3417  }
3418  }
3419  }
3420  if (!Info)
3421  {
3422  if (plci->call_dir & CALL_DIR_OUT)
3424  else if (plci->call_dir & CALL_DIR_IN)
3426  start_internal_command(Id, plci, select_b_command);
3427  return false;
3428  }
3429  }
3430  }
3431  sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3432  return false;
3433 }
3434 
3435 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3436  PLCI *plci, APPL *appl, API_PARSE *parms)
3437 {
3438  word command;
3439  word i;
3440  word ncci;
3441  API_PARSE *m;
3442  API_PARSE m_parms[5];
3443  word codec;
3444  byte req;
3445  byte ch;
3446  byte dir;
3447  static byte chi[2] = {0x01, 0x00};
3448  static byte lli[2] = {0x01, 0x00};
3449  static byte codec_cai[2] = {0x01, 0x01};
3450  static byte null_msg = {0};
3451  static API_PARSE null_parms = { 0, &null_msg };
3452  PLCI *v_plci;
3453  word Info = 0;
3454 
3455  dbug(1, dprintf("manufacturer_req"));
3456  for (i = 0; i < 5; i++) m_parms[i].length = 0;
3457 
3458  if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3459  Info = _WRONG_MESSAGE_FORMAT;
3460  }
3461  command = GET_WORD(parms[1].info);
3462  m = &parms[2];
3463  if (!Info)
3464  {
3465  switch (command) {
3466  case _DI_ASSIGN_PLCI:
3467  if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3468  Info = _WRONG_MESSAGE_FORMAT;
3469  break;
3470  }
3471  codec = GET_WORD(m_parms[0].info);
3472  ch = m_parms[1].info[0];
3473  dir = m_parms[2].info[0];
3474  if ((i = get_plci(a))) {
3475  plci = &a->plci[i - 1];
3476  plci->appl = appl;
3477  plci->command = _MANUFACTURER_R;
3478  plci->m_command = command;
3479  plci->number = Number;
3480  plci->State = LOCAL_CONNECT;
3481  Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3482  dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3483 
3484  if ((ch == 1 || ch == 2) && (dir <= 2)) {
3485  chi[1] = (byte)(0x80 | ch);
3486  lli[1] = 0;
3488  switch (codec)
3489  {
3490  case 0:
3491  Info = add_b1(plci, &m_parms[3], 0, 0);
3492  break;
3493  case 1:
3494  add_p(plci, CAI, codec_cai);
3495  break;
3496  /* manual 'swich on' to the codec support without signalling */
3497  /* first 'assign plci' with this function, then use */
3498  case 2:
3499  if (AdvCodecSupport(a, plci, appl, 0)) {
3500  Info = _RESOURCE_ERROR;
3501  }
3502  else {
3503  Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3504  lli[1] = 0x10; /* local call codec stream */
3505  }
3506  break;
3507  }
3508 
3509  plci->State = LOCAL_CONNECT;
3510  plci->manufacturer = true;
3511  plci->command = _MANUFACTURER_R;
3512  plci->m_command = command;
3513  plci->number = Number;
3514 
3515  if (!Info)
3516  {
3517  add_p(plci, LLI, lli);
3518  add_p(plci, CHI, chi);
3519  add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3520  sig_req(plci, ASSIGN, DSIG_ID);
3521 
3522  if (!codec)
3523  {
3524  Info = add_b23(plci, &m_parms[3]);
3525  if (!Info)
3526  {
3527  nl_req_ncci(plci, ASSIGN, 0);
3528  send_req(plci);
3529  }
3530  }
3531  if (!Info)
3532  {
3533  dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3534  if (plci->spoofed_msg == SPOOFING_REQUIRED)
3535  {
3536  api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3538  plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3539  plci->command = 0;
3540  send_req(plci);
3541  return false;
3542  }
3543  if (dir == 1) {
3544  sig_req(plci, CALL_REQ, 0);
3545  }
3546  else if (!dir) {
3547  sig_req(plci, LISTEN_REQ, 0);
3548  }
3549  send_req(plci);
3550  }
3551  else
3552  {
3553  sendf(appl,
3555  Id,
3556  Number,
3557  "dww", _DI_MANU_ID, command, Info);
3558  return 2;
3559  }
3560  }
3561  }
3562  }
3563  else Info = _OUT_OF_PLCI;
3564  break;
3565 
3566  case _DI_IDI_CTRL:
3567  if (!plci)
3568  {
3569  Info = _WRONG_IDENTIFIER;
3570  break;
3571  }
3572  if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3573  Info = _WRONG_MESSAGE_FORMAT;
3574  break;
3575  }
3576  req = m_parms[0].info[0];
3577  plci->command = _MANUFACTURER_R;
3578  plci->m_command = command;
3579  plci->number = Number;
3580  if (req == CALL_REQ)
3581  {
3582  plci->b_channel = getChannel(&m_parms[1]);
3583  mixer_set_bchannel_id_esc(plci, plci->b_channel);
3584  if (plci->spoofed_msg == SPOOFING_REQUIRED)
3585  {
3587  plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3588  plci->command = 0;
3589  break;
3590  }
3591  }
3592  else if (req == LAW_REQ)
3593  {
3594  plci->cr_enquiry = true;
3595  }
3596  add_ss(plci, FTY, &m_parms[1]);
3597  sig_req(plci, req, 0);
3598  send_req(plci);
3599  if (req == HANGUP)
3600  {
3601  if (plci->NL.Id && !plci->nl_remove_id)
3602  {
3603  if (plci->channels)
3604  {
3605  for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3606  {
3607  if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3608  {
3610  cleanup_ncci_data(plci, ncci);
3611  nl_req_ncci(plci, N_DISC, (byte)ncci);
3612  }
3613  }
3614  }
3615  mixer_remove(plci);
3616  nl_req_ncci(plci, REMOVE, 0);
3617  send_req(plci);
3618  }
3619  }
3620  break;
3621 
3622  case _DI_SIG_CTRL:
3623  /* signalling control for loop activation B-channel */
3624  if (!plci)
3625  {
3626  Info = _WRONG_IDENTIFIER;
3627  break;
3628  }
3629  if (m->length) {
3630  plci->command = _MANUFACTURER_R;
3631  plci->number = Number;
3632  add_ss(plci, FTY, m);
3633  sig_req(plci, SIG_CTRL, 0);
3634  send_req(plci);
3635  }
3636  else Info = _WRONG_MESSAGE_FORMAT;
3637  break;
3638 
3639  case _DI_RXT_CTRL:
3640  /* activation control for receiver/transmitter B-channel */
3641  if (!plci)
3642  {
3643  Info = _WRONG_IDENTIFIER;
3644  break;
3645  }
3646  if (m->length) {
3647  plci->command = _MANUFACTURER_R;
3648  plci->number = Number;
3649  add_ss(plci, FTY, m);
3650  sig_req(plci, DSP_CTRL, 0);
3651  send_req(plci);
3652  }
3653  else Info = _WRONG_MESSAGE_FORMAT;
3654  break;
3655 
3656  case _DI_ADV_CODEC:
3657  case _DI_DSP_CTRL:
3658  /* TEL_CTRL commands to support non standard adjustments: */
3659  /* Ring on/off, Handset micro volume, external micro vol. */
3660  /* handset+external speaker volume, receiver+transm. gain,*/
3661  /* handsfree on (hookinfo off), set mixer command */
3662 
3663  if (command == _DI_ADV_CODEC)
3664  {
3665  if (!a->AdvCodecPLCI) {
3666  Info = _WRONG_STATE;
3667  break;
3668  }
3669  v_plci = a->AdvCodecPLCI;
3670  }
3671  else
3672  {
3673  if (plci
3674  && (m->length >= 3)
3675  && (m->info[1] == 0x1c)
3676  && (m->info[2] >= 1))
3677  {
3679  {
3680  if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3681  {
3682  Info = _WRONG_STATE;
3683  break;
3684  }
3685  a->adv_voice_coef_length = m->info[2] - 1;
3686  if (a->adv_voice_coef_length > m->length - 3)
3687  a->adv_voice_coef_length = (byte)(m->length - 3);
3690  for (i = 0; i < a->adv_voice_coef_length; i++)
3691  a->adv_voice_coef_buffer[i] = m->info[4 + i];
3693  adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3694  break;
3695  }
3696  else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3697  {
3699  {
3700  Info = _FACILITY_NOT_SUPPORTED;
3701  break;
3702  }
3703 
3704  plci->dtmf_parameter_length = m->info[2] - 1;
3705  if (plci->dtmf_parameter_length > m->length - 3)
3706  plci->dtmf_parameter_length = (byte)(m->length - 3);
3709  for (i = 0; i < plci->dtmf_parameter_length; i++)
3710  plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3712  dtmf_parameter_write(plci);
3713  break;
3714 
3715  }
3716  }
3717  v_plci = plci;
3718  }
3719 
3720  if (!v_plci)
3721  {
3722  Info = _WRONG_IDENTIFIER;
3723  break;
3724  }
3725  if (m->length) {
3726  add_ss(v_plci, FTY, m);
3727  sig_req(v_plci, TEL_CTRL, 0);
3728  send_req(v_plci);
3729  }
3730  else Info = _WRONG_MESSAGE_FORMAT;
3731 
3732  break;
3733 
3734  case _DI_OPTIONS_REQUEST:
3735  if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3736  Info = _WRONG_MESSAGE_FORMAT;
3737  break;
3738  }
3739  if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3740  {
3741  Info = _FACILITY_NOT_SUPPORTED;
3742  break;
3743  }
3744  a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3745  break;
3746 
3747 
3748 
3749  default:
3750  Info = _WRONG_MESSAGE_FORMAT;
3751  break;
3752  }
3753  }
3754 
3755  sendf(appl,
3757  Id,
3758  Number,
3759  "dww", _DI_MANU_ID, command, Info);
3760  return false;
3761 }
3762 
3763 
3764 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3765  PLCI *plci, APPL *appl, API_PARSE *msg)
3766 {
3767  word indication;
3768 
3769  API_PARSE m_parms[3];
3770  API_PARSE *ncpi;
3771  API_PARSE fax_parms[9];
3772  word i;
3773  byte len;
3774 
3775 
3776  dbug(1, dprintf("manufacturer_res"));
3777 
3778  if ((msg[0].length == 0)
3779  || (msg[1].length == 0)
3780  || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3781  {
3782  return false;
3783  }
3784  indication = GET_WORD(msg[1].info);
3785  switch (indication)
3786  {
3787 
3788  case _DI_NEGOTIATE_B3:
3789  if (!plci)
3790  break;
3791  if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3792  || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3793  {
3794  dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795  break;
3796  }
3797  if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3798  {
3799  dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3800  break;
3801  }
3802  ncpi = &m_parms[1];
3803  len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3804  if (plci->fax_connect_info_length < len)
3805  {
3806  ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3807  ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3808  }
3809  if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3810  {
3811  dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3812  }
3813  else
3814  {
3815  if (plci->fax_connect_info_length <= len)
3816  plci->fax_connect_info_buffer[len] = 0;
3817  len += 1 + plci->fax_connect_info_buffer[len];
3818  if (plci->fax_connect_info_length <= len)
3819  plci->fax_connect_info_buffer[len] = 0;
3820  len += 1 + plci->fax_connect_info_buffer[len];
3821  if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3822  plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3823  plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3824  for (i = 0; i < fax_parms[7].length; i++)
3825  plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3826  }
3827  plci->fax_connect_info_length = len;
3829  start_internal_command(Id, plci, fax_edata_ack_command);
3830  break;
3831 
3832  }
3833  return false;
3834 }
3835 
3836 /*------------------------------------------------------------------*/
3837 /* IDI callback function */
3838 /*------------------------------------------------------------------*/
3839 
3840 void callback(ENTITY *e)
3841 {
3843  APPL *appl;
3844  PLCI *plci;
3845  CAPI_MSG *m;
3846  word i, j;
3847  byte rc;
3848  byte ch;
3849  byte req;
3850  byte global_req;
3851  int no_cancel_rc;
3852 
3853  dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3854  (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3855 
3856  a = &(adapter[(byte)e->user[0]]);
3857  plci = &(a->plci[e->user[1]]);
3858  no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859 
3860  /*
3861  If new protocol code and new XDI is used then CAPI should work
3862  fully in accordance with IDI cpec an look on callback field instead
3863  of Rc field for return codes.
3864  */
3865  if (((e->complete == 0xff) && no_cancel_rc) ||
3866  (e->Rc && !no_cancel_rc)) {
3867  rc = e->Rc;
3868  ch = e->RcCh;
3869  req = e->Req;
3870  e->Rc = 0;
3871 
3872  if (e->user[0] & 0x8000)
3873  {
3874  /*
3875  If REMOVE request was sent then we have to wait until
3876  return code with Id set to zero arrives.
3877  All other return codes should be ignored.
3878  */
3879  if (req == REMOVE)
3880  {
3881  if (e->Id)
3882  {
3883  dbug(1, dprintf("cancel RC in REMOVE state"));
3884  return;
3885  }
3886  channel_flow_control_remove(plci);
3887  for (i = 0; i < 256; i++)
3888  {
3889  if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3890  a->FlowControlIdTable[i] = 0;
3891  }
3892  plci->nl_remove_id = 0;
3893  if (plci->rx_dma_descriptor > 0) {
3894  diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3895  plci->rx_dma_descriptor = 0;
3896  }
3897  }
3898  if (rc == OK_FC)
3899  {
3900  a->FlowControlIdTable[ch] = e->Id;
3901  a->FlowControlSkipTable[ch] = 0;
3902 
3903  a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3904  a->ch_flow_plci[ch] = plci->Id;
3905  plci->nl_req = 0;
3906  }
3907  else
3908  {
3909  /*
3910  Cancel return codes self, if feature was requested
3911  */
3912  if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3913  a->FlowControlIdTable[ch] = 0;
3914  if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3915  dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3916  return;
3917  }
3918  }
3919 
3920  if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3921  {
3922  a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3923  if (ch == e->ReqCh)
3924  plci->nl_req = 0;
3925  }
3926  else
3927  plci->nl_req = 0;
3928  }
3929  if (plci->nl_req)
3930  control_rc(plci, 0, rc, ch, 0, true);
3931  else
3932  {
3933  if (req == N_XON)
3934  {
3935  channel_x_on(plci, ch);
3936  if (plci->internal_command)
3937  control_rc(plci, req, rc, ch, 0, true);
3938  }
3939  else
3940  {
3941  if (plci->nl_global_req)
3942  {
3943  global_req = plci->nl_global_req;
3944  plci->nl_global_req = 0;
3945  if (rc != ASSIGN_OK) {
3946  e->Id = 0;
3947  if (plci->rx_dma_descriptor > 0) {
3948  diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3949  plci->rx_dma_descriptor = 0;
3950  }
3951  }
3952  channel_xmit_xon(plci);
3953  control_rc(plci, 0, rc, ch, global_req, true);
3954  }
3955  else if (plci->data_sent)
3956  {
3957  channel_xmit_xon(plci);
3958  plci->data_sent = false;
3959  plci->NL.XNum = 1;
3960  data_rc(plci, ch);
3961  if (plci->internal_command)
3962  control_rc(plci, req, rc, ch, 0, true);
3963  }
3964  else
3965  {
3966  channel_xmit_xon(plci);
3967  control_rc(plci, req, rc, ch, 0, true);
3968  }
3969  }
3970  }
3971  }
3972  else
3973  {
3974  /*
3975  If REMOVE request was sent then we have to wait until
3976  return code with Id set to zero arrives.
3977  All other return codes should be ignored.
3978  */
3979  if (req == REMOVE)
3980  {
3981  if (e->Id)
3982  {
3983  dbug(1, dprintf("cancel RC in REMOVE state"));
3984  return;
3985  }
3986  plci->sig_remove_id = 0;
3987  }
3988  plci->sig_req = 0;
3989  if (plci->sig_global_req)
3990  {
3991  global_req = plci->sig_global_req;
3992  plci->sig_global_req = 0;
3993  if (rc != ASSIGN_OK)
3994  e->Id = 0;
3995  channel_xmit_xon(plci);
3996  control_rc(plci, 0, rc, ch, global_req, false);
3997  }
3998  else
3999  {
4000  channel_xmit_xon(plci);
4001  control_rc(plci, req, rc, ch, 0, false);
4002  }
4003  }
4004  /*
4005  Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4006  same callback. Also if new XDI and protocol code used then jump
4007  direct to finish.
4008  */
4009  if (no_cancel_rc) {
4010  channel_xmit_xon(plci);
4011  goto capi_callback_suffix;
4012  }
4013  }
4014 
4015  channel_xmit_xon(plci);
4016 
4017  if (e->Ind) {
4018  if (e->user[0] & 0x8000) {
4019  byte Ind = e->Ind & 0x0f;
4020  byte Ch = e->IndCh;
4021  if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4022  (a->ch_flow_plci[Ch] == plci->Id)) {
4023  if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4024  dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4025  }
4026  a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4027  }
4028  nl_ind(plci);
4029  if ((e->RNR != 1) &&
4030  (a->ch_flow_plci[Ch] == plci->Id) &&
4031  (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4032  a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033  dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4034  }
4035  } else {
4036  sig_ind(plci);
4037  }
4038  e->Ind = 0;
4039  }
4040 
4041 capi_callback_suffix:
4042 
4043  while (!plci->req_in
4044  && !plci->internal_command
4045  && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4046  {
4047  j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4048 
4049  i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4050 
4051  m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4052  appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4053  dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4054  m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4055  if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4056  {
4058  plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4059  }
4060  else
4061  {
4062  plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4063  }
4064  if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4065  {
4068  }
4069  else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4070  {
4073  }
4074  i = api_put(appl, m);
4075  if (i != 0)
4076  {
4077  if (m->header.command == _DATA_B3_R)
4078 
4079  TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4080 
4081  dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4082  break;
4083  }
4084 
4085  if (plci->li_notify_update)
4086  {
4087  plci->li_notify_update = false;
4088  mixer_notify_update(plci, false);
4089  }
4090 
4091  }
4092  send_data(plci);
4093  send_req(plci);
4094 }
4095 
4096 
4097 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4098  byte nl_rc)
4099 {
4100  dword Id;
4101  dword rId;
4102  word Number;
4103  word Info = 0;
4104  word i;
4105  word ncci;
4107  APPL *appl;
4108  PLCI *rplci;
4109  byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4110  byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111 
4112  if (!plci) {
4113  dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4114  return;
4115  }
4116  dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4117  if (plci->req_in != plci->req_out)
4118  {
4119  if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4120  {
4121  dbug(1, dprintf("req_1return"));
4122  return;
4123  }
4124  /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4125  }
4126  plci->req_in = plci->req_in_start = plci->req_out = 0;
4127  dbug(1, dprintf("control_rc"));
4128 
4129  appl = plci->appl;
4130  a = plci->adapter;
4131  ncci = a->ch_ncci[ch];
4132  if (appl)
4133  {
4134  Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4135  if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4136  Number = plci->number;
4137  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));
4138  dbug(1, dprintf("channels=0x%x", plci->channels));
4139  if (plci_remove_check(plci))
4140  return;
4141  if (req == REMOVE && rc == ASSIGN_OK)
4142  {
4143  sig_req(plci, HANGUP, 0);
4144  sig_req(plci, REMOVE, 0);
4145  send_req(plci);
4146  }
4147  if (plci->command)
4148  {
4149  switch (plci->command)
4150  {
4151  case C_HOLD_REQ:
4152  dbug(1, dprintf("HoldRC=0x%x", rc));
4153  SSparms[1] = (byte)S_HOLD;
4154  if (rc != OK)
4155  {
4156  plci->SuppState = IDLE;
4157  Info = 0x2001;
4158  }
4159  sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4160  break;
4161 
4162  case C_RETRIEVE_REQ:
4163  dbug(1, dprintf("RetrieveRC=0x%x", rc));
4164  SSparms[1] = (byte)S_RETRIEVE;
4165  if (rc != OK)
4166  {
4167  plci->SuppState = CALL_HELD;
4168  Info = 0x2001;
4169  }
4170  sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4171  break;
4172 
4173  case _INFO_R:
4174  dbug(1, dprintf("InfoRC=0x%x", rc));
4175  if (rc != OK) Info = _WRONG_STATE;
4176  sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4177  break;
4178 
4179  case _CONNECT_R:
4180  dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4181  if (plci->State == INC_DIS_PENDING)
4182  break;
4183  if (plci->Sig.Id != 0xff)
4184  {
4185  if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4186  || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4187  {
4188  dbug(1, dprintf("No more IDs/Call_Req failed"));
4189  sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4190  plci_remove(plci);
4191  plci->State = IDLE;
4192  break;
4193  }
4194  if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4195  sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4196  }
4197  else /* D-ch activation */
4198  {
4199  if (rc != ASSIGN_OK)
4200  {
4201  dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4202  sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4203  plci_remove(plci);
4204  plci->State = IDLE;
4205  break;
4206  }
4207  sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4208  sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4209  plci->State = INC_ACT_PENDING;
4210  }
4211  break;
4212 
4213  case _CONNECT_I | RESPONSE:
4214  if (plci->State != INC_DIS_PENDING)
4215  plci->State = INC_CON_ACCEPT;
4216  break;
4217 
4218  case _DISCONNECT_R:
4219  if (plci->State == INC_DIS_PENDING)
4220  break;
4221  if (plci->Sig.Id != 0xff)
4222  {
4223  plci->State = OUTG_DIS_PENDING;
4224  sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4225  }
4226  break;
4227 
4228  case SUSPEND_REQ:
4229  break;
4230 
4231  case RESUME_REQ:
4232  break;
4233 
4234  case _CONNECT_B3_R:
4235  if (rc != OK)
4236  {
4237  sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4238  break;
4239  }
4240  ncci = get_ncci(plci, ch, 0);
4241  Id = (Id & 0xffff) | (((dword) ncci) << 16);
4242  plci->channels++;
4243  if (req == N_RESET)
4244  {
4246  sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4247  sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4248  }
4249  else
4250  {
4252  sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4253  }
4254  break;
4255 
4256  case _CONNECT_B3_I | RESPONSE:
4257  break;
4258 
4259  case _RESET_B3_R:
4260 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261  break;
4262 
4263  case _DISCONNECT_B3_R:
4264  sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4265  break;
4266 
4267  case _MANUFACTURER_R:
4268  break;
4269 
4270  case PERM_LIST_REQ:
4271  if (rc != OK)
4272  {
4273  Info = _WRONG_IDENTIFIER;
4274  sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4275  plci_remove(plci);
4276  }
4277  else
4278  sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4279  break;
4280 
4281  default:
4282  break;
4283  }
4284  plci->command = 0;
4285  }
4286  else if (plci->internal_command)
4287  {
4288  switch (plci->internal_command)
4289  {
4290  case BLOCK_PLCI:
4291  return;
4292 
4293  case GET_MWI_STATE:
4294  if (rc == OK) /* command supported, wait for indication */
4295  {
4296  return;
4297  }
4298  plci_remove(plci);
4299  break;
4300 
4301  /* Get Supported Services */
4302  case GETSERV_REQ_PEND:
4303  if (rc == OK) /* command supported, wait for indication */
4304  {
4305  break;
4306  }
4307  PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4308  sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4309  plci_remove(plci);
4310  break;
4311 
4312  case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4314  case CF_START_PEND: /* Call Forwarding Start pending */
4315  case CF_STOP_PEND: /* Call Forwarding Stop pending */
4316  case CCBS_REQUEST_REQ_PEND:
4319  switch (plci->internal_command)
4320  {
4322  SSparms[1] = S_INTERROGATE_DIVERSION;
4323  break;
4325  SSparms[1] = S_INTERROGATE_NUMBERS;
4326  break;
4327  case CF_START_PEND:
4328  SSparms[1] = S_CALL_FORWARDING_START;
4329  break;
4330  case CF_STOP_PEND:
4331  SSparms[1] = S_CALL_FORWARDING_STOP;
4332  break;
4333  case CCBS_REQUEST_REQ_PEND:
4334  SSparms[1] = S_CCBS_REQUEST;
4335  break;
4337  SSparms[1] = S_CCBS_DEACTIVATE;
4338  break;
4340  SSparms[1] = S_CCBS_INTERROGATE;
4341  break;
4342  }
4343  if (global_req == ASSIGN)
4344  {
4345  dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4346  return;
4347  }
4348  if (!plci->appl) break;
4349  if (rc == ISDN_GUARD_REJ)
4350  {
4351  Info = _CAPI_GUARD_ERROR;
4352  }
4353  else if (rc != OK)
4354  {
4356  }
4357  sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4358  plci->number, "wws", Info, (word)3, SSparms);
4359  if (Info) plci_remove(plci);
4360  break;
4361 
4362  /* 3pty conference pending */
4363  case PTY_REQ_PEND:
4364  if (!plci->relatedPTYPLCI) break;
4365  rplci = plci->relatedPTYPLCI;
4366  SSparms[1] = plci->ptyState;
4367  rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4368  if (rplci->tel) rId |= EXT_CONTROLLER;
4369  if (rc != OK)
4370  {
4371  Info = 0x300E; /* not supported */
4372  plci->relatedPTYPLCI = NULL;
4373  plci->ptyState = 0;
4374  }
4375  sendf(rplci->appl,
4376  _FACILITY_R | CONFIRM,
4377  rId,
4378  plci->number,
4379  "wws", Info, (word)3, SSparms);
4380  break;
4381 
4382  /* Explicit Call Transfer pending */
4383  case ECT_REQ_PEND:
4384  dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4385  if (!plci->relatedPTYPLCI) break;
4386  rplci = plci->relatedPTYPLCI;
4387  SSparms[1] = S_ECT;
4388  rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4389  if (rplci->tel) rId |= EXT_CONTROLLER;
4390  if (rc != OK)
4391  {
4392  Info = 0x300E; /* not supported */
4393  plci->relatedPTYPLCI = NULL;
4394  plci->ptyState = 0;
4395  }
4396  sendf(rplci->appl,
4397  _FACILITY_R | CONFIRM,
4398  rId,
4399  plci->number,
4400  "wws", Info, (word)3, SSparms);
4401  break;
4402 
4403  case _MANUFACTURER_R:
4404  dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4405  if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4406  {
4407  dbug(1, dprintf("No more IDs"));
4408  sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4409  plci_remove(plci); /* after codec init, internal codec commands pending */
4410  }
4411  break;
4412 
4413  case _CONNECT_R:
4414  dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4415  if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4416  {
4417  dbug(1, dprintf("No more IDs"));
4418  sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4419  plci_remove(plci); /* after codec init, internal codec commands pending */
4420  }
4421  break;
4422 
4423  case PERM_COD_HOOK: /* finished with Hook_Ind */
4424  return;
4425 
4426  case PERM_COD_CALL:
4427  dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4429  return;
4430 
4431  case PERM_COD_ASSIGN:
4432  dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4433  if (rc != ASSIGN_OK) break;
4434  sig_req(plci, CALL_REQ, 0);
4435  send_req(plci);
4437  return;
4438 
4439  /* Null Call Reference Request pending */
4440  case C_NCR_FAC_REQ:
4441  dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4442  if (global_req == ASSIGN)
4443  {
4444  if (rc == ASSIGN_OK)
4445  {
4446  return;
4447  }
4448  else
4449  {
4450  sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4451  appl->NullCREnable = false;
4452  plci_remove(plci);
4453  }
4454  }
4455  else if (req == NCR_FACILITY)
4456  {
4457  if (rc == OK)
4458  {
4459  sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4460  }
4461  else
4462  {
4463  sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4464  appl->NullCREnable = false;
4465  }
4466  plci_remove(plci);
4467  }
4468  break;
4469 
4470  case HOOK_ON_REQ:
4471  if (plci->channels)
4472  {
4473  if (a->ncci_state[ncci] == CONNECTED)
4474  {
4476  cleanup_ncci_data(plci, ncci);
4477  nl_req_ncci(plci, N_DISC, (byte)ncci);
4478  }
4479  break;
4480  }
4481  break;
4482 
4483  case HOOK_OFF_REQ:
4484  if (plci->State == INC_DIS_PENDING)
4485  break;
4486  sig_req(plci, CALL_REQ, 0);
4487  send_req(plci);
4488  plci->State = OUTG_CON_PENDING;
4489  break;
4490 
4491 
4492  case MWI_ACTIVATE_REQ_PEND:
4494  if (global_req == ASSIGN && rc == ASSIGN_OK)
4495  {
4496  dbug(1, dprintf("MWI_REQ assigned"));
4497  return;
4498  }
4499  else if (rc != OK)
4500  {
4501  if (rc == WRONG_IE)
4502  {
4503  Info = 0x2007; /* Illegal message parameter coding */
4504  dbug(1, dprintf("MWI_REQ invalid parameter"));
4505  }
4506  else
4507  {
4508  Info = 0x300B; /* not supported */
4509  dbug(1, dprintf("MWI_REQ not supported"));
4510  }
4511  /* 0x3010: Request not allowed in this state */
4512  PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513 
4514  }
4516  {
4517  PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4518  }
4519  else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4520 
4521  if (plci->cr_enquiry)
4522  {
4523  sendf(plci->appl,
4524  _FACILITY_R | CONFIRM,
4525  Id & 0xf,
4526  plci->number,
4527  "wws", Info, (word)3, SSparms);
4528  if (rc != OK) plci_remove(plci);
4529  }
4530  else
4531  {
4532  sendf(plci->appl,
4533  _FACILITY_R | CONFIRM,
4534  Id,
4535  plci->number,
4536  "wws", Info, (word)3, SSparms);
4537  }
4538  break;
4539 
4540  case CONF_BEGIN_REQ_PEND:
4541  case CONF_ADD_REQ_PEND:
4542  case CONF_SPLIT_REQ_PEND:
4543  case CONF_DROP_REQ_PEND:
4544  case CONF_ISOLATE_REQ_PEND:
4546  dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4547  if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4548  rplci = plci;
4549  rId = Id;
4550  switch (plci->internal_command)
4551  {
4552  case CONF_BEGIN_REQ_PEND:
4553  SSparms[1] = S_CONF_BEGIN;
4554  break;
4555  case CONF_ADD_REQ_PEND:
4556  SSparms[1] = S_CONF_ADD;
4557  rplci = plci->relatedPTYPLCI;
4558  rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4559  break;
4560  case CONF_SPLIT_REQ_PEND:
4561  SSparms[1] = S_CONF_SPLIT;
4562  break;
4563  case CONF_DROP_REQ_PEND:
4564  SSparms[1] = S_CONF_DROP;
4565  break;
4566  case CONF_ISOLATE_REQ_PEND:
4567  SSparms[1] = S_CONF_ISOLATE;
4568  break;
4570  SSparms[1] = S_CONF_REATTACH;
4571  break;
4572  }
4573 
4574  if (rc != OK)
4575  {
4576  Info = 0x300E; /* not supported */
4577  plci->relatedPTYPLCI = NULL;
4578  plci->ptyState = 0;
4579  }
4580  sendf(rplci->appl,
4581  _FACILITY_R | CONFIRM,
4582  rId,
4583  plci->number,
4584  "wws", Info, (word)3, SSparms);
4585  break;
4586 
4587  case VSWITCH_REQ_PEND:
4588  if (rc != OK)
4589  {
4590  if (plci->relatedPTYPLCI)
4591  {
4592  plci->relatedPTYPLCI->vswitchstate = 0;
4593  plci->relatedPTYPLCI->vsprot = 0;
4594  plci->relatedPTYPLCI->vsprotdialect = 0;
4595  }
4596  plci->vswitchstate = 0;
4597  plci->vsprot = 0;
4598  plci->vsprotdialect = 0;
4599  }
4600  else
4601  {
4602  if (plci->relatedPTYPLCI &&
4603  plci->vswitchstate == 1 &&
4604  plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4605  plci->vswitchstate = 3;
4606  }
4607  break;
4608 
4609  /* Call Deflection Request pending (SSCT) */
4610  case CD_REQ_PEND:
4611  SSparms[1] = S_CALL_DEFLECTION;
4612  if (rc != OK)
4613  {
4614  Info = 0x300E; /* not supported */
4615  plci->appl->CDEnable = 0;
4616  }
4617  sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4618  plci->number, "wws", Info, (word)3, SSparms);
4619  break;
4620 
4622  if (rc == OK)
4623  {
4624  ncci = get_ncci(plci, ch, 0);
4625  Id = (Id & 0xffff) | (((dword) ncci) << 16);
4626  plci->channels++;
4628  }
4629 
4630  default:
4631  if (plci->internal_command_queue[0])
4632  {
4633  (*(plci->internal_command_queue[0]))(Id, plci, rc);
4634  if (plci->internal_command)
4635  return;
4636  }
4637  break;
4638  }
4639  next_internal_command(Id, plci);
4640  }
4641  }
4642  else /* appl==0 */
4643  {
4644  Id = ((word)plci->Id << 8) | plci->adapter->Id;
4645  if (plci->tel) Id |= EXT_CONTROLLER;
4646 
4647  switch (plci->internal_command)
4648  {
4649  case BLOCK_PLCI:
4650  return;
4651 
4654  if (global_req == ASSIGN)
4655  {
4656  break;
4657  }
4658  else
4659  {
4660  dbug(1, dprintf("***L1 Req rem PLCI"));
4661  plci->internal_command = 0;
4662  sig_req(plci, REMOVE, 0);
4663  send_req(plci);
4664  }
4665  break;
4666 
4667  /* Call Deflection Request pending, just no appl ptr assigned */
4668  case CD_REQ_PEND:
4669  SSparms[1] = S_CALL_DEFLECTION;
4670  if (rc != OK)
4671  {
4672  Info = 0x300E; /* not supported */
4673  }
4674  for (i = 0; i < max_appl; i++)
4675  {
4676  if (application[i].CDEnable)
4677  {
4678  if (!application[i].Id) application[i].CDEnable = 0;
4679  else
4680  {
4681  sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4682  plci->number, "wws", Info, (word)3, SSparms);
4683  if (Info) application[i].CDEnable = 0;
4684  }
4685  }
4686  }
4687  plci->internal_command = 0;
4688  break;
4689 
4690  case PERM_COD_HOOK: /* finished with Hook_Ind */
4691  return;
4692 
4693  case PERM_COD_CALL:
4695  dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4696  return;
4697 
4698  case PERM_COD_ASSIGN:
4699  dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4700  plci->internal_command = 0;
4701  if (rc != ASSIGN_OK) break;
4703  sig_req(plci, CALL_REQ, 0);
4704  send_req(plci);
4705  return;
4706 
4708  if (rc == ASSIGN_OK)
4709  {
4710  plci->internal_command = 0;
4711  dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4712  add_p(plci, ESC, "\x02\x18\x00"); /* support call waiting */
4713  sig_req(plci, INDICATE_REQ, 0);
4714  send_req(plci);
4715  }
4716  else
4717  {
4718  dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4719  a->listen_active--;
4720  plci_remove(plci);
4721  plci->State = IDLE;
4722  }
4723  break;
4724 
4725  case USELAW_REQ:
4726  if (global_req == ASSIGN)
4727  {
4728  if (rc == ASSIGN_OK)
4729  {
4730  sig_req(plci, LAW_REQ, 0);
4731  send_req(plci);
4732  dbug(1, dprintf("Auto-Law assigned"));
4733  }
4734  else
4735  {
4736  dbug(1, dprintf("Auto-Law assign failed"));
4737  a->automatic_law = 3;
4738  plci->internal_command = 0;
4739  a->automatic_lawPLCI = NULL;
4740  }
4741  break;
4742  }
4743  else if (req == LAW_REQ && rc == OK)
4744  {
4745  dbug(1, dprintf("Auto-Law initiated"));
4746  a->automatic_law = 2;
4747  plci->internal_command = 0;
4748  }
4749  else
4750  {
4751  dbug(1, dprintf("Auto-Law not supported"));
4752  a->automatic_law = 3;
4753  plci->internal_command = 0;
4754  sig_req(plci, REMOVE, 0);
4755  send_req(plci);
4756  a->automatic_lawPLCI = NULL;
4757  }
4758  break;
4759  }
4760  plci_remove_check(plci);
4761  }
4762 }
4763 
4764 static void data_rc(PLCI *plci, byte ch)
4765 {
4766  dword Id;
4768  NCCI *ncci_ptr;
4769  DATA_B3_DESC *data;
4770  word ncci;
4771 
4772  if (plci->appl)
4773  {
4774  TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4775  a = plci->adapter;
4776  ncci = a->ch_ncci[ch];
4777  if (ncci && (a->ncci_plci[ncci] == plci->Id))
4778  {
4779  ncci_ptr = &(a->ncci[ncci]);
4780  dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4781  if (ncci_ptr->data_pending)
4782  {
4783  data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4784  if (!(data->Flags & 4) && a->ncci_state[ncci])
4785  {
4786  Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4787  if (plci->tel) Id |= EXT_CONTROLLER;
4788  sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4789  "ww", data->Handle, 0);
4790  }
4791  (ncci_ptr->data_out)++;
4792  if (ncci_ptr->data_out == MAX_DATA_B3)
4793  ncci_ptr->data_out = 0;
4794  (ncci_ptr->data_pending)--;
4795  }
4796  }
4797  }
4798 }
4799 
4800 static void data_ack(PLCI *plci, byte ch)
4801 {
4802  dword Id;
4804  NCCI *ncci_ptr;
4805  word ncci;
4806 
4807  a = plci->adapter;
4808  ncci = a->ch_ncci[ch];
4809  ncci_ptr = &(a->ncci[ncci]);
4810  if (ncci_ptr->data_ack_pending)
4811  {
4812  if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4813  {
4814  Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4815  if (plci->tel) Id |= EXT_CONTROLLER;
4816  sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4817  "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4818  }
4819  (ncci_ptr->data_ack_out)++;
4820  if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4821  ncci_ptr->data_ack_out = 0;
4822  (ncci_ptr->data_ack_pending)--;
4823  }
4824 }
4825 
4826 static void sig_ind(PLCI *plci)
4827 {
4828  dword x_Id;
4829  dword Id;
4830  dword rId;
4831  word i;
4832  word cip;
4833  dword cip_mask;
4834  byte *ie;
4836  API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4837 #define MAXPARMSIDS 31
4838  byte *parms[MAXPARMSIDS];
4839  byte *add_i[4];
4840  byte *multi_fac_parms[MAX_MULTI_IE];
4841  byte *multi_pi_parms[MAX_MULTI_IE];
4842  byte *multi_ssext_parms[MAX_MULTI_IE];
4843  byte *multi_CiPN_parms[MAX_MULTI_IE];
4844 
4845  byte *multi_vswitch_parms[MAX_MULTI_IE];
4846 
4847  byte ai_len;
4848  byte *esc_chi = "";
4849  byte *esc_law = "";
4850  byte *pty_cai = "";
4851  byte *esc_cr = "";
4852  byte *esc_profile = "";
4853 
4854  byte facility[256];
4855  PLCI *tplci = NULL;
4856  byte chi[] = "\x02\x18\x01";
4857  byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4858  byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4859  /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4860  /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4861  /* SMSG is situated at the end because its 0 (for compatibility reasons */
4862  /* (see Info_Mask Bit 4, first IE. then the message type) */
4863  word parms_id[] =
4864  {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4866  RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4867  CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4868  /* 14 FTY repl by ESC_CHI */
4869  /* 18 PI repl by ESC_LAW */
4870  /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4871  word multi_fac_id[] = {1, FTY};
4872  word multi_pi_id[] = {1, PI};
4873  word multi_CiPN_id[] = {1, OAD};
4874  word multi_ssext_id[] = {1, ESC_SSEXT};
4875 
4876  word multi_vswitch_id[] = {1, ESC_VSWITCH};
4877 
4878  byte *cau;
4879  word ncci;
4880  byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881  byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882  byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883  byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4884  byte force_mt_info = false;
4885  byte dir;
4886  dword d;
4887  word w;
4888 
4889  a = plci->adapter;
4890  Id = ((word)plci->Id << 8) | a->Id;
4891  PUT_WORD(&SS_Ind[4], 0x0000);
4892 
4893  if (plci->sig_remove_id)
4894  {
4895  plci->Sig.RNR = 2; /* discard */
4896  dbug(1, dprintf("SIG discard while remove pending"));
4897  return;
4898  }
4899  if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900  dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901  Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902  if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4903  {
4904  plci->Sig.RNR = 1;
4905  return;
4906  }
4907  if (plci->Sig.Ind == HANGUP && plci->channels)
4908  {
4909  plci->Sig.RNR = 1;
4910  plci->hangup_flow_ctrl_timer++;
4911  /* recover the network layer after timeout */
4912  if (plci->hangup_flow_ctrl_timer == 100)
4913  {
4914  dbug(1, dprintf("Exceptional disc"));
4915  plci->Sig.RNR = 0;
4916  plci->hangup_flow_ctrl_timer = 0;
4917  for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4918  {
4919  if (a->ncci_plci[ncci] == plci->Id)
4920  {
4921  cleanup_ncci_data(plci, ncci);
4922  if (plci->channels)plci->channels--;
4923  if (plci->appl)
4924  sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925  }
4926  }
4927  if (plci->appl)
4928  sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4929  plci_remove(plci);
4930  plci->State = IDLE;
4931  }
4932  return;
4933  }
4934 
4935  /* do first parse the info with no OAD in, because OAD will be converted */
4936  /* first the multiple facility IE, then mult. progress ind. */
4937  /* then the parameters for the info_ind + conn_ind */
4938  IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939  IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940  IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4941 
4942  IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4943 
4944  IndParse(plci, parms_id, parms, 0);
4945  IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946  esc_chi = parms[14];
4947  esc_law = parms[18];
4948  pty_cai = parms[24];
4949  esc_cr = parms[25];
4950  esc_profile = parms[27];
4951  if (esc_cr[0] && plci)
4952  {
4953  if (plci->cr_enquiry && plci->appl)
4954  {
4955  plci->cr_enquiry = false;
4956  /* d = MANU_ID */
4957  /* w = m_command */
4958  /* b = total length */
4959  /* b = indication type */
4960  /* b = length of all IEs */
4961  /* b = IE1 */
4962  /* S = IE1 length + cont. */
4963  /* b = IE2 */
4964  /* S = IE2 length + cont. */
4965  sendf(plci->appl,
4967  Id,
4968  0,
4969  "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970  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);
4971  }
4972  }
4973  /* create the additional info structure */
4974  add_i[1] = parms[15]; /* KEY of additional info */
4975  add_i[2] = parms[11]; /* UUI of additional info */
4976  ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4977 
4978  /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4979  /* indication returns by the card if requested by the function */
4980  /* AutomaticLaw() after driver init */
4981  if (a->automatic_law < 4)
4982  {
4983  if (esc_law[0]) {
4984  if (esc_law[2]) {
4985  dbug(0, dprintf("u-Law selected"));
4986  a->u_law = 1;
4987  }
4988  else {
4989  dbug(0, dprintf("a-Law selected"));
4990  a->u_law = 0;
4991  }
4992  a->automatic_law = 4;
4993  if (plci == a->automatic_lawPLCI) {
4994  plci->internal_command = 0;
4995  sig_req(plci, REMOVE, 0);
4996  send_req(plci);
4997  a->automatic_lawPLCI = NULL;
4998  }
4999  }
5000  if (esc_profile[0])
5001  {
5002  dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003  UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004  GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005  GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5006 
5007  a->profile.Global_Options &= 0x000000ffL;
5008  a->profile.B1_Protocols &= 0x000003ffL;
5009  a->profile.B2_Protocols &= 0x00001fdfL;
5010  a->profile.B3_Protocols &= 0x000000b7L;
5011 
5012  a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5014  a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015  a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016  a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017  a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5019 
5021  {
5024  }
5025 
5026 
5029  a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030  a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031 
5032 
5035 
5036 
5039 
5040 
5043 
5044 
5047 
5048 
5051 
5052 
5055 
5056 
5059 
5060 
5063 
5064  }
5065  else
5066  {
5067  a->profile.Global_Options &= 0x0000007fL;
5068  a->profile.B1_Protocols &= 0x000003dfL;
5069  a->profile.B2_Protocols &= 0x00001adfL;
5070  a->profile.B3_Protocols &= 0x000000b7L;
5072  }
5075  {
5077  }
5079  dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5083  }
5084  /* codec plci for the handset/hook state support is just an internal id */
5085  if (plci != a->AdvCodecPLCI)
5086  {
5087  force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088  force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089  SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090  SendInfo(plci, Id, parms, force_mt_info);
5091 
5092  VSwitchReqInd(plci, Id, multi_vswitch_parms);
5093 
5094  }
5095 
5096  /* switch the codec to the b-channel */
5097  if (esc_chi[0] && plci && !plci->SuppState) {
5098  plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099  mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100  dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101  if (plci->tel == ADV_VOICE && plci->appl) {
5102  SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5103  }
5104  }
5105 
5106  if (plci->appl) plci->appl->Number++;
5107 
5108  switch (plci->Sig.Ind) {
5109  /* Response to Get_Supported_Services request */
5110  case S_SUPPORTED:
5111  dbug(1, dprintf("S_Supported"));
5112  if (!plci->appl) break;
5113  if (pty_cai[0] == 4)
5114  {
5115  PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5116  }
5117  else
5118  {
5119  PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5120  }
5121  PUT_WORD(&CF_Ind[1], 0);
5122  PUT_WORD(&CF_Ind[4], 0);
5123  sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5124  plci_remove(plci);
5125  break;
5126 
5127  /* Supplementary Service rejected */
5128  case S_SERVICE_REJ:
5129  dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130  if (!pty_cai[0]) break;
5131  switch (pty_cai[5])
5132  {
5133  case ECT_EXECUTE:
5134  case THREE_PTY_END:
5135  case THREE_PTY_BEGIN:
5136  if (!plci->relatedPTYPLCI) break;
5137  tplci = plci->relatedPTYPLCI;
5138  rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139  if (tplci->tel) rId |= EXT_CONTROLLER;
5140  if (pty_cai[5] == ECT_EXECUTE)
5141  {
5142  PUT_WORD(&SS_Ind[1], S_ECT);
5143 
5144  plci->vswitchstate = 0;
5145  plci->relatedPTYPLCI->vswitchstate = 0;
5146 
5147  }
5148  else
5149  {
5150  PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5151  }
5152  if (pty_cai[2] != 0xff)
5153  {
5154  PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5155  }
5156  else
5157  {
5158  PUT_WORD(&SS_Ind[4], 0x300E);
5159  }
5160  plci->relatedPTYPLCI = NULL;
5161  plci->ptyState = 0;
5162  sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163  break;
5164 
5165  case CALL_DEFLECTION:
5166  if (pty_cai[2] != 0xff)
5167  {
5168  PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5169  }
5170  else
5171  {
5172  PUT_WORD(&SS_Ind[4], 0x300E);
5173  }
5174  PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175  for (i = 0; i < max_appl; i++)
5176  {
5177  if (application[i].CDEnable)
5178  {
5179  if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180  application[i].CDEnable = false;
5181  }
5182  }
5183  break;
5184 
5186  case ACTIVATION_DIVERSION:
5191  case CCBS_REQUEST:
5192  case CCBS_DEACTIVATE:
5193  case CCBS_INTERROGATE:
5194  if (!plci->appl) break;
5195  if (pty_cai[2] != 0xff)
5196  {
5197  PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5198  }
5199  else
5200  {
5201  PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5202  }
5203  switch (pty_cai[5])
5204  {
5206  dbug(1, dprintf("Deact_Div"));
5207  Interr_Err_Ind[0] = 0x9;
5208  Interr_Err_Ind[3] = 0x6;
5209  PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5210  break;
5211  case ACTIVATION_DIVERSION:
5212  dbug(1, dprintf("Act_Div"));
5213  Interr_Err_Ind[0] = 0x9;
5214  Interr_Err_Ind[3] = 0x6;
5215  PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5216  break;
5220  dbug(1, dprintf("Interr_Div"));
5221  Interr_Err_Ind[0] = 0xa;
5222  Interr_Err_Ind[3] = 0x7;
5223  PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5224  break;
5226  dbug(1, dprintf("Interr_Num"));
5227  Interr_Err_Ind[0] = 0xa;
5228  Interr_Err_Ind[3] = 0x7;
5229  PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230  break;
5231  case CCBS_REQUEST:
5232  dbug(1, dprintf("CCBS Request"));
5233  Interr_Err_Ind[0] = 0xd;
5234  Interr_Err_Ind[3] = 0xa;
5235  PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5236  break;
5237  case CCBS_DEACTIVATE:
5238  dbug(1, dprintf("CCBS Deactivate"));
5239  Interr_Err_Ind[0] = 0x9;
5240  Interr_Err_Ind[3] = 0x6;
5241  PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5242  break;
5243  case CCBS_INTERROGATE:
5244  dbug(1, dprintf("CCBS Interrogate"));
5245  Interr_Err_Ind[0] = 0xb;
5246  Interr_Err_Ind[3] = 0x8;
5247  PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248  break;
5249  }
5250  PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251  sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252  plci_remove(plci);
5253  break;
5254  case ACTIVATION_MWI:
5255  case DEACTIVATION_MWI:
5256  if (pty_cai[5] == ACTIVATION_MWI)
5257  {
5258  PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5259  }
5260  else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5261 
5262  if (pty_cai[2] != 0xff)
5263  {
5264  PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5265  }
5266  else
5267  {
5268  PUT_WORD(&SS_Ind[4], 0x300E);
5269  }
5270 
5271  if (plci->cr_enquiry)
5272  {
5273  sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5274  plci_remove(plci);
5275  }
5276  else
5277  {
5278  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279  }
5280  break;
5281  case CONF_ADD: /* ERROR */
5282  case CONF_BEGIN:
5283  case CONF_DROP:
5284  case CONF_ISOLATE:
5285  case CONF_REATTACH:
5286  CONF_Ind[0] = 9;
5287  CONF_Ind[3] = 6;
5288  switch (pty_cai[5])
5289  {
5290  case CONF_BEGIN:
5291  PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5292  plci->ptyState = 0;
5293  break;
5294  case CONF_DROP:
5295  CONF_Ind[0] = 5;
5296  CONF_Ind[3] = 2;
5297  PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298  plci->ptyState = CONNECTED;
5299  break;
5300  case CONF_ISOLATE:
5301  CONF_Ind[0] = 5;
5302  CONF_Ind[3] = 2;
5303  PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304  plci->ptyState = CONNECTED;
5305  break;
5306  case CONF_REATTACH:
5307  CONF_Ind[0] = 5;
5308  CONF_Ind[3] = 2;
5309  PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310  plci->ptyState = CONNECTED;
5311  break;
5312  case CONF_ADD:
5313  PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314  plci->relatedPTYPLCI = NULL;
5315  tplci = plci->relatedPTYPLCI;
5316  if (tplci) tplci->ptyState = CONNECTED;
5317  plci->ptyState = CONNECTED;
5318  break;
5319  }
5320 
5321  if (pty_cai[2] != 0xff)
5322  {
5323  PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5324  }
5325  else
5326  {
5327  PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328  within the required time */
5329  }
5330 
5331  PUT_DWORD(&CONF_Ind[6], 0x0);
5332  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5333  break;
5334  }
5335  break;
5336 
5337  /* Supplementary Service indicates success */
5338  case S_SERVICE:
5339  dbug(1, dprintf("Service_Ind"));
5340  PUT_WORD(&CF_Ind[4], 0);
5341  switch (pty_cai[5])
5342  {
5343  case THREE_PTY_END:
5344  case THREE_PTY_BEGIN:
5345  case ECT_EXECUTE:
5346  if (!plci->relatedPTYPLCI) break;
5347  tplci = plci->relatedPTYPLCI;
5348  rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349  if (tplci->tel) rId |= EXT_CONTROLLER;
5350  if (pty_cai[5] == ECT_EXECUTE)
5351  {
5352  PUT_WORD(&SS_Ind[1], S_ECT);
5353 
5354  if (plci->vswitchstate != 3)
5355  {
5356 
5357  plci->ptyState = IDLE;
5358  plci->relatedPTYPLCI = NULL;
5359  plci->ptyState = 0;
5360 
5361  }
5362 
5363  dbug(1, dprintf("ECT OK"));
5364  sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5365 
5366 
5367 
5368  }
5369  else
5370  {
5371  switch (plci->ptyState)
5372  {
5373  case S_3PTY_BEGIN:
5374  plci->ptyState = CONNECTED;
5375  dbug(1, dprintf("3PTY ON"));
5376  break;
5377 
5378  case S_3PTY_END:
5379  plci->ptyState = IDLE;
5380  plci->relatedPTYPLCI = NULL;
5381  plci->ptyState = 0;
5382  dbug(1, dprintf("3PTY OFF"));
5383  break;
5384  }
5385  PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386  sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5387  }
5388  break;
5389 
5390  case CALL_DEFLECTION:
5391  PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392  for (i = 0; i < max_appl; i++)
5393  {
5394  if (application[i].CDEnable)
5395  {
5396  if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397  application[i].CDEnable = false;
5398  }
5399  }
5400  break;
5401 
5403  case ACTIVATION_DIVERSION:
5404  if (!plci->appl) break;
5405  PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406  PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407  sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5408  plci_remove(plci);
5409  break;
5410 
5415  case CCBS_REQUEST:
5416  case CCBS_DEACTIVATE:
5417  case CCBS_INTERROGATE:
5418  if (!plci->appl) break;
5419  switch (pty_cai[5])
5420  {
5424  dbug(1, dprintf("Interr_Div"));
5425  PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426  pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5427  break;
5429  dbug(1, dprintf("Interr_Num"));
5430  PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431  pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432  break;
5433  case CCBS_REQUEST:
5434  dbug(1, dprintf("CCBS Request"));
5435  PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436  pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5437  break;
5438  case CCBS_DEACTIVATE:
5439  dbug(1, dprintf("CCBS Deactivate"));
5440  PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441  pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5442  break;
5443  case CCBS_INTERROGATE:
5444  dbug(1, dprintf("CCBS Interrogate"));
5445  PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446  pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447  break;
5448  }
5449  PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450  PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451  sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5452  plci_remove(plci);
5453  break;
5454 
5455  case ACTIVATION_MWI:
5456  case DEACTIVATION_MWI:
5457  if (pty_cai[5] == ACTIVATION_MWI)
5458  {
5459  PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5460  }
5461  else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462  if (plci->cr_enquiry)
5463  {
5464  sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5465  plci_remove(plci);
5466  }
5467  else
5468  {
5469  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470  }
5471  break;
5472  case MWI_INDICATION:
5473  if (pty_cai[0] >= 0x12)
5474  {
5475  PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476  pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477  pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478  if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5479  {
5480  if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5481  {
5482  sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5483  plci_remove(plci);
5484  return;
5485  }
5486  else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5487  pty_cai[0] = 0;
5488  }
5489  else
5490  {
5491  for (i = 0; i < max_appl; i++)
5492  {
5493  if (a->Notification_Mask[i]&SMASK_MWI)
5494  {
5495  sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5496  pty_cai[0] = 0;
5497  }
5498  }
5499  }
5500 
5501  if (!pty_cai[0])
5502  { /* acknowledge */
5503  facility[2] = 0; /* returncode */
5504  }
5505  else facility[2] = 0xff;
5506  }
5507  else
5508  {
5509  /* reject */
5510  facility[2] = 0xff; /* returncode */
5511  }
5512  facility[0] = 2;
5513  facility[1] = MWI_RESPONSE; /* Function */
5514  add_p(plci, CAI, facility);
5515  add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516  sig_req(plci, S_SERVICE, 0);
5517  send_req(plci);
5518  plci->command = 0;
5519  next_internal_command(Id, plci);
5520  break;
5521  case CONF_ADD: /* OK */
5522  case CONF_BEGIN:
5523  case CONF_DROP:
5524  case CONF_ISOLATE:
5525  case CONF_REATTACH:
5526  case CONF_PARTYDISC:
5527  CONF_Ind[0] = 9;
5528  CONF_Ind[3] = 6;
5529  switch (pty_cai[5])
5530  {
5531  case CONF_BEGIN:
5532  PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533  if (pty_cai[0] == 6)
5534  {
5535  d = pty_cai[6];
5536  PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5537  }
5538  else
5539  {
5540  PUT_DWORD(&CONF_Ind[6], 0x0);
5541  }
5542  break;
5543  case CONF_ISOLATE:
5544  PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5545  CONF_Ind[0] = 5;
5546  CONF_Ind[3] = 2;
5547  break;
5548  case CONF_REATTACH:
5549  PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5550  CONF_Ind[0] = 5;
5551  CONF_Ind[3] = 2;
5552  break;
5553  case CONF_DROP:
5554  PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5555  CONF_Ind[0] = 5;
5556  CONF_Ind[3] = 2;
5557  break;
5558  case CONF_ADD:
5559  PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5560  d = pty_cai[6];
5561  PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562  tplci = plci->relatedPTYPLCI;
5563  if (tplci) tplci->ptyState = CONNECTED;
5564  break;
5565  case CONF_PARTYDISC:
5566  CONF_Ind[0] = 7;
5567  CONF_Ind[3] = 4;
5568  PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5569  d = pty_cai[6];
5570  PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571  break;
5572  }
5573  plci->ptyState = CONNECTED;
5574  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5575  break;
5576  case CCBS_INFO_RETAIN:
5578  case CCBS_STOP_ALERTING:
5579  CONF_Ind[0] = 5;
5580  CONF_Ind[3] = 2;
5581  switch (pty_cai[5])
5582  {
5583  case CCBS_INFO_RETAIN:
5584  PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5585  break;
5586  case CCBS_STOP_ALERTING:
5587  PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5588  break;
5590  PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5591  CONF_Ind[0] = 7;
5592  CONF_Ind[3] = 4;
5593  CONF_Ind[6] = 0;
5594  CONF_Ind[7] = 0;
5595  break;
5596  }
5597  w = pty_cai[6];
5598  PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5599 
5600  if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5601  {
5602  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5603  }
5604  else
5605  {
5606  for (i = 0; i < max_appl; i++)
5607  if (a->Notification_Mask[i] & SMASK_CCBS)
5608  sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5609  }
5610  break;
5611  }
5612  break;
5613  case CALL_HOLD_REJ:
5614  cau = parms[7];
5615  if (cau)
5616  {
5617  i = _L3_CAUSE | cau[2];
5618  if (cau[2] == 0) i = 0x3603;
5619  }
5620  else
5621  {
5622  i = 0x3603;
5623  }
5624  PUT_WORD(&SS_Ind[1], S_HOLD);
5625  PUT_WORD(&SS_Ind[4], i);
5626  if (plci->SuppState == HOLD_REQUEST)
5627  {
5628  plci->SuppState = IDLE;
5629  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5630  }
5631  break;
5632 
5633  case CALL_HOLD_ACK:
5634  if (plci->SuppState == HOLD_REQUEST)
5635  {
5636  plci->SuppState = CALL_HELD;
5637  CodecIdCheck(a, plci);
5638  start_internal_command(Id, plci, hold_save_command);
5639  }
5640  break;
5641 
5642  case CALL_RETRIEVE_REJ:
5643  cau = parms[7];
5644  if (cau)
5645  {
5646  i = _L3_CAUSE | cau[2];
5647  if (cau[2] == 0) i = 0x3603;
5648  }
5649  else
5650  {
5651  i = 0x3603;
5652  }
5653  PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654  PUT_WORD(&SS_Ind[4], i);
5655  if (plci->SuppState == RETRIEVE_REQUEST)
5656  {
5657  plci->SuppState = CALL_HELD;
5658  CodecIdCheck(a, plci);
5659  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5660  }
5661  break;
5662 
5663  case CALL_RETRIEVE_ACK:
5664  PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665  if (plci->SuppState == RETRIEVE_REQUEST)
5666  {
5667  plci->SuppState = IDLE;
5669  plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670  if (plci->tel)
5671  {
5672  mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673  dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674  SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675  if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5676  {
5677  dbug(1, dprintf("Get B-ch"));
5678  start_internal_command(Id, plci, retrieve_restore_command);
5679  }
5680  else
5681  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682  }
5683  else
5684  start_internal_command(Id, plci, retrieve_restore_command);
5685  }
5686  break;
5687 
5688  case INDICATE_IND:
5689  if (plci->State != LISTENING) {
5690  sig_req(plci, HANGUP, 0);
5691  send_req(plci);
5692  break;
5693  }
5694  cip = find_cip(a, parms[4], parms[6]);
5695  cip_mask = 1L << cip;
5696  dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697  clear_c_ind_mask(plci);
5698  if (!remove_started && !a->adapter_disabled)
5699  {
5700  set_c_ind_mask_bit(plci, MAX_APPL);
5701  group_optimization(a, plci);
5702  for (i = 0; i < max_appl; i++) {
5703  if (application[i].Id
5704  && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705  && CPN_filter_ok(parms[0], a, i)
5706  && test_group_ind_mask_bit(plci, i)) {
5707  dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708  set_c_ind_mask_bit(plci, i);
5709  dump_c_ind_mask(plci);
5710  plci->State = INC_CON_PENDING;
5711  plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5713  if (esc_chi[0]) {
5714  plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715  mixer_set_bchannel_id_esc(plci, plci->b_channel);
5716  }
5717  /* if a listen on the ext controller is done, check if hook states */
5718  /* are supported or if just a on board codec must be activated */
5719  if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720  if (a->profile.Global_Options & HANDSET)
5721  plci->tel = ADV_VOICE;
5722  else if (a->profile.Global_Options & ON_BOARD_CODEC)
5723  plci->tel = CODEC;
5724  if (plci->tel) Id |= EXT_CONTROLLER;
5725  a->codec_listen[i] = plci;
5726  }
5727 
5728  sendf(&application[i], _CONNECT_I, Id, 0,
5729  "wSSSSSSSbSSSSS", cip, /* CIP */
5730  parms[0], /* CalledPartyNumber */
5731  multi_CiPN_parms[0], /* CallingPartyNumber */
5732  parms[2], /* CalledPartySubad */
5733  parms[3], /* CallingPartySubad */
5734  parms[4], /* BearerCapability */
5735  parms[5], /* LowLC */
5736  parms[6], /* HighLC */
5737  ai_len, /* nested struct add_i */
5738  add_i[0], /* B channel info */
5739  add_i[1], /* keypad facility */
5740  add_i[2], /* user user data */
5741  add_i[3], /* nested facility */
5742  multi_CiPN_parms[1] /* second CiPN(SCR) */
5743  );
5744  SendSSExtInd(&application[i],
5745  plci,
5746  Id,
5747  multi_ssext_parms);
5748  SendSetupInfo(&application[i],
5749  plci,
5750  Id,
5751  parms,
5752  SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753  }
5754  }
5755  clear_c_ind_mask_bit(plci, MAX_APPL);
5756  dump_c_ind_mask(plci);
5757  }
5758  if (c_ind_mask_empty(plci)) {
5759  sig_req(plci, HANGUP, 0);
5760  send_req(plci);
5761  plci->State = IDLE;
5762  }
5763  plci->notifiedcall = 0;
5764  a->listen_active--;
5765  listen_check(a);
5766  break;
5767 
5768  case CALL_PEND_NOTIFY:
5769  plci->notifiedcall = 1;
5770  listen_check(a);
5771  break;
5772 
5773  case CALL_IND:
5774  case CALL_CON:
5775  if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5776  {
5777  if (plci->internal_command == PERM_COD_CONN_PEND)
5778  {
5779  if (plci->State == ADVANCED_VOICE_NOSIG)
5780  {
5781  dbug(1, dprintf("***Codec OK"));
5782  if (a->AdvSignalPLCI)
5783  {
5784  tplci = a->AdvSignalPLCI;
5785  if (tplci->spoofed_msg)
5786  {
5787  dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5788  tplci->command = 0;
5789  tplci->internal_command = 0;
5790  x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791  switch (tplci->spoofed_msg)
5792  {
5793  case CALL_RES:
5794  tplci->command = _CONNECT_I | RESPONSE;
5795  api_load_msg(&tplci->saved_msg, saved_parms);
5796  add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797  if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5798  {
5799  /* early B3 connect (CIP mask bit 9) no release after a disc */
5800  add_p(tplci, LLI, "\x01\x01");
5801  }
5802  add_s(tplci, CONN_NR, &saved_parms[2]);
5803  add_s(tplci, LLC, &saved_parms[4]);
5804  add_ai(tplci, &saved_parms[5]);
5805  tplci->State = INC_CON_ACCEPT;
5806  sig_req(tplci, CALL_RES, 0);
5807  send_req(tplci);
5808  break;
5809 
5810  case AWAITING_SELECT_B:
5811  dbug(1, dprintf("Select_B continue"));
5812  start_internal_command(x_Id, tplci, select_b_command);
5813  break;
5814 
5815  case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816  if (!tplci->Sig.Id)
5817  {
5818  dbug(1, dprintf("No SigID!"));
5819  sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5820  plci_remove(tplci);
5821  break;
5822  }
5823  tplci->command = _MANUFACTURER_R;
5824  api_load_msg(&tplci->saved_msg, saved_parms);
5825  dir = saved_parms[2].info[0];
5826  if (dir == 1) {
5827  sig_req(tplci, CALL_REQ, 0);
5828  }
5829  else if (!dir) {
5830  sig_req(tplci, LISTEN_REQ, 0);
5831  }
5832  send_req(tplci);
5833  sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834  break;
5835 
5836  case (CALL_REQ | AWAITING_MANUF_CON):
5837  sig_req(tplci, CALL_REQ, 0);
5838  send_req(tplci);
5839  break;
5840 
5841  case CALL_REQ:
5842  if (!tplci->Sig.Id)
5843  {
5844  dbug(1, dprintf("No SigID!"));
5845  sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5846  plci_remove(tplci);
5847  break;
5848  }
5849  tplci->command = _CONNECT_R;
5850  api_load_msg(&tplci->saved_msg, saved_parms);
5851  add_s(tplci, CPN, &saved_parms[1]);
5852  add_s(tplci, DSA, &saved_parms[3]);
5853  add_ai(tplci, &saved_parms[9]);
5854  sig_req(tplci, CALL_REQ, 0);
5855  send_req(tplci);
5856  break;
5857 
5858  case CALL_RETRIEVE:
5859  tplci->command = C_RETRIEVE_REQ;
5860  sig_req(tplci, CALL_RETRIEVE, 0);
5861  send_req(tplci);
5862  break;
5863  }
5864  tplci->spoofed_msg = 0;
5865  if (tplci->internal_command == 0)
5866  next_internal_command(x_Id, tplci);
5867  }
5868  }
5869  next_internal_command(Id, plci);
5870  break;
5871  }
5872  dbug(1, dprintf("***Codec Hook Init Req"));
5874  add_p(plci, FTY, "\x01\x09"); /* Get Hook State*/
5875  sig_req(plci, TEL_CTRL, 0);
5876  send_req(plci);
5877  }
5878  }
5879  else if (plci->command != _MANUFACTURER_R /* old style permanent connect */
5880  && plci->State != INC_ACT_PENDING)
5881  {
5882  mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883  if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5884  {
5885  chi[2] = plci->b_channel;
5886  SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5887  }
5888  sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889  plci->State = INC_ACT_PENDING;
5890  }
5891  break;
5892 
5893  case TEL_CTRL:
5894  ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895  if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896  switch (ie[1] & 0x91) {
5897  case 0x80: /* hook off */
5898  case 0x81:
5899  if (plci->internal_command == PERM_COD_HOOK)
5900  {
5901  dbug(1, dprintf("init:hook_off"));
5902  plci->hook_state = ie[1];
5903  next_internal_command(Id, plci);
5904  break;
5905  }
5906  else /* ignore doubled hook indications */
5907  {
5908  if (((plci->hook_state) & 0xf0) == 0x80)
5909  {
5910  dbug(1, dprintf("ignore hook"));
5911  break;
5912  }
5913  plci->hook_state = ie[1]&0x91;
5914  }
5915  /* check for incoming call pending */
5916  /* and signal '+'.Appl must decide */
5917  /* with connect_res if call must */
5918  /* accepted or not */
5919  for (i = 0, tplci = NULL; i < max_appl; i++) {
5920  if (a->codec_listen[i]
5921  && (a->codec_listen[i]->State == INC_CON_PENDING
5922  || a->codec_listen[i]->State == INC_CON_ALERT)) {
5923  tplci = a->codec_listen[i];
5924  tplci->appl = &application[i];
5925  }
5926  }
5927  /* no incoming call, do outgoing call */
5928  /* and signal '+' if outg. setup */
5929  if (!a->AdvSignalPLCI && !tplci) {
5930  if ((i = get_plci(a))) {
5931  a->AdvSignalPLCI = &a->plci[i - 1];
5932  tplci = a->AdvSignalPLCI;
5933  tplci->tel = ADV_VOICE;
5934  PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935  if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936  /* early B3 connect (CIP mask bit 9) no release after a disc */
5937  add_p(tplci, LLI, "\x01\x01");
5938  }
5939  add_p(tplci, CAI, voice_cai);
5940  add_p(tplci, OAD, a->TelOAD);
5941  add_p(tplci, OSA, a->TelOSA);
5942  add_p(tplci, SHIFT | 6, NULL);
5943  add_p(tplci, SIN, "\x02\x01\x00");
5944  add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945  sig_req(tplci, ASSIGN, DSIG_ID);
5947  a->AdvSignalPLCI->command = 0;
5948  tplci->appl = a->AdvSignalAppl;
5950  send_req(tplci);
5951  }
5952 
5953  }
5954 
5955  if (!tplci) break;
5956  Id = ((word)tplci->Id << 8) | a->Id;
5957  Id |= EXT_CONTROLLER;
5958  sendf(tplci->appl,
5959  _FACILITY_I,
5960  Id,
5961  0,
5962  "ws", (word)0, "\x01+");
5963  break;
5964 
5965  case 0x90: /* hook on */
5966  case 0x91:
5967  if (plci->internal_command == PERM_COD_HOOK)
5968  {
5969  dbug(1, dprintf("init:hook_on"));
5970  plci->hook_state = ie[1] & 0x91;
5971  next_internal_command(Id, plci);
5972  break;
5973  }
5974  else /* ignore doubled hook indications */
5975  {
5976  if (((plci->hook_state) & 0xf0) == 0x90) break;
5977  plci->hook_state = ie[1] & 0x91;
5978  }
5979  /* hangup the adv. voice call and signal '-' to the appl */
5980  if (a->AdvSignalPLCI) {
5981  Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982  if (plci->tel) Id |= EXT_CONTROLLER;
5983  sendf(a->AdvSignalAppl,
5984  _FACILITY_I,
5985  Id,
5986  0,
5987  "ws", (word)0, "\x01-");
5989  a->AdvSignalPLCI->command = 0;
5990  sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991  send_req(a->AdvSignalPLCI);
5992  }
5993  break;
5994  }
5995  }
5996  break;
5997 
5998  case RESUME:
5999  clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000  PUT_WORD(&resume_cau[4], GOOD);
6001  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6002  break;
6003 
6004  case SUSPEND:
6005  clear_c_ind_mask(plci);
6006 
6007  if (plci->NL.Id && !plci->nl_remove_id) {
6008  mixer_remove(plci);
6009  nl_req_ncci(plci, REMOVE, 0);
6010  }
6011  if (!plci->sig_remove_id) {
6012  plci->internal_command = 0;
6013  sig_req(plci, REMOVE, 0);
6014  }
6015  send_req(plci);
6016  if (!plci->channels) {
6017  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018  sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6019  }
6020  break;
6021 
6022  case SUSPEND_REJ:
6023  break;
6024 
6025  case HANGUP:
6026  plci->hangup_flow_ctrl_timer = 0;
6027  if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028  cau = parms[7];
6029  if (cau) {
6030  i = _L3_CAUSE | cau[2];
6031  if (cau[2] == 0) i = 0;
6032  else if (cau[2] == 8) i = _L1_ERROR;
6033  else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034  else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6035  }
6036  else {
6037  i = _L3_ERROR;
6038  }
6039 
6040  if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6041  {
6042  for (i = 0; i < max_appl; i++)
6043  {
6044  if (test_c_ind_mask_bit(plci, i))
6045  sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046  }
6047  }
6048  else
6049  {
6050  clear_c_ind_mask(plci);
6051  }
6052  if (!plci->appl)
6053  {
6054  if (plci->State == LISTENING)
6055  {
6056  plci->notifiedcall = 0;
6057  a->listen_active--;
6058  }
6059  plci->State = INC_DIS_PENDING;
6060  if (c_ind_mask_empty(plci))
6061  {
6062  plci->State = IDLE;
6063  if (plci->NL.Id && !plci->nl_remove_id)
6064  {
6065  mixer_remove(plci);
6066  nl_req_ncci(plci, REMOVE, 0);
6067  }
6068  if (!plci->sig_remove_id)
6069  {
6070  plci->internal_command = 0;
6071  sig_req(plci, REMOVE, 0);
6072  }
6073  send_req(plci);
6074  }
6075  }
6076  else
6077  {
6078  /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6079  /* result in a second HANGUP! Don't generate another */
6080  /* DISCONNECT */
6081  if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6082  {
6083  if (plci->State == RESUMING)
6084  {
6085  PUT_WORD(&resume_cau[4], i);
6086  sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6087  }
6088  plci->State = INC_DIS_PENDING;
6089  sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090  }
6091  }
6092  break;
6093 
6094  case SSEXT_IND:
6095  SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6096  break;
6097 
6098  case VSWITCH_REQ:
6099  VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100  break;
6101  case VSWITCH_IND:
6102  if (plci->relatedPTYPLCI &&
6103  plci->vswitchstate == 3 &&
6104  plci->relatedPTYPLCI->vswitchstate == 3 &&
6105  parms[MAXPARMSIDS - 1][0])
6106  {
6107  add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108  sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109  send_req(plci->relatedPTYPLCI);
6110  }
6111  else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6112  break;
6113 
6114  }
6115 }
6116 
6117 
6118 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6119 {
6120  word i;
6121  byte *ie;
6122  word Info_Number;
6123  byte *Info_Element;
6124  word Info_Mask = 0;
6125 
6126  dbug(1, dprintf("SetupInfo"));
6127 
6128  for (i = 0; i < MAXPARMSIDS; i++) {
6129  ie = parms[i];
6130  Info_Number = 0;
6131  Info_Element = ie;
6132  if (ie[0]) {
6133  switch (i) {
6134  case 0:
6135  dbug(1, dprintf("CPN "));
6136  Info_Number = 0x0070;
6137  Info_Mask = 0x80;
6138  Info_Sent_Flag = true;
6139  break;
6140  case 8: /* display */
6141  dbug(1, dprintf("display(%d)", i));
6142  Info_Number = 0x0028;
6143  Info_Mask = 0x04;
6144  Info_Sent_Flag = true;
6145  break;
6146  case 16: /* Channel Id */
6147  dbug(1, dprintf("CHI"));
6148  Info_Number = 0x0018;
6149  Info_Mask = 0x100;
6150  Info_Sent_Flag = true;
6151  mixer_set_bchannel_id(plci, Info_Element);
6152  break;
6153  case 19: /* Redirected Number */
6154  dbug(1, dprintf("RDN"));
6155  Info_Number = 0x0074;
6156  Info_Mask = 0x400;
6157  Info_Sent_Flag = true;
6158  break;
6159  case 20: /* Redirected Number extended */
6160  dbug(1, dprintf("RDX"));
6161  Info_Number = 0x0073;
6162  Info_Mask = 0x400;
6163  Info_Sent_Flag = true;
6164  break;
6165  case 22: /* Redirecing Number */
6166  dbug(1, dprintf("RIN"));
6167  Info_Number = 0x0076;
6168  Info_Mask = 0x400;
6169  Info_Sent_Flag = true;
6170  break;
6171  default:
6172  Info_Number = 0;
6173  break;
6174  }
6175  }
6176 
6177  if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6178  Info_Number = 0x8000 | 5;
6179  Info_Mask = 0x10;
6180  Info_Element = "";
6181  }
6182 
6183  if (Info_Sent_Flag && Info_Number) {
6184  if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6185  sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6186  }
6187  }
6188  }
6189 }
6190 
6191 
6192 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6193 {
6194  word i;
6195  word j;
6196  word k;
6197  byte *ie;
6198  word Info_Number;
6199  byte *Info_Element;
6200  word Info_Mask = 0;
6201  static byte charges[5] = {4, 0, 0, 0, 0};
6202  static byte cause[] = {0x02, 0x80, 0x00};
6203  APPL *appl;
6204 
6205  dbug(1, dprintf("InfoParse "));
6206 
6207  if (
6208  !plci->appl
6209  && !plci->State
6210  && plci->Sig.Ind != NCR_FACILITY
6211  )
6212  {
6213  dbug(1, dprintf("NoParse "));
6214  return;
6215  }
6216  cause[2] = 0;
6217  for (i = 0; i < MAXPARMSIDS; i++) {
6218  ie = parms[i];
6219  Info_Number = 0;
6220  Info_Element = ie;
6221  if (ie[0]) {
6222  switch (i) {
6223  case 0:
6224  dbug(1, dprintf("CPN "));
6225  Info_Number = 0x0070;
6226  Info_Mask = 0x80;
6227  break;
6228  case 7: /* ESC_CAU */
6229  dbug(1, dprintf("cau(0x%x)", ie[2]));
6230  Info_Number = 0x0008;
6231  Info_Mask = 0x00;
6232  cause[2] = ie[2];
6233  Info_Element = NULL;
6234  break;
6235  case 8: /* display */
6236  dbug(1, dprintf("display(%d)", i));
6237  Info_Number = 0x0028;
6238  Info_Mask = 0x04;
6239  break;
6240  case 9: /* Date display */
6241  dbug(1, dprintf("date(%d)", i));
6242  Info_Number = 0x0029;
6243  Info_Mask = 0x02;
6244  break;
6245  case 10: /* charges */
6246  for (j = 0; j < 4; j++) charges[1 + j] = 0;
6247  for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6248  for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6249  Info_Number = 0x4000;
6250  Info_Mask = 0x40;
6251  Info_Element = charges;
6252  break;
6253  case 11: /* user user info */
6254  dbug(1, dprintf("uui"));
6255  Info_Number = 0x007E;
6256  Info_Mask = 0x08;
6257  break;
6258  case 12: /* congestion receiver ready */
6259  dbug(1, dprintf("clRDY"));
6260  Info_Number = 0x00B0;
6261  Info_Mask = 0x08;
6262  Info_Element = "";
6263  break;
6264  case 13: /* congestion receiver not ready */
6265  dbug(1, dprintf("clNRDY"));
6266  Info_Number = 0x00BF;
6267  Info_Mask = 0x08;
6268  Info_Element = "";
6269  break;
6270  case 15: /* Keypad Facility */
6271  dbug(1, dprintf("KEY"));
6272  Info_Number = 0x002C;
6273  Info_Mask = 0x20;
6274  break;
6275  case 16: /* Channel Id */
6276  dbug(1, dprintf("CHI"));
6277  Info_Number = 0x0018;
6278  Info_Mask = 0x100;
6279  mixer_set_bchannel_id(plci, Info_Element);
6280  break;
6281  case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6282  dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6283  if (!cause[2] || cause[2] < 0x80) break; /* eg. layer 1 error */
6284  Info_Number = 0x0008;
6285  Info_Mask = 0x01;
6286  if (cause[2] != ie[2]) Info_Element = cause;
6287  break;
6288  case 19: /* Redirected Number */
6289  dbug(1, dprintf("RDN"));
6290  Info_Number = 0x0074;
6291  Info_Mask = 0x400;
6292  break;
6293  case 22: /* Redirecing Number */
6294  dbug(1, dprintf("RIN"));
6295  Info_Number = 0x0076;
6296  Info_Mask = 0x400;
6297  break;
6298  case 23: /* Notification Indicator */
6299  dbug(1, dprintf("NI"));
6300  Info_Number = (word)NI;
6301  Info_Mask = 0x210;
6302  break;
6303  case 26: /* Call State */
6304  dbug(1, dprintf("CST"));
6305  Info_Number = (word)CST;
6306  Info_Mask = 0x01; /* do with cause i.e. for now */
6307  break;
6308  case MAXPARMSIDS - 2: /* Escape Message Type, must be the last indication */
6309  dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6310  Info_Number = 0x8000 | ie[3];
6311  if (iesent) Info_Mask = 0xffff;
6312  else Info_Mask = 0x10;
6313  Info_Element = "";
6314  break;
6315  default:
6316  Info_Number = 0;
6317  Info_Mask = 0;
6318  Info_Element = "";
6319  break;
6320  }
6321  }
6322 
6323  if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6324  {
6325  for (j = 0; j < max_appl; j++)
6326  {
6327  appl = &application[j];
6328  if (Info_Number
6329  && appl->Id
6330  && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6331  {
6332  dbug(1, dprintf("NCR_Ind"));
6333  iesent = true;
6334  sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6335  }
6336  }
6337  }
6338  else if (!plci->appl)
6339  { /* overlap receiving broadcast */
6340  if (Info_Number == CPN
6341  || Info_Number == KEY
6342  || Info_Number == NI
6343  || Info_Number == DSP
6344  || Info_Number == UUI)
6345  {
6346  for (j = 0; j < max_appl; j++)
6347  {
6348  if (test_c_ind_mask_bit(plci, j))
6349  {
6350  dbug(1, dprintf("Ovl_Ind"));
6351  iesent = true;
6352  sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6353  }
6354  }
6355  }
6356  } /* all other signalling states */
6357  else if (Info_Number
6358  && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6359  {
6360  dbug(1, dprintf("Std_Ind"));
6361  iesent = true;
6362  sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6363  }
6364  }
6365 }
6366 
6367 
6368 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6369  dword info_mask, byte setupParse)
6370 {
6371  word i;
6372  word j;
6373  byte *ie;
6374  word Info_Number;
6375  byte *Info_Element;
6376  APPL *appl;
6377  word Info_Mask = 0;
6378  byte iesent = 0;
6379 
6380  if (
6381  !plci->appl
6382  && !plci->State
6383  && plci->Sig.Ind != NCR_FACILITY
6384  && !setupParse
6385  )
6386  {
6387  dbug(1, dprintf("NoM-IEParse "));
6388  return 0;
6389  }
6390  dbug(1, dprintf("M-IEParse "));
6391 
6392  for (i = 0; i < MAX_MULTI_IE; i++)
6393  {
6394  ie = parms[i];
6395  Info_Number = 0;
6396  Info_Element = ie;
6397  if (ie[0])
6398  {
6399  dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6400  Info_Number = (word)ie_type;
6401  Info_Mask = (word)info_mask;
6402  }
6403 
6404  if (plci->Sig.Ind == NCR_FACILITY) /* check controller broadcast */
6405  {
6406  for (j = 0; j < max_appl; j++)
6407  {
6408  appl = &application[j];
6409  if (Info_Number
6410  && appl->Id
6411  && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6412  {
6413  iesent = true;
6414  dbug(1, dprintf("Mlt_NCR_Ind"));
6415  sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6416  }
6417  }
6418  }
6419  else if (!plci->appl && Info_Number)
6420  { /* overlap receiving broadcast */
6421  for (j = 0; j < max_appl; j++)
6422  {
6423  if (test_c_ind_mask_bit(plci, j))
6424  {
6425  iesent = true;
6426  dbug(1, dprintf("Mlt_Ovl_Ind"));
6427  sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428  }
6429  }
6430  } /* all other signalling states */
6431  else if (Info_Number
6432  && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6433  {
6434  iesent = true;
6435  dbug(1, dprintf("Mlt_Std_Ind"));
6436  sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6437  }
6438  }
6439  return iesent;
6440 }
6441 
6442 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6443 {
6444  word i;
6445  /* Format of multi_ssext_parms[i][]:
6446  0 byte length
6447  1 byte SSEXTIE
6448  2 byte SSEXT_REQ/SSEXT_IND
6449  3 byte length
6450  4 word SSExtCommand
6451  6... Params
6452  */
6453  if (
6454  plci
6455  && plci->State
6456  && plci->Sig.Ind != NCR_FACILITY
6457  )
6458  for (i = 0; i < MAX_MULTI_IE; i++)
6459  {
6460  if (parms[i][0] < 6) continue;
6461  if (parms[i][2] == SSEXT_REQ) continue;
6462 
6463  if (appl)
6464  {
6465  parms[i][0] = 0; /* kill it */
6466  sendf(appl, _MANUFACTURER_I,
6467  Id,
6468  0,
6469  "dwS",
6470  _DI_MANU_ID,
6472  &parms[i][3]);
6473  }
6474  else if (plci->appl)
6475  {
6476  parms[i][0] = 0; /* kill it */
6477  sendf(plci->appl, _MANUFACTURER_I,
6478  Id,
6479  0,
6480  "dwS",
6481  _DI_MANU_ID,
6483  &parms[i][3]);
6484  }
6485  }
6486 };
6487 
6488 static void nl_ind(PLCI *plci)
6489 {
6490  byte ch;
6491  word ncci;
6492  dword Id;
6494  word NCCIcode;
6495  APPL *APPLptr;
6496  word count;
6497  word Num;
6498  word i, ncpi_state;
6499  byte len, ncci_state;
6500  word msg;
6501  word info = 0;
6502  word fax_feature_bits;
6503  byte fax_send_edata_ack;
6504  static byte v120_header_buffer[2 + 3];
6505  static word fax_info[] = {
6506  0, /* T30_SUCCESS */
6507  _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6508  _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6509  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6510  _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6511  _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6512  _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6513  _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6514  _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6515  _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6516  _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6517  _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6518  _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6519  _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6520  _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6521  _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6522  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6523  _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6524  _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6525  _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6526  _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6527  _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6528  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6529  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6530  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6531  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6532  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6533  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6534  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6535  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6536  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6537  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6538  _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6539  0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6540  0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6541  0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6542  _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6543  _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6544  _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6545  _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6546  _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6547  _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6548  _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6549  _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6550  _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6551  _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6552  _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6553  };
6554 
6555  byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556 
6557 
6558  static word rtp_info[] = {
6559  GOOD, /* RTP_SUCCESS */
6560  0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6561  };
6562 
6563  static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6564  {
6565  0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6566  0x00000000, 0x00000000, 0x00000000, 0x00000000
6567  };
6568 
6569  ch = plci->NL.IndCh;
6570  a = plci->adapter;
6571  ncci = a->ch_ncci[ch];
6572  Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6573  if (plci->tel) Id |= EXT_CONTROLLER;
6574  APPLptr = plci->appl;
6575  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",
6576  plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6577 
6578  /* in the case if no connect_active_Ind was sent to the appl we wait for */
6579 
6580  if (plci->nl_remove_id)
6581  {
6582  plci->NL.RNR = 2; /* discard */
6583  dbug(1, dprintf("NL discard while remove pending"));
6584  return;
6585  }
6586  if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6587  {
6588  if (plci->State == INC_DIS_PENDING
6589  || plci->State == OUTG_DIS_PENDING
6590  || plci->State == IDLE)
6591  {
6592  plci->NL.RNR = 2; /* discard */
6593  dbug(1, dprintf("discard n_connect"));
6594  return;
6595  }
6596  if (plci->State < INC_ACT_PENDING)
6597  {
6598  plci->NL.RNR = 1; /* flow control */
6599  channel_x_off(plci, ch, N_XON_CONNECT_IND);
6600  return;
6601  }
6602  }
6603 
6604  if (!APPLptr) /* no application or invalid data */
6605  { /* while reloading the DSP */
6606  dbug(1, dprintf("discard1"));
6607  plci->NL.RNR = 2;
6608  return;
6609  }
6610 
6611  if (((plci->NL.Ind & 0x0f) == N_UDATA)
6612  && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6613  || (plci->B2_prot == 7)
6614  || (plci->B3_prot == 7)))
6615  {
6616  plci->ncpi_buffer[0] = 0;
6617 
6618  ncpi_state = plci->ncpi_state;
6619  if (plci->NL.complete == 1)
6620  {
6621  byte *data = &plci->NL.RBuffer->P[0];
6622 
6623  if ((plci->NL.RBuffer->length >= 12)
6624  && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6625  || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6626  {
6627  word conn_opt, ncpi_opt = 0x00;
6628 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6629 
6630  if (*data == DSP_UDATA_INDICATION_DCD_ON)
6632  if (*data == DSP_UDATA_INDICATION_CTS_ON)
6634 
6635  data++; /* indication code */
6636  data += 2; /* timestamp */
6637  if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6639  data++; /* connected norm */
6640  conn_opt = GET_WORD(data);
6641  data += 2; /* connected options */
6642 
6643  PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6644 
6645  if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6646  {
6647  ncpi_opt |= MDM_NCPI_ECM_V42;
6648  }
6649  else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6650  {
6651  ncpi_opt |= MDM_NCPI_ECM_MNP;
6652  }
6653  else
6654  {
6655  ncpi_opt |= MDM_NCPI_TRANSPARENT;
6656  }
6658  {
6659  ncpi_opt |= MDM_NCPI_COMPRESSED;
6660  }
6661  PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6662  plci->ncpi_buffer[0] = 4;
6663 
6665  }
6666  }
6667  if (plci->B3_prot == 7)
6668  {
6669  if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6671  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6672  {
6674  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6676  }
6677  }
6678 
6679  if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6680  & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6681  || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6682  || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6683 
6684  {
6685  plci->NL.RNR = 2;
6686  return;
6687  }
6688  }
6689 
6690  if (plci->NL.complete == 2)
6691  {
6692  if (((plci->NL.Ind & 0x0f) == N_UDATA)
6693  && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6694  {
6695  switch (plci->RData[0].P[0])
6696  {
6697 
6700  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6701  break;
6704  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6705  break;
6707  dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6708  break;
6710  dtmf_confirmation(Id, plci);
6711  break;
6712 
6713 
6715  capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6716  i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6717  if (i != 0)
6718  {
6719  dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6720  dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6721  }
6722  break;
6723 
6724 
6726  mixer_indication_coefs_set(Id, plci);
6727  break;
6729  mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6730  break;
6732  mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6733  break;
6734 
6735 
6737  ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6738  break;
6739 
6740 
6741 
6742  default:
6743  break;
6744  }
6745  }
6746  else
6747  {
6748  if ((plci->RData[0].PLength != 0)
6749  && ((plci->B2_prot == B2_V120_ASYNC)
6750  || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6751  || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752  {
6753 
6754  sendf(plci->appl, _DATA_B3_I, Id, 0,
6755  "dwww",
6756  plci->RData[1].P,
6757  (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6758  plci->RNum,
6759  plci->RFlags);
6760 
6761  }
6762  else
6763  {
6764 
6765  sendf(plci->appl, _DATA_B3_I, Id, 0,
6766  "dwww",
6767  plci->RData[0].P,
6768  plci->RData[0].PLength,
6769  plci->RNum,
6770  plci->RFlags);
6771 
6772  }
6773  }
6774  return;
6775  }
6776 
6777  fax_feature_bits = 0;
6778  if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6779  (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6780  (plci->NL.Ind & 0x0f) == N_DISC ||
6781  (plci->NL.Ind & 0x0f) == N_EDATA ||
6782  (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6783  {
6784  info = 0;
6785  plci->ncpi_buffer[0] = 0;
6786  switch (plci->B3_prot) {
6787  case 0: /*XPARENT*/
6788  case 1: /*T.90 NL*/
6789  break; /* no network control protocol info - jfr */
6790  case 2: /*ISO8202*/
6791  case 3: /*X25 DCE*/
6792  for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6793  plci->ncpi_buffer[0] = (byte)(i + 3);
6794  plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6795  plci->ncpi_buffer[2] = 0;
6796  plci->ncpi_buffer[3] = 0;
6797  break;
6798  case 4: /*T.30 - FAX*/
6799  case 5: /*T.30 - FAX*/
6800  if (plci->NL.RLength >= sizeof(T30_INFO))
6801  {
6802  dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6803  len = 9;
6804  PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6805  fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6806  i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6807  if (plci->B3_prot == 5)
6808  {
6809  if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6810  i |= 0x8000; /* This is not an ECM connection */
6811  if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6812  i |= 0x4000; /* This is a connection with MMR compression */
6813  if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6814  i |= 0x2000; /* This is a connection with MR compression */
6815  if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6816  i |= 0x0004; /* More documents */
6817  if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6818  i |= 0x0002; /* Fax-polling indication */
6819  }
6820  dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6821  PUT_WORD(&(plci->ncpi_buffer[3]), i);
6822  PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6823  plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6824  plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6825  plci->ncpi_buffer[len] = 0;
6826  if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6827  {
6828  plci->ncpi_buffer[len] = 20;
6829  for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6830  plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6831  }
6832  if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6833  {
6834  if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6835  info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6836  else
6837  info = _FAX_PROTOCOL_ERROR;
6838  }
6839 
6840  if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6842  {
6843  i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6844  while (i < plci->NL.RBuffer->length)
6845  plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846  }
6847 
6848  plci->ncpi_buffer[0] = len;
6849  fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6850  PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6851 
6853  if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6854  || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6855  && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6856  || (((plci->NL.Ind & 0x0f) == N_EDATA)
6857  && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6858  || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6859  || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6860  {
6862  }
6863  if (((plci->NL.Ind & 0x0f) == N_DISC)
6864  || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6865  || (((plci->NL.Ind & 0x0f) == N_EDATA)
6866  && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6867  {
6869  }
6870  }
6871  break;
6872 
6873  case B3_RTP:
6874  if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6875  {
6876  if (plci->NL.RLength != 0)
6877  {
6878  info = rtp_info[plci->NL.RBuffer->P[0]];
6879  plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6880  for (i = 1; i < plci->NL.RLength; i++)
6881  plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6882  }
6883  }
6884  break;
6885 
6886  }
6887  plci->NL.RNR = 2;
6888  }
6889  switch (plci->NL.Ind & 0x0f) {
6890  case N_EDATA:
6891  if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6892  {
6893  dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6894  ((T30_INFO *)plci->NL.RBuffer->P)->code));
6895  fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6896 
6899  && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6900  && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6902  && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6903  {
6904  ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6905  sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6906  (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6909  fax_send_edata_ack = false;
6910  }
6911 
6913  {
6914  switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6915  {
6916  case EDATA_T30_DIS:
6917  if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6918  && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6920  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6921  {
6923  if (plci->B3_prot == 4)
6924  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6925  else
6926  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6928  }
6929  break;
6930 
6931  case EDATA_T30_TRAIN_OK:
6932  if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6934  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6935  {
6936  if (plci->B3_prot == 4)
6937  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6938  else
6939  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6941  }
6942  break;
6943 
6944  case EDATA_T30_EOP_CAPI:
6945  if (a->ncci_state[ncci] == CONNECTED)
6946  {
6947  sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6949  plci->ncpi_state = 0;
6950  fax_send_edata_ack = false;
6951  }
6952  break;
6953  }
6954  }
6955  else
6956  {
6957  switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6958  {
6959  case EDATA_T30_TRAIN_OK:
6960  if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6962  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6963  {
6964  if (plci->B3_prot == 4)
6965  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6966  else
6967  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6969  }
6970  break;
6971  }
6972  }
6973  if (fax_send_edata_ack)
6974  {
6975  ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6976  plci->fax_edata_ack_length = 1;
6977  start_internal_command(Id, plci, fax_edata_ack_command);
6978  }
6979  }
6980  else
6981  {
6982  dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6983  }
6984  break;
6985  case N_CONNECT:
6986  if (!a->ch_ncci[ch])
6987  {
6988  ncci = get_ncci(plci, ch, 0);
6989  Id = (Id & 0xffff) | (((dword) ncci) << 16);
6990  }
6991  dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6992  ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6993 
6994  msg = _CONNECT_B3_I;
6995  if (a->ncci_state[ncci] == IDLE)
6996  plci->channels++;
6997  else if (plci->B3_prot == 1)
6999 
7001  if (plci->B3_prot == 4)
7002  sendf(plci->appl, msg, Id, 0, "s", "");
7003  else
7004  sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7005  break;
7006  case N_CONNECT_ACK:
7007  dbug(1, dprintf("N_connect_Ack"));
7008  if (plci->internal_command_queue[0]
7009  && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7010  || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7011  || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7012  {
7013  (*(plci->internal_command_queue[0]))(Id, plci, 0);
7014  if (!plci->internal_command)
7015  next_internal_command(Id, plci);
7016  break;
7017  }
7018  msg = _CONNECT_B3_ACTIVE_I;
7019  if (plci->B3_prot == 1)
7020  {
7021  if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7024  sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7025  }
7026  else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7027  {
7028  if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7029  && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7030  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7031  {
7033  if (plci->B3_prot == 4)
7034  sendf(plci->appl, msg, Id, 0, "s", "");
7035  else
7036  sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7037  plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7038  }
7039  }
7040  else
7041  {
7043  sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7044  }
7045  if (plci->adjust_b_restore)
7046  {
7047  plci->adjust_b_restore = false;
7048  start_internal_command(Id, plci, adjust_b_restore);
7049  }
7050  break;
7051  case N_DISC:
7052  case N_DISC_ACK:
7053  if (plci->internal_command_queue[0]
7054  && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7055  || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7056  || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7057  {
7058  (*(plci->internal_command_queue[0]))(Id, plci, 0);
7059  if (!plci->internal_command)
7060  next_internal_command(Id, plci);
7061  }
7062  ncci_state = a->ncci_state[ncci];
7063  ncci_remove(plci, ncci, false);
7064 
7065  /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7066  /* channel, so we cannot store the state in ncci_state! The */
7067  /* information which channel we received a N_DISC is thus */
7068  /* stored in the inc_dis_ncci_table buffer. */
7069  for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7070  plci->inc_dis_ncci_table[i] = (byte) ncci;
7071 
7072  /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7073  if (!plci->channels
7074  && (plci->B1_resource == 16)
7075  && (plci->State <= CONNECTED))
7076  {
7077  len = 9;
7078  i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7079  PUT_WORD(&plci->ncpi_buffer[1], i);
7080  PUT_WORD(&plci->ncpi_buffer[3], 0);
7081  i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7082  PUT_WORD(&plci->ncpi_buffer[5], i);
7083  PUT_WORD(&plci->ncpi_buffer[7], 0);
7084  plci->ncpi_buffer[len] = 0;
7085  plci->ncpi_buffer[0] = len;
7086  if (plci->B3_prot == 4)
7087  sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7088  else
7089  {
7090 
7091  if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7092  & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7093  {
7094  plci->ncpi_buffer[++len] = 0;
7095  plci->ncpi_buffer[++len] = 0;
7096  plci->ncpi_buffer[++len] = 0;
7097  plci->ncpi_buffer[0] = len;
7098  }
7099 
7100  sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7101  }
7102  sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7103  plci->ncpi_state = 0;
7104  sig_req(plci, HANGUP, 0);
7105  send_req(plci);
7106  plci->State = OUTG_DIS_PENDING;
7107  /* disc here */
7108  }
7110  && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7111  && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7112  {
7113  if (ncci_state == IDLE)
7114  {
7115  if (plci->channels)
7116  plci->channels--;
7117  if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7118  if (plci->State == SUSPENDING) {
7119  sendf(plci->appl,
7120  _FACILITY_I,
7121  Id & 0xffffL,
7122  0,
7123  "ws", (word)3, "\x03\x04\x00\x00");
7124  sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7125  }
7126  plci_remove(plci);
7127  plci->State = IDLE;
7128  }
7129  }
7130  }
7131  else if (plci->channels)
7132  {
7133  sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7134  plci->ncpi_state = 0;
7135  if ((ncci_state == OUTG_REJ_PENDING)
7136  && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7137  {
7138  sig_req(plci, HANGUP, 0);
7139  send_req(plci);
7140  plci->State = OUTG_DIS_PENDING;
7141  }
7142  }
7143  break;
7144  case N_RESET:
7146  sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7147  break;
7148  case N_RESET_ACK:
7149  a->ncci_state[ncci] = CONNECTED;
7150  sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7151  break;
7152 
7153  case N_UDATA:
7154  if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7155  {
7156  plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7157  plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7158  plci->NL.R = plci->RData;
7159  plci->NL.RNum = 1;
7160  return;
7161  }
7162  case N_BDATA:
7163  case N_DATA:
7164  if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7165  || (a->ncci_state[ncci] == IDLE)
7166  || (a->ncci_state[ncci] == INC_DIS_PENDING))
7167  {
7168  plci->NL.RNR = 2;
7169  break;
7170  }
7171  if ((a->ncci_state[ncci] != CONNECTED)
7172  && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7173  && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7174  {
7175  dbug(1, dprintf("flow control"));
7176  plci->NL.RNR = 1; /* flow control */
7177  channel_x_off(plci, ch, 0);
7178  break;
7179  }
7180 
7181  NCCIcode = ncci | (((word)a->Id) << 8);
7182 
7183  /* count all buffers within the Application pool */
7184  /* belonging to the same NCCI. If this is below the */
7185  /* number of buffers available per NCCI we accept */
7186  /* this packet, otherwise we reject it */
7187  count = 0;
7188  Num = 0xffff;
7189  for (i = 0; i < APPLptr->MaxBuffer; i++) {
7190  if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7191  if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192  }
7193 
7194  if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7195  {
7196  dbug(3, dprintf("Flow-Control"));
7197  plci->NL.RNR = 1;
7198  if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7200  {
7201  plci->NL.RNR = 2;
7202  dbug(3, dprintf("DiscardData"));
7203  } else {
7204  channel_x_off(plci, ch, 0);
7205  }
7206  break;
7207  }
7208  else
7209  {
7210  APPLptr->NCCIDataFlowCtrlTimer = 0;
7211  }
7212 
7213  plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7214  if (!plci->RData[0].P) {
7215  plci->NL.RNR = 1;
7216  channel_x_off(plci, ch, 0);
7217  break;
7218  }
7219 
7220  APPLptr->DataNCCI[Num] = NCCIcode;
7221  APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7222  dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7223 
7224  plci->RNum = Num;
7225  plci->RFlags = plci->NL.Ind >> 4;
7226  plci->RData[0].PLength = APPLptr->MaxDataLength;
7227  plci->NL.R = plci->RData;
7228  if ((plci->NL.RLength != 0)
7229  && ((plci->B2_prot == B2_V120_ASYNC)
7230  || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7231  || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7232  {
7233  plci->RData[1].P = plci->RData[0].P;
7234  plci->RData[1].PLength = plci->RData[0].PLength;
7235  plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7236  if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7237  plci->RData[0].PLength = 1;
7238  else
7239  plci->RData[0].PLength = 2;
7240  if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7241  plci->RFlags |= 0x0010;
7242  if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7243  plci->RFlags |= 0x8000;
7244  plci->NL.RNum = 2;
7245  }
7246  else
7247  {
7248  if ((plci->NL.Ind & 0x0f) == N_UDATA)
7249  plci->RFlags |= 0x0010;
7250 
7251  else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7252  plci->RFlags |= 0x0001;
7253 
7254  plci->NL.RNum = 1;
7255  }
7256  break;
7257  case N_DATA_ACK:
7258  data_ack(plci, ch);
7259  break;
7260  default:
7261  plci->NL.RNR = 2;
7262  break;
7263  }
7264 }
7265 
7266 /*------------------------------------------------------------------*/
7267 /* find a free PLCI */
7268 /*------------------------------------------------------------------*/
7269 
7270 static word get_plci(DIVA_CAPI_ADAPTER *a)
7271 {
7272  word i, j;
7273  PLCI *plci;
7274 
7275  dump_plcis(a);
7276  for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7277  if (i == a->max_plci) {
7278  dbug(1, dprintf("get_plci: out of PLCIs"));
7279  return 0;
7280  }
7281  plci = &a->plci[i];
7282  plci->Id = (byte)(i + 1);
7283 
7284  plci->Sig.Id = 0;
7285  plci->NL.Id = 0;
7286  plci->sig_req = 0;
7287  plci->nl_req = 0;
7288 
7289  plci->appl = NULL;
7290  plci->relatedPTYPLCI = NULL;
7291  plci->State = IDLE;
7292  plci->SuppState = IDLE;
7293  plci->channels = 0;
7294  plci->tel = 0;
7295  plci->B1_resource = 0;
7296  plci->B2_prot = 0;
7297  plci->B3_prot = 0;
7298 
7299  plci->command = 0;
7300  plci->m_command = 0;
7301  init_internal_command_queue(plci);
7302  plci->number = 0;
7303  plci->req_in_start = 0;
7304  plci->req_in = 0;
7305  plci->req_out = 0;
7309 
7310  plci->data_sent = false;
7311  plci->send_disc = 0;
7312  plci->sig_global_req = 0;
7313  plci->sig_remove_id = 0;
7314  plci->nl_global_req = 0;
7315  plci->nl_remove_id = 0;
7316  plci->adv_nl = 0;
7317  plci->manufacturer = false;
7319  plci->spoofed_msg = 0;
7320  plci->ptyState = 0;
7321  plci->cr_enquiry = false;
7322  plci->hangup_flow_ctrl_timer = 0;
7323 
7324  plci->ncci_ring_list = 0;
7325  for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7326  clear_c_ind_mask(plci);
7327  set_group_ind_mask(plci);
7328  plci->fax_connect_info_length = 0;
7329  plci->nsf_control_bits = 0;
7330  plci->ncpi_state = 0x00;
7331  plci->ncpi_buffer[0] = 0;
7332 
7333  plci->requested_options_conn = 0;
7334  plci->requested_options = 0;
7335  plci->notifiedcall = 0;
7336  plci->vswitchstate = 0;
7337  plci->vsprot = 0;
7338  plci->vsprotdialect = 0;
7339  init_b1_config(plci);
7340  dbug(1, dprintf("get_plci(%x)", plci->Id));
7341  return i + 1;
7342 }
7343 
7344 /*------------------------------------------------------------------*/
7345 /* put a parameter in the parameter buffer */
7346 /*------------------------------------------------------------------*/
7347 
7348 static void add_p(PLCI *plci, byte code, byte *p)
7349 {
7350  word p_length;
7351 
7352  p_length = 0;
7353  if (p) p_length = p[0];
7354  add_ie(plci, code, p, p_length);
7355 }
7356 
7357 /*------------------------------------------------------------------*/
7358 /* put a structure in the parameter buffer */
7359 /*------------------------------------------------------------------*/
7360 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7361 {
7362  if (p) add_ie(plci, code, p->info, (word)p->length);
7363 }
7364 
7365 /*------------------------------------------------------------------*/
7366 /* put multiple structures in the parameter buffer */
7367 /*------------------------------------------------------------------*/
7368 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7369 {
7370  byte i;
7371 
7372  if (p) {
7373  dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7374  for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7375  dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7376  add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7377  }
7378  }
7379 }
7380 
7381 /*------------------------------------------------------------------*/
7382 /* return the channel number sent by the application in a esc_chi */
7383 /*------------------------------------------------------------------*/
7384 static byte getChannel(API_PARSE *p)
7385 {
7386  byte i;
7387 
7388  if (p) {
7389  for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7390  if (p->info[i] == 2) {
7391  if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7392  }
7393  }
7394  }
7395  return 0;
7396 }
7397 
7398 
7399 /*------------------------------------------------------------------*/
7400 /* put an information element in the parameter buffer */
7401 /*------------------------------------------------------------------*/
7402 
7403 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7404 {
7405  word i;
7406 
7407  if (!(code & 0x80) && !p_length) return;
7408 
7409  if (plci->req_in == plci->req_in_start) {
7410  plci->req_in += 2;
7411  }
7412  else {
7413  plci->req_in--;
7414  }
7415  plci->RBuffer[plci->req_in++] = code;
7416 
7417  if (p) {
7418  plci->RBuffer[plci->req_in++] = (byte)p_length;
7419  for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420  }
7421 
7422  plci->RBuffer[plci->req_in++] = 0;
7423 }
7424 
7425 /*------------------------------------------------------------------*/
7426 /* put a unstructured data into the buffer */
7427 /*------------------------------------------------------------------*/
7428 
7429 static void add_d(PLCI *plci, word length, byte *p)
7430 {
7431  word i;
7432 
7433  if (plci->req_in == plci->req_in_start) {
7434  plci->req_in += 2;
7435  }
7436  else {
7437  plci->req_in--;
7438  }
7439  for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440 }
7441 
7442 /*------------------------------------------------------------------*/
7443 /* put parameters from the Additional Info parameter in the */
7444 /* parameter buffer */
7445 /*------------------------------------------------------------------*/
7446 
7447 static void add_ai(PLCI *plci, API_PARSE *ai)
7448 {
7449  word i;
7450  API_PARSE ai_parms[5];
7451 
7452  for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7453 
7454  if (!ai->length)
7455  return;
7456  if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7457  return;
7458 
7459  add_s(plci, KEY, &ai_parms[1]);
7460  add_s(plci, UUI, &ai_parms[2]);
7461  add_ss(plci, FTY, &ai_parms[3]);
7462 }
7463 
7464 /*------------------------------------------------------------------*/
7465 /* put parameter for b1 protocol in the parameter buffer */
7466 /*------------------------------------------------------------------*/
7467 
7468 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7469  word b1_facilities)
7470 {
7471  API_PARSE bp_parms[8];
7472  API_PARSE mdm_cfg[9];
7473  API_PARSE global_config[2];
7474  byte cai[256];
7475  byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7476  byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7477  word i;
7478 
7479  API_PARSE mdm_cfg_v18[4];
7480  word j, n, w;
7481  dword d;
7482 
7483 
7484  for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7485  for (i = 0; i < 2; i++) global_config[i].length = 0;
7486 
7487  dbug(1, dprintf("add_b1"));
7488  api_save_msg(bp, "s", &plci->B_protocol);
7489 
7490  if (b_channel_info == 2) {
7491  plci->B1_resource = 0;
7492  adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7493  add_p(plci, CAI, "\x01\x00");
7494  dbug(1, dprintf("Cai=1,0 (no resource)"));
7495  return 0;
7496  }
7497 
7498  if (plci->tel == CODEC_PERMANENT) return 0;
7499  else if (plci->tel == CODEC) {
7500  plci->B1_resource = 1;
7501  adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7502  add_p(plci, CAI, "\x01\x01");
7503  dbug(1, dprintf("Cai=1,1 (Codec)"));
7504  return 0;
7505  }
7506  else if (plci->tel == ADV_VOICE) {
7507  plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7508  adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7509  voice_cai[1] = plci->B1_resource;
7510  PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7511  add_p(plci, CAI, voice_cai);
7512  dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7513  return 0;
7514  }
7516  if (plci->call_dir & CALL_DIR_OUT)
7517  plci->call_dir |= CALL_DIR_ORIGINATE;
7518  else if (plci->call_dir & CALL_DIR_IN)
7519  plci->call_dir |= CALL_DIR_ANSWER;
7520 
7521  if (!bp->length) {
7522  plci->B1_resource = 0x5;
7523  adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7524  add_p(plci, CAI, "\x01\x05");
7525  return 0;
7526  }
7527 
7528  dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7529  if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7530  if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7531  {
7532  bp_parms[6].length = 0;
7533  if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7534  {
7535  dbug(1, dprintf("b-form.!"));
7536  return _WRONG_MESSAGE_FORMAT;
7537  }
7538  }
7539  else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7540  {
7541  dbug(1, dprintf("b-form.!"));
7542  return _WRONG_MESSAGE_FORMAT;
7543  }
7544 
7545  if (bp_parms[6].length)
7546  {
7547  if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7548  {
7549  return _WRONG_MESSAGE_FORMAT;
7550  }
7551  switch (GET_WORD(global_config[0].info))
7552  {
7553  case 1:
7554  plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7555  break;
7556  case 2:
7557  plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7558  break;
7559  }
7560  }
7561  dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562 
7563 
7564  if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7565  && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7566  {
7567  plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7568  adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7569  cai[1] = plci->B1_resource;
7570  cai[2] = 0;
7571  cai[3] = 0;
7572  cai[4] = 0;
7573  PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7574  for (i = 0; i < bp_parms[3].length; i++)
7575  cai[7 + i] = bp_parms[3].info[1 + i];
7576  cai[0] = 6 + bp_parms[3].length;
7577  add_p(plci, CAI, cai);
7578  return 0;
7579  }
7580 
7581 
7582  if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7583  && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7584  {
7585  plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7586  adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587  cai[1] = plci->B1_resource;
7588  cai[2] = 0;
7589  cai[3] = 0;
7590  cai[4] = 0;
7591  PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7592  cai[0] = 6;
7593  add_p(plci, CAI, cai);
7594  return 0;
7595  }
7596 
7597 
7598  if ((GET_WORD(bp_parms[0].info) >= 32)
7599  || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7600  && ((GET_WORD(bp_parms[0].info) != 3)
7601  || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7602  || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7603  {
7604  return _B1_NOT_SUPPORTED;
7605  }
7606  plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7607  (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608  adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7609  cai[0] = 6;
7610  cai[1] = plci->B1_resource;
7611  for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7612 
7613  if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7614  || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7615  || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7616  { /* B1 - modem */
7617  for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7618 
7619  if (bp_parms[3].length)
7620  {
7621  if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7622  {
7623  return (_WRONG_MESSAGE_FORMAT);
7624  }
7625 
7626  cai[2] = 0; /* Bit rate for adaptation */
7627 
7628  dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7629 
7630  PUT_WORD(&cai[13], 0); /* Min Tx speed */
7631  PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7632  PUT_WORD(&cai[17], 0); /* Min Rx speed */
7633  PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7634 
7635  cai[3] = 0; /* Async framing parameters */
7636  switch (GET_WORD(mdm_cfg[2].info))
7637  { /* Parity */
7638  case 1: /* odd parity */
7640  dbug(1, dprintf("MDM: odd parity"));
7641  break;
7642 
7643  case 2: /* even parity */
7645  dbug(1, dprintf("MDM: even parity"));
7646  break;
7647 
7648  default:
7649  dbug(1, dprintf("MDM: no parity"));
7650  break;
7651  }
7652 
7653  switch (GET_WORD(mdm_cfg[3].info))
7654  { /* stop bits */
7655  case 1: /* 2 stop bits */
7656  cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7657  dbug(1, dprintf("MDM: 2 stop bits"));
7658  break;
7659 
7660  default:
7661  dbug(1, dprintf("MDM: 1 stop bit"));
7662  break;
7663  }
7664 
7665  switch (GET_WORD(mdm_cfg[1].info))
7666  { /* char length */
7667  case 5:
7668  cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7669  dbug(1, dprintf("MDM: 5 bits"));
7670  break;
7671 
7672  case 6:
7673  cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7674  dbug(1, dprintf("MDM: 6 bits"));
7675  break;
7676 
7677  case 7:
7678  cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7679  dbug(1, dprintf("MDM: 7 bits"));
7680  break;
7681 
7682  default:
7683  dbug(1, dprintf("MDM: 8 bits"));
7684  break;
7685  }
7686 
7687  cai[7] = 0; /* Line taking options */
7688  cai[8] = 0; /* Modulation negotiation options */
7689  cai[9] = 0; /* Modulation options */
7690 
7691  if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7692  {
7694  dbug(1, dprintf("MDM: Reverse direction"));
7695  }
7696 
7697  if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7698  {
7700  dbug(1, dprintf("MDM: Disable retrain"));
7701  }
7702 
7703  if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7704  {
7706  dbug(1, dprintf("MDM: Disable ring tone"));
7707  }
7708 
7709  if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7710  {
7712  dbug(1, dprintf("MDM: 1800 guard tone"));
7713  }
7714  else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7715  {
7717  dbug(1, dprintf("MDM: 550 guard tone"));
7718  }
7719 
7720  if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7721  {
7722  cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7723  dbug(1, dprintf("MDM: V100"));
7724  }
7725  else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7726  {
7728  dbug(1, dprintf("MDM: IN CLASS"));
7729  }
7730  else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7731  {
7733  dbug(1, dprintf("MDM: DISABLED"));
7734  }
7735  cai[0] = 20;
7736 
7737  if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7738  && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7739  {
7740  plci->requested_options |= 1L << PRIVATE_V18;
7741  }
7742  if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7743  plci->requested_options |= 1L << PRIVATE_VOWN;
7744 
7745  if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7746  & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7747  {
7748  if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7749  {
7750  i = 27;
7751  if (mdm_cfg[6].length >= 4)
7752  {
7753  d = GET_DWORD(&mdm_cfg[6].info[1]);
7754  cai[7] |= (byte) d; /* line taking options */
7755  cai[9] |= (byte)(d >> 8); /* modulation options */
7756  cai[++i] = (byte)(d >> 16); /* vown modulation options */
7757  cai[++i] = (byte)(d >> 24);
7758  if (mdm_cfg[6].length >= 8)
7759  {
7760  d = GET_DWORD(&mdm_cfg[6].info[5]);
7761  cai[10] |= (byte) d; /* disabled modulations mask */
7762  cai[11] |= (byte)(d >> 8);
7763  if (mdm_cfg[6].length >= 12)
7764  {
7765  d = GET_DWORD(&mdm_cfg[6].info[9]);
7766  cai[12] = (byte) d; /* enabled modulations mask */
7767  cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7768  cai[++i] = (byte)(d >> 16);
7769  cai[++i] = (byte)(d >> 24);
7770  cai[++i] = 0;
7771  if (mdm_cfg[6].length >= 14)
7772  {
7773  w = GET_WORD(&mdm_cfg[6].info[13]);
7774  if (w != 0)
7775  PUT_WORD(&cai[13], w); /* min tx speed */
7776  if (mdm_cfg[6].length >= 16)
7777  {
7778  w = GET_WORD(&mdm_cfg[6].info[15]);
7779  if (w != 0)
7780  PUT_WORD(&cai[15], w); /* max tx speed */
7781  if (mdm_cfg[6].length >= 18)
7782  {
7783  w = GET_WORD(&mdm_cfg[6].info[17]);
7784  if (w != 0)
7785  PUT_WORD(&cai[17], w); /* min rx speed */
7786  if (mdm_cfg[6].length >= 20)
7787  {
7788  w = GET_WORD(&mdm_cfg[6].info[19]);
7789  if (w != 0)
7790  PUT_WORD(&cai[19], w); /* max rx speed */
7791  if (mdm_cfg[6].length >= 22)
7792  {
7793  w = GET_WORD(&mdm_cfg[6].info[21]);
7794  cai[23] = (byte)(-((short) w)); /* transmit level */
7795  if (mdm_cfg[6].length >= 24)
7796  {
7797  w = GET_WORD(&mdm_cfg[6].info[23]);
7798  cai[22] |= (byte) w; /* info options mask */
7799  cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7800  }
7801  }
7802  }
7803  }
7804  }
7805  }
7806  }
7807  }
7808  }
7809  cai[27] = i - 27;
7810  i++;
7811  if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7812  {
7813  if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7814  {
7815  for (n = 0; n < 3; n++)
7816  {
7817  cai[i] = (byte)(mdm_cfg_v18[n].length);
7818  for (j = 1; j < ((word)(cai[i] + 1)); j++)
7819  cai[i + j] = mdm_cfg_v18[n].info[j];
7820  i += cai[i] + 1;
7821  }
7822  }
7823  }
7824  cai[0] = (byte)(i - 1);
7825  }
7826  }
7827 
7828  }
7829  }
7830  if (GET_WORD(bp_parms[0].info) == 2 || /* V.110 async */
7831  GET_WORD(bp_parms[0].info) == 3) /* V.110 sync */
7832  {
7833  if (bp_parms[3].length) {
7834  dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7835  switch (GET_WORD(&bp_parms[3].info[1])) { /* Rate */
7836  case 0:
7837  case 56000:
7838  if (GET_WORD(bp_parms[0].info) == 3) { /* V.110 sync 56k */
7839  dbug(1, dprintf("56k sync HSCX"));
7840  cai[1] = 8;
7841  cai[2] = 0;
7842  cai[3] = 0;
7843  }
7844  else if (GET_WORD(bp_parms[0].info) == 2) {
7845  dbug(1, dprintf("56k async DSP"));
7846  cai[2] = 9;
7847  }
7848  break;
7849  case 50: cai[2] = 1; break;
7850  case 75: cai[2] = 1; break;
7851  case 110: cai[2] = 1; break;
7852  case 150: cai[2] = 1; break;
7853  case 200: cai[2] = 1; break;
7854  case 300: cai[2] = 1; break;
7855  case 600: cai[2] = 1; break;
7856  case 1200: cai[2] = 2; break;
7857  case 2400: cai[2] = 3; break;
7858  case 4800: cai[2] = 4; break;
7859  case 7200: cai[2] = 10; break;
7860  case 9600: cai[2] = 5; break;
7861  case 12000: cai[2] = 13; break;
7862  case 24000: cai[2] = 0; break;
7863  case 14400: cai[2] = 11; break;
7864  case 19200: cai[2] = 6; break;
7865  case 28800: cai[2] = 12; break;
7866  case 38400: cai[2] = 7; break;
7867  case 48000: cai[2] = 8; break;
7868  case 76: cai[2] = 15; break; /* 75/1200 */
7869  case 1201: cai[2] = 14; break; /* 1200/75 */
7870  case 56001: cai[2] = 9; break; /* V.110 56000 */
7871 
7872  default:
7873  return _B1_PARM_NOT_SUPPORTED;
7874  }
7875  cai[3] = 0;
7876  if (cai[1] == 13) /* v.110 async */
7877  {
7878  if (bp_parms[3].length >= 8)
7879  {
7880  switch (GET_WORD(&bp_parms[3].info[3]))
7881  { /* char length */
7882  case 5:
7883  cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7884  break;
7885  case 6:
7886  cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7887  break;
7888  case 7:
7889  cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7890  break;
7891  }
7892  switch (GET_WORD(&bp_parms[3].info[5]))
7893  { /* Parity */
7894  case 1: /* odd parity */
7896  break;
7897  case 2: /* even parity */
7899  break;
7900  }
7901  switch (GET_WORD(&bp_parms[3].info[7]))
7902  { /* stop bits */
7903  case 1: /* 2 stop bits */
7904  cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7905  break;
7906  }
7907  }
7908  }
7909  }
7910  else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7911  dbug(1, dprintf("V.110 default 56k sync"));
7912  cai[1] = 8;
7913  cai[2] = 0;
7914  cai[3] = 0;
7915  }
7916  else {
7917  dbug(1, dprintf("V.110 default 9600 async"));
7918  cai[2] = 5;
7919  }
7920  }
7921  PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7922  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]));
7923 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7924 
7925  add_p(plci, CAI, cai);
7926  return 0;
7927 }
7928 
7929 /*------------------------------------------------------------------*/
7930 /* put parameter for b2 and B3 protocol in the parameter buffer */
7931 /*------------------------------------------------------------------*/
7932 
7933 static word add_b23(PLCI *plci, API_PARSE *bp)
7934 {
7935  word i, fax_control_bits;
7936  byte pos, len;
7937  byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7938  API_PARSE bp_parms[8];
7939  API_PARSE *b1_config;
7940  API_PARSE *b2_config;
7941  API_PARSE b2_config_parms[8];
7942  API_PARSE *b3_config;
7943  API_PARSE b3_config_parms[6];
7944  API_PARSE global_config[2];
7945 
7946  static byte llc[3] = {2,0,0};
7947  static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7948  static byte nlc[256];
7949  static byte lli[12] = {1,1};
7950 
7951  const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952  const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7953 
7954  const byte llc3[] = {4,3,2,2,6,6,0};
7955  const byte header[] = {0,2,3,3,0,0,0};
7956 
7957  for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7958  for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7959  for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7960 
7961  lli[0] = 1;
7962  lli[1] = 1;
7964  lli[1] |= 2;
7966  lli[1] |= 4;
7967 
7968  if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7969  lli[1] |= 0x10;
7970  if (plci->rx_dma_descriptor <= 0) {
7971  plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7972  if (plci->rx_dma_descriptor >= 0)
7973  plci->rx_dma_descriptor++;
7974  }
7975  if (plci->rx_dma_descriptor > 0) {
7976  lli[0] = 6;
7977  lli[1] |= 0x40;
7978  lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7979  lli[3] = (byte)plci->rx_dma_magic;
7980  lli[4] = (byte)(plci->rx_dma_magic >> 8);
7981  lli[5] = (byte)(plci->rx_dma_magic >> 16);
7982  lli[6] = (byte)(plci->rx_dma_magic >> 24);
7983  }
7984  }
7985 
7987  lli[1] |= 0x20;
7988  }
7989 
7990  dbug(1, dprintf("add_b23"));
7991  api_save_msg(bp, "s", &plci->B_protocol);
7992 
7993  if (!bp->length && plci->tel)
7994  {
7995  plci->adv_nl = true;
7996  dbug(1, dprintf("Default adv.Nl"));
7997  add_p(plci, LLI, lli);
7998  plci->B2_prot = 1 /*XPARENT*/;
7999  plci->B3_prot = 0 /*XPARENT*/;
8000  llc[1] = 2;
8001  llc[2] = 4;
8002  add_p(plci, LLC, llc);
8003  dlc[0] = 2;
8004  PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8005  add_p(plci, DLC, dlc);
8006  return 0;
8007  }
8008 
8009  if (!bp->length) /*default*/
8010  {
8011  dbug(1, dprintf("ret default"));
8012  add_p(plci, LLI, lli);
8013  plci->B2_prot = 0 /*X.75 */;
8014  plci->B3_prot = 0 /*XPARENT*/;
8015  llc[1] = 1;
8016  llc[2] = 4;
8017  add_p(plci, LLC, llc);
8018  dlc[0] = 2;
8019  PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8020  add_p(plci, DLC, dlc);
8021  return 0;
8022  }
8023  dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8024  if ((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8025 
8026  if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8027  {
8028  bp_parms[6].length = 0;
8029  if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8030  {
8031  dbug(1, dprintf("b-form.!"));
8032  return _WRONG_MESSAGE_FORMAT;
8033  }
8034  }
8035  else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8036  {
8037  dbug(1, dprintf("b-form.!"));
8038  return _WRONG_MESSAGE_FORMAT;
8039  }
8040 
8041  if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8042  {
8043  if (GET_WORD(bp_parms[1].info) != 1
8044  || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8045  plci->adv_nl = true;
8046  }
8047  else if (plci->tel) return _B2_NOT_SUPPORTED;
8048 
8049 
8050  if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8051  && (GET_WORD(bp_parms[2].info) == B3_RTP)
8052  && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8053  {
8054  add_p(plci, LLI, lli);
8055  plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8056  plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8057  llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8058  llc[2] = 4;
8059  add_p(plci, LLC, llc);
8060  dlc[0] = 2;
8061  PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8062  dlc[3] = 3; /* Addr A */
8063  dlc[4] = 1; /* Addr B */
8064  dlc[5] = 7; /* modulo mode */
8065  dlc[6] = 7; /* window size */
8066  dlc[7] = 0; /* XID len Lo */
8067  dlc[8] = 0; /* XID len Hi */
8068  for (i = 0; i < bp_parms[4].length; i++)
8069  dlc[9 + i] = bp_parms[4].info[1 + i];
8070  dlc[0] = (byte)(8 + bp_parms[4].length);
8071  add_p(plci, DLC, dlc);
8072  for (i = 0; i < bp_parms[5].length; i++)
8073  nlc[1 + i] = bp_parms[5].info[1 + i];
8074  nlc[0] = (byte)(bp_parms[5].length);
8075  add_p(plci, NLC, nlc);
8076  return 0;
8077  }
8078 
8079 
8080 
8081  if ((GET_WORD(bp_parms[1].info) >= 32)
8082  || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8083  && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8084  || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085 
8086  {
8087  return _B2_NOT_SUPPORTED;
8088  }
8089  if ((GET_WORD(bp_parms[2].info) >= 32)
8090  || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8091  {
8092  return _B3_NOT_SUPPORTED;
8093  }
8094  if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8095  && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8096  || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8097  || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8098  {
8099  return (add_modem_b23(plci, bp_parms));
8100  }
8101 
8102  add_p(plci, LLI, lli);
8103 
8104  plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8105  plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8106  if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8107 
8108  if (bp_parms[6].length)
8109  {
8110  if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8111  {
8112  return _WRONG_MESSAGE_FORMAT;
8113  }
8114  switch (GET_WORD(global_config[0].info))
8115  {
8116  case 1:
8117  plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8118  break;
8119  case 2:
8120  plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8121  break;
8122  }
8123  }
8124  dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125 
8126 
8127  if (plci->B2_prot == B2_PIAFS)
8128  llc[1] = PIAFS_CRC;
8129  else
8130 /* IMPLEMENT_PIAFS */
8131  {
8132  llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8133  llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8134  }
8135  llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8136 
8137  add_p(plci, LLC, llc);
8138 
8139  dlc[0] = 2;
8140  PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8141  header[GET_WORD(bp_parms[2].info)]);
8142 
8143  b1_config = &bp_parms[3];
8144  nlc[0] = 0;
8145  if (plci->B3_prot == 4
8146  || plci->B3_prot == 5)
8147  {
8148  for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8149  nlc[0] = sizeof(T30_INFO);
8151  ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8152  ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8153  if (b1_config->length >= 2)
8154  {
8155  ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156  }
8157  }
8158  b2_config = &bp_parms[4];
8159 
8160 
8161  if (llc[1] == PIAFS_CRC)
8162  {
8163  if (plci->B3_prot != B3_TRANSPARENT)
8164  {
8165  return _B_STACK_NOT_SUPPORTED;
8166  }
8167  if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8168  return _WRONG_MESSAGE_FORMAT;
8169  }
8170  PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8171  dlc[3] = 0; /* Addr A */
8172  dlc[4] = 0; /* Addr B */
8173  dlc[5] = 0; /* modulo mode */
8174  dlc[6] = 0; /* window size */
8175  if (b2_config->length >= 7) {
8176  dlc[7] = 7;
8177  dlc[8] = 0;
8178  dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8179  dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8180  dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8181  dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8182  dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8183  dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8184  dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8185  dlc[0] = 15;
8186  if (b2_config->length >= 8) { /* PIAFS control abilities */
8187  dlc[7] = 10;
8188  dlc[16] = 2; /* Length of PIAFS extension */
8189  dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8190  dlc[18] = b2_config_parms[4].info[0]; /* value */
8191  dlc[0] = 18;
8192  }
8193  }
8194  else /* default values, 64K, variable, no compression */
8195  {
8196  dlc[7] = 7;
8197  dlc[8] = 0;
8198  dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8199  dlc[10] = 0x03; /* V.42bis P0 */
8200  dlc[11] = 0; /* V.42bis P0 */
8201  dlc[12] = 0; /* V.42bis P1 */
8202  dlc[13] = 0; /* V.42bis P1 */
8203  dlc[14] = 0; /* V.42bis P2 */
8204  dlc[15] = 0; /* V.42bis P2 */
8205  dlc[0] = 15;
8206  }
8207  add_p(plci, DLC, dlc);
8208  }
8209  else
8210 
8211  if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8212  {
8213  if (plci->B3_prot != B3_TRANSPARENT)
8214  return _B_STACK_NOT_SUPPORTED;
8215 
8216  dlc[0] = 6;
8217  PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8218  dlc[3] = 0x08;
8219  dlc[4] = 0x01;
8220  dlc[5] = 127;
8221  dlc[6] = 7;
8222  if (b2_config->length != 0)
8223  {
8224  if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8225  return _WRONG_MESSAGE_FORMAT;
8226  }
8227  dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8228  dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8229  if (b2_config->info[3] != 128)
8230  {
8231  dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8232  return _B2_PARM_NOT_SUPPORTED;
8233  }
8234  dlc[5] = (byte)(b2_config->info[3] - 1);
8235  dlc[6] = b2_config->info[4];
8236  if (llc[1] == V120_V42BIS) {
8237  if (b2_config->length >= 10) {
8238  dlc[7] = 6;
8239  dlc[8] = 0;
8240  dlc[9] = b2_config_parms[4].info[0];
8241  dlc[10] = b2_config_parms[4].info[1];
8242  dlc[11] = b2_config_parms[5].info[0];
8243  dlc[12] = b2_config_parms[5].info[1];
8244  dlc[13] = b2_config_parms[6].info[0];
8245  dlc[14] = b2_config_parms[6].info[1];
8246  dlc[0] = 14;
8247  dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8248  dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8249  dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8250  }
8251  else {
8252  dlc[6] = 14;
8253  }
8254  }
8255  }
8256  }
8257  else
8258  {
8259  if (b2_config->length)
8260  {
8261  dbug(1, dprintf("B2-Config"));
8262  if (llc[1] == X75_V42BIS) {
8263  if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8264  {
8265  return _WRONG_MESSAGE_FORMAT;
8266  }
8267  }
8268  else {
8269  if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8270  {
8271  return _WRONG_MESSAGE_FORMAT;
8272  }
8273  }
8274  /* if B2 Protocol is LAPD, b2_config structure is different */
8275  if (llc[1] == 6)
8276  {
8277  dlc[0] = 4;
8278  if (b2_config->length >= 1) dlc[2] = b2_config->info[1]; /* TEI */
8279  else dlc[2] = 0x01;
8280  if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8281  {
8282  SAPI = b2_config->info[2]; /* SAPI */
8283  }
8284  dlc[1] = SAPI;
8285  if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8286  {
8287  dlc[3] = 127; /* Mode */
8288  }
8289  else
8290  {
8291  dlc[3] = 7; /* Mode */
8292  }
8293 
8294  if (b2_config->length >= 4) dlc[4] = b2_config->info[4]; /* Window */
8295  else dlc[4] = 1;
8296  dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8297  if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8298  }
8299  else
8300  {
8301  dlc[0] = (byte)(b2_config_parms[4].length + 6);
8302  dlc[3] = b2_config->info[1];
8303  dlc[4] = b2_config->info[2];
8304  if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8305  dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8306  return _B2_PARM_NOT_SUPPORTED;
8307  }
8308 
8309  dlc[5] = (byte)(b2_config->info[3] - 1);
8310  dlc[6] = b2_config->info[4];
8311  if (dlc[6] > dlc[5]) {
8312  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]));
8313  return _B2_PARM_NOT_SUPPORTED;
8314  }
8315 
8316  if (llc[1] == X75_V42BIS) {
8317  if (b2_config->length >= 10) {
8318  dlc[7] = 6;
8319  dlc[8] = 0;
8320  dlc[9] = b2_config_parms[4].info[0];
8321  dlc[10] = b2_config_parms[4].info[1];
8322  dlc[11] = b2_config_parms[5].info[0];
8323  dlc[12] = b2_config_parms[5].info[1];
8324  dlc[13] = b2_config_parms[6].info[0];
8325  dlc[14] = b2_config_parms[6].info[1];
8326  dlc[0] = 14;
8327  dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8328  dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8329  dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8330  }
8331  else {
8332  dlc[6] = 14;
8333  }
8334 
8335  }
8336  else {
8337  PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8338  for (i = 0; i < b2_config_parms[4].length; i++)
8339  dlc[11 + i] = b2_config_parms[4].info[1 + i];
8340  }
8341  }
8342  }
8343  }
8344  add_p(plci, DLC, dlc);
8345 
8346  b3_config = &bp_parms[5];
8347  if (b3_config->length)
8348  {
8349  if (plci->B3_prot == 4
8350  || plci->B3_prot == 5)
8351  {
8352  if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8353  {
8354  return _WRONG_MESSAGE_FORMAT;
8355  }
8356  i = GET_WORD((byte *)(b3_config_parms[0].info));
8357  ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8358  ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8359  ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8360  fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8361  if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8362  fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8364  {
8365 
8366  if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8367  & (1L << PRIVATE_FAX_PAPER_FORMATS))
8368  {
8369  ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8372  }
8373 
8374  ((T30_INFO *)&nlc[1])->recording_properties =
8378  }
8379  if (plci->B3_prot == 5)
8380  {
8381  if (i & 0x0002) /* Accept incoming fax-polling requests */
8382  fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8383  if (i & 0x2000) /* Do not use MR compression */
8384  fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8385  if (i & 0x4000) /* Do not use MMR compression */
8386  fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8387  if (i & 0x8000) /* Do not use ECM */
8388  fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8389  if (plci->fax_connect_info_length != 0)
8390  {
8391  ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8392  ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8393  ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8394  fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8396  }
8397  }
8398  /* copy station id to NLC */
8399  for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8400  {
8401  if (i < b3_config_parms[2].length)
8402  {
8403  ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8404  }
8405  else
8406  {
8407  ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408  }
8409  }
8410  ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8411  /* copy head line to NLC */
8412  if (b3_config_parms[3].length)
8413  {
8414 
8415  pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8416  if (pos != 0)
8417  {
8418  if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8419  pos = 0;
8420  else
8421  {
8422  nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8423  nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8424  len = (byte)b3_config_parms[2].length;
8425  if (len > 20)
8426  len = 20;
8427  if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8428  {
8429  for (i = 0; i < len; i++)
8430  nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8431  nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8432  nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8433  }
8434  }
8435  }
8436 
8437  len = (byte)b3_config_parms[3].length;
8438  if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8439  len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8440  ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8441  nlc[0] += (byte)(pos + len);
8442  for (i = 0; i < len; i++)
8443  nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1 + i];
8444  } else
8445  ((T30_INFO *)&nlc[1])->head_line_len = 0;
8446 
8447  plci->nsf_control_bits = 0;
8448  if (plci->B3_prot == 5)
8449  {
8450  if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451  && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8452  {
8454  }
8456  && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8457  {
8459  }
8460  if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8462  {
8463  if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8464  & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8465  {
8467  if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8468  fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8469  }
8470  len = nlc[0];
8471  pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8472  if (pos < plci->fax_connect_info_length)
8473  {
8474  for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475  nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476  }
8477  else
8478  nlc[++len] = 0;
8479  if (pos < plci->fax_connect_info_length)
8480  {
8481  for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482  nlc[++len] = plci->fax_connect_info_buffer[pos++];
8483  }
8484  else
8485  nlc[++len] = 0;
8486  if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8487  & (1L << PRIVATE_FAX_NONSTANDARD))
8488  {
8489  if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8490  {
8491  if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8492  plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8493  for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8494  nlc[++len] = plci->fax_connect_info_buffer[pos++];
8495  }
8496  else
8497  {
8498  if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8499  {
8500  dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8501  nlc[++len] = 0;
8502  }
8503  else
8504  {
8505  if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8506  plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8507  nlc[++len] = (byte)(b3_config_parms[4].length);
8508  for (i = 0; i < b3_config_parms[4].length; i++)
8509  nlc[++len] = b3_config_parms[4].info[1 + i];
8510  }
8511  }
8512  }
8513  nlc[0] = len;
8516  {
8517  ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8518  }
8519  }
8520  }
8521 
8522  PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8523  len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8524  for (i = 0; i < len; i++)
8525  plci->fax_connect_info_buffer[i] = nlc[1 + i];
8526  ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8527  i += ((T30_INFO *)&nlc[1])->head_line_len;
8528  while (i < nlc[0])
8529  plci->fax_connect_info_buffer[len++] = nlc[++i];
8530  plci->fax_connect_info_length = len;
8531  }
8532  else
8533  {
8534  nlc[0] = 14;
8535  if (b3_config->length != 16)
8536  return _B3_PARM_NOT_SUPPORTED;
8537  for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8538  if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8539  return _B3_PARM_NOT_SUPPORTED;
8540  nlc[13] = b3_config->info[13];
8541  if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8542  return _B3_PARM_NOT_SUPPORTED;
8543  nlc[14] = b3_config->info[15];
8544  }
8545  }
8546  else
8547  {
8548  if (plci->B3_prot == 4
8549  || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8550  }
8551  add_p(plci, NLC, nlc);
8552  return 0;
8553 }
8554 
8555 /*----------------------------------------------------------------*/
8556 /* make the same as add_b23, but only for the modem related */
8557 /* L2 and L3 B-Chan protocol. */
8558 /* */
8559 /* Enabled L2 and L3 Configurations: */
8560 /* If L1 == Modem all negotiation */
8561 /* only L2 == Modem with full negotiation is allowed */
8562 /* If L1 == Modem async or sync */
8563 /* only L2 == Transparent is allowed */
8564 /* L3 == Modem or L3 == Transparent are allowed */
8565 /* B2 Configuration for modem: */
8566 /* word : enable/disable compression, bitoptions */
8567 /* B3 Configuration for modem: */
8568 /* empty */
8569 /*----------------------------------------------------------------*/
8570 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8571 {
8572  static byte lli[12] = {1,1};
8573  static byte llc[3] = {2,0,0};
8574  static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8575  API_PARSE mdm_config[2];
8576  word i;
8577  word b2_config = 0;
8578 
8579  for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8580  for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8581 
8582  if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8583  && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8584  || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8585  && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8586  {
8587  return (_B_STACK_NOT_SUPPORTED);
8588  }
8589  if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8590  && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8591  {
8592  return (_B_STACK_NOT_SUPPORTED);
8593  }
8594 
8595  plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8596  plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8597 
8598  if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8599  {
8600  if (api_parse(&bp_parms[4].info[1],
8601  (word)bp_parms[4].length, "w",
8602  mdm_config))
8603  {
8604  return (_WRONG_MESSAGE_FORMAT);
8605  }
8606  b2_config = GET_WORD(mdm_config[0].info);
8607  }
8608 
8609  /* OK, L2 is modem */
8610 
8611  lli[0] = 1;
8612  lli[1] = 1;
8614  lli[1] |= 2;
8616  lli[1] |= 4;
8617 
8618  if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8619  lli[1] |= 0x10;
8620  if (plci->rx_dma_descriptor <= 0) {
8621  plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8622  if (plci->rx_dma_descriptor >= 0)
8623  plci->rx_dma_descriptor++;
8624  }
8625  if (plci->rx_dma_descriptor > 0) {
8626  lli[1] |= 0x40;
8627  lli[0] = 6;
8628  lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8629  lli[3] = (byte)plci->rx_dma_magic;
8630  lli[4] = (byte)(plci->rx_dma_magic >> 8);
8631  lli[5] = (byte)(plci->rx_dma_magic >> 16);
8632  lli[6] = (byte)(plci->rx_dma_magic >> 24);
8633  }
8634  }
8635 
8637  lli[1] |= 0x20;
8638  }
8639 
8640  llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8641  /*V42*/ 10 : /*V42_IN*/ 9;
8642  llc[2] = 4; /* pass L3 always transparent */
8643  add_p(plci, LLI, lli);
8644  add_p(plci, LLC, llc);
8645  i = 1;
8646  PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8647  i += 2;
8648  if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8649  {
8650  if (bp_parms[4].length)
8651  {
8652  dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8653  dlc[i++] = 3; /* Addr A */
8654  dlc[i++] = 1; /* Addr B */
8655  dlc[i++] = 7; /* modulo mode */
8656  dlc[i++] = 7; /* window size */
8657  dlc[i++] = 0; /* XID len Lo */
8658  dlc[i++] = 0; /* XID len Hi */
8659 
8660  if (b2_config & MDM_B2_DISABLE_V42bis)
8661  {
8663  }
8664  if (b2_config & MDM_B2_DISABLE_MNP)
8665  {
8667  }
8668  if (b2_config & MDM_B2_DISABLE_TRANS)
8669  {
8671  }
8672  if (b2_config & MDM_B2_DISABLE_V42)
8673  {
8675  }
8676  if (b2_config & MDM_B2_DISABLE_COMP)
8677  {
8679  }
8680  i++;
8681  }
8682  }
8683  else
8684  {
8685  dlc[i++] = 3; /* Addr A */
8686  dlc[i++] = 1; /* Addr B */
8687  dlc[i++] = 7; /* modulo mode */
8688  dlc[i++] = 7; /* window size */
8689  dlc[i++] = 0; /* XID len Lo */
8690  dlc[i++] = 0; /* XID len Hi */
8695  }
8696  dlc[0] = (byte)(i - 1);
8697 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8698  add_p(plci, DLC, dlc);
8699  return (0);
8700 }
8701 
8702 
8703 /*------------------------------------------------------------------*/
8704 /* send a request for the signaling entity */
8705 /*------------------------------------------------------------------*/
8706 
8707 static void sig_req(PLCI *plci, byte req, byte Id)
8708 {
8709  if (!plci) return;
8710  if (plci->adapter->adapter_disabled) return;
8711  dbug(1, dprintf("sig_req(%x)", req));
8712  if (req == REMOVE)
8713  plci->sig_remove_id = plci->Sig.Id;
8714  if (plci->req_in == plci->req_in_start) {
8715  plci->req_in += 2;
8716  plci->RBuffer[plci->req_in++] = 0;
8717  }
8718  PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8719  plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8720  plci->RBuffer[plci->req_in++] = req; /* request */
8721  plci->RBuffer[plci->req_in++] = 0; /* channel */
8722  plci->req_in_start = plci->req_in;
8723 }
8724 
8725 /*------------------------------------------------------------------*/
8726 /* send a request for the network layer entity */
8727 /*------------------------------------------------------------------*/
8728 
8729 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8730 {
8731  if (!plci) return;
8732  if (plci->adapter->adapter_disabled) return;
8733  dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8734  if (req == REMOVE)
8735  {
8736  plci->nl_remove_id = plci->NL.Id;
8737  ncci_remove(plci, 0, (byte)(ncci != 0));
8738  ncci = 0;
8739  }
8740  if (plci->req_in == plci->req_in_start) {
8741  plci->req_in += 2;
8742  plci->RBuffer[plci->req_in++] = 0;
8743  }
8744  PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8745  plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8746  plci->RBuffer[plci->req_in++] = req; /* request */
8747  plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8748  plci->req_in_start = plci->req_in;
8749 }
8750 
8751 static void send_req(PLCI *plci)
8752 {
8753  ENTITY *e;
8754  word l;
8755 /* word i; */
8756 
8757  if (!plci) return;
8758  if (plci->adapter->adapter_disabled) return;
8759  channel_xmit_xon(plci);
8760 
8761  /* if nothing to do, return */
8762  if (plci->req_in == plci->req_out) return;
8763  dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8764 
8765  if (plci->nl_req || plci->sig_req) return;
8766 
8767  l = GET_WORD(&plci->RBuffer[plci->req_out]);
8768  plci->req_out += 2;
8769  plci->XData[0].P = &plci->RBuffer[plci->req_out];
8770  plci->req_out += l;
8771  if (plci->RBuffer[plci->req_out] == 1)
8772  {
8773  e = &plci->NL;
8774  plci->req_out++;
8775  e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8776  e->ReqCh = plci->RBuffer[plci->req_out++];
8777  if (!(e->Id & 0x1f))
8778  {
8779  e->Id = NL_ID;
8780  plci->RBuffer[plci->req_out - 4] = CAI;
8781  plci->RBuffer[plci->req_out - 3] = 1;
8782  plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8783  plci->RBuffer[plci->req_out - 1] = 0;
8784  l += 3;
8785  plci->nl_global_req = plci->nl_req;
8786  }
8787  dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8788  }
8789  else
8790  {
8791  e = &plci->Sig;
8792  if (plci->RBuffer[plci->req_out])
8793  e->Id = plci->RBuffer[plci->req_out];
8794  plci->req_out++;
8795  e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8796  e->ReqCh = plci->RBuffer[plci->req_out++];
8797  if (!(e->Id & 0x1f))
8798  plci->sig_global_req = plci->sig_req;
8799  dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8800  }
8801  plci->XData[0].PLength = l;
8802  e->X = plci->XData;
8803  plci->adapter->request(e);
8804  dbug(1, dprintf("send_ok"));
8805 }
8806 
8807 static void send_data(PLCI *plci)
8808 {
8810  DATA_B3_DESC *data;
8811  NCCI *ncci_ptr;
8812  word ncci;
8813 
8814  if (!plci->nl_req && plci->ncci_ring_list)
8815  {
8816  a = plci->adapter;
8817  ncci = plci->ncci_ring_list;
8818  do
8819  {
8820  ncci = a->ncci_next[ncci];
8821  ncci_ptr = &(a->ncci[ncci]);
8822  if (!(a->ncci_ch[ncci]
8823  && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8824  {
8825  if (ncci_ptr->data_pending)
8826  {
8827  if ((a->ncci_state[ncci] == CONNECTED)
8828  || (a->ncci_state[ncci] == INC_ACT_PENDING)
8829  || (plci->send_disc == ncci))
8830  {
8831  data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8832  if ((plci->B2_prot == B2_V120_ASYNC)
8833  || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8834  || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8835  {
8836  plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8837  plci->NData[1].PLength = data->Length;
8838  if (data->Flags & 0x10)
8839  plci->NData[0].P = v120_break_header;
8840  else
8841  plci->NData[0].P = v120_default_header;
8842  plci->NData[0].PLength = 1;
8843  plci->NL.XNum = 2;
8844  plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8845  }
8846  else
8847  {
8848  plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8849  plci->NData[0].PLength = data->Length;
8850  if (data->Flags & 0x10)
8851  plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8852 
8853  else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8854  plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8855 
8856  else
8857  plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8858  }
8859  plci->NL.X = plci->NData;
8860  plci->NL.ReqCh = a->ncci_ch[ncci];
8861  dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8862  plci->data_sent = true;
8863  plci->data_sent_ptr = data->P;
8864  a->request(&plci->NL);
8865  }
8866  else {
8867  cleanup_ncci_data(plci, ncci);
8868  }
8869  }
8870  else if (plci->send_disc == ncci)
8871  {
8872  /* dprintf("N_DISC"); */
8873  plci->NData[0].PLength = 0;
8874  plci->NL.ReqCh = a->ncci_ch[ncci];
8875  plci->NL.Req = plci->nl_req = N_DISC;
8876  a->request(&plci->NL);
8877  plci->command = _DISCONNECT_B3_R;
8878  plci->send_disc = 0;
8879  }
8880  }
8881  } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8882  plci->ncci_ring_list = ncci;
8883  }
8884 }
8885 
8886 static void listen_check(DIVA_CAPI_ADAPTER *a)
8887 {
8888  word i, j;
8889  PLCI *plci;
8890  byte activnotifiedcalls = 0;
8891 
8892  dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8893  if (!remove_started && !a->adapter_disabled)
8894  {
8895  for (i = 0; i < a->max_plci; i++)
8896  {
8897  plci = &(a->plci[i]);
8898  if (plci->notifiedcall) activnotifiedcalls++;
8899  }
8900  dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8901 
8902  for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8903  if ((j = get_plci(a))) {
8904  a->listen_active++;
8905  plci = &a->plci[j - 1];
8906  plci->State = LISTENING;
8907 
8908  add_p(plci, OAD, "\x01\xfd");
8909 
8910  add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8911 
8912  add_p(plci, CAI, "\x01\xc0");
8913  add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8914  add_p(plci, LLI, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8915  add_p(plci, SHIFT | 6, NULL);
8916  add_p(plci, SIN, "\x02\x00\x00");
8917  plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8918  sig_req(plci, ASSIGN, DSIG_ID);
8919  send_req(plci);
8920  }
8921  }
8922  }
8923 }
8924 
8925 /*------------------------------------------------------------------*/
8926 /* functions for all parameters sent in INDs */
8927 /*------------------------------------------------------------------*/
8928 
8929 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8930 {
8931  word ploc; /* points to current location within packet */
8932  byte w;
8933  byte wlen;
8934  byte codeset, lock;
8935  byte *in;
8936  word i;
8937  word code;
8938  word mIEindex = 0;
8939  ploc = 0;
8940  codeset = 0;
8941  lock = 0;
8942 
8943  in = plci->Sig.RBuffer->P;
8944  for (i = 0; i < parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8945  { /* element but parms array is larger */
8946  parms[i] = (byte *)"";
8947  }
8948  for (i = 0; i < multiIEsize; i++)
8949  {
8950  parms[i] = (byte *)"";
8951  }
8952 
8953  while (ploc < plci->Sig.RBuffer->length - 1) {
8954 
8955  /* read information element id and length */
8956  w = in[ploc];
8957 
8958  if (w & 0x80) {
8959 /* w &=0xf0; removed, cannot detect congestion levels */
8960 /* upper 4 bit masked with w==SHIFT now */
8961  wlen = 0;
8962  }
8963  else {
8964  wlen = (byte)(in[ploc + 1] + 1);
8965  }
8966  /* check if length valid (not exceeding end of packet) */
8967  if ((ploc + wlen) > 270) return;
8968  if (lock & 0x80) lock &= 0x7f;
8969  else codeset = lock;
8970 
8971  if ((w & 0xf0) == SHIFT) {
8972  codeset = in[ploc];
8973  if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8974  codeset &= 7;
8975  lock |= 0x80;
8976  }
8977  else {
8978  if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8979  else code = w;
8980  code |= (codeset << 8);
8981 
8982  for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8983 
8984  if (i < parms_id[0] + 1) {
8985  if (!multiIEsize) { /* with multiIEs use next field index, */
8986  mIEindex = i - 1; /* with normal IEs use same index like parms_id */
8987  }
8988 
8989  parms[mIEindex] = &in[ploc + 1];
8990  dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8991  if (parms_id[i] == OAD
8992  || parms_id[i] == CONN_NR
8993  || parms_id[i] == CAD) {
8994  if (in[ploc + 2] & 0x80) {
8995  in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8996  in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8997  in[ploc + 2] = 0x80;
8998  parms[mIEindex] = &in[ploc];
8999  }
9000  }
9001  mIEindex++; /* effects multiIEs only */
9002  }
9003  }
9004 
9005  ploc += (wlen + 1);
9006  }
9007  return;
9008 }
9009 
9010 /*------------------------------------------------------------------*/
9011 /* try to match a cip from received BC and HLC */
9012 /*------------------------------------------------------------------*/
9013 
9014 static byte ie_compare(byte *ie1, byte *ie2)
9015 {
9016  word i;
9017  if (!ie1 || !ie2) return false;
9018  if (!ie1[0]) return false;
9019  for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9020  return true;
9021 }
9022 
9023 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9024 {
9025  word i;
9026  word j;
9027 
9028  for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9029 
9030  for (j = 16; j < 29 &&
9031  (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9032  if (j == 29) return i;
9033  return j;
9034 }
9035 
9036 
9037 static byte AddInfo(byte **add_i,
9038  byte **fty_i,
9039  byte *esc_chi,
9040  byte *facility)
9041 {
9042  byte i;
9043  byte j;
9044  byte k;
9045  byte flen;
9046  byte len = 0;
9047  /* facility is a nested structure */
9048  /* FTY can be more than once */
9049 
9050  if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9051  {
9052  add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9053  }
9054 
9055  else
9056  {
9057  add_i[0] = (byte *)"";
9058  }
9059  if (!fty_i[0][0])
9060  {
9061  add_i[3] = (byte *)"";
9062  }
9063  else
9064  { /* facility array found */
9065  for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9066  {
9067  dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9068  len += fty_i[i][0];
9069  len += 2;
9070  flen = fty_i[i][0];
9071  facility[j++] = 0x1c; /* copy fac IE */
9072  for (k = 0; k <= flen; k++, j++)
9073  {
9074  facility[j] = fty_i[i][k];
9075 /* dbug(1, dprintf("%x ",facility[j])); */
9076  }
9077  }
9078  facility[0] = len;
9079  add_i[3] = facility;
9080  }
9081 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
9082  len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9083  len += 4; /* calculate length of all */
9084  return (len);
9085 }
9086 
9087 /*------------------------------------------------------------------*/
9088 /* voice and codec features */
9089 /*------------------------------------------------------------------*/
9090 
9091 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9092 {
9093  byte voice_chi[] = "\x02\x18\x01";
9094  byte channel;
9095 
9096  channel = chi[chi[0]] & 0x3;
9097  dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9098  voice_chi[2] = (channel) ? channel : 1;
9099  add_p(plci, FTY, "\x02\x01\x07"); /* B On, default on 1 */
9100  add_p(plci, ESC, voice_chi); /* Channel */
9101  sig_req(plci, TEL_CTRL, 0);
9102  send_req(plci);
9103  if (a->AdvSignalPLCI)
9104  {
9105  adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9106  }
9107 }
9108 
9109 static void VoiceChannelOff(PLCI *plci)
9110 {
9111  dbug(1, dprintf("ExtDevOFF"));
9112  add_p(plci, FTY, "\x02\x01\x08"); /* B Off */
9113  sig_req(plci, TEL_CTRL, 0);
9114  send_req(plci);
9115  if (plci->adapter->AdvSignalPLCI)
9116  {
9117  adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9118  }
9119 }
9120 
9121 
9122 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9123  byte hook_listen)
9124 {
9125  word j;
9126  PLCI *splci;
9127 
9128  /* check if hardware supports handset with hook states (adv.codec) */
9129  /* or if just a on board codec is supported */
9130  /* the advanced codec plci is just for internal use */
9131 
9132  /* diva Pro with on-board codec: */
9133  if (a->profile.Global_Options & HANDSET)
9134  {
9135  /* new call, but hook states are already signalled */
9136  if (a->AdvCodecFLAG)
9137  {
9138  if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9139  {
9140  dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9141  return 0x2001; /* codec in use by another application */
9142  }
9143  if (plci != NULL)
9144  {
9145  a->AdvSignalPLCI = plci;
9146  plci->tel = ADV_VOICE;
9147  }
9148  return 0; /* adv codec still used */
9149  }
9150  if ((j = get_plci(a)))
9151  {
9152  splci = &a->plci[j - 1];
9153  splci->tel = CODEC_PERMANENT;
9154  /* hook_listen indicates if a facility_req with handset/hook support */
9155  /* was sent. Otherwise if just a call on an external device was made */
9156  /* the codec will be used but the hook info will be discarded (just */
9157  /* the external controller is in use */
9158  if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9159  else
9160  {
9161  splci->State = ADVANCED_VOICE_NOSIG;
9162  if (plci)
9163  {
9165  }
9166  /* indicate D-ch connect if */
9167  } /* codec is connected OK */
9168  if (plci != NULL)
9169  {
9170  a->AdvSignalPLCI = plci;
9171  plci->tel = ADV_VOICE;
9172  }
9173  a->AdvSignalAppl = appl;
9174  a->AdvCodecFLAG = true;
9175  a->AdvCodecPLCI = splci;
9176  add_p(splci, CAI, "\x01\x15");
9177  add_p(splci, LLI, "\x01\x00");
9178  add_p(splci, ESC, "\x02\x18\x00");
9179  add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9181  dbug(1, dprintf("Codec Assign"));
9182  sig_req(splci, ASSIGN, DSIG_ID);
9183  send_req(splci);
9184  }
9185  else
9186  {
9187  return 0x2001; /* wrong state, no more plcis */
9188  }
9189  }
9190  else if (a->profile.Global_Options & ON_BOARD_CODEC)
9191  {
9192  if (hook_listen) return 0x300B; /* Facility not supported */
9193  /* no hook with SCOM */
9194  if (plci != NULL) plci->tel = CODEC;
9195  dbug(1, dprintf("S/SCOM codec"));
9196  /* first time we use the scom-s codec we must shut down the internal */
9197  /* handset application of the card. This can be done by an assign with */
9198  /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9199  if (!a->scom_appl_disable) {
9200  if ((j = get_plci(a))) {
9201  splci = &a->plci[j - 1];
9202  add_p(splci, CAI, "\x01\x80");
9203  add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9204  sig_req(splci, ASSIGN, 0xC0); /* 0xc0 is the TEL_ID */
9205  send_req(splci);
9206  a->scom_appl_disable = true;
9207  }
9208  else{
9209  return 0x2001; /* wrong state, no more plcis */
9210  }
9211  }
9212  }
9213  else return 0x300B; /* Facility not supported */
9214 
9215  return 0;
9216 }
9217 
9218 
9219 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220 {
9221 
9222  dbug(1, dprintf("CodecIdCheck"));
9223 
9224  if (a->AdvSignalPLCI == plci)
9225  {
9226  dbug(1, dprintf("PLCI owns codec"));
9227  VoiceChannelOff(a->AdvCodecPLCI);
9229  {
9230  dbug(1, dprintf("remove temp codec PLCI"));
9231  plci_remove(a->AdvCodecPLCI);
9232  a->AdvCodecFLAG = 0;
9233  a->AdvCodecPLCI = NULL;
9234  a->AdvSignalAppl = NULL;
9235  }
9236  a->AdvSignalPLCI = NULL;
9237  }
9238 }
9239 
9240 /* -------------------------------------------------------------------
9241  Ask for physical address of card on PCI bus
9242  ------------------------------------------------------------------- */
9243 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9244  IDI_SYNC_REQ *preq) {
9245  a->sdram_bar = 0;
9246  if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9247  ENTITY *e = (ENTITY *)preq;
9248 
9249  e->user[0] = a->Id - 1;
9250  preq->xdi_sdram_bar.info.bar = 0;
9251  preq->xdi_sdram_bar.Req = 0;
9253 
9254  (*(a->request))(e);
9255 
9256  a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9257  dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9258  }
9259 }
9260 
9261 /* -------------------------------------------------------------------
9262  Ask XDI about extended features
9263  ------------------------------------------------------------------- */
9264 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9265  IDI_SYNC_REQ *preq;
9266  char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9267 
9268  char features[4];
9269  preq = (IDI_SYNC_REQ *)&buffer[0];
9270 
9271  if (!diva_xdi_extended_features) {
9272  ENTITY *e = (ENTITY *)preq;
9273  diva_xdi_extended_features |= 0x80000000;
9274 
9275  e->user[0] = a->Id - 1;
9276  preq->xdi_extended_features.Req = 0;
9278  preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9279  preq->xdi_extended_features.info.features = &features[0];
9280 
9281  (*(a->request))(e);
9282 
9283  if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9284  /*
9285  Check features located in the byte '0'
9286  */
9287  if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9288  diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9289  }
9290  if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9291  diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9292  dbug(1, dprintf("XDI provides RxDMA"));
9293  }
9294  if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9295  diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9296  }
9297  if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9298  diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9299  dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9300  }
9301 
9302  }
9303  }
9304 
9305  diva_ask_for_xdi_sdram_bar(a, preq);
9306 }
9307 
9308 /*------------------------------------------------------------------*/
9309 /* automatic law */
9310 /*------------------------------------------------------------------*/
9311 /* called from OS specific part after init time to get the Law */
9312 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9314 {
9315  word j;
9316  PLCI *splci;
9317 
9318  if (a->automatic_law) {
9319  return;
9320  }
9321  if ((j = get_plci(a))) {
9322  diva_get_extended_adapter_features(a);
9323  splci = &a->plci[j - 1];
9324  a->automatic_lawPLCI = splci;
9325  a->automatic_law = 1;
9326  add_p(splci, CAI, "\x01\x80");
9327  add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9328  splci->internal_command = USELAW_REQ;
9329  splci->command = 0;
9330  splci->number = 0;
9331  sig_req(splci, ASSIGN, DSIG_ID);
9332  send_req(splci);
9333  }
9334 }
9335 
9336 /* called from OS specific part if an application sends an Capi20Release */
9338 {
9339  word i, j, appls_found;
9340  PLCI *plci;
9341  APPL *this;
9343 
9344  if (!Id)
9345  {
9346  dbug(0, dprintf("A: CapiRelease(Id==0)"));
9347  return (_WRONG_APPL_ID);
9348  }
9349 
9350  this = &application[Id - 1]; /* get application pointer */
9351 
9352  for (i = 0, appls_found = 0; i < max_appl; i++)
9353  {
9354  if (application[i].Id) /* an application has been found */
9355  {
9356  appls_found++;
9357  }
9358  }
9359 
9360  for (i = 0; i < max_adapter; i++) /* scan all adapters... */
9361  {
9362  a = &adapter[i];
9363  if (a->request)
9364  {
9365  a->Info_Mask[Id - 1] = 0;
9366  a->CIP_Mask[Id - 1] = 0;
9367  a->Notification_Mask[Id - 1] = 0;
9368  a->codec_listen[Id - 1] = NULL;
9369  a->requested_options_table[Id - 1] = 0;
9370  for (j = 0; j < a->max_plci; j++) /* and all PLCIs connected */
9371  { /* with this application */
9372  plci = &a->plci[j];
9373  if (plci->Id) /* if plci owns no application */
9374  { /* it may be not jet connected */
9375  if (plci->State == INC_CON_PENDING
9376  || plci->State == INC_CON_ALERT)
9377  {
9378  if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9379  {
9380  clear_c_ind_mask_bit(plci, (word)(Id - 1));
9381  if (c_ind_mask_empty(plci))
9382  {
9383  sig_req(plci, HANGUP, 0);
9384  send_req(plci);
9385  plci->State = OUTG_DIS_PENDING;
9386  }
9387  }
9388  }
9389  if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9390  {
9391  clear_c_ind_mask_bit(plci, (word)(Id - 1));
9392  if (c_ind_mask_empty(plci))
9393  {
9394  if (!plci->appl)
9395  {
9396  plci_remove(plci);
9397  plci->State = IDLE;
9398  }
9399  }
9400  }
9401  if (plci->appl == this)
9402  {
9403  plci->appl = NULL;
9404  plci_remove(plci);
9405  plci->State = IDLE;
9406  }
9407  }
9408  }
9409  listen_check(a);
9410 
9411  if (a->flag_dynamic_l1_down)
9412  {
9413  if (appls_found == 1) /* last application does a capi release */
9414  {
9415  if ((j = get_plci(a)))
9416  {
9417  plci = &a->plci[j - 1];
9418  plci->command = 0;
9419  add_p(plci, OAD, "\x01\xfd");
9420  add_p(plci, CAI, "\x01\x80");
9421  add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9422  add_p(plci, SHIFT | 6, NULL);
9423  add_p(plci, SIN, "\x02\x00\x00");
9425  sig_req(plci, ASSIGN, DSIG_ID);
9426  add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9427  sig_req(plci, SIG_CTRL, 0);
9428  send_req(plci);
9429  }
9430  }
9431  }
9432  if (a->AdvSignalAppl == this)
9433  {
9434  this->NullCREnable = false;
9435  if (a->AdvCodecPLCI)
9436  {
9437  plci_remove(a->AdvCodecPLCI);
9438  a->AdvCodecPLCI->tel = 0;
9439  a->AdvCodecPLCI->adv_nl = 0;
9440  }
9441  a->AdvSignalAppl = NULL;
9442  a->AdvSignalPLCI = NULL;
9443  a->AdvCodecFLAG = 0;
9444  a->AdvCodecPLCI = NULL;
9445  }
9446  }
9447  }
9448 
9449  this->Id = 0;
9450 
9451  return GOOD;
9452 }
9453 
9454 static word plci_remove_check(PLCI *plci)
9455 {
9456  if (!plci) return true;
9457  if (!plci->NL.Id && c_ind_mask_empty(plci))
9458  {
9459  if (plci->Sig.Id == 0xff)
9460  plci->Sig.Id = 0;
9461  if (!plci->Sig.Id)
9462  {
9463  dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9464  dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9465  if (plci->Id)
9466  {
9467  CodecIdCheck(plci->adapter, plci);
9468  clear_b1_config(plci);
9469  ncci_remove(plci, 0, false);
9470  plci_free_msg_in_queue(plci);
9471  channel_flow_control_remove(plci);
9472  plci->Id = 0;
9473  plci->State = IDLE;
9474  plci->channels = 0;
9475  plci->appl = NULL;
9476  plci->notifiedcall = 0;
9477  }
9478  listen_check(plci->adapter);
9479  return true;
9480  }
9481  }
9482  return false;
9483 }
9484 
9485 
9486 /*------------------------------------------------------------------*/
9487 
9488 static byte plci_nl_busy(PLCI *plci)
9489 {
9490  /* only applicable for non-multiplexed protocols */
9491  return (plci->nl_req
9492  || (plci->ncci_ring_list
9493  && plci->adapter->ncci_ch[plci->ncci_ring_list]
9494  && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9495 }
9496 
9497 
9498 /*------------------------------------------------------------------*/
9499 /* DTMF facilities */
9500 /*------------------------------------------------------------------*/
9501 
9502 
9503 static struct
9504 {
9509 } dtmf_digit_map[] =
9510 {
9511  { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9512  { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9513  { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9514  { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9515  { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9516  { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9517  { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9518  { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9519  { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9520  { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9521  { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9522  { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9523  { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9524  { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9525  { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9526  { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9527  { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9528  { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9529  { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9530  { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9531 
9532  { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9533  { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9534  { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9535  { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9536  { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9537  { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9538  { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9539  { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9540  { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9541  { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9542  { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9543  { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9544  { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9545  { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9546  { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9547  { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9548  { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9549  { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9550  { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9551  { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9552  { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9553  { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9554  { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9555  { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9556  { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9557  { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9558  { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9559  { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9560  { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9561  { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9562  { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9563  { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9564  { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9565  { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9566  { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9567  { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9568  { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9569  { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9570  { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9571  { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9572  { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9573  { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9574  { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9575  { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9576  { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9577  { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9578  { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9579  { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9580  { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9581  { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9582  { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9583  { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9584 
9585 };
9586 
9587 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588 
9589 
9590 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9591 {
9592  word min_digit_duration, min_gap_duration;
9593 
9594  dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9595  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9596  (char *)(FILE_), __LINE__, enable_mask));
9597 
9598  if (enable_mask != 0)
9599  {
9600  min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9601  min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9603  PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9604  PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9605  plci->NData[0].PLength = 5;
9606 
9607  PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9608  plci->NData[0].PLength += 2;
9609  capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9610 
9611  }
9612  else
9613  {
9615  plci->NData[0].PLength = 1;
9616 
9618 
9619  }
9620  plci->NData[0].P = plci->internal_req_buffer;
9621  plci->NL.X = plci->NData;
9622  plci->NL.ReqCh = 0;
9623  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9624  plci->adapter->request(&plci->NL);
9625 }
9626 
9627 
9628 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9629 {
9630  word w, i;
9631 
9632  dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9633  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9634  (char *)(FILE_), __LINE__, digit_count));
9635 
9637  w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9638  PUT_WORD(&plci->internal_req_buffer[1], w);
9639  w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9640  PUT_WORD(&plci->internal_req_buffer[3], w);
9641  for (i = 0; i < digit_count; i++)
9642  {
9643  w = 0;
9644  while ((w < DTMF_DIGIT_MAP_ENTRIES)
9645  && (digit_buffer[i] != dtmf_digit_map[w].character))
9646  {
9647  w++;
9648  }
9649  plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9650  dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9651  }
9652  plci->NData[0].PLength = 5 + digit_count;
9653  plci->NData[0].P = plci->internal_req_buffer;
9654  plci->NL.X = plci->NData;
9655  plci->NL.ReqCh = 0;
9656  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9657  plci->adapter->request(&plci->NL);
9658 }
9659 
9660 
9661 static void dtmf_rec_clear_config(PLCI *plci)
9662 {
9663 
9664  dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9665  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9666  (char *)(FILE_), __LINE__));
9667 
9668  plci->dtmf_rec_active = 0;
9669  plci->dtmf_rec_pulse_ms = 0;
9670  plci->dtmf_rec_pause_ms = 0;
9671 
9672  capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9673 
9674 }
9675 
9676 
9677 static void dtmf_send_clear_config(PLCI *plci)
9678 {
9679 
9680  dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9681  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9682  (char *)(FILE_), __LINE__));
9683 
9684  plci->dtmf_send_requests = 0;
9685  plci->dtmf_send_pulse_ms = 0;
9686  plci->dtmf_send_pause_ms = 0;
9687 }
9688 
9689 
9690 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691 {
9692 
9693  dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9694  UnMapId(Id), (char *)(FILE_), __LINE__));
9695 
9696  while (plci->dtmf_send_requests != 0)
9697  dtmf_confirmation(Id, plci);
9698 }
9699 
9700 
9701 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702 {
9703 
9704  dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9705  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9706 
9707  return (GOOD);
9708 }
9709 
9710 
9711 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9712 {
9713  word Info;
9714 
9715  dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9716  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9717 
9718  Info = GOOD;
9719  if (plci->B1_facilities & B1_FACILITY_DTMFR)
9720  {
9721  switch (plci->adjust_b_state)
9722  {
9724  plci->internal_command = plci->adjust_b_command;
9725  if (plci_nl_busy(plci))
9726  {
9728  break;
9729  }
9730  dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9732  break;
9734  if ((Rc != OK) && (Rc != OK_FC))
9735  {
9736  dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9737  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9738  Info = _WRONG_STATE;
9739  break;
9740  }
9741  break;
9742  }
9743  }
9744  return (Info);
9745 }
9746 
9747 
9748 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9749 {
9750  word internal_command, Info;
9751  byte mask;
9752  byte result[4];
9753 
9754  dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9755  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9756  plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9757  plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9758 
9759  Info = GOOD;
9760  result[0] = 2;
9761  PUT_WORD(&result[1], DTMF_SUCCESS);
9762  internal_command = plci->internal_command;
9763  plci->internal_command = 0;
9764  mask = 0x01;
9765  switch (plci->dtmf_cmd)
9766  {
9767 
9769  mask <<= 1;
9770  case DTMF_LISTEN_MF_START:
9771  mask <<= 1;
9772 
9773  case DTMF_LISTEN_START:
9774  switch (internal_command)
9775  {
9776  default:
9777  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9779  case DTMF_COMMAND_1:
9780  if (adjust_b_process(Id, plci, Rc) != GOOD)
9781  {
9782  dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9783  UnMapId(Id), (char *)(FILE_), __LINE__));
9784  Info = _FACILITY_NOT_SUPPORTED;
9785  break;
9786  }
9787  if (plci->internal_command)
9788  return;
9789  case DTMF_COMMAND_2:
9790  if (plci_nl_busy(plci))
9791  {
9793  return;
9794  }
9796  dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9797  return;
9798  case DTMF_COMMAND_3:
9799  if ((Rc != OK) && (Rc != OK_FC))
9800  {
9801  dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9802  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9803  Info = _FACILITY_NOT_SUPPORTED;
9804  break;
9805  }
9806 
9808 
9809  plci->dtmf_rec_active |= mask;
9810  break;
9811  }
9812  break;
9813 
9814 
9815  case DTMF_LISTEN_TONE_STOP:
9816  mask <<= 1;
9817  case DTMF_LISTEN_MF_STOP:
9818  mask <<= 1;
9819 
9820  case DTMF_LISTEN_STOP:
9821  switch (internal_command)
9822  {
9823  default:
9824  plci->dtmf_rec_active &= ~mask;
9825  if (plci->dtmf_rec_active)
9826  break;
9827 /*
9828  case DTMF_COMMAND_1:
9829  if (plci->dtmf_rec_active)
9830  {
9831  if (plci_nl_busy (plci))
9832  {
9833  plci->internal_command = DTMF_COMMAND_1;
9834  return;
9835  }
9836  plci->dtmf_rec_active &= ~mask;
9837  plci->internal_command = DTMF_COMMAND_2;
9838  dtmf_enable_receiver (plci, false);
9839  return;
9840  }
9841  Rc = OK;
9842  case DTMF_COMMAND_2:
9843  if ((Rc != OK) && (Rc != OK_FC))
9844  {
9845  dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9846  UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9847  Info = _FACILITY_NOT_SUPPORTED;
9848  break;
9849  }
9850 */
9851  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9853  case DTMF_COMMAND_3:
9854  if (adjust_b_process(Id, plci, Rc) != GOOD)
9855  {
9856  dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9857  UnMapId(Id), (char *)(FILE_), __LINE__));
9858  Info = _FACILITY_NOT_SUPPORTED;
9859  break;
9860  }
9861  if (plci->internal_command)
9862  return;
9863  break;
9864  }
9865  break;
9866 
9867 
9868  case DTMF_SEND_TONE:
9869  mask <<= 1;
9870  case DTMF_SEND_MF:
9871  mask <<= 1;
9872 
9873  case DTMF_DIGITS_SEND:
9874  switch (internal_command)
9875  {
9876  default:
9877  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9879  DTMF_COMMAND_1);
9880  case DTMF_COMMAND_1:
9881  if (adjust_b_process(Id, plci, Rc) != GOOD)
9882  {
9883  dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9884  UnMapId(Id), (char *)(FILE_), __LINE__));
9885  Info = _FACILITY_NOT_SUPPORTED;
9886  break;
9887  }
9888  if (plci->internal_command)
9889  return;
9890  case DTMF_COMMAND_2:
9891  if (plci_nl_busy(plci))
9892  {
9894  return;
9895  }
9896  plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9898  dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9899  return;
9900  case DTMF_COMMAND_3:
9901  if ((Rc != OK) && (Rc != OK_FC))
9902  {
9903  dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9904  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9905  if (plci->dtmf_send_requests != 0)
9906  (plci->dtmf_send_requests)--;
9907  Info = _FACILITY_NOT_SUPPORTED;
9908  break;
9909  }
9910  return;
9911  }
9912  break;
9913  }
9914  sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9915  "wws", Info, SELECTOR_DTMF, result);
9916 }
9917 
9918 
9919 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9920 {
9921  word Info;
9922  word i, j;
9923  byte mask;
9924  API_PARSE dtmf_parms[5];
9925  byte result[40];
9926 
9927  dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9928  UnMapId(Id), (char *)(FILE_), __LINE__));
9929 
9930  Info = GOOD;
9931  result[0] = 2;
9932  PUT_WORD(&result[1], DTMF_SUCCESS);
9934  {
9935  dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9936  UnMapId(Id), (char *)(FILE_), __LINE__));
9937  Info = _FACILITY_NOT_SUPPORTED;
9938  }
9939  else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9940  {
9941  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9942  UnMapId(Id), (char *)(FILE_), __LINE__));
9943  Info = _WRONG_MESSAGE_FORMAT;
9944  }
9945 
9946  else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947  || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9948  {
9949  if (!((a->requested_options_table[appl->Id - 1])
9950  & (1L << PRIVATE_DTMF_TONE)))
9951  {
9952  dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9953  UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9954  PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9955  }
9956  else
9957  {
9958  for (i = 0; i < 32; i++)
9959  result[4 + i] = 0;
9960  if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9961  {
9962  for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9963  {
9964  if (dtmf_digit_map[i].listen_mask != 0)
9965  result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966  }
9967  }
9968  else
9969  {
9970  for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9971  {
9972  if (dtmf_digit_map[i].send_mask != 0)
9973  result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9974  }
9975  }
9976  result[0] = 3 + 32;
9977  result[3] = 32;
9978  }
9979  }
9980 
9981  else if (plci == NULL)
9982  {
9983  dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9984  UnMapId(Id), (char *)(FILE_), __LINE__));
9985  Info = _WRONG_IDENTIFIER;
9986  }
9987  else
9988  {
9989  if (!plci->State
9990  || !plci->NL.Id || plci->nl_remove_id)
9991  {
9992  dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9993  UnMapId(Id), (char *)(FILE_), __LINE__));
9994  Info = _WRONG_STATE;
9995  }
9996  else
9997  {
9998  plci->command = 0;
9999  plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
10000  mask = 0x01;
10001  switch (plci->dtmf_cmd)
10002  {
10003 
10005  case DTMF_LISTEN_TONE_STOP:
10006  mask <<= 1;
10007  case DTMF_LISTEN_MF_START:
10008  case DTMF_LISTEN_MF_STOP:
10009  mask <<= 1;
10010  if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10011  & (1L << PRIVATE_DTMF_TONE)))
10012  {
10013  dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10014  UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10015  PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10016  break;
10017  }
10018 
10019  case DTMF_LISTEN_START:
10020  case DTMF_LISTEN_STOP:
10023  {
10024  dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10025  UnMapId(Id), (char *)(FILE_), __LINE__));
10026  Info = _FACILITY_NOT_SUPPORTED;
10027  break;
10028  }
10029  if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10030  {
10031  if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10032  {
10033  plci->dtmf_rec_pulse_ms = 0;
10034  plci->dtmf_rec_pause_ms = 0;
10035  }
10036  else
10037  {
10038  plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10039  plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040  }
10041  }
10042  start_internal_command(Id, plci, dtmf_command);
10043  return (false);
10044 
10045 
10046  case DTMF_SEND_TONE:
10047  mask <<= 1;
10048  case DTMF_SEND_MF:
10049  mask <<= 1;
10050  if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10051  & (1L << PRIVATE_DTMF_TONE)))
10052  {
10053  dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10054  UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10055  PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10056  break;
10057  }
10058 
10059  case DTMF_DIGITS_SEND:
10060  if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10061  {
10062  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10063  UnMapId(Id), (char *)(FILE_), __LINE__));
10064  Info = _WRONG_MESSAGE_FORMAT;
10065  break;
10066  }
10067  if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10068  {
10069  plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10070  plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10071  }
10072  i = 0;
10073  j = 0;
10074  while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10075  {
10076  j = 0;
10077  while ((j < DTMF_DIGIT_MAP_ENTRIES)
10078  && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10079  || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10080  {
10081  j++;
10082  }
10083  i++;
10084  }
10085  if (j == DTMF_DIGIT_MAP_ENTRIES)
10086  {
10087  dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10088  UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10089  PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10090  break;
10091  }
10093  {
10094  dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10095  UnMapId(Id), (char *)(FILE_), __LINE__));
10096  Info = _WRONG_STATE;
10097  break;
10098  }
10099  api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10100  start_internal_command(Id, plci, dtmf_command);
10101  return (false);
10102 
10103  default:
10104  dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10105  UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10106  PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10107  }
10108  }
10109  }
10110  sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10111  "wws", Info, SELECTOR_DTMF, result);
10112  return (false);
10113 }
10114 
10115 
10116 static void dtmf_confirmation(dword Id, PLCI *plci)
10117 {
10118  word i;
10119  byte result[4];
10120 
10121  dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10122  UnMapId(Id), (char *)(FILE_), __LINE__));
10123 
10124  result[0] = 2;
10125  PUT_WORD(&result[1], DTMF_SUCCESS);
10126  if (plci->dtmf_send_requests != 0)
10127  {
10128  sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10129  "wws", GOOD, SELECTOR_DTMF, result);
10130  (plci->dtmf_send_requests)--;
10131  for (i = 0; i < plci->dtmf_send_requests; i++)
10132  plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10133  }
10134 }
10135 
10136 
10137 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10138 {
10139  word i, j, n;
10140 
10141  dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10142  UnMapId(Id), (char *)(FILE_), __LINE__));
10143 
10144  n = 0;
10145  for (i = 1; i < length; i++)
10146  {
10147  j = 0;
10148  while ((j < DTMF_DIGIT_MAP_ENTRIES)
10149  && ((msg[i] != dtmf_digit_map[j].code)
10150  || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10151  {
10152  j++;
10153  }
10154  if (j < DTMF_DIGIT_MAP_ENTRIES)
10155  {
10156 
10157  if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10159  && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10160  {
10161  if (n + 1 == i)
10162  {
10163  for (i = length; i > n + 1; i--)
10164  msg[i] = msg[i - 1];
10165  length++;
10166  i++;
10167  }
10169  }
10170  plci->tone_last_indication_code = dtmf_digit_map[j].character;
10171 
10172  msg[++n] = dtmf_digit_map[j].character;
10173  }
10174  }
10175  if (n != 0)
10176  {
10177  msg[0] = (byte) n;
10178  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10179  }
10180 }
10181 
10182 
10183 /*------------------------------------------------------------------*/
10184 /* DTMF parameters */
10185 /*------------------------------------------------------------------*/
10186 
10187 static void dtmf_parameter_write(PLCI *plci)
10188 {
10189  word i;
10190  byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10191 
10192  dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10193  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10194  (char *)(FILE_), __LINE__));
10195 
10196  parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10197  parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10198  for (i = 0; i < plci->dtmf_parameter_length; i++)
10199  parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10200  add_p(plci, FTY, parameter_buffer);
10201  sig_req(plci, TEL_CTRL, 0);
10202  send_req(plci);
10203 }
10204 
10205 
10206 static void dtmf_parameter_clear_config(PLCI *plci)
10207 {
10208 
10209  dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10210  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10211  (char *)(FILE_), __LINE__));
10212 
10213  plci->dtmf_parameter_length = 0;
10214 }
10215 
10216 
10217 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218 {
10219 
10220  dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10221  UnMapId(Id), (char *)(FILE_), __LINE__));
10222 
10223 }
10224 
10225 
10226 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227 {
10228 
10229  dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10230  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231 
10232  return (GOOD);
10233 }
10234 
10235 
10236 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10237 {
10238  word Info;
10239 
10240  dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10241  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10242 
10243  Info = GOOD;
10244  if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10245  && (plci->dtmf_parameter_length != 0))
10246  {
10247  switch (plci->adjust_b_state)
10248  {
10250  plci->internal_command = plci->adjust_b_command;
10251  if (plci->sig_req)
10252  {
10254  break;
10255  }
10256  dtmf_parameter_write(plci);
10258  break;
10260  if ((Rc != OK) && (Rc != OK_FC))
10261  {
10262  dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10263  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10264  Info = _WRONG_STATE;
10265  break;
10266  }
10267  break;
10268  }
10269  }
10270  return (Info);
10271 }
10272 
10273 
10274 /*------------------------------------------------------------------*/
10275 /* Line interconnect facilities */
10276 /*------------------------------------------------------------------*/
10277 
10278 
10281 
10282 
10283 /*------------------------------------------------------------------*/
10284 /* translate a CHI information element to a channel number */
10285 /* returns 0xff - any channel */
10286 /* 0xfe - chi wrong coding */
10287 /* 0xfd - D-channel */
10288 /* 0x00 - no channel */
10289 /* else channel number / PRI: timeslot */
10290 /* if channels is provided we accept more than one channel. */
10291 /*------------------------------------------------------------------*/
10292 
10293 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10294 {
10295  int p;
10296  int i;
10297  dword map;
10298  byte excl;
10299  byte ofs;
10300  byte ch;
10301 
10302  if (pchannelmap) *pchannelmap = 0;
10303  if (!chi[0]) return 0xff;
10304  excl = 0;
10305 
10306  if (chi[1] & 0x20) {
10307  if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10308  for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10309  if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10310  if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10311  if (chi[1] & 0x08) excl = 0x40;
10312 
10313  /* int. id present */
10314  if (chi[1] & 0x40) {
10315  p = i + 1;
10316  for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10317  if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318  }
10319 
10320  /* coding standard, Number/Map, Channel Type */
10321  p = i + 1;
10322  for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10323  if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10324  if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10325 
10326  /* Number/Map */
10327  if (chi[p] & 0x10) {
10328 
10329  /* map */
10330  if ((chi[0] - p) == 4) ofs = 0;
10331  else if ((chi[0] - p) == 3) ofs = 1;
10332  else return 0xfe;
10333  ch = 0;
10334  map = 0;
10335  for (i = 0; i < 4 && p < chi[0]; i++) {
10336  p++;
10337  ch += 8;
10338  map <<= 8;
10339  if (chi[p]) {
10340  for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10341  map |= chi[p];
10342  }
10343  }
10344  ch += ofs;
10345  map <<= ofs;
10346  }
10347  else {
10348 
10349  /* number */
10350  p = i + 1;
10351  ch = chi[p] & 0x3f;
10352  if (pchannelmap) {
10353  if ((byte)(chi[0] - p) > 30) return 0xfe;
10354  map = 0;
10355  for (i = p; i <= chi[0]; i++) {
10356  if ((chi[i] & 0x7f) > 31) return 0xfe;
10357  map |= (1L << (chi[i] & 0x7f));
10358  }
10359  }
10360  else {
10361  if (p != chi[0]) return 0xfe;
10362  if (ch > 31) return 0xfe;
10363  map = (1L << ch);
10364  }
10365  if (chi[p] & 0x40) return 0xfe;
10366  }
10367  if (pchannelmap) *pchannelmap = map;
10368  else if (map != ((dword)(1L << ch))) return 0xfe;
10369  return (byte)(excl | ch);
10370  }
10371  else { /* not PRI */
10372  for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10373  if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10374  if (chi[1] & 0x08) excl = 0x40;
10375 
10376  switch (chi[1] | 0x98) {
10377  case 0x98: return 0;
10378  case 0x99:
10379  if (pchannelmap) *pchannelmap = 2;
10380  return excl | 1;
10381  case 0x9a:
10382  if (pchannelmap) *pchannelmap = 4;
10383  return excl | 2;
10384  case 0x9b: return 0xff;
10385  case 0x9c: return 0xfd; /* d-ch */
10386  default: return 0xfe;
10387  }
10388  }
10389 }
10390 
10391 
10392 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10393 {
10395  PLCI *splci;
10396  byte old_id;
10397 
10398  a = plci->adapter;
10399  old_id = plci->li_bchannel_id;
10400  if (a->li_pri)
10401  {
10402  if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10403  li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10404  plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10405  if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10406  li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10407  }
10408  else
10409  {
10410  if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10411  {
10412  if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10413  li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10414  plci->li_bchannel_id = bchannel_id & 0x03;
10415  if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10416  {
10417  splci = a->AdvSignalPLCI;
10418  if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10419  {
10420  if ((splci->li_bchannel_id != 0)
10421  && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10422  {
10423  li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10424  }
10425  splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10426  li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10427  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10428  (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10429  (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430  }
10431  }
10432  if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10433  li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434  }
10435  }
10436  if ((old_id == 0) && (plci->li_bchannel_id != 0)
10437  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10438  {
10439  mixer_clear_config(plci);
10440  }
10441  dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10442  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10443  (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10444 }
10445 
10446 
10447 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10448 {
10450  PLCI *splci;
10451  byte ch, old_id;
10452 
10453  a = plci->adapter;
10454  old_id = plci->li_bchannel_id;
10455  ch = chi_to_channel(chi, NULL);
10456  if (!(ch & 0x80))
10457  {
10458  if (a->li_pri)
10459  {
10460  if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10461  li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10462  plci->li_bchannel_id = (ch & 0x1f) + 1;
10463  if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10464  li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10465  }
10466  else
10467  {
10468  if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10469  {
10470  if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10471  li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10472  plci->li_bchannel_id = ch & 0x1f;
10473  if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10474  {
10475  splci = a->AdvSignalPLCI;
10476  if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10477  {
10478  if ((splci->li_bchannel_id != 0)
10479  && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10480  {
10481  li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10482  }
10483  splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10484  li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10485  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10486  (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10487  (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488  }
10489  }
10490  if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10491  li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10492  }
10493  }
10494  }
10495  if ((old_id == 0) && (plci->li_bchannel_id != 0)
10496  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10497  {
10498  mixer_clear_config(plci);
10499  }
10500  dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10501  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10502  (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10503 }
10504 
10505 
10506 #define MIXER_MAX_DUMP_CHANNELS 34
10507 
10508 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10509 {
10510  static char hex_digit_table[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
10511  word n, i, j;
10512  char *p;
10513  char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10514 
10515  dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10516  (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10517 
10518  for (i = 0; i < li_total_channels; i++)
10519  {
10520  li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10521  if (li_config_table[i].chflags != 0)
10522  li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10523  else
10524  {
10525  for (j = 0; j < li_total_channels; j++)
10526  {
10527  if (((li_config_table[i].flag_table[j]) != 0)
10528  || ((li_config_table[j].flag_table[i]) != 0))
10529  {
10530  li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10531  }
10532  if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10533  || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10534  {
10535  li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10536  }
10537  }
10538  }
10539  }
10540  for (i = 0; i < li_total_channels; i++)
10541  {
10542  for (j = 0; j < li_total_channels; j++)
10543  {
10544  li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10545  if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10546  li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10547  }
10548  }
10549  for (n = 0; n < li_total_channels; n++)
10550  {
10551  if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10552  {
10553  for (i = 0; i < li_total_channels; i++)
10554  {
10555  if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10556  {
10557  for (j = 0; j < li_total_channels; j++)
10558  {
10559  li_config_table[i].coef_table[j] |=
10560  li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10561  }
10562  }
10563  }
10564  }
10565  }
10566  for (i = 0; i < li_total_channels; i++)
10567  {
10568  if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10569  {
10570  li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10571  for (j = 0; j < li_total_channels; j++)
10572  {
10573  if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10574  li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10575  }
10576  if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10577  li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10578  }
10579  }
10580  for (i = 0; i < li_total_channels; i++)
10581  {
10582  if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10583  {
10584  for (j = 0; j < li_total_channels; j++)
10585  {
10586  if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587  li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10588  if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10589  li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590  if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10591  li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10592  if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10593  li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10594  }
10595  if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10596  {
10597  for (j = 0; j < li_total_channels; j++)
10598  {
10599  if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10600  {
10601  li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10602  if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10603  li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604  }
10605  }
10606  }
10607  if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10608  {
10609  for (j = 0; j < li_total_channels; j++)
10610  {
10611  if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10612  li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10613  }
10614  }
10615  if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10616  {
10617  for (j = 0; j < li_total_channels; j++)
10618  {
10619  if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10620  {
10621  for (n = 0; n < li_total_channels; n++)
10622  {
10623  if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10624  {
10625  li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10626  if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10627  {
10628  li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10629  if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630  li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10631  }
10632  else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10633  li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10634  }
10635  }
10636  }
10637  }
10638  }
10639  }
10640  }
10641  for (i = 0; i < li_total_channels; i++)
10642  {
10643  if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10644  {
10645  if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10646  li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647  if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10648  li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649  if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10650  li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651  for (j = 0; j < li_total_channels; j++)
10652  {
10653  if ((li_config_table[i].flag_table[j] &
10655  || (li_config_table[j].flag_table[i] &
10657  {
10658  li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10659  }
10660  if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10661  li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10662  if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10663  li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10664  }
10665  if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10666  {
10667  li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10668  li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669  }
10670  }
10671  }
10672  for (i = 0; i < li_total_channels; i++)
10673  {
10674  if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10675  {
10676  j = 0;
10677  while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10678  j++;
10679  if (j < li_total_channels)
10680  {
10681  for (j = 0; j < li_total_channels; j++)
10682  {
10683  li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10684  if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10685  li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10686  }
10687  }
10688  }
10689  }
10690  n = li_total_channels;
10691  if (n > MIXER_MAX_DUMP_CHANNELS)
10693  p = hex_line;
10694  for (j = 0; j < n; j++)
10695  {
10696  if ((j & 0x7) == 0)
10697  *(p++) = ' ';
10698  *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10699  *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10700  }
10701  *p = '\0';
10702  dbug(1, dprintf("[%06lx] CURRENT %s",
10703  (dword)(UnMapController(a->Id)), (char *)hex_line));
10704  p = hex_line;
10705  for (j = 0; j < n; j++)
10706  {
10707  if ((j & 0x7) == 0)
10708  *(p++) = ' ';
10709  *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10710  *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10711  }
10712  *p = '\0';
10713  dbug(1, dprintf("[%06lx] CHANNEL %s",
10714  (dword)(UnMapController(a->Id)), (char *)hex_line));
10715  p = hex_line;
10716  for (j = 0; j < n; j++)
10717  {
10718  if ((j & 0x7) == 0)
10719  *(p++) = ' ';
10720  *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10721  *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10722  }
10723  *p = '\0';
10724  dbug(1, dprintf("[%06lx] CHFLAG %s",
10725  (dword)(UnMapController(a->Id)), (char *)hex_line));
10726  for (i = 0; i < n; i++)
10727  {
10728  p = hex_line;
10729  for (j = 0; j < n; j++)
10730  {
10731  if ((j & 0x7) == 0)
10732  *(p++) = ' ';
10733  *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10734  *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10735  }
10736  *p = '\0';
10737  dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10738  (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10739  }
10740  for (i = 0; i < n; i++)
10741  {
10742  p = hex_line;
10743  for (j = 0; j < n; j++)
10744  {
10745  if ((j & 0x7) == 0)
10746  *(p++) = ' ';
10747  *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10748  *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10749  }
10750  *p = '\0';
10751  dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10752  (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10753  }
10754 }
10755 
10756 
10757 static struct
10758 {
10761 } mixer_write_prog_pri[] =
10762 {
10763  { LI_COEF_CH_CH, 0 },
10767 };
10768 
10769 static struct
10770 {
10773  byte mask;
10775 } mixer_write_prog_bri[] =
10776 {
10777  { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10778  { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10779  { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10780  { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10781  { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10782  { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10783  { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10784  { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10785  { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10786  { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10787  { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10788  { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10789  { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10790  { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10791  { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10792  { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10793  { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10794  { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10795  { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10796  { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10797  { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10798  { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10799  { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10800  { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10801  { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10802  { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10803  { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10804  { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10805  { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10806  { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10807  { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10808  { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10809  { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10810  { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10811  { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10812  { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10813 };
10814 
10815 static byte mixer_swapped_index_bri[] =
10816 {
10817  18, /* B to B */
10818  19, /* Alt B to B */
10819  20, /* PC to B */
10820  21, /* Alt PC to B */
10821  22, /* IC to B */
10822  23, /* Alt IC to B */
10823  24, /* B to PC */
10824  25, /* Alt B to PC */
10825  26, /* PC to PC */
10826  27, /* Alt PC to PC */
10827  28, /* IC to PC */
10828  29, /* Alt IC to PC */
10829  30, /* B to IC */
10830  31, /* Alt B to IC */
10831  32, /* PC to IC */
10832  33, /* Alt PC to IC */
10833  34, /* IC to IC */
10834  35, /* Alt IC to IC */
10835  0, /* Alt B to Alt B */
10836  1, /* B to Alt B */
10837  2, /* Alt PC to Alt B */
10838  3, /* PC to Alt B */
10839  4, /* Alt IC to Alt B */
10840  5, /* IC to Alt B */
10841  6, /* Alt B to Alt PC */
10842  7, /* B to Alt PC */
10843  8, /* Alt PC to Alt PC */
10844  9, /* PC to Alt PC */
10845  10, /* Alt IC to Alt PC */
10846  11, /* IC to Alt PC */
10847  12, /* Alt B to Alt IC */
10848  13, /* B to Alt IC */
10849  14, /* Alt PC to Alt IC */
10850  15, /* PC to Alt IC */
10851  16, /* Alt IC to Alt IC */
10852  17 /* IC to Alt IC */
10853 };
10854 
10855 static struct
10856 {
10857  byte mask;
10860 } xconnect_write_prog[] =
10861 {
10862  { LI_COEF_CH_CH, false, false },
10863  { LI_COEF_CH_PC, false, true },
10864  { LI_COEF_PC_CH, true, false },
10865  { LI_COEF_PC_PC, true, true }
10866 };
10867 
10868 
10869 static void xconnect_query_addresses(PLCI *plci)
10870 {
10872  word w, ch;
10873  byte *p;
10874 
10875  dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10876  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10877  (char *)(FILE_), __LINE__));
10878 
10879  a = plci->adapter;
10880  if (a->li_pri && ((plci->li_bchannel_id == 0)
10881  || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10882  {
10883  dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10884  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10885  (char *)(FILE_), __LINE__));
10886  return;
10887  }
10888  p = plci->internal_req_buffer;
10889  ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10890  *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10891  w = ch;
10892  *(p++) = (byte) w;
10893  *(p++) = (byte)(w >> 8);
10894  w = ch | XCONNECT_CHANNEL_PORT_PC;
10895  *(p++) = (byte) w;
10896  *(p++) = (byte)(w >> 8);
10897  plci->NData[0].P = plci->internal_req_buffer;
10898  plci->NData[0].PLength = p - plci->internal_req_buffer;
10899  plci->NL.X = plci->NData;
10900  plci->NL.ReqCh = 0;
10901  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10902  plci->adapter->request(&plci->NL);
10903 }
10904 
10905 
10906 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10907 {
10908 
10909  dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10910  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10911  (char *)(FILE_), __LINE__, internal_command));
10912 
10913  plci->li_write_command = internal_command;
10914  plci->li_write_channel = 0;
10915 }
10916 
10917 
10918 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10919 {
10921  word w, n, i, j, r, s, to_ch;
10922  dword d;
10923  byte *p;
10924  struct xconnect_transfer_address_s *transfer_address;
10925  byte ch_map[MIXER_CHANNELS_BRI];
10926 
10927  dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10928  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10929 
10930  a = plci->adapter;
10931  if ((plci->li_bchannel_id == 0)
10932  || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10933  {
10934  dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10935  UnMapId(Id), (char *)(FILE_), __LINE__));
10936  return (true);
10937  }
10938  i = a->li_base + (plci->li_bchannel_id - 1);
10939  j = plci->li_write_channel;
10940  p = plci->internal_req_buffer;
10941  if (j != 0)
10942  {
10943  if ((Rc != OK) && (Rc != OK_FC))
10944  {
10945  dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10946  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10947  return (false);
10948  }
10949  }
10950  if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10951  {
10952  r = 0;
10953  s = 0;
10954  if (j < li_total_channels)
10955  {
10956  if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10957  {
10958  s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10960  ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10962  }
10963  r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964  while ((j < li_total_channels)
10965  && ((r == 0)
10966  || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10967  || (!li_config_table[j].adapter->li_pri
10968  && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10969  || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10970  || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10972  || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10973  || ((li_config_table[j].adapter->li_base != a->li_base)
10974  && !(r & s &
10975  ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10977  ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10979  {
10980  j++;
10981  if (j < li_total_channels)
10982  r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10983  }
10984  }
10985  if (j < li_total_channels)
10986  {
10987  plci->internal_command = plci->li_write_command;
10988  if (plci_nl_busy(plci))
10989  return (true);
10990  to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10991  *(p++) = UDATA_REQUEST_XCONNECT_TO;
10992  do
10993  {
10994  if (li_config_table[j].adapter->li_base != a->li_base)
10995  {
10996  r &= s &
10997  ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10999  ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11001  }
11002  n = 0;
11003  do
11004  {
11005  if (r & xconnect_write_prog[n].mask)
11006  {
11007  if (xconnect_write_prog[n].from_pc)
11008  transfer_address = &(li_config_table[j].send_pc);
11009  else
11010  transfer_address = &(li_config_table[j].send_b);
11011  d = transfer_address->card_address.low;
11012  *(p++) = (byte) d;
11013  *(p++) = (byte)(d >> 8);
11014  *(p++) = (byte)(d >> 16);
11015  *(p++) = (byte)(d >> 24);
11016  d = transfer_address->card_address.high;
11017  *(p++) = (byte) d;
11018  *(p++) = (byte)(d >> 8);
11019  *(p++) = (byte)(d >> 16);
11020  *(p++) = (byte)(d >> 24);
11021  d = transfer_address->offset;
11022  *(p++) = (byte) d;
11023  *(p++) = (byte)(d >> 8);
11024  *(p++) = (byte)(d >> 16);
11025  *(p++) = (byte)(d >> 24);
11026  w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11027  *(p++) = (byte) w;
11028  *(p++) = (byte)(w >> 8);
11029  w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11030  (li_config_table[i].adapter->u_law ?
11031  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11032  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11033  *(p++) = (byte) w;
11034  *(p++) = (byte) 0;
11035  li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11036  }
11037  n++;
11038  } while ((n < ARRAY_SIZE(xconnect_write_prog))
11039  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11040  if (n == ARRAY_SIZE(xconnect_write_prog))
11041  {
11042  do
11043  {
11044  j++;
11045  if (j < li_total_channels)
11046  r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11047  } while ((j < li_total_channels)
11048  && ((r == 0)
11049  || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11050  || (!li_config_table[j].adapter->li_pri
11051  && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11052  || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11053  || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11055  || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11056  || ((li_config_table[j].adapter->li_base != a->li_base)
11057  && !(r & s &
11058  ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11060  ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11062  }
11063  } while ((j < li_total_channels)
11064  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11065  }
11066  else if (j == li_total_channels)
11067  {
11068  plci->internal_command = plci->li_write_command;
11069  if (plci_nl_busy(plci))
11070  return (true);
11071  if (a->li_pri)
11072  {
11074  w = 0;
11075  if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11077  if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11079  *(p++) = (byte) w;
11080  *(p++) = (byte)(w >> 8);
11081  }
11082  else
11083  {
11085  w = 0;
11086  if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11087  && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11088  {
11090  }
11091  if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11093  if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11095  *(p++) = (byte) w;
11096  *(p++) = (byte)(w >> 8);
11097  for (j = 0; j < sizeof(ch_map); j += 2)
11098  {
11099  if (plci->li_bchannel_id == 2)
11100  {
11101  ch_map[j] = (byte)(j + 1);
11102  ch_map[j + 1] = (byte) j;
11103  }
11104  else
11105  {
11106  ch_map[j] = (byte) j;
11107  ch_map[j + 1] = (byte)(j + 1);
11108  }
11109  }
11110  for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11111  {
11112  i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11113  j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11114  if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11115  {
11116  *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11117  mixer_write_prog_bri[n].xconnect_override :
11118  ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11119  if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11120  {
11121  w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11122  li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11123  }
11124  }
11125  else
11126  {
11127  *p = 0x00;
11128  if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11129  {
11130  w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11131  if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11132  *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11133  }
11134  }
11135  p++;
11136  }
11137  }
11138  j = li_total_channels + 1;
11139  }
11140  }
11141  else
11142  {
11143  if (j <= li_total_channels)
11144  {
11145  plci->internal_command = plci->li_write_command;
11146  if (plci_nl_busy(plci))
11147  return (true);
11148  if (j < a->li_base)
11149  j = a->li_base;
11150  if (a->li_pri)
11151  {
11153  w = 0;
11154  if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11156  if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11158  *(p++) = (byte) w;
11159  *(p++) = (byte)(w >> 8);
11160  for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11161  {
11162  *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11163  for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11164  {
11165  w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11166  if (w & mixer_write_prog_pri[n].mask)
11167  {
11168  *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169  li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11170  }
11171  else
11172  *(p++) = 0x00;
11173  }
11174  *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11175  for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11176  {
11177  w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11178  if (w & mixer_write_prog_pri[n].mask)
11179  {
11180  *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11181  li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11182  }
11183  else
11184  *(p++) = 0x00;
11185  }
11186  }
11187  }
11188  else
11189  {
11191  w = 0;
11192  if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11193  && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11194  {
11196  }
11197  if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11199  if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11201  *(p++) = (byte) w;
11202  *(p++) = (byte)(w >> 8);
11203  for (j = 0; j < sizeof(ch_map); j += 2)
11204  {
11205  if (plci->li_bchannel_id == 2)
11206  {
11207  ch_map[j] = (byte)(j + 1);
11208  ch_map[j + 1] = (byte) j;
11209  }
11210  else
11211  {
11212  ch_map[j] = (byte) j;
11213  ch_map[j + 1] = (byte)(j + 1);
11214  }
11215  }
11216  for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11217  {
11218  i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11219  j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11220  if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11221  {
11222  *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11223  w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11224  li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11225  }
11226  else
11227  {
11228  *p = 0x00;
11229  if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11230  {
11231  w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11232  if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11233  *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11234  }
11235  }
11236  p++;
11237  }
11238  }
11239  j = li_total_channels + 1;
11240  }
11241  }
11242  plci->li_write_channel = j;
11243  if (p != plci->internal_req_buffer)
11244  {
11245  plci->NData[0].P = plci->internal_req_buffer;
11246  plci->NData[0].PLength = p - plci->internal_req_buffer;
11247  plci->NL.X = plci->NData;
11248  plci->NL.ReqCh = 0;
11249  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11250  plci->adapter->request(&plci->NL);
11251  }
11252  return (true);
11253 }
11254 
11255 
11256 static void mixer_notify_update(PLCI *plci, byte others)
11257 {
11259  word i, w;
11260  PLCI *notify_plci;
11261  byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11262 
11263  dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11264  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11265  (char *)(FILE_), __LINE__, others));
11266 
11267  a = plci->adapter;
11269  {
11270  if (others)
11271  plci->li_notify_update = true;
11272  i = 0;
11273  do
11274  {
11275  notify_plci = NULL;
11276  if (others)
11277  {
11278  while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11279  i++;
11280  if (i < li_total_channels)
11281  notify_plci = li_config_table[i++].plci;
11282  }
11283  else
11284  {
11285  if ((plci->li_bchannel_id != 0)
11286  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11287  {
11288  notify_plci = plci;
11289  }
11290  }
11291  if ((notify_plci != NULL)
11292  && !notify_plci->li_notify_update
11293  && (notify_plci->appl != NULL)
11294  && (notify_plci->State)
11295  && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11296  {
11297  notify_plci->li_notify_update = true;
11298  ((CAPI_MSG *) msg)->header.length = 18;
11299  ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11300  ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11301  ((CAPI_MSG *) msg)->header.number = 0;
11302  ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11303  ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11304  ((CAPI_MSG *) msg)->header.ncci = 0;
11305  ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11306  ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11307  PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11308  ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11309  w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11310  if (w != _QUEUE_FULL)
11311  {
11312  if (w != 0)
11313  {
11314  dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11315  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11316  (char *)(FILE_), __LINE__,
11317  (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11318  }
11319  notify_plci->li_notify_update = false;
11320  }
11321  }
11322  } while (others && (notify_plci != NULL));
11323  if (others)
11324  plci->li_notify_update = false;
11325  }
11326 }
11327 
11328 
11329 static void mixer_clear_config(PLCI *plci)
11330 {
11332  word i, j;
11333 
11334  dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11335  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11336  (char *)(FILE_), __LINE__));
11337 
11338  plci->li_notify_update = false;
11339  plci->li_plci_b_write_pos = 0;
11340  plci->li_plci_b_read_pos = 0;
11341  plci->li_plci_b_req_pos = 0;
11342  a = plci->adapter;
11343  if ((plci->li_bchannel_id != 0)
11344  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11345  {
11346  i = a->li_base + (plci->li_bchannel_id - 1);
11347  li_config_table[i].curchnl = 0;
11348  li_config_table[i].channel = 0;
11349  li_config_table[i].chflags = 0;
11350  for (j = 0; j < li_total_channels; j++)
11351  {
11352  li_config_table[j].flag_table[i] = 0;
11353  li_config_table[i].flag_table[j] = 0;
11354  li_config_table[i].coef_table[j] = 0;
11355  li_config_table[j].coef_table[i] = 0;
11356  }
11357  if (!a->li_pri)
11358  {
11359  li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11360  if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11361  {
11362  i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11363  li_config_table[i].curchnl = 0;
11364  li_config_table[i].channel = 0;
11365  li_config_table[i].chflags = 0;
11366  for (j = 0; j < li_total_channels; j++)
11367  {
11368  li_config_table[i].flag_table[j] = 0;
11369  li_config_table[j].flag_table[i] = 0;
11370  li_config_table[i].coef_table[j] = 0;
11371  li_config_table[j].coef_table[i] = 0;
11372  }
11374  {
11375  i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11376  li_config_table[i].curchnl = 0;
11377  li_config_table[i].channel = 0;
11378  li_config_table[i].chflags = 0;
11379  for (j = 0; j < li_total_channels; j++)
11380  {
11381  li_config_table[i].flag_table[j] = 0;
11382  li_config_table[j].flag_table[i] = 0;
11383  li_config_table[i].coef_table[j] = 0;
11384  li_config_table[j].coef_table[i] = 0;
11385  }
11386  }
11387  }
11388  }
11389  }
11390 }
11391 
11392 
11393 static void mixer_prepare_switch(dword Id, PLCI *plci)
11394 {
11395 
11396  dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11397  UnMapId(Id), (char *)(FILE_), __LINE__));
11398 
11399  do
11400  {
11401  mixer_indication_coefs_set(Id, plci);
11402  } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11403 }
11404 
11405 
11406 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11407 {
11409  word i, j;
11410 
11411  dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11412  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11413 
11414  a = plci->adapter;
11415  if ((plci->li_bchannel_id != 0)
11416  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11417  {
11418  i = a->li_base + (plci->li_bchannel_id - 1);
11419  for (j = 0; j < li_total_channels; j++)
11420  {
11421  li_config_table[i].coef_table[j] &= 0xf;
11422  li_config_table[j].coef_table[i] &= 0xf;
11423  }
11424  if (!a->li_pri)
11425  li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11426  }
11427  return (GOOD);
11428 }
11429 
11430 
11431 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11432 {
11434  word Info;
11435 
11436  dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11437  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11438 
11439  Info = GOOD;
11440  a = plci->adapter;
11441  if ((plci->B1_facilities & B1_FACILITY_MIXER)
11442  && (plci->li_bchannel_id != 0)
11443  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11444  {
11445  switch (plci->adjust_b_state)
11446  {
11448  if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11449  {
11450  plci->internal_command = plci->adjust_b_command;
11451  if (plci_nl_busy(plci))
11452  {
11454  break;
11455  }
11456  xconnect_query_addresses(plci);
11458  break;
11459  }
11461  Rc = OK;
11465  if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11466  {
11467  dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11468  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11469  Info = _WRONG_STATE;
11470  break;
11471  }
11472  if (Rc == OK)
11473  {
11476  else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11478  }
11479  else if (Rc == 0)
11480  {
11483  else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11485  }
11487  {
11488  plci->internal_command = plci->adjust_b_command;
11489  break;
11490  }
11492  xconnect_write_coefs(plci, plci->adjust_b_command);
11494  Rc = OK;
11496  if (!xconnect_write_coefs_process(Id, plci, Rc))
11497  {
11498  dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11499  UnMapId(Id), (char *)(FILE_), __LINE__));
11500  Info = _FACILITY_NOT_SUPPORTED;
11501  break;
11502  }
11503  if (plci->internal_command)
11504  break;
11507  break;
11508  }
11509  }
11510  return (Info);
11511 }
11512 
11513 
11514 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11515 {
11517  word i, internal_command;
11518 
11519  dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11520  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11521  plci->li_cmd));
11522 
11523  a = plci->adapter;
11524  internal_command = plci->internal_command;
11525  plci->internal_command = 0;
11526  switch (plci->li_cmd)
11527  {
11528  case LI_REQ_CONNECT:
11529  case LI_REQ_DISCONNECT:
11530  case LI_REQ_SILENT_UPDATE:
11531  switch (internal_command)
11532  {
11533  default:
11534  if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535  {
11536  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11538  }
11539  case MIXER_COMMAND_1:
11540  if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11541  {
11542  if (adjust_b_process(Id, plci, Rc) != GOOD)
11543  {
11544  dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11545  UnMapId(Id), (char *)(FILE_), __LINE__));
11546  break;
11547  }
11548  if (plci->internal_command)
11549  return;
11550  }
11551  plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11552  if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553  || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554  && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11555  ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556  {
11557  xconnect_write_coefs(plci, MIXER_COMMAND_2);
11558  }
11559  else
11560  {
11561  do
11562  {
11563  mixer_indication_coefs_set(Id, plci);
11564  } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11565  }
11566  case MIXER_COMMAND_2:
11567  if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11568  || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11569  && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11570  ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11571  {
11572  if (!xconnect_write_coefs_process(Id, plci, Rc))
11573  {
11574  dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11575  UnMapId(Id), (char *)(FILE_), __LINE__));
11576  if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11577  {
11578  do
11579  {
11580  plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11582  i = (plci->li_plci_b_write_pos == 0) ?
11584  } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11585  && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11586  }
11587  break;
11588  }
11589  if (plci->internal_command)
11590  return;
11591  }
11592  if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593  {
11594  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11596  }
11597  case MIXER_COMMAND_3:
11598  if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11599  {
11600  if (adjust_b_process(Id, plci, Rc) != GOOD)
11601  {
11602  dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11603  UnMapId(Id), (char *)(FILE_), __LINE__));
11604  break;
11605  }
11606  if (plci->internal_command)
11607  return;
11608  }
11609  break;
11610  }
11611  break;
11612  }
11613  if ((plci->li_bchannel_id == 0)
11614  || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11615  {
11616  dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11617  UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11618  }
11619  else
11620  {
11621  i = a->li_base + (plci->li_bchannel_id - 1);
11622  li_config_table[i].curchnl = plci->li_channel_bits;
11623  if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11624  {
11625  i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11626  li_config_table[i].curchnl = plci->li_channel_bits;
11628  {
11629  i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11630  li_config_table[i].curchnl = plci->li_channel_bits;
11631  }
11632  }
11633  }
11634 }
11635 
11636 
11637 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11638  dword plci_b_id, byte connect, dword li_flags)
11639 {
11640  word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11641  PLCI *plci_b;
11642  DIVA_CAPI_ADAPTER *a_b;
11643 
11644  a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11645  plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11646  ch_a = a->li_base + (plci->li_bchannel_id - 1);
11647  if (!a->li_pri && (plci->tel == ADV_VOICE)
11648  && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11649  {
11650  ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11652  a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11653  }
11654  else
11655  {
11656  ch_a_v = ch_a;
11657  ch_a_s = ch_a;
11658  }
11659  ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11660  if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11661  && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11662  {
11663  ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11665  a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11666  }
11667  else
11668  {
11669  ch_b_v = ch_b;
11670  ch_b_s = ch_b;
11671  }
11672  if (connect)
11673  {
11674  li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11675  li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11676  li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677  li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678  }
11679  li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11680  li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11681  li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11682  li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683  if (ch_a_v == ch_b_v)
11684  {
11685  li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11686  li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11687  }
11688  else
11689  {
11690  if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11691  {
11692  for (i = 0; i < li_total_channels; i++)
11693  {
11694  if (i != ch_a_v)
11695  li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11696  }
11697  }
11698  if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11699  {
11700  for (i = 0; i < li_total_channels; i++)
11701  {
11702  if (i != ch_a_s)
11703  li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11704  }
11705  }
11706  if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11707  {
11708  for (i = 0; i < li_total_channels; i++)
11709  {
11710  if (i != ch_a_v)
11711  li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11712  }
11713  }
11714  if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11715  {
11716  for (i = 0; i < li_total_channels; i++)
11717  {
11718  if (i != ch_a_s)
11719  li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11720  }
11721  }
11722  }
11723  if (li_flags & LI_FLAG_CONFERENCE_A_B)
11724  {
11725  li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11726  li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727  li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11728  li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729  }
11730  if (li_flags & LI_FLAG_CONFERENCE_B_A)
11731  {
11732  li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11733  li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11734  li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11735  li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11736  }
11737  if (li_flags & LI_FLAG_MONITOR_A)
11738  {
11739  li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11740  li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11741  }
11742  if (li_flags & LI_FLAG_MONITOR_B)
11743  {
11744  li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11745  li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11746  }
11747  if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11748  {
11749  li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750  li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751  }
11752  if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11753  {
11754  li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11755  li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756  }
11757  if (li_flags & LI_FLAG_MIX_A)
11758  {
11759  li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11760  li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11761  }
11762  if (li_flags & LI_FLAG_MIX_B)
11763  {
11764  li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11765  li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11766  }
11767  if (ch_a_v != ch_a_s)
11768  {
11769  li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11770  li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11771  }
11772  if (ch_b_v != ch_b_s)
11773  {
11774  li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11775  li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11776  }
11777 }
11778 
11779 
11780 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11781  dword plci_b_id, byte connect, dword li_flags)
11782 {
11783  word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11784  PLCI *plci_b;
11785  DIVA_CAPI_ADAPTER *a_b;
11786 
11787  a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11788  plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11789  ch_a = a->li_base + (plci->li_bchannel_id - 1);
11790  if (!a->li_pri && (plci->tel == ADV_VOICE)
11791  && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11792  {
11793  ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11795  a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11796  }
11797  else
11798  {
11799  ch_a_v = ch_a;
11800  ch_a_s = ch_a;
11801  }
11802  ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11803  if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11804  && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11805  {
11806  ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11808  a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11809  }
11810  else
11811  {
11812  ch_b_v = ch_b;
11813  ch_b_s = ch_b;
11814  }
11815  if (connect)
11816  {
11817  li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11818  li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11819  li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11820  li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821  li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11822  li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11823  }
11824  li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825  li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826  li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827  li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828  li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829  li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830  li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831  li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832  if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11833  {
11834  li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11835  li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836  li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11837  li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838  }
11839  if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11840  {
11841  li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11842  li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11843  li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11844  li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11845  }
11846  if (li_flags & LI2_FLAG_MONITOR_B)
11847  {
11848  li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11849  li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11850  }
11851  if (li_flags & LI2_FLAG_MIX_B)
11852  {
11853  li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11854  li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11855  }
11856  if (li_flags & LI2_FLAG_MONITOR_X)
11857  li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11858  if (li_flags & LI2_FLAG_MIX_X)
11859  li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11860  if (li_flags & LI2_FLAG_LOOP_B)
11861  {
11862  li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11863  li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864  li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11865  li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866  }
11867  if (li_flags & LI2_FLAG_LOOP_PC)
11868  li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11869  if (li_flags & LI2_FLAG_LOOP_X)
11870  li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11871  if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11872  li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11873  if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11874  li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11875  if (ch_a_v != ch_a_s)
11876  {
11877  li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11878  li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11879  }
11880  if (ch_b_v != ch_b_s)
11881  {
11882  li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11883  li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11884  }
11885 }
11886 
11887 
11888 static word li_check_main_plci(dword Id, PLCI *plci)
11889 {
11890  if (plci == NULL)
11891  {
11892  dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11893  UnMapId(Id), (char *)(FILE_), __LINE__));
11894  return (_WRONG_IDENTIFIER);
11895  }
11896  if (!plci->State
11897  || !plci->NL.Id || plci->nl_remove_id
11898  || (plci->li_bchannel_id == 0))
11899  {
11900  dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11901  UnMapId(Id), (char *)(FILE_), __LINE__));
11902  return (_WRONG_STATE);
11903  }
11904  li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11905  return (GOOD);
11906 }
11907 
11908 
11909 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11910  dword plci_b_id, word plci_b_write_pos, byte *p_result)
11911 {
11912  byte ctlr_b;
11913  PLCI *plci_b;
11914 
11915  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11916  LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11917  {
11918  dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11919  UnMapId(Id), (char *)(FILE_), __LINE__));
11920  PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11921  return (NULL);
11922  }
11923  ctlr_b = 0;
11924  if ((plci_b_id & 0x7f) != 0)
11925  {
11926  ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11927  if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11928  ctlr_b = 0;
11929  }
11930  if ((ctlr_b == 0)
11931  || (((plci_b_id >> 8) & 0xff) == 0)
11932  || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11933  {
11934  dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11935  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11936  PUT_WORD(p_result, _WRONG_IDENTIFIER);
11937  return (NULL);
11938  }
11939  plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11940  if (!plci_b->State
11941  || !plci_b->NL.Id || plci_b->nl_remove_id
11942  || (plci_b->li_bchannel_id == 0))
11943  {
11944  dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11945  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11946  PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11947  return (NULL);
11948  }
11949  li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11950  if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11951  ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11953  || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11954  {
11955  dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11956  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11957  PUT_WORD(p_result, _WRONG_IDENTIFIER);
11958  return (NULL);
11959  }
11960  if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11962  {
11963  dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11964  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11965  PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11966  return (NULL);
11967  }
11968  return (plci_b);
11969 }
11970 
11971 
11972 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11973  dword plci_b_id, word plci_b_write_pos, byte *p_result)
11974 {
11975  byte ctlr_b;
11976  PLCI *plci_b;
11977 
11978  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11979  LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11980  {
11981  dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11982  UnMapId(Id), (char *)(FILE_), __LINE__));
11983  PUT_WORD(p_result, _WRONG_STATE);
11984  return (NULL);
11985  }
11986  ctlr_b = 0;
11987  if ((plci_b_id & 0x7f) != 0)
11988  {
11989  ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11990  if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11991  ctlr_b = 0;
11992  }
11993  if ((ctlr_b == 0)
11994  || (((plci_b_id >> 8) & 0xff) == 0)
11995  || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11996  {
11997  dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11998  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11999  PUT_WORD(p_result, _WRONG_IDENTIFIER);
12000  return (NULL);
12001  }
12002  plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12003  if (!plci_b->State
12004  || !plci_b->NL.Id || plci_b->nl_remove_id
12005  || (plci_b->li_bchannel_id == 0)
12006  || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12007  {
12008  dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12009  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12010  PUT_WORD(p_result, _WRONG_STATE);
12011  return (NULL);
12012  }
12013  if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12014  ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12015  && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12016  || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12017  {
12018  dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12019  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12020  PUT_WORD(p_result, _WRONG_IDENTIFIER);
12021  return (NULL);
12022  }
12023  if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12024  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12025  {
12026  dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12027  UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12028  PUT_WORD(p_result, _WRONG_STATE);
12029  return (NULL);
12030  }
12031  return (plci_b);
12032 }
12033 
12034 
12035 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12036 {
12037  word Info;
12038  word i;
12039  dword d, li_flags, plci_b_id;
12040  PLCI *plci_b;
12041  API_PARSE li_parms[3];
12042  API_PARSE li_req_parms[3];
12043  API_PARSE li_participant_struct[2];
12044  API_PARSE li_participant_parms[3];
12045  word participant_parms_pos;
12046  byte result_buffer[32];
12047  byte *result;
12048  word result_pos;
12049  word plci_b_write_pos;
12050 
12051  dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12052  UnMapId(Id), (char *)(FILE_), __LINE__));
12053 
12054  Info = GOOD;
12055  result = result_buffer;
12056  result_buffer[0] = 0;
12058  {
12059  dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12060  UnMapId(Id), (char *)(FILE_), __LINE__));
12061  Info = _FACILITY_NOT_SUPPORTED;
12062  }
12063  else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12064  {
12065  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12066  UnMapId(Id), (char *)(FILE_), __LINE__));
12067  Info = _WRONG_MESSAGE_FORMAT;
12068  }
12069  else
12070  {
12071  result_buffer[0] = 3;
12072  PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12073  result_buffer[3] = 0;
12074  switch (GET_WORD(li_parms[0].info))
12075  {
12077  if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12078  {
12079  result_buffer[0] = 17;
12080  result_buffer[3] = 14;
12081  PUT_WORD(&result_buffer[4], GOOD);
12082  d = 0;
12089  if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091  PUT_DWORD(&result_buffer[6], d);
12092  if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12093  {
12094  d = 0;
12095  for (i = 0; i < li_total_channels; i++)
12096  {
12097  if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12098  && (li_config_table[i].adapter->li_pri
12099  || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12100  {
12101  d++;
12102  }
12103  }
12104  }
12105  else
12106  {
12107  d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12108  }
12109  PUT_DWORD(&result_buffer[10], d / 2);
12110  PUT_DWORD(&result_buffer[14], d);
12111  }
12112  else
12113  {
12114  result_buffer[0] = 25;
12115  result_buffer[3] = 22;
12116  PUT_WORD(&result_buffer[4], GOOD);
12124  if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12126  PUT_DWORD(&result_buffer[6], d);
12127  d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12128  PUT_DWORD(&result_buffer[10], d / 2);
12129  PUT_DWORD(&result_buffer[14], d - 1);
12130  if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12131  {
12132  d = 0;
12133  for (i = 0; i < li_total_channels; i++)
12134  {
12135  if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12136  && (li_config_table[i].adapter->li_pri
12137  || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12138  {
12139  d++;
12140  }
12141  }
12142  }
12143  PUT_DWORD(&result_buffer[18], d / 2);
12144  PUT_DWORD(&result_buffer[22], d - 1);
12145  }
12146  break;
12147 
12148  case LI_REQ_CONNECT:
12149  if (li_parms[1].length == 8)
12150  {
12152  if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12153  {
12154  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12155  UnMapId(Id), (char *)(FILE_), __LINE__));
12156  Info = _WRONG_MESSAGE_FORMAT;
12157  break;
12158  }
12159  plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12160  li_flags = GET_DWORD(li_req_parms[1].info);
12161  Info = li_check_main_plci(Id, plci);
12162  result_buffer[0] = 9;
12163  result_buffer[3] = 6;
12164  PUT_DWORD(&result_buffer[4], plci_b_id);
12165  PUT_WORD(&result_buffer[8], GOOD);
12166  if (Info != GOOD)
12167  break;
12168  result = plci->saved_msg.info;
12169  for (i = 0; i <= result_buffer[0]; i++)
12170  result[i] = result_buffer[i];
12171  plci_b_write_pos = plci->li_plci_b_write_pos;
12172  plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12173  if (plci_b == NULL)
12174  break;
12175  li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12176  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12177  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12178  plci->li_plci_b_write_pos = plci_b_write_pos;
12179  }
12180  else
12181  {
12183  if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12184  {
12185  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12186  UnMapId(Id), (char *)(FILE_), __LINE__));
12187  Info = _WRONG_MESSAGE_FORMAT;
12188  break;
12189  }
12190  li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12191  Info = li_check_main_plci(Id, plci);
12192  result_buffer[0] = 7;
12193  result_buffer[3] = 4;
12194  PUT_WORD(&result_buffer[4], Info);
12195  result_buffer[6] = 0;
12196  if (Info != GOOD)
12197  break;
12198  result = plci->saved_msg.info;
12199  for (i = 0; i <= result_buffer[0]; i++)
12200  result[i] = result_buffer[i];
12201  plci_b_write_pos = plci->li_plci_b_write_pos;
12202  participant_parms_pos = 0;
12203  result_pos = 7;
12204  li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12205  while (participant_parms_pos < li_req_parms[1].length)
12206  {
12207  result[result_pos] = 6;
12208  result_pos += 7;
12209  PUT_DWORD(&result[result_pos - 6], 0);
12210  PUT_WORD(&result[result_pos - 2], GOOD);
12211  if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12212  (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12213  {
12214  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12215  UnMapId(Id), (char *)(FILE_), __LINE__));
12216  PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12217  break;
12218  }
12219  if (api_parse(&li_participant_struct[0].info[1],
12220  li_participant_struct[0].length, "dd", li_participant_parms))
12221  {
12222  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12223  UnMapId(Id), (char *)(FILE_), __LINE__));
12224  PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12225  break;
12226  }
12227  plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12228  li_flags = GET_DWORD(li_participant_parms[1].info);
12229  PUT_DWORD(&result[result_pos - 6], plci_b_id);
12230  if (sizeof(result) - result_pos < 7)
12231  {
12232  dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12233  UnMapId(Id), (char *)(FILE_), __LINE__));
12234  PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12235  break;
12236  }
12237  plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12238  if (plci_b != NULL)
12239  {
12240  li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12241  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12242  ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12243  LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12244  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12245  }
12246  participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12247  (&li_req_parms[1].info[1]));
12248  }
12249  result[0] = (byte)(result_pos - 1);
12250  result[3] = (byte)(result_pos - 4);
12251  result[6] = (byte)(result_pos - 7);
12252  i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12253  if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12254  || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12255  {
12256  plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12257  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12258  }
12259  else
12261  plci->li_plci_b_write_pos = plci_b_write_pos;
12262  }
12263  mixer_calculate_coefs(a);
12264  plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12265  mixer_notify_update(plci, true);
12266  sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12267  "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12268  plci->command = 0;
12269  plci->li_cmd = GET_WORD(li_parms[0].info);
12270  start_internal_command(Id, plci, mixer_command);
12271  return (false);
12272 
12273  case LI_REQ_DISCONNECT:
12274  if (li_parms[1].length == 4)
12275  {
12277  if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12278  {
12279  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12280  UnMapId(Id), (char *)(FILE_), __LINE__));
12281  Info = _WRONG_MESSAGE_FORMAT;
12282  break;
12283  }
12284  plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12285  Info = li_check_main_plci(Id, plci);
12286  result_buffer[0] = 9;
12287  result_buffer[3] = 6;
12288  PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12289  PUT_WORD(&result_buffer[8], GOOD);
12290  if (Info != GOOD)
12291  break;
12292  result = plci->saved_msg.info;
12293  for (i = 0; i <= result_buffer[0]; i++)
12294  result[i] = result_buffer[i];
12295  plci_b_write_pos = plci->li_plci_b_write_pos;
12296  plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12297  if (plci_b == NULL)
12298  break;
12299  li_update_connect(Id, a, plci, plci_b_id, false, 0);
12300  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12301  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12302  plci->li_plci_b_write_pos = plci_b_write_pos;
12303  }
12304  else
12305  {
12307  if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12308  {
12309  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12310  UnMapId(Id), (char *)(FILE_), __LINE__));
12311  Info = _WRONG_MESSAGE_FORMAT;
12312  break;
12313  }
12314  Info = li_check_main_plci(Id, plci);
12315  result_buffer[0] = 7;
12316  result_buffer[3] = 4;
12317  PUT_WORD(&result_buffer[4], Info);
12318  result_buffer[6] = 0;
12319  if (Info != GOOD)
12320  break;
12321  result = plci->saved_msg.info;
12322  for (i = 0; i <= result_buffer[0]; i++)
12323  result[i] = result_buffer[i];
12324  plci_b_write_pos = plci->li_plci_b_write_pos;
12325  participant_parms_pos = 0;
12326  result_pos = 7;
12327  while (participant_parms_pos < li_req_parms[0].length)
12328  {
12329  result[result_pos] = 6;
12330  result_pos += 7;
12331  PUT_DWORD(&result[result_pos - 6], 0);
12332  PUT_WORD(&result[result_pos - 2], GOOD);
12333  if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12334  (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12335  {
12336  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12337  UnMapId(Id), (char *)(FILE_), __LINE__));
12338  PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12339  break;
12340  }
12341  if (api_parse(&li_participant_struct[0].info[1],
12342  li_participant_struct[0].length, "d", li_participant_parms))
12343  {
12344  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12345  UnMapId(Id), (char *)(FILE_), __LINE__));
12346  PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12347  break;
12348  }
12349  plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12350  PUT_DWORD(&result[result_pos - 6], plci_b_id);
12351  if (sizeof(result) - result_pos < 7)
12352  {
12353  dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12354  UnMapId(Id), (char *)(FILE_), __LINE__));
12355  PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12356  break;
12357  }
12358  plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12359  if (plci_b != NULL)
12360  {
12361  li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12362  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12363  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12364  }
12365  participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12366  (&li_req_parms[0].info[1]));
12367  }
12368  result[0] = (byte)(result_pos - 1);
12369  result[3] = (byte)(result_pos - 4);
12370  result[6] = (byte)(result_pos - 7);
12371  i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12372  if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12373  || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12374  {
12375  plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12376  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12377  }
12378  else
12380  plci->li_plci_b_write_pos = plci_b_write_pos;
12381  }
12382  mixer_calculate_coefs(a);
12383  plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12384  mixer_notify_update(plci, true);
12385  sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12386  "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12387  plci->command = 0;
12388  plci->li_cmd = GET_WORD(li_parms[0].info);
12389  start_internal_command(Id, plci, mixer_command);
12390  return (false);
12391 
12392  case LI_REQ_SILENT_UPDATE:
12393  if (!plci || !plci->State
12394  || !plci->NL.Id || plci->nl_remove_id
12395  || (plci->li_bchannel_id == 0)
12396  || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12397  {
12398  dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12399  UnMapId(Id), (char *)(FILE_), __LINE__));
12400  return (false);
12401  }
12402  plci_b_write_pos = plci->li_plci_b_write_pos;
12403  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12404  LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12405  {
12406  dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12407  UnMapId(Id), (char *)(FILE_), __LINE__));
12408  return (false);
12409  }
12410  i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12411  if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12412  || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12413  {
12414  plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12415  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12416  }
12417  else
12419  plci->li_plci_b_write_pos = plci_b_write_pos;
12420  plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12421  plci->command = 0;
12422  plci->li_cmd = GET_WORD(li_parms[0].info);
12423  start_internal_command(Id, plci, mixer_command);
12424  return (false);
12425 
12426  default:
12427  dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12428  UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12429  Info = _FACILITY_NOT_SUPPORTED;
12430  }
12431  }
12432  sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12433  "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12434  return (false);
12435 }
12436 
12437 
12438 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12439 {
12440  dword d;
12441  byte result[12];
12442 
12443  dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12444  UnMapId(Id), (char *)(FILE_), __LINE__));
12445 
12446  if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12447  {
12448  do
12449  {
12450  d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12451  if (!(d & LI_PLCI_B_SKIP_FLAG))
12452  {
12453  if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12454  {
12455  if (d & LI_PLCI_B_DISC_FLAG)
12456  {
12457  result[0] = 5;
12458  PUT_WORD(&result[1], LI_IND_DISCONNECT);
12459  result[3] = 2;
12460  PUT_WORD(&result[4], _LI_USER_INITIATED);
12461  }
12462  else
12463  {
12464  result[0] = 7;
12465  PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12466  result[3] = 4;
12467  PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12468  }
12469  }
12470  else
12471  {
12472  if (d & LI_PLCI_B_DISC_FLAG)
12473  {
12474  result[0] = 9;
12475  PUT_WORD(&result[1], LI_IND_DISCONNECT);
12476  result[3] = 6;
12477  PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12478  PUT_WORD(&result[8], _LI_USER_INITIATED);
12479  }
12480  else
12481  {
12482  result[0] = 7;
12483  PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12484  result[3] = 4;
12485  PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12486  }
12487  }
12488  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12489  "ws", SELECTOR_LINE_INTERCONNECT, result);
12490  }
12492  0 : plci->li_plci_b_read_pos + 1;
12493  } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12494  }
12495 }
12496 
12497 
12498 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12499 {
12500  word i, j, ch;
12501  struct xconnect_transfer_address_s s, *p;
12503 
12504  dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12505  UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12506 
12507  a = plci->adapter;
12508  i = 1;
12509  for (i = 1; i < length; i += 16)
12510  {
12511  s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12512  s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12513  s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12514  ch = msg[i + 12] | (msg[i + 13] << 8);
12516  if (!a->li_pri && (plci->li_bchannel_id == 2))
12517  j = 1 - j;
12518  j += a->li_base;
12519  if (ch & XCONNECT_CHANNEL_PORT_PC)
12520  p = &(li_config_table[j].send_pc);
12521  else
12522  p = &(li_config_table[j].send_b);
12523  p->card_address.low = s.card_address.low;
12524  p->card_address.high = s.card_address.high;
12525  p->offset = s.offset;
12526  li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12527  }
12528  if (plci->internal_command_queue[0]
12532  {
12533  (*(plci->internal_command_queue[0]))(Id, plci, 0);
12534  if (!plci->internal_command)
12535  next_internal_command(Id, plci);
12536  }
12537  mixer_notify_update(plci, true);
12538 }
12539 
12540 
12541 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12542 {
12543 
12544  dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12545  UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12546 
12547 }
12548 
12549 
12550 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12551 {
12552  word plci_b_write_pos;
12553 
12554  plci_b_write_pos = plci->li_plci_b_write_pos;
12555  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12556  LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12557  {
12558  dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12559  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12560  (char *)(FILE_), __LINE__));
12561  return (false);
12562  }
12563  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12564  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12565  plci->li_plci_b_write_pos = plci_b_write_pos;
12566  return (true);
12567 }
12568 
12569 
12570 static void mixer_remove(PLCI *plci)
12571 {
12573  PLCI *notify_plci;
12574  dword plci_b_id;
12575  word i, j;
12576 
12577  dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12578  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12579  (char *)(FILE_), __LINE__));
12580 
12581  a = plci->adapter;
12582  plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12584  {
12585  if ((plci->li_bchannel_id != 0)
12586  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12587  {
12588  i = a->li_base + (plci->li_bchannel_id - 1);
12589  if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12590  {
12591  for (j = 0; j < li_total_channels; j++)
12592  {
12593  if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12594  || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12595  {
12596  notify_plci = li_config_table[j].plci;
12597  if ((notify_plci != NULL)
12598  && (notify_plci != plci)
12599  && (notify_plci->appl != NULL)
12600  && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12601  && (notify_plci->State)
12602  && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12603  {
12604  mixer_notify_source_removed(notify_plci, plci_b_id);
12605  }
12606  }
12607  }
12608  mixer_clear_config(plci);
12609  mixer_calculate_coefs(a);
12610  mixer_notify_update(plci, true);
12611  }
12612  li_config_table[i].plci = NULL;
12613  plci->li_bchannel_id = 0;
12614  }
12615  }
12616 }
12617 
12618 
12619 /*------------------------------------------------------------------*/
12620 /* Echo canceller facilities */
12621 /*------------------------------------------------------------------*/
12622 
12623 
12624 static void ec_write_parameters(PLCI *plci)
12625 {
12626  word w;
12627  byte parameter_buffer[6];
12628 
12629  dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12630  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12631  (char *)(FILE_), __LINE__));
12632 
12633  parameter_buffer[0] = 5;
12634  parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12635  PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12637  w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12638  PUT_WORD(&parameter_buffer[4], w);
12639  add_p(plci, FTY, parameter_buffer);
12640  sig_req(plci, TEL_CTRL, 0);
12641  send_req(plci);
12642 }
12643 
12644 
12645 static void ec_clear_config(PLCI *plci)
12646 {
12647 
12648  dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12649  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12650  (char *)(FILE_), __LINE__));
12651 
12654  plci->ec_tail_length = 0;
12655 }
12656 
12657 
12658 static void ec_prepare_switch(dword Id, PLCI *plci)
12659 {
12660 
12661  dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12662  UnMapId(Id), (char *)(FILE_), __LINE__));
12663 
12664 }
12665 
12666 
12667 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12668 {
12669 
12670  dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12671  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672 
12673  return (GOOD);
12674 }
12675 
12676 
12677 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12678 {
12679  word Info;
12680 
12681  dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12682  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12683 
12684  Info = GOOD;
12685  if (plci->B1_facilities & B1_FACILITY_EC)
12686  {
12687  switch (plci->adjust_b_state)
12688  {
12689  case ADJUST_B_RESTORE_EC_1:
12690  plci->internal_command = plci->adjust_b_command;
12691  if (plci->sig_req)
12692  {
12694  break;
12695  }
12696  ec_write_parameters(plci);
12698  break;
12699  case ADJUST_B_RESTORE_EC_2:
12700  if ((Rc != OK) && (Rc != OK_FC))
12701  {
12702  dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12703  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12704  Info = _WRONG_STATE;
12705  break;
12706  }
12707  break;
12708  }
12709  }
12710  return (Info);
12711 }
12712 
12713 
12714 static void ec_command(dword Id, PLCI *plci, byte Rc)
12715 {
12716  word internal_command, Info;
12717  byte result[8];
12718 
12719  dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12720  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12721  plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12722 
12723  Info = GOOD;
12724  if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12725  {
12726  result[0] = 2;
12727  PUT_WORD(&result[1], EC_SUCCESS);
12728  }
12729  else
12730  {
12731  result[0] = 5;
12732  PUT_WORD(&result[1], plci->ec_cmd);
12733  result[3] = 2;
12734  PUT_WORD(&result[4], GOOD);
12735  }
12736  internal_command = plci->internal_command;
12737  plci->internal_command = 0;
12738  switch (plci->ec_cmd)
12739  {
12740  case EC_ENABLE_OPERATION:
12743  case EC_RESET_COEFFICIENTS:
12744  switch (internal_command)
12745  {
12746  default:
12747  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12749  case EC_COMMAND_1:
12750  if (adjust_b_process(Id, plci, Rc) != GOOD)
12751  {
12752  dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12753  UnMapId(Id), (char *)(FILE_), __LINE__));
12754  Info = _FACILITY_NOT_SUPPORTED;
12755  break;
12756  }
12757  if (plci->internal_command)
12758  return;
12759  case EC_COMMAND_2:
12760  if (plci->sig_req)
12761  {
12763  return;
12764  }
12766  ec_write_parameters(plci);
12767  return;
12768  case EC_COMMAND_3:
12769  if ((Rc != OK) && (Rc != OK_FC))
12770  {
12771  dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12772  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12773  Info = _FACILITY_NOT_SUPPORTED;
12774  break;
12775  }
12776  break;
12777  }
12778  break;
12779 
12780  case EC_DISABLE_OPERATION:
12781  switch (internal_command)
12782  {
12783  default:
12784  case EC_COMMAND_1:
12785  if (plci->B1_facilities & B1_FACILITY_EC)
12786  {
12787  if (plci->sig_req)
12788  {
12790  return;
12791  }
12793  ec_write_parameters(plci);
12794  return;
12795  }
12796  Rc = OK;
12797  case EC_COMMAND_2:
12798  if ((Rc != OK) && (Rc != OK_FC))
12799  {
12800  dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12801  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12802  Info = _FACILITY_NOT_SUPPORTED;
12803  break;
12804  }
12805  adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12807  case EC_COMMAND_3:
12808  if (adjust_b_process(Id, plci, Rc) != GOOD)
12809  {
12810  dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12811  UnMapId(Id), (char *)(FILE_), __LINE__));
12812  Info = _FACILITY_NOT_SUPPORTED;
12813  break;
12814  }
12815  if (plci->internal_command)
12816  return;
12817  break;
12818  }
12819  break;
12820  }
12821  sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12822  "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12824 }
12825 
12826 
12827 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12828 {
12829  word Info;
12830  word opt;
12831  API_PARSE ec_parms[3];
12832  byte result[16];
12833 
12834  dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12835  UnMapId(Id), (char *)(FILE_), __LINE__));
12836 
12837  Info = GOOD;
12838  result[0] = 0;
12840  {
12841  dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12842  UnMapId(Id), (char *)(FILE_), __LINE__));
12843  Info = _FACILITY_NOT_SUPPORTED;
12844  }
12845  else
12846  {
12847  if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12848  {
12849  if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12850  {
12851  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12852  UnMapId(Id), (char *)(FILE_), __LINE__));
12853  Info = _WRONG_MESSAGE_FORMAT;
12854  }
12855  else
12856  {
12857  if (plci == NULL)
12858  {
12859  dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12860  UnMapId(Id), (char *)(FILE_), __LINE__));
12861  Info = _WRONG_IDENTIFIER;
12862  }
12863  else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12864  {
12865  dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12866  UnMapId(Id), (char *)(FILE_), __LINE__));
12867  Info = _WRONG_STATE;
12868  }
12869  else
12870  {
12871  plci->command = 0;
12872  plci->ec_cmd = GET_WORD(ec_parms[0].info);
12874  result[0] = 2;
12875  PUT_WORD(&result[1], EC_SUCCESS);
12876  if (msg[1].length >= 4)
12877  {
12878  opt = GET_WORD(&ec_parms[0].info[2]);
12881  if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12883  if (opt & EC_DETECT_DISABLE_TONE)
12885  if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12887  if (msg[1].length >= 6)
12888  {
12889  plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12890  }
12891  }
12892  switch (plci->ec_cmd)
12893  {
12894  case EC_ENABLE_OPERATION:
12896  start_internal_command(Id, plci, ec_command);
12897  return (false);
12898 
12899  case EC_DISABLE_OPERATION:
12903  start_internal_command(Id, plci, ec_command);
12904  return (false);
12905 
12908  start_internal_command(Id, plci, ec_command);
12909  return (false);
12910 
12913  start_internal_command(Id, plci, ec_command);
12914  return (false);
12915 
12916  case EC_RESET_COEFFICIENTS:
12918  start_internal_command(Id, plci, ec_command);
12919  return (false);
12920 
12921  default:
12922  dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12923  UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12924  PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12925  }
12926  }
12927  }
12928  }
12929  else
12930  {
12931  if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12932  {
12933  dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12934  UnMapId(Id), (char *)(FILE_), __LINE__));
12935  Info = _WRONG_MESSAGE_FORMAT;
12936  }
12937  else
12938  {
12939  if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12940  {
12941  result[0] = 11;
12942  PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12943  result[3] = 8;
12944  PUT_WORD(&result[4], GOOD);
12945  PUT_WORD(&result[6], 0x0007);
12946  PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12947  PUT_WORD(&result[10], 0);
12948  }
12949  else if (plci == NULL)
12950  {
12951  dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12952  UnMapId(Id), (char *)(FILE_), __LINE__));
12953  Info = _WRONG_IDENTIFIER;
12954  }
12955  else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12956  {
12957  dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12958  UnMapId(Id), (char *)(FILE_), __LINE__));
12959  Info = _WRONG_STATE;
12960  }
12961  else
12962  {
12963  plci->command = 0;
12964  plci->ec_cmd = GET_WORD(ec_parms[0].info);
12966  result[0] = 5;
12967  PUT_WORD(&result[1], plci->ec_cmd);
12968  result[3] = 2;
12969  PUT_WORD(&result[4], GOOD);
12972  plci->ec_tail_length = 0;
12973  if (ec_parms[1].length >= 2)
12974  {
12975  opt = GET_WORD(&ec_parms[1].info[1]);
12978  if (opt & EC_DETECT_DISABLE_TONE)
12980  if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12982  if (ec_parms[1].length >= 4)
12983  {
12984  plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12985  }
12986  }
12987  switch (plci->ec_cmd)
12988  {
12989  case EC_ENABLE_OPERATION:
12991  start_internal_command(Id, plci, ec_command);
12992  return (false);
12993 
12994  case EC_DISABLE_OPERATION:
12998  start_internal_command(Id, plci, ec_command);
12999  return (false);
13000 
13001  default:
13002  dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13003  UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13004  PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13005  }
13006  }
13007  }
13008  }
13009  }
13010  sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13011  "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13013  return (false);
13014 }
13015 
13016 
13017 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13018 {
13019  byte result[8];
13020 
13021  dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13022  UnMapId(Id), (char *)(FILE_), __LINE__));
13023 
13024  if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13025  {
13026  if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13027  {
13028  result[0] = 2;
13029  PUT_WORD(&result[1], 0);
13030  switch (msg[1])
13031  {
13033  PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13034  break;
13036  PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13037  break;
13038  case LEC_DISABLE_RELEASED:
13039  PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13040  break;
13041  }
13042  }
13043  else
13044  {
13045  result[0] = 5;
13046  PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13047  result[3] = 2;
13048  PUT_WORD(&result[4], 0);
13049  switch (msg[1])
13050  {
13052  PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13053  break;
13055  PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13056  break;
13057  case LEC_DISABLE_RELEASED:
13058  PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13059  break;
13060  }
13061  }
13062  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13064  }
13065 }
13066 
13067 
13068 
13069 /*------------------------------------------------------------------*/
13070 /* Advanced voice */
13071 /*------------------------------------------------------------------*/
13072 
13073 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13074 {
13076  word i;
13077  byte *p;
13078 
13079  word w, n, j, k;
13080  byte ch_map[MIXER_CHANNELS_BRI];
13081 
13082  byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13083 
13084  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13085  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13086  (char *)(FILE_), __LINE__, write_command));
13087 
13088  a = plci->adapter;
13089  p = coef_buffer + 1;
13091  i = 0;
13092  while (i + sizeof(word) <= a->adv_voice_coef_length)
13093  {
13094  PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13095  p += 2;
13096  i += 2;
13097  }
13098  while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13099  {
13100  PUT_WORD(p, 0x8000);
13101  p += 2;
13102  i += 2;
13103  }
13104 
13105  if (!a->li_pri && (plci->li_bchannel_id == 0))
13106  {
13107  if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13108  {
13109  plci->li_bchannel_id = 1;
13110  li_config_table[a->li_base].plci = plci;
13111  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13112  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13113  (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13114  }
13115  else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13116  {
13117  plci->li_bchannel_id = 2;
13118  li_config_table[a->li_base + 1].plci = plci;
13119  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13120  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13121  (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13122  }
13123  }
13124  if (!a->li_pri && (plci->li_bchannel_id != 0)
13125  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13126  {
13127  i = a->li_base + (plci->li_bchannel_id - 1);
13128  switch (write_command)
13129  {
13131  j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13132  k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13133  if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13134  {
13135  li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13136  li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13137  }
13139  {
13140  li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13141  li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13142  li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13143  li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13144  }
13145  mixer_calculate_coefs(a);
13146  li_config_table[i].curchnl = li_config_table[i].channel;
13147  li_config_table[j].curchnl = li_config_table[j].channel;
13149  li_config_table[k].curchnl = li_config_table[k].channel;
13150  break;
13151 
13153  for (j = 0; j < li_total_channels; j++)
13154  {
13155  li_config_table[i].flag_table[j] = 0;
13156  li_config_table[j].flag_table[i] = 0;
13157  }
13158  k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13159  for (j = 0; j < li_total_channels; j++)
13160  {
13161  li_config_table[k].flag_table[j] = 0;
13162  li_config_table[j].flag_table[k] = 0;
13163  }
13165  {
13166  k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13167  for (j = 0; j < li_total_channels; j++)
13168  {
13169  li_config_table[k].flag_table[j] = 0;
13170  li_config_table[j].flag_table[k] = 0;
13171  }
13172  }
13173  mixer_calculate_coefs(a);
13174  break;
13175  }
13176  if (plci->B1_facilities & B1_FACILITY_MIXER)
13177  {
13178  w = 0;
13181  if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13183  if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13185  *(p++) = (byte) w;
13186  *(p++) = (byte)(w >> 8);
13187  for (j = 0; j < sizeof(ch_map); j += 2)
13188  {
13189  ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13190  ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13191  }
13192  for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13193  {
13194  i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13195  j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13196  if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13197  {
13198  *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13199  w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13200  li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13201  }
13202  else
13203  {
13204  *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13205  a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13206  }
13207  }
13208  }
13209  else
13210  {
13211  for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212  *(p++) = a->adv_voice_coef_buffer[i];
13213  }
13214  }
13215  else
13216 
13217  {
13218  for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13219  *(p++) = a->adv_voice_coef_buffer[i];
13220  }
13221  coef_buffer[0] = (p - coef_buffer) - 1;
13222  add_p(plci, FTY, coef_buffer);
13223  sig_req(plci, TEL_CTRL, 0);
13224  send_req(plci);
13225 }
13226 
13227 
13228 static void adv_voice_clear_config(PLCI *plci)
13229 {
13231 
13232  word i, j;
13233 
13234 
13235  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13236  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13237  (char *)(FILE_), __LINE__));
13238 
13239  a = plci->adapter;
13240  if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13241  {
13242  a->adv_voice_coef_length = 0;
13243 
13244  if (!a->li_pri && (plci->li_bchannel_id != 0)
13245  && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13246  {
13247  i = a->li_base + (plci->li_bchannel_id - 1);
13248  li_config_table[i].curchnl = 0;
13249  li_config_table[i].channel = 0;
13250  li_config_table[i].chflags = 0;
13251  for (j = 0; j < li_total_channels; j++)
13252  {
13253  li_config_table[i].flag_table[j] = 0;
13254  li_config_table[j].flag_table[i] = 0;
13255  li_config_table[i].coef_table[j] = 0;
13256  li_config_table[j].coef_table[i] = 0;
13257  }
13258  li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13259  i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13260  li_config_table[i].curchnl = 0;
13261  li_config_table[i].channel = 0;
13262  li_config_table[i].chflags = 0;
13263  for (j = 0; j < li_total_channels; j++)
13264  {
13265  li_config_table[i].flag_table[j] = 0;
13266  li_config_table[j].flag_table[i] = 0;
13267  li_config_table[i].coef_table[j] = 0;
13268  li_config_table[j].coef_table[i] = 0;
13269  }
13271  {
13272  i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13273  li_config_table[i].curchnl = 0;
13274  li_config_table[i].channel = 0;
13275  li_config_table[i].chflags = 0;
13276  for (j = 0; j < li_total_channels; j++)
13277  {
13278  li_config_table[i].flag_table[j] = 0;
13279  li_config_table[j].flag_table[i] = 0;
13280  li_config_table[i].coef_table[j] = 0;
13281  li_config_table[j].coef_table[i] = 0;
13282  }
13283  }
13284  }
13285 
13286  }
13287 }
13288 
13289 
13290 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13291 {
13292 
13293  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13294  UnMapId(Id), (char *)(FILE_), __LINE__));
13295 
13296 }
13297 
13298 
13299 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13300 {
13301 
13302  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13303  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13304 
13305  return (GOOD);
13306 }
13307 
13308 
13309 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13310 {
13312  word Info;
13313 
13314  dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13315  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13316 
13317  Info = GOOD;
13318  a = plci->adapter;
13319  if ((plci->B1_facilities & B1_FACILITY_VOICE)
13320  && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13321  {
13322  switch (plci->adjust_b_state)
13323  {
13325  plci->internal_command = plci->adjust_b_command;
13326  if (plci->sig_req)
13327  {
13329  break;
13330  }
13331  adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13333  break;
13335  if ((Rc != OK) && (Rc != OK_FC))
13336  {
13337  dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13338  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13339  Info = _WRONG_STATE;
13340  break;
13341  }
13342  break;
13343  }
13344  }
13345  return (Info);
13346 }
13347 
13348 
13349 
13350 
13351 /*------------------------------------------------------------------*/
13352 /* B1 resource switching */
13353 /*------------------------------------------------------------------*/
13354 
13355 static byte b1_facilities_table[] =
13356 {
13357  0x00, /* 0 No bchannel resources */
13358  0x00, /* 1 Codec (automatic law) */
13359  0x00, /* 2 Codec (A-law) */
13360  0x00, /* 3 Codec (y-law) */
13361  0x00, /* 4 HDLC for X.21 */
13362  0x00, /* 5 HDLC */
13363  0x00, /* 6 External Device 0 */
13364  0x00, /* 7 External Device 1 */
13365  0x00, /* 8 HDLC 56k */
13366  0x00, /* 9 Transparent */
13367  0x00, /* 10 Loopback to network */
13368  0x00, /* 11 Test pattern to net */
13369  0x00, /* 12 Rate adaptation sync */
13370  0x00, /* 13 Rate adaptation async */
13371  0x00, /* 14 R-Interface */
13372  0x00, /* 15 HDLC 128k leased line */
13373  0x00, /* 16 FAX */
13374  0x00, /* 17 Modem async */
13375  0x00, /* 18 Modem sync HDLC */
13376  0x00, /* 19 V.110 async HDLC */
13377  0x12, /* 20 Adv voice (Trans,mixer) */
13378  0x00, /* 21 Codec connected to IC */
13379  0x0c, /* 22 Trans,DTMF */
13380  0x1e, /* 23 Trans,DTMF+mixer */
13381  0x1f, /* 24 Trans,DTMF+mixer+local */
13382  0x13, /* 25 Trans,mixer+local */
13383  0x12, /* 26 HDLC,mixer */
13384  0x12, /* 27 HDLC 56k,mixer */
13385  0x2c, /* 28 Trans,LEC+DTMF */
13386  0x3e, /* 29 Trans,LEC+DTMF+mixer */
13387  0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13388  0x2c, /* 31 RTP,LEC+DTMF */
13389  0x3e, /* 32 RTP,LEC+DTMF+mixer */
13390  0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13391  0x00, /* 34 Signaling task */
13392  0x00, /* 35 PIAFS */
13393  0x0c, /* 36 Trans,DTMF+TONE */
13394  0x1e, /* 37 Trans,DTMF+TONE+mixer */
13395  0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13396 };
13397 
13398 
13399 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13400 {
13401  word b1_facilities;
13402 
13403  b1_facilities = b1_facilities_table[b1_resource];
13404  if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13405  {
13406 
13407  if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13408  || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13409 
13410  {
13412  b1_facilities |= B1_FACILITY_DTMFX;
13414  b1_facilities |= B1_FACILITY_DTMFR;
13415  }
13416  }
13417  if ((b1_resource == 17) || (b1_resource == 18))
13418  {
13420  b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13421  }
13422 /*
13423  dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13424  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13425  (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13426 */
13427  return (b1_facilities);
13428 }
13429 
13430 
13431 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13432 {
13433  byte b;
13434 
13435  switch (b1_resource)
13436  {
13437  case 5:
13438  case 26:
13439  if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13440  b = 26;
13441  else
13442  b = 5;
13443  break;
13444 
13445  case 8:
13446  case 27:
13447  if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13448  b = 27;
13449  else
13450  b = 8;
13451  break;
13452 
13453  case 9:
13454  case 20:
13455  case 22:
13456  case 23:
13457  case 24:
13458  case 25:
13459  case 28:
13460  case 29:
13461  case 30:
13462  case 36:
13463  case 37:
13464  case 38:
13465  if (b1_facilities & B1_FACILITY_EC)
13466  {
13467  if (b1_facilities & B1_FACILITY_LOCAL)
13468  b = 30;
13469  else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470  b = 29;
13471  else
13472  b = 28;
13473  }
13474 
13475  else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13476  && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13477  || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13478  {
13479  if (b1_facilities & B1_FACILITY_LOCAL)
13480  b = 38;
13481  else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482  b = 37;
13483  else
13484  b = 36;
13485  }
13486 
13489  || ((b1_facilities & B1_FACILITY_DTMFR)
13490  && ((b1_facilities & B1_FACILITY_MIXER)
13492  || ((b1_facilities & B1_FACILITY_DTMFX)
13493  && ((b1_facilities & B1_FACILITY_MIXER)
13495  {
13496  if (b1_facilities & B1_FACILITY_LOCAL)
13497  b = 24;
13498  else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13499  b = 23;
13500  else
13501  b = 22;
13502  }
13503  else
13504  {
13505  if (b1_facilities & B1_FACILITY_LOCAL)
13506  b = 25;
13507  else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13508  b = 20;
13509  else
13510  b = 9;
13511  }
13512  break;
13513 
13514  case 31:
13515  case 32:
13516  case 33:
13517  if (b1_facilities & B1_FACILITY_LOCAL)
13518  b = 33;
13519  else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520  b = 32;
13521  else
13522  b = 31;
13523  break;
13524 
13525  default:
13526  b = b1_resource;
13527  }
13528  dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13529  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13530  (char *)(FILE_), __LINE__,
13531  b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13532  return (b);
13533 }
13534 
13535 
13536 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13537 {
13538  word removed_facilities;
13539 
13540  dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13541  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13542  (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13543  new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13544 
13545  new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13546  removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13547 
13548  if (removed_facilities & B1_FACILITY_EC)
13549  ec_clear_config(plci);
13550 
13551 
13552  if (removed_facilities & B1_FACILITY_DTMFR)
13553  {
13554  dtmf_rec_clear_config(plci);
13555  dtmf_parameter_clear_config(plci);
13556  }
13557  if (removed_facilities & B1_FACILITY_DTMFX)
13558  dtmf_send_clear_config(plci);
13559 
13560 
13561  if (removed_facilities & B1_FACILITY_MIXER)
13562  mixer_clear_config(plci);
13563 
13564  if (removed_facilities & B1_FACILITY_VOICE)
13565  adv_voice_clear_config(plci);
13566  plci->B1_facilities = new_b1_facilities;
13567 }
13568 
13569 
13570 static void adjust_b_clear(PLCI *plci)
13571 {
13572 
13573  dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13574  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13575  (char *)(FILE_), __LINE__));
13576 
13577  plci->adjust_b_restore = false;
13578 }
13579 
13580 
13581 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13582 {
13583  word Info;
13584  byte b1_resource;
13585  NCCI *ncci_ptr;
13586  API_PARSE bp[2];
13587 
13588  dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13589  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13590 
13591  Info = GOOD;
13592  switch (plci->adjust_b_state)
13593  {
13594  case ADJUST_B_START:
13595  if ((plci->adjust_b_parms_msg == NULL)
13599  {
13600  b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13601  0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13602  if (b1_resource == plci->B1_resource)
13603  {
13604  adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13605  break;
13606  }
13607  if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13608  {
13609  dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13610  UnMapId(Id), (char *)(FILE_), __LINE__,
13611  plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13612  Info = _WRONG_STATE;
13613  break;
13614  }
13615  }
13616  if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13617  {
13618 
13619  mixer_prepare_switch(Id, plci);
13620 
13621 
13622  dtmf_prepare_switch(Id, plci);
13623  dtmf_parameter_prepare_switch(Id, plci);
13624 
13625 
13626  ec_prepare_switch(Id, plci);
13627 
13628  adv_voice_prepare_switch(Id, plci);
13629  }
13631  Rc = OK;
13632  case ADJUST_B_SAVE_MIXER_1:
13633  if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634  {
13635 
13636  Info = mixer_save_config(Id, plci, Rc);
13637  if ((Info != GOOD) || plci->internal_command)
13638  break;
13639 
13640  }
13642  Rc = OK;
13643  case ADJUST_B_SAVE_DTMF_1:
13644  if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13645  {
13646 
13647  Info = dtmf_save_config(Id, plci, Rc);
13648  if ((Info != GOOD) || plci->internal_command)
13649  break;
13650 
13651  }
13653  case ADJUST_B_REMOVE_L23_1:
13655  && plci->NL.Id && !plci->nl_remove_id)
13656  {
13657  plci->internal_command = plci->adjust_b_command;
13658  if (plci->adjust_b_ncci != 0)
13659  {
13660  ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13661  while (ncci_ptr->data_pending)
13662  {
13663  plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13664  data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13665  }
13666  while (ncci_ptr->data_ack_pending)
13667  data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13668  }
13669  nl_req_ncci(plci, REMOVE,
13670  (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13671  send_req(plci);
13673  break;
13674  }
13676  Rc = OK;
13677  case ADJUST_B_REMOVE_L23_2:
13678  if ((Rc != OK) && (Rc != OK_FC))
13679  {
13680  dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13681  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13682  Info = _WRONG_STATE;
13683  break;
13684  }
13686  {
13687  if (plci_nl_busy(plci))
13688  {
13689  plci->internal_command = plci->adjust_b_command;
13690  break;
13691  }
13692  }
13694  Rc = OK;
13695  case ADJUST_B_SAVE_EC_1:
13696  if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697  {
13698 
13699  Info = ec_save_config(Id, plci, Rc);
13700  if ((Info != GOOD) || plci->internal_command)
13701  break;
13702 
13703  }
13705  Rc = OK;
13707  if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708  {
13709 
13710  Info = dtmf_parameter_save_config(Id, plci, Rc);
13711  if ((Info != GOOD) || plci->internal_command)
13712  break;
13713 
13714  }
13716  Rc = OK;
13717  case ADJUST_B_SAVE_VOICE_1:
13718  if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13719  {
13720  Info = adv_voice_save_config(Id, plci, Rc);
13721  if ((Info != GOOD) || plci->internal_command)
13722  break;
13723  }
13725  case ADJUST_B_SWITCH_L1_1:
13727  {
13728  if (plci->sig_req)
13729  {
13730  plci->internal_command = plci->adjust_b_command;
13731  break;
13732  }
13733  if (plci->adjust_b_parms_msg != NULL)
13734  api_load_msg(plci->adjust_b_parms_msg, bp);
13735  else
13736  api_load_msg(&plci->B_protocol, bp);
13737  Info = add_b1(plci, bp,
13738  (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13739  plci->adjust_b_facilities);
13740  if (Info != GOOD)
13741  {
13742  dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13743  UnMapId(Id), (char *)(FILE_), __LINE__,
13744  plci->B1_resource, plci->adjust_b_facilities));
13745  break;
13746  }
13747  plci->internal_command = plci->adjust_b_command;
13748  sig_req(plci, RESOURCES, 0);
13749  send_req(plci);
13751  break;
13752  }
13754  Rc = OK;
13755  case ADJUST_B_SWITCH_L1_2:
13756  if ((Rc != OK) && (Rc != OK_FC))
13757  {
13758  dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13759  UnMapId(Id), (char *)(FILE_), __LINE__,
13760  Rc, plci->B1_resource, plci->adjust_b_facilities));
13761  Info = _WRONG_STATE;
13762  break;
13763  }
13765  Rc = OK;
13769  {
13770  Info = adv_voice_restore_config(Id, plci, Rc);
13771  if ((Info != GOOD) || plci->internal_command)
13772  break;
13773  }
13775  Rc = OK;
13779  {
13780 
13781  Info = dtmf_parameter_restore_config(Id, plci, Rc);
13782  if ((Info != GOOD) || plci->internal_command)
13783  break;
13784 
13785  }
13787  Rc = OK;
13788  case ADJUST_B_RESTORE_EC_1:
13789  case ADJUST_B_RESTORE_EC_2:
13791  {
13792 
13793  Info = ec_restore_config(Id, plci, Rc);
13794  if ((Info != GOOD) || plci->internal_command)
13795  break;
13796 
13797  }
13799  case ADJUST_B_ASSIGN_L23_1:
13801  {
13802  if (plci_nl_busy(plci))
13803  {
13804  plci->internal_command = plci->adjust_b_command;
13805  break;
13806  }
13809  if (plci->adjust_b_parms_msg != NULL)
13810  api_load_msg(plci->adjust_b_parms_msg, bp);
13811  else
13812  api_load_msg(&plci->B_protocol, bp);
13813  Info = add_b23(plci, bp);
13814  if (Info != GOOD)
13815  {
13816  dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13817  UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13818  break;
13819  }
13820  plci->internal_command = plci->adjust_b_command;
13821  nl_req_ncci(plci, ASSIGN, 0);
13822  send_req(plci);
13824  break;
13825  }
13827  Rc = ASSIGN_OK;
13828  case ADJUST_B_ASSIGN_L23_2:
13829  if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13830  {
13831  dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13832  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13833  Info = _WRONG_STATE;
13834  break;
13835  }
13837  {
13838  if (Rc != ASSIGN_OK)
13839  {
13840  plci->internal_command = plci->adjust_b_command;
13841  break;
13842  }
13843  }
13845  {
13846  plci->adjust_b_restore = true;
13847  break;
13848  }
13850  case ADJUST_B_CONNECT_1:
13852  {
13853  plci->internal_command = plci->adjust_b_command;
13854  if (plci_nl_busy(plci))
13855  break;
13856  nl_req_ncci(plci, N_CONNECT, 0);
13857  send_req(plci);
13859  break;
13860  }
13862  Rc = OK;
13863  case ADJUST_B_CONNECT_2:
13864  case ADJUST_B_CONNECT_3:
13865  case ADJUST_B_CONNECT_4:
13866  if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13867  {
13868  dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13869  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13870  Info = _WRONG_STATE;
13871  break;
13872  }
13873  if (Rc == OK)
13874  {
13876  {
13877  get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13878  Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13879  }
13880  if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882  else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13884  }
13885  else if (Rc == 0)
13886  {
13887  if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13889  else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13891  }
13893  {
13894  plci->internal_command = plci->adjust_b_command;
13895  break;
13896  }
13897  Rc = OK;
13901  {
13902 
13903  Info = dtmf_restore_config(Id, plci, Rc);
13904  if ((Info != GOOD) || plci->internal_command)
13905  break;
13906 
13907  }
13909  Rc = OK;
13918  {
13919 
13920  Info = mixer_restore_config(Id, plci, Rc);
13921  if ((Info != GOOD) || plci->internal_command)
13922  break;
13923 
13924  }
13925  plci->adjust_b_state = ADJUST_B_END;
13926  case ADJUST_B_END:
13927  break;
13928  }
13929  return (Info);
13930 }
13931 
13932 
13933 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13934 {
13935 
13936  dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13937  UnMapId(Id), (char *)(FILE_), __LINE__,
13938  plci->B1_resource, b1_facilities));
13939 
13940  plci->adjust_b_parms_msg = bp_msg;
13941  plci->adjust_b_facilities = b1_facilities;
13942  plci->adjust_b_command = internal_command;
13943  plci->adjust_b_ncci = (word)(Id >> 16);
13944  if ((bp_msg == NULL) && (plci->B1_resource == 0))
13946  else
13949  dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13950  UnMapId(Id), (char *)(FILE_), __LINE__,
13951  plci->B1_resource, b1_facilities));
13952 }
13953 
13954 
13955 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13956 {
13957  word internal_command;
13958 
13959  dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13960  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13961 
13962  internal_command = plci->internal_command;
13963  plci->internal_command = 0;
13964  switch (internal_command)
13965  {
13966  default:
13967  plci->command = 0;
13968  if (plci->req_in != 0)
13969  {
13971  break;
13972  }
13973  Rc = OK;
13974  case ADJUST_B_RESTORE_1:
13975  if ((Rc != OK) && (Rc != OK_FC))
13976  {
13977  dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13978  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13979  }
13980  plci->adjust_b_parms_msg = NULL;
13981  plci->adjust_b_facilities = plci->B1_facilities;
13983  plci->adjust_b_ncci = (word)(Id >> 16);
13986  dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13987  UnMapId(Id), (char *)(FILE_), __LINE__));
13988  case ADJUST_B_RESTORE_2:
13989  if (adjust_b_process(Id, plci, Rc) != GOOD)
13990  {
13991  dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13992  UnMapId(Id), (char *)(FILE_), __LINE__));
13993  }
13994  if (plci->internal_command)
13995  break;
13996  break;
13997  }
13998 }
13999 
14000 
14001 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14002 {
14003  word Info;
14004  word internal_command;
14005 
14006  dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14007  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14008 
14009  Info = GOOD;
14010  internal_command = plci->internal_command;
14011  plci->internal_command = 0;
14012  switch (internal_command)
14013  {
14014  default:
14015  plci->command = 0;
14016  plci->adjust_b_parms_msg = NULL;
14017  plci->adjust_b_facilities = plci->B1_facilities;
14019  plci->adjust_b_ncci = (word)(Id >> 16);
14022  dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14023  UnMapId(Id), (char *)(FILE_), __LINE__));
14024  case RESET_B3_COMMAND_1:
14025  Info = adjust_b_process(Id, plci, Rc);
14026  if (Info != GOOD)
14027  {
14028  dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14029  UnMapId(Id), (char *)(FILE_), __LINE__));
14030  break;
14031  }
14032  if (plci->internal_command)
14033  return;
14034  break;
14035  }
14036 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14037  sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14038 }
14039 
14040 
14041 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14042 {
14043  word Info;
14044  word internal_command;
14045  byte esc_chi[3];
14046 
14047  dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14048  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14049 
14050  Info = GOOD;
14051  internal_command = plci->internal_command;
14052  plci->internal_command = 0;
14053  switch (internal_command)
14054  {
14055  default:
14056  plci->command = 0;
14057  plci->adjust_b_parms_msg = &plci->saved_msg;
14058  if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14060  else
14063  plci->adjust_b_ncci = (word)(Id >> 16);
14064  if (plci->saved_msg.parms[0].length == 0)
14065  {
14068  }
14069  else
14070  {
14073  }
14075  dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14076  UnMapId(Id), (char *)(FILE_), __LINE__));
14077  case SELECT_B_COMMAND_1:
14078  Info = adjust_b_process(Id, plci, Rc);
14079  if (Info != GOOD)
14080  {
14081  dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14082  UnMapId(Id), (char *)(FILE_), __LINE__));
14083  break;
14084  }
14085  if (plci->internal_command)
14086  return;
14087  if (plci->tel == ADV_VOICE)
14088  {
14089  esc_chi[0] = 0x02;
14090  esc_chi[1] = 0x18;
14091  esc_chi[2] = plci->b_channel;
14092  SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14093  }
14094  break;
14095  }
14096  sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14097 }
14098 
14099 
14100 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14101 {
14102  word internal_command;
14103 
14104  dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14105  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14106 
14107  internal_command = plci->internal_command;
14108  plci->internal_command = 0;
14109  switch (internal_command)
14110  {
14111  default:
14112  plci->command = 0;
14114  if (plci_nl_busy(plci))
14115  {
14117  return;
14118  }
14120  plci->NData[0].P = plci->fax_connect_info_buffer;
14121  plci->NData[0].PLength = plci->fax_connect_info_length;
14122  plci->NL.X = plci->NData;
14123  plci->NL.ReqCh = 0;
14124  plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14125  plci->adapter->request(&plci->NL);
14126  return;
14128  if ((Rc != OK) && (Rc != OK_FC))
14129  {
14130  dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14131  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14132  break;
14133  }
14134  }
14136  && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14137  {
14138  if (plci->B3_prot == 4)
14139  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14140  else
14141  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14143  }
14144 }
14145 
14146 
14147 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14148 {
14149  word internal_command;
14150 
14151  dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14152  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14153 
14154  internal_command = plci->internal_command;
14155  plci->internal_command = 0;
14156  switch (internal_command)
14157  {
14158  default:
14159  plci->command = 0;
14161  if (plci_nl_busy(plci))
14162  {
14164  return;
14165  }
14167  plci->NData[0].P = plci->fax_connect_info_buffer;
14168  plci->NData[0].PLength = plci->fax_edata_ack_length;
14169  plci->NL.X = plci->NData;
14170  plci->NL.ReqCh = 0;
14171  plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14172  plci->adapter->request(&plci->NL);
14173  return;
14175  if ((Rc != OK) && (Rc != OK_FC))
14176  {
14177  dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14178  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14179  break;
14180  }
14181  }
14182 }
14183 
14184 
14185 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14186 {
14187  word Info;
14188  word internal_command;
14189 
14190  dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14191  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14192 
14193  Info = GOOD;
14194  internal_command = plci->internal_command;
14195  plci->internal_command = 0;
14196  switch (internal_command)
14197  {
14198  default:
14199  plci->command = 0;
14201  if (plci_nl_busy(plci))
14202  {
14204  return;
14205  }
14207  plci->NData[0].P = plci->fax_connect_info_buffer;
14208  plci->NData[0].PLength = plci->fax_connect_info_length;
14209  plci->NL.X = plci->NData;
14210  plci->NL.ReqCh = 0;
14211  plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14212  plci->adapter->request(&plci->NL);
14213  return;
14215  if ((Rc != OK) && (Rc != OK_FC))
14216  {
14217  dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14218  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14219  Info = _WRONG_STATE;
14220  break;
14221  }
14222  if (plci_nl_busy(plci))
14223  {
14225  return;
14226  }
14227  plci->command = _CONNECT_B3_R;
14228  nl_req_ncci(plci, N_CONNECT, 0);
14229  send_req(plci);
14230  return;
14231  }
14232  sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233 }
14234 
14235 
14236 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14237 {
14238  word Info;
14239  word internal_command;
14240 
14241  dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14242  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14243 
14244  Info = GOOD;
14245  internal_command = plci->internal_command;
14246  plci->internal_command = 0;
14247  switch (internal_command)
14248  {
14249  default:
14250  plci->command = 0;
14251  plci->adjust_b_parms_msg = NULL;
14252  plci->adjust_b_facilities = plci->B1_facilities;
14254  plci->adjust_b_ncci = (word)(Id >> 16);
14257  dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14258  UnMapId(Id), (char *)(FILE_), __LINE__));
14260  Info = adjust_b_process(Id, plci, Rc);
14261  if (Info != GOOD)
14262  {
14263  dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14264  UnMapId(Id), (char *)(FILE_), __LINE__));
14265  break;
14266  }
14267  if (plci->internal_command)
14268  return;
14270  if (plci_nl_busy(plci))
14271  {
14273  return;
14274  }
14275  plci->command = _CONNECT_B3_R;
14276  nl_req_ncci(plci, N_CONNECT, 0);
14277  send_req(plci);
14278  return;
14279  }
14280  sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14281 }
14282 
14283 
14284 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14285 {
14286  word internal_command;
14287 
14288  dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14289  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14290 
14291  internal_command = plci->internal_command;
14292  plci->internal_command = 0;
14293  switch (internal_command)
14294  {
14295  default:
14296  plci->command = 0;
14298  return;
14302  if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14303  {
14304  dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14305  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14306  break;
14307  }
14308  if (Rc == OK)
14309  {
14310  if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14311  || (internal_command == FAX_DISCONNECT_COMMAND_2))
14312  {
14314  }
14315  }
14316  else if (Rc == 0)
14317  {
14318  if (internal_command == FAX_DISCONNECT_COMMAND_1)
14320  }
14321  return;
14322  }
14323 }
14324 
14325 
14326 
14327 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14328 {
14329  word Info;
14330  word internal_command;
14331 
14332  dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14333  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14334 
14335  Info = GOOD;
14336  internal_command = plci->internal_command;
14337  plci->internal_command = 0;
14338  switch (internal_command)
14339  {
14340  default:
14341  plci->command = 0;
14343  if (plci_nl_busy(plci))
14344  {
14346  return;
14347  }
14349  nl_req_ncci(plci, N_CONNECT, 0);
14350  send_req(plci);
14351  return;
14353  if ((Rc != OK) && (Rc != OK_FC))
14354  {
14355  dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14356  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14357  Info = _WRONG_STATE;
14358  break;
14359  }
14360  if (plci_nl_busy(plci))
14361  {
14363  return;
14364  }
14366  plci->NData[0].PLength = plci->internal_req_buffer[0];
14367  plci->NData[0].P = plci->internal_req_buffer + 1;
14368  plci->NL.X = plci->NData;
14369  plci->NL.ReqCh = 0;
14370  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14371  plci->adapter->request(&plci->NL);
14372  break;
14374  return;
14375  }
14376  sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14377 }
14378 
14379 
14380 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14381 {
14382  word internal_command;
14383 
14384  dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14385  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14386 
14387  internal_command = plci->internal_command;
14388  plci->internal_command = 0;
14389  switch (internal_command)
14390  {
14391  default:
14392  plci->command = 0;
14394  if (plci_nl_busy(plci))
14395  {
14397  return;
14398  }
14400  nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14401  send_req(plci);
14402  return;
14404  if ((Rc != OK) && (Rc != OK_FC))
14405  {
14406  dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14407  UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14408  break;
14409  }
14410  if (plci_nl_busy(plci))
14411  {
14413  return;
14414  }
14415  sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14417  plci->NData[0].PLength = plci->internal_req_buffer[0];
14418  plci->NData[0].P = plci->internal_req_buffer + 1;
14419  plci->NL.X = plci->NData;
14420  plci->NL.ReqCh = 0;
14421  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422  plci->adapter->request(&plci->NL);
14423  return;
14425  return;
14426  }
14427 }
14428 
14429 
14430 
14431 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14432 {
14433  byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14434  word Info;
14435  word internal_command;
14436 
14437  dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14438  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14439 
14440  Info = GOOD;
14441  internal_command = plci->internal_command;
14442  plci->internal_command = 0;
14443  switch (internal_command)
14444  {
14445  default:
14446  if (!plci->NL.Id)
14447  break;
14448  plci->command = 0;
14449  plci->adjust_b_parms_msg = NULL;
14450  plci->adjust_b_facilities = plci->B1_facilities;
14452  plci->adjust_b_ncci = (word)(Id >> 16);
14455  dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14456  UnMapId(Id), (char *)(FILE_), __LINE__));
14457  case HOLD_SAVE_COMMAND_1:
14458  Info = adjust_b_process(Id, plci, Rc);
14459  if (Info != GOOD)
14460  {
14461  dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14462  UnMapId(Id), (char *)(FILE_), __LINE__));
14463  break;
14464  }
14465  if (plci->internal_command)
14466  return;
14467  }
14468  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14469 }
14470 
14471 
14472 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14473 {
14474  byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14475  word Info;
14476  word internal_command;
14477 
14478  dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479  UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14480 
14481  Info = GOOD;
14482  internal_command = plci->internal_command;
14483  plci->internal_command = 0;
14484  switch (internal_command)
14485  {
14486  default:
14487  plci->command = 0;
14488  plci->adjust_b_parms_msg = NULL;
14489  plci->adjust_b_facilities = plci->B1_facilities;
14491  plci->adjust_b_ncci = (word)(Id >> 16);
14494  dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14495  UnMapId(Id), (char *)(FILE_), __LINE__));
14497  Info = adjust_b_process(Id, plci, Rc);
14498  if (Info != GOOD)
14499  {
14500  dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14501  UnMapId(Id), (char *)(FILE_), __LINE__));
14502  break;
14503  }
14504  if (plci->internal_command)
14505  return;
14506  }
14507  sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14508 }
14509 
14510 
14511 static void init_b1_config(PLCI *plci)
14512 {
14513 
14514  dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14515  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14516  (char *)(FILE_), __LINE__));
14517 
14518  plci->B1_resource = 0;
14519  plci->B1_facilities = 0;
14520 
14521  plci->li_bchannel_id = 0;
14522  mixer_clear_config(plci);
14523 
14524 
14525  ec_clear_config(plci);
14526 
14527 
14528  dtmf_rec_clear_config(plci);
14529  dtmf_send_clear_config(plci);
14530  dtmf_parameter_clear_config(plci);
14531 
14532  adv_voice_clear_config(plci);
14533  adjust_b_clear(plci);
14534 }
14535 
14536 
14537 static void clear_b1_config(PLCI *plci)
14538 {
14539 
14540  dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14541  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14542  (char *)(FILE_), __LINE__));
14543 
14544  adv_voice_clear_config(plci);
14545  adjust_b_clear(plci);
14546 
14547  ec_clear_config(plci);
14548 
14549 
14550  dtmf_rec_clear_config(plci);
14551  dtmf_send_clear_config(plci);
14552  dtmf_parameter_clear_config(plci);
14553 
14554 
14555  if ((plci->li_bchannel_id != 0)
14556  && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14557  {
14558  mixer_clear_config(plci);
14559  li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560  plci->li_bchannel_id = 0;
14561  }
14562 
14563  plci->B1_resource = 0;
14564  plci->B1_facilities = 0;
14565 }
14566 
14567 
14568 /* -----------------------------------------------------------------
14569  XON protocol local helpers
14570  ----------------------------------------------------------------- */
14571 static void channel_flow_control_remove(PLCI *plci) {
14572  DIVA_CAPI_ADAPTER *a = plci->adapter;
14573  word i;
14574  for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14575  if (a->ch_flow_plci[i] == plci->Id) {
14576  a->ch_flow_plci[i] = 0;
14577  a->ch_flow_control[i] = 0;
14578  }
14579  }
14580 }
14581 
14582 static void channel_x_on(PLCI *plci, byte ch) {
14583  DIVA_CAPI_ADAPTER *a = plci->adapter;
14584  if (a->ch_flow_control[ch] & N_XON_SENT) {
14585  a->ch_flow_control[ch] &= ~N_XON_SENT;
14586  }
14587 }
14588 
14589 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14590  DIVA_CAPI_ADAPTER *a = plci->adapter;
14591  if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592  a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593  a->ch_flow_plci[ch] = plci->Id;
14595  }
14596 }
14597 
14598 static void channel_request_xon(PLCI *plci, byte ch) {
14599  DIVA_CAPI_ADAPTER *a = plci->adapter;
14600 
14601  if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602  a->ch_flow_control[ch] |= N_XON_REQ;
14603  a->ch_flow_control[ch] &= ~N_CH_XOFF;
14605  }
14606 }
14607 
14608 static void channel_xmit_extended_xon(PLCI *plci) {
14610  int max_ch = ARRAY_SIZE(a->ch_flow_control);
14611  int i, one_requested = 0;
14612 
14613  if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14614  return;
14615  }
14616 
14617  for (i = 0; i < max_ch; i++) {
14618  if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619  (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620  (plci->Id == a->ch_flow_plci[i])) {
14621  channel_request_xon(plci, (byte)i);
14622  one_requested = 1;
14623  }
14624  }
14625 
14626  if (one_requested) {
14627  channel_xmit_xon(plci);
14628  }
14629 }
14630 
14631 /*
14632  Try to xmit next X_ON
14633 */
14634 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14635  int max_ch = ARRAY_SIZE(a->ch_flow_control);
14636  int i;
14637 
14639  return (0);
14640  }
14641 
14642  if (a->last_flow_control_ch >= max_ch) {
14643  a->last_flow_control_ch = 1;
14644  }
14645  for (i = a->last_flow_control_ch; i < max_ch; i++) {
14646  if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647  (plci->Id == a->ch_flow_plci[i])) {
14648  a->last_flow_control_ch = i + 1;
14649  return (i);
14650  }
14651  }
14652 
14653  for (i = 1; i < a->last_flow_control_ch; i++) {
14654  if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655  (plci->Id == a->ch_flow_plci[i])) {
14656  a->last_flow_control_ch = i + 1;
14657  return (i);
14658  }
14659  }
14660 
14661  return (0);
14662 }
14663 
14664 static void channel_xmit_xon(PLCI *plci) {
14665  DIVA_CAPI_ADAPTER *a = plci->adapter;
14666  byte ch;
14667 
14668  if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14669  return;
14670  }
14671  if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14672  return;
14673  }
14674  a->ch_flow_control[ch] &= ~N_XON_REQ;
14675  a->ch_flow_control[ch] |= N_XON_SENT;
14676 
14677  plci->NL.Req = plci->nl_req = (byte)N_XON;
14678  plci->NL.ReqCh = ch;
14679  plci->NL.X = plci->NData;
14680  plci->NL.XNum = 1;
14681  plci->NData[0].P = &plci->RBuffer[0];
14682  plci->NData[0].PLength = 0;
14683 
14684  plci->adapter->request(&plci->NL);
14685 }
14686 
14687 static int channel_can_xon(PLCI *plci, byte ch) {
14688  APPL *APPLptr;
14690  word NCCIcode;
14691  dword count;
14692  word Num;
14693  word i;
14694 
14695  APPLptr = plci->appl;
14696  a = plci->adapter;
14697 
14698  if (!APPLptr)
14699  return (0);
14700 
14701  NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14702 
14703  /* count all buffers within the Application pool */
14704  /* belonging to the same NCCI. XON if a first is */
14705  /* used. */
14706  count = 0;
14707  Num = 0xffff;
14708  for (i = 0; i < APPLptr->MaxBuffer; i++) {
14709  if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14710  if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14711  }
14712  if ((count > 2) || (Num == 0xffff)) {
14713  return (0);
14714  }
14715  return (1);
14716 }
14717 
14718 
14719 /*------------------------------------------------------------------*/
14720 
14721 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14722 {
14723  return 1;
14724 }
14725 
14726 
14727 
14728 /**********************************************************************************/
14729 /* function groups the listening applications according to the CIP mask and the */
14730 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14733 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14734 /* OS specific part (per adapter). */
14735 /**********************************************************************************/
14736 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14737 {
14738  word i, j, k, busy, group_found;
14739  dword info_mask_group[MAX_CIP_TYPES];
14740  dword cip_mask_group[MAX_CIP_TYPES];
14741  word appl_number_group_type[MAX_APPL];
14742  PLCI *auxplci;
14743 
14744  set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14745 
14747  {
14748  dbug(1, dprintf("No group optimization"));
14749  return;
14750  }
14751 
14752  dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14753 
14754  for (i = 0; i < MAX_CIP_TYPES; i++)
14755  {
14756  info_mask_group[i] = 0;
14757  cip_mask_group[i] = 0;
14758  }
14759  for (i = 0; i < MAX_APPL; i++)
14760  {
14761  appl_number_group_type[i] = 0;
14762  }
14763  for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14764  { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765  if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14766  {
14767  dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14768  return; /* allow good application unfiltered access */
14769  }
14770  }
14771  for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14772  {
14773  if (application[i].Id && a->CIP_Mask[i])
14774  {
14775  for (k = 0, busy = false; k < a->max_plci; k++)
14776  {
14777  if (a->plci[k].Id)
14778  {
14779  auxplci = &a->plci[k];
14780  if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14781  {
14782  busy = true;
14783  dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14784  }
14785  else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14786  {
14787  busy = true;
14788  dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14789  }
14790  }
14791  }
14792 
14793  for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++) /* build groups with free applications only */
14794  {
14795  if (j == MAX_CIP_TYPES) /* all groups are in use but group still not found */
14796  { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797  appl_number_group_type[i] = MAX_CIP_TYPES;
14798  group_found = true;
14799  dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14800  }
14801  else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14802  { /* is group already present ? */
14803  appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14804  group_found = true;
14805  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]));
14806  }
14807  else if (!info_mask_group[j])
14808  { /* establish a new group */
14809  appl_number_group_type[i] = j | 0x80; /* store the group number for each application */
14810  info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14811  cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14812  group_found = true;
14813  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]));
14814  }
14815  }
14816  }
14817  }
14818 
14819  for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14820  {
14821  if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14822  {
14823  if (appl_number_group_type[i] == MAX_CIP_TYPES)
14824  {
14825  dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14826  }
14827  else
14828  {
14829  dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14830  for (j = i + 1; j < max_appl; j++) /* search other group members and mark them as busy */
14831  {
14832  if (appl_number_group_type[i] == appl_number_group_type[j])
14833  {
14834  dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14835  clear_group_ind_mask_bit(plci, j); /* disable call on other group members */
14836  appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14837  }
14838  }
14839  }
14840  }
14841  else /* application should not get a call */
14842  {
14843  clear_group_ind_mask_bit(plci, i);
14844  }
14845  }
14846 
14847 }
14848 
14849 
14850 
14851 /* OS notifies the driver about a application Capi_Register */
14853 {
14854  word i, j, appls_found;
14855 
14856  PLCI *plci;
14858 
14859  for (i = 0, appls_found = 0; i < max_appl; i++)
14860  {
14861  if (application[i].Id && (application[i].Id != id))
14862  {
14863  appls_found++; /* an application has been found */
14864  }
14865  }
14866 
14867  if (appls_found) return true;
14868  for (i = 0; i < max_adapter; i++) /* scan all adapters... */
14869  {
14870  a = &adapter[i];
14871  if (a->request)
14872  {
14873  if (a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14874  {
14875  if (!appls_found) /* first application does a capi register */
14876  {
14877  if ((j = get_plci(a))) /* activate L1 of all adapters */
14878  {
14879  plci = &a->plci[j - 1];
14880  plci->command = 0;
14881  add_p(plci, OAD, "\x01\xfd");
14882  add_p(plci, CAI, "\x01\x80");
14883  add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14884  add_p(plci, SHIFT | 6, NULL);
14885  add_p(plci, SIN, "\x02\x00\x00");
14887  sig_req(plci, ASSIGN, DSIG_ID);
14888  add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14889  sig_req(plci, SIG_CTRL, 0);
14890  send_req(plci);
14891  }
14892  }
14893  }
14894  }
14895  }
14896  return false;
14897 }
14898 
14899 /*------------------------------------------------------------------*/
14900 
14901 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14902 
14903 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14904 {
14905  word i;
14906  /* Format of vswitch_t:
14907  0 byte length
14908  1 byte VSWITCHIE
14909  2 byte VSWITCH_REQ/VSWITCH_IND
14910  3 byte reserved
14911  4 word VSwitchcommand
14912  6 word returnerror
14913  8... Params
14914  */
14915  if (!plci ||
14916  !plci->appl ||
14917  !plci->State ||
14918  plci->Sig.Ind == NCR_FACILITY
14919  )
14920  return;
14921 
14922  for (i = 0; i < MAX_MULTI_IE; i++)
14923  {
14924  if (!parms[i][0]) continue;
14925  if (parms[i][0] < 7)
14926  {
14927  parms[i][0] = 0; /* kill it */
14928  continue;
14929  }
14930  dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14931  switch (parms[i][4])
14932  {
14933  case VSJOIN:
14934  if (!plci->relatedPTYPLCI ||
14935  (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14936  { /* Error */
14937  break;
14938  }
14939  /* remember all necessary informations */
14940  if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14941  {
14942  break;
14943  }
14944  if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14945  { /* first indication after ECT-Request on Consultation Call */
14946  plci->vswitchstate = parms[i][9];
14947  parms[i][9] = 2; /* State */
14948  /* now ask first Call to join */
14949  }
14950  else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14951  { /* Answer of VSWITCH_REQ from first Call */
14952  plci->vswitchstate = parms[i][9];
14953  /* tell consultation call to join
14954  and the protocol capabilities of the first call */
14955  }
14956  else
14957  { /* Error */
14958  break;
14959  }
14960  plci->vsprot = parms[i][10]; /* protocol */
14961  plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14962  /* send join request to related PLCI */
14963  parms[i][1] = VSWITCHIE;
14964  parms[i][2] = VSWITCH_REQ;
14965 
14966  plci->relatedPTYPLCI->command = 0;
14968  add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14969  sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14970  send_req(plci->relatedPTYPLCI);
14971  break;
14972  case VSTRANSPORT:
14973  default:
14974  if (plci->relatedPTYPLCI &&
14975  plci->vswitchstate == 3 &&
14976  plci->relatedPTYPLCI->vswitchstate == 3)
14977  {
14978  add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14979  sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14980  send_req(plci->relatedPTYPLCI);
14981  }
14982  break;
14983  }
14984  parms[i][0] = 0; /* kill it */
14985  }
14986 }
14987 
14988 
14989 /*------------------------------------------------------------------*/
14990 
14991 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic) {
14992  ENTITY e;
14993  IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14994 
14995  if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14996  return (-1);
14997  }
14998 
14999  pReq->xdi_dma_descriptor_operation.Req = 0;
15001 
15003  pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15004  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005  pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15006 
15007  e.user[0] = plci->adapter->Id - 1;
15008  plci->adapter->request((ENTITY *)pReq);
15009 
15010  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011  (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012  pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013  *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014  dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15015  plci->adapter->Id,
15016  pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15017  *dma_magic));
15018  return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15019  } else {
15020  dbug(1, dprintf("dma_alloc failed"));
15021  return (-1);
15022  }
15023 }
15024 
15025 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15026  ENTITY e;
15027  IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15028 
15029  if (nr < 0) {
15030  return;
15031  }
15032 
15033  pReq->xdi_dma_descriptor_operation.Req = 0;
15035 
15037  pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15038  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039  pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15040 
15041  e.user[0] = plci->adapter->Id - 1;
15042  plci->adapter->request((ENTITY *)pReq);
15043 
15044  if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045  dbug(1, dprintf("dma_free(%d)", nr));
15046  } else {
15047  dbug(1, dprintf("dma_free failed (%d)", nr));
15048  }
15049 }
15050 
15051 /*------------------------------------------------------------------*/