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]);