blob: ab1c112dfb7c23726b01e2d2dd1867ce3ab6c58b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001
2/*
3 *
4 Copyright (c) Eicon Networks, 2002.
5 *
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
8 *
9 Eicon File Revision : 2.1
10 *
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15 *
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
20 *
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27
28
29
30
31#include "platform.h"
32#include "di_defs.h"
33#include "pc.h"
34#include "capi20.h"
35#include "divacapi.h"
36#include "mdm_msg.h"
37#include "divasync.h"
38
39
40
41#define FILE_ "MESSAGE.C"
42#define dprintf
43
44
45
46
47
48
49
50
51
52/*------------------------------------------------------------------*/
53/* This is options supported for all adapters that are server by */
54/* XDI driver. Allo it is not necessary to ask it from every adapter*/
55/* and it is not necessary to save it separate for every adapter */
56/* Macrose defined here have only local meaning */
57/*------------------------------------------------------------------*/
58static dword diva_xdi_extended_features = 0;
59
60#define DIVA_CAPI_USE_CMA 0x00000001
61#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
62#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
63#define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
64
65/*
66 CAPI can request to process all return codes self only if:
67 protocol code supports this && xdi supports this
68 */
69#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))
70
71/*------------------------------------------------------------------*/
72/* local function prototypes */
73/*------------------------------------------------------------------*/
74
75static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci);
76static void set_group_ind_mask (PLCI *plci);
77static void clear_group_ind_mask_bit (PLCI *plci, word b);
78static byte test_group_ind_mask_bit (PLCI *plci, word b);
79void AutomaticLaw(DIVA_CAPI_ADAPTER *);
80word CapiRelease(word);
81word CapiRegister(word);
82word api_put(APPL *, CAPI_MSG *);
83static word api_parse(byte *, word, byte *, API_PARSE *);
84static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
85static void api_load_msg(API_SAVE *in, API_PARSE *out);
86
87word api_remove_start(void);
88void api_remove_complete(void);
89
90static void plci_remove(PLCI *);
91static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a);
92static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
93
94void callback(ENTITY *);
95
96static void control_rc(PLCI *, byte, byte, byte, byte, byte);
97static void data_rc(PLCI *, byte);
98static void data_ack(PLCI *, byte);
99static void sig_ind(PLCI *);
100static void SendInfo(PLCI *, dword, byte * *, byte);
101static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte);
102static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms);
103
104static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
105
106static void nl_ind(PLCI *);
107
108static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
132
133static word get_plci(DIVA_CAPI_ADAPTER *);
134static void add_p(PLCI *, byte, byte *);
135static void add_s(PLCI * plci, byte code, API_PARSE * p);
136static void add_ss(PLCI * plci, byte code, API_PARSE * p);
137static void add_ie(PLCI * plci, byte code, byte * p, word p_length);
138static void add_d(PLCI *, word, byte *);
139static void add_ai(PLCI *, API_PARSE *);
140static word add_b1(PLCI *, API_PARSE *, word, word);
141static word add_b23(PLCI *, API_PARSE *);
142static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms);
143static void sig_req(PLCI *, byte, byte);
144static void nl_req_ncci(PLCI *, byte, byte);
145static void send_req(PLCI *);
146static void send_data(PLCI *);
147static word plci_remove_check(PLCI *);
148static void listen_check(DIVA_CAPI_ADAPTER *);
149static byte AddInfo(byte **, byte **, byte *, byte *);
150static byte getChannel(API_PARSE *);
151static void IndParse(PLCI *, word *, byte **, byte);
152static byte ie_compare(byte *, byte *);
153static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
154static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word);
155
156/*
157 XON protocol helpers
158 */
159static void channel_flow_control_remove (PLCI * plci);
160static void channel_x_off (PLCI * plci, byte ch, byte flag);
161static void channel_x_on (PLCI * plci, byte ch);
162static void channel_request_xon (PLCI * plci, byte ch);
163static void channel_xmit_xon (PLCI * plci);
164static int channel_can_xon (PLCI * plci, byte ch);
165static void channel_xmit_extended_xon (PLCI * plci);
166
167static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse);
168static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
169static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
170static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * );
171static void VoiceChannelOff(PLCI *plci);
172static void adv_voice_write_coefs (PLCI *plci, word write_command);
173static void adv_voice_clear_config (PLCI *plci);
174
175static word get_b1_facilities (PLCI * plci, byte b1_resource);
176static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities);
177static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities);
178static word adjust_b_process (dword Id, PLCI *plci, byte Rc);
179static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
180static void adjust_b_restore (dword Id, PLCI *plci, byte Rc);
181static void reset_b3_command (dword Id, PLCI *plci, byte Rc);
182static void select_b_command (dword Id, PLCI *plci, byte Rc);
183static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc);
184static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc);
185static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc);
186static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc);
187static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc);
188static void hold_save_command (dword Id, PLCI *plci, byte Rc);
189static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc);
190static void init_b1_config (PLCI *plci);
191static void clear_b1_config (PLCI *plci);
192
193static void dtmf_command (dword Id, PLCI *plci, byte Rc);
194static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
195static void dtmf_confirmation (dword Id, PLCI *plci);
196static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length);
197static void dtmf_parameter_write (PLCI *plci);
198
199
200static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id);
201static void mixer_set_bchannel_id (PLCI *plci, byte *chi);
202static void mixer_clear_config (PLCI *plci);
203static void mixer_notify_update (PLCI *plci, byte others);
204static void mixer_command (dword Id, PLCI *plci, byte Rc);
205static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
206static void mixer_indication_coefs_set (dword Id, PLCI *plci);
207static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length);
208static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length);
209static void mixer_remove (PLCI *plci);
210
211
212static void ec_command (dword Id, PLCI *plci, byte Rc);
213static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
214static void ec_indication (dword Id, PLCI *plci, byte *msg, word length);
215
216
217static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc);
218static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc);
219
220
221static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
222static void diva_free_dma_descriptor (PLCI *plci, int nr);
223
224/*------------------------------------------------------------------*/
225/* external function prototypes */
226/*------------------------------------------------------------------*/
227
228extern byte MapController (byte);
229extern byte UnMapController (byte);
230#define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
231#define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
232
233void sendf(APPL *, word, dword, word, byte *, ...);
234void * TransmitBufferSet(APPL * appl, dword ref);
235void * TransmitBufferGet(APPL * appl, void * p);
236void TransmitBufferFree(APPL * appl, void * p);
237void * ReceiveBufferGet(APPL * appl, int Num);
238
239int fax_head_line_time (char *buffer);
240
241
242/*------------------------------------------------------------------*/
243/* Global data definitions */
244/*------------------------------------------------------------------*/
245extern byte max_adapter;
246extern byte max_appl;
247extern DIVA_CAPI_ADAPTER * adapter;
248extern APPL * application;
249
250
251
252
253
254
255
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800256static byte remove_started = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257static PLCI dummy_plci;
258
259
260static struct _ftable {
261 word command;
262 byte * format;
263 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
264} ftable[] = {
265 {_DATA_B3_R, "dwww", data_b3_req},
266 {_DATA_B3_I|RESPONSE, "w", data_b3_res},
267 {_INFO_R, "ss", info_req},
268 {_INFO_I|RESPONSE, "", info_res},
269 {_CONNECT_R, "wsssssssss", connect_req},
270 {_CONNECT_I|RESPONSE, "wsssss", connect_res},
271 {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res},
272 {_DISCONNECT_R, "s", disconnect_req},
273 {_DISCONNECT_I|RESPONSE, "", disconnect_res},
274 {_LISTEN_R, "dddss", listen_req},
275 {_ALERT_R, "s", alert_req},
276 {_FACILITY_R, "ws", facility_req},
277 {_FACILITY_I|RESPONSE, "ws", facility_res},
278 {_CONNECT_B3_R, "s", connect_b3_req},
279 {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res},
280 {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res},
281 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
282 {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res},
283 {_RESET_B3_R, "s", reset_b3_req},
284 {_RESET_B3_I|RESPONSE, "", reset_b3_res},
285 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res},
286 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res},
287 {_SELECT_B_REQ, "s", select_b_req},
288 {_MANUFACTURER_R, "dws", manufacturer_req},
289 {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res},
290 {_MANUFACTURER_I|RESPONSE, "", manufacturer_res}
291};
292
293static byte * cip_bc[29][2] = {
294 { "", "" }, /* 0 */
295 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
296 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
297 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
298 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
299 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
300 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
301 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
302 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
303 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
304 { "", "" }, /* 10 */
305 { "", "" }, /* 11 */
306 { "", "" }, /* 12 */
307 { "", "" }, /* 13 */
308 { "", "" }, /* 14 */
309 { "", "" }, /* 15 */
310
311 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
312 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
320 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
322 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
323 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
324};
325
326static byte * cip_hlc[29] = {
327 "", /* 0 */
328 "", /* 1 */
329 "", /* 2 */
330 "", /* 3 */
331 "", /* 4 */
332 "", /* 5 */
333 "", /* 6 */
334 "", /* 7 */
335 "", /* 8 */
336 "", /* 9 */
337 "", /* 10 */
338 "", /* 11 */
339 "", /* 12 */
340 "", /* 13 */
341 "", /* 14 */
342 "", /* 15 */
343
344 "\x02\x91\x81", /* 16 */
345 "\x02\x91\x84", /* 17 */
346 "\x02\x91\xa1", /* 18 */
347 "\x02\x91\xa4", /* 19 */
348 "\x02\x91\xa8", /* 20 */
349 "\x02\x91\xb1", /* 21 */
350 "\x02\x91\xb2", /* 22 */
351 "\x02\x91\xb5", /* 23 */
352 "\x02\x91\xb8", /* 24 */
353 "\x02\x91\xc1", /* 25 */
354 "\x02\x91\x81", /* 26 */
355 "\x03\x91\xe0\x01", /* 27 */
356 "\x03\x91\xe0\x02" /* 28 */
357};
358
359/*------------------------------------------------------------------*/
360
361#define V120_HEADER_LENGTH 1
362#define V120_HEADER_EXTEND_BIT 0x80
363#define V120_HEADER_BREAK_BIT 0x40
364#define V120_HEADER_C1_BIT 0x04
365#define V120_HEADER_C2_BIT 0x08
366#define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
367
368static byte v120_default_header[] =
369{
370
371 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
372
373};
374
375static byte v120_break_header[] =
376{
377
378 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
379
380};
381
382
383/*------------------------------------------------------------------*/
384/* API_PUT function */
385/*------------------------------------------------------------------*/
386
387word api_put(APPL * appl, CAPI_MSG * msg)
388{
389 word i, j, k, l, n;
390 word ret;
391 byte c;
392 byte controller;
393 DIVA_CAPI_ADAPTER * a;
394 PLCI * plci;
395 NCCI * ncci_ptr;
396 word ncci;
397 CAPI_MSG *m;
398 API_PARSE msg_parms[MAX_MSG_PARMS+1];
399
400 if (msg->header.length < sizeof (msg->header) ||
401 msg->header.length > MAX_MSG_SIZE) {
402 dbug(1,dprintf("bad len"));
403 return _BAD_MSG;
404 }
405
406 controller = (byte)((msg->header.controller &0x7f)-1);
407
408 /* controller starts with 0 up to (max_adapter - 1) */
409 if ( controller >= max_adapter )
410 {
411 dbug(1,dprintf("invalid ctrl"));
412 return _BAD_MSG;
413 }
414
415 a = &adapter[controller];
416 plci = NULL;
417 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
418 {
419 dbug(1,dprintf("plci=%x",msg->header.plci));
420 plci = &a->plci[msg->header.plci-1];
421 ncci = GET_WORD(&msg->header.ncci);
422 if (plci->Id
423 && (plci->appl
424 || (plci->State == INC_CON_PENDING)
425 || (plci->State == INC_CON_ALERT)
426 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
427 && ((ncci == 0)
428 || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
429 || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
430 {
431 i = plci->msg_in_read_pos;
432 j = plci->msg_in_write_pos;
433 if (j >= i)
434 {
435 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
436 i += MSG_IN_QUEUE_SIZE - j;
437 else
438 j = 0;
439 }
440 else
441 {
442
443 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444
445 if (i > MSG_IN_QUEUE_SIZE - n)
446 i = MSG_IN_QUEUE_SIZE - n + 1;
447 i -= j;
448 }
449
450 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
451
452 {
453 dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
454 msg->header.length, plci->msg_in_write_pos,
455 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
456
457 return _QUEUE_FULL;
458 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800459 c = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
461 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
462 {
463 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800464 c = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 }
466 if (msg->header.command == _DATA_B3_R)
467 {
468 if (msg->header.length < 20)
469 {
470 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
471 return _BAD_MSG;
472 }
473 ncci_ptr = &(a->ncci[ncci]);
474 n = ncci_ptr->data_pending;
475 l = ncci_ptr->data_ack_pending;
476 k = plci->msg_in_read_pos;
477 while (k != plci->msg_in_write_pos)
478 {
479 if (k == plci->msg_in_wrap_pos)
480 k = 0;
481 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
482 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
483 {
484 n++;
485 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
486 l++;
487 }
488
489 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
490 MSG_IN_OVERHEAD + 3) & 0xfffc;
491
492 }
493 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
494 {
495 dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
496 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
497
498 return _QUEUE_FULL;
499 }
500 if (plci->req_in || plci->internal_command)
501 {
502 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
503 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504 {
505 dbug(0,dprintf("Q-FULL3(requeue)"));
506
507 return _QUEUE_FULL;
508 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800509 c = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 }
511 }
512 else
513 {
514 if (plci->req_in || plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800515 c = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 else
517 {
518 plci->command = msg->header.command;
519 plci->number = msg->header.number;
520 }
521 }
522 if (c)
523 {
524 dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
525 msg->header.command, plci->req_in, plci->internal_command,
526 msg->header.length, plci->msg_in_write_pos,
527 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
528 if (j == 0)
529 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
530 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
531 for (i = 0; i < msg->header.length; i++)
532 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
533 if (m->header.command == _DATA_B3_R)
534 {
535
536 m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
537
538 }
539
540 j = (j + 3) & 0xfffc;
541
542 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
543 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
544 return 0;
545 }
546 }
547 else
548 {
549 plci = NULL;
550 }
551 }
552 dbug(1,dprintf("com=%x",msg->header.command));
553
554 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
555 for(i=0, ret = _BAD_MSG;
556 i<(sizeof(ftable)/sizeof(struct _ftable));
557 i++) {
558
559 if(ftable[i].command==msg->header.command) {
560 /* break loop if the message is correct, otherwise continue scan */
561 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
562 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
563 ret = 0;
564 break;
565 }
566 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
567 }
568 }
569 if(ret) {
570 dbug(1,dprintf("BAD_MSG"));
571 if(plci) plci->command = 0;
572 return ret;
573 }
574
575
576 c = ftable[i].function(GET_DWORD(&msg->header.controller),
577 msg->header.number,
578 a,
579 plci,
580 appl,
581 msg_parms);
582
583 channel_xmit_extended_xon (plci);
584
585 if(c==1) send_req(plci);
586 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
587 if(plci && !plci->req_in) plci->command = 0;
588 return 0;
589}
590
591
592/*------------------------------------------------------------------*/
593/* api_parse function, check the format of api messages */
594/*------------------------------------------------------------------*/
595
596word api_parse(byte * msg, word length, byte * format, API_PARSE * parms)
597{
598 word i;
599 word p;
600
601 for(i=0,p=0; format[i]; i++) {
602 if(parms)
603 {
604 parms[i].info = &msg[p];
605 }
606 switch(format[i]) {
607 case 'b':
608 p +=1;
609 break;
610 case 'w':
611 p +=2;
612 break;
613 case 'd':
614 p +=4;
615 break;
616 case 's':
617 if(msg[p]==0xff) {
618 parms[i].info +=2;
619 parms[i].length = msg[p+1] + (msg[p+2]<<8);
620 p +=(parms[i].length +3);
621 }
622 else {
623 parms[i].length = msg[p];
624 p +=(parms[i].length +1);
625 }
626 break;
627 }
628
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800629 if(p>length) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 }
631 if(parms) parms[i].info = NULL;
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800632 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633}
634
635void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
636{
637 word i, j, n = 0;
638 byte *p;
639
640 p = out->info;
641 for (i = 0; format[i] != '\0'; i++)
642 {
643 out->parms[i].info = p;
644 out->parms[i].length = in[i].length;
645 switch (format[i])
646 {
647 case 'b':
648 n = 1;
649 break;
650 case 'w':
651 n = 2;
652 break;
653 case 'd':
654 n = 4;
655 break;
656 case 's':
657 n = in[i].length + 1;
658 break;
659 }
660 for (j = 0; j < n; j++)
661 *(p++) = in[i].info[j];
662 }
663 out->parms[i].info = NULL;
664 out->parms[i].length = 0;
665}
666
667void api_load_msg(API_SAVE *in, API_PARSE *out)
668{
669 word i;
670
671 i = 0;
672 do
673 {
674 out[i].info = in->parms[i].info;
675 out[i].length = in->parms[i].length;
676 } while (in->parms[i++].info);
677}
678
679
680/*------------------------------------------------------------------*/
681/* CAPI remove function */
682/*------------------------------------------------------------------*/
683
684word api_remove_start(void)
685{
686 word i;
687 word j;
688
689 if(!remove_started) {
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800690 remove_started = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 for(i=0;i<max_adapter;i++) {
692 if(adapter[i].request) {
693 for(j=0;j<adapter[i].max_plci;j++) {
694 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
695 }
696 }
697 }
698 return 1;
699 }
700 else {
701 for(i=0;i<max_adapter;i++) {
702 if(adapter[i].request) {
703 for(j=0;j<adapter[i].max_plci;j++) {
704 if(adapter[i].plci[j].Sig.Id) return 1;
705 }
706 }
707 }
708 }
709 api_remove_complete();
710 return 0;
711}
712
713
714/*------------------------------------------------------------------*/
715/* internal command queue */
716/*------------------------------------------------------------------*/
717
718static void init_internal_command_queue (PLCI *plci)
719{
720 word i;
721
722 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
723 (char *)(FILE_), __LINE__));
724
725 plci->internal_command = 0;
726 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
727 plci->internal_command_queue[i] = NULL;
728}
729
730
731static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
732{
733 word i;
734
735 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
736 UnMapId (Id), (char *)(FILE_), __LINE__));
737
738 if (plci->internal_command == 0)
739 {
740 plci->internal_command_queue[0] = command_function;
741 (* command_function)(Id, plci, OK);
742 }
743 else
744 {
745 i = 1;
746 while (plci->internal_command_queue[i] != 0)
747 i++;
748 plci->internal_command_queue[i] = command_function;
749 }
750}
751
752
753static void next_internal_command (dword Id, PLCI *plci)
754{
755 word i;
756
757 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
758 UnMapId (Id), (char *)(FILE_), __LINE__));
759
760 plci->internal_command = 0;
761 plci->internal_command_queue[0] = NULL;
762 while (plci->internal_command_queue[1] != 0)
763 {
764 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
765 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
766 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
767 (*(plci->internal_command_queue[0]))(Id, plci, OK);
768 if (plci->internal_command != 0)
769 return;
770 plci->internal_command_queue[0] = NULL;
771 }
772}
773
774
775/*------------------------------------------------------------------*/
776/* NCCI allocate/remove function */
777/*------------------------------------------------------------------*/
778
779static dword ncci_mapping_bug = 0;
780
781static word get_ncci (PLCI *plci, byte ch, word force_ncci)
782{
783 DIVA_CAPI_ADAPTER *a;
784 word ncci, i, j, k;
785
786 a = plci->adapter;
787 if (!ch || a->ch_ncci[ch])
788 {
789 ncci_mapping_bug++;
790 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
791 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
792 ncci = ch;
793 }
794 else
795 {
796 if (force_ncci)
797 ncci = force_ncci;
798 else
799 {
800 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
801 ncci = ch;
802 else
803 {
804 ncci = 1;
805 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
806 ncci++;
807 if (ncci == MAX_NCCI+1)
808 {
809 ncci_mapping_bug++;
810 i = 1;
811 do
812 {
813 j = 1;
814 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
815 j++;
816 k = j;
817 if (j < MAX_NCCI+1)
818 {
819 do
820 {
821 j++;
822 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
823 }
824 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
825 if (i < MAX_NL_CHANNEL+1)
826 {
827 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
828 ncci_mapping_bug, ch, force_ncci, i, k, j));
829 }
830 else
831 {
832 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
833 ncci_mapping_bug, ch, force_ncci));
834 }
835 ncci = ch;
836 }
837 }
838 a->ncci_plci[ncci] = plci->Id;
839 a->ncci_state[ncci] = IDLE;
840 if (!plci->ncci_ring_list)
841 plci->ncci_ring_list = ncci;
842 else
843 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
844 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
845 }
846 a->ncci_ch[ncci] = ch;
847 a->ch_ncci[ch] = (byte) ncci;
848 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
849 ncci_mapping_bug, ch, force_ncci, ch, ncci));
850 }
851 return (ncci);
852}
853
854
855static void ncci_free_receive_buffers (PLCI *plci, word ncci)
856{
857 DIVA_CAPI_ADAPTER *a;
858 APPL *appl;
859 word i, ncci_code;
860 dword Id;
861
862 a = plci->adapter;
863 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
864 if (ncci)
865 {
866 if (a->ncci_plci[ncci] == plci->Id)
867 {
868 if (!plci->appl)
869 {
870 ncci_mapping_bug++;
871 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
872 ncci_mapping_bug, Id));
873 }
874 else
875 {
876 appl = plci->appl;
877 ncci_code = ncci | (((word) a->Id) << 8);
878 for (i = 0; i < appl->MaxBuffer; i++)
879 {
880 if ((appl->DataNCCI[i] == ncci_code)
881 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
882 {
883 appl->DataNCCI[i] = 0;
884 }
885 }
886 }
887 }
888 }
889 else
890 {
891 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
892 {
893 if (a->ncci_plci[ncci] == plci->Id)
894 {
895 if (!plci->appl)
896 {
897 ncci_mapping_bug++;
898 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
899 ncci_mapping_bug, Id));
900 }
901 else
902 {
903 appl = plci->appl;
904 ncci_code = ncci | (((word) a->Id) << 8);
905 for (i = 0; i < appl->MaxBuffer; i++)
906 {
907 if ((appl->DataNCCI[i] == ncci_code)
908 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
909 {
910 appl->DataNCCI[i] = 0;
911 }
912 }
913 }
914 }
915 }
916 }
917}
918
919
920static void cleanup_ncci_data (PLCI *plci, word ncci)
921{
922 NCCI *ncci_ptr;
923
924 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
925 {
926 ncci_ptr = &(plci->adapter->ncci[ncci]);
927 if (plci->appl)
928 {
929 while (ncci_ptr->data_pending != 0)
930 {
931 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
932 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
933 (ncci_ptr->data_out)++;
934 if (ncci_ptr->data_out == MAX_DATA_B3)
935 ncci_ptr->data_out = 0;
936 (ncci_ptr->data_pending)--;
937 }
938 }
939 ncci_ptr->data_out = 0;
940 ncci_ptr->data_pending = 0;
941 ncci_ptr->data_ack_out = 0;
942 ncci_ptr->data_ack_pending = 0;
943 }
944}
945
946
947static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
948{
949 DIVA_CAPI_ADAPTER *a;
950 dword Id;
951 word i;
952
953 a = plci->adapter;
954 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
955 if (!preserve_ncci)
956 ncci_free_receive_buffers (plci, ncci);
957 if (ncci)
958 {
959 if (a->ncci_plci[ncci] != plci->Id)
960 {
961 ncci_mapping_bug++;
962 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
963 ncci_mapping_bug, Id, preserve_ncci));
964 }
965 else
966 {
967 cleanup_ncci_data (plci, ncci);
968 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
969 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
970 a->ch_ncci[a->ncci_ch[ncci]] = 0;
971 if (!preserve_ncci)
972 {
973 a->ncci_ch[ncci] = 0;
974 a->ncci_plci[ncci] = 0;
975 a->ncci_state[ncci] = IDLE;
976 i = plci->ncci_ring_list;
977 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
978 i = a->ncci_next[i];
979 if ((i != 0) && (a->ncci_next[i] == ncci))
980 {
981 if (i == ncci)
982 plci->ncci_ring_list = 0;
983 else if (plci->ncci_ring_list == ncci)
984 plci->ncci_ring_list = i;
985 a->ncci_next[i] = a->ncci_next[ncci];
986 }
987 a->ncci_next[ncci] = 0;
988 }
989 }
990 }
991 else
992 {
993 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
994 {
995 if (a->ncci_plci[ncci] == plci->Id)
996 {
997 cleanup_ncci_data (plci, ncci);
998 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
999 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1000 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1001 if (!preserve_ncci)
1002 {
1003 a->ncci_ch[ncci] = 0;
1004 a->ncci_plci[ncci] = 0;
1005 a->ncci_state[ncci] = IDLE;
1006 a->ncci_next[ncci] = 0;
1007 }
1008 }
1009 }
1010 if (!preserve_ncci)
1011 plci->ncci_ring_list = 0;
1012 }
1013}
1014
1015
1016/*------------------------------------------------------------------*/
1017/* PLCI remove function */
1018/*------------------------------------------------------------------*/
1019
1020static void plci_free_msg_in_queue (PLCI *plci)
1021{
1022 word i;
1023
1024 if (plci->appl)
1025 {
1026 i = plci->msg_in_read_pos;
1027 while (i != plci->msg_in_write_pos)
1028 {
1029 if (i == plci->msg_in_wrap_pos)
1030 i = 0;
1031 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1032 {
1033
1034 TransmitBufferFree (plci->appl,
1035 (byte *)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036
1037 }
1038
1039 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1040 MSG_IN_OVERHEAD + 3) & 0xfffc;
1041
1042 }
1043 }
1044 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1045 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1046 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047}
1048
1049
1050static void plci_remove(PLCI * plci)
1051{
1052
1053 if(!plci) {
1054 dbug(1,dprintf("plci_remove(no plci)"));
1055 return;
1056 }
1057 init_internal_command_queue (plci);
1058 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1059 if(plci_remove_check(plci))
1060 {
1061 return;
1062 }
1063 if (plci->Sig.Id == 0xff)
1064 {
1065 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1066 if (plci->NL.Id && !plci->nl_remove_id)
1067 {
1068 nl_req_ncci(plci,REMOVE,0);
1069 send_req(plci);
1070 }
1071 }
1072 else
1073 {
1074 if (!plci->sig_remove_id
1075 && (plci->Sig.Id
1076 || (plci->req_in!=plci->req_out)
1077 || (plci->nl_req || plci->sig_req)))
1078 {
1079 sig_req(plci,HANGUP,0);
1080 send_req(plci);
1081 }
1082 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001083 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 plci_free_msg_in_queue (plci);
1085
1086 plci->channels = 0;
1087 plci->appl = NULL;
1088 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1089 plci->State = OUTG_DIS_PENDING;
1090}
1091
1092/*------------------------------------------------------------------*/
1093/* Application Group function helpers */
1094/*------------------------------------------------------------------*/
1095
1096static void set_group_ind_mask (PLCI *plci)
1097{
1098 word i;
1099
1100 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1101 plci->group_optimization_mask_table[i] = 0xffffffffL;
1102}
1103
1104static void clear_group_ind_mask_bit (PLCI *plci, word b)
1105{
1106 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1107}
1108
1109static byte test_group_ind_mask_bit (PLCI *plci, word b)
1110{
1111 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1112}
1113
1114/*------------------------------------------------------------------*/
1115/* c_ind_mask operations for arbitrary MAX_APPL */
1116/*------------------------------------------------------------------*/
1117
1118static void clear_c_ind_mask (PLCI *plci)
1119{
1120 word i;
1121
1122 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1123 plci->c_ind_mask_table[i] = 0;
1124}
1125
1126static byte c_ind_mask_empty (PLCI *plci)
1127{
1128 word i;
1129
1130 i = 0;
1131 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1132 i++;
1133 return (i == C_IND_MASK_DWORDS);
1134}
1135
1136static void set_c_ind_mask_bit (PLCI *plci, word b)
1137{
1138 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1139}
1140
1141static void clear_c_ind_mask_bit (PLCI *plci, word b)
1142{
1143 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1144}
1145
1146static byte test_c_ind_mask_bit (PLCI *plci, word b)
1147{
1148 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1149}
1150
1151static void dump_c_ind_mask (PLCI *plci)
1152{
1153static char hex_digit_table[0x10] =
1154 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1155 word i, j, k;
1156 dword d;
1157 char *p;
1158 char buf[40];
1159
1160 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1161 {
1162 p = buf + 36;
1163 *p = '\0';
1164 for (j = 0; j < 4; j++)
1165 {
1166 if (i+j < C_IND_MASK_DWORDS)
1167 {
1168 d = plci->c_ind_mask_table[i+j];
1169 for (k = 0; k < 8; k++)
1170 {
1171 *(--p) = hex_digit_table[d & 0xf];
1172 d >>= 4;
1173 }
1174 }
1175 else if (i != 0)
1176 {
1177 for (k = 0; k < 8; k++)
1178 *(--p) = ' ';
1179 }
1180 *(--p) = ' ';
1181 }
1182 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1183 }
1184}
1185
1186
1187
1188
1189
1190#define dump_plcis(a)
1191
1192
1193
1194/*------------------------------------------------------------------*/
1195/* translation function for each message */
1196/*------------------------------------------------------------------*/
1197
1198byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1199{
1200 word ch;
1201 word i;
1202 word Info;
1203 word CIP;
1204 byte LinkLayer;
1205 API_PARSE * ai;
1206 API_PARSE * bp;
1207 API_PARSE ai_parms[5];
1208 word channel = 0;
1209 dword ch_mask;
1210 byte m;
1211 static byte esc_chi[35] = {0x02,0x18,0x01};
1212 static byte lli[2] = {0x01,0x00};
1213 byte noCh = 0;
1214 word dir = 0;
1215 byte *p_chi = "";
1216
1217 for(i=0;i<5;i++) ai_parms[i].length = 0;
1218
1219 dbug(1,dprintf("connect_req(%d)",parms->length));
1220 Info = _WRONG_IDENTIFIER;
1221 if(a)
1222 {
1223 if(a->adapter_disabled)
1224 {
1225 dbug(1,dprintf("adapter disabled"));
1226 Id = ((word)1<<8)|a->Id;
1227 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001229 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }
1231 Info = _OUT_OF_PLCI;
1232 if((i=get_plci(a)))
1233 {
1234 Info = 0;
1235 plci = &a->plci[i-1];
1236 plci->appl = appl;
1237 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238 /* check 'external controller' bit for codec support */
1239 if(Id & EXT_CONTROLLER)
1240 {
1241 if(AdvCodecSupport(a, plci, appl, 0) )
1242 {
1243 plci->Id = 0;
1244 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1245 return 2;
1246 }
1247 }
1248 ai = &parms[9];
1249 bp = &parms[5];
1250 ch = 0;
1251 if(bp->length)LinkLayer = bp->info[3];
1252 else LinkLayer = 0;
1253 if(ai->length)
1254 {
1255 ch=0xffff;
1256 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1257 {
1258 ch = 0;
1259 if(ai_parms[0].length)
1260 {
1261 ch = GET_WORD(ai_parms[0].info+1);
1262 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263 if(ch==4) /* explizit CHI in message */
1264 {
1265 /* check length of B-CH struct */
1266 if((ai_parms[0].info)[3]>=1)
1267 {
1268 if((ai_parms[0].info)[4]==CHI)
1269 {
1270 p_chi = &((ai_parms[0].info)[5]);
1271 }
1272 else
1273 {
1274 p_chi = &((ai_parms[0].info)[3]);
1275 }
1276 if(p_chi[0]>35) /* check length of channel ID */
1277 {
1278 Info = _WRONG_MESSAGE_FORMAT;
1279 }
1280 }
1281 else Info = _WRONG_MESSAGE_FORMAT;
1282 }
1283
1284 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285 {
1286 dir = GET_WORD(ai_parms[0].info+3);
1287 ch_mask = 0;
1288 m = 0x3f;
1289 for(i=0; i+5<=ai_parms[0].length; i++)
1290 {
1291 if(ai_parms[0].info[i+5]!=0)
1292 {
1293 if((ai_parms[0].info[i+5] | m) != 0xff)
1294 Info = _WRONG_MESSAGE_FORMAT;
1295 else
1296 {
1297 if (ch_mask == 0)
1298 channel = i;
1299 ch_mask |= 1L << i;
1300 }
1301 }
1302 m = 0;
1303 }
1304 if (ch_mask == 0)
1305 Info = _WRONG_MESSAGE_FORMAT;
1306 if (!Info)
1307 {
1308 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309 {
1310 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311 for(i=0; i+5<=ai_parms[0].length; i++)
1312 esc_chi[i+3] = ai_parms[0].info[i+5];
1313 }
1314 else
1315 esc_chi[0] = 2;
1316 esc_chi[2] = (byte)channel;
1317 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318 add_p(plci,LLI,lli);
1319 add_p(plci,ESC,esc_chi);
1320 plci->State = LOCAL_CONNECT;
1321 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1322 }
1323 }
1324 }
1325 }
1326 else Info = _WRONG_MESSAGE_FORMAT;
1327 }
1328
1329 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330 plci->command = _CONNECT_R;
1331 plci->number = Number;
1332 /* x.31 or D-ch free SAPI in LinkLayer? */
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001333 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335 {
1336 /* B-channel used for B3 connections (ch==0), or no B channel */
1337 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1338 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1339 else Info = add_b1(plci,&parms[5],ch,0);
1340 add_s(plci,OAD,&parms[2]);
1341 add_s(plci,OSA,&parms[4]);
1342 add_s(plci,BC,&parms[6]);
1343 add_s(plci,LLC,&parms[7]);
1344 add_s(plci,HLC,&parms[8]);
1345 CIP = GET_WORD(parms[0].info);
1346 if (a->Info_Mask[appl->Id-1] & 0x200)
1347 {
1348 /* early B3 connect (CIP mask bit 9) no release after a disc */
1349 add_p(plci,LLI,"\x01\x01");
1350 }
1351 if(GET_WORD(parms[0].info)<29) {
1352 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354 }
1355 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356 sig_req(plci,ASSIGN,DSIG_ID);
1357 }
1358 else if(ch==1) {
1359
1360 /* D-Channel used for B3 connections */
1361 plci->Sig.Id = 0xff;
1362 Info = 0;
1363 }
1364
1365 if(!Info && ch!=2 && !noCh ) {
1366 Info = add_b23(plci,&parms[5]);
1367 if(!Info) {
1368 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1369 }
1370 }
1371
1372 if(!Info)
1373 {
1374 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375 {
1376 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377 {
1378 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379 plci->spoofed_msg = CALL_REQ;
1380 plci->internal_command = BLOCK_PLCI;
1381 plci->command = 0;
1382 dbug(1,dprintf("Spoof"));
1383 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001384 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 }
1386 if(ch==4)add_p(plci,CHI,p_chi);
1387 add_s(plci,CPN,&parms[1]);
1388 add_s(plci,DSA,&parms[3]);
1389 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1390 add_ai(plci,&parms[9]);
1391 if(!dir)sig_req(plci,CALL_REQ,0);
1392 else
1393 {
1394 plci->command = PERM_LIST_REQ;
1395 plci->appl = appl;
1396 sig_req(plci,LISTEN_REQ,0);
1397 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001398 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 }
1400 }
1401 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001402 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 }
1404 plci->Id = 0;
1405 }
1406 }
1407 sendf(appl,
1408 _CONNECT_R|CONFIRM,
1409 Id,
1410 Number,
1411 "w",Info);
1412 return 2;
1413}
1414
1415byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1416{
1417 word i, Info;
1418 word Reject;
1419 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1420 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1421 API_PARSE * ai;
1422 API_PARSE ai_parms[5];
1423 word ch=0;
1424
1425 if(!plci) {
1426 dbug(1,dprintf("connect_res(no plci)"));
1427 return 0; /* no plci, no send */
1428 }
1429
1430 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1431 for(i=0;i<5;i++) ai_parms[i].length = 0;
1432 ai = &parms[5];
1433 dbug(1,dprintf("ai->length=%d",ai->length));
1434
1435 if(ai->length)
1436 {
1437 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1438 {
1439 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1440 ch = 0;
1441 if(ai_parms[0].length)
1442 {
1443 ch = GET_WORD(ai_parms[0].info+1);
1444 dbug(1,dprintf("BCH-I=0x%x",ch));
1445 }
1446 }
1447 }
1448
1449 if(plci->State==INC_CON_CONNECTED_ALERT)
1450 {
1451 dbug(1,dprintf("Connected Alert Call_Res"));
1452 if (a->Info_Mask[appl->Id-1] & 0x200)
1453 {
1454 /* early B3 connect (CIP mask bit 9) no release after a disc */
1455 add_p(plci,LLI,"\x01\x01");
1456 }
1457 add_s(plci, CONN_NR, &parms[2]);
1458 add_s(plci, LLC, &parms[4]);
1459 add_ai(plci, &parms[5]);
1460 plci->State = INC_CON_ACCEPT;
1461 sig_req(plci, CALL_RES,0);
1462 return 1;
1463 }
1464 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1465 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1466 dump_c_ind_mask (plci);
1467 Reject = GET_WORD(parms[0].info);
1468 dbug(1,dprintf("Reject=0x%x",Reject));
1469 if(Reject)
1470 {
1471 if(c_ind_mask_empty (plci))
1472 {
1473 if((Reject&0xff00)==0x3400)
1474 {
1475 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1476 add_p(plci,ESC,esc_t);
1477 add_ai(plci, &parms[5]);
1478 sig_req(plci,REJECT,0);
1479 }
1480 else if(Reject==1 || Reject>9)
1481 {
1482 add_ai(plci, &parms[5]);
1483 sig_req(plci,HANGUP,0);
1484 }
1485 else
1486 {
1487 esc_t[2] = cau_t[(Reject&0x000f)];
1488 add_p(plci,ESC,esc_t);
1489 add_ai(plci, &parms[5]);
1490 sig_req(plci,REJECT,0);
1491 }
1492 plci->appl = appl;
1493 }
1494 else
1495 {
1496 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1497 }
1498 }
1499 else {
1500 plci->appl = appl;
1501 if(Id & EXT_CONTROLLER){
1502 if(AdvCodecSupport(a, plci, appl, 0)){
1503 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1504 sig_req(plci,HANGUP,0);
1505 return 1;
1506 }
1507 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508 {
1509 Info = add_b23(plci, &parms[1]);
1510 if (Info)
1511 {
1512 dbug(1,dprintf("connect_res(error from add_b23)"));
1513 sig_req(plci,HANGUP,0);
1514 return 1;
1515 }
1516 if(plci->adv_nl)
1517 {
1518 nl_req_ncci(plci, ASSIGN, 0);
1519 }
1520 }
1521 }
1522 else
1523 {
1524 plci->tel = 0;
1525 if(ch!=2)
1526 {
1527 Info = add_b23(plci, &parms[1]);
1528 if (Info)
1529 {
1530 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1531 sig_req(plci,HANGUP,0);
1532 return 1;
1533 }
1534 }
1535 nl_req_ncci(plci, ASSIGN, 0);
1536 }
1537
1538 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1539 {
1540 api_save_msg(parms, "wsssss", &plci->saved_msg);
1541 plci->spoofed_msg = CALL_RES;
1542 plci->internal_command = BLOCK_PLCI;
1543 plci->command = 0;
1544 dbug(1,dprintf("Spoof"));
1545 }
1546 else
1547 {
1548 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1549 if (a->Info_Mask[appl->Id-1] & 0x200)
1550 {
1551 /* early B3 connect (CIP mask bit 9) no release after a disc */
1552 add_p(plci,LLI,"\x01\x01");
1553 }
1554 add_s(plci, CONN_NR, &parms[2]);
1555 add_s(plci, LLC, &parms[4]);
1556 add_ai(plci, &parms[5]);
1557 plci->State = INC_CON_ACCEPT;
1558 sig_req(plci, CALL_RES,0);
1559 }
1560
1561 for(i=0; i<max_appl; i++) {
1562 if(test_c_ind_mask_bit (plci, i)) {
1563 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1564 }
1565 }
1566 }
1567 }
1568 return 1;
1569}
1570
1571byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1572{
1573 dbug(1,dprintf("connect_a_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001574 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575}
1576
1577byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1578{
1579 word Info;
1580 word i;
1581
1582 dbug(1,dprintf("disconnect_req"));
1583
1584 Info = _WRONG_IDENTIFIER;
1585
1586 if(plci)
1587 {
1588 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1589 {
1590 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1591 plci->appl = appl;
1592 for(i=0; i<max_appl; i++)
1593 {
1594 if(test_c_ind_mask_bit (plci, i))
1595 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596 }
1597 plci->State = OUTG_DIS_PENDING;
1598 }
1599 if(plci->Sig.Id && plci->appl)
1600 {
1601 Info = 0;
1602 if(plci->Sig.Id!=0xff)
1603 {
1604 if(plci->State!=INC_DIS_PENDING)
1605 {
1606 add_ai(plci, &msg[0]);
1607 sig_req(plci,HANGUP,0);
1608 plci->State = OUTG_DIS_PENDING;
1609 return 1;
1610 }
1611 }
1612 else
1613 {
1614 if (plci->NL.Id && !plci->nl_remove_id)
1615 {
1616 mixer_remove (plci);
1617 nl_req_ncci(plci,REMOVE,0);
1618 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1619 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1620 plci->State = INC_DIS_PENDING;
1621 }
1622 return 1;
1623 }
1624 }
1625 }
1626
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001627 if(!appl) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001629 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630}
1631
1632byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, 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
1659byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1660{
1661 word Info;
1662 byte i;
1663
1664 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1665
1666 Info = _WRONG_IDENTIFIER;
1667 if(a) {
1668 Info = 0;
1669 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1670 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1671 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1672 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1673 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1674 }
1675
1676 /* check if external controller listen and switch listen on or off*/
1677 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1678 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1679 dummy_plci.State = IDLE;
1680 a->codec_listen[appl->Id-1] = &dummy_plci;
1681 a->TelOAD[0] = (byte)(parms[3].length);
1682 for(i=1;parms[3].length>=i && i<22;i++) {
1683 a->TelOAD[i] = parms[3].info[i];
1684 }
1685 a->TelOAD[i] = 0;
1686 a->TelOSA[0] = (byte)(parms[4].length);
1687 for(i=1;parms[4].length>=i && i<22;i++) {
1688 a->TelOSA[i] = parms[4].info[i];
1689 }
1690 a->TelOSA[i] = 0;
1691 }
1692 else Info = 0x2002; /* wrong controller, codec not supported */
1693 }
1694 else{ /* clear listen */
1695 a->codec_listen[appl->Id-1] = (PLCI *)0;
1696 }
1697 }
1698 sendf(appl,
1699 _LISTEN_R|CONFIRM,
1700 Id,
1701 Number,
1702 "w",Info);
1703
1704 if (a) listen_check(a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001705 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706}
1707
1708byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1709{
1710 word i;
1711 API_PARSE * ai;
1712 PLCI * rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1714 word Info = 0;
1715
1716 dbug(1,dprintf("info_req"));
1717 for(i=0;i<5;i++) ai_parms[i].length = 0;
1718
1719 ai = &msg[1];
1720
1721 if(ai->length)
1722 {
1723 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1724 {
1725 dbug(1,dprintf("AddInfo wrong"));
1726 Info = _WRONG_MESSAGE_FORMAT;
1727 }
1728 }
1729 if(!a) Info = _WRONG_STATE;
1730
1731 if(!Info && plci)
1732 { /* no fac, with CPN, or KEY */
1733 rc_plci = plci;
1734 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1735 {
1736 /* overlap sending option */
1737 dbug(1,dprintf("OvlSnd"));
1738 add_s(plci,CPN,&msg[0]);
1739 add_s(plci,KEY,&ai_parms[1]);
1740 sig_req(plci,INFO_REQ,0);
1741 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001742 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 }
1744
1745 if(plci->State && ai_parms[2].length)
1746 {
1747 /* User_Info option */
1748 dbug(1,dprintf("UUI"));
1749 add_s(plci,UUI,&ai_parms[2]);
1750 sig_req(plci,USER_DATA,0);
1751 }
1752 else if(plci->State && ai_parms[3].length)
1753 {
1754 /* Facility option */
1755 dbug(1,dprintf("FAC"));
1756 add_s(plci,CPN,&msg[0]);
1757 add_ai(plci, &msg[1]);
1758 sig_req(plci,FACILITY_REQ,0);
1759 }
1760 else
1761 {
1762 Info = _WRONG_STATE;
1763 }
1764 }
1765 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766 {
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1,dprintf("NCR_FAC"));
1769 if((i=get_plci(a)))
1770 {
1771 rc_plci = &a->plci[i-1];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001772 appl->NullCREnable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 rc_plci->internal_command = C_NCR_FAC_REQ;
1774 rc_plci->appl = appl;
1775 add_p(rc_plci,CAI,"\x01\x80");
1776 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci,ASSIGN,DSIG_ID);
1778 send_req(rc_plci);
1779 }
1780 else
1781 {
1782 Info = _OUT_OF_PLCI;
1783 }
1784
1785 if(!Info)
1786 {
1787 add_s(rc_plci,CPN,&msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci,NCR_FACILITY,0);
1790 send_req(rc_plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001791 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 /* for application controlled supplementary services */
1793 }
1794 }
1795
1796 if (!rc_plci)
1797 {
1798 Info = _WRONG_MESSAGE_FORMAT;
1799 }
1800
1801 if(!Info)
1802 {
1803 send_req(rc_plci);
1804 }
1805 else
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1,dprintf("localInfoCon"));
1808 sendf(appl,
1809 _INFO_R|CONFIRM,
1810 Id,
1811 Number,
1812 "w",Info);
1813 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001814 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815}
1816
1817byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1818{
1819 dbug(1,dprintf("info_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001820 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821}
1822
1823byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1824{
1825 word Info;
1826 byte ret;
1827
1828 dbug(1,dprintf("alert_req"));
1829
1830 Info = _WRONG_IDENTIFIER;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001831 ret = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 if(plci) {
1833 Info = _ALERT_IGNORED;
1834 if(plci->State!=INC_CON_ALERT) {
1835 Info = _WRONG_STATE;
1836 if(plci->State==INC_CON_PENDING) {
1837 Info = 0;
1838 plci->State=INC_CON_ALERT;
1839 add_ai(plci, &msg[0]);
1840 sig_req(plci,CALL_ALERT,0);
1841 ret = 1;
1842 }
1843 }
1844 }
1845 sendf(appl,
1846 _ALERT_R|CONFIRM,
1847 Id,
1848 Number,
1849 "w",Info);
1850 return ret;
1851}
1852
1853byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1854{
1855 word Info = 0;
1856 word i = 0;
1857
1858 word selector;
1859 word SSreq;
1860 long relatedPLCIvalue;
1861 DIVA_CAPI_ADAPTER * relatedadapter;
1862 byte * SSparms = "";
1863 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1864 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1865 API_PARSE * parms;
1866 API_PARSE ss_parms[11];
1867 PLCI *rplci;
1868 byte cai[15];
1869 dword d;
1870 API_PARSE dummy;
1871
1872 dbug(1,dprintf("facility_req"));
1873 for(i=0;i<9;i++) ss_parms[i].length = 0;
1874
1875 parms = &msg[1];
1876
1877 if(!a)
1878 {
1879 dbug(1,dprintf("wrong Ctrl"));
1880 Info = _WRONG_IDENTIFIER;
1881 }
1882
1883 selector = GET_WORD(msg[0].info);
1884
1885 if(!Info)
1886 {
1887 switch(selector)
1888 {
1889 case SELECTOR_HANDSET:
1890 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1891 break;
1892
1893 case SELECTOR_SU_SERV:
1894 if(!msg[1].length)
1895 {
1896 Info = _WRONG_MESSAGE_FORMAT;
1897 break;
1898 }
1899 SSreq = GET_WORD(&(msg[1].info[1]));
1900 PUT_WORD(&RCparms[1],SSreq);
1901 SSparms = RCparms;
1902 switch(SSreq)
1903 {
1904 case S_GET_SUPPORTED_SERVICES:
1905 if((i=get_plci(a)))
1906 {
1907 rplci = &a->plci[i-1];
1908 rplci->appl = appl;
1909 add_p(rplci,CAI,"\x01\x80");
1910 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1911 sig_req(rplci,ASSIGN,DSIG_ID);
1912 send_req(rplci);
1913 }
1914 else
1915 {
1916 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1917 SSparms = (byte *)SSstruct;
1918 break;
1919 }
1920 rplci->internal_command = GETSERV_REQ_PEND;
1921 rplci->number = Number;
1922 rplci->appl = appl;
1923 sig_req(rplci,S_SUPPORTED,0);
1924 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001925 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 break;
1927
1928 case S_LISTEN:
1929 if(parms->length==7)
1930 {
1931 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1932 {
1933 dbug(1,dprintf("format wrong"));
1934 Info = _WRONG_MESSAGE_FORMAT;
1935 break;
1936 }
1937 }
1938 else
1939 {
1940 Info = _WRONG_MESSAGE_FORMAT;
1941 break;
1942 }
1943 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1944 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1945 {
1946 if((i=get_plci(a)))
1947 {
1948 rplci = &a->plci[i-1];
1949 rplci->appl = appl;
1950 add_p(rplci,CAI,"\x01\x80");
1951 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1952 sig_req(rplci,ASSIGN,DSIG_ID);
1953 send_req(rplci);
1954 }
1955 else
1956 {
1957 break;
1958 }
1959 rplci->internal_command = GET_MWI_STATE;
1960 rplci->number = Number;
1961 sig_req(rplci,MWI_POLL,0);
1962 send_req(rplci);
1963 }
1964 break;
1965
1966 case S_HOLD:
1967 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1968 if(plci && plci->State && plci->SuppState==IDLE)
1969 {
1970 plci->SuppState = HOLD_REQUEST;
1971 plci->command = C_HOLD_REQ;
1972 add_s(plci,CAI,&ss_parms[1]);
1973 sig_req(plci,CALL_HOLD,0);
1974 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001975 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 }
1977 else Info = 0x3010; /* wrong state */
1978 break;
1979 case S_RETRIEVE:
1980 if(plci && plci->State && plci->SuppState==CALL_HELD)
1981 {
1982 if(Id & EXT_CONTROLLER)
1983 {
1984 if(AdvCodecSupport(a, plci, appl, 0))
1985 {
1986 Info = 0x3010; /* wrong state */
1987 break;
1988 }
1989 }
1990 else plci->tel = 0;
1991
1992 plci->SuppState = RETRIEVE_REQUEST;
1993 plci->command = C_RETRIEVE_REQ;
1994 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1995 {
1996 plci->spoofed_msg = CALL_RETRIEVE;
1997 plci->internal_command = BLOCK_PLCI;
1998 plci->command = 0;
1999 dbug(1,dprintf("Spoof"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002000 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 }
2002 else
2003 {
2004 sig_req(plci,CALL_RETRIEVE,0);
2005 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002006 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 }
2008 }
2009 else Info = 0x3010; /* wrong state */
2010 break;
2011 case S_SUSPEND:
2012 if(parms->length)
2013 {
2014 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2015 {
2016 dbug(1,dprintf("format wrong"));
2017 Info = _WRONG_MESSAGE_FORMAT;
2018 break;
2019 }
2020 }
2021 if(plci && plci->State)
2022 {
2023 add_s(plci,CAI,&ss_parms[2]);
2024 plci->command = SUSPEND_REQ;
2025 sig_req(plci,SUSPEND,0);
2026 plci->State = SUSPENDING;
2027 send_req(plci);
2028 }
2029 else Info = 0x3010; /* wrong state */
2030 break;
2031
2032 case S_RESUME:
2033 if(!(i=get_plci(a)) )
2034 {
2035 Info = _OUT_OF_PLCI;
2036 break;
2037 }
2038 rplci = &a->plci[i-1];
2039 rplci->appl = appl;
2040 rplci->number = Number;
2041 rplci->tel = 0;
2042 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2043 /* check 'external controller' bit for codec support */
2044 if(Id & EXT_CONTROLLER)
2045 {
2046 if(AdvCodecSupport(a, rplci, appl, 0) )
2047 {
2048 rplci->Id = 0;
2049 Info = 0x300A;
2050 break;
2051 }
2052 }
2053 if(parms->length)
2054 {
2055 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2056 {
2057 dbug(1,dprintf("format wrong"));
2058 rplci->Id = 0;
2059 Info = _WRONG_MESSAGE_FORMAT;
2060 break;
2061 }
2062 }
2063 dummy.length = 0;
2064 dummy.info = "\x00";
2065 add_b1(rplci, &dummy, 0, 0);
2066 if (a->Info_Mask[appl->Id-1] & 0x200)
2067 {
2068 /* early B3 connect (CIP mask bit 9) no release after a disc */
2069 add_p(rplci,LLI,"\x01\x01");
2070 }
2071 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2072 sig_req(rplci,ASSIGN,DSIG_ID);
2073 send_req(rplci);
2074 add_s(rplci,CAI,&ss_parms[2]);
2075 rplci->command = RESUME_REQ;
2076 sig_req(rplci,RESUME,0);
2077 rplci->State = RESUMING;
2078 send_req(rplci);
2079 break;
2080
2081 case S_CONF_BEGIN: /* Request */
2082 case S_CONF_DROP:
2083 case S_CONF_ISOLATE:
2084 case S_CONF_REATTACH:
2085 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2086 {
2087 dbug(1,dprintf("format wrong"));
2088 Info = _WRONG_MESSAGE_FORMAT;
2089 break;
2090 }
2091 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2092 {
2093 d = GET_DWORD(ss_parms[2].info);
2094 if(d>=0x80)
2095 {
2096 dbug(1,dprintf("format wrong"));
2097 Info = _WRONG_MESSAGE_FORMAT;
2098 break;
2099 }
2100 plci->ptyState = (byte)SSreq;
2101 plci->command = 0;
2102 cai[0] = 2;
2103 switch(SSreq)
2104 {
2105 case S_CONF_BEGIN:
2106 cai[1] = CONF_BEGIN;
2107 plci->internal_command = CONF_BEGIN_REQ_PEND;
2108 break;
2109 case S_CONF_DROP:
2110 cai[1] = CONF_DROP;
2111 plci->internal_command = CONF_DROP_REQ_PEND;
2112 break;
2113 case S_CONF_ISOLATE:
2114 cai[1] = CONF_ISOLATE;
2115 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2116 break;
2117 case S_CONF_REATTACH:
2118 cai[1] = CONF_REATTACH;
2119 plci->internal_command = CONF_REATTACH_REQ_PEND;
2120 break;
2121 }
2122 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2123 add_p(plci,CAI,cai);
2124 sig_req(plci,S_SERVICE,0);
2125 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002126 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 }
2128 else Info = 0x3010; /* wrong state */
2129 break;
2130
2131 case S_ECT:
2132 case S_3PTY_BEGIN:
2133 case S_3PTY_END:
2134 case S_CONF_ADD:
2135 if(parms->length==7)
2136 {
2137 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2138 {
2139 dbug(1,dprintf("format wrong"));
2140 Info = _WRONG_MESSAGE_FORMAT;
2141 break;
2142 }
2143 }
2144 else if(parms->length==8) /* workaround for the T-View-S */
2145 {
2146 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2147 {
2148 dbug(1,dprintf("format wrong"));
2149 Info = _WRONG_MESSAGE_FORMAT;
2150 break;
2151 }
2152 }
2153 else
2154 {
2155 Info = _WRONG_MESSAGE_FORMAT;
2156 break;
2157 }
2158 if(!msg[1].length)
2159 {
2160 Info = _WRONG_MESSAGE_FORMAT;
2161 break;
2162 }
2163 if (!plci)
2164 {
2165 Info = _WRONG_IDENTIFIER;
2166 break;
2167 }
2168 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2169 relatedPLCIvalue &= 0x0000FFFF;
2170 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2171 /* controller starts with 0 up to (max_adapter - 1) */
2172 if (((relatedPLCIvalue & 0x7f) == 0)
2173 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2174 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2175 {
2176 if(SSreq==S_3PTY_END)
2177 {
2178 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2179 rplci = plci;
2180 }
2181 else
2182 {
2183 Info = 0x3010; /* wrong state */
2184 break;
2185 }
2186 }
2187 else
2188 {
2189 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2190 relatedPLCIvalue >>=8;
2191 /* find PLCI PTR*/
2192 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2193 {
2194 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2195 {
2196 rplci = &relatedadapter->plci[i];
2197 }
2198 }
2199 if(!rplci || !relatedPLCIvalue)
2200 {
2201 if(SSreq==S_3PTY_END)
2202 {
2203 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2204 rplci = plci;
2205 }
2206 else
2207 {
2208 Info = 0x3010; /* wrong state */
2209 break;
2210 }
2211 }
2212 }
2213/*
2214 dbug(1,dprintf("rplci:%x",rplci));
2215 dbug(1,dprintf("plci:%x",plci));
2216 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2217 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2218 dbug(1,dprintf("SSreq:%x",SSreq));
2219 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2220 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2221 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2222*/
2223 /* send PTY/ECT req, cannot check all states because of US stuff */
2224 if( !rplci->internal_command && rplci->appl )
2225 {
2226 plci->command = 0;
2227 rplci->relatedPTYPLCI = plci;
2228 plci->relatedPTYPLCI = rplci;
2229 rplci->ptyState = (byte)SSreq;
2230 if(SSreq==S_ECT)
2231 {
2232 rplci->internal_command = ECT_REQ_PEND;
2233 cai[1] = ECT_EXECUTE;
2234
2235 rplci->vswitchstate=0;
2236 rplci->vsprot=0;
2237 rplci->vsprotdialect=0;
2238 plci->vswitchstate=0;
2239 plci->vsprot=0;
2240 plci->vsprotdialect=0;
2241
2242 }
2243 else if(SSreq==S_CONF_ADD)
2244 {
2245 rplci->internal_command = CONF_ADD_REQ_PEND;
2246 cai[1] = CONF_ADD;
2247 }
2248 else
2249 {
2250 rplci->internal_command = PTY_REQ_PEND;
2251 cai[1] = (byte)(SSreq-3);
2252 }
2253 rplci->number = Number;
2254 if(plci!=rplci) /* explicit invocation */
2255 {
2256 cai[0] = 2;
2257 cai[2] = plci->Sig.Id;
2258 dbug(1,dprintf("explicit invocation"));
2259 }
2260 else
2261 {
2262 dbug(1,dprintf("implicit invocation"));
2263 cai[0] = 1;
2264 }
2265 add_p(rplci,CAI,cai);
2266 sig_req(rplci,S_SERVICE,0);
2267 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002268 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 }
2270 else
2271 {
2272 dbug(0,dprintf("Wrong line"));
2273 Info = 0x3010; /* wrong state */
2274 break;
2275 }
2276 break;
2277
2278 case S_CALL_DEFLECTION:
2279 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2280 {
2281 dbug(1,dprintf("format wrong"));
2282 Info = _WRONG_MESSAGE_FORMAT;
2283 break;
2284 }
2285 if (!plci)
2286 {
2287 Info = _WRONG_IDENTIFIER;
2288 break;
2289 }
2290 /* reuse unused screening indicator */
2291 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2292 plci->command = 0;
2293 plci->internal_command = CD_REQ_PEND;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002294 appl->CDEnable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 cai[0] = 1;
2296 cai[1] = CALL_DEFLECTION;
2297 add_p(plci,CAI,cai);
2298 add_p(plci,CPN,ss_parms[3].info);
2299 sig_req(plci,S_SERVICE,0);
2300 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002301 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 break;
2303
2304 case S_CALL_FORWARDING_START:
2305 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2306 {
2307 dbug(1,dprintf("format wrong"));
2308 Info = _WRONG_MESSAGE_FORMAT;
2309 break;
2310 }
2311
2312 if((i=get_plci(a)))
2313 {
2314 rplci = &a->plci[i-1];
2315 rplci->appl = appl;
2316 add_p(rplci,CAI,"\x01\x80");
2317 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2318 sig_req(rplci,ASSIGN,DSIG_ID);
2319 send_req(rplci);
2320 }
2321 else
2322 {
2323 Info = _OUT_OF_PLCI;
2324 break;
2325 }
2326
2327 /* reuse unused screening indicator */
2328 rplci->internal_command = CF_START_PEND;
2329 rplci->appl = appl;
2330 rplci->number = Number;
2331 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2332 cai[0] = 2;
2333 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2334 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2335 add_p(rplci,CAI,cai);
2336 add_p(rplci,OAD,ss_parms[5].info);
2337 add_p(rplci,CPN,ss_parms[6].info);
2338 sig_req(rplci,S_SERVICE,0);
2339 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002340 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 break;
2342
2343 case S_INTERROGATE_DIVERSION:
2344 case S_INTERROGATE_NUMBERS:
2345 case S_CALL_FORWARDING_STOP:
2346 case S_CCBS_REQUEST:
2347 case S_CCBS_DEACTIVATE:
2348 case S_CCBS_INTERROGATE:
2349 switch(SSreq)
2350 {
2351 case S_INTERROGATE_NUMBERS:
2352 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2353 {
2354 dbug(0,dprintf("format wrong"));
2355 Info = _WRONG_MESSAGE_FORMAT;
2356 }
2357 break;
2358 case S_CCBS_REQUEST:
2359 case S_CCBS_DEACTIVATE:
2360 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2361 {
2362 dbug(0,dprintf("format wrong"));
2363 Info = _WRONG_MESSAGE_FORMAT;
2364 }
2365 break;
2366 case S_CCBS_INTERROGATE:
2367 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2368 {
2369 dbug(0,dprintf("format wrong"));
2370 Info = _WRONG_MESSAGE_FORMAT;
2371 }
2372 break;
2373 default:
2374 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2375 {
2376 dbug(0,dprintf("format wrong"));
2377 Info = _WRONG_MESSAGE_FORMAT;
2378 break;
2379 }
2380 break;
2381 }
2382
2383 if(Info) break;
2384 if((i=get_plci(a)))
2385 {
2386 rplci = &a->plci[i-1];
2387 switch(SSreq)
2388 {
2389 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2390 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2391 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2392 break;
2393 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2394 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2395 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2396 break;
2397 case S_CALL_FORWARDING_STOP:
2398 rplci->internal_command = CF_STOP_PEND;
2399 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400 break;
2401 case S_CCBS_REQUEST:
2402 cai[1] = CCBS_REQUEST;
2403 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2404 break;
2405 case S_CCBS_DEACTIVATE:
2406 cai[1] = CCBS_DEACTIVATE;
2407 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2408 break;
2409 case S_CCBS_INTERROGATE:
2410 cai[1] = CCBS_INTERROGATE;
2411 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2412 break;
2413 default:
2414 cai[1] = 0;
2415 break;
2416 }
2417 rplci->appl = appl;
2418 rplci->number = Number;
2419 add_p(rplci,CAI,"\x01\x80");
2420 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2421 sig_req(rplci,ASSIGN,DSIG_ID);
2422 send_req(rplci);
2423 }
2424 else
2425 {
2426 Info = _OUT_OF_PLCI;
2427 break;
2428 }
2429
2430 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2431 switch(SSreq)
2432 {
2433 case S_INTERROGATE_NUMBERS:
2434 cai[0] = 1;
2435 add_p(rplci,CAI,cai);
2436 break;
2437 case S_CCBS_REQUEST:
2438 case S_CCBS_DEACTIVATE:
2439 cai[0] = 3;
2440 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2441 add_p(rplci,CAI,cai);
2442 break;
2443 case S_CCBS_INTERROGATE:
2444 cai[0] = 3;
2445 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2446 add_p(rplci,CAI,cai);
2447 add_p(rplci,OAD,ss_parms[4].info);
2448 break;
2449 default:
2450 cai[0] = 2;
2451 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2452 add_p(rplci,CAI,cai);
2453 add_p(rplci,OAD,ss_parms[5].info);
2454 break;
2455 }
2456
2457 sig_req(rplci,S_SERVICE,0);
2458 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002459 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 break;
2461
2462 case S_MWI_ACTIVATE:
2463 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2464 {
2465 dbug(1,dprintf("format wrong"));
2466 Info = _WRONG_MESSAGE_FORMAT;
2467 break;
2468 }
2469 if(!plci)
2470 {
2471 if((i=get_plci(a)))
2472 {
2473 rplci = &a->plci[i-1];
2474 rplci->appl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002475 rplci->cr_enquiry=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 add_p(rplci,CAI,"\x01\x80");
2477 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2478 sig_req(rplci,ASSIGN,DSIG_ID);
2479 send_req(rplci);
2480 }
2481 else
2482 {
2483 Info = _OUT_OF_PLCI;
2484 break;
2485 }
2486 }
2487 else
2488 {
2489 rplci = plci;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002490 rplci->cr_enquiry=false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 }
2492
2493 rplci->command = 0;
2494 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2495 rplci->appl = appl;
2496 rplci->number = Number;
2497
2498 cai[0] = 13;
2499 cai[1] = ACTIVATION_MWI; /* Function */
2500 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2501 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2502 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2503 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2504 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2505 add_p(rplci,CAI,cai);
2506 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2507 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2508 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2509 add_p(rplci,UID,ss_parms[10].info); /* Time */
2510 sig_req(rplci,S_SERVICE,0);
2511 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002512 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
2514 case S_MWI_DEACTIVATE:
2515 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2516 {
2517 dbug(1,dprintf("format wrong"));
2518 Info = _WRONG_MESSAGE_FORMAT;
2519 break;
2520 }
2521 if(!plci)
2522 {
2523 if((i=get_plci(a)))
2524 {
2525 rplci = &a->plci[i-1];
2526 rplci->appl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002527 rplci->cr_enquiry=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 add_p(rplci,CAI,"\x01\x80");
2529 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2530 sig_req(rplci,ASSIGN,DSIG_ID);
2531 send_req(rplci);
2532 }
2533 else
2534 {
2535 Info = _OUT_OF_PLCI;
2536 break;
2537 }
2538 }
2539 else
2540 {
2541 rplci = plci;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002542 rplci->cr_enquiry=false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 }
2544
2545 rplci->command = 0;
2546 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2547 rplci->appl = appl;
2548 rplci->number = Number;
2549
2550 cai[0] = 5;
2551 cai[1] = DEACTIVATION_MWI; /* Function */
2552 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2553 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2554 add_p(rplci,CAI,cai);
2555 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2556 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2557 sig_req(rplci,S_SERVICE,0);
2558 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002559 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
2561 default:
2562 Info = 0x300E; /* not supported */
2563 break;
2564 }
2565 break; /* case SELECTOR_SU_SERV: end */
2566
2567
2568 case SELECTOR_DTMF:
2569 return (dtmf_request (Id, Number, a, plci, appl, msg));
2570
2571
2572
2573 case SELECTOR_LINE_INTERCONNECT:
2574 return (mixer_request (Id, Number, a, plci, appl, msg));
2575
2576
2577
2578 case PRIV_SELECTOR_ECHO_CANCELLER:
2579 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2580 return (ec_request (Id, Number, a, plci, appl, msg));
2581
2582 case SELECTOR_ECHO_CANCELLER:
2583 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2584 return (ec_request (Id, Number, a, plci, appl, msg));
2585
2586
2587 case SELECTOR_V42BIS:
2588 default:
2589 Info = _FACILITY_NOT_SUPPORTED;
2590 break;
2591 } /* end of switch(selector) */
2592 }
2593
2594 dbug(1,dprintf("SendFacRc"));
2595 sendf(appl,
2596 _FACILITY_R|CONFIRM,
2597 Id,
2598 Number,
2599 "wws",Info,selector,SSparms);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002600 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601}
2602
2603byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2604{
2605 dbug(1,dprintf("facility_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002606 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607}
2608
2609byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2610{
2611 word Info = 0;
2612 byte req;
2613 byte len;
2614 word w;
2615 word fax_control_bits, fax_feature_bits, fax_info_change;
2616 API_PARSE * ncpi;
2617 byte pvc[2];
2618
2619 API_PARSE fax_parms[9];
2620 word i;
2621
2622
2623 dbug(1,dprintf("connect_b3_req"));
2624 if(plci)
2625 {
2626 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2627 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2628 {
2629 Info = _WRONG_STATE;
2630 }
2631 else
2632 {
2633 /* local reply if assign unsuccessfull
2634 or B3 protocol allows only one layer 3 connection
2635 and already connected
2636 or B2 protocol not any LAPD
2637 and connect_b3_req contradicts originate/answer direction */
2638 if (!plci->NL.Id
2639 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2640 && ((plci->channels != 0)
2641 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2642 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2643 {
2644 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2645 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2646 Info = _WRONG_STATE;
2647 sendf(appl,
2648 _CONNECT_B3_R|CONFIRM,
2649 Id,
2650 Number,
2651 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002652 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 }
2654 plci->requested_options_conn = 0;
2655
2656 req = N_CONNECT;
2657 ncpi = &parms[0];
2658 if(plci->B3_prot==2 || plci->B3_prot==3)
2659 {
2660 if(ncpi->length>2)
2661 {
2662 /* check for PVC */
2663 if(ncpi->info[2] || ncpi->info[3])
2664 {
2665 pvc[0] = ncpi->info[3];
2666 pvc[1] = ncpi->info[2];
2667 add_d(plci,2,pvc);
2668 req = N_RESET;
2669 }
2670 else
2671 {
2672 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2673 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2674 }
2675 }
2676 }
2677 else if(plci->B3_prot==5)
2678 {
2679 if (plci->NL.Id && !plci->nl_remove_id)
2680 {
2681 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2682 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2683 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2684 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2685 {
2686 len = (byte)(&(((T30_INFO *) 0)->universal_6));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002687 fax_info_change = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 if (ncpi->length >= 4)
2689 {
2690 w = GET_WORD(&ncpi->info[3]);
2691 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2692 {
2693 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2694 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2695 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002696 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 }
2698 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2699 if (w & 0x0002) /* Fax-polling request */
2700 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2701 if ((w & 0x0004) /* Request to send / poll another document */
2702 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2703 {
2704 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2705 }
2706 if (ncpi->length >= 6)
2707 {
2708 w = GET_WORD(&ncpi->info[5]);
2709 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2710 {
2711 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002712 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 }
2714
2715 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2716 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2717 {
2718 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2719 }
2720 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2721 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2722 {
2723 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2724 }
2725 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2726 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2727 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2728 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2729 {
2730 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2731 Info = _WRONG_MESSAGE_FORMAT;
2732 else
2733 {
2734 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2735 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2736 {
2737 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2738 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2739 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2740 }
2741 w = fax_parms[4].length;
2742 if (w > 20)
2743 w = 20;
2744 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2745 for (i = 0; i < w; i++)
2746 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2747 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2748 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2749 w = fax_parms[5].length;
2750 if (w > 20)
2751 w = 20;
2752 plci->fax_connect_info_buffer[len++] = (byte) w;
2753 for (i = 0; i < w; i++)
2754 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2755 w = fax_parms[6].length;
2756 if (w > 20)
2757 w = 20;
2758 plci->fax_connect_info_buffer[len++] = (byte) w;
2759 for (i = 0; i < w; i++)
2760 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2761 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2762 & (1L << PRIVATE_FAX_NONSTANDARD))
2763 {
2764 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2765 {
2766 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2767 plci->fax_connect_info_buffer[len++] = 0;
2768 }
2769 else
2770 {
2771 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2772 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2773 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2774 for (i = 0; i < fax_parms[7].length; i++)
2775 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2776 }
2777 }
2778 }
2779 }
2780 else
2781 {
2782 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2783 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002784 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785
2786 }
2787 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2788 {
2789 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002790 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 }
2792 }
2793 if (Info == GOOD)
2794 {
2795 plci->fax_connect_info_length = len;
2796 if (fax_info_change)
2797 {
2798 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2799 {
2800 start_internal_command (Id, plci, fax_connect_info_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002801 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 }
2803 else
2804 {
2805 start_internal_command (Id, plci, fax_adjust_b23_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002806 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 }
2808 }
2809 }
2810 }
2811 else Info = _WRONG_STATE;
2812 }
2813 else Info = _WRONG_STATE;
2814 }
2815
2816 else if (plci->B3_prot == B3_RTP)
2817 {
2818 plci->internal_req_buffer[0] = ncpi->length + 1;
2819 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2820 for (w = 0; w < ncpi->length; w++)
2821 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2822 start_internal_command (Id, plci, rtp_connect_b3_req_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002823 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 }
2825
2826 if(!Info)
2827 {
2828 nl_req_ncci(plci,req,0);
2829 return 1;
2830 }
2831 }
2832 }
2833 else Info = _WRONG_IDENTIFIER;
2834
2835 sendf(appl,
2836 _CONNECT_B3_R|CONFIRM,
2837 Id,
2838 Number,
2839 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002840 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841}
2842
2843byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2844{
2845 word ncci;
2846 API_PARSE * ncpi;
2847 byte req;
2848
2849 word w;
2850
2851
2852 API_PARSE fax_parms[9];
2853 word i;
2854 byte len;
2855
2856
2857 dbug(1,dprintf("connect_b3_res"));
2858
2859 ncci = (word)(Id>>16);
2860 if(plci && ncci) {
2861 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2862 if (GET_WORD (&parms[0].info[0]) != 0)
2863 {
2864 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2865 channel_request_xon (plci, a->ncci_ch[ncci]);
2866 channel_xmit_xon (plci);
2867 cleanup_ncci_data (plci, ncci);
2868 nl_req_ncci(plci,N_DISC,(byte)ncci);
2869 return 1;
2870 }
2871 a->ncci_state[ncci] = INC_ACT_PENDING;
2872
2873 req = N_CONNECT_ACK;
2874 ncpi = &parms[1];
2875 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2876 {
2877
2878 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2879 & (1L << PRIVATE_FAX_NONSTANDARD))
2880 {
2881 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2882 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2883 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2884 {
2885 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2886 if (plci->fax_connect_info_length < len)
2887 {
2888 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2889 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2890 }
2891 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2892 {
2893 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2894 }
2895 else
2896 {
2897 if (plci->fax_connect_info_length <= len)
2898 plci->fax_connect_info_buffer[len] = 0;
2899 len += 1 + plci->fax_connect_info_buffer[len];
2900 if (plci->fax_connect_info_length <= len)
2901 plci->fax_connect_info_buffer[len] = 0;
2902 len += 1 + plci->fax_connect_info_buffer[len];
2903 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2904 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2905 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2906 for (i = 0; i < fax_parms[7].length; i++)
2907 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2908 }
2909 plci->fax_connect_info_length = len;
2910 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2911 start_internal_command (Id, plci, fax_connect_ack_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002912 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 }
2914 }
2915
2916 nl_req_ncci(plci,req,(byte)ncci);
2917 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2919 {
2920 if (plci->B3_prot == 4)
2921 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2922 else
2923 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2924 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2925 }
2926 }
2927
2928 else if (plci->B3_prot == B3_RTP)
2929 {
2930 plci->internal_req_buffer[0] = ncpi->length + 1;
2931 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2932 for (w = 0; w < ncpi->length; w++)
2933 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2934 start_internal_command (Id, plci, rtp_connect_b3_res_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002935 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 }
2937
2938 else
2939 {
2940 if(ncpi->length>2) {
2941 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2942 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2943 }
2944 nl_req_ncci(plci,req,(byte)ncci);
2945 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2946 if (plci->adjust_b_restore)
2947 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002948 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 start_internal_command (Id, plci, adjust_b_restore);
2950 }
2951 }
2952 return 1;
2953 }
2954 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002955 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956}
2957
2958byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2959{
2960 word ncci;
2961
2962 ncci = (word)(Id>>16);
2963 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2964
2965 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2966 && (plci->State != OUTG_DIS_PENDING))
2967 {
2968 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2969 a->ncci_state[ncci] = CONNECTED;
2970 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2971 channel_request_xon (plci, a->ncci_ch[ncci]);
2972 channel_xmit_xon (plci);
2973 }
2974 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002975 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976}
2977
2978byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2979{
2980 word Info;
2981 word ncci;
2982 API_PARSE * ncpi;
2983
2984 dbug(1,dprintf("disconnect_b3_req"));
2985
2986 Info = _WRONG_IDENTIFIER;
2987 ncci = (word)(Id>>16);
2988 if (plci && ncci)
2989 {
2990 Info = _WRONG_STATE;
2991 if ((a->ncci_state[ncci] == CONNECTED)
2992 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2993 || (a->ncci_state[ncci] == INC_CON_PENDING)
2994 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2995 {
2996 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2997 channel_request_xon (plci, a->ncci_ch[ncci]);
2998 channel_xmit_xon (plci);
2999
3000 if (a->ncci[ncci].data_pending
3001 && ((plci->B3_prot == B3_TRANSPARENT)
3002 || (plci->B3_prot == B3_T30)
3003 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3004 {
3005 plci->send_disc = (byte)ncci;
3006 plci->command = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003007 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 }
3009 else
3010 {
3011 cleanup_ncci_data (plci, ncci);
3012
3013 if(plci->B3_prot==2 || plci->B3_prot==3)
3014 {
3015 ncpi = &parms[0];
3016 if(ncpi->length>3)
3017 {
3018 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3019 }
3020 }
3021 nl_req_ncci(plci,N_DISC,(byte)ncci);
3022 }
3023 return 1;
3024 }
3025 }
3026 sendf(appl,
3027 _DISCONNECT_B3_R|CONFIRM,
3028 Id,
3029 Number,
3030 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003031 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032}
3033
3034byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3035{
3036 word ncci;
3037 word i;
3038
3039 ncci = (word)(Id>>16);
3040 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3041 if(plci && ncci) {
3042 plci->requested_options_conn = 0;
3043 plci->fax_connect_info_length = 0;
3044 plci->ncpi_state = 0x00;
3045 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3046 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3047 {
3048 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3049 }
3050 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3051 if(i<MAX_CHANNELS_PER_PLCI) {
3052 if(plci->channels)plci->channels--;
3053 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3054 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3055
3056 ncci_free_receive_buffers (plci, ncci);
3057
3058 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3059 if(plci->State == SUSPENDING){
3060 sendf(plci->appl,
3061 _FACILITY_I,
3062 Id & 0xffffL,
3063 0,
3064 "ws", (word)3, "\x03\x04\x00\x00");
3065 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3066 }
3067 plci_remove(plci);
3068 plci->State=IDLE;
3069 }
3070 }
3071 else
3072 {
3073 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3074 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3075 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3076 {
3077 ncci_free_receive_buffers (plci, ncci);
3078
3079 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3080
3081 plci->adapter->ncci_state[ncci] = IDLE;
3082 start_internal_command (Id, plci, fax_disconnect_command);
3083 return 1;
3084 }
3085 }
3086 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003087 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088}
3089
3090byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3091{
3092 NCCI *ncci_ptr;
3093 DATA_B3_DESC *data;
3094 word Info;
3095 word ncci;
3096 word i;
3097
3098 dbug(1,dprintf("data_b3_req"));
3099
3100 Info = _WRONG_IDENTIFIER;
3101 ncci = (word)(Id>>16);
3102 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3103
3104 if (plci && ncci)
3105 {
3106 Info = _WRONG_STATE;
3107 if ((a->ncci_state[ncci] == CONNECTED)
3108 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3109 {
3110 /* queue data */
3111 ncci_ptr = &(a->ncci[ncci]);
3112 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3113 if (i >= MAX_DATA_B3)
3114 i -= MAX_DATA_B3;
3115 data = &(ncci_ptr->DBuffer[i]);
3116 data->Number = Number;
3117 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3118 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3119 {
3120
3121 data->P = (byte *)(*((dword *)(parms[0].info)));
3122
3123 }
3124 else
3125 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3126 data->Length = GET_WORD(parms[1].info);
3127 data->Handle = GET_WORD(parms[2].info);
3128 data->Flags = GET_WORD(parms[3].info);
3129 (ncci_ptr->data_pending)++;
3130
3131 /* check for delivery confirmation */
3132 if (data->Flags & 0x0004)
3133 {
3134 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3135 if (i >= MAX_DATA_ACK)
3136 i -= MAX_DATA_ACK;
3137 ncci_ptr->DataAck[i].Number = data->Number;
3138 ncci_ptr->DataAck[i].Handle = data->Handle;
3139 (ncci_ptr->data_ack_pending)++;
3140 }
3141
3142 send_data(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003143 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 }
3145 }
3146 if (appl)
3147 {
3148 if (plci)
3149 {
3150 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3151 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3152 {
3153
3154 TransmitBufferFree (appl, (byte *)(*((dword *)(parms[0].info))));
3155
3156 }
3157 }
3158 sendf(appl,
3159 _DATA_B3_R|CONFIRM,
3160 Id,
3161 Number,
3162 "ww",GET_WORD(parms[2].info),Info);
3163 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003164 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165}
3166
3167byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3168{
3169 word n;
3170 word ncci;
3171 word NCCIcode;
3172
3173 dbug(1,dprintf("data_b3_res"));
3174
3175 ncci = (word)(Id>>16);
3176 if(plci && ncci) {
3177 n = GET_WORD(parms[0].info);
3178 dbug(1,dprintf("free(%d)",n));
3179 NCCIcode = ncci | (((word) a->Id) << 8);
3180 if(n<appl->MaxBuffer &&
3181 appl->DataNCCI[n]==NCCIcode &&
3182 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3183 dbug(1,dprintf("found"));
3184 appl->DataNCCI[n] = 0;
3185
3186 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3187 channel_request_xon (plci, a->ncci_ch[ncci]);
3188 }
3189 channel_xmit_xon (plci);
3190
3191 if(appl->DataFlags[n] &4) {
3192 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3193 return 1;
3194 }
3195 }
3196 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003197 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198}
3199
3200byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3201{
3202 word Info;
3203 word ncci;
3204
3205 dbug(1,dprintf("reset_b3_req"));
3206
3207 Info = _WRONG_IDENTIFIER;
3208 ncci = (word)(Id>>16);
3209 if(plci && ncci)
3210 {
3211 Info = _WRONG_STATE;
3212 switch (plci->B3_prot)
3213 {
3214 case B3_ISO8208:
3215 case B3_X25_DCE:
3216 if(a->ncci_state[ncci]==CONNECTED)
3217 {
3218 nl_req_ncci(plci,N_RESET,(byte)ncci);
3219 send_req(plci);
3220 Info = GOOD;
3221 }
3222 break;
3223 case B3_TRANSPARENT:
3224 if(a->ncci_state[ncci]==CONNECTED)
3225 {
3226 start_internal_command (Id, plci, reset_b3_command);
3227 Info = GOOD;
3228 }
3229 break;
3230 }
3231 }
3232 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3233 sendf(appl,
3234 _RESET_B3_R|CONFIRM,
3235 Id,
3236 Number,
3237 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003238 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239}
3240
3241byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3242{
3243 word ncci;
3244
3245 dbug(1,dprintf("reset_b3_res"));
3246
3247 ncci = (word)(Id>>16);
3248 if(plci && ncci) {
3249 switch (plci->B3_prot)
3250 {
3251 case B3_ISO8208:
3252 case B3_X25_DCE:
3253 if(a->ncci_state[ncci]==INC_RES_PENDING)
3254 {
3255 a->ncci_state[ncci] = CONNECTED;
3256 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003257 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 }
3259 break;
3260 }
3261 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003262 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263}
3264
3265byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3266{
3267 word ncci;
3268 API_PARSE * ncpi;
3269 byte req;
3270
3271 dbug(1,dprintf("connect_b3_t90_a_res"));
3272
3273 ncci = (word)(Id>>16);
3274 if(plci && ncci) {
3275 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3276 a->ncci_state[ncci] = CONNECTED;
3277 }
3278 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3279 a->ncci_state[ncci] = CONNECTED;
3280
3281 req = N_CONNECT_ACK;
3282
3283 /* parms[0]==0 for CAPI original message definition! */
3284 if(parms[0].info) {
3285 ncpi = &parms[1];
3286 if(ncpi->length>2) {
3287 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3288 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3289 }
3290 }
3291 nl_req_ncci(plci,req,(byte)ncci);
3292 return 1;
3293 }
3294 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003295 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296}
3297
3298
3299byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3300{
3301 word Info=0;
3302 word i;
3303 byte tel;
3304 API_PARSE bp_parms[7];
3305
3306 if(!plci || !msg)
3307 {
3308 Info = _WRONG_IDENTIFIER;
3309 }
3310 else
3311 {
3312 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3313 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3314 dbug(1,dprintf("PlciState=0x%x",plci->State));
3315 for(i=0;i<7;i++) bp_parms[i].length = 0;
3316
3317 /* check if no channel is open, no B3 connected only */
3318 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3319 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3320 {
3321 Info = _WRONG_STATE;
3322 }
3323 /* check message format and fill bp_parms pointer */
3324 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3325 {
3326 Info = _WRONG_MESSAGE_FORMAT;
3327 }
3328 else
3329 {
3330 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3331 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3332 if(Id & EXT_CONTROLLER)
3333 {
3334 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3335 return 0;
3336 }
3337 plci->State=INC_CON_CONNECTED_ALERT;
3338 plci->appl = appl;
3339 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3340 dump_c_ind_mask (plci);
3341 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3342 { /* its quasi a connect */
3343 if(test_c_ind_mask_bit (plci, i))
3344 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3345 }
3346 }
3347
3348 api_save_msg(msg, "s", &plci->saved_msg);
3349 tel = plci->tel;
3350 if(Id & EXT_CONTROLLER)
3351 {
3352 if(tel) /* external controller in use by this PLCI */
3353 {
3354 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3355 {
3356 dbug(1,dprintf("Ext_Ctrl in use 1"));
3357 Info = _WRONG_STATE;
3358 }
3359 }
3360 else /* external controller NOT in use by this PLCI ? */
3361 {
3362 if(a->AdvSignalPLCI)
3363 {
3364 dbug(1,dprintf("Ext_Ctrl in use 2"));
3365 Info = _WRONG_STATE;
3366 }
3367 else /* activate the codec */
3368 {
3369 dbug(1,dprintf("Ext_Ctrl start"));
3370 if(AdvCodecSupport(a, plci, appl, 0) )
3371 {
3372 dbug(1,dprintf("Error in codec procedures"));
3373 Info = _WRONG_STATE;
3374 }
3375 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3376 {
3377 plci->spoofed_msg = AWAITING_SELECT_B;
3378 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3379 plci->command = 0;
3380 dbug(1,dprintf("continue if codec loaded"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003381 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382 }
3383 }
3384 }
3385 }
3386 else /* external controller bit is OFF */
3387 {
3388 if(tel) /* external controller in use, need to switch off */
3389 {
3390 if(a->AdvSignalAppl==appl)
3391 {
3392 CodecIdCheck(a, plci);
3393 plci->tel = 0;
3394 plci->adv_nl = 0;
3395 dbug(1,dprintf("Ext_Ctrl disable"));
3396 }
3397 else
3398 {
3399 dbug(1,dprintf("Ext_Ctrl not requested"));
3400 }
3401 }
3402 }
3403 if (!Info)
3404 {
3405 if (plci->call_dir & CALL_DIR_OUT)
3406 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3407 else if (plci->call_dir & CALL_DIR_IN)
3408 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3409 start_internal_command (Id, plci, select_b_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003410 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 }
3412 }
3413 }
3414 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003415 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416}
3417
3418byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3419{
3420 word command;
3421 word i;
3422 word ncci;
3423 API_PARSE * m;
3424 API_PARSE m_parms[5];
3425 word codec;
3426 byte req;
3427 byte ch;
3428 byte dir;
3429 static byte chi[2] = {0x01,0x00};
3430 static byte lli[2] = {0x01,0x00};
3431 static byte codec_cai[2] = {0x01,0x01};
3432 static byte null_msg = {0};
3433 static API_PARSE null_parms = { 0, &null_msg };
3434 PLCI * v_plci;
3435 word Info=0;
3436
3437 dbug(1,dprintf("manufacturer_req"));
3438 for(i=0;i<5;i++) m_parms[i].length = 0;
3439
3440 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441 Info = _WRONG_MESSAGE_FORMAT;
3442 }
3443 command = GET_WORD(parms[1].info);
3444 m = &parms[2];
3445 if (!Info)
3446 {
3447 switch(command) {
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
3451 break;
3452 }
3453 codec = GET_WORD(m_parms[0].info);
3454 ch = m_parms[1].info[0];
3455 dir = m_parms[2].info[0];
3456 if((i=get_plci(a))) {
3457 plci = &a->plci[i-1];
3458 plci->appl = appl;
3459 plci->command = _MANUFACTURER_R;
3460 plci->m_command = command;
3461 plci->number = Number;
3462 plci->State = LOCAL_CONNECT;
3463 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3465
3466 if((ch==1 || ch==2) && (dir<=2)) {
3467 chi[1] = (byte)(0x80|ch);
3468 lli[1] = 0;
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470 switch(codec)
3471 {
3472 case 0:
3473 Info = add_b1(plci,&m_parms[3],0,0);
3474 break;
3475 case 1:
3476 add_p(plci,CAI,codec_cai);
3477 break;
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3480 case 2:
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3483 }
3484 else {
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3487 }
3488 break;
3489 }
3490
3491 plci->State = LOCAL_CONNECT;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003492 plci->manufacturer = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
3496
3497 if(!Info)
3498 {
3499 add_p(plci,LLI,lli);
3500 add_p(plci,CHI,chi);
3501 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502 sig_req(plci,ASSIGN,DSIG_ID);
3503
3504 if(!codec)
3505 {
3506 Info = add_b23(plci,&m_parms[3]);
3507 if(!Info)
3508 {
3509 nl_req_ncci(plci,ASSIGN,0);
3510 send_req(plci);
3511 }
3512 }
3513 if(!Info)
3514 {
3515 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3517 {
3518 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519 plci->spoofed_msg = AWAITING_MANUF_CON;
3520 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521 plci->command = 0;
3522 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003523 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 }
3525 if(dir==1) {
3526 sig_req(plci,CALL_REQ,0);
3527 }
3528 else if(!dir){
3529 sig_req(plci,LISTEN_REQ,0);
3530 }
3531 send_req(plci);
3532 }
3533 else
3534 {
3535 sendf(appl,
3536 _MANUFACTURER_R|CONFIRM,
3537 Id,
3538 Number,
3539 "dww",_DI_MANU_ID,command,Info);
3540 return 2;
3541 }
3542 }
3543 }
3544 }
3545 else Info = _OUT_OF_PLCI;
3546 break;
3547
3548 case _DI_IDI_CTRL:
3549 if(!plci)
3550 {
3551 Info = _WRONG_IDENTIFIER;
3552 break;
3553 }
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3556 break;
3557 }
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
3562 if(req==CALL_REQ)
3563 {
3564 plci->b_channel = getChannel(&m_parms[1]);
3565 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3567 {
3568 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570 plci->command = 0;
3571 break;
3572 }
3573 }
3574 else if(req==LAW_REQ)
3575 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003576 plci->cr_enquiry = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 }
3578 add_ss(plci,FTY,&m_parms[1]);
3579 sig_req(plci,req,0);
3580 send_req(plci);
3581 if(req==HANGUP)
3582 {
3583 if (plci->NL.Id && !plci->nl_remove_id)
3584 {
3585 if (plci->channels)
3586 {
3587 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3588 {
3589 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3590 {
3591 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592 cleanup_ncci_data (plci, ncci);
3593 nl_req_ncci(plci,N_DISC,(byte)ncci);
3594 }
3595 }
3596 }
3597 mixer_remove (plci);
3598 nl_req_ncci(plci,REMOVE,0);
3599 send_req(plci);
3600 }
3601 }
3602 break;
3603
3604 case _DI_SIG_CTRL:
3605 /* signalling control for loop activation B-channel */
3606 if(!plci)
3607 {
3608 Info = _WRONG_IDENTIFIER;
3609 break;
3610 }
3611 if(m->length){
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3614 add_ss(plci,FTY,m);
3615 sig_req(plci,SIG_CTRL,0);
3616 send_req(plci);
3617 }
3618 else Info = _WRONG_MESSAGE_FORMAT;
3619 break;
3620
3621 case _DI_RXT_CTRL:
3622 /* activation control for receiver/transmitter B-channel */
3623 if(!plci)
3624 {
3625 Info = _WRONG_IDENTIFIER;
3626 break;
3627 }
3628 if(m->length){
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3631 add_ss(plci,FTY,m);
3632 sig_req(plci,DSP_CTRL,0);
3633 send_req(plci);
3634 }
3635 else Info = _WRONG_MESSAGE_FORMAT;
3636 break;
3637
3638 case _DI_ADV_CODEC:
3639 case _DI_DSP_CTRL:
3640 /* TEL_CTRL commands to support non standard adjustments: */
3641 /* Ring on/off, Handset micro volume, external micro vol. */
3642 /* handset+external speaker volume, receiver+transm. gain,*/
3643 /* handsfree on (hookinfo off), set mixer command */
3644
3645 if(command == _DI_ADV_CODEC)
3646 {
3647 if(!a->AdvCodecPLCI) {
3648 Info = _WRONG_STATE;
3649 break;
3650 }
3651 v_plci = a->AdvCodecPLCI;
3652 }
3653 else
3654 {
3655 if (plci
3656 && (m->length >= 3)
3657 && (m->info[1] == 0x1c)
3658 && (m->info[2] >= 1))
3659 {
3660 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3661 {
3662 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3663 {
3664 Info = _WRONG_STATE;
3665 break;
3666 }
3667 a->adv_voice_coef_length = m->info[2] - 1;
3668 if (a->adv_voice_coef_length > m->length - 3)
3669 a->adv_voice_coef_length = (byte)(m->length - 3);
3670 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672 for (i = 0; i < a->adv_voice_coef_length; i++)
3673 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674 if (plci->B1_facilities & B1_FACILITY_VOICE)
3675 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676 break;
3677 }
3678 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3679 {
3680 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3681 {
3682 Info = _FACILITY_NOT_SUPPORTED;
3683 break;
3684 }
3685
3686 plci->dtmf_parameter_length = m->info[2] - 1;
3687 if (plci->dtmf_parameter_length > m->length - 3)
3688 plci->dtmf_parameter_length = (byte)(m->length - 3);
3689 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691 for (i = 0; i < plci->dtmf_parameter_length; i++)
3692 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694 dtmf_parameter_write (plci);
3695 break;
3696
3697 }
3698 }
3699 v_plci = plci;
3700 }
3701
3702 if(!v_plci)
3703 {
3704 Info = _WRONG_IDENTIFIER;
3705 break;
3706 }
3707 if(m->length){
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3710 send_req(v_plci);
3711 }
3712 else Info = _WRONG_MESSAGE_FORMAT;
3713
3714 break;
3715
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3719 break;
3720 }
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3722 {
3723 Info = _FACILITY_NOT_SUPPORTED;
3724 break;
3725 }
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727 break;
3728
3729
3730
3731 default:
3732 Info = _WRONG_MESSAGE_FORMAT;
3733 break;
3734 }
3735 }
3736
3737 sendf(appl,
3738 _MANUFACTURER_R|CONFIRM,
3739 Id,
3740 Number,
3741 "dww",_DI_MANU_ID,command,Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003742 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743}
3744
3745
3746byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3747{
3748 word indication;
3749
3750 API_PARSE m_parms[3];
3751 API_PARSE *ncpi;
3752 API_PARSE fax_parms[9];
3753 word i;
3754 byte len;
3755
3756
3757 dbug(1,dprintf("manufacturer_res"));
3758
3759 if ((msg[0].length == 0)
3760 || (msg[1].length == 0)
3761 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3762 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003763 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 }
3765 indication = GET_WORD(msg[1].info);
3766 switch (indication)
3767 {
3768
3769 case _DI_NEGOTIATE_B3:
3770 if(!plci)
3771 break;
3772 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3773 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3774 {
3775 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3776 break;
3777 }
3778 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3779 {
3780 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3781 break;
3782 }
3783 ncpi = &m_parms[1];
3784 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3785 if (plci->fax_connect_info_length < len)
3786 {
3787 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3788 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3789 }
3790 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3791 {
3792 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3793 }
3794 else
3795 {
3796 if (plci->fax_connect_info_length <= len)
3797 plci->fax_connect_info_buffer[len] = 0;
3798 len += 1 + plci->fax_connect_info_buffer[len];
3799 if (plci->fax_connect_info_length <= len)
3800 plci->fax_connect_info_buffer[len] = 0;
3801 len += 1 + plci->fax_connect_info_buffer[len];
3802 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3803 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3804 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3805 for (i = 0; i < fax_parms[7].length; i++)
3806 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3807 }
3808 plci->fax_connect_info_length = len;
3809 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3810 start_internal_command (Id, plci, fax_edata_ack_command);
3811 break;
3812
3813 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003814 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815}
3816
3817/*------------------------------------------------------------------*/
3818/* IDI callback function */
3819/*------------------------------------------------------------------*/
3820
3821void callback(ENTITY * e)
3822{
3823 DIVA_CAPI_ADAPTER * a;
3824 APPL * appl;
3825 PLCI * plci;
3826 CAPI_MSG *m;
3827 word i, j;
3828 byte rc;
3829 byte ch;
3830 byte req;
3831 byte global_req;
3832 int no_cancel_rc;
3833
3834 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3835 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3836
3837 a = &(adapter[(byte)e->user[0]]);
3838 plci = &(a->plci[e->user[1]]);
3839 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3840
3841 /*
3842 If new protocol code and new XDI is used then CAPI should work
3843 fully in accordance with IDI cpec an look on callback field instead
3844 of Rc field for return codes.
3845 */
3846 if (((e->complete == 0xff) && no_cancel_rc) ||
3847 (e->Rc && !no_cancel_rc)) {
3848 rc = e->Rc;
3849 ch = e->RcCh;
3850 req = e->Req;
3851 e->Rc = 0;
3852
3853 if (e->user[0] & 0x8000)
3854 {
3855 /*
3856 If REMOVE request was sent then we have to wait until
3857 return code with Id set to zero arrives.
3858 All other return codes should be ignored.
3859 */
3860 if (req == REMOVE)
3861 {
3862 if (e->Id)
3863 {
3864 dbug(1,dprintf("cancel RC in REMOVE state"));
3865 return;
3866 }
3867 channel_flow_control_remove (plci);
3868 for (i = 0; i < 256; i++)
3869 {
3870 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3871 a->FlowControlIdTable[i] = 0;
3872 }
3873 plci->nl_remove_id = 0;
3874 if (plci->rx_dma_descriptor > 0) {
3875 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3876 plci->rx_dma_descriptor = 0;
3877 }
3878 }
3879 if (rc == OK_FC)
3880 {
3881 a->FlowControlIdTable[ch] = e->Id;
3882 a->FlowControlSkipTable[ch] = 0;
3883
3884 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3885 a->ch_flow_plci[ch] = plci->Id;
3886 plci->nl_req = 0;
3887 }
3888 else
3889 {
3890 /*
3891 Cancel return codes self, if feature was requested
3892 */
3893 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3894 a->FlowControlIdTable[ch] = 0;
3895 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3896 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3897 return;
3898 }
3899 }
3900
3901 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3902 {
3903 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3904 if (ch == e->ReqCh)
3905 plci->nl_req = 0;
3906 }
3907 else
3908 plci->nl_req = 0;
3909 }
3910 if (plci->nl_req)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003911 control_rc (plci, 0, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 else
3913 {
3914 if (req == N_XON)
3915 {
3916 channel_x_on (plci, ch);
3917 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003918 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 }
3920 else
3921 {
3922 if (plci->nl_global_req)
3923 {
3924 global_req = plci->nl_global_req;
3925 plci->nl_global_req = 0;
3926 if (rc != ASSIGN_OK) {
3927 e->Id = 0;
3928 if (plci->rx_dma_descriptor > 0) {
3929 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3930 plci->rx_dma_descriptor = 0;
3931 }
3932 }
3933 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003934 control_rc (plci, 0, rc, ch, global_req, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 }
3936 else if (plci->data_sent)
3937 {
3938 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003939 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 plci->NL.XNum = 1;
3941 data_rc (plci, ch);
3942 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003943 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 }
3945 else
3946 {
3947 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003948 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 }
3950 }
3951 }
3952 }
3953 else
3954 {
3955 /*
3956 If REMOVE request was sent then we have to wait until
3957 return code with Id set to zero arrives.
3958 All other return codes should be ignored.
3959 */
3960 if (req == REMOVE)
3961 {
3962 if (e->Id)
3963 {
3964 dbug(1,dprintf("cancel RC in REMOVE state"));
3965 return;
3966 }
3967 plci->sig_remove_id = 0;
3968 }
3969 plci->sig_req = 0;
3970 if (plci->sig_global_req)
3971 {
3972 global_req = plci->sig_global_req;
3973 plci->sig_global_req = 0;
3974 if (rc != ASSIGN_OK)
3975 e->Id = 0;
3976 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003977 control_rc (plci, 0, rc, ch, global_req, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 }
3979 else
3980 {
3981 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003982 control_rc (plci, req, rc, ch, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 }
3984 }
3985 /*
3986 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3987 same callback. Also if new XDI and protocol code used then jump
3988 direct to finish.
3989 */
3990 if (no_cancel_rc) {
3991 channel_xmit_xon(plci);
3992 goto capi_callback_suffix;
3993 }
3994 }
3995
3996 channel_xmit_xon(plci);
3997
3998 if (e->Ind) {
3999 if (e->user[0] &0x8000) {
4000 byte Ind = e->Ind & 0x0f;
4001 byte Ch = e->IndCh;
4002 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4003 (a->ch_flow_plci[Ch] == plci->Id)) {
4004 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4005 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4006 }
4007 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4008 }
4009 nl_ind(plci);
4010 if ((e->RNR != 1) &&
4011 (a->ch_flow_plci[Ch] == plci->Id) &&
4012 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4013 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4014 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4015 }
4016 } else {
4017 sig_ind(plci);
4018 }
4019 e->Ind = 0;
4020 }
4021
4022capi_callback_suffix:
4023
4024 while (!plci->req_in
4025 && !plci->internal_command
4026 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4027 {
4028 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4029
4030 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4031
4032 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4033 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4034 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4035 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4036 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4037 {
4038 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4039 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4040 }
4041 else
4042 {
4043 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4044 }
4045 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4046 {
4047 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4048 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4049 }
4050 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4051 {
4052 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4053 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4054 }
4055 i = api_put (appl, m);
4056 if (i != 0)
4057 {
4058 if (m->header.command == _DATA_B3_R)
4059
4060 TransmitBufferFree (appl, (byte *)(m->info.data_b3_req.Data));
4061
4062 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4063 break;
4064 }
4065
4066 if (plci->li_notify_update)
4067 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004068 plci->li_notify_update = false;
4069 mixer_notify_update (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070 }
4071
4072 }
4073 send_data(plci);
4074 send_req(plci);
4075}
4076
4077
4078void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4079{
4080 dword Id;
4081 dword rId;
4082 word Number;
4083 word Info=0;
4084 word i;
4085 word ncci;
4086 DIVA_CAPI_ADAPTER * a;
4087 APPL * appl;
4088 PLCI * rplci;
4089 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4090 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4091
4092 if (!plci) {
4093 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4094 return;
4095 }
4096 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4097 if(plci->req_in!=plci->req_out)
4098 {
4099 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4100 {
4101 dbug(1,dprintf("req_1return"));
4102 return;
4103 }
4104 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4105 }
4106 plci->req_in = plci->req_in_start = plci->req_out = 0;
4107 dbug(1,dprintf("control_rc"));
4108
4109 appl = plci->appl;
4110 a = plci->adapter;
4111 ncci = a->ch_ncci[ch];
4112 if(appl)
4113 {
4114 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4115 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4116 Number = plci->number;
4117 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));
4118 dbug(1,dprintf("channels=0x%x",plci->channels));
4119 if (plci_remove_check(plci))
4120 return;
4121 if(req==REMOVE && rc==ASSIGN_OK)
4122 {
4123 sig_req(plci,HANGUP,0);
4124 sig_req(plci,REMOVE,0);
4125 send_req(plci);
4126 }
4127 if(plci->command)
4128 {
4129 switch(plci->command)
4130 {
4131 case C_HOLD_REQ:
4132 dbug(1,dprintf("HoldRC=0x%x",rc));
4133 SSparms[1] = (byte)S_HOLD;
4134 if(rc!=OK)
4135 {
4136 plci->SuppState = IDLE;
4137 Info = 0x2001;
4138 }
4139 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4140 break;
4141
4142 case C_RETRIEVE_REQ:
4143 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4144 SSparms[1] = (byte)S_RETRIEVE;
4145 if(rc!=OK)
4146 {
4147 plci->SuppState = CALL_HELD;
4148 Info = 0x2001;
4149 }
4150 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4151 break;
4152
4153 case _INFO_R:
4154 dbug(1,dprintf("InfoRC=0x%x",rc));
4155 if(rc!=OK) Info=_WRONG_STATE;
4156 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4157 break;
4158
4159 case _CONNECT_R:
4160 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4161 if (plci->State == INC_DIS_PENDING)
4162 break;
4163 if(plci->Sig.Id!=0xff)
4164 {
4165 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4166 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4167 {
4168 dbug(1,dprintf("No more IDs/Call_Req failed"));
4169 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4170 plci_remove(plci);
4171 plci->State = IDLE;
4172 break;
4173 }
4174 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4175 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4176 }
4177 else /* D-ch activation */
4178 {
4179 if (rc != ASSIGN_OK)
4180 {
4181 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4182 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4183 plci_remove(plci);
4184 plci->State = IDLE;
4185 break;
4186 }
4187 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4188 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4189 plci->State = INC_ACT_PENDING;
4190 }
4191 break;
4192
4193 case _CONNECT_I|RESPONSE:
4194 if (plci->State != INC_DIS_PENDING)
4195 plci->State = INC_CON_ACCEPT;
4196 break;
4197
4198 case _DISCONNECT_R:
4199 if (plci->State == INC_DIS_PENDING)
4200 break;
4201 if(plci->Sig.Id!=0xff)
4202 {
4203 plci->State = OUTG_DIS_PENDING;
4204 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4205 }
4206 break;
4207
4208 case SUSPEND_REQ:
4209 break;
4210
4211 case RESUME_REQ:
4212 break;
4213
4214 case _CONNECT_B3_R:
4215 if(rc!=OK)
4216 {
4217 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4218 break;
4219 }
4220 ncci = get_ncci (plci, ch, 0);
4221 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4222 plci->channels++;
4223 if(req==N_RESET)
4224 {
4225 a->ncci_state[ncci] = INC_ACT_PENDING;
4226 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4227 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4228 }
4229 else
4230 {
4231 a->ncci_state[ncci] = OUTG_CON_PENDING;
4232 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4233 }
4234 break;
4235
4236 case _CONNECT_B3_I|RESPONSE:
4237 break;
4238
4239 case _RESET_B3_R:
4240/* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4241 break;
4242
4243 case _DISCONNECT_B3_R:
4244 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4245 break;
4246
4247 case _MANUFACTURER_R:
4248 break;
4249
4250 case PERM_LIST_REQ:
4251 if(rc!=OK)
4252 {
4253 Info = _WRONG_IDENTIFIER;
4254 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4255 plci_remove(plci);
4256 }
4257 else
4258 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4259 break;
4260
4261 default:
4262 break;
4263 }
4264 plci->command = 0;
4265 }
4266 else if (plci->internal_command)
4267 {
4268 switch(plci->internal_command)
4269 {
4270 case BLOCK_PLCI:
4271 return;
4272
4273 case GET_MWI_STATE:
4274 if(rc==OK) /* command supported, wait for indication */
4275 {
4276 return;
4277 }
4278 plci_remove(plci);
4279 break;
4280
4281 /* Get Supported Services */
4282 case GETSERV_REQ_PEND:
4283 if(rc==OK) /* command supported, wait for indication */
4284 {
4285 break;
4286 }
4287 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4288 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4289 plci_remove(plci);
4290 break;
4291
4292 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4293 case INTERR_NUMBERS_REQ_PEND:
4294 case CF_START_PEND: /* Call Forwarding Start pending */
4295 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4296 case CCBS_REQUEST_REQ_PEND:
4297 case CCBS_DEACTIVATE_REQ_PEND:
4298 case CCBS_INTERROGATE_REQ_PEND:
4299 switch(plci->internal_command)
4300 {
4301 case INTERR_DIVERSION_REQ_PEND:
4302 SSparms[1] = S_INTERROGATE_DIVERSION;
4303 break;
4304 case INTERR_NUMBERS_REQ_PEND:
4305 SSparms[1] = S_INTERROGATE_NUMBERS;
4306 break;
4307 case CF_START_PEND:
4308 SSparms[1] = S_CALL_FORWARDING_START;
4309 break;
4310 case CF_STOP_PEND:
4311 SSparms[1] = S_CALL_FORWARDING_STOP;
4312 break;
4313 case CCBS_REQUEST_REQ_PEND:
4314 SSparms[1] = S_CCBS_REQUEST;
4315 break;
4316 case CCBS_DEACTIVATE_REQ_PEND:
4317 SSparms[1] = S_CCBS_DEACTIVATE;
4318 break;
4319 case CCBS_INTERROGATE_REQ_PEND:
4320 SSparms[1] = S_CCBS_INTERROGATE;
4321 break;
4322 }
4323 if(global_req==ASSIGN)
4324 {
4325 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4326 return;
4327 }
4328 if(!plci->appl) break;
4329 if(rc==ISDN_GUARD_REJ)
4330 {
4331 Info = _CAPI_GUARD_ERROR;
4332 }
4333 else if(rc!=OK)
4334 {
4335 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4336 }
4337 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4338 plci->number,"wws",Info,(word)3,SSparms);
4339 if(Info) plci_remove(plci);
4340 break;
4341
4342 /* 3pty conference pending */
4343 case PTY_REQ_PEND:
4344 if(!plci->relatedPTYPLCI) break;
4345 rplci = plci->relatedPTYPLCI;
4346 SSparms[1] = plci->ptyState;
4347 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4348 if(rplci->tel) rId|=EXT_CONTROLLER;
4349 if(rc!=OK)
4350 {
4351 Info = 0x300E; /* not supported */
4352 plci->relatedPTYPLCI = NULL;
4353 plci->ptyState = 0;
4354 }
4355 sendf(rplci->appl,
4356 _FACILITY_R|CONFIRM,
4357 rId,
4358 plci->number,
4359 "wws",Info,(word)3,SSparms);
4360 break;
4361
4362 /* Explicit Call Transfer pending */
4363 case ECT_REQ_PEND:
4364 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4365 if(!plci->relatedPTYPLCI) break;
4366 rplci = plci->relatedPTYPLCI;
4367 SSparms[1] = S_ECT;
4368 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4369 if(rplci->tel) rId|=EXT_CONTROLLER;
4370 if(rc!=OK)
4371 {
4372 Info = 0x300E; /* not supported */
4373 plci->relatedPTYPLCI = NULL;
4374 plci->ptyState = 0;
4375 }
4376 sendf(rplci->appl,
4377 _FACILITY_R|CONFIRM,
4378 rId,
4379 plci->number,
4380 "wws",Info,(word)3,SSparms);
4381 break;
4382
4383 case _MANUFACTURER_R:
4384 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4385 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4386 {
4387 dbug(1,dprintf("No more IDs"));
4388 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4389 plci_remove(plci); /* after codec init, internal codec commands pending */
4390 }
4391 break;
4392
4393 case _CONNECT_R:
4394 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4395 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4396 {
4397 dbug(1,dprintf("No more IDs"));
4398 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4399 plci_remove(plci); /* after codec init, internal codec commands pending */
4400 }
4401 break;
4402
4403 case PERM_COD_HOOK: /* finished with Hook_Ind */
4404 return;
4405
4406 case PERM_COD_CALL:
4407 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4408 plci->internal_command = PERM_COD_CONN_PEND;
4409 return;
4410
4411 case PERM_COD_ASSIGN:
4412 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4413 if(rc!=ASSIGN_OK) break;
4414 sig_req(plci,CALL_REQ,0);
4415 send_req(plci);
4416 plci->internal_command = PERM_COD_CALL;
4417 return;
4418
4419 /* Null Call Reference Request pending */
4420 case C_NCR_FAC_REQ:
4421 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4422 if(global_req==ASSIGN)
4423 {
4424 if(rc==ASSIGN_OK)
4425 {
4426 return;
4427 }
4428 else
4429 {
4430 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004431 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 plci_remove(plci);
4433 }
4434 }
4435 else if(req==NCR_FACILITY)
4436 {
4437 if(rc==OK)
4438 {
4439 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4440 }
4441 else
4442 {
4443 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004444 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 }
4446 plci_remove(plci);
4447 }
4448 break;
4449
4450 case HOOK_ON_REQ:
4451 if(plci->channels)
4452 {
4453 if(a->ncci_state[ncci]==CONNECTED)
4454 {
4455 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4456 cleanup_ncci_data (plci, ncci);
4457 nl_req_ncci(plci,N_DISC,(byte)ncci);
4458 }
4459 break;
4460 }
4461 break;
4462
4463 case HOOK_OFF_REQ:
4464 if (plci->State == INC_DIS_PENDING)
4465 break;
4466 sig_req(plci,CALL_REQ,0);
4467 send_req(plci);
4468 plci->State=OUTG_CON_PENDING;
4469 break;
4470
4471
4472 case MWI_ACTIVATE_REQ_PEND:
4473 case MWI_DEACTIVATE_REQ_PEND:
4474 if(global_req == ASSIGN && rc==ASSIGN_OK)
4475 {
4476 dbug(1,dprintf("MWI_REQ assigned"));
4477 return;
4478 }
4479 else if(rc!=OK)
4480 {
4481 if(rc==WRONG_IE)
4482 {
4483 Info = 0x2007; /* Illegal message parameter coding */
4484 dbug(1,dprintf("MWI_REQ invalid parameter"));
4485 }
4486 else
4487 {
4488 Info = 0x300B; /* not supported */
4489 dbug(1,dprintf("MWI_REQ not supported"));
4490 }
4491 /* 0x3010: Request not allowed in this state */
4492 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4493
4494 }
4495 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4496 {
4497 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4498 }
4499 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4500
4501 if(plci->cr_enquiry)
4502 {
4503 sendf(plci->appl,
4504 _FACILITY_R|CONFIRM,
4505 Id&0xf,
4506 plci->number,
4507 "wws",Info,(word)3,SSparms);
4508 if(rc!=OK) plci_remove(plci);
4509 }
4510 else
4511 {
4512 sendf(plci->appl,
4513 _FACILITY_R|CONFIRM,
4514 Id,
4515 plci->number,
4516 "wws",Info,(word)3,SSparms);
4517 }
4518 break;
4519
4520 case CONF_BEGIN_REQ_PEND:
4521 case CONF_ADD_REQ_PEND:
4522 case CONF_SPLIT_REQ_PEND:
4523 case CONF_DROP_REQ_PEND:
4524 case CONF_ISOLATE_REQ_PEND:
4525 case CONF_REATTACH_REQ_PEND:
4526 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4527 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4528 rplci = plci;
4529 rId = Id;
4530 switch(plci->internal_command)
4531 {
4532 case CONF_BEGIN_REQ_PEND:
4533 SSparms[1] = S_CONF_BEGIN;
4534 break;
4535 case CONF_ADD_REQ_PEND:
4536 SSparms[1] = S_CONF_ADD;
4537 rplci = plci->relatedPTYPLCI;
4538 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4539 break;
4540 case CONF_SPLIT_REQ_PEND:
4541 SSparms[1] = S_CONF_SPLIT;
4542 break;
4543 case CONF_DROP_REQ_PEND:
4544 SSparms[1] = S_CONF_DROP;
4545 break;
4546 case CONF_ISOLATE_REQ_PEND:
4547 SSparms[1] = S_CONF_ISOLATE;
4548 break;
4549 case CONF_REATTACH_REQ_PEND:
4550 SSparms[1] = S_CONF_REATTACH;
4551 break;
4552 }
4553
4554 if(rc!=OK)
4555 {
4556 Info = 0x300E; /* not supported */
4557 plci->relatedPTYPLCI = NULL;
4558 plci->ptyState = 0;
4559 }
4560 sendf(rplci->appl,
4561 _FACILITY_R|CONFIRM,
4562 rId,
4563 plci->number,
4564 "wws",Info,(word)3,SSparms);
4565 break;
4566
4567 case VSWITCH_REQ_PEND:
4568 if(rc!=OK)
4569 {
4570 if(plci->relatedPTYPLCI)
4571 {
4572 plci->relatedPTYPLCI->vswitchstate=0;
4573 plci->relatedPTYPLCI->vsprot=0;
4574 plci->relatedPTYPLCI->vsprotdialect=0;
4575 }
4576 plci->vswitchstate=0;
4577 plci->vsprot=0;
4578 plci->vsprotdialect=0;
4579 }
4580 else
4581 {
4582 if(plci->relatedPTYPLCI &&
4583 plci->vswitchstate==1 &&
4584 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4585 plci->vswitchstate=3;
4586 }
4587 break;
4588
4589 /* Call Deflection Request pending (SSCT) */
4590 case CD_REQ_PEND:
4591 SSparms[1] = S_CALL_DEFLECTION;
4592 if(rc!=OK)
4593 {
4594 Info = 0x300E; /* not supported */
4595 plci->appl->CDEnable = 0;
4596 }
4597 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4598 plci->number,"wws",Info,(word)3,SSparms);
4599 break;
4600
4601 case RTP_CONNECT_B3_REQ_COMMAND_2:
4602 if (rc == OK)
4603 {
4604 ncci = get_ncci (plci, ch, 0);
4605 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4606 plci->channels++;
4607 a->ncci_state[ncci] = OUTG_CON_PENDING;
4608 }
4609
4610 default:
4611 if (plci->internal_command_queue[0])
4612 {
4613 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4614 if (plci->internal_command)
4615 return;
4616 }
4617 break;
4618 }
4619 next_internal_command (Id, plci);
4620 }
4621 }
4622 else /* appl==0 */
4623 {
4624 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4625 if(plci->tel) Id|=EXT_CONTROLLER;
4626
4627 switch(plci->internal_command)
4628 {
4629 case BLOCK_PLCI:
4630 return;
4631
4632 case START_L1_SIG_ASSIGN_PEND:
4633 case REM_L1_SIG_ASSIGN_PEND:
4634 if(global_req == ASSIGN)
4635 {
4636 break;
4637 }
4638 else
4639 {
4640 dbug(1,dprintf("***L1 Req rem PLCI"));
4641 plci->internal_command = 0;
4642 sig_req(plci,REMOVE,0);
4643 send_req(plci);
4644 }
4645 break;
4646
4647 /* Call Deflection Request pending, just no appl ptr assigned */
4648 case CD_REQ_PEND:
4649 SSparms[1] = S_CALL_DEFLECTION;
4650 if(rc!=OK)
4651 {
4652 Info = 0x300E; /* not supported */
4653 }
4654 for(i=0; i<max_appl; i++)
4655 {
4656 if(application[i].CDEnable)
4657 {
4658 if(!application[i].Id) application[i].CDEnable = 0;
4659 else
4660 {
4661 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4662 plci->number,"wws",Info,(word)3,SSparms);
4663 if(Info) application[i].CDEnable = 0;
4664 }
4665 }
4666 }
4667 plci->internal_command = 0;
4668 break;
4669
4670 case PERM_COD_HOOK: /* finished with Hook_Ind */
4671 return;
4672
4673 case PERM_COD_CALL:
4674 plci->internal_command = PERM_COD_CONN_PEND;
4675 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4676 return;
4677
4678 case PERM_COD_ASSIGN:
4679 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4680 plci->internal_command = 0;
4681 if(rc!=ASSIGN_OK) break;
4682 plci->internal_command = PERM_COD_CALL;
4683 sig_req(plci,CALL_REQ,0);
4684 send_req(plci);
4685 return;
4686
4687 case LISTEN_SIG_ASSIGN_PEND:
4688 if(rc == ASSIGN_OK)
4689 {
4690 plci->internal_command = 0;
4691 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4692 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4693 sig_req(plci,INDICATE_REQ,0);
4694 send_req(plci);
4695 }
4696 else
4697 {
4698 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4699 a->listen_active--;
4700 plci_remove(plci);
4701 plci->State = IDLE;
4702 }
4703 break;
4704
4705 case USELAW_REQ:
4706 if(global_req == ASSIGN)
4707 {
4708 if (rc==ASSIGN_OK)
4709 {
4710 sig_req(plci,LAW_REQ,0);
4711 send_req(plci);
4712 dbug(1,dprintf("Auto-Law assigned"));
4713 }
4714 else
4715 {
4716 dbug(1,dprintf("Auto-Law assign failed"));
4717 a->automatic_law = 3;
4718 plci->internal_command = 0;
4719 a->automatic_lawPLCI = NULL;
4720 }
4721 break;
4722 }
4723 else if(req == LAW_REQ && rc==OK)
4724 {
4725 dbug(1,dprintf("Auto-Law initiated"));
4726 a->automatic_law = 2;
4727 plci->internal_command = 0;
4728 }
4729 else
4730 {
4731 dbug(1,dprintf("Auto-Law not supported"));
4732 a->automatic_law = 3;
4733 plci->internal_command = 0;
4734 sig_req(plci,REMOVE,0);
4735 send_req(plci);
4736 a->automatic_lawPLCI = NULL;
4737 }
4738 break;
4739 }
4740 plci_remove_check(plci);
4741 }
4742}
4743
4744void data_rc(PLCI * plci, byte ch)
4745{
4746 dword Id;
4747 DIVA_CAPI_ADAPTER * a;
4748 NCCI *ncci_ptr;
4749 DATA_B3_DESC *data;
4750 word ncci;
4751
4752 if (plci->appl)
4753 {
4754 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4755 a = plci->adapter;
4756 ncci = a->ch_ncci[ch];
4757 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4758 {
4759 ncci_ptr = &(a->ncci[ncci]);
4760 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4761 if (ncci_ptr->data_pending)
4762 {
4763 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4764 if (!(data->Flags &4) && a->ncci_state[ncci])
4765 {
4766 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4767 if(plci->tel) Id|=EXT_CONTROLLER;
4768 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4769 "ww",data->Handle,0);
4770 }
4771 (ncci_ptr->data_out)++;
4772 if (ncci_ptr->data_out == MAX_DATA_B3)
4773 ncci_ptr->data_out = 0;
4774 (ncci_ptr->data_pending)--;
4775 }
4776 }
4777 }
4778}
4779
4780void data_ack(PLCI * plci, byte ch)
4781{
4782 dword Id;
4783 DIVA_CAPI_ADAPTER * a;
4784 NCCI *ncci_ptr;
4785 word ncci;
4786
4787 a = plci->adapter;
4788 ncci = a->ch_ncci[ch];
4789 ncci_ptr = &(a->ncci[ncci]);
4790 if (ncci_ptr->data_ack_pending)
4791 {
4792 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4793 {
4794 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4795 if(plci->tel) Id|=EXT_CONTROLLER;
4796 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4797 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4798 }
4799 (ncci_ptr->data_ack_out)++;
4800 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4801 ncci_ptr->data_ack_out = 0;
4802 (ncci_ptr->data_ack_pending)--;
4803 }
4804}
4805
4806void sig_ind(PLCI * plci)
4807{
4808 dword x_Id;
4809 dword Id;
4810 dword rId;
4811 word Number = 0;
4812 word i;
4813 word cip;
4814 dword cip_mask;
4815 byte *ie;
4816 DIVA_CAPI_ADAPTER * a;
4817 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4818#define MAXPARMSIDS 31
4819 byte * parms[MAXPARMSIDS];
4820 byte * add_i[4];
4821 byte * multi_fac_parms[MAX_MULTI_IE];
4822 byte * multi_pi_parms [MAX_MULTI_IE];
4823 byte * multi_ssext_parms [MAX_MULTI_IE];
4824 byte * multi_CiPN_parms [MAX_MULTI_IE];
4825
4826 byte * multi_vswitch_parms [MAX_MULTI_IE];
4827
4828 byte ai_len;
4829 byte *esc_chi = "";
4830 byte *esc_law = "";
4831 byte *pty_cai = "";
4832 byte *esc_cr = "";
4833 byte *esc_profile = "";
4834
4835 byte facility[256];
4836 PLCI * tplci = NULL;
4837 byte chi[] = "\x02\x18\x01";
4838 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4839 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4840 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4841 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4842 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4843 /* (see Info_Mask Bit 4, first IE. then the message type) */
4844 word parms_id[] =
4845 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4846 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4847 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4848 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4849 /* 14 FTY repl by ESC_CHI */
4850 /* 18 PI repl by ESC_LAW */
4851 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4852 word multi_fac_id[] = {1, FTY};
4853 word multi_pi_id[] = {1, PI};
4854 word multi_CiPN_id[] = {1, OAD};
4855 word multi_ssext_id[] = {1, ESC_SSEXT};
4856
4857 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4858
4859 byte * cau;
4860 word ncci;
4861 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4862 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4863 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4864 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004865 byte force_mt_info = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866 byte dir;
4867 dword d;
4868 word w;
4869
4870 a = plci->adapter;
4871 Id = ((word)plci->Id<<8)|a->Id;
4872 PUT_WORD(&SS_Ind[4],0x0000);
4873
4874 if (plci->sig_remove_id)
4875 {
4876 plci->Sig.RNR = 2; /* discard */
4877 dbug(1,dprintf("SIG discard while remove pending"));
4878 return;
4879 }
4880 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4881 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4882 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4883 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4884 {
4885 plci->Sig.RNR = 1;
4886 return;
4887 }
4888 if(plci->Sig.Ind==HANGUP && plci->channels)
4889 {
4890 plci->Sig.RNR = 1;
4891 plci->hangup_flow_ctrl_timer++;
4892 /* recover the network layer after timeout */
4893 if(plci->hangup_flow_ctrl_timer==100)
4894 {
4895 dbug(1,dprintf("Exceptional disc"));
4896 plci->Sig.RNR = 0;
4897 plci->hangup_flow_ctrl_timer = 0;
4898 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4899 {
4900 if (a->ncci_plci[ncci] == plci->Id)
4901 {
4902 cleanup_ncci_data (plci, ncci);
4903 if(plci->channels)plci->channels--;
4904 if (plci->appl)
4905 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4906 }
4907 }
4908 if (plci->appl)
4909 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4910 plci_remove(plci);
4911 plci->State=IDLE;
4912 }
4913 return;
4914 }
4915
4916 /* do first parse the info with no OAD in, because OAD will be converted */
4917 /* first the multiple facility IE, then mult. progress ind. */
4918 /* then the parameters for the info_ind + conn_ind */
4919 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4920 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4921 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4922
4923 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4924
4925 IndParse(plci,parms_id,parms,0);
4926 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4927 esc_chi = parms[14];
4928 esc_law = parms[18];
4929 pty_cai = parms[24];
4930 esc_cr = parms[25];
4931 esc_profile = parms[27];
4932 if(esc_cr[0] && plci)
4933 {
4934 if(plci->cr_enquiry && plci->appl)
4935 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004936 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004937 /* d = MANU_ID */
4938 /* w = m_command */
4939 /* b = total length */
4940 /* b = indication type */
4941 /* b = length of all IEs */
4942 /* b = IE1 */
4943 /* S = IE1 length + cont. */
4944 /* b = IE2 */
4945 /* S = IE2 lenght + cont. */
4946 sendf(plci->appl,
4947 _MANUFACTURER_I,
4948 Id,
4949 0,
4950 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4951 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);
4952 }
4953 }
4954 /* create the additional info structure */
4955 add_i[1] = parms[15]; /* KEY of additional info */
4956 add_i[2] = parms[11]; /* UUI of additional info */
4957 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4958
4959 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4960 /* indication returns by the card if requested by the function */
4961 /* AutomaticLaw() after driver init */
4962 if (a->automatic_law<4)
4963 {
4964 if(esc_law[0]){
4965 if(esc_law[2]){
4966 dbug(0,dprintf("u-Law selected"));
4967 a->u_law = 1;
4968 }
4969 else {
4970 dbug(0,dprintf("a-Law selected"));
4971 a->u_law = 0;
4972 }
4973 a->automatic_law = 4;
4974 if(plci==a->automatic_lawPLCI) {
4975 plci->internal_command = 0;
4976 sig_req(plci,REMOVE,0);
4977 send_req(plci);
4978 a->automatic_lawPLCI = NULL;
4979 }
4980 }
4981 if (esc_profile[0])
4982 {
4983 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4984 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4985 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4986 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4987
4988 a->profile.Global_Options &= 0x000000ffL;
4989 a->profile.B1_Protocols &= 0x000003ffL;
4990 a->profile.B2_Protocols &= 0x00001fdfL;
4991 a->profile.B3_Protocols &= 0x000000b7L;
4992
4993 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4994 GL_BCHANNEL_OPERATION_SUPPORTED;
4995 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4996 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4997 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4998 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4999 a->man_profile.private_options = 0;
5000
5001 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5002 {
5003 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5004 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5005 }
5006
5007
5008 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5009 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5010 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5011 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5012
5013
5014 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5015 a->man_profile.private_options |= 1L << PRIVATE_T38;
5016
5017
5018 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5019 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5020
5021
5022 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5023 a->man_profile.private_options |= 1L << PRIVATE_V18;
5024
5025
5026 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5027 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5028
5029
5030 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5031 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5032
5033
5034 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5035 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5036
5037
5038 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5039 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5040
5041
5042 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5043 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5044
5045 }
5046 else
5047 {
5048 a->profile.Global_Options &= 0x0000007fL;
5049 a->profile.B1_Protocols &= 0x000003dfL;
5050 a->profile.B2_Protocols &= 0x00001adfL;
5051 a->profile.B3_Protocols &= 0x000000b7L;
5052 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5053 }
5054 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5055 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5056 {
5057 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5058 }
5059 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5060 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5061 UnMapController (a->Id), a->profile.Global_Options,
5062 a->profile.B1_Protocols, a->profile.B2_Protocols,
5063 a->profile.B3_Protocols, a->manufacturer_features));
5064 }
5065 /* codec plci for the handset/hook state support is just an internal id */
5066 if(plci!=a->AdvCodecPLCI)
5067 {
5068 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5069 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5070 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5071 SendInfo(plci,Id, parms, force_mt_info);
5072
5073 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5074
5075 }
5076
5077 /* switch the codec to the b-channel */
5078 if(esc_chi[0] && plci && !plci->SuppState){
5079 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5080 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5081 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5082 if(plci->tel==ADV_VOICE && plci->appl) {
5083 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5084 }
5085 }
5086
5087 if(plci->appl) Number = plci->appl->Number++;
5088
5089 switch(plci->Sig.Ind) {
5090 /* Response to Get_Supported_Services request */
5091 case S_SUPPORTED:
5092 dbug(1,dprintf("S_Supported"));
5093 if(!plci->appl) break;
5094 if(pty_cai[0]==4)
5095 {
5096 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5097 }
5098 else
5099 {
5100 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5101 }
5102 PUT_WORD (&CF_Ind[1], 0);
5103 PUT_WORD (&CF_Ind[4], 0);
5104 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5105 plci_remove(plci);
5106 break;
5107
5108 /* Supplementary Service rejected */
5109 case S_SERVICE_REJ:
5110 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5111 if(!pty_cai[0]) break;
5112 switch (pty_cai[5])
5113 {
5114 case ECT_EXECUTE:
5115 case THREE_PTY_END:
5116 case THREE_PTY_BEGIN:
5117 if(!plci->relatedPTYPLCI) break;
5118 tplci = plci->relatedPTYPLCI;
5119 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5120 if(tplci->tel) rId|=EXT_CONTROLLER;
5121 if(pty_cai[5]==ECT_EXECUTE)
5122 {
5123 PUT_WORD(&SS_Ind[1],S_ECT);
5124
5125 plci->vswitchstate=0;
5126 plci->relatedPTYPLCI->vswitchstate=0;
5127
5128 }
5129 else
5130 {
5131 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5132 }
5133 if(pty_cai[2]!=0xff)
5134 {
5135 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5136 }
5137 else
5138 {
5139 PUT_WORD(&SS_Ind[4],0x300E);
5140 }
5141 plci->relatedPTYPLCI = NULL;
5142 plci->ptyState = 0;
5143 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5144 break;
5145
5146 case CALL_DEFLECTION:
5147 if(pty_cai[2]!=0xff)
5148 {
5149 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5150 }
5151 else
5152 {
5153 PUT_WORD(&SS_Ind[4],0x300E);
5154 }
5155 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5156 for(i=0; i<max_appl; i++)
5157 {
5158 if(application[i].CDEnable)
5159 {
5160 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005161 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162 }
5163 }
5164 break;
5165
5166 case DEACTIVATION_DIVERSION:
5167 case ACTIVATION_DIVERSION:
5168 case DIVERSION_INTERROGATE_CFU:
5169 case DIVERSION_INTERROGATE_CFB:
5170 case DIVERSION_INTERROGATE_CFNR:
5171 case DIVERSION_INTERROGATE_NUM:
5172 case CCBS_REQUEST:
5173 case CCBS_DEACTIVATE:
5174 case CCBS_INTERROGATE:
5175 if(!plci->appl) break;
5176 if(pty_cai[2]!=0xff)
5177 {
5178 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5179 }
5180 else
5181 {
5182 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5183 }
5184 switch (pty_cai[5])
5185 {
5186 case DEACTIVATION_DIVERSION:
5187 dbug(1,dprintf("Deact_Div"));
5188 Interr_Err_Ind[0]=0x9;
5189 Interr_Err_Ind[3]=0x6;
5190 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5191 break;
5192 case ACTIVATION_DIVERSION:
5193 dbug(1,dprintf("Act_Div"));
5194 Interr_Err_Ind[0]=0x9;
5195 Interr_Err_Ind[3]=0x6;
5196 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5197 break;
5198 case DIVERSION_INTERROGATE_CFU:
5199 case DIVERSION_INTERROGATE_CFB:
5200 case DIVERSION_INTERROGATE_CFNR:
5201 dbug(1,dprintf("Interr_Div"));
5202 Interr_Err_Ind[0]=0xa;
5203 Interr_Err_Ind[3]=0x7;
5204 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5205 break;
5206 case DIVERSION_INTERROGATE_NUM:
5207 dbug(1,dprintf("Interr_Num"));
5208 Interr_Err_Ind[0]=0xa;
5209 Interr_Err_Ind[3]=0x7;
5210 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5211 break;
5212 case CCBS_REQUEST:
5213 dbug(1,dprintf("CCBS Request"));
5214 Interr_Err_Ind[0]=0xd;
5215 Interr_Err_Ind[3]=0xa;
5216 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5217 break;
5218 case CCBS_DEACTIVATE:
5219 dbug(1,dprintf("CCBS Deactivate"));
5220 Interr_Err_Ind[0]=0x9;
5221 Interr_Err_Ind[3]=0x6;
5222 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5223 break;
5224 case CCBS_INTERROGATE:
5225 dbug(1,dprintf("CCBS Interrogate"));
5226 Interr_Err_Ind[0]=0xb;
5227 Interr_Err_Ind[3]=0x8;
5228 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5229 break;
5230 }
5231 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5232 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5233 plci_remove(plci);
5234 break;
5235 case ACTIVATION_MWI:
5236 case DEACTIVATION_MWI:
5237 if(pty_cai[5]==ACTIVATION_MWI)
5238 {
5239 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5240 }
5241 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5242
5243 if(pty_cai[2]!=0xff)
5244 {
5245 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5246 }
5247 else
5248 {
5249 PUT_WORD(&SS_Ind[4],0x300E);
5250 }
5251
5252 if(plci->cr_enquiry)
5253 {
5254 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5255 plci_remove(plci);
5256 }
5257 else
5258 {
5259 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5260 }
5261 break;
5262 case CONF_ADD: /* ERROR */
5263 case CONF_BEGIN:
5264 case CONF_DROP:
5265 case CONF_ISOLATE:
5266 case CONF_REATTACH:
5267 CONF_Ind[0]=9;
5268 CONF_Ind[3]=6;
5269 switch(pty_cai[5])
5270 {
5271 case CONF_BEGIN:
5272 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5273 plci->ptyState = 0;
5274 break;
5275 case CONF_DROP:
5276 CONF_Ind[0]=5;
5277 CONF_Ind[3]=2;
5278 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5279 plci->ptyState = CONNECTED;
5280 break;
5281 case CONF_ISOLATE:
5282 CONF_Ind[0]=5;
5283 CONF_Ind[3]=2;
5284 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5285 plci->ptyState = CONNECTED;
5286 break;
5287 case CONF_REATTACH:
5288 CONF_Ind[0]=5;
5289 CONF_Ind[3]=2;
5290 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5291 plci->ptyState = CONNECTED;
5292 break;
5293 case CONF_ADD:
5294 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5295 plci->relatedPTYPLCI = NULL;
5296 tplci=plci->relatedPTYPLCI;
5297 if(tplci) tplci->ptyState = CONNECTED;
5298 plci->ptyState = CONNECTED;
5299 break;
5300 }
5301
5302 if(pty_cai[2]!=0xff)
5303 {
5304 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5305 }
5306 else
5307 {
5308 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5309 within the required time */
5310 }
5311
5312 PUT_DWORD(&CONF_Ind[6],0x0);
5313 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5314 break;
5315 }
5316 break;
5317
5318 /* Supplementary Service indicates success */
5319 case S_SERVICE:
5320 dbug(1,dprintf("Service_Ind"));
5321 PUT_WORD (&CF_Ind[4], 0);
5322 switch (pty_cai[5])
5323 {
5324 case THREE_PTY_END:
5325 case THREE_PTY_BEGIN:
5326 case ECT_EXECUTE:
5327 if(!plci->relatedPTYPLCI) break;
5328 tplci = plci->relatedPTYPLCI;
5329 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5330 if(tplci->tel) rId|=EXT_CONTROLLER;
5331 if(pty_cai[5]==ECT_EXECUTE)
5332 {
5333 PUT_WORD(&SS_Ind[1],S_ECT);
5334
5335 if(plci->vswitchstate!=3)
5336 {
5337
5338 plci->ptyState = IDLE;
5339 plci->relatedPTYPLCI = NULL;
5340 plci->ptyState = 0;
5341
5342 }
5343
5344 dbug(1,dprintf("ECT OK"));
5345 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5346
5347
5348
5349 }
5350 else
5351 {
5352 switch (plci->ptyState)
5353 {
5354 case S_3PTY_BEGIN:
5355 plci->ptyState = CONNECTED;
5356 dbug(1,dprintf("3PTY ON"));
5357 break;
5358
5359 case S_3PTY_END:
5360 plci->ptyState = IDLE;
5361 plci->relatedPTYPLCI = NULL;
5362 plci->ptyState = 0;
5363 dbug(1,dprintf("3PTY OFF"));
5364 break;
5365 }
5366 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5367 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368 }
5369 break;
5370
5371 case CALL_DEFLECTION:
5372 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5373 for(i=0; i<max_appl; i++)
5374 {
5375 if(application[i].CDEnable)
5376 {
5377 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005378 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 }
5380 }
5381 break;
5382
5383 case DEACTIVATION_DIVERSION:
5384 case ACTIVATION_DIVERSION:
5385 if(!plci->appl) break;
5386 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5387 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5388 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5389 plci_remove(plci);
5390 break;
5391
5392 case DIVERSION_INTERROGATE_CFU:
5393 case DIVERSION_INTERROGATE_CFB:
5394 case DIVERSION_INTERROGATE_CFNR:
5395 case DIVERSION_INTERROGATE_NUM:
5396 case CCBS_REQUEST:
5397 case CCBS_DEACTIVATE:
5398 case CCBS_INTERROGATE:
5399 if(!plci->appl) break;
5400 switch (pty_cai[5])
5401 {
5402 case DIVERSION_INTERROGATE_CFU:
5403 case DIVERSION_INTERROGATE_CFB:
5404 case DIVERSION_INTERROGATE_CFNR:
5405 dbug(1,dprintf("Interr_Div"));
5406 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5407 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5408 break;
5409 case DIVERSION_INTERROGATE_NUM:
5410 dbug(1,dprintf("Interr_Num"));
5411 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5412 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5413 break;
5414 case CCBS_REQUEST:
5415 dbug(1,dprintf("CCBS Request"));
5416 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5417 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5418 break;
5419 case CCBS_DEACTIVATE:
5420 dbug(1,dprintf("CCBS Deactivate"));
5421 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5422 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5423 break;
5424 case CCBS_INTERROGATE:
5425 dbug(1,dprintf("CCBS Interrogate"));
5426 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5427 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5428 break;
5429 }
5430 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5431 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5432 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5433 plci_remove(plci);
5434 break;
5435
5436 case ACTIVATION_MWI:
5437 case DEACTIVATION_MWI:
5438 if(pty_cai[5]==ACTIVATION_MWI)
5439 {
5440 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5441 }
5442 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5443 if(plci->cr_enquiry)
5444 {
5445 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5446 plci_remove(plci);
5447 }
5448 else
5449 {
5450 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5451 }
5452 break;
5453 case MWI_INDICATION:
5454 if(pty_cai[0]>=0x12)
5455 {
5456 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5457 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5458 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5459 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5460 {
5461 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5462 {
5463 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5464 plci_remove(plci);
5465 return;
5466 }
5467 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5468 pty_cai[0]=0;
5469 }
5470 else
5471 {
5472 for(i=0; i<max_appl; i++)
5473 {
5474 if(a->Notification_Mask[i]&SMASK_MWI)
5475 {
5476 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5477 pty_cai[0]=0;
5478 }
5479 }
5480 }
5481
5482 if(!pty_cai[0])
5483 { /* acknowledge */
5484 facility[2]= 0; /* returncode */
5485 }
5486 else facility[2]= 0xff;
5487 }
5488 else
5489 {
5490 /* reject */
5491 facility[2]= 0xff; /* returncode */
5492 }
5493 facility[0]= 2;
5494 facility[1]= MWI_RESPONSE; /* Function */
5495 add_p(plci,CAI,facility);
5496 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5497 sig_req(plci,S_SERVICE,0);
5498 send_req(plci);
5499 plci->command = 0;
5500 next_internal_command (Id, plci);
5501 break;
5502 case CONF_ADD: /* OK */
5503 case CONF_BEGIN:
5504 case CONF_DROP:
5505 case CONF_ISOLATE:
5506 case CONF_REATTACH:
5507 case CONF_PARTYDISC:
5508 CONF_Ind[0]=9;
5509 CONF_Ind[3]=6;
5510 switch(pty_cai[5])
5511 {
5512 case CONF_BEGIN:
5513 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5514 if(pty_cai[0]==6)
5515 {
5516 d=pty_cai[6];
5517 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5518 }
5519 else
5520 {
5521 PUT_DWORD(&CONF_Ind[6],0x0);
5522 }
5523 break;
5524 case CONF_ISOLATE:
5525 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5526 CONF_Ind[0]=5;
5527 CONF_Ind[3]=2;
5528 break;
5529 case CONF_REATTACH:
5530 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5531 CONF_Ind[0]=5;
5532 CONF_Ind[3]=2;
5533 break;
5534 case CONF_DROP:
5535 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5536 CONF_Ind[0]=5;
5537 CONF_Ind[3]=2;
5538 break;
5539 case CONF_ADD:
5540 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5541 d=pty_cai[6];
5542 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5543 tplci=plci->relatedPTYPLCI;
5544 if(tplci) tplci->ptyState = CONNECTED;
5545 break;
5546 case CONF_PARTYDISC:
5547 CONF_Ind[0]=7;
5548 CONF_Ind[3]=4;
5549 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5550 d=pty_cai[6];
5551 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5552 break;
5553 }
5554 plci->ptyState = CONNECTED;
5555 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5556 break;
5557 case CCBS_INFO_RETAIN:
5558 case CCBS_ERASECALLLINKAGEID:
5559 case CCBS_STOP_ALERTING:
5560 CONF_Ind[0]=5;
5561 CONF_Ind[3]=2;
5562 switch(pty_cai[5])
5563 {
5564 case CCBS_INFO_RETAIN:
5565 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5566 break;
5567 case CCBS_STOP_ALERTING:
5568 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5569 break;
5570 case CCBS_ERASECALLLINKAGEID:
5571 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5572 CONF_Ind[0]=7;
5573 CONF_Ind[3]=4;
5574 CONF_Ind[6]=0;
5575 CONF_Ind[7]=0;
5576 break;
5577 }
5578 w=pty_cai[6];
5579 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5580
5581 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5582 {
5583 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5584 }
5585 else
5586 {
5587 for(i=0; i<max_appl; i++)
5588 if(a->Notification_Mask[i]&SMASK_CCBS)
5589 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5590 }
5591 break;
5592 }
5593 break;
5594 case CALL_HOLD_REJ:
5595 cau = parms[7];
5596 if(cau)
5597 {
5598 i = _L3_CAUSE | cau[2];
5599 if(cau[2]==0) i = 0x3603;
5600 }
5601 else
5602 {
5603 i = 0x3603;
5604 }
5605 PUT_WORD(&SS_Ind[1],S_HOLD);
5606 PUT_WORD(&SS_Ind[4],i);
5607 if(plci->SuppState == HOLD_REQUEST)
5608 {
5609 plci->SuppState = IDLE;
5610 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5611 }
5612 break;
5613
5614 case CALL_HOLD_ACK:
5615 if(plci->SuppState == HOLD_REQUEST)
5616 {
5617 plci->SuppState = CALL_HELD;
5618 CodecIdCheck(a, plci);
5619 start_internal_command (Id, plci, hold_save_command);
5620 }
5621 break;
5622
5623 case CALL_RETRIEVE_REJ:
5624 cau = parms[7];
5625 if(cau)
5626 {
5627 i = _L3_CAUSE | cau[2];
5628 if(cau[2]==0) i = 0x3603;
5629 }
5630 else
5631 {
5632 i = 0x3603;
5633 }
5634 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5635 PUT_WORD(&SS_Ind[4],i);
5636 if(plci->SuppState == RETRIEVE_REQUEST)
5637 {
5638 plci->SuppState = CALL_HELD;
5639 CodecIdCheck(a, plci);
5640 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5641 }
5642 break;
5643
5644 case CALL_RETRIEVE_ACK:
5645 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5646 if(plci->SuppState == RETRIEVE_REQUEST)
5647 {
5648 plci->SuppState = IDLE;
5649 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5650 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5651 if(plci->tel)
5652 {
5653 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5654 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5655 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5656 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5657 {
5658 dbug(1,dprintf("Get B-ch"));
5659 start_internal_command (Id, plci, retrieve_restore_command);
5660 }
5661 else
5662 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663 }
5664 else
5665 start_internal_command (Id, plci, retrieve_restore_command);
5666 }
5667 break;
5668
5669 case INDICATE_IND:
5670 if(plci->State != LISTENING) {
5671 sig_req(plci,HANGUP,0);
5672 send_req(plci);
5673 break;
5674 }
5675 cip = find_cip(a,parms[4],parms[6]);
5676 cip_mask = 1L<<cip;
5677 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5678 clear_c_ind_mask (plci);
5679 if (!remove_started && !a->adapter_disabled)
5680 {
5681 set_c_ind_mask_bit (plci, MAX_APPL);
5682 group_optimization(a, plci);
5683 for(i=0; i<max_appl; i++) {
5684 if(application[i].Id
5685 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5686 && CPN_filter_ok(parms[0],a,i)
5687 && test_group_ind_mask_bit (plci, i) ) {
5688 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5689 set_c_ind_mask_bit (plci, i);
5690 dump_c_ind_mask (plci);
5691 plci->State = INC_CON_PENDING;
5692 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5693 CALL_DIR_IN | CALL_DIR_ANSWER;
5694 if(esc_chi[0]) {
5695 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5696 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5697 }
5698 /* if a listen on the ext controller is done, check if hook states */
5699 /* are supported or if just a on board codec must be activated */
5700 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5701 if(a->profile.Global_Options & HANDSET)
5702 plci->tel = ADV_VOICE;
5703 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5704 plci->tel = CODEC;
5705 if(plci->tel) Id|=EXT_CONTROLLER;
5706 a->codec_listen[i] = plci;
5707 }
5708
5709 sendf(&application[i],_CONNECT_I,Id,0,
5710 "wSSSSSSSbSSSSS", cip, /* CIP */
5711 parms[0], /* CalledPartyNumber */
5712 multi_CiPN_parms[0], /* CallingPartyNumber */
5713 parms[2], /* CalledPartySubad */
5714 parms[3], /* CallingPartySubad */
5715 parms[4], /* BearerCapability */
5716 parms[5], /* LowLC */
5717 parms[6], /* HighLC */
5718 ai_len, /* nested struct add_i */
5719 add_i[0], /* B channel info */
5720 add_i[1], /* keypad facility */
5721 add_i[2], /* user user data */
5722 add_i[3], /* nested facility */
5723 multi_CiPN_parms[1] /* second CiPN(SCR) */
5724 );
5725 SendSSExtInd(&application[i],
5726 plci,
5727 Id,
5728 multi_ssext_parms);
5729 SendSetupInfo(&application[i],
5730 plci,
5731 Id,
5732 parms,
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005733 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734 }
5735 }
5736 clear_c_ind_mask_bit (plci, MAX_APPL);
5737 dump_c_ind_mask (plci);
5738 }
5739 if(c_ind_mask_empty (plci)) {
5740 sig_req(plci,HANGUP,0);
5741 send_req(plci);
5742 plci->State = IDLE;
5743 }
5744 plci->notifiedcall = 0;
5745 a->listen_active--;
5746 listen_check(a);
5747 break;
5748
5749 case CALL_PEND_NOTIFY:
5750 plci->notifiedcall = 1;
5751 listen_check(a);
5752 break;
5753
5754 case CALL_IND:
5755 case CALL_CON:
5756 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5757 {
5758 if(plci->internal_command==PERM_COD_CONN_PEND)
5759 {
5760 if(plci->State==ADVANCED_VOICE_NOSIG)
5761 {
5762 dbug(1,dprintf("***Codec OK"));
5763 if(a->AdvSignalPLCI)
5764 {
5765 tplci = a->AdvSignalPLCI;
5766 if(tplci->spoofed_msg)
5767 {
5768 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5769 tplci->command = 0;
5770 tplci->internal_command = 0;
5771 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5772 switch (tplci->spoofed_msg)
5773 {
5774 case CALL_RES:
5775 tplci->command = _CONNECT_I|RESPONSE;
5776 api_load_msg (&tplci->saved_msg, saved_parms);
5777 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5778 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5779 {
5780 /* early B3 connect (CIP mask bit 9) no release after a disc */
5781 add_p(tplci,LLI,"\x01\x01");
5782 }
5783 add_s(tplci, CONN_NR, &saved_parms[2]);
5784 add_s(tplci, LLC, &saved_parms[4]);
5785 add_ai(tplci, &saved_parms[5]);
5786 tplci->State = INC_CON_ACCEPT;
5787 sig_req(tplci, CALL_RES,0);
5788 send_req(tplci);
5789 break;
5790
5791 case AWAITING_SELECT_B:
5792 dbug(1,dprintf("Select_B continue"));
5793 start_internal_command (x_Id, tplci, select_b_command);
5794 break;
5795
5796 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5797 if(!tplci->Sig.Id)
5798 {
5799 dbug(1,dprintf("No SigID!"));
5800 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5801 plci_remove(tplci);
5802 break;
5803 }
5804 tplci->command = _MANUFACTURER_R;
5805 api_load_msg (&tplci->saved_msg, saved_parms);
5806 dir = saved_parms[2].info[0];
5807 if(dir==1) {
5808 sig_req(tplci,CALL_REQ,0);
5809 }
5810 else if(!dir){
5811 sig_req(tplci,LISTEN_REQ,0);
5812 }
5813 send_req(tplci);
5814 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5815 break;
5816
5817 case (CALL_REQ|AWAITING_MANUF_CON):
5818 sig_req(tplci,CALL_REQ,0);
5819 send_req(tplci);
5820 break;
5821
5822 case CALL_REQ:
5823 if(!tplci->Sig.Id)
5824 {
5825 dbug(1,dprintf("No SigID!"));
5826 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5827 plci_remove(tplci);
5828 break;
5829 }
5830 tplci->command = _CONNECT_R;
5831 api_load_msg (&tplci->saved_msg, saved_parms);
5832 add_s(tplci,CPN,&saved_parms[1]);
5833 add_s(tplci,DSA,&saved_parms[3]);
5834 add_ai(tplci,&saved_parms[9]);
5835 sig_req(tplci,CALL_REQ,0);
5836 send_req(tplci);
5837 break;
5838
5839 case CALL_RETRIEVE:
5840 tplci->command = C_RETRIEVE_REQ;
5841 sig_req(tplci,CALL_RETRIEVE,0);
5842 send_req(tplci);
5843 break;
5844 }
5845 tplci->spoofed_msg = 0;
5846 if (tplci->internal_command == 0)
5847 next_internal_command (x_Id, tplci);
5848 }
5849 }
5850 next_internal_command (Id, plci);
5851 break;
5852 }
5853 dbug(1,dprintf("***Codec Hook Init Req"));
5854 plci->internal_command = PERM_COD_HOOK;
5855 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5856 sig_req(plci,TEL_CTRL,0);
5857 send_req(plci);
5858 }
5859 }
5860 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5861 && plci->State!=INC_ACT_PENDING)
5862 {
5863 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5864 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5865 {
5866 chi[2] = plci->b_channel;
5867 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5868 }
5869 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5870 plci->State = INC_ACT_PENDING;
5871 }
5872 break;
5873
5874 case TEL_CTRL:
5875 Number = 0;
5876 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5877 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5878 switch (ie[1]&0x91) {
5879 case 0x80: /* hook off */
5880 case 0x81:
5881 if(plci->internal_command==PERM_COD_HOOK)
5882 {
5883 dbug(1,dprintf("init:hook_off"));
5884 plci->hook_state = ie[1];
5885 next_internal_command (Id, plci);
5886 break;
5887 }
5888 else /* ignore doubled hook indications */
5889 {
5890 if( ((plci->hook_state)&0xf0)==0x80)
5891 {
5892 dbug(1,dprintf("ignore hook"));
5893 break;
5894 }
5895 plci->hook_state = ie[1]&0x91;
5896 }
5897 /* check for incoming call pending */
5898 /* and signal '+'.Appl must decide */
5899 /* with connect_res if call must */
5900 /* accepted or not */
5901 for(i=0, tplci=NULL;i<max_appl;i++){
5902 if(a->codec_listen[i]
5903 && (a->codec_listen[i]->State==INC_CON_PENDING
5904 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5905 tplci = a->codec_listen[i];
5906 tplci->appl = &application[i];
5907 }
5908 }
5909 /* no incoming call, do outgoing call */
5910 /* and signal '+' if outg. setup */
5911 if(!a->AdvSignalPLCI && !tplci){
5912 if((i=get_plci(a))) {
5913 a->AdvSignalPLCI = &a->plci[i-1];
5914 tplci = a->AdvSignalPLCI;
5915 tplci->tel = ADV_VOICE;
5916 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5917 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5918 /* early B3 connect (CIP mask bit 9) no release after a disc */
5919 add_p(tplci,LLI,"\x01\x01");
5920 }
5921 add_p(tplci, CAI, voice_cai);
5922 add_p(tplci, OAD, a->TelOAD);
5923 add_p(tplci, OSA, a->TelOSA);
5924 add_p(tplci,SHIFT|6,NULL);
5925 add_p(tplci,SIN,"\x02\x01\x00");
5926 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5927 sig_req(tplci,ASSIGN,DSIG_ID);
5928 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5929 a->AdvSignalPLCI->command = 0;
5930 tplci->appl = a->AdvSignalAppl;
5931 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5932 send_req(tplci);
5933 }
5934
5935 }
5936
5937 if(!tplci) break;
5938 Id = ((word)tplci->Id<<8)|a->Id;
5939 Id|=EXT_CONTROLLER;
5940 sendf(tplci->appl,
5941 _FACILITY_I,
5942 Id,
5943 0,
5944 "ws", (word)0, "\x01+");
5945 break;
5946
5947 case 0x90: /* hook on */
5948 case 0x91:
5949 if(plci->internal_command==PERM_COD_HOOK)
5950 {
5951 dbug(1,dprintf("init:hook_on"));
5952 plci->hook_state = ie[1]&0x91;
5953 next_internal_command (Id, plci);
5954 break;
5955 }
5956 else /* ignore doubled hook indications */
5957 {
5958 if( ((plci->hook_state)&0xf0)==0x90) break;
5959 plci->hook_state = ie[1]&0x91;
5960 }
5961 /* hangup the adv. voice call and signal '-' to the appl */
5962 if(a->AdvSignalPLCI) {
5963 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5964 if(plci->tel) Id|=EXT_CONTROLLER;
5965 sendf(a->AdvSignalAppl,
5966 _FACILITY_I,
5967 Id,
5968 0,
5969 "ws", (word)0, "\x01-");
5970 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5971 a->AdvSignalPLCI->command = 0;
5972 sig_req(a->AdvSignalPLCI,HANGUP,0);
5973 send_req(a->AdvSignalPLCI);
5974 }
5975 break;
5976 }
5977 }
5978 break;
5979
5980 case RESUME:
5981 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5982 PUT_WORD(&resume_cau[4],GOOD);
5983 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5984 break;
5985
5986 case SUSPEND:
5987 clear_c_ind_mask (plci);
5988
5989 if (plci->NL.Id && !plci->nl_remove_id) {
5990 mixer_remove (plci);
5991 nl_req_ncci(plci,REMOVE,0);
5992 }
5993 if (!plci->sig_remove_id) {
5994 plci->internal_command = 0;
5995 sig_req(plci,REMOVE,0);
5996 }
5997 send_req(plci);
5998 if(!plci->channels) {
5999 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6000 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6001 }
6002 break;
6003
6004 case SUSPEND_REJ:
6005 break;
6006
6007 case HANGUP:
6008 plci->hangup_flow_ctrl_timer=0;
6009 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6010 cau = parms[7];
6011 if(cau) {
6012 i = _L3_CAUSE | cau[2];
6013 if(cau[2]==0) i = 0;
6014 else if(cau[2]==8) i = _L1_ERROR;
6015 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6016 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6017 }
6018 else {
6019 i = _L3_ERROR;
6020 }
6021
6022 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6023 {
6024 for(i=0; i<max_appl; i++)
6025 {
6026 if(test_c_ind_mask_bit (plci, i))
6027 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6028 }
6029 }
6030 else
6031 {
6032 clear_c_ind_mask (plci);
6033 }
6034 if(!plci->appl)
6035 {
6036 if (plci->State == LISTENING)
6037 {
6038 plci->notifiedcall=0;
6039 a->listen_active--;
6040 }
6041 plci->State = INC_DIS_PENDING;
6042 if(c_ind_mask_empty (plci))
6043 {
6044 plci->State = IDLE;
6045 if (plci->NL.Id && !plci->nl_remove_id)
6046 {
6047 mixer_remove (plci);
6048 nl_req_ncci(plci,REMOVE,0);
6049 }
6050 if (!plci->sig_remove_id)
6051 {
6052 plci->internal_command = 0;
6053 sig_req(plci,REMOVE,0);
6054 }
6055 send_req(plci);
6056 }
6057 }
6058 else
6059 {
6060 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6061 /* result in a second HANGUP! Don't generate another */
6062 /* DISCONNECT */
6063 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6064 {
6065 if(plci->State==RESUMING)
6066 {
6067 PUT_WORD(&resume_cau[4],i);
6068 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6069 }
6070 plci->State = INC_DIS_PENDING;
6071 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6072 }
6073 }
6074 break;
6075
6076 case SSEXT_IND:
6077 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6078 break;
6079
6080 case VSWITCH_REQ:
6081 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6082 break;
6083 case VSWITCH_IND:
6084 if(plci->relatedPTYPLCI &&
6085 plci->vswitchstate==3 &&
6086 plci->relatedPTYPLCI->vswitchstate==3 &&
6087 parms[MAXPARMSIDS-1][0])
6088 {
6089 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6090 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6091 send_req(plci->relatedPTYPLCI);
6092 }
6093 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6094 break;
6095
6096 }
6097}
6098
6099
6100static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6101{
6102 word i;
6103 byte * ie;
6104 word Info_Number;
6105 byte * Info_Element;
6106 word Info_Mask = 0;
6107
6108 dbug(1,dprintf("SetupInfo"));
6109
6110 for(i=0; i<MAXPARMSIDS; i++) {
6111 ie = parms[i];
6112 Info_Number = 0;
6113 Info_Element = ie;
6114 if(ie[0]) {
6115 switch(i) {
6116 case 0:
6117 dbug(1,dprintf("CPN "));
6118 Info_Number = 0x0070;
6119 Info_Mask = 0x80;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006120 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121 break;
6122 case 8: /* display */
6123 dbug(1,dprintf("display(%d)",i));
6124 Info_Number = 0x0028;
6125 Info_Mask = 0x04;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006126 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127 break;
6128 case 16: /* Channel Id */
6129 dbug(1,dprintf("CHI"));
6130 Info_Number = 0x0018;
6131 Info_Mask = 0x100;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006132 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006133 mixer_set_bchannel_id (plci, Info_Element);
6134 break;
6135 case 19: /* Redirected Number */
6136 dbug(1,dprintf("RDN"));
6137 Info_Number = 0x0074;
6138 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006139 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140 break;
6141 case 20: /* Redirected Number extended */
6142 dbug(1,dprintf("RDX"));
6143 Info_Number = 0x0073;
6144 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006145 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146 break;
6147 case 22: /* Redirecing Number */
6148 dbug(1,dprintf("RIN"));
6149 Info_Number = 0x0076;
6150 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006151 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152 break;
6153 default:
6154 Info_Number = 0;
6155 break;
6156 }
6157 }
6158
6159 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6160 Info_Number = 0x8000 |5;
6161 Info_Mask = 0x10;
6162 Info_Element = "";
6163 }
6164
6165 if(Info_Sent_Flag && Info_Number){
6166 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6167 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6168 }
6169 }
6170 }
6171}
6172
6173
6174void SendInfo(PLCI * plci, dword Id, byte * * parms, byte iesent)
6175{
6176 word i;
6177 word j;
6178 word k;
6179 byte * ie;
6180 word Info_Number;
6181 byte * Info_Element;
6182 word Info_Mask = 0;
6183 static byte charges[5] = {4,0,0,0,0};
6184 static byte cause[] = {0x02,0x80,0x00};
6185 APPL *appl;
6186
6187 dbug(1,dprintf("InfoParse "));
6188
6189 if(
6190 !plci->appl
6191 && !plci->State
6192 && plci->Sig.Ind!=NCR_FACILITY
6193 )
6194 {
6195 dbug(1,dprintf("NoParse "));
6196 return;
6197 }
6198 cause[2] = 0;
6199 for(i=0; i<MAXPARMSIDS; i++) {
6200 ie = parms[i];
6201 Info_Number = 0;
6202 Info_Element = ie;
6203 if(ie[0]) {
6204 switch(i) {
6205 case 0:
6206 dbug(1,dprintf("CPN "));
6207 Info_Number = 0x0070;
6208 Info_Mask = 0x80;
6209 break;
6210 case 7: /* ESC_CAU */
6211 dbug(1,dprintf("cau(0x%x)",ie[2]));
6212 Info_Number = 0x0008;
6213 Info_Mask = 0x00;
6214 cause[2] = ie[2];
6215 Info_Element = NULL;
6216 break;
6217 case 8: /* display */
6218 dbug(1,dprintf("display(%d)",i));
6219 Info_Number = 0x0028;
6220 Info_Mask = 0x04;
6221 break;
6222 case 9: /* Date display */
6223 dbug(1,dprintf("date(%d)",i));
6224 Info_Number = 0x0029;
6225 Info_Mask = 0x02;
6226 break;
6227 case 10: /* charges */
6228 for(j=0;j<4;j++) charges[1+j] = 0;
6229 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6230 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6231 Info_Number = 0x4000;
6232 Info_Mask = 0x40;
6233 Info_Element = charges;
6234 break;
6235 case 11: /* user user info */
6236 dbug(1,dprintf("uui"));
6237 Info_Number = 0x007E;
6238 Info_Mask = 0x08;
6239 break;
6240 case 12: /* congestion receiver ready */
6241 dbug(1,dprintf("clRDY"));
6242 Info_Number = 0x00B0;
6243 Info_Mask = 0x08;
6244 Info_Element = "";
6245 break;
6246 case 13: /* congestion receiver not ready */
6247 dbug(1,dprintf("clNRDY"));
6248 Info_Number = 0x00BF;
6249 Info_Mask = 0x08;
6250 Info_Element = "";
6251 break;
6252 case 15: /* Keypad Facility */
6253 dbug(1,dprintf("KEY"));
6254 Info_Number = 0x002C;
6255 Info_Mask = 0x20;
6256 break;
6257 case 16: /* Channel Id */
6258 dbug(1,dprintf("CHI"));
6259 Info_Number = 0x0018;
6260 Info_Mask = 0x100;
6261 mixer_set_bchannel_id (plci, Info_Element);
6262 break;
6263 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6264 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6265 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6266 Info_Number = 0x0008;
6267 Info_Mask = 0x01;
6268 if(cause[2] != ie[2]) Info_Element = cause;
6269 break;
6270 case 19: /* Redirected Number */
6271 dbug(1,dprintf("RDN"));
6272 Info_Number = 0x0074;
6273 Info_Mask = 0x400;
6274 break;
6275 case 22: /* Redirecing Number */
6276 dbug(1,dprintf("RIN"));
6277 Info_Number = 0x0076;
6278 Info_Mask = 0x400;
6279 break;
6280 case 23: /* Notification Indicator */
6281 dbug(1,dprintf("NI"));
6282 Info_Number = (word)NI;
6283 Info_Mask = 0x210;
6284 break;
6285 case 26: /* Call State */
6286 dbug(1,dprintf("CST"));
6287 Info_Number = (word)CST;
6288 Info_Mask = 0x01; /* do with cause i.e. for now */
6289 break;
6290 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6291 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6292 Info_Number = 0x8000 |ie[3];
6293 if(iesent) Info_Mask = 0xffff;
6294 else Info_Mask = 0x10;
6295 Info_Element = "";
6296 break;
6297 default:
6298 Info_Number = 0;
6299 Info_Mask = 0;
6300 Info_Element = "";
6301 break;
6302 }
6303 }
6304
6305 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6306 {
6307 for(j=0; j<max_appl; j++)
6308 {
6309 appl = &application[j];
6310 if(Info_Number
6311 && appl->Id
6312 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6313 {
6314 dbug(1,dprintf("NCR_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006315 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6317 }
6318 }
6319 }
6320 else if(!plci->appl)
6321 { /* overlap receiving broadcast */
6322 if(Info_Number==CPN
6323 || Info_Number==KEY
6324 || Info_Number==NI
6325 || Info_Number==DSP
6326 || Info_Number==UUI )
6327 {
6328 for(j=0; j<max_appl; j++)
6329 {
6330 if(test_c_ind_mask_bit (plci, j))
6331 {
6332 dbug(1,dprintf("Ovl_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006333 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6335 }
6336 }
6337 }
6338 } /* all other signalling states */
6339 else if(Info_Number
6340 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6341 {
6342 dbug(1,dprintf("Std_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006343 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006344 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6345 }
6346 }
6347}
6348
6349
6350byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse)
6351{
6352 word i;
6353 word j;
6354 byte * ie;
6355 word Info_Number;
6356 byte * Info_Element;
6357 APPL *appl;
6358 word Info_Mask = 0;
6359 byte iesent=0;
6360
6361 if(
6362 !plci->appl
6363 && !plci->State
6364 && plci->Sig.Ind!=NCR_FACILITY
6365 && !setupParse
6366 )
6367 {
6368 dbug(1,dprintf("NoM-IEParse "));
6369 return 0;
6370 }
6371 dbug(1,dprintf("M-IEParse "));
6372
6373 for(i=0; i<MAX_MULTI_IE; i++)
6374 {
6375 ie = parms[i];
6376 Info_Number = 0;
6377 Info_Element = ie;
6378 if(ie[0])
6379 {
6380 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6381 Info_Number = (word)ie_type;
6382 Info_Mask = (word)info_mask;
6383 }
6384
6385 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6386 {
6387 for(j=0; j<max_appl; j++)
6388 {
6389 appl = &application[j];
6390 if(Info_Number
6391 && appl->Id
6392 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6393 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006394 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006395 dbug(1,dprintf("Mlt_NCR_Ind"));
6396 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6397 }
6398 }
6399 }
6400 else if(!plci->appl && Info_Number)
6401 { /* overlap receiving broadcast */
6402 for(j=0; j<max_appl; j++)
6403 {
6404 if(test_c_ind_mask_bit (plci, j))
6405 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006406 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006407 dbug(1,dprintf("Mlt_Ovl_Ind"));
6408 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6409 }
6410 }
6411 } /* all other signalling states */
6412 else if(Info_Number
6413 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6414 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006415 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006416 dbug(1,dprintf("Mlt_Std_Ind"));
6417 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6418 }
6419 }
6420 return iesent;
6421}
6422
6423static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6424{
6425 word i;
6426 /* Format of multi_ssext_parms[i][]:
6427 0 byte length
6428 1 byte SSEXTIE
6429 2 byte SSEXT_REQ/SSEXT_IND
6430 3 byte length
6431 4 word SSExtCommand
6432 6... Params
6433 */
6434 if(
6435 plci
6436 && plci->State
6437 && plci->Sig.Ind!=NCR_FACILITY
6438 )
6439 for(i=0;i<MAX_MULTI_IE;i++)
6440 {
6441 if(parms[i][0]<6) continue;
6442 if(parms[i][2]==SSEXT_REQ) continue;
6443
6444 if(appl)
6445 {
6446 parms[i][0]=0; /* kill it */
6447 sendf(appl,_MANUFACTURER_I,
6448 Id,
6449 0,
6450 "dwS",
6451 _DI_MANU_ID,
6452 _DI_SSEXT_CTRL,
6453 &parms[i][3]);
6454 }
6455 else if(plci->appl)
6456 {
6457 parms[i][0]=0; /* kill it */
6458 sendf(plci->appl,_MANUFACTURER_I,
6459 Id,
6460 0,
6461 "dwS",
6462 _DI_MANU_ID,
6463 _DI_SSEXT_CTRL,
6464 &parms[i][3]);
6465 }
6466 }
6467};
6468
6469void nl_ind(PLCI * plci)
6470{
6471 byte ch;
6472 word ncci;
6473 dword Id;
6474 DIVA_CAPI_ADAPTER * a;
6475 word NCCIcode;
6476 APPL * APPLptr;
6477 word count;
6478 word Num;
6479 word i, ncpi_state;
6480 byte len, ncci_state;
6481 word msg;
6482 word info = 0;
6483 word fax_feature_bits;
6484 byte fax_send_edata_ack;
6485 static byte v120_header_buffer[2 + 3];
6486 static word fax_info[] = {
6487 0, /* T30_SUCCESS */
6488 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6489 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6490 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6491 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6492 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6493 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6494 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6495 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6496 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6497 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6498 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6499 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6500 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6501 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6502 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6503 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6504 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6505 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6506 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6508 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6511 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6520 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6521 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6522 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6523 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6524 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6525 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6526 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6527 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6532 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6533 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6534 };
6535
6536 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6537
6538
6539 static word rtp_info[] = {
6540 GOOD, /* RTP_SUCCESS */
6541 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6542 };
6543
6544 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6545 {
6546 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6547 0x00000000, 0x00000000, 0x00000000, 0x00000000
6548 };
6549
6550 ch = plci->NL.IndCh;
6551 a = plci->adapter;
6552 ncci = a->ch_ncci[ch];
6553 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6554 if(plci->tel) Id|=EXT_CONTROLLER;
6555 APPLptr = plci->appl;
6556 dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6557 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6558
6559 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6560
6561 if (plci->nl_remove_id)
6562 {
6563 plci->NL.RNR = 2; /* discard */
6564 dbug(1,dprintf("NL discard while remove pending"));
6565 return;
6566 }
6567 if((plci->NL.Ind &0x0f)==N_CONNECT)
6568 {
6569 if(plci->State==INC_DIS_PENDING
6570 || plci->State==OUTG_DIS_PENDING
6571 || plci->State==IDLE)
6572 {
6573 plci->NL.RNR = 2; /* discard */
6574 dbug(1,dprintf("discard n_connect"));
6575 return;
6576 }
6577 if(plci->State < INC_ACT_PENDING)
6578 {
6579 plci->NL.RNR = 1; /* flow control */
6580 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6581 return;
6582 }
6583 }
6584
6585 if(!APPLptr) /* no application or invalid data */
6586 { /* while reloading the DSP */
6587 dbug(1,dprintf("discard1"));
6588 plci->NL.RNR = 2;
6589 return;
6590 }
6591
6592 if (((plci->NL.Ind &0x0f) == N_UDATA)
6593 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6594 || (plci->B2_prot == 7)
6595 || (plci->B3_prot == 7)) )
6596 {
6597 plci->ncpi_buffer[0] = 0;
6598
6599 ncpi_state = plci->ncpi_state;
6600 if (plci->NL.complete == 1)
6601 {
6602 byte * data = &plci->NL.RBuffer->P[0];
6603
6604 if ((plci->NL.RBuffer->length >= 12)
6605 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6606 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6607 {
6608 word conn_opt, ncpi_opt = 0x00;
6609/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6610
6611 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6612 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6613 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6614 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6615
6616 data++; /* indication code */
6617 data += 2; /* timestamp */
6618 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6619 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6620 data++; /* connected norm */
6621 conn_opt = GET_WORD(data);
6622 data += 2; /* connected options */
6623
6624 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6625
6626 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6627 {
6628 ncpi_opt |= MDM_NCPI_ECM_V42;
6629 }
6630 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6631 {
6632 ncpi_opt |= MDM_NCPI_ECM_MNP;
6633 }
6634 else
6635 {
6636 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6637 }
6638 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6639 {
6640 ncpi_opt |= MDM_NCPI_COMPRESSED;
6641 }
6642 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6643 plci->ncpi_buffer[0] = 4;
6644
6645 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6646 }
6647 }
6648 if (plci->B3_prot == 7)
6649 {
6650 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6651 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6652 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6653 {
6654 a->ncci_state[ncci] = INC_ACT_PENDING;
6655 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6656 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6657 }
6658 }
6659
6660 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6661 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6662 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6663 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6664
6665 {
6666 plci->NL.RNR = 2;
6667 return;
6668 }
6669 }
6670
6671 if(plci->NL.complete == 2)
6672 {
6673 if (((plci->NL.Ind &0x0f) == N_UDATA)
6674 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6675 {
6676 switch(plci->RData[0].P[0])
6677 {
6678
6679 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6680 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6681 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6682 break;
6683 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6684 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6685 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6686 break;
6687 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6688 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6689 break;
6690 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6691 dtmf_confirmation (Id, plci);
6692 break;
6693
6694
6695 case UDATA_INDICATION_MIXER_TAP_DATA:
6696 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6697 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6698 if (i != 0)
6699 {
6700 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6701 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6702 }
6703 break;
6704
6705
6706 case UDATA_INDICATION_MIXER_COEFS_SET:
6707 mixer_indication_coefs_set (Id, plci);
6708 break;
6709 case UDATA_INDICATION_XCONNECT_FROM:
6710 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6711 break;
6712 case UDATA_INDICATION_XCONNECT_TO:
6713 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714 break;
6715
6716
6717 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6718 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6719 break;
6720
6721
6722
6723 default:
6724 break;
6725 }
6726 }
6727 else
6728 {
6729 if ((plci->RData[0].PLength != 0)
6730 && ((plci->B2_prot == B2_V120_ASYNC)
6731 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6732 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6733 {
6734
6735 sendf(plci->appl,_DATA_B3_I,Id,0,
6736 "dwww",
6737 plci->RData[1].P,
6738 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6739 plci->RNum,
6740 plci->RFlags);
6741
6742 }
6743 else
6744 {
6745
6746 sendf(plci->appl,_DATA_B3_I,Id,0,
6747 "dwww",
6748 plci->RData[0].P,
6749 plci->RData[0].PLength,
6750 plci->RNum,
6751 plci->RFlags);
6752
6753 }
6754 }
6755 return;
6756 }
6757
6758 fax_feature_bits = 0;
6759 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6760 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6761 (plci->NL.Ind &0x0f)==N_DISC ||
6762 (plci->NL.Ind &0x0f)==N_EDATA ||
6763 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6764 {
6765 info = 0;
6766 plci->ncpi_buffer[0] = 0;
6767 switch (plci->B3_prot) {
6768 case 0: /*XPARENT*/
6769 case 1: /*T.90 NL*/
6770 break; /* no network control protocol info - jfr */
6771 case 2: /*ISO8202*/
6772 case 3: /*X25 DCE*/
6773 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6774 plci->ncpi_buffer[0] = (byte)(i+3);
6775 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6776 plci->ncpi_buffer[2] = 0;
6777 plci->ncpi_buffer[3] = 0;
6778 break;
6779 case 4: /*T.30 - FAX*/
6780 case 5: /*T.30 - FAX*/
6781 if(plci->NL.RLength>=sizeof(T30_INFO))
6782 {
6783 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6784 len = 9;
6785 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6786 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6787 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6788 if (plci->B3_prot == 5)
6789 {
6790 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6791 i |= 0x8000; /* This is not an ECM connection */
6792 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6793 i |= 0x4000; /* This is a connection with MMR compression */
6794 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6795 i |= 0x2000; /* This is a connection with MR compression */
6796 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6797 i |= 0x0004; /* More documents */
6798 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6799 i |= 0x0002; /* Fax-polling indication */
6800 }
6801 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6802 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6803 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6804 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6805 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6806 plci->ncpi_buffer[len] = 0;
6807 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6808 {
6809 plci->ncpi_buffer[len] = 20;
6810 for (i = 0; i < 20; i++)
6811 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6812 }
6813 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6814 {
6815 if (((T30_INFO *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
6816 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6817 else
6818 info = _FAX_PROTOCOL_ERROR;
6819 }
6820
6821 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6822 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6823 {
6824 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6825 while (i < plci->NL.RBuffer->length)
6826 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6827 }
6828
6829 plci->ncpi_buffer[0] = len;
6830 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6831 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6832
6833 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6834 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6835 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6836 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6837 || (((plci->NL.Ind &0x0f) == N_EDATA)
6838 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6839 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6840 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6841 {
6842 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6843 }
6844 if (((plci->NL.Ind &0x0f) == N_DISC)
6845 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6846 || (((plci->NL.Ind &0x0f) == N_EDATA)
6847 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6848 {
6849 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6850 }
6851 }
6852 break;
6853
6854 case B3_RTP:
6855 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6856 {
6857 if (plci->NL.RLength != 0)
6858 {
6859 info = rtp_info[plci->NL.RBuffer->P[0]];
6860 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6861 for (i = 1; i < plci->NL.RLength; i++)
6862 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6863 }
6864 }
6865 break;
6866
6867 }
6868 plci->NL.RNR = 2;
6869 }
6870 switch(plci->NL.Ind &0x0f) {
6871 case N_EDATA:
6872 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6873 {
6874 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6875 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6876 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6877
6878 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6879 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6880 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6881 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6882 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6883 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6884 {
6885 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6886 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6887 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6888 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6889 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006890 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006891 }
6892
6893 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6894 {
6895 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6896 {
6897 case EDATA_T30_DIS:
6898 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6899 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6900 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6901 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6902 {
6903 a->ncci_state[ncci] = INC_ACT_PENDING;
6904 if (plci->B3_prot == 4)
6905 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6906 else
6907 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6908 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6909 }
6910 break;
6911
6912 case EDATA_T30_TRAIN_OK:
6913 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6914 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6915 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6916 {
6917 if (plci->B3_prot == 4)
6918 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6919 else
6920 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6921 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6922 }
6923 break;
6924
6925 case EDATA_T30_EOP_CAPI:
6926 if (a->ncci_state[ncci] == CONNECTED)
6927 {
6928 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6929 a->ncci_state[ncci] = INC_DIS_PENDING;
6930 plci->ncpi_state = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006931 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006932 }
6933 break;
6934 }
6935 }
6936 else
6937 {
6938 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6939 {
6940 case EDATA_T30_TRAIN_OK:
6941 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6942 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6943 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6944 {
6945 if (plci->B3_prot == 4)
6946 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6947 else
6948 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6949 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6950 }
6951 break;
6952 }
6953 }
6954 if (fax_send_edata_ack)
6955 {
6956 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6957 plci->fax_edata_ack_length = 1;
6958 start_internal_command (Id, plci, fax_edata_ack_command);
6959 }
6960 }
6961 else
6962 {
6963 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6964 }
6965 break;
6966 case N_CONNECT:
6967 if (!a->ch_ncci[ch])
6968 {
6969 ncci = get_ncci (plci, ch, 0);
6970 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6971 }
6972 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6973 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6974
6975 msg = _CONNECT_B3_I;
6976 if (a->ncci_state[ncci] == IDLE)
6977 plci->channels++;
6978 else if (plci->B3_prot == 1)
6979 msg = _CONNECT_B3_T90_ACTIVE_I;
6980
6981 a->ncci_state[ncci] = INC_CON_PENDING;
6982 if(plci->B3_prot == 4)
6983 sendf(plci->appl,msg,Id,0,"s","");
6984 else
6985 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6986 break;
6987 case N_CONNECT_ACK:
6988 dbug(1,dprintf("N_connect_Ack"));
6989 if (plci->internal_command_queue[0]
6990 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6991 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6992 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6993 {
6994 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6995 if (!plci->internal_command)
6996 next_internal_command (Id, plci);
6997 break;
6998 }
6999 msg = _CONNECT_B3_ACTIVE_I;
7000 if (plci->B3_prot == 1)
7001 {
7002 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7003 msg = _CONNECT_B3_T90_ACTIVE_I;
7004 a->ncci_state[ncci] = INC_ACT_PENDING;
7005 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7006 }
7007 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7008 {
7009 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7010 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7011 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7012 {
7013 a->ncci_state[ncci] = INC_ACT_PENDING;
7014 if (plci->B3_prot == 4)
7015 sendf(plci->appl,msg,Id,0,"s","");
7016 else
7017 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7018 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7019 }
7020 }
7021 else
7022 {
7023 a->ncci_state[ncci] = INC_ACT_PENDING;
7024 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7025 }
7026 if (plci->adjust_b_restore)
7027 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007028 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007029 start_internal_command (Id, plci, adjust_b_restore);
7030 }
7031 break;
7032 case N_DISC:
7033 case N_DISC_ACK:
7034 if (plci->internal_command_queue[0]
7035 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7036 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7037 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7038 {
7039 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7040 if (!plci->internal_command)
7041 next_internal_command (Id, plci);
7042 }
7043 ncci_state = a->ncci_state[ncci];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007044 ncci_remove (plci, ncci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045
7046 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7047 /* channel, so we cannot store the state in ncci_state! The */
7048 /* information which channel we received a N_DISC is thus */
7049 /* stored in the inc_dis_ncci_table buffer. */
7050 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7051 plci->inc_dis_ncci_table[i] = (byte) ncci;
7052
7053 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7054 if (!plci->channels
7055 && (plci->B1_resource == 16)
7056 && (plci->State <= CONNECTED))
7057 {
7058 len = 9;
7059 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7060 PUT_WORD (&plci->ncpi_buffer[1], i);
7061 PUT_WORD (&plci->ncpi_buffer[3], 0);
7062 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7063 PUT_WORD (&plci->ncpi_buffer[5], i);
7064 PUT_WORD (&plci->ncpi_buffer[7], 0);
7065 plci->ncpi_buffer[len] = 0;
7066 plci->ncpi_buffer[0] = len;
7067 if(plci->B3_prot == 4)
7068 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7069 else
7070 {
7071
7072 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7073 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7074 {
7075 plci->ncpi_buffer[++len] = 0;
7076 plci->ncpi_buffer[++len] = 0;
7077 plci->ncpi_buffer[++len] = 0;
7078 plci->ncpi_buffer[0] = len;
7079 }
7080
7081 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7082 }
7083 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7084 plci->ncpi_state = 0;
7085 sig_req(plci,HANGUP,0);
7086 send_req(plci);
7087 plci->State = OUTG_DIS_PENDING;
7088 /* disc here */
7089 }
7090 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7091 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7092 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7093 {
7094 if (ncci_state == IDLE)
7095 {
7096 if (plci->channels)
7097 plci->channels--;
7098 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7099 if(plci->State == SUSPENDING){
7100 sendf(plci->appl,
7101 _FACILITY_I,
7102 Id & 0xffffL,
7103 0,
7104 "ws", (word)3, "\x03\x04\x00\x00");
7105 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7106 }
7107 plci_remove(plci);
7108 plci->State=IDLE;
7109 }
7110 }
7111 }
7112 else if (plci->channels)
7113 {
7114 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7115 plci->ncpi_state = 0;
7116 if ((ncci_state == OUTG_REJ_PENDING)
7117 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7118 {
7119 sig_req(plci,HANGUP,0);
7120 send_req(plci);
7121 plci->State = OUTG_DIS_PENDING;
7122 }
7123 }
7124 break;
7125 case N_RESET:
7126 a->ncci_state[ncci] = INC_RES_PENDING;
7127 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7128 break;
7129 case N_RESET_ACK:
7130 a->ncci_state[ncci] = CONNECTED;
7131 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7132 break;
7133
7134 case N_UDATA:
7135 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7136 {
7137 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7138 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7139 plci->NL.R = plci->RData;
7140 plci->NL.RNum = 1;
7141 return;
7142 }
7143 case N_BDATA:
7144 case N_DATA:
7145 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7146 || (a->ncci_state[ncci] == IDLE)
7147 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7148 {
7149 plci->NL.RNR = 2;
7150 break;
7151 }
7152 if ((a->ncci_state[ncci] != CONNECTED)
7153 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7154 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7155 {
7156 dbug(1,dprintf("flow control"));
7157 plci->NL.RNR = 1; /* flow control */
7158 channel_x_off (plci, ch, 0);
7159 break;
7160 }
7161
7162 NCCIcode = ncci | (((word)a->Id) << 8);
7163
7164 /* count all buffers within the Application pool */
7165 /* belonging to the same NCCI. If this is below the */
7166 /* number of buffers available per NCCI we accept */
7167 /* this packet, otherwise we reject it */
7168 count = 0;
7169 Num = 0xffff;
7170 for(i=0; i<APPLptr->MaxBuffer; i++) {
7171 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7172 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7173 }
7174
7175 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7176 {
7177 dbug(3,dprintf("Flow-Control"));
7178 plci->NL.RNR = 1;
7179 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7180 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7181 {
7182 plci->NL.RNR = 2;
7183 dbug(3,dprintf("DiscardData"));
7184 } else {
7185 channel_x_off (plci, ch, 0);
7186 }
7187 break;
7188 }
7189 else
7190 {
7191 APPLptr->NCCIDataFlowCtrlTimer = 0;
7192 }
7193
7194 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7195 if(!plci->RData[0].P) {
7196 plci->NL.RNR = 1;
7197 channel_x_off (plci, ch, 0);
7198 break;
7199 }
7200
7201 APPLptr->DataNCCI[Num] = NCCIcode;
7202 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7203 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7204
7205 plci->RNum = Num;
7206 plci->RFlags = plci->NL.Ind>>4;
7207 plci->RData[0].PLength = APPLptr->MaxDataLength;
7208 plci->NL.R = plci->RData;
7209 if ((plci->NL.RLength != 0)
7210 && ((plci->B2_prot == B2_V120_ASYNC)
7211 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7212 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7213 {
7214 plci->RData[1].P = plci->RData[0].P;
7215 plci->RData[1].PLength = plci->RData[0].PLength;
7216 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7217 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7218 plci->RData[0].PLength = 1;
7219 else
7220 plci->RData[0].PLength = 2;
7221 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7222 plci->RFlags |= 0x0010;
7223 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7224 plci->RFlags |= 0x8000;
7225 plci->NL.RNum = 2;
7226 }
7227 else
7228 {
7229 if((plci->NL.Ind &0x0f)==N_UDATA)
7230 plci->RFlags |= 0x0010;
7231
7232 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7233 plci->RFlags |= 0x0001;
7234
7235 plci->NL.RNum = 1;
7236 }
7237 break;
7238 case N_DATA_ACK:
7239 data_ack (plci, ch);
7240 break;
7241 default:
7242 plci->NL.RNR = 2;
7243 break;
7244 }
7245}
7246
7247/*------------------------------------------------------------------*/
7248/* find a free PLCI */
7249/*------------------------------------------------------------------*/
7250
7251word get_plci(DIVA_CAPI_ADAPTER * a)
7252{
7253 word i,j;
7254 PLCI * plci;
7255
7256 dump_plcis (a);
7257 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7258 if(i==a->max_plci) {
7259 dbug(1,dprintf("get_plci: out of PLCIs"));
7260 return 0;
7261 }
7262 plci = &a->plci[i];
7263 plci->Id = (byte)(i+1);
7264
7265 plci->Sig.Id = 0;
7266 plci->NL.Id = 0;
7267 plci->sig_req = 0;
7268 plci->nl_req = 0;
7269
7270 plci->appl = NULL;
7271 plci->relatedPTYPLCI = NULL;
7272 plci->State = IDLE;
7273 plci->SuppState = IDLE;
7274 plci->channels = 0;
7275 plci->tel = 0;
7276 plci->B1_resource = 0;
7277 plci->B2_prot = 0;
7278 plci->B3_prot = 0;
7279
7280 plci->command = 0;
7281 plci->m_command = 0;
7282 init_internal_command_queue (plci);
7283 plci->number = 0;
7284 plci->req_in_start = 0;
7285 plci->req_in = 0;
7286 plci->req_out = 0;
7287 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7288 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7289 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7290
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007291 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007292 plci->send_disc = 0;
7293 plci->sig_global_req = 0;
7294 plci->sig_remove_id = 0;
7295 plci->nl_global_req = 0;
7296 plci->nl_remove_id = 0;
7297 plci->adv_nl = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007298 plci->manufacturer = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7300 plci->spoofed_msg = 0;
7301 plci->ptyState = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007302 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007303 plci->hangup_flow_ctrl_timer = 0;
7304
7305 plci->ncci_ring_list = 0;
7306 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7307 clear_c_ind_mask (plci);
7308 set_group_ind_mask (plci);
7309 plci->fax_connect_info_length = 0;
7310 plci->nsf_control_bits = 0;
7311 plci->ncpi_state = 0x00;
7312 plci->ncpi_buffer[0] = 0;
7313
7314 plci->requested_options_conn = 0;
7315 plci->requested_options = 0;
7316 plci->notifiedcall = 0;
7317 plci->vswitchstate = 0;
7318 plci->vsprot = 0;
7319 plci->vsprotdialect = 0;
7320 init_b1_config (plci);
7321 dbug(1,dprintf("get_plci(%x)",plci->Id));
7322 return i+1;
7323}
7324
7325/*------------------------------------------------------------------*/
7326/* put a parameter in the parameter buffer */
7327/*------------------------------------------------------------------*/
7328
7329static void add_p(PLCI * plci, byte code, byte * p)
7330{
7331 word p_length;
7332
7333 p_length = 0;
7334 if(p) p_length = p[0];
7335 add_ie(plci, code, p, p_length);
7336}
7337
7338/*------------------------------------------------------------------*/
7339/* put a structure in the parameter buffer */
7340/*------------------------------------------------------------------*/
7341static void add_s(PLCI * plci, byte code, API_PARSE * p)
7342{
7343 if(p) add_ie(plci, code, p->info, (word)p->length);
7344}
7345
7346/*------------------------------------------------------------------*/
7347/* put multiple structures in the parameter buffer */
7348/*------------------------------------------------------------------*/
7349static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7350{
7351 byte i;
7352
7353 if(p){
7354 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7355 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7356 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7357 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7358 }
7359 }
7360}
7361
7362/*------------------------------------------------------------------*/
7363/* return the channel number sent by the application in a esc_chi */
7364/*------------------------------------------------------------------*/
7365static byte getChannel(API_PARSE * p)
7366{
7367 byte i;
7368
7369 if(p){
7370 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7371 if(p->info[i]==2){
7372 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7373 }
7374 }
7375 }
7376 return 0;
7377}
7378
7379
7380/*------------------------------------------------------------------*/
7381/* put an information element in the parameter buffer */
7382/*------------------------------------------------------------------*/
7383
7384static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7385{
7386 word i;
7387
7388 if(!(code &0x80) && !p_length) return;
7389
7390 if(plci->req_in==plci->req_in_start) {
7391 plci->req_in +=2;
7392 }
7393 else {
7394 plci->req_in--;
7395 }
7396 plci->RBuffer[plci->req_in++] = code;
7397
7398 if(p) {
7399 plci->RBuffer[plci->req_in++] = (byte)p_length;
7400 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7401 }
7402
7403 plci->RBuffer[plci->req_in++] = 0;
7404}
7405
7406/*------------------------------------------------------------------*/
7407/* put a unstructured data into the buffer */
7408/*------------------------------------------------------------------*/
7409
7410void add_d(PLCI * plci, word length, byte * p)
7411{
7412 word i;
7413
7414 if(plci->req_in==plci->req_in_start) {
7415 plci->req_in +=2;
7416 }
7417 else {
7418 plci->req_in--;
7419 }
7420 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7421}
7422
7423/*------------------------------------------------------------------*/
7424/* put parameters from the Additional Info parameter in the */
7425/* parameter buffer */
7426/*------------------------------------------------------------------*/
7427
7428void add_ai(PLCI * plci, API_PARSE * ai)
7429{
7430 word i;
7431 API_PARSE ai_parms[5];
7432
7433 for(i=0;i<5;i++) ai_parms[i].length = 0;
7434
7435 if(!ai->length)
7436 return;
7437 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7438 return;
7439
7440 add_s (plci,KEY,&ai_parms[1]);
7441 add_s (plci,UUI,&ai_parms[2]);
7442 add_ss(plci,FTY,&ai_parms[3]);
7443}
7444
7445/*------------------------------------------------------------------*/
7446/* put parameter for b1 protocol in the parameter buffer */
7447/*------------------------------------------------------------------*/
7448
7449word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7450{
7451 API_PARSE bp_parms[8];
7452 API_PARSE mdm_cfg[9];
7453 API_PARSE global_config[2];
7454 byte cai[256];
7455 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7456 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7457 word i;
7458
7459 API_PARSE mdm_cfg_v18[4];
7460 word j, n, w;
7461 dword d;
7462
7463
7464 for(i=0;i<8;i++) bp_parms[i].length = 0;
7465 for(i=0;i<2;i++) global_config[i].length = 0;
7466
7467 dbug(1,dprintf("add_b1"));
7468 api_save_msg(bp, "s", &plci->B_protocol);
7469
7470 if(b_channel_info==2){
7471 plci->B1_resource = 0;
7472 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7473 add_p(plci, CAI, "\x01\x00");
7474 dbug(1,dprintf("Cai=1,0 (no resource)"));
7475 return 0;
7476 }
7477
7478 if(plci->tel == CODEC_PERMANENT) return 0;
7479 else if(plci->tel == CODEC){
7480 plci->B1_resource = 1;
7481 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7482 add_p(plci, CAI, "\x01\x01");
7483 dbug(1,dprintf("Cai=1,1 (Codec)"));
7484 return 0;
7485 }
7486 else if(plci->tel == ADV_VOICE){
7487 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7488 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7489 voice_cai[1] = plci->B1_resource;
7490 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7491 add_p(plci, CAI, voice_cai);
7492 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7493 return 0;
7494 }
7495 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7496 if (plci->call_dir & CALL_DIR_OUT)
7497 plci->call_dir |= CALL_DIR_ORIGINATE;
7498 else if (plci->call_dir & CALL_DIR_IN)
7499 plci->call_dir |= CALL_DIR_ANSWER;
7500
7501 if(!bp->length){
7502 plci->B1_resource = 0x5;
7503 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7504 add_p(plci, CAI, "\x01\x05");
7505 return 0;
7506 }
7507
7508 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7509 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7510 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7511 {
7512 bp_parms[6].length = 0;
7513 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7514 {
7515 dbug(1,dprintf("b-form.!"));
7516 return _WRONG_MESSAGE_FORMAT;
7517 }
7518 }
7519 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7520 {
7521 dbug(1,dprintf("b-form.!"));
7522 return _WRONG_MESSAGE_FORMAT;
7523 }
7524
7525 if(bp_parms[6].length)
7526 {
7527 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7528 {
7529 return _WRONG_MESSAGE_FORMAT;
7530 }
7531 switch(GET_WORD(global_config[0].info))
7532 {
7533 case 1:
7534 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7535 break;
7536 case 2:
7537 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7538 break;
7539 }
7540 }
7541 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7542
7543
7544 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7545 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7546 {
7547 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7549 cai[1] = plci->B1_resource;
7550 cai[2] = 0;
7551 cai[3] = 0;
7552 cai[4] = 0;
7553 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7554 for (i = 0; i < bp_parms[3].length; i++)
7555 cai[7+i] = bp_parms[3].info[1+i];
7556 cai[0] = 6 + bp_parms[3].length;
7557 add_p(plci, CAI, cai);
7558 return 0;
7559 }
7560
7561
7562 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7563 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7564 {
7565 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567 cai[1] = plci->B1_resource;
7568 cai[2] = 0;
7569 cai[3] = 0;
7570 cai[4] = 0;
7571 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7572 cai[0] = 6;
7573 add_p(plci, CAI, cai);
7574 return 0;
7575 }
7576
7577
7578 if ((GET_WORD(bp_parms[0].info) >= 32)
7579 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7580 && ((GET_WORD(bp_parms[0].info) != 3)
7581 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7582 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7583 {
7584 return _B1_NOT_SUPPORTED;
7585 }
7586 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7587 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7589 cai[0] = 6;
7590 cai[1] = plci->B1_resource;
7591 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7592
7593 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7594 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7595 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7596 { /* B1 - modem */
7597 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7598
7599 if (bp_parms[3].length)
7600 {
7601 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7602 {
7603 return (_WRONG_MESSAGE_FORMAT);
7604 }
7605
7606 cai[2] = 0; /* Bit rate for adaptation */
7607
7608 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7609
7610 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7611 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7612 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7613 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7614
7615 cai[3] = 0; /* Async framing parameters */
7616 switch (GET_WORD (mdm_cfg[2].info))
7617 { /* Parity */
7618 case 1: /* odd parity */
7619 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7620 dbug(1,dprintf("MDM: odd parity"));
7621 break;
7622
7623 case 2: /* even parity */
7624 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7625 dbug(1,dprintf("MDM: even parity"));
7626 break;
7627
7628 default:
7629 dbug(1,dprintf("MDM: no parity"));
7630 break;
7631 }
7632
7633 switch (GET_WORD (mdm_cfg[3].info))
7634 { /* stop bits */
7635 case 1: /* 2 stop bits */
7636 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7637 dbug(1,dprintf("MDM: 2 stop bits"));
7638 break;
7639
7640 default:
7641 dbug(1,dprintf("MDM: 1 stop bit"));
7642 break;
7643 }
7644
7645 switch (GET_WORD (mdm_cfg[1].info))
7646 { /* char length */
7647 case 5:
7648 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7649 dbug(1,dprintf("MDM: 5 bits"));
7650 break;
7651
7652 case 6:
7653 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7654 dbug(1,dprintf("MDM: 6 bits"));
7655 break;
7656
7657 case 7:
7658 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7659 dbug(1,dprintf("MDM: 7 bits"));
7660 break;
7661
7662 default:
7663 dbug(1,dprintf("MDM: 8 bits"));
7664 break;
7665 }
7666
7667 cai[7] = 0; /* Line taking options */
7668 cai[8] = 0; /* Modulation negotiation options */
7669 cai[9] = 0; /* Modulation options */
7670
7671 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7672 {
7673 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7674 dbug(1, dprintf("MDM: Reverse direction"));
7675 }
7676
7677 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7678 {
7679 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7680 dbug(1, dprintf("MDM: Disable retrain"));
7681 }
7682
7683 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7684 {
7685 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7686 dbug(1, dprintf("MDM: Disable ring tone"));
7687 }
7688
7689 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7690 {
7691 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7692 dbug(1, dprintf("MDM: 1800 guard tone"));
7693 }
7694 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7695 {
7696 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7697 dbug(1, dprintf("MDM: 550 guard tone"));
7698 }
7699
7700 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7701 {
7702 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7703 dbug(1, dprintf("MDM: V100"));
7704 }
7705 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7706 {
7707 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7708 dbug(1, dprintf("MDM: IN CLASS"));
7709 }
7710 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7711 {
7712 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7713 dbug(1, dprintf("MDM: DISABLED"));
7714 }
7715 cai[0] = 20;
7716
7717 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7718 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7719 {
7720 plci->requested_options |= 1L << PRIVATE_V18;
7721 }
7722 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7723 plci->requested_options |= 1L << PRIVATE_VOWN;
7724
7725 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7726 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7727 {
7728 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7729 {
7730 i = 27;
7731 if (mdm_cfg[6].length >= 4)
7732 {
7733 d = GET_DWORD(&mdm_cfg[6].info[1]);
7734 cai[7] |= (byte) d; /* line taking options */
7735 cai[9] |= (byte)(d >> 8); /* modulation options */
7736 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7737 cai[++i] = (byte)(d >> 24);
7738 if (mdm_cfg[6].length >= 8)
7739 {
7740 d = GET_DWORD(&mdm_cfg[6].info[5]);
7741 cai[10] |= (byte) d; /* disabled modulations mask */
7742 cai[11] |= (byte)(d >> 8);
7743 if (mdm_cfg[6].length >= 12)
7744 {
7745 d = GET_DWORD(&mdm_cfg[6].info[9]);
7746 cai[12] = (byte) d; /* enabled modulations mask */
7747 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7748 cai[++i] = (byte)(d >> 16);
7749 cai[++i] = (byte)(d >> 24);
7750 cai[++i] = 0;
7751 if (mdm_cfg[6].length >= 14)
7752 {
7753 w = GET_WORD(&mdm_cfg[6].info[13]);
7754 if (w != 0)
7755 PUT_WORD(&cai[13], w); /* min tx speed */
7756 if (mdm_cfg[6].length >= 16)
7757 {
7758 w = GET_WORD(&mdm_cfg[6].info[15]);
7759 if (w != 0)
7760 PUT_WORD(&cai[15], w); /* max tx speed */
7761 if (mdm_cfg[6].length >= 18)
7762 {
7763 w = GET_WORD(&mdm_cfg[6].info[17]);
7764 if (w != 0)
7765 PUT_WORD(&cai[17], w); /* min rx speed */
7766 if (mdm_cfg[6].length >= 20)
7767 {
7768 w = GET_WORD(&mdm_cfg[6].info[19]);
7769 if (w != 0)
7770 PUT_WORD(&cai[19], w); /* max rx speed */
7771 if (mdm_cfg[6].length >= 22)
7772 {
7773 w = GET_WORD(&mdm_cfg[6].info[21]);
7774 cai[23] = (byte)(-((short) w)); /* transmit level */
7775 if (mdm_cfg[6].length >= 24)
7776 {
7777 w = GET_WORD(&mdm_cfg[6].info[23]);
7778 cai[22] |= (byte) w; /* info options mask */
7779 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7780 }
7781 }
7782 }
7783 }
7784 }
7785 }
7786 }
7787 }
7788 }
7789 cai[27] = i - 27;
7790 i++;
7791 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7792 {
7793 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7794 {
7795 for (n = 0; n < 3; n++)
7796 {
7797 cai[i] = (byte)(mdm_cfg_v18[n].length);
7798 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7799 cai[i+j] = mdm_cfg_v18[n].info[j];
7800 i += cai[i] + 1;
7801 }
7802 }
7803 }
7804 cai[0] = (byte)(i - 1);
7805 }
7806 }
7807
7808 }
7809 }
7810 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7811 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7812 {
7813 if(bp_parms[3].length){
7814 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7815 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7816 case 0:
7817 case 56000:
7818 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7819 dbug(1,dprintf("56k sync HSCX"));
7820 cai[1] = 8;
7821 cai[2] = 0;
7822 cai[3] = 0;
7823 }
7824 else if(GET_WORD(bp_parms[0].info)==2){
7825 dbug(1,dprintf("56k async DSP"));
7826 cai[2] = 9;
7827 }
7828 break;
7829 case 50: cai[2] = 1; break;
7830 case 75: cai[2] = 1; break;
7831 case 110: cai[2] = 1; break;
7832 case 150: cai[2] = 1; break;
7833 case 200: cai[2] = 1; break;
7834 case 300: cai[2] = 1; break;
7835 case 600: cai[2] = 1; break;
7836 case 1200: cai[2] = 2; break;
7837 case 2400: cai[2] = 3; break;
7838 case 4800: cai[2] = 4; break;
7839 case 7200: cai[2] = 10; break;
7840 case 9600: cai[2] = 5; break;
7841 case 12000: cai[2] = 13; break;
7842 case 24000: cai[2] = 0; break;
7843 case 14400: cai[2] = 11; break;
7844 case 19200: cai[2] = 6; break;
7845 case 28800: cai[2] = 12; break;
7846 case 38400: cai[2] = 7; break;
7847 case 48000: cai[2] = 8; break;
7848 case 76: cai[2] = 15; break; /* 75/1200 */
7849 case 1201: cai[2] = 14; break; /* 1200/75 */
7850 case 56001: cai[2] = 9; break; /* V.110 56000 */
7851
7852 default:
7853 return _B1_PARM_NOT_SUPPORTED;
7854 }
7855 cai[3] = 0;
7856 if (cai[1] == 13) /* v.110 async */
7857 {
7858 if (bp_parms[3].length >= 8)
7859 {
7860 switch (GET_WORD (&bp_parms[3].info[3]))
7861 { /* char length */
7862 case 5:
7863 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7864 break;
7865 case 6:
7866 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7867 break;
7868 case 7:
7869 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7870 break;
7871 }
7872 switch (GET_WORD (&bp_parms[3].info[5]))
7873 { /* Parity */
7874 case 1: /* odd parity */
7875 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7876 break;
7877 case 2: /* even parity */
7878 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7879 break;
7880 }
7881 switch (GET_WORD (&bp_parms[3].info[7]))
7882 { /* stop bits */
7883 case 1: /* 2 stop bits */
7884 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7885 break;
7886 }
7887 }
7888 }
7889 }
7890 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7891 dbug(1,dprintf("V.110 default 56k sync"));
7892 cai[1] = 8;
7893 cai[2] = 0;
7894 cai[3] = 0;
7895 }
7896 else {
7897 dbug(1,dprintf("V.110 default 9600 async"));
7898 cai[2] = 5;
7899 }
7900 }
7901 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7902 dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7903/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7904
7905 add_p(plci, CAI, cai);
7906 return 0;
7907}
7908
7909/*------------------------------------------------------------------*/
7910/* put parameter for b2 and B3 protocol in the parameter buffer */
7911/*------------------------------------------------------------------*/
7912
7913word add_b23(PLCI * plci, API_PARSE * bp)
7914{
7915 word i, fax_control_bits;
7916 byte pos, len;
7917 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7918 API_PARSE bp_parms[8];
7919 API_PARSE * b1_config;
7920 API_PARSE * b2_config;
7921 API_PARSE b2_config_parms[8];
7922 API_PARSE * b3_config;
7923 API_PARSE b3_config_parms[6];
7924 API_PARSE global_config[2];
7925
7926 static byte llc[3] = {2,0,0};
7927 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7928 static byte nlc[256];
7929 static byte lli[12] = {1,1};
7930
7931 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7933
7934 const byte llc3[] = {4,3,2,2,6,6,0};
7935 const byte header[] = {0,2,3,3,0,0,0};
7936
7937 for(i=0;i<8;i++) bp_parms[i].length = 0;
7938 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7939 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7940
7941 lli[0] = 1;
7942 lli[1] = 1;
7943 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7944 lli[1] |= 2;
7945 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7946 lli[1] |= 4;
7947
7948 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7949 lli[1] |= 0x10;
7950 if (plci->rx_dma_descriptor <= 0) {
7951 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7952 if (plci->rx_dma_descriptor >= 0)
7953 plci->rx_dma_descriptor++;
7954 }
7955 if (plci->rx_dma_descriptor > 0) {
7956 lli[0] = 6;
7957 lli[1] |= 0x40;
7958 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7959 lli[3] = (byte)plci->rx_dma_magic;
7960 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7961 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7962 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7963 }
7964 }
7965
7966 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7967 lli[1] |= 0x20;
7968 }
7969
7970 dbug(1,dprintf("add_b23"));
7971 api_save_msg(bp, "s", &plci->B_protocol);
7972
7973 if(!bp->length && plci->tel)
7974 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007975 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007976 dbug(1,dprintf("Default adv.Nl"));
7977 add_p(plci,LLI,lli);
7978 plci->B2_prot = 1 /*XPARENT*/;
7979 plci->B3_prot = 0 /*XPARENT*/;
7980 llc[1] = 2;
7981 llc[2] = 4;
7982 add_p(plci, LLC, llc);
7983 dlc[0] = 2;
7984 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7985 add_p(plci, DLC, dlc);
7986 return 0;
7987 }
7988
7989 if(!bp->length) /*default*/
7990 {
7991 dbug(1,dprintf("ret default"));
7992 add_p(plci,LLI,lli);
7993 plci->B2_prot = 0 /*X.75 */;
7994 plci->B3_prot = 0 /*XPARENT*/;
7995 llc[1] = 1;
7996 llc[2] = 4;
7997 add_p(plci, LLC, llc);
7998 dlc[0] = 2;
7999 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8000 add_p(plci, DLC, dlc);
8001 return 0;
8002 }
8003 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8004 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8005
8006 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8007 {
8008 bp_parms[6].length = 0;
8009 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8010 {
8011 dbug(1,dprintf("b-form.!"));
8012 return _WRONG_MESSAGE_FORMAT;
8013 }
8014 }
8015 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8016 {
8017 dbug(1,dprintf("b-form.!"));
8018 return _WRONG_MESSAGE_FORMAT;
8019 }
8020
8021 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8022 {
8023 if(GET_WORD(bp_parms[1].info)!=1
8024 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008025 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008026 }
8027 else if(plci->tel) return _B2_NOT_SUPPORTED;
8028
8029
8030 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8031 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8032 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8033 {
8034 add_p(plci,LLI,lli);
8035 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8036 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8037 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8038 llc[2] = 4;
8039 add_p(plci, LLC, llc);
8040 dlc[0] = 2;
8041 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8042 dlc[3] = 3; /* Addr A */
8043 dlc[4] = 1; /* Addr B */
8044 dlc[5] = 7; /* modulo mode */
8045 dlc[6] = 7; /* window size */
8046 dlc[7] = 0; /* XID len Lo */
8047 dlc[8] = 0; /* XID len Hi */
8048 for (i = 0; i < bp_parms[4].length; i++)
8049 dlc[9+i] = bp_parms[4].info[1+i];
8050 dlc[0] = (byte)(8 + bp_parms[4].length);
8051 add_p(plci, DLC, dlc);
8052 for (i = 0; i < bp_parms[5].length; i++)
8053 nlc[1+i] = bp_parms[5].info[1+i];
8054 nlc[0] = (byte)(bp_parms[5].length);
8055 add_p(plci, NLC, nlc);
8056 return 0;
8057 }
8058
8059
8060
8061 if ((GET_WORD(bp_parms[1].info) >= 32)
8062 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8063 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8064 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8065
8066 {
8067 return _B2_NOT_SUPPORTED;
8068 }
8069 if ((GET_WORD(bp_parms[2].info) >= 32)
8070 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8071 {
8072 return _B3_NOT_SUPPORTED;
8073 }
8074 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8075 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8076 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8077 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8078 {
8079 return (add_modem_b23 (plci, bp_parms));
8080 }
8081
8082 add_p(plci,LLI,lli);
8083
8084 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8085 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8086 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8087
8088 if(bp_parms[6].length)
8089 {
8090 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8091 {
8092 return _WRONG_MESSAGE_FORMAT;
8093 }
8094 switch(GET_WORD(global_config[0].info))
8095 {
8096 case 1:
8097 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8098 break;
8099 case 2:
8100 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8101 break;
8102 }
8103 }
8104 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8105
8106
8107 if (plci->B2_prot == B2_PIAFS)
8108 llc[1] = PIAFS_CRC;
8109 else
8110/* IMPLEMENT_PIAFS */
8111 {
8112 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8113 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8114 }
8115 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8116
8117 add_p(plci, LLC, llc);
8118
8119 dlc[0] = 2;
8120 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8121 header[GET_WORD(bp_parms[2].info)]);
8122
8123 b1_config = &bp_parms[3];
8124 nlc[0] = 0;
8125 if(plci->B3_prot == 4
8126 || plci->B3_prot == 5)
8127 {
8128 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8129 nlc[0] = sizeof(T30_INFO);
8130 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8131 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8132 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8133 if(b1_config->length>=2)
8134 {
8135 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8136 }
8137 }
8138 b2_config = &bp_parms[4];
8139
8140
8141 if (llc[1] == PIAFS_CRC)
8142 {
8143 if (plci->B3_prot != B3_TRANSPARENT)
8144 {
8145 return _B_STACK_NOT_SUPPORTED;
8146 }
8147 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8148 return _WRONG_MESSAGE_FORMAT;
8149 }
8150 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8151 dlc[3] = 0; /* Addr A */
8152 dlc[4] = 0; /* Addr B */
8153 dlc[5] = 0; /* modulo mode */
8154 dlc[6] = 0; /* window size */
8155 if (b2_config->length >= 7){
8156 dlc[ 7] = 7;
8157 dlc[ 8] = 0;
8158 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8159 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8160 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8161 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8162 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8163 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8164 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8165 dlc[ 0] = 15;
8166 if(b2_config->length >= 8) { /* PIAFS control abilities */
8167 dlc[ 7] = 10;
8168 dlc[16] = 2; /* Length of PIAFS extention */
8169 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8170 dlc[18] = b2_config_parms[4].info[0]; /* value */
8171 dlc[ 0] = 18;
8172 }
8173 }
8174 else /* default values, 64K, variable, no compression */
8175 {
8176 dlc[ 7] = 7;
8177 dlc[ 8] = 0;
8178 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8179 dlc[10] = 0x03; /* V.42bis P0 */
8180 dlc[11] = 0; /* V.42bis P0 */
8181 dlc[12] = 0; /* V.42bis P1 */
8182 dlc[13] = 0; /* V.42bis P1 */
8183 dlc[14] = 0; /* V.42bis P2 */
8184 dlc[15] = 0; /* V.42bis P2 */
8185 dlc[ 0] = 15;
8186 }
8187 add_p(plci, DLC, dlc);
8188 }
8189 else
8190
8191 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8192 {
8193 if (plci->B3_prot != B3_TRANSPARENT)
8194 return _B_STACK_NOT_SUPPORTED;
8195
8196 dlc[0] = 6;
8197 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8198 dlc[3] = 0x08;
8199 dlc[4] = 0x01;
8200 dlc[5] = 127;
8201 dlc[6] = 7;
8202 if (b2_config->length != 0)
8203 {
8204 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8205 return _WRONG_MESSAGE_FORMAT;
8206 }
8207 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8208 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8209 if (b2_config->info[3] != 128)
8210 {
8211 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8212 return _B2_PARM_NOT_SUPPORTED;
8213 }
8214 dlc[5] = (byte)(b2_config->info[3] - 1);
8215 dlc[6] = b2_config->info[4];
8216 if(llc[1]==V120_V42BIS){
8217 if (b2_config->length >= 10){
8218 dlc[ 7] = 6;
8219 dlc[ 8] = 0;
8220 dlc[ 9] = b2_config_parms[4].info[0];
8221 dlc[10] = b2_config_parms[4].info[1];
8222 dlc[11] = b2_config_parms[5].info[0];
8223 dlc[12] = b2_config_parms[5].info[1];
8224 dlc[13] = b2_config_parms[6].info[0];
8225 dlc[14] = b2_config_parms[6].info[1];
8226 dlc[ 0] = 14;
8227 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8228 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8229 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8230 }
8231 else {
8232 dlc[ 6] = 14;
8233 }
8234 }
8235 }
8236 }
8237 else
8238 {
8239 if(b2_config->length)
8240 {
8241 dbug(1,dprintf("B2-Config"));
8242 if(llc[1]==X75_V42BIS){
8243 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8244 {
8245 return _WRONG_MESSAGE_FORMAT;
8246 }
8247 }
8248 else {
8249 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8250 {
8251 return _WRONG_MESSAGE_FORMAT;
8252 }
8253 }
8254 /* if B2 Protocol is LAPD, b2_config structure is different */
8255 if(llc[1]==6)
8256 {
8257 dlc[0] = 4;
8258 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8259 else dlc[2] = 0x01;
8260 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8261 {
8262 SAPI = b2_config->info[2]; /* SAPI */
8263 }
8264 dlc[1] = SAPI;
8265 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8266 {
8267 dlc[3] = 127; /* Mode */
8268 }
8269 else
8270 {
8271 dlc[3] = 7; /* Mode */
8272 }
8273
8274 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8275 else dlc[4] = 1;
8276 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8277 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8278 }
8279 else
8280 {
8281 dlc[0] = (byte)(b2_config_parms[4].length+6);
8282 dlc[3] = b2_config->info[1];
8283 dlc[4] = b2_config->info[2];
8284 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8285 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8286 return _B2_PARM_NOT_SUPPORTED;
8287 }
8288
8289 dlc[5] = (byte)(b2_config->info[3]-1);
8290 dlc[6] = b2_config->info[4];
8291 if(dlc[6]>dlc[5]){
8292 dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8293 return _B2_PARM_NOT_SUPPORTED;
8294 }
8295
8296 if(llc[1]==X75_V42BIS) {
8297 if (b2_config->length >= 10){
8298 dlc[ 7] = 6;
8299 dlc[ 8] = 0;
8300 dlc[ 9] = b2_config_parms[4].info[0];
8301 dlc[10] = b2_config_parms[4].info[1];
8302 dlc[11] = b2_config_parms[5].info[0];
8303 dlc[12] = b2_config_parms[5].info[1];
8304 dlc[13] = b2_config_parms[6].info[0];
8305 dlc[14] = b2_config_parms[6].info[1];
8306 dlc[ 0] = 14;
8307 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8308 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8309 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8310 }
8311 else {
8312 dlc[ 6] = 14;
8313 }
8314
8315 }
8316 else {
8317 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8318 for(i=0; i<b2_config_parms[4].length; i++)
8319 dlc[11+i] = b2_config_parms[4].info[1+i];
8320 }
8321 }
8322 }
8323 }
8324 add_p(plci, DLC, dlc);
8325
8326 b3_config = &bp_parms[5];
8327 if(b3_config->length)
8328 {
8329 if(plci->B3_prot == 4
8330 || plci->B3_prot == 5)
8331 {
8332 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8333 {
8334 return _WRONG_MESSAGE_FORMAT;
8335 }
8336 i = GET_WORD((byte *)(b3_config_parms[0].info));
8337 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8338 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8339 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8340 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8341 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8342 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8343 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8344 {
8345
8346 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8347 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8348 {
8349 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8350 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8351 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8352 }
8353
8354 ((T30_INFO *)&nlc[1])->recording_properties =
8355 T30_RECORDING_WIDTH_ISO_A3 |
8356 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8357 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8358 }
8359 if(plci->B3_prot == 5)
8360 {
8361 if (i & 0x0002) /* Accept incoming fax-polling requests */
8362 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8363 if (i & 0x2000) /* Do not use MR compression */
8364 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8365 if (i & 0x4000) /* Do not use MMR compression */
8366 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8367 if (i & 0x8000) /* Do not use ECM */
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8369 if (plci->fax_connect_info_length != 0)
8370 {
8371 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8372 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8373 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8374 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8375 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8376 }
8377 }
8378 /* copy station id to NLC */
8379 for(i=0; i<20; i++)
8380 {
8381 if(i<b3_config_parms[2].length)
8382 {
8383 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8384 }
8385 else
8386 {
8387 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8388 }
8389 }
8390 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8391 /* copy head line to NLC */
8392 if(b3_config_parms[3].length)
8393 {
8394
8395 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8396 if (pos != 0)
8397 {
8398 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8399 pos = 0;
8400 else
8401 {
8402 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8404 len = (byte)b3_config_parms[2].length;
8405 if (len > 20)
8406 len = 20;
8407 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8408 {
8409 for (i = 0; i < len; i++)
8410 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8411 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8413 }
8414 }
8415 }
8416
8417 len = (byte)b3_config_parms[3].length;
8418 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8419 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8420 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8421 nlc[0] += (byte)(pos + len);
8422 for (i = 0; i < len; i++)
8423 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8424 }
8425 else
8426 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8427
8428 plci->nsf_control_bits = 0;
8429 if(plci->B3_prot == 5)
8430 {
8431 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8432 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8433 {
8434 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8435 }
8436 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8437 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8438 {
8439 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8440 }
8441 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8442 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8443 {
8444 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8445 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8446 {
8447 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8448 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8449 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8450 }
8451 len = nlc[0];
8452 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8453 if (pos < plci->fax_connect_info_length)
8454 {
8455 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8456 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8457 }
8458 else
8459 nlc[++len] = 0;
8460 if (pos < plci->fax_connect_info_length)
8461 {
8462 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8463 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8464 }
8465 else
8466 nlc[++len] = 0;
8467 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468 & (1L << PRIVATE_FAX_NONSTANDARD))
8469 {
8470 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8471 {
8472 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8473 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8474 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476 }
8477 else
8478 {
8479 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8480 {
8481 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8482 nlc[++len] = 0;
8483 }
8484 else
8485 {
8486 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8487 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8488 nlc[++len] = (byte)(b3_config_parms[4].length);
8489 for (i = 0; i < b3_config_parms[4].length; i++)
8490 nlc[++len] = b3_config_parms[4].info[1+i];
8491 }
8492 }
8493 }
8494 nlc[0] = len;
8495 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8496 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8497 {
8498 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8499 }
8500 }
8501 }
8502
8503 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8504 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8505 for (i = 0; i < len; i++)
8506 plci->fax_connect_info_buffer[i] = nlc[1+i];
8507 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8508 i += ((T30_INFO *)&nlc[1])->head_line_len;
8509 while (i < nlc[0])
8510 plci->fax_connect_info_buffer[len++] = nlc[++i];
8511 plci->fax_connect_info_length = len;
8512 }
8513 else
8514 {
8515 nlc[0] = 14;
8516 if(b3_config->length!=16)
8517 return _B3_PARM_NOT_SUPPORTED;
8518 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8519 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8520 return _B3_PARM_NOT_SUPPORTED;
8521 nlc[13] = b3_config->info[13];
8522 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8523 return _B3_PARM_NOT_SUPPORTED;
8524 nlc[14] = b3_config->info[15];
8525 }
8526 }
8527 else
8528 {
8529 if (plci->B3_prot == 4
8530 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8531 }
8532 add_p(plci, NLC, nlc);
8533 return 0;
8534}
8535
8536/*----------------------------------------------------------------*/
8537/* make the same as add_b23, but only for the modem related */
8538/* L2 and L3 B-Chan protocol. */
8539/* */
8540/* Enabled L2 and L3 Configurations: */
8541/* If L1 == Modem all negotiation */
8542/* only L2 == Modem with full negotiation is allowed */
8543/* If L1 == Modem async or sync */
8544/* only L2 == Transparent is allowed */
8545/* L3 == Modem or L3 == Transparent are allowed */
8546/* B2 Configuration for modem: */
8547/* word : enable/disable compression, bitoptions */
8548/* B3 Configuration for modem: */
8549/* empty */
8550/*----------------------------------------------------------------*/
8551static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8552{
8553 static byte lli[12] = {1,1};
8554 static byte llc[3] = {2,0,0};
8555 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8556 API_PARSE mdm_config[2];
8557 word i;
8558 word b2_config = 0;
8559
8560 for(i=0;i<2;i++) mdm_config[i].length = 0;
8561 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8562
8563 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8564 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8565 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8566 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8567 {
8568 return (_B_STACK_NOT_SUPPORTED);
8569 }
8570 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8571 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8572 {
8573 return (_B_STACK_NOT_SUPPORTED);
8574 }
8575
8576 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8577 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8578
8579 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8580 {
8581 if (api_parse (&bp_parms[4].info[1],
8582 (word)bp_parms[4].length, "w",
8583 mdm_config))
8584 {
8585 return (_WRONG_MESSAGE_FORMAT);
8586 }
8587 b2_config = GET_WORD(mdm_config[0].info);
8588 }
8589
8590 /* OK, L2 is modem */
8591
8592 lli[0] = 1;
8593 lli[1] = 1;
8594 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8595 lli[1] |= 2;
8596 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8597 lli[1] |= 4;
8598
8599 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8600 lli[1] |= 0x10;
8601 if (plci->rx_dma_descriptor <= 0) {
8602 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8603 if (plci->rx_dma_descriptor >= 0)
8604 plci->rx_dma_descriptor++;
8605 }
8606 if (plci->rx_dma_descriptor > 0) {
8607 lli[1] |= 0x40;
8608 lli[0] = 6;
8609 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8610 lli[3] = (byte)plci->rx_dma_magic;
8611 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8612 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8613 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8614 }
8615 }
8616
8617 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8618 lli[1] |= 0x20;
8619 }
8620
8621 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8622 /*V42*/ 10 : /*V42_IN*/ 9;
8623 llc[2] = 4; /* pass L3 always transparent */
8624 add_p(plci, LLI, lli);
8625 add_p(plci, LLC, llc);
8626 i = 1;
8627 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8628 i += 2;
8629 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8630 {
8631 if (bp_parms[4].length)
8632 {
8633 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8634 dlc[i++] = 3; /* Addr A */
8635 dlc[i++] = 1; /* Addr B */
8636 dlc[i++] = 7; /* modulo mode */
8637 dlc[i++] = 7; /* window size */
8638 dlc[i++] = 0; /* XID len Lo */
8639 dlc[i++] = 0; /* XID len Hi */
8640
8641 if (b2_config & MDM_B2_DISABLE_V42bis)
8642 {
8643 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8644 }
8645 if (b2_config & MDM_B2_DISABLE_MNP)
8646 {
8647 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8648 }
8649 if (b2_config & MDM_B2_DISABLE_TRANS)
8650 {
8651 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8652 }
8653 if (b2_config & MDM_B2_DISABLE_V42)
8654 {
8655 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8656 }
8657 if (b2_config & MDM_B2_DISABLE_COMP)
8658 {
8659 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8660 }
8661 i++;
8662 }
8663 }
8664 else
8665 {
8666 dlc[i++] = 3; /* Addr A */
8667 dlc[i++] = 1; /* Addr B */
8668 dlc[i++] = 7; /* modulo mode */
8669 dlc[i++] = 7; /* window size */
8670 dlc[i++] = 0; /* XID len Lo */
8671 dlc[i++] = 0; /* XID len Hi */
8672 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8673 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8674 DLC_MODEMPROT_DISABLE_V42_DETECT |
8675 DLC_MODEMPROT_DISABLE_COMPRESSION;
8676 }
8677 dlc[0] = (byte)(i - 1);
8678/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8679 add_p(plci, DLC, dlc);
8680 return (0);
8681}
8682
8683
8684/*------------------------------------------------------------------*/
8685/* send a request for the signaling entity */
8686/*------------------------------------------------------------------*/
8687
8688void sig_req(PLCI * plci, byte req, byte Id)
8689{
8690 if(!plci) return;
8691 if(plci->adapter->adapter_disabled) return;
8692 dbug(1,dprintf("sig_req(%x)",req));
8693 if (req == REMOVE)
8694 plci->sig_remove_id = plci->Sig.Id;
8695 if(plci->req_in==plci->req_in_start) {
8696 plci->req_in +=2;
8697 plci->RBuffer[plci->req_in++] = 0;
8698 }
8699 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8700 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8701 plci->RBuffer[plci->req_in++] = req; /* request */
8702 plci->RBuffer[plci->req_in++] = 0; /* channel */
8703 plci->req_in_start = plci->req_in;
8704}
8705
8706/*------------------------------------------------------------------*/
8707/* send a request for the network layer entity */
8708/*------------------------------------------------------------------*/
8709
8710void nl_req_ncci(PLCI * plci, byte req, byte ncci)
8711{
8712 if(!plci) return;
8713 if(plci->adapter->adapter_disabled) return;
8714 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8715 if (req == REMOVE)
8716 {
8717 plci->nl_remove_id = plci->NL.Id;
8718 ncci_remove (plci, 0, (byte)(ncci != 0));
8719 ncci = 0;
8720 }
8721 if(plci->req_in==plci->req_in_start) {
8722 plci->req_in +=2;
8723 plci->RBuffer[plci->req_in++] = 0;
8724 }
8725 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8726 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8727 plci->RBuffer[plci->req_in++] = req; /* request */
8728 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8729 plci->req_in_start = plci->req_in;
8730}
8731
8732void send_req(PLCI * plci)
8733{
8734 ENTITY * e;
8735 word l;
8736/* word i; */
8737
8738 if(!plci) return;
8739 if(plci->adapter->adapter_disabled) return;
8740 channel_xmit_xon (plci);
8741
8742 /* if nothing to do, return */
8743 if(plci->req_in==plci->req_out) return;
8744 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8745
8746 if(plci->nl_req || plci->sig_req) return;
8747
8748 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8749 plci->req_out += 2;
8750 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8751 plci->req_out += l;
8752 if(plci->RBuffer[plci->req_out]==1)
8753 {
8754 e = &plci->NL;
8755 plci->req_out++;
8756 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8757 e->ReqCh = plci->RBuffer[plci->req_out++];
8758 if(!(e->Id & 0x1f))
8759 {
8760 e->Id = NL_ID;
8761 plci->RBuffer[plci->req_out-4] = CAI;
8762 plci->RBuffer[plci->req_out-3] = 1;
8763 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8764 plci->RBuffer[plci->req_out-1] = 0;
8765 l+=3;
8766 plci->nl_global_req = plci->nl_req;
8767 }
8768 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8769 }
8770 else
8771 {
8772 e = &plci->Sig;
8773 if(plci->RBuffer[plci->req_out])
8774 e->Id = plci->RBuffer[plci->req_out];
8775 plci->req_out++;
8776 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8777 e->ReqCh = plci->RBuffer[plci->req_out++];
8778 if(!(e->Id & 0x1f))
8779 plci->sig_global_req = plci->sig_req;
8780 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8781 }
8782 plci->XData[0].PLength = l;
8783 e->X = plci->XData;
8784 plci->adapter->request(e);
8785 dbug(1,dprintf("send_ok"));
8786}
8787
8788void send_data(PLCI * plci)
8789{
8790 DIVA_CAPI_ADAPTER * a;
8791 DATA_B3_DESC * data;
8792 NCCI *ncci_ptr;
8793 word ncci;
8794
8795 if (!plci->nl_req && plci->ncci_ring_list)
8796 {
8797 a = plci->adapter;
8798 ncci = plci->ncci_ring_list;
8799 do
8800 {
8801 ncci = a->ncci_next[ncci];
8802 ncci_ptr = &(a->ncci[ncci]);
8803 if (!(a->ncci_ch[ncci]
8804 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8805 {
8806 if (ncci_ptr->data_pending)
8807 {
8808 if ((a->ncci_state[ncci] == CONNECTED)
8809 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8810 || (plci->send_disc == ncci))
8811 {
8812 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8813 if ((plci->B2_prot == B2_V120_ASYNC)
8814 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8815 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8816 {
8817 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8818 plci->NData[1].PLength = data->Length;
8819 if (data->Flags & 0x10)
8820 plci->NData[0].P = v120_break_header;
8821 else
8822 plci->NData[0].P = v120_default_header;
8823 plci->NData[0].PLength = 1 ;
8824 plci->NL.XNum = 2;
8825 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8826 }
8827 else
8828 {
8829 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8830 plci->NData[0].PLength = data->Length;
8831 if (data->Flags & 0x10)
8832 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8833
8834 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8835 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8836
8837 else
8838 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8839 }
8840 plci->NL.X = plci->NData;
8841 plci->NL.ReqCh = a->ncci_ch[ncci];
8842 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008843 plci->data_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008844 plci->data_sent_ptr = data->P;
8845 a->request(&plci->NL);
8846 }
8847 else {
8848 cleanup_ncci_data (plci, ncci);
8849 }
8850 }
8851 else if (plci->send_disc == ncci)
8852 {
8853 /* dprintf("N_DISC"); */
8854 plci->NData[0].PLength = 0;
8855 plci->NL.ReqCh = a->ncci_ch[ncci];
8856 plci->NL.Req = plci->nl_req = N_DISC;
8857 a->request(&plci->NL);
8858 plci->command = _DISCONNECT_B3_R;
8859 plci->send_disc = 0;
8860 }
8861 }
8862 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8863 plci->ncci_ring_list = ncci;
8864 }
8865}
8866
8867void listen_check(DIVA_CAPI_ADAPTER * a)
8868{
8869 word i,j;
8870 PLCI * plci;
8871 byte activnotifiedcalls = 0;
8872
8873 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8874 if (!remove_started && !a->adapter_disabled)
8875 {
8876 for(i=0;i<a->max_plci;i++)
8877 {
8878 plci = &(a->plci[i]);
8879 if(plci->notifiedcall) activnotifiedcalls++;
8880 }
8881 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8882
8883 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8884 if((j=get_plci(a))) {
8885 a->listen_active++;
8886 plci = &a->plci[j-1];
8887 plci->State = LISTENING;
8888
8889 add_p(plci,OAD,"\x01\xfd");
8890
8891 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8892
8893 add_p(plci,CAI,"\x01\xc0");
8894 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8895 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8896 add_p(plci,SHIFT|6,NULL);
8897 add_p(plci,SIN,"\x02\x00\x00");
8898 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8899 sig_req(plci,ASSIGN,DSIG_ID);
8900 send_req(plci);
8901 }
8902 }
8903 }
8904}
8905
8906/*------------------------------------------------------------------*/
8907/* functions for all parameters sent in INDs */
8908/*------------------------------------------------------------------*/
8909
8910void IndParse(PLCI * plci, word * parms_id, byte ** parms, byte multiIEsize)
8911{
8912 word ploc; /* points to current location within packet */
8913 byte w;
8914 byte wlen;
8915 byte codeset,lock;
8916 byte * in;
8917 word i;
8918 word code;
8919 word mIEindex = 0;
8920 ploc = 0;
8921 codeset = 0;
8922 lock = 0;
8923
8924 in = plci->Sig.RBuffer->P;
8925 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8926 { /* element but parms array is larger */
8927 parms[i] = (byte *)"";
8928 }
8929 for(i=0; i<multiIEsize; i++)
8930 {
8931 parms[i] = (byte *)"";
8932 }
8933
8934 while(ploc<plci->Sig.RBuffer->length-1) {
8935
8936 /* read information element id and length */
8937 w = in[ploc];
8938
8939 if(w & 0x80) {
8940/* w &=0xf0; removed, cannot detect congestion levels */
8941/* upper 4 bit masked with w==SHIFT now */
8942 wlen = 0;
8943 }
8944 else {
8945 wlen = (byte)(in[ploc+1]+1);
8946 }
8947 /* check if length valid (not exceeding end of packet) */
8948 if((ploc+wlen) > 270) return ;
8949 if(lock & 0x80) lock &=0x7f;
8950 else codeset = lock;
8951
8952 if((w&0xf0)==SHIFT) {
8953 codeset = in[ploc];
8954 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8955 codeset &=7;
8956 lock |=0x80;
8957 }
8958 else {
8959 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8960 else code = w;
8961 code |= (codeset<<8);
8962
8963 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8964
8965 if(i<parms_id[0]+1) {
8966 if(!multiIEsize) { /* with multiIEs use next field index, */
8967 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8968 }
8969
8970 parms[mIEindex] = &in[ploc+1];
8971 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8972 if(parms_id[i]==OAD
8973 || parms_id[i]==CONN_NR
8974 || parms_id[i]==CAD) {
8975 if(in[ploc+2] &0x80) {
8976 in[ploc+0] = (byte)(in[ploc+1]+1);
8977 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8978 in[ploc+2] = 0x80;
8979 parms[mIEindex] = &in[ploc];
8980 }
8981 }
8982 mIEindex++; /* effects multiIEs only */
8983 }
8984 }
8985
8986 ploc +=(wlen+1);
8987 }
8988 return ;
8989}
8990
8991/*------------------------------------------------------------------*/
8992/* try to match a cip from received BC and HLC */
8993/*------------------------------------------------------------------*/
8994
8995byte ie_compare(byte * ie1, byte * ie2)
8996{
8997 word i;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008998 if(!ie1 || ! ie2) return false;
8999 if(!ie1[0]) return false;
9000 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9001 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009002}
9003
9004word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc)
9005{
9006 word i;
9007 word j;
9008
9009 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9010
9011 for(j=16;j<29 &&
9012 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9013 if(j==29) return i;
9014 return j;
9015}
9016
9017
9018static byte AddInfo(byte **add_i,
9019 byte **fty_i,
9020 byte *esc_chi,
9021 byte *facility)
9022{
9023 byte i;
9024 byte j;
9025 byte k;
9026 byte flen;
9027 byte len=0;
9028 /* facility is a nested structure */
9029 /* FTY can be more than once */
9030
9031 if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9032 {
9033 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9034 }
9035
9036 else
9037 {
9038 add_i[0] = (byte *)"";
9039 }
9040 if(!fty_i[0][0])
9041 {
9042 add_i[3] = (byte *)"";
9043 }
9044 else
9045 { /* facility array found */
9046 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9047 {
9048 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9049 len += fty_i[i][0];
9050 len += 2;
9051 flen=fty_i[i][0];
9052 facility[j++]=0x1c; /* copy fac IE */
9053 for(k=0;k<=flen;k++,j++)
9054 {
9055 facility[j]=fty_i[i][k];
9056/* dbug(1,dprintf("%x ",facility[j])); */
9057 }
9058 }
9059 facility[0] = len;
9060 add_i[3] = facility;
9061 }
9062/* dbug(1,dprintf("FacArrLen=%d ",len)); */
9063 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9064 len += 4; /* calculate length of all */
9065 return(len);
9066}
9067
9068/*------------------------------------------------------------------*/
9069/* voice and codec features */
9070/*------------------------------------------------------------------*/
9071
9072void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER * a)
9073{
9074 byte voice_chi[] = "\x02\x18\x01";
9075 byte channel;
9076
9077 channel = chi[chi[0]]&0x3;
9078 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9079 voice_chi[2] = (channel) ? channel : 1;
9080 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9081 add_p(plci,ESC,voice_chi); /* Channel */
9082 sig_req(plci,TEL_CTRL,0);
9083 send_req(plci);
9084 if(a->AdvSignalPLCI)
9085 {
9086 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9087 }
9088}
9089
9090void VoiceChannelOff(PLCI *plci)
9091{
9092 dbug(1,dprintf("ExtDevOFF"));
9093 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9094 sig_req(plci,TEL_CTRL,0);
9095 send_req(plci);
9096 if(plci->adapter->AdvSignalPLCI)
9097 {
9098 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9099 }
9100}
9101
9102
9103word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte hook_listen)
9104{
9105 word j;
9106 PLCI *splci;
9107
9108 /* check if hardware supports handset with hook states (adv.codec) */
9109 /* or if just a on board codec is supported */
9110 /* the advanced codec plci is just for internal use */
9111
9112 /* diva Pro with on-board codec: */
9113 if(a->profile.Global_Options & HANDSET)
9114 {
9115 /* new call, but hook states are already signalled */
9116 if(a->AdvCodecFLAG)
9117 {
9118 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9119 {
9120 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9121 return 0x2001; /* codec in use by another application */
9122 }
9123 if(plci!=0)
9124 {
9125 a->AdvSignalPLCI = plci;
9126 plci->tel=ADV_VOICE;
9127 }
9128 return 0; /* adv codec still used */
9129 }
9130 if((j=get_plci(a)))
9131 {
9132 splci = &a->plci[j-1];
9133 splci->tel = CODEC_PERMANENT;
9134 /* hook_listen indicates if a facility_req with handset/hook support */
9135 /* was sent. Otherwise if just a call on an external device was made */
9136 /* the codec will be used but the hook info will be discarded (just */
9137 /* the external controller is in use */
9138 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9139 else
9140 {
9141 splci->State = ADVANCED_VOICE_NOSIG;
9142 if(plci)
9143 {
9144 plci->spoofed_msg = SPOOFING_REQUIRED;
9145 }
9146 /* indicate D-ch connect if */
9147 } /* codec is connected OK */
9148 if(plci!=0)
9149 {
9150 a->AdvSignalPLCI = plci;
9151 plci->tel=ADV_VOICE;
9152 }
9153 a->AdvSignalAppl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009154 a->AdvCodecFLAG = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009155 a->AdvCodecPLCI = splci;
9156 add_p(splci,CAI,"\x01\x15");
9157 add_p(splci,LLI,"\x01\x00");
9158 add_p(splci,ESC,"\x02\x18\x00");
9159 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9160 splci->internal_command = PERM_COD_ASSIGN;
9161 dbug(1,dprintf("Codec Assign"));
9162 sig_req(splci,ASSIGN,DSIG_ID);
9163 send_req(splci);
9164 }
9165 else
9166 {
9167 return 0x2001; /* wrong state, no more plcis */
9168 }
9169 }
9170 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9171 {
9172 if(hook_listen) return 0x300B; /* Facility not supported */
9173 /* no hook with SCOM */
9174 if(plci!=0) plci->tel = CODEC;
9175 dbug(1,dprintf("S/SCOM codec"));
9176 /* first time we use the scom-s codec we must shut down the internal */
9177 /* handset application of the card. This can be done by an assign with */
9178 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9179 if(!a->scom_appl_disable){
9180 if((j=get_plci(a))) {
9181 splci = &a->plci[j-1];
9182 add_p(splci,CAI,"\x01\x80");
9183 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9185 send_req(splci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009186 a->scom_appl_disable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009187 }
9188 else{
9189 return 0x2001; /* wrong state, no more plcis */
9190 }
9191 }
9192 }
9193 else return 0x300B; /* Facility not supported */
9194
9195 return 0;
9196}
9197
9198
9199void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9200{
9201
9202 dbug(1,dprintf("CodecIdCheck"));
9203
9204 if(a->AdvSignalPLCI == plci)
9205 {
9206 dbug(1,dprintf("PLCI owns codec"));
9207 VoiceChannelOff(a->AdvCodecPLCI);
9208 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9209 {
9210 dbug(1,dprintf("remove temp codec PLCI"));
9211 plci_remove(a->AdvCodecPLCI);
9212 a->AdvCodecFLAG = 0;
9213 a->AdvCodecPLCI = NULL;
9214 a->AdvSignalAppl = NULL;
9215 }
9216 a->AdvSignalPLCI = NULL;
9217 }
9218}
9219
9220/* -------------------------------------------------------------------
9221 Ask for physical address of card on PCI bus
9222 ------------------------------------------------------------------- */
9223static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9224 IDI_SYNC_REQ * preq) {
9225 a->sdram_bar = 0;
9226 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9227 ENTITY * e = (ENTITY *)preq;
9228
9229 e->user[0] = a->Id - 1;
9230 preq->xdi_sdram_bar.info.bar = 0;
9231 preq->xdi_sdram_bar.Req = 0;
9232 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9233
9234 (*(a->request))(e);
9235
9236 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9237 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9238 }
9239}
9240
9241/* -------------------------------------------------------------------
9242 Ask XDI about extended features
9243 ------------------------------------------------------------------- */
9244static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9245 IDI_SYNC_REQ * preq;
9246 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9247
9248 char features[4];
9249 preq = (IDI_SYNC_REQ *)&buffer[0];
9250
9251 if (!diva_xdi_extended_features) {
9252 ENTITY * e = (ENTITY *)preq;
9253 diva_xdi_extended_features |= 0x80000000;
9254
9255 e->user[0] = a->Id - 1;
9256 preq->xdi_extended_features.Req = 0;
9257 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9258 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9259 preq->xdi_extended_features.info.features = &features[0];
9260
9261 (*(a->request))(e);
9262
9263 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9264 /*
9265 Check features located in the byte '0'
9266 */
9267 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9268 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9269 }
9270 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9271 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9272 dbug(1,dprintf("XDI provides RxDMA"));
9273 }
9274 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9275 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9276 }
9277 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9278 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9279 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9280 }
9281
9282 }
9283 }
9284
9285 diva_ask_for_xdi_sdram_bar (a, preq);
9286}
9287
9288/*------------------------------------------------------------------*/
9289/* automatic law */
9290/*------------------------------------------------------------------*/
9291/* called from OS specific part after init time to get the Law */
9292/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9293void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9294{
9295 word j;
9296 PLCI *splci;
9297
9298 if(a->automatic_law) {
9299 return;
9300 }
9301 if((j=get_plci(a))) {
9302 diva_get_extended_adapter_features (a);
9303 splci = &a->plci[j-1];
9304 a->automatic_lawPLCI = splci;
9305 a->automatic_law = 1;
9306 add_p(splci,CAI,"\x01\x80");
9307 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9308 splci->internal_command = USELAW_REQ;
9309 splci->command = 0;
9310 splci->number = 0;
9311 sig_req(splci,ASSIGN,DSIG_ID);
9312 send_req(splci);
9313 }
9314}
9315
9316/* called from OS specific part if an application sends an Capi20Release */
9317word CapiRelease(word Id)
9318{
9319 word i, j, appls_found;
9320 PLCI *plci;
9321 APPL *this;
9322 DIVA_CAPI_ADAPTER *a;
9323
9324 if (!Id)
9325 {
9326 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9327 return (_WRONG_APPL_ID);
9328 }
9329
9330 this = &application[Id-1]; /* get application pointer */
9331
9332 for(i=0,appls_found=0; i<max_appl; i++)
9333 {
9334 if(application[i].Id) /* an application has been found */
9335 {
9336 appls_found++;
9337 }
9338 }
9339
9340 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9341 {
9342 a = &adapter[i];
9343 if (a->request)
9344 {
9345 a->Info_Mask[Id-1] = 0;
9346 a->CIP_Mask[Id-1] = 0;
9347 a->Notification_Mask[Id-1] = 0;
9348 a->codec_listen[Id-1] = NULL;
9349 a->requested_options_table[Id-1] = 0;
9350 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9351 { /* with this application */
9352 plci = &a->plci[j];
9353 if(plci->Id) /* if plci owns no application */
9354 { /* it may be not jet connected */
9355 if(plci->State==INC_CON_PENDING
9356 || plci->State==INC_CON_ALERT)
9357 {
9358 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9359 {
9360 clear_c_ind_mask_bit (plci, (word)(Id-1));
9361 if(c_ind_mask_empty (plci))
9362 {
9363 sig_req(plci,HANGUP,0);
9364 send_req(plci);
9365 plci->State = OUTG_DIS_PENDING;
9366 }
9367 }
9368 }
9369 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9370 {
9371 clear_c_ind_mask_bit (plci, (word)(Id-1));
9372 if(c_ind_mask_empty (plci))
9373 {
9374 if(!plci->appl)
9375 {
9376 plci_remove(plci);
9377 plci->State = IDLE;
9378 }
9379 }
9380 }
9381 if(plci->appl==this)
9382 {
9383 plci->appl = NULL;
9384 plci_remove(plci);
9385 plci->State = IDLE;
9386 }
9387 }
9388 }
9389 listen_check(a);
9390
9391 if(a->flag_dynamic_l1_down)
9392 {
9393 if(appls_found==1) /* last application does a capi release */
9394 {
9395 if((j=get_plci(a)))
9396 {
9397 plci = &a->plci[j-1];
9398 plci->command = 0;
9399 add_p(plci,OAD,"\x01\xfd");
9400 add_p(plci,CAI,"\x01\x80");
9401 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9402 add_p(plci,SHIFT|6,NULL);
9403 add_p(plci,SIN,"\x02\x00\x00");
9404 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9405 sig_req(plci,ASSIGN,DSIG_ID);
9406 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9407 sig_req(plci,SIG_CTRL,0);
9408 send_req(plci);
9409 }
9410 }
9411 }
9412 if(a->AdvSignalAppl==this)
9413 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009414 this->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009415 if (a->AdvCodecPLCI)
9416 {
9417 plci_remove(a->AdvCodecPLCI);
9418 a->AdvCodecPLCI->tel = 0;
9419 a->AdvCodecPLCI->adv_nl = 0;
9420 }
9421 a->AdvSignalAppl = NULL;
9422 a->AdvSignalPLCI = NULL;
9423 a->AdvCodecFLAG = 0;
9424 a->AdvCodecPLCI = NULL;
9425 }
9426 }
9427 }
9428
9429 this->Id = 0;
9430
9431 return GOOD;
9432}
9433
9434static word plci_remove_check(PLCI *plci)
9435{
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009436 if(!plci) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009437 if(!plci->NL.Id && c_ind_mask_empty (plci))
9438 {
9439 if(plci->Sig.Id == 0xff)
9440 plci->Sig.Id = 0;
9441 if(!plci->Sig.Id)
9442 {
9443 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9444 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9445 if (plci->Id)
9446 {
9447 CodecIdCheck(plci->adapter, plci);
9448 clear_b1_config (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009449 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009450 plci_free_msg_in_queue (plci);
9451 channel_flow_control_remove (plci);
9452 plci->Id = 0;
9453 plci->State = IDLE;
9454 plci->channels = 0;
9455 plci->appl = NULL;
9456 plci->notifiedcall = 0;
9457 }
9458 listen_check(plci->adapter);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009459 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009460 }
9461 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009462 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009463}
9464
9465
9466/*------------------------------------------------------------------*/
9467
9468static byte plci_nl_busy (PLCI *plci)
9469{
9470 /* only applicable for non-multiplexed protocols */
9471 return (plci->nl_req
9472 || (plci->ncci_ring_list
9473 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9474 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9475}
9476
9477
9478/*------------------------------------------------------------------*/
9479/* DTMF facilities */
9480/*------------------------------------------------------------------*/
9481
9482
9483static struct
9484{
9485 byte send_mask;
9486 byte listen_mask;
9487 byte character;
9488 byte code;
9489} dtmf_digit_map[] =
9490{
9491 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9492 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9493 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9494 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9495 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9496 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9497 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9498 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9499 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9500 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9501 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9502 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9503 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9504 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9505 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9506 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9507 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9508 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9509 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9510 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9511
9512 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9513 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9514 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9515 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9516 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9517 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9518 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9519 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9520 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9521 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9522 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9523 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9524 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9525 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9526 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9527 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9528 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9529 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9530 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9531 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9532 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9533 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9534 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9535 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9536 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9537 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9538 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9539 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9540 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9541 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9542 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9543 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9544 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9545 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9546 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9547 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9548 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9549 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9550 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9551 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9552 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9553 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9554 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9555 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9556 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9557 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9558 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9559 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9560 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9561 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9562 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9563 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9564
9565};
9566
9567#define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
9568
9569
9570static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9571{
9572 word min_digit_duration, min_gap_duration;
9573
9574 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9575 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9576 (char *)(FILE_), __LINE__, enable_mask));
9577
9578 if (enable_mask != 0)
9579 {
9580 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9581 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9582 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9583 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9584 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9585 plci->NData[0].PLength = 5;
9586
9587 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9588 plci->NData[0].PLength += 2;
9589 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9590
9591 }
9592 else
9593 {
9594 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9595 plci->NData[0].PLength = 1;
9596
9597 capidtmf_recv_disable (&(plci->capidtmf_state));
9598
9599 }
9600 plci->NData[0].P = plci->internal_req_buffer;
9601 plci->NL.X = plci->NData;
9602 plci->NL.ReqCh = 0;
9603 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9604 plci->adapter->request (&plci->NL);
9605}
9606
9607
9608static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9609{
9610 word w, i;
9611
9612 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9613 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9614 (char *)(FILE_), __LINE__, digit_count));
9615
9616 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9617 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9618 PUT_WORD (&plci->internal_req_buffer[1], w);
9619 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9620 PUT_WORD (&plci->internal_req_buffer[3], w);
9621 for (i = 0; i < digit_count; i++)
9622 {
9623 w = 0;
9624 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9625 && (digit_buffer[i] != dtmf_digit_map[w].character))
9626 {
9627 w++;
9628 }
9629 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9630 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9631 }
9632 plci->NData[0].PLength = 5 + digit_count;
9633 plci->NData[0].P = plci->internal_req_buffer;
9634 plci->NL.X = plci->NData;
9635 plci->NL.ReqCh = 0;
9636 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9637 plci->adapter->request (&plci->NL);
9638}
9639
9640
9641static void dtmf_rec_clear_config (PLCI *plci)
9642{
9643
9644 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9645 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9646 (char *)(FILE_), __LINE__));
9647
9648 plci->dtmf_rec_active = 0;
9649 plci->dtmf_rec_pulse_ms = 0;
9650 plci->dtmf_rec_pause_ms = 0;
9651
9652 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9653
9654}
9655
9656
9657static void dtmf_send_clear_config (PLCI *plci)
9658{
9659
9660 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9661 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9662 (char *)(FILE_), __LINE__));
9663
9664 plci->dtmf_send_requests = 0;
9665 plci->dtmf_send_pulse_ms = 0;
9666 plci->dtmf_send_pause_ms = 0;
9667}
9668
9669
9670static void dtmf_prepare_switch (dword Id, PLCI *plci)
9671{
9672
9673 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9674 UnMapId (Id), (char *)(FILE_), __LINE__));
9675
9676 while (plci->dtmf_send_requests != 0)
9677 dtmf_confirmation (Id, plci);
9678}
9679
9680
9681static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9682{
9683
9684 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9685 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9686
9687 return (GOOD);
9688}
9689
9690
9691static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9692{
9693 word Info;
9694
9695 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9697
9698 Info = GOOD;
9699 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9700 {
9701 switch (plci->adjust_b_state)
9702 {
9703 case ADJUST_B_RESTORE_DTMF_1:
9704 plci->internal_command = plci->adjust_b_command;
9705 if (plci_nl_busy (plci))
9706 {
9707 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9708 break;
9709 }
9710 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9711 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9712 break;
9713 case ADJUST_B_RESTORE_DTMF_2:
9714 if ((Rc != OK) && (Rc != OK_FC))
9715 {
9716 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9717 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9718 Info = _WRONG_STATE;
9719 break;
9720 }
9721 break;
9722 }
9723 }
9724 return (Info);
9725}
9726
9727
9728static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9729{
9730 word internal_command, Info;
9731 byte mask;
9732 byte result[4];
9733
9734 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9735 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9736 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9737 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9738
9739 Info = GOOD;
9740 result[0] = 2;
9741 PUT_WORD (&result[1], DTMF_SUCCESS);
9742 internal_command = plci->internal_command;
9743 plci->internal_command = 0;
9744 mask = 0x01;
9745 switch (plci->dtmf_cmd)
9746 {
9747
9748 case DTMF_LISTEN_TONE_START:
9749 mask <<= 1;
9750 case DTMF_LISTEN_MF_START:
9751 mask <<= 1;
9752
9753 case DTMF_LISTEN_START:
9754 switch (internal_command)
9755 {
9756 default:
9757 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9758 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9759 case DTMF_COMMAND_1:
9760 if (adjust_b_process (Id, plci, Rc) != GOOD)
9761 {
9762 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9763 UnMapId (Id), (char *)(FILE_), __LINE__));
9764 Info = _FACILITY_NOT_SUPPORTED;
9765 break;
9766 }
9767 if (plci->internal_command)
9768 return;
9769 case DTMF_COMMAND_2:
9770 if (plci_nl_busy (plci))
9771 {
9772 plci->internal_command = DTMF_COMMAND_2;
9773 return;
9774 }
9775 plci->internal_command = DTMF_COMMAND_3;
9776 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9777 return;
9778 case DTMF_COMMAND_3:
9779 if ((Rc != OK) && (Rc != OK_FC))
9780 {
9781 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9782 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9783 Info = _FACILITY_NOT_SUPPORTED;
9784 break;
9785 }
9786
9787 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9788
9789 plci->dtmf_rec_active |= mask;
9790 break;
9791 }
9792 break;
9793
9794
9795 case DTMF_LISTEN_TONE_STOP:
9796 mask <<= 1;
9797 case DTMF_LISTEN_MF_STOP:
9798 mask <<= 1;
9799
9800 case DTMF_LISTEN_STOP:
9801 switch (internal_command)
9802 {
9803 default:
9804 plci->dtmf_rec_active &= ~mask;
9805 if (plci->dtmf_rec_active)
9806 break;
9807/*
9808 case DTMF_COMMAND_1:
9809 if (plci->dtmf_rec_active)
9810 {
9811 if (plci_nl_busy (plci))
9812 {
9813 plci->internal_command = DTMF_COMMAND_1;
9814 return;
9815 }
9816 plci->dtmf_rec_active &= ~mask;
9817 plci->internal_command = DTMF_COMMAND_2;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009818 dtmf_enable_receiver (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009819 return;
9820 }
9821 Rc = OK;
9822 case DTMF_COMMAND_2:
9823 if ((Rc != OK) && (Rc != OK_FC))
9824 {
9825 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9826 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9827 Info = _FACILITY_NOT_SUPPORTED;
9828 break;
9829 }
9830*/
9831 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9832 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9833 case DTMF_COMMAND_3:
9834 if (adjust_b_process (Id, plci, Rc) != GOOD)
9835 {
9836 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9837 UnMapId (Id), (char *)(FILE_), __LINE__));
9838 Info = _FACILITY_NOT_SUPPORTED;
9839 break;
9840 }
9841 if (plci->internal_command)
9842 return;
9843 break;
9844 }
9845 break;
9846
9847
9848 case DTMF_SEND_TONE:
9849 mask <<= 1;
9850 case DTMF_SEND_MF:
9851 mask <<= 1;
9852
9853 case DTMF_DIGITS_SEND:
9854 switch (internal_command)
9855 {
9856 default:
9857 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9858 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9859 DTMF_COMMAND_1);
9860 case DTMF_COMMAND_1:
9861 if (adjust_b_process (Id, plci, Rc) != GOOD)
9862 {
9863 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9864 UnMapId (Id), (char *)(FILE_), __LINE__));
9865 Info = _FACILITY_NOT_SUPPORTED;
9866 break;
9867 }
9868 if (plci->internal_command)
9869 return;
9870 case DTMF_COMMAND_2:
9871 if (plci_nl_busy (plci))
9872 {
9873 plci->internal_command = DTMF_COMMAND_2;
9874 return;
9875 }
9876 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9877 plci->internal_command = DTMF_COMMAND_3;
9878 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9879 return;
9880 case DTMF_COMMAND_3:
9881 if ((Rc != OK) && (Rc != OK_FC))
9882 {
9883 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9884 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9885 if (plci->dtmf_send_requests != 0)
9886 (plci->dtmf_send_requests)--;
9887 Info = _FACILITY_NOT_SUPPORTED;
9888 break;
9889 }
9890 return;
9891 }
9892 break;
9893 }
9894 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9895 "wws", Info, SELECTOR_DTMF, result);
9896}
9897
9898
9899static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9900{
9901 word Info;
9902 word i, j;
9903 byte mask;
9904 API_PARSE dtmf_parms[5];
9905 byte result[40];
9906
9907 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9908 UnMapId (Id), (char *)(FILE_), __LINE__));
9909
9910 Info = GOOD;
9911 result[0] = 2;
9912 PUT_WORD (&result[1], DTMF_SUCCESS);
9913 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9914 {
9915 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9916 UnMapId (Id), (char *)(FILE_), __LINE__));
9917 Info = _FACILITY_NOT_SUPPORTED;
9918 }
9919 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9920 {
9921 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9922 UnMapId (Id), (char *)(FILE_), __LINE__));
9923 Info = _WRONG_MESSAGE_FORMAT;
9924 }
9925
9926 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9927 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9928 {
9929 if (!((a->requested_options_table[appl->Id-1])
9930 & (1L << PRIVATE_DTMF_TONE)))
9931 {
9932 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9933 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9934 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9935 }
9936 else
9937 {
9938 for (i = 0; i < 32; i++)
9939 result[4 + i] = 0;
9940 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9941 {
9942 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9943 {
9944 if (dtmf_digit_map[i].listen_mask != 0)
9945 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9946 }
9947 }
9948 else
9949 {
9950 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9951 {
9952 if (dtmf_digit_map[i].send_mask != 0)
9953 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9954 }
9955 }
9956 result[0] = 3 + 32;
9957 result[3] = 32;
9958 }
9959 }
9960
9961 else if (plci == NULL)
9962 {
9963 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9964 UnMapId (Id), (char *)(FILE_), __LINE__));
9965 Info = _WRONG_IDENTIFIER;
9966 }
9967 else
9968 {
9969 if (!plci->State
9970 || !plci->NL.Id || plci->nl_remove_id)
9971 {
9972 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9973 UnMapId (Id), (char *)(FILE_), __LINE__));
9974 Info = _WRONG_STATE;
9975 }
9976 else
9977 {
9978 plci->command = 0;
9979 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9980 mask = 0x01;
9981 switch (plci->dtmf_cmd)
9982 {
9983
9984 case DTMF_LISTEN_TONE_START:
9985 case DTMF_LISTEN_TONE_STOP:
9986 mask <<= 1;
9987 case DTMF_LISTEN_MF_START:
9988 case DTMF_LISTEN_MF_STOP:
9989 mask <<= 1;
9990 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9991 & (1L << PRIVATE_DTMF_TONE)))
9992 {
9993 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9994 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9995 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9996 break;
9997 }
9998
9999 case DTMF_LISTEN_START:
10000 case DTMF_LISTEN_STOP:
10001 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10002 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10003 {
10004 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10005 UnMapId (Id), (char *)(FILE_), __LINE__));
10006 Info = _FACILITY_NOT_SUPPORTED;
10007 break;
10008 }
10009 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10010 {
10011 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10012 {
10013 plci->dtmf_rec_pulse_ms = 0;
10014 plci->dtmf_rec_pause_ms = 0;
10015 }
10016 else
10017 {
10018 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10019 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10020 }
10021 }
10022 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010023 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010024
10025
10026 case DTMF_SEND_TONE:
10027 mask <<= 1;
10028 case DTMF_SEND_MF:
10029 mask <<= 1;
10030 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10031 & (1L << PRIVATE_DTMF_TONE)))
10032 {
10033 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10034 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10035 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10036 break;
10037 }
10038
10039 case DTMF_DIGITS_SEND:
10040 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10041 {
10042 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10043 UnMapId (Id), (char *)(FILE_), __LINE__));
10044 Info = _WRONG_MESSAGE_FORMAT;
10045 break;
10046 }
10047 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10048 {
10049 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10050 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10051 }
10052 i = 0;
10053 j = 0;
10054 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10055 {
10056 j = 0;
10057 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10058 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10059 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10060 {
10061 j++;
10062 }
10063 i++;
10064 }
10065 if (j == DTMF_DIGIT_MAP_ENTRIES)
10066 {
10067 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10068 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10069 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10070 break;
10071 }
10072 if (plci->dtmf_send_requests >=
10073 sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
10074 {
10075 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10076 UnMapId (Id), (char *)(FILE_), __LINE__));
10077 Info = _WRONG_STATE;
10078 break;
10079 }
10080 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10081 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010082 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010083
10084 default:
10085 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10086 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10087 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10088 }
10089 }
10090 }
10091 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10092 "wws", Info, SELECTOR_DTMF, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010093 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010094}
10095
10096
10097static void dtmf_confirmation (dword Id, PLCI *plci)
10098{
10099 word Info;
10100 word i;
10101 byte result[4];
10102
10103 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10104 UnMapId (Id), (char *)(FILE_), __LINE__));
10105
10106 Info = GOOD;
10107 result[0] = 2;
10108 PUT_WORD (&result[1], DTMF_SUCCESS);
10109 if (plci->dtmf_send_requests != 0)
10110 {
10111 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10112 "wws", GOOD, SELECTOR_DTMF, result);
10113 (plci->dtmf_send_requests)--;
10114 for (i = 0; i < plci->dtmf_send_requests; i++)
10115 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10116 }
10117}
10118
10119
10120static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10121{
10122 word i, j, n;
10123
10124 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10125 UnMapId (Id), (char *)(FILE_), __LINE__));
10126
10127 n = 0;
10128 for (i = 1; i < length; i++)
10129 {
10130 j = 0;
10131 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10132 && ((msg[i] != dtmf_digit_map[j].code)
10133 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10134 {
10135 j++;
10136 }
10137 if (j < DTMF_DIGIT_MAP_ENTRIES)
10138 {
10139
10140 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10141 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10142 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10143 {
10144 if (n + 1 == i)
10145 {
10146 for (i = length; i > n + 1; i--)
10147 msg[i] = msg[i - 1];
10148 length++;
10149 i++;
10150 }
10151 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10152 }
10153 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10154
10155 msg[++n] = dtmf_digit_map[j].character;
10156 }
10157 }
10158 if (n != 0)
10159 {
10160 msg[0] = (byte) n;
10161 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10162 }
10163}
10164
10165
10166/*------------------------------------------------------------------*/
10167/* DTMF parameters */
10168/*------------------------------------------------------------------*/
10169
10170static void dtmf_parameter_write (PLCI *plci)
10171{
10172 word i;
10173 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10174
10175 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10176 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10177 (char *)(FILE_), __LINE__));
10178
10179 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10180 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10181 for (i = 0; i < plci->dtmf_parameter_length; i++)
10182 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10183 add_p (plci, FTY, parameter_buffer);
10184 sig_req (plci, TEL_CTRL, 0);
10185 send_req (plci);
10186}
10187
10188
10189static void dtmf_parameter_clear_config (PLCI *plci)
10190{
10191
10192 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10193 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10194 (char *)(FILE_), __LINE__));
10195
10196 plci->dtmf_parameter_length = 0;
10197}
10198
10199
10200static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10201{
10202
10203 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10204 UnMapId (Id), (char *)(FILE_), __LINE__));
10205
10206}
10207
10208
10209static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10210{
10211
10212 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10213 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10214
10215 return (GOOD);
10216}
10217
10218
10219static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10220{
10221 word Info;
10222
10223 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10224 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10225
10226 Info = GOOD;
10227 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10228 && (plci->dtmf_parameter_length != 0))
10229 {
10230 switch (plci->adjust_b_state)
10231 {
10232 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10233 plci->internal_command = plci->adjust_b_command;
10234 if (plci->sig_req)
10235 {
10236 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10237 break;
10238 }
10239 dtmf_parameter_write (plci);
10240 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10241 break;
10242 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10243 if ((Rc != OK) && (Rc != OK_FC))
10244 {
10245 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10246 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10247 Info = _WRONG_STATE;
10248 break;
10249 }
10250 break;
10251 }
10252 }
10253 return (Info);
10254}
10255
10256
10257/*------------------------------------------------------------------*/
10258/* Line interconnect facilities */
10259/*------------------------------------------------------------------*/
10260
10261
10262LI_CONFIG *li_config_table;
10263word li_total_channels;
10264
10265
10266/*------------------------------------------------------------------*/
10267/* translate a CHI information element to a channel number */
10268/* returns 0xff - any channel */
10269/* 0xfe - chi wrong coding */
10270/* 0xfd - D-channel */
10271/* 0x00 - no channel */
10272/* else channel number / PRI: timeslot */
10273/* if channels is provided we accept more than one channel. */
10274/*------------------------------------------------------------------*/
10275
10276static byte chi_to_channel (byte *chi, dword *pchannelmap)
10277{
10278 int p;
10279 int i;
10280 dword map;
10281 byte excl;
10282 byte ofs;
10283 byte ch;
10284
10285 if (pchannelmap) *pchannelmap = 0;
10286 if(!chi[0]) return 0xff;
10287 excl = 0;
10288
10289 if(chi[1] & 0x20) {
10290 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10291 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10292 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10293 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10294 if(chi[1] &0x08) excl = 0x40;
10295
10296 /* int. id present */
10297 if(chi[1] &0x40) {
10298 p=i+1;
10299 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10300 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10301 }
10302
10303 /* coding standard, Number/Map, Channel Type */
10304 p=i+1;
10305 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10306 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10307 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10308
10309 /* Number/Map */
10310 if(chi[p] &0x10) {
10311
10312 /* map */
10313 if((chi[0]-p)==4) ofs = 0;
10314 else if((chi[0]-p)==3) ofs = 1;
10315 else return 0xfe;
10316 ch = 0;
10317 map = 0;
10318 for(i=0; i<4 && p<chi[0]; i++) {
10319 p++;
10320 ch += 8;
10321 map <<= 8;
10322 if(chi[p]) {
10323 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10324 map |= chi[p];
10325 }
10326 }
10327 ch += ofs;
10328 map <<= ofs;
10329 }
10330 else {
10331
10332 /* number */
10333 p=i+1;
10334 ch = chi[p] &0x3f;
10335 if(pchannelmap) {
10336 if((byte)(chi[0]-p)>30) return 0xfe;
10337 map = 0;
10338 for(i=p; i<=chi[0]; i++) {
10339 if ((chi[i] &0x7f) > 31) return 0xfe;
10340 map |= (1L << (chi[i] &0x7f));
10341 }
10342 }
10343 else {
10344 if(p!=chi[0]) return 0xfe;
10345 if (ch > 31) return 0xfe;
10346 map = (1L << ch);
10347 }
10348 if(chi[p] &0x40) return 0xfe;
10349 }
10350 if (pchannelmap) *pchannelmap = map;
10351 else if (map != ((dword)(1L << ch))) return 0xfe;
10352 return (byte)(excl | ch);
10353 }
10354 else { /* not PRI */
10355 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10356 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10357 if(chi[1] &0x08) excl = 0x40;
10358
10359 switch(chi[1] |0x98) {
10360 case 0x98: return 0;
10361 case 0x99:
10362 if (pchannelmap) *pchannelmap = 2;
10363 return excl |1;
10364 case 0x9a:
10365 if (pchannelmap) *pchannelmap = 4;
10366 return excl |2;
10367 case 0x9b: return 0xff;
10368 case 0x9c: return 0xfd; /* d-ch */
10369 default: return 0xfe;
10370 }
10371 }
10372}
10373
10374
10375static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10376{
10377 DIVA_CAPI_ADAPTER *a;
10378 PLCI *splci;
10379 byte old_id;
10380
10381 a = plci->adapter;
10382 old_id = plci->li_bchannel_id;
10383 if (a->li_pri)
10384 {
10385 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10386 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10387 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10388 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10389 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10390 }
10391 else
10392 {
10393 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10394 {
10395 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10396 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10397 plci->li_bchannel_id = bchannel_id & 0x03;
10398 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10399 {
10400 splci = a->AdvSignalPLCI;
10401 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10402 {
10403 if ((splci->li_bchannel_id != 0)
10404 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10405 {
10406 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10407 }
10408 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10409 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10410 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10411 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10412 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10413 }
10414 }
10415 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10416 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10417 }
10418 }
10419 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10420 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10421 {
10422 mixer_clear_config (plci);
10423 }
10424 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10425 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10426 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10427}
10428
10429
10430static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10431{
10432 DIVA_CAPI_ADAPTER *a;
10433 PLCI *splci;
10434 byte ch, old_id;
10435
10436 a = plci->adapter;
10437 old_id = plci->li_bchannel_id;
10438 ch = chi_to_channel (chi, NULL);
10439 if (!(ch & 0x80))
10440 {
10441 if (a->li_pri)
10442 {
10443 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10444 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10445 plci->li_bchannel_id = (ch & 0x1f) + 1;
10446 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10447 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10448 }
10449 else
10450 {
10451 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10452 {
10453 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10454 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10455 plci->li_bchannel_id = ch & 0x1f;
10456 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10457 {
10458 splci = a->AdvSignalPLCI;
10459 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10460 {
10461 if ((splci->li_bchannel_id != 0)
10462 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10463 {
10464 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10465 }
10466 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10467 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10468 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10469 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10470 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10471 }
10472 }
10473 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10474 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10475 }
10476 }
10477 }
10478 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10479 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10480 {
10481 mixer_clear_config (plci);
10482 }
10483 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10484 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10485 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10486}
10487
10488
10489#define MIXER_MAX_DUMP_CHANNELS 34
10490
10491static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10492{
10493static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10494 word n, i, j;
10495 char *p;
10496 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10497
10498 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10499 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10500
10501 for (i = 0; i < li_total_channels; i++)
10502 {
10503 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10504 if (li_config_table[i].chflags != 0)
10505 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10506 else
10507 {
10508 for (j = 0; j < li_total_channels; j++)
10509 {
10510 if (((li_config_table[i].flag_table[j]) != 0)
10511 || ((li_config_table[j].flag_table[i]) != 0))
10512 {
10513 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10514 }
10515 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10516 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10517 {
10518 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10519 }
10520 }
10521 }
10522 }
10523 for (i = 0; i < li_total_channels; i++)
10524 {
10525 for (j = 0; j < li_total_channels; j++)
10526 {
10527 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10528 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10529 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10530 }
10531 }
10532 for (n = 0; n < li_total_channels; n++)
10533 {
10534 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10535 {
10536 for (i = 0; i < li_total_channels; i++)
10537 {
10538 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10539 {
10540 for (j = 0; j < li_total_channels; j++)
10541 {
10542 li_config_table[i].coef_table[j] |=
10543 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10544 }
10545 }
10546 }
10547 }
10548 }
10549 for (i = 0; i < li_total_channels; i++)
10550 {
10551 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10552 {
10553 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10554 for (j = 0; j < li_total_channels; j++)
10555 {
10556 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10557 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10558 }
10559 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10560 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10561 }
10562 }
10563 for (i = 0; i < li_total_channels; i++)
10564 {
10565 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10566 {
10567 for (j = 0; j < li_total_channels; j++)
10568 {
10569 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10570 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10571 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10572 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10573 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10574 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10575 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10576 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10577 }
10578 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10579 {
10580 for (j = 0; j < li_total_channels; j++)
10581 {
10582 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10583 {
10584 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10585 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10586 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10587 }
10588 }
10589 }
10590 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10591 {
10592 for (j = 0; j < li_total_channels; j++)
10593 {
10594 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10595 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10596 }
10597 }
10598 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10599 {
10600 for (j = 0; j < li_total_channels; j++)
10601 {
10602 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10603 {
10604 for (n = 0; n < li_total_channels; n++)
10605 {
10606 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10607 {
10608 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10609 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10610 {
10611 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10612 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10613 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10614 }
10615 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10616 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10617 }
10618 }
10619 }
10620 }
10621 }
10622 }
10623 }
10624 for (i = 0; i < li_total_channels; i++)
10625 {
10626 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10627 {
10628 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10629 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10630 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10631 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10632 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10633 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10634 for (j = 0; j < li_total_channels; j++)
10635 {
10636 if ((li_config_table[i].flag_table[j] &
10637 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10638 || (li_config_table[j].flag_table[i] &
10639 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10640 {
10641 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10642 }
10643 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10644 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10645 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10646 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10647 }
10648 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10649 {
10650 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10651 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10652 }
10653 }
10654 }
10655 for (i = 0; i < li_total_channels; i++)
10656 {
10657 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10658 {
10659 j = 0;
10660 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10661 j++;
10662 if (j < li_total_channels)
10663 {
10664 for (j = 0; j < li_total_channels; j++)
10665 {
10666 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10667 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10668 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10669 }
10670 }
10671 }
10672 }
10673 n = li_total_channels;
10674 if (n > MIXER_MAX_DUMP_CHANNELS)
10675 n = MIXER_MAX_DUMP_CHANNELS;
10676 p = hex_line;
10677 for (j = 0; j < n; j++)
10678 {
10679 if ((j & 0x7) == 0)
10680 *(p++) = ' ';
10681 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10682 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10683 }
10684 *p = '\0';
10685 dbug (1, dprintf ("[%06lx] CURRENT %s",
10686 (dword)(UnMapController (a->Id)), (char *) hex_line));
10687 p = hex_line;
10688 for (j = 0; j < n; j++)
10689 {
10690 if ((j & 0x7) == 0)
10691 *(p++) = ' ';
10692 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10693 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10694 }
10695 *p = '\0';
10696 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10697 (dword)(UnMapController (a->Id)), (char *) hex_line));
10698 p = hex_line;
10699 for (j = 0; j < n; j++)
10700 {
10701 if ((j & 0x7) == 0)
10702 *(p++) = ' ';
10703 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10704 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10705 }
10706 *p = '\0';
10707 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10708 (dword)(UnMapController (a->Id)), (char *) hex_line));
10709 for (i = 0; i < n; i++)
10710 {
10711 p = hex_line;
10712 for (j = 0; j < n; j++)
10713 {
10714 if ((j & 0x7) == 0)
10715 *(p++) = ' ';
10716 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10717 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10718 }
10719 *p = '\0';
10720 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10721 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10722 }
10723 for (i = 0; i < n; i++)
10724 {
10725 p = hex_line;
10726 for (j = 0; j < n; j++)
10727 {
10728 if ((j & 0x7) == 0)
10729 *(p++) = ' ';
10730 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10731 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10732 }
10733 *p = '\0';
10734 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10735 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10736 }
10737}
10738
10739
10740static struct
10741{
10742 byte mask;
10743 byte line_flags;
10744} mixer_write_prog_pri[] =
10745{
10746 { LI_COEF_CH_CH, 0 },
10747 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10748 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10749 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10750};
10751
10752static struct
10753{
10754 byte from_ch;
10755 byte to_ch;
10756 byte mask;
10757 byte xconnect_override;
10758} mixer_write_prog_bri[] =
10759{
10760 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10761 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10762 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10763 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10764 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10765 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10766 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10767 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10768 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10769 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10770 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10771 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10772 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10773 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10774 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10775 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10776 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10777 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10778 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10779 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10780 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10781 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10782 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10783 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10784 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10785 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10786 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10787 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10788 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10789 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10790 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10791 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10792 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10793 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10794 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10795 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10796};
10797
10798static byte mixer_swapped_index_bri[] =
10799{
10800 18, /* B to B */
10801 19, /* Alt B to B */
10802 20, /* PC to B */
10803 21, /* Alt PC to B */
10804 22, /* IC to B */
10805 23, /* Alt IC to B */
10806 24, /* B to PC */
10807 25, /* Alt B to PC */
10808 26, /* PC to PC */
10809 27, /* Alt PC to PC */
10810 28, /* IC to PC */
10811 29, /* Alt IC to PC */
10812 30, /* B to IC */
10813 31, /* Alt B to IC */
10814 32, /* PC to IC */
10815 33, /* Alt PC to IC */
10816 34, /* IC to IC */
10817 35, /* Alt IC to IC */
10818 0, /* Alt B to Alt B */
10819 1, /* B to Alt B */
10820 2, /* Alt PC to Alt B */
10821 3, /* PC to Alt B */
10822 4, /* Alt IC to Alt B */
10823 5, /* IC to Alt B */
10824 6, /* Alt B to Alt PC */
10825 7, /* B to Alt PC */
10826 8, /* Alt PC to Alt PC */
10827 9, /* PC to Alt PC */
10828 10, /* Alt IC to Alt PC */
10829 11, /* IC to Alt PC */
10830 12, /* Alt B to Alt IC */
10831 13, /* B to Alt IC */
10832 14, /* Alt PC to Alt IC */
10833 15, /* PC to Alt IC */
10834 16, /* Alt IC to Alt IC */
10835 17 /* IC to Alt IC */
10836};
10837
10838static struct
10839{
10840 byte mask;
10841 byte from_pc;
10842 byte to_pc;
10843} xconnect_write_prog[] =
10844{
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010845 { LI_COEF_CH_CH, false, false },
10846 { LI_COEF_CH_PC, false, true },
10847 { LI_COEF_PC_CH, true, false },
10848 { LI_COEF_PC_PC, true, true }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010849};
10850
10851
10852static void xconnect_query_addresses (PLCI *plci)
10853{
10854 DIVA_CAPI_ADAPTER *a;
10855 word w, ch;
10856 byte *p;
10857
10858 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10859 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10860 (char *)(FILE_), __LINE__));
10861
10862 a = plci->adapter;
10863 if (a->li_pri && ((plci->li_bchannel_id == 0)
10864 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10865 {
10866 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10867 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10868 (char *)(FILE_), __LINE__));
10869 return;
10870 }
10871 p = plci->internal_req_buffer;
10872 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10873 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10874 w = ch;
10875 *(p++) = (byte) w;
10876 *(p++) = (byte)(w >> 8);
10877 w = ch | XCONNECT_CHANNEL_PORT_PC;
10878 *(p++) = (byte) w;
10879 *(p++) = (byte)(w >> 8);
10880 plci->NData[0].P = plci->internal_req_buffer;
10881 plci->NData[0].PLength = p - plci->internal_req_buffer;
10882 plci->NL.X = plci->NData;
10883 plci->NL.ReqCh = 0;
10884 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10885 plci->adapter->request (&plci->NL);
10886}
10887
10888
10889static void xconnect_write_coefs (PLCI *plci, word internal_command)
10890{
10891
10892 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10893 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10894 (char *)(FILE_), __LINE__, internal_command));
10895
10896 plci->li_write_command = internal_command;
10897 plci->li_write_channel = 0;
10898}
10899
10900
10901static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10902{
10903 DIVA_CAPI_ADAPTER *a;
10904 word w, n, i, j, r, s, to_ch;
10905 dword d;
10906 byte *p;
10907 struct xconnect_transfer_address_s *transfer_address;
10908 byte ch_map[MIXER_CHANNELS_BRI];
10909
10910 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10911 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10912
10913 a = plci->adapter;
10914 if ((plci->li_bchannel_id == 0)
10915 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10916 {
10917 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10918 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010919 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010920 }
10921 i = a->li_base + (plci->li_bchannel_id - 1);
10922 j = plci->li_write_channel;
10923 p = plci->internal_req_buffer;
10924 if (j != 0)
10925 {
10926 if ((Rc != OK) && (Rc != OK_FC))
10927 {
10928 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10929 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010930 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010931 }
10932 }
10933 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10934 {
10935 r = 0;
10936 s = 0;
10937 if (j < li_total_channels)
10938 {
10939 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10940 {
10941 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10942 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10943 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10944 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10945 }
10946 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10947 while ((j < li_total_channels)
10948 && ((r == 0)
10949 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10950 || (!li_config_table[j].adapter->li_pri
10951 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10952 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10953 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10954 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10955 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10956 || ((li_config_table[j].adapter->li_base != a->li_base)
10957 && !(r & s &
10958 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10959 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10960 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10961 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10962 {
10963 j++;
10964 if (j < li_total_channels)
10965 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10966 }
10967 }
10968 if (j < li_total_channels)
10969 {
10970 plci->internal_command = plci->li_write_command;
10971 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010972 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010973 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10974 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10975 do
10976 {
10977 if (li_config_table[j].adapter->li_base != a->li_base)
10978 {
10979 r &= s &
10980 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10981 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10982 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10983 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10984 }
10985 n = 0;
10986 do
10987 {
10988 if (r & xconnect_write_prog[n].mask)
10989 {
10990 if (xconnect_write_prog[n].from_pc)
10991 transfer_address = &(li_config_table[j].send_pc);
10992 else
10993 transfer_address = &(li_config_table[j].send_b);
10994 d = transfer_address->card_address.low;
10995 *(p++) = (byte) d;
10996 *(p++) = (byte)(d >> 8);
10997 *(p++) = (byte)(d >> 16);
10998 *(p++) = (byte)(d >> 24);
10999 d = transfer_address->card_address.high;
11000 *(p++) = (byte) d;
11001 *(p++) = (byte)(d >> 8);
11002 *(p++) = (byte)(d >> 16);
11003 *(p++) = (byte)(d >> 24);
11004 d = transfer_address->offset;
11005 *(p++) = (byte) d;
11006 *(p++) = (byte)(d >> 8);
11007 *(p++) = (byte)(d >> 16);
11008 *(p++) = (byte)(d >> 24);
11009 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11010 *(p++) = (byte) w;
11011 *(p++) = (byte)(w >> 8);
11012 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11013 (li_config_table[i].adapter->u_law ?
11014 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11015 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11016 *(p++) = (byte) w;
11017 *(p++) = (byte) 0;
11018 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11019 }
11020 n++;
11021 } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11022 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11023 if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11024 {
11025 do
11026 {
11027 j++;
11028 if (j < li_total_channels)
11029 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030 } while ((j < li_total_channels)
11031 && ((r == 0)
11032 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11033 || (!li_config_table[j].adapter->li_pri
11034 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11035 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11036 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11037 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11038 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11039 || ((li_config_table[j].adapter->li_base != a->li_base)
11040 && !(r & s &
11041 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11042 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11043 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11044 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11045 }
11046 } while ((j < li_total_channels)
11047 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11048 }
11049 else if (j == li_total_channels)
11050 {
11051 plci->internal_command = plci->li_write_command;
11052 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011053 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011054 if (a->li_pri)
11055 {
11056 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11057 w = 0;
11058 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11059 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11060 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11061 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11062 *(p++) = (byte) w;
11063 *(p++) = (byte)(w >> 8);
11064 }
11065 else
11066 {
11067 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11068 w = 0;
11069 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11070 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11071 {
11072 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11073 }
11074 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11075 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11076 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11077 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11078 *(p++) = (byte) w;
11079 *(p++) = (byte)(w >> 8);
11080 for (j = 0; j < sizeof(ch_map); j += 2)
11081 {
11082 if (plci->li_bchannel_id == 2)
11083 {
11084 ch_map[j] = (byte)(j+1);
11085 ch_map[j+1] = (byte) j;
11086 }
11087 else
11088 {
11089 ch_map[j] = (byte) j;
11090 ch_map[j+1] = (byte)(j+1);
11091 }
11092 }
11093 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11094 {
11095 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11096 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11097 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11098 {
11099 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11100 mixer_write_prog_bri[n].xconnect_override :
11101 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11102 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11103 {
11104 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11105 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11106 }
11107 }
11108 else
11109 {
11110 *p = 0x00;
11111 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11112 {
11113 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11114 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11115 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11116 }
11117 }
11118 p++;
11119 }
11120 }
11121 j = li_total_channels + 1;
11122 }
11123 }
11124 else
11125 {
11126 if (j <= li_total_channels)
11127 {
11128 plci->internal_command = plci->li_write_command;
11129 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011130 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011131 if (j < a->li_base)
11132 j = a->li_base;
11133 if (a->li_pri)
11134 {
11135 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11136 w = 0;
11137 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11138 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11139 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11140 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11141 *(p++) = (byte) w;
11142 *(p++) = (byte)(w >> 8);
11143 for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
11144 {
11145 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11146 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11147 {
11148 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11149 if (w & mixer_write_prog_pri[n].mask)
11150 {
11151 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11152 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11153 }
11154 else
11155 *(p++) = 0x00;
11156 }
11157 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11158 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11159 {
11160 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11161 if (w & mixer_write_prog_pri[n].mask)
11162 {
11163 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11164 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11165 }
11166 else
11167 *(p++) = 0x00;
11168 }
11169 }
11170 }
11171 else
11172 {
11173 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11174 w = 0;
11175 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11176 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11177 {
11178 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11179 }
11180 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11181 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11182 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11183 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11184 *(p++) = (byte) w;
11185 *(p++) = (byte)(w >> 8);
11186 for (j = 0; j < sizeof(ch_map); j += 2)
11187 {
11188 if (plci->li_bchannel_id == 2)
11189 {
11190 ch_map[j] = (byte)(j+1);
11191 ch_map[j+1] = (byte) j;
11192 }
11193 else
11194 {
11195 ch_map[j] = (byte) j;
11196 ch_map[j+1] = (byte)(j+1);
11197 }
11198 }
11199 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11200 {
11201 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11202 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11203 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11204 {
11205 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11206 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11207 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11208 }
11209 else
11210 {
11211 *p = 0x00;
11212 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11213 {
11214 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11215 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11216 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11217 }
11218 }
11219 p++;
11220 }
11221 }
11222 j = li_total_channels + 1;
11223 }
11224 }
11225 plci->li_write_channel = j;
11226 if (p != plci->internal_req_buffer)
11227 {
11228 plci->NData[0].P = plci->internal_req_buffer;
11229 plci->NData[0].PLength = p - plci->internal_req_buffer;
11230 plci->NL.X = plci->NData;
11231 plci->NL.ReqCh = 0;
11232 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11233 plci->adapter->request (&plci->NL);
11234 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011235 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011236}
11237
11238
11239static void mixer_notify_update (PLCI *plci, byte others)
11240{
11241 DIVA_CAPI_ADAPTER *a;
11242 word i, w;
11243 PLCI *notify_plci;
11244 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11245
11246 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11247 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11248 (char *)(FILE_), __LINE__, others));
11249
11250 a = plci->adapter;
11251 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11252 {
11253 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011254 plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011255 i = 0;
11256 do
11257 {
11258 notify_plci = NULL;
11259 if (others)
11260 {
11261 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11262 i++;
11263 if (i < li_total_channels)
11264 notify_plci = li_config_table[i++].plci;
11265 }
11266 else
11267 {
11268 if ((plci->li_bchannel_id != 0)
11269 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11270 {
11271 notify_plci = plci;
11272 }
11273 }
11274 if ((notify_plci != NULL)
11275 && !notify_plci->li_notify_update
11276 && (notify_plci->appl != NULL)
11277 && (notify_plci->State)
11278 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11279 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011280 notify_plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011281 ((CAPI_MSG *) msg)->header.length = 18;
11282 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11283 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11284 ((CAPI_MSG *) msg)->header.number = 0;
11285 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11286 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11287 ((CAPI_MSG *) msg)->header.ncci = 0;
11288 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11289 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11290 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11291 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11292 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11293 if (w != _QUEUE_FULL)
11294 {
11295 if (w != 0)
11296 {
11297 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11298 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11299 (char *)(FILE_), __LINE__,
11300 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11301 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011302 notify_plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011303 }
11304 }
11305 } while (others && (notify_plci != NULL));
11306 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011307 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011308 }
11309}
11310
11311
11312static void mixer_clear_config (PLCI *plci)
11313{
11314 DIVA_CAPI_ADAPTER *a;
11315 word i, j;
11316
11317 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11318 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11319 (char *)(FILE_), __LINE__));
11320
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011321 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011322 plci->li_plci_b_write_pos = 0;
11323 plci->li_plci_b_read_pos = 0;
11324 plci->li_plci_b_req_pos = 0;
11325 a = plci->adapter;
11326 if ((plci->li_bchannel_id != 0)
11327 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11328 {
11329 i = a->li_base + (plci->li_bchannel_id - 1);
11330 li_config_table[i].curchnl = 0;
11331 li_config_table[i].channel = 0;
11332 li_config_table[i].chflags = 0;
11333 for (j = 0; j < li_total_channels; j++)
11334 {
11335 li_config_table[j].flag_table[i] = 0;
11336 li_config_table[i].flag_table[j] = 0;
11337 li_config_table[i].coef_table[j] = 0;
11338 li_config_table[j].coef_table[i] = 0;
11339 }
11340 if (!a->li_pri)
11341 {
11342 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11343 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11344 {
11345 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11346 li_config_table[i].curchnl = 0;
11347 li_config_table[i].channel = 0;
11348 li_config_table[i].chflags = 0;
11349 for (j = 0; j < li_total_channels; j++)
11350 {
11351 li_config_table[i].flag_table[j] = 0;
11352 li_config_table[j].flag_table[i] = 0;
11353 li_config_table[i].coef_table[j] = 0;
11354 li_config_table[j].coef_table[i] = 0;
11355 }
11356 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11357 {
11358 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11359 li_config_table[i].curchnl = 0;
11360 li_config_table[i].channel = 0;
11361 li_config_table[i].chflags = 0;
11362 for (j = 0; j < li_total_channels; j++)
11363 {
11364 li_config_table[i].flag_table[j] = 0;
11365 li_config_table[j].flag_table[i] = 0;
11366 li_config_table[i].coef_table[j] = 0;
11367 li_config_table[j].coef_table[i] = 0;
11368 }
11369 }
11370 }
11371 }
11372 }
11373}
11374
11375
11376static void mixer_prepare_switch (dword Id, PLCI *plci)
11377{
11378
11379 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11380 UnMapId (Id), (char *)(FILE_), __LINE__));
11381
11382 do
11383 {
11384 mixer_indication_coefs_set (Id, plci);
11385 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11386}
11387
11388
11389static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11390{
11391 DIVA_CAPI_ADAPTER *a;
11392 word i, j;
11393
11394 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11395 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11396
11397 a = plci->adapter;
11398 if ((plci->li_bchannel_id != 0)
11399 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11400 {
11401 i = a->li_base + (plci->li_bchannel_id - 1);
11402 for (j = 0; j < li_total_channels; j++)
11403 {
11404 li_config_table[i].coef_table[j] &= 0xf;
11405 li_config_table[j].coef_table[i] &= 0xf;
11406 }
11407 if (!a->li_pri)
11408 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11409 }
11410 return (GOOD);
11411}
11412
11413
11414static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11415{
11416 DIVA_CAPI_ADAPTER *a;
11417 word Info;
11418
11419 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11420 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11421
11422 Info = GOOD;
11423 a = plci->adapter;
11424 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11425 && (plci->li_bchannel_id != 0)
11426 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11427 {
11428 switch (plci->adjust_b_state)
11429 {
11430 case ADJUST_B_RESTORE_MIXER_1:
11431 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11432 {
11433 plci->internal_command = plci->adjust_b_command;
11434 if (plci_nl_busy (plci))
11435 {
11436 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11437 break;
11438 }
11439 xconnect_query_addresses (plci);
11440 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11441 break;
11442 }
11443 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11444 Rc = OK;
11445 case ADJUST_B_RESTORE_MIXER_2:
11446 case ADJUST_B_RESTORE_MIXER_3:
11447 case ADJUST_B_RESTORE_MIXER_4:
11448 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11449 {
11450 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11451 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11452 Info = _WRONG_STATE;
11453 break;
11454 }
11455 if (Rc == OK)
11456 {
11457 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11458 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11459 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11460 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461 }
11462 else if (Rc == 0)
11463 {
11464 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11465 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11466 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11467 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468 }
11469 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11470 {
11471 plci->internal_command = plci->adjust_b_command;
11472 break;
11473 }
11474 case ADJUST_B_RESTORE_MIXER_5:
11475 xconnect_write_coefs (plci, plci->adjust_b_command);
11476 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11477 Rc = OK;
11478 case ADJUST_B_RESTORE_MIXER_6:
11479 if (!xconnect_write_coefs_process (Id, plci, Rc))
11480 {
11481 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11482 UnMapId (Id), (char *)(FILE_), __LINE__));
11483 Info = _FACILITY_NOT_SUPPORTED;
11484 break;
11485 }
11486 if (plci->internal_command)
11487 break;
11488 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11489 case ADJUST_B_RESTORE_MIXER_7:
11490 break;
11491 }
11492 }
11493 return (Info);
11494}
11495
11496
11497static void mixer_command (dword Id, PLCI *plci, byte Rc)
11498{
11499 DIVA_CAPI_ADAPTER *a;
11500 word i, internal_command, Info;
11501
11502 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11503 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11504 plci->li_cmd));
11505
11506 Info = GOOD;
11507 a = plci->adapter;
11508 internal_command = plci->internal_command;
11509 plci->internal_command = 0;
11510 switch (plci->li_cmd)
11511 {
11512 case LI_REQ_CONNECT:
11513 case LI_REQ_DISCONNECT:
11514 case LI_REQ_SILENT_UPDATE:
11515 switch (internal_command)
11516 {
11517 default:
11518 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11519 {
11520 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11521 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11522 }
11523 case MIXER_COMMAND_1:
11524 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11525 {
11526 if (adjust_b_process (Id, plci, Rc) != GOOD)
11527 {
11528 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11529 UnMapId (Id), (char *)(FILE_), __LINE__));
11530 Info = _FACILITY_NOT_SUPPORTED;
11531 break;
11532 }
11533 if (plci->internal_command)
11534 return;
11535 }
11536 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11537 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11538 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11539 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11540 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11541 {
11542 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11543 }
11544 else
11545 {
11546 do
11547 {
11548 mixer_indication_coefs_set (Id, plci);
11549 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11550 }
11551 case MIXER_COMMAND_2:
11552 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11555 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556 {
11557 if (!xconnect_write_coefs_process (Id, plci, Rc))
11558 {
11559 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11560 UnMapId (Id), (char *)(FILE_), __LINE__));
11561 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11562 {
11563 do
11564 {
11565 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11566 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11567 i = (plci->li_plci_b_write_pos == 0) ?
11568 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11569 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11570 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11571 }
11572 Info = _FACILITY_NOT_SUPPORTED;
11573 break;
11574 }
11575 if (plci->internal_command)
11576 return;
11577 }
11578 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11579 {
11580 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11581 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11582 }
11583 case MIXER_COMMAND_3:
11584 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11585 {
11586 if (adjust_b_process (Id, plci, Rc) != GOOD)
11587 {
11588 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11589 UnMapId (Id), (char *)(FILE_), __LINE__));
11590 Info = _FACILITY_NOT_SUPPORTED;
11591 break;
11592 }
11593 if (plci->internal_command)
11594 return;
11595 }
11596 break;
11597 }
11598 break;
11599 }
11600 if ((plci->li_bchannel_id == 0)
11601 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11602 {
11603 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11604 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11605 }
11606 else
11607 {
11608 i = a->li_base + (plci->li_bchannel_id - 1);
11609 li_config_table[i].curchnl = plci->li_channel_bits;
11610 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11611 {
11612 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11613 li_config_table[i].curchnl = plci->li_channel_bits;
11614 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11615 {
11616 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11617 li_config_table[i].curchnl = plci->li_channel_bits;
11618 }
11619 }
11620 }
11621}
11622
11623
11624static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11625 dword plci_b_id, byte connect, dword li_flags)
11626{
11627 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11628 PLCI *plci_b;
11629 DIVA_CAPI_ADAPTER *a_b;
11630
11631 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11632 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11633 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11634 if (!a->li_pri && (plci->tel == ADV_VOICE)
11635 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11636 {
11637 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11638 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11639 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11640 }
11641 else
11642 {
11643 ch_a_v = ch_a;
11644 ch_a_s = ch_a;
11645 }
11646 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11647 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11648 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11649 {
11650 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11651 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11652 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11653 }
11654 else
11655 {
11656 ch_b_v = ch_b;
11657 ch_b_s = ch_b;
11658 }
11659 if (connect)
11660 {
11661 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11662 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11663 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11664 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11665 }
11666 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11667 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11668 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670 if (ch_a_v == ch_b_v)
11671 {
11672 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11673 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11674 }
11675 else
11676 {
11677 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11678 {
11679 for (i = 0; i < li_total_channels; i++)
11680 {
11681 if (i != ch_a_v)
11682 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11683 }
11684 }
11685 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11686 {
11687 for (i = 0; i < li_total_channels; i++)
11688 {
11689 if (i != ch_a_s)
11690 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11691 }
11692 }
11693 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11694 {
11695 for (i = 0; i < li_total_channels; i++)
11696 {
11697 if (i != ch_a_v)
11698 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11699 }
11700 }
11701 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11702 {
11703 for (i = 0; i < li_total_channels; i++)
11704 {
11705 if (i != ch_a_s)
11706 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11707 }
11708 }
11709 }
11710 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11711 {
11712 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11713 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11714 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11715 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11716 }
11717 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11718 {
11719 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11722 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11723 }
11724 if (li_flags & LI_FLAG_MONITOR_A)
11725 {
11726 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11727 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11728 }
11729 if (li_flags & LI_FLAG_MONITOR_B)
11730 {
11731 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11732 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11733 }
11734 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11735 {
11736 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11737 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11738 }
11739 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11740 {
11741 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743 }
11744 if (li_flags & LI_FLAG_MIX_A)
11745 {
11746 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11747 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11748 }
11749 if (li_flags & LI_FLAG_MIX_B)
11750 {
11751 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11752 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11753 }
11754 if (ch_a_v != ch_a_s)
11755 {
11756 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11757 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11758 }
11759 if (ch_b_v != ch_b_s)
11760 {
11761 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11762 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11763 }
11764}
11765
11766
11767static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11768 dword plci_b_id, byte connect, dword li_flags)
11769{
11770 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11771 PLCI *plci_b;
11772 DIVA_CAPI_ADAPTER *a_b;
11773
11774 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11775 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11776 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11777 if (!a->li_pri && (plci->tel == ADV_VOICE)
11778 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11779 {
11780 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11781 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11782 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11783 }
11784 else
11785 {
11786 ch_a_v = ch_a;
11787 ch_a_s = ch_a;
11788 }
11789 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11790 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11791 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11792 {
11793 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11794 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11795 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11796 }
11797 else
11798 {
11799 ch_b_v = ch_b;
11800 ch_b_s = ch_b;
11801 }
11802 if (connect)
11803 {
11804 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11805 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11806 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11807 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11808 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11809 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11810 }
11811 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11820 {
11821 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11822 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11823 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11824 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11825 }
11826 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11827 {
11828 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11831 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11832 }
11833 if (li_flags & LI2_FLAG_MONITOR_B)
11834 {
11835 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11836 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11837 }
11838 if (li_flags & LI2_FLAG_MIX_B)
11839 {
11840 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11841 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11842 }
11843 if (li_flags & LI2_FLAG_MONITOR_X)
11844 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11845 if (li_flags & LI2_FLAG_MIX_X)
11846 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11847 if (li_flags & LI2_FLAG_LOOP_B)
11848 {
11849 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11850 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11851 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11852 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853 }
11854 if (li_flags & LI2_FLAG_LOOP_PC)
11855 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11856 if (li_flags & LI2_FLAG_LOOP_X)
11857 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11858 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11859 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11860 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11861 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11862 if (ch_a_v != ch_a_s)
11863 {
11864 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11865 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11866 }
11867 if (ch_b_v != ch_b_s)
11868 {
11869 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11870 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11871 }
11872}
11873
11874
11875static word li_check_main_plci (dword Id, PLCI *plci)
11876{
11877 if (plci == NULL)
11878 {
11879 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11880 UnMapId (Id), (char *)(FILE_), __LINE__));
11881 return (_WRONG_IDENTIFIER);
11882 }
11883 if (!plci->State
11884 || !plci->NL.Id || plci->nl_remove_id
11885 || (plci->li_bchannel_id == 0))
11886 {
11887 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11888 UnMapId (Id), (char *)(FILE_), __LINE__));
11889 return (_WRONG_STATE);
11890 }
11891 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11892 return (GOOD);
11893}
11894
11895
11896static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11897 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11898{
11899 byte ctlr_b;
11900 PLCI *plci_b;
11901
11902 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11903 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11904 {
11905 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11906 UnMapId (Id), (char *)(FILE_), __LINE__));
11907 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11908 return (NULL);
11909 }
11910 ctlr_b = 0;
11911 if ((plci_b_id & 0x7f) != 0)
11912 {
11913 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11914 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11915 ctlr_b = 0;
11916 }
11917 if ((ctlr_b == 0)
11918 || (((plci_b_id >> 8) & 0xff) == 0)
11919 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11920 {
11921 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11922 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11923 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11924 return (NULL);
11925 }
11926 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11927 if (!plci_b->State
11928 || !plci_b->NL.Id || plci_b->nl_remove_id
11929 || (plci_b->li_bchannel_id == 0))
11930 {
11931 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11932 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11933 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11934 return (NULL);
11935 }
11936 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11937 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11938 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11939 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11940 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11941 {
11942 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11943 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11944 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11945 return (NULL);
11946 }
11947 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11948 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11949 {
11950 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11951 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11952 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11953 return (NULL);
11954 }
11955 return (plci_b);
11956}
11957
11958
11959static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11960 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11961{
11962 byte ctlr_b;
11963 PLCI *plci_b;
11964
11965 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11966 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11967 {
11968 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11969 UnMapId (Id), (char *)(FILE_), __LINE__));
11970 PUT_WORD (p_result, _WRONG_STATE);
11971 return (NULL);
11972 }
11973 ctlr_b = 0;
11974 if ((plci_b_id & 0x7f) != 0)
11975 {
11976 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11977 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11978 ctlr_b = 0;
11979 }
11980 if ((ctlr_b == 0)
11981 || (((plci_b_id >> 8) & 0xff) == 0)
11982 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11983 {
11984 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11985 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11986 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11987 return (NULL);
11988 }
11989 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11990 if (!plci_b->State
11991 || !plci_b->NL.Id || plci_b->nl_remove_id
11992 || (plci_b->li_bchannel_id == 0)
11993 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11994 {
11995 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11996 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11997 PUT_WORD (p_result, _WRONG_STATE);
11998 return (NULL);
11999 }
12000 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12001 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12002 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12003 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12004 {
12005 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12006 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12007 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12008 return (NULL);
12009 }
12010 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12011 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12012 {
12013 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12014 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12015 PUT_WORD (p_result, _WRONG_STATE);
12016 return (NULL);
12017 }
12018 return (plci_b);
12019}
12020
12021
12022static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12023{
12024 word Info;
12025 word i;
12026 dword d, li_flags, plci_b_id;
12027 PLCI *plci_b;
12028 API_PARSE li_parms[3];
12029 API_PARSE li_req_parms[3];
12030 API_PARSE li_participant_struct[2];
12031 API_PARSE li_participant_parms[3];
12032 word participant_parms_pos;
12033 byte result_buffer[32];
12034 byte *result;
12035 word result_pos;
12036 word plci_b_write_pos;
12037
12038 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12039 UnMapId (Id), (char *)(FILE_), __LINE__));
12040
12041 Info = GOOD;
12042 result = result_buffer;
12043 result_buffer[0] = 0;
12044 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12045 {
12046 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12047 UnMapId (Id), (char *)(FILE_), __LINE__));
12048 Info = _FACILITY_NOT_SUPPORTED;
12049 }
12050 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12051 {
12052 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12053 UnMapId (Id), (char *)(FILE_), __LINE__));
12054 Info = _WRONG_MESSAGE_FORMAT;
12055 }
12056 else
12057 {
12058 result_buffer[0] = 3;
12059 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12060 result_buffer[3] = 0;
12061 switch (GET_WORD (li_parms[0].info))
12062 {
12063 case LI_GET_SUPPORTED_SERVICES:
12064 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12065 {
12066 result_buffer[0] = 17;
12067 result_buffer[3] = 14;
12068 PUT_WORD (&result_buffer[4], GOOD);
12069 d = 0;
12070 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12071 d |= LI_CONFERENCING_SUPPORTED;
12072 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12073 d |= LI_MONITORING_SUPPORTED;
12074 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12075 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12076 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12077 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12078 PUT_DWORD (&result_buffer[6], d);
12079 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12080 {
12081 d = 0;
12082 for (i = 0; i < li_total_channels; i++)
12083 {
12084 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12085 && (li_config_table[i].adapter->li_pri
12086 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12087 {
12088 d++;
12089 }
12090 }
12091 }
12092 else
12093 {
12094 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12095 }
12096 PUT_DWORD (&result_buffer[10], d / 2);
12097 PUT_DWORD (&result_buffer[14], d);
12098 }
12099 else
12100 {
12101 result_buffer[0] = 25;
12102 result_buffer[3] = 22;
12103 PUT_WORD (&result_buffer[4], GOOD);
12104 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12105 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12106 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12107 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12108 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12109 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12110 d |= LI2_PC_LOOPING_SUPPORTED;
12111 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12112 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12113 PUT_DWORD (&result_buffer[6], d);
12114 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12115 PUT_DWORD (&result_buffer[10], d / 2);
12116 PUT_DWORD (&result_buffer[14], d - 1);
12117 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118 {
12119 d = 0;
12120 for (i = 0; i < li_total_channels; i++)
12121 {
12122 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12123 && (li_config_table[i].adapter->li_pri
12124 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12125 {
12126 d++;
12127 }
12128 }
12129 }
12130 PUT_DWORD (&result_buffer[18], d / 2);
12131 PUT_DWORD (&result_buffer[22], d - 1);
12132 }
12133 break;
12134
12135 case LI_REQ_CONNECT:
12136 if (li_parms[1].length == 8)
12137 {
12138 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12139 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12140 {
12141 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12142 UnMapId (Id), (char *)(FILE_), __LINE__));
12143 Info = _WRONG_MESSAGE_FORMAT;
12144 break;
12145 }
12146 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12147 li_flags = GET_DWORD (li_req_parms[1].info);
12148 Info = li_check_main_plci (Id, plci);
12149 result_buffer[0] = 9;
12150 result_buffer[3] = 6;
12151 PUT_DWORD (&result_buffer[4], plci_b_id);
12152 PUT_WORD (&result_buffer[8], GOOD);
12153 if (Info != GOOD)
12154 break;
12155 result = plci->saved_msg.info;
12156 for (i = 0; i <= result_buffer[0]; i++)
12157 result[i] = result_buffer[i];
12158 plci_b_write_pos = plci->li_plci_b_write_pos;
12159 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12160 if (plci_b == NULL)
12161 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012162 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012163 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12164 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12165 plci->li_plci_b_write_pos = plci_b_write_pos;
12166 }
12167 else
12168 {
12169 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12170 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12171 {
12172 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12173 UnMapId (Id), (char *)(FILE_), __LINE__));
12174 Info = _WRONG_MESSAGE_FORMAT;
12175 break;
12176 }
12177 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12178 Info = li_check_main_plci (Id, plci);
12179 result_buffer[0] = 7;
12180 result_buffer[3] = 4;
12181 PUT_WORD (&result_buffer[4], Info);
12182 result_buffer[6] = 0;
12183 if (Info != GOOD)
12184 break;
12185 result = plci->saved_msg.info;
12186 for (i = 0; i <= result_buffer[0]; i++)
12187 result[i] = result_buffer[i];
12188 plci_b_write_pos = plci->li_plci_b_write_pos;
12189 participant_parms_pos = 0;
12190 result_pos = 7;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012191 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012192 while (participant_parms_pos < li_req_parms[1].length)
12193 {
12194 result[result_pos] = 6;
12195 result_pos += 7;
12196 PUT_DWORD (&result[result_pos - 6], 0);
12197 PUT_WORD (&result[result_pos - 2], GOOD);
12198 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12199 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12200 {
12201 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12202 UnMapId (Id), (char *)(FILE_), __LINE__));
12203 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12204 break;
12205 }
12206 if (api_parse (&li_participant_struct[0].info[1],
12207 li_participant_struct[0].length, "dd", li_participant_parms))
12208 {
12209 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12210 UnMapId (Id), (char *)(FILE_), __LINE__));
12211 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12212 break;
12213 }
12214 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12215 li_flags = GET_DWORD (li_participant_parms[1].info);
12216 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12217 if (sizeof(result) - result_pos < 7)
12218 {
12219 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12220 UnMapId (Id), (char *)(FILE_), __LINE__));
12221 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12222 break;
12223 }
12224 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12225 if (plci_b != NULL)
12226 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012227 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012228 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12229 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12230 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12231 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12232 }
12233 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12234 (&li_req_parms[1].info[1]));
12235 }
12236 result[0] = (byte)(result_pos - 1);
12237 result[3] = (byte)(result_pos - 4);
12238 result[6] = (byte)(result_pos - 7);
12239 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12240 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12241 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12242 {
12243 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12244 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12245 }
12246 else
12247 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12248 plci->li_plci_b_write_pos = plci_b_write_pos;
12249 }
12250 mixer_calculate_coefs (a);
12251 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012252 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012253 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12254 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12255 plci->command = 0;
12256 plci->li_cmd = GET_WORD (li_parms[0].info);
12257 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012258 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012259
12260 case LI_REQ_DISCONNECT:
12261 if (li_parms[1].length == 4)
12262 {
12263 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12264 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12265 {
12266 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12267 UnMapId (Id), (char *)(FILE_), __LINE__));
12268 Info = _WRONG_MESSAGE_FORMAT;
12269 break;
12270 }
12271 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12272 Info = li_check_main_plci (Id, plci);
12273 result_buffer[0] = 9;
12274 result_buffer[3] = 6;
12275 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12276 PUT_WORD (&result_buffer[8], GOOD);
12277 if (Info != GOOD)
12278 break;
12279 result = plci->saved_msg.info;
12280 for (i = 0; i <= result_buffer[0]; i++)
12281 result[i] = result_buffer[i];
12282 plci_b_write_pos = plci->li_plci_b_write_pos;
12283 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12284 if (plci_b == NULL)
12285 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012286 li_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012287 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12288 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12289 plci->li_plci_b_write_pos = plci_b_write_pos;
12290 }
12291 else
12292 {
12293 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12294 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12295 {
12296 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12297 UnMapId (Id), (char *)(FILE_), __LINE__));
12298 Info = _WRONG_MESSAGE_FORMAT;
12299 break;
12300 }
12301 Info = li_check_main_plci (Id, plci);
12302 result_buffer[0] = 7;
12303 result_buffer[3] = 4;
12304 PUT_WORD (&result_buffer[4], Info);
12305 result_buffer[6] = 0;
12306 if (Info != GOOD)
12307 break;
12308 result = plci->saved_msg.info;
12309 for (i = 0; i <= result_buffer[0]; i++)
12310 result[i] = result_buffer[i];
12311 plci_b_write_pos = plci->li_plci_b_write_pos;
12312 participant_parms_pos = 0;
12313 result_pos = 7;
12314 while (participant_parms_pos < li_req_parms[0].length)
12315 {
12316 result[result_pos] = 6;
12317 result_pos += 7;
12318 PUT_DWORD (&result[result_pos - 6], 0);
12319 PUT_WORD (&result[result_pos - 2], GOOD);
12320 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12321 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12322 {
12323 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12324 UnMapId (Id), (char *)(FILE_), __LINE__));
12325 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12326 break;
12327 }
12328 if (api_parse (&li_participant_struct[0].info[1],
12329 li_participant_struct[0].length, "d", li_participant_parms))
12330 {
12331 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12332 UnMapId (Id), (char *)(FILE_), __LINE__));
12333 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12334 break;
12335 }
12336 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12337 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12338 if (sizeof(result) - result_pos < 7)
12339 {
12340 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12341 UnMapId (Id), (char *)(FILE_), __LINE__));
12342 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12343 break;
12344 }
12345 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12346 if (plci_b != NULL)
12347 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012348 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012349 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12350 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12351 }
12352 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12353 (&li_req_parms[0].info[1]));
12354 }
12355 result[0] = (byte)(result_pos - 1);
12356 result[3] = (byte)(result_pos - 4);
12357 result[6] = (byte)(result_pos - 7);
12358 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12359 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12360 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12361 {
12362 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12363 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12364 }
12365 else
12366 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12367 plci->li_plci_b_write_pos = plci_b_write_pos;
12368 }
12369 mixer_calculate_coefs (a);
12370 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012371 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012372 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12373 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12374 plci->command = 0;
12375 plci->li_cmd = GET_WORD (li_parms[0].info);
12376 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012377 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012378
12379 case LI_REQ_SILENT_UPDATE:
12380 if (!plci || !plci->State
12381 || !plci->NL.Id || plci->nl_remove_id
12382 || (plci->li_bchannel_id == 0)
12383 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12384 {
12385 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12386 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012387 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012388 }
12389 plci_b_write_pos = plci->li_plci_b_write_pos;
12390 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12391 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12392 {
12393 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12394 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012395 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012396 }
12397 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12398 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12399 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12400 {
12401 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12402 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12403 }
12404 else
12405 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12406 plci->li_plci_b_write_pos = plci_b_write_pos;
12407 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12408 plci->command = 0;
12409 plci->li_cmd = GET_WORD (li_parms[0].info);
12410 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012411 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012412
12413 default:
12414 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12415 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12416 Info = _FACILITY_NOT_SUPPORTED;
12417 }
12418 }
12419 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12420 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012421 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012422}
12423
12424
12425static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12426{
12427 dword d;
12428 DIVA_CAPI_ADAPTER *a;
12429 byte result[12];
12430
12431 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12432 UnMapId (Id), (char *)(FILE_), __LINE__));
12433
12434 a = plci->adapter;
12435 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12436 {
12437 do
12438 {
12439 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12440 if (!(d & LI_PLCI_B_SKIP_FLAG))
12441 {
12442 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12443 {
12444 if (d & LI_PLCI_B_DISC_FLAG)
12445 {
12446 result[0] = 5;
12447 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12448 result[3] = 2;
12449 PUT_WORD (&result[4], _LI_USER_INITIATED);
12450 }
12451 else
12452 {
12453 result[0] = 7;
12454 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12455 result[3] = 4;
12456 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12457 }
12458 }
12459 else
12460 {
12461 if (d & LI_PLCI_B_DISC_FLAG)
12462 {
12463 result[0] = 9;
12464 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12465 result[3] = 6;
12466 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12467 PUT_WORD (&result[8], _LI_USER_INITIATED);
12468 }
12469 else
12470 {
12471 result[0] = 7;
12472 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12473 result[3] = 4;
12474 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12475 }
12476 }
12477 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12478 "ws", SELECTOR_LINE_INTERCONNECT, result);
12479 }
12480 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12481 0 : plci->li_plci_b_read_pos + 1;
12482 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12483 }
12484}
12485
12486
12487static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12488{
12489 word i, j, ch;
12490 struct xconnect_transfer_address_s s, *p;
12491 DIVA_CAPI_ADAPTER *a;
12492
12493 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12494 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12495
12496 a = plci->adapter;
12497 i = 1;
12498 for (i = 1; i < length; i += 16)
12499 {
12500 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12501 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12502 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12503 ch = msg[i+12] | (msg[i+13] << 8);
12504 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12505 if (!a->li_pri && (plci->li_bchannel_id == 2))
12506 j = 1 - j;
12507 j += a->li_base;
12508 if (ch & XCONNECT_CHANNEL_PORT_PC)
12509 p = &(li_config_table[j].send_pc);
12510 else
12511 p = &(li_config_table[j].send_b);
12512 p->card_address.low = s.card_address.low;
12513 p->card_address.high = s.card_address.high;
12514 p->offset = s.offset;
12515 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12516 }
12517 if (plci->internal_command_queue[0]
12518 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12519 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12520 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12521 {
12522 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12523 if (!plci->internal_command)
12524 next_internal_command (Id, plci);
12525 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012526 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012527}
12528
12529
12530static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12531{
12532
12533 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12534 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12535
12536}
12537
12538
12539static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12540{
12541 word plci_b_write_pos;
12542
12543 plci_b_write_pos = plci->li_plci_b_write_pos;
12544 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12545 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12546 {
12547 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12548 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12549 (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012550 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012551 }
12552 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12553 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12554 plci->li_plci_b_write_pos = plci_b_write_pos;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012555 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012556}
12557
12558
12559static void mixer_remove (PLCI *plci)
12560{
12561 DIVA_CAPI_ADAPTER *a;
12562 PLCI *notify_plci;
12563 dword plci_b_id;
12564 word i, j;
12565
12566 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12567 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12568 (char *)(FILE_), __LINE__));
12569
12570 a = plci->adapter;
12571 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12572 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12573 {
12574 if ((plci->li_bchannel_id != 0)
12575 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12576 {
12577 i = a->li_base + (plci->li_bchannel_id - 1);
12578 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12579 {
12580 for (j = 0; j < li_total_channels; j++)
12581 {
12582 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12583 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12584 {
12585 notify_plci = li_config_table[j].plci;
12586 if ((notify_plci != NULL)
12587 && (notify_plci != plci)
12588 && (notify_plci->appl != NULL)
12589 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12590 && (notify_plci->State)
12591 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12592 {
12593 mixer_notify_source_removed (notify_plci, plci_b_id);
12594 }
12595 }
12596 }
12597 mixer_clear_config (plci);
12598 mixer_calculate_coefs (a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012599 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012600 }
12601 li_config_table[i].plci = NULL;
12602 plci->li_bchannel_id = 0;
12603 }
12604 }
12605}
12606
12607
12608/*------------------------------------------------------------------*/
12609/* Echo canceller facilities */
12610/*------------------------------------------------------------------*/
12611
12612
12613static void ec_write_parameters (PLCI *plci)
12614{
12615 word w;
12616 byte parameter_buffer[6];
12617
12618 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12619 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12620 (char *)(FILE_), __LINE__));
12621
12622 parameter_buffer[0] = 5;
12623 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12624 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12625 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12626 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12627 PUT_WORD (&parameter_buffer[4], w);
12628 add_p (plci, FTY, parameter_buffer);
12629 sig_req (plci, TEL_CTRL, 0);
12630 send_req (plci);
12631}
12632
12633
12634static void ec_clear_config (PLCI *plci)
12635{
12636
12637 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12638 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12639 (char *)(FILE_), __LINE__));
12640
12641 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12642 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12643 plci->ec_tail_length = 0;
12644}
12645
12646
12647static void ec_prepare_switch (dword Id, PLCI *plci)
12648{
12649
12650 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12651 UnMapId (Id), (char *)(FILE_), __LINE__));
12652
12653}
12654
12655
12656static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12657{
12658
12659 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12660 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12661
12662 return (GOOD);
12663}
12664
12665
12666static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12667{
12668 word Info;
12669
12670 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12671 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672
12673 Info = GOOD;
12674 if (plci->B1_facilities & B1_FACILITY_EC)
12675 {
12676 switch (plci->adjust_b_state)
12677 {
12678 case ADJUST_B_RESTORE_EC_1:
12679 plci->internal_command = plci->adjust_b_command;
12680 if (plci->sig_req)
12681 {
12682 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12683 break;
12684 }
12685 ec_write_parameters (plci);
12686 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12687 break;
12688 case ADJUST_B_RESTORE_EC_2:
12689 if ((Rc != OK) && (Rc != OK_FC))
12690 {
12691 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12692 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12693 Info = _WRONG_STATE;
12694 break;
12695 }
12696 break;
12697 }
12698 }
12699 return (Info);
12700}
12701
12702
12703static void ec_command (dword Id, PLCI *plci, byte Rc)
12704{
12705 word internal_command, Info;
12706 byte result[8];
12707
12708 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12709 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12710 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12711
12712 Info = GOOD;
12713 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12714 {
12715 result[0] = 2;
12716 PUT_WORD (&result[1], EC_SUCCESS);
12717 }
12718 else
12719 {
12720 result[0] = 5;
12721 PUT_WORD (&result[1], plci->ec_cmd);
12722 result[3] = 2;
12723 PUT_WORD (&result[4], GOOD);
12724 }
12725 internal_command = plci->internal_command;
12726 plci->internal_command = 0;
12727 switch (plci->ec_cmd)
12728 {
12729 case EC_ENABLE_OPERATION:
12730 case EC_FREEZE_COEFFICIENTS:
12731 case EC_RESUME_COEFFICIENT_UPDATE:
12732 case EC_RESET_COEFFICIENTS:
12733 switch (internal_command)
12734 {
12735 default:
12736 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12737 B1_FACILITY_EC), EC_COMMAND_1);
12738 case EC_COMMAND_1:
12739 if (adjust_b_process (Id, plci, Rc) != GOOD)
12740 {
12741 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12742 UnMapId (Id), (char *)(FILE_), __LINE__));
12743 Info = _FACILITY_NOT_SUPPORTED;
12744 break;
12745 }
12746 if (plci->internal_command)
12747 return;
12748 case EC_COMMAND_2:
12749 if (plci->sig_req)
12750 {
12751 plci->internal_command = EC_COMMAND_2;
12752 return;
12753 }
12754 plci->internal_command = EC_COMMAND_3;
12755 ec_write_parameters (plci);
12756 return;
12757 case EC_COMMAND_3:
12758 if ((Rc != OK) && (Rc != OK_FC))
12759 {
12760 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12761 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12762 Info = _FACILITY_NOT_SUPPORTED;
12763 break;
12764 }
12765 break;
12766 }
12767 break;
12768
12769 case EC_DISABLE_OPERATION:
12770 switch (internal_command)
12771 {
12772 default:
12773 case EC_COMMAND_1:
12774 if (plci->B1_facilities & B1_FACILITY_EC)
12775 {
12776 if (plci->sig_req)
12777 {
12778 plci->internal_command = EC_COMMAND_1;
12779 return;
12780 }
12781 plci->internal_command = EC_COMMAND_2;
12782 ec_write_parameters (plci);
12783 return;
12784 }
12785 Rc = OK;
12786 case EC_COMMAND_2:
12787 if ((Rc != OK) && (Rc != OK_FC))
12788 {
12789 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12790 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12791 Info = _FACILITY_NOT_SUPPORTED;
12792 break;
12793 }
12794 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12795 ~B1_FACILITY_EC), EC_COMMAND_3);
12796 case EC_COMMAND_3:
12797 if (adjust_b_process (Id, plci, Rc) != GOOD)
12798 {
12799 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12800 UnMapId (Id), (char *)(FILE_), __LINE__));
12801 Info = _FACILITY_NOT_SUPPORTED;
12802 break;
12803 }
12804 if (plci->internal_command)
12805 return;
12806 break;
12807 }
12808 break;
12809 }
12810 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12811 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12812 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12813}
12814
12815
12816static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12817{
12818 word Info;
12819 word opt;
12820 API_PARSE ec_parms[3];
12821 byte result[16];
12822
12823 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12824 UnMapId (Id), (char *)(FILE_), __LINE__));
12825
12826 Info = GOOD;
12827 result[0] = 0;
12828 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12829 {
12830 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12831 UnMapId (Id), (char *)(FILE_), __LINE__));
12832 Info = _FACILITY_NOT_SUPPORTED;
12833 }
12834 else
12835 {
12836 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12837 {
12838 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12839 {
12840 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12841 UnMapId (Id), (char *)(FILE_), __LINE__));
12842 Info = _WRONG_MESSAGE_FORMAT;
12843 }
12844 else
12845 {
12846 if (plci == NULL)
12847 {
12848 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12849 UnMapId (Id), (char *)(FILE_), __LINE__));
12850 Info = _WRONG_IDENTIFIER;
12851 }
12852 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12853 {
12854 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12855 UnMapId (Id), (char *)(FILE_), __LINE__));
12856 Info = _WRONG_STATE;
12857 }
12858 else
12859 {
12860 plci->command = 0;
12861 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12862 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12863 result[0] = 2;
12864 PUT_WORD (&result[1], EC_SUCCESS);
12865 if (msg[1].length >= 4)
12866 {
12867 opt = GET_WORD (&ec_parms[0].info[2]);
12868 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12869 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12870 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12871 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12872 if (opt & EC_DETECT_DISABLE_TONE)
12873 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12874 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12875 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12876 if (msg[1].length >= 6)
12877 {
12878 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12879 }
12880 }
12881 switch (plci->ec_cmd)
12882 {
12883 case EC_ENABLE_OPERATION:
12884 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12885 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012886 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012887
12888 case EC_DISABLE_OPERATION:
12889 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12890 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12891 LEC_RESET_COEFFICIENTS;
12892 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012893 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012894
12895 case EC_FREEZE_COEFFICIENTS:
12896 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12897 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012898 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012899
12900 case EC_RESUME_COEFFICIENT_UPDATE:
12901 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12902 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012903 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012904
12905 case EC_RESET_COEFFICIENTS:
12906 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12907 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012908 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012909
12910 default:
12911 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12912 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12913 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12914 }
12915 }
12916 }
12917 }
12918 else
12919 {
12920 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12921 {
12922 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12923 UnMapId (Id), (char *)(FILE_), __LINE__));
12924 Info = _WRONG_MESSAGE_FORMAT;
12925 }
12926 else
12927 {
12928 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12929 {
12930 result[0] = 11;
12931 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12932 result[3] = 8;
12933 PUT_WORD (&result[4], GOOD);
12934 PUT_WORD (&result[6], 0x0007);
12935 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12936 PUT_WORD (&result[10], 0);
12937 }
12938 else if (plci == NULL)
12939 {
12940 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12941 UnMapId (Id), (char *)(FILE_), __LINE__));
12942 Info = _WRONG_IDENTIFIER;
12943 }
12944 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12945 {
12946 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12947 UnMapId (Id), (char *)(FILE_), __LINE__));
12948 Info = _WRONG_STATE;
12949 }
12950 else
12951 {
12952 plci->command = 0;
12953 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12954 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12955 result[0] = 5;
12956 PUT_WORD (&result[1], plci->ec_cmd);
12957 result[3] = 2;
12958 PUT_WORD (&result[4], GOOD);
12959 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12960 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12961 plci->ec_tail_length = 0;
12962 if (ec_parms[1].length >= 2)
12963 {
12964 opt = GET_WORD (&ec_parms[1].info[1]);
12965 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12966 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12967 if (opt & EC_DETECT_DISABLE_TONE)
12968 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12969 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12970 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12971 if (ec_parms[1].length >= 4)
12972 {
12973 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12974 }
12975 }
12976 switch (plci->ec_cmd)
12977 {
12978 case EC_ENABLE_OPERATION:
12979 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12980 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012981 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012982
12983 case EC_DISABLE_OPERATION:
12984 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12985 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12986 LEC_RESET_COEFFICIENTS;
12987 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012988 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012989
12990 default:
12991 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12992 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12993 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12994 }
12995 }
12996 }
12997 }
12998 }
12999 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13000 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13001 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013002 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013003}
13004
13005
13006static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13007{
13008 byte result[8];
13009
13010 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13011 UnMapId (Id), (char *)(FILE_), __LINE__));
13012
13013 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13014 {
13015 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13016 {
13017 result[0] = 2;
13018 PUT_WORD (&result[1], 0);
13019 switch (msg[1])
13020 {
13021 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13022 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13023 break;
13024 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13025 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13026 break;
13027 case LEC_DISABLE_RELEASED:
13028 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13029 break;
13030 }
13031 }
13032 else
13033 {
13034 result[0] = 5;
13035 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13036 result[3] = 2;
13037 PUT_WORD (&result[4], 0);
13038 switch (msg[1])
13039 {
13040 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13041 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13042 break;
13043 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13044 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13045 break;
13046 case LEC_DISABLE_RELEASED:
13047 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13048 break;
13049 }
13050 }
13051 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13052 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13053 }
13054}
13055
13056
13057
13058/*------------------------------------------------------------------*/
13059/* Advanced voice */
13060/*------------------------------------------------------------------*/
13061
13062static void adv_voice_write_coefs (PLCI *plci, word write_command)
13063{
13064 DIVA_CAPI_ADAPTER *a;
13065 word i;
13066 byte *p;
13067
13068 word w, n, j, k;
13069 byte ch_map[MIXER_CHANNELS_BRI];
13070
13071 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13072
13073 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13074 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13075 (char *)(FILE_), __LINE__, write_command));
13076
13077 a = plci->adapter;
13078 p = coef_buffer + 1;
13079 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13080 i = 0;
13081 while (i + sizeof(word) <= a->adv_voice_coef_length)
13082 {
13083 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13084 p += 2;
13085 i += 2;
13086 }
13087 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13088 {
13089 PUT_WORD (p, 0x8000);
13090 p += 2;
13091 i += 2;
13092 }
13093
13094 if (!a->li_pri && (plci->li_bchannel_id == 0))
13095 {
13096 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13097 {
13098 plci->li_bchannel_id = 1;
13099 li_config_table[a->li_base].plci = plci;
13100 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13101 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13102 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13103 }
13104 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13105 {
13106 plci->li_bchannel_id = 2;
13107 li_config_table[a->li_base + 1].plci = plci;
13108 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13109 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13110 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13111 }
13112 }
13113 if (!a->li_pri && (plci->li_bchannel_id != 0)
13114 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13115 {
13116 i = a->li_base + (plci->li_bchannel_id - 1);
13117 switch (write_command)
13118 {
13119 case ADV_VOICE_WRITE_ACTIVATION:
13120 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13121 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13122 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13123 {
13124 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13125 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13126 }
13127 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13128 {
13129 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13132 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13133 }
13134 mixer_calculate_coefs (a);
13135 li_config_table[i].curchnl = li_config_table[i].channel;
13136 li_config_table[j].curchnl = li_config_table[j].channel;
13137 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13138 li_config_table[k].curchnl = li_config_table[k].channel;
13139 break;
13140
13141 case ADV_VOICE_WRITE_DEACTIVATION:
13142 for (j = 0; j < li_total_channels; j++)
13143 {
13144 li_config_table[i].flag_table[j] = 0;
13145 li_config_table[j].flag_table[i] = 0;
13146 }
13147 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13148 for (j = 0; j < li_total_channels; j++)
13149 {
13150 li_config_table[k].flag_table[j] = 0;
13151 li_config_table[j].flag_table[k] = 0;
13152 }
13153 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13154 {
13155 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13156 for (j = 0; j < li_total_channels; j++)
13157 {
13158 li_config_table[k].flag_table[j] = 0;
13159 li_config_table[j].flag_table[k] = 0;
13160 }
13161 }
13162 mixer_calculate_coefs (a);
13163 break;
13164 }
13165 if (plci->B1_facilities & B1_FACILITY_MIXER)
13166 {
13167 w = 0;
13168 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13169 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13170 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13171 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13172 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13173 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13174 *(p++) = (byte) w;
13175 *(p++) = (byte)(w >> 8);
13176 for (j = 0; j < sizeof(ch_map); j += 2)
13177 {
13178 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13179 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13180 }
13181 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
13182 {
13183 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13184 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13185 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13186 {
13187 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13188 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13189 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13190 }
13191 else
13192 {
13193 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13194 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13195 }
13196 }
13197 }
13198 else
13199 {
13200 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13201 *(p++) = a->adv_voice_coef_buffer[i];
13202 }
13203 }
13204 else
13205
13206 {
13207 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13208 *(p++) = a->adv_voice_coef_buffer[i];
13209 }
13210 coef_buffer[0] = (p - coef_buffer) - 1;
13211 add_p (plci, FTY, coef_buffer);
13212 sig_req (plci, TEL_CTRL, 0);
13213 send_req (plci);
13214}
13215
13216
13217static void adv_voice_clear_config (PLCI *plci)
13218{
13219 DIVA_CAPI_ADAPTER *a;
13220
13221 word i, j;
13222
13223
13224 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13225 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13226 (char *)(FILE_), __LINE__));
13227
13228 a = plci->adapter;
13229 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13230 {
13231 a->adv_voice_coef_length = 0;
13232
13233 if (!a->li_pri && (plci->li_bchannel_id != 0)
13234 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13235 {
13236 i = a->li_base + (plci->li_bchannel_id - 1);
13237 li_config_table[i].curchnl = 0;
13238 li_config_table[i].channel = 0;
13239 li_config_table[i].chflags = 0;
13240 for (j = 0; j < li_total_channels; j++)
13241 {
13242 li_config_table[i].flag_table[j] = 0;
13243 li_config_table[j].flag_table[i] = 0;
13244 li_config_table[i].coef_table[j] = 0;
13245 li_config_table[j].coef_table[i] = 0;
13246 }
13247 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13248 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13249 li_config_table[i].curchnl = 0;
13250 li_config_table[i].channel = 0;
13251 li_config_table[i].chflags = 0;
13252 for (j = 0; j < li_total_channels; j++)
13253 {
13254 li_config_table[i].flag_table[j] = 0;
13255 li_config_table[j].flag_table[i] = 0;
13256 li_config_table[i].coef_table[j] = 0;
13257 li_config_table[j].coef_table[i] = 0;
13258 }
13259 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13260 {
13261 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13262 li_config_table[i].curchnl = 0;
13263 li_config_table[i].channel = 0;
13264 li_config_table[i].chflags = 0;
13265 for (j = 0; j < li_total_channels; j++)
13266 {
13267 li_config_table[i].flag_table[j] = 0;
13268 li_config_table[j].flag_table[i] = 0;
13269 li_config_table[i].coef_table[j] = 0;
13270 li_config_table[j].coef_table[i] = 0;
13271 }
13272 }
13273 }
13274
13275 }
13276}
13277
13278
13279static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13280{
13281
13282 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13283 UnMapId (Id), (char *)(FILE_), __LINE__));
13284
13285}
13286
13287
13288static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13289{
13290
13291 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13292 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13293
13294 return (GOOD);
13295}
13296
13297
13298static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13299{
13300 DIVA_CAPI_ADAPTER *a;
13301 word Info;
13302
13303 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13304 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13305
13306 Info = GOOD;
13307 a = plci->adapter;
13308 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13309 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13310 {
13311 switch (plci->adjust_b_state)
13312 {
13313 case ADJUST_B_RESTORE_VOICE_1:
13314 plci->internal_command = plci->adjust_b_command;
13315 if (plci->sig_req)
13316 {
13317 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13318 break;
13319 }
13320 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13321 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13322 break;
13323 case ADJUST_B_RESTORE_VOICE_2:
13324 if ((Rc != OK) && (Rc != OK_FC))
13325 {
13326 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13327 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13328 Info = _WRONG_STATE;
13329 break;
13330 }
13331 break;
13332 }
13333 }
13334 return (Info);
13335}
13336
13337
13338
13339
13340/*------------------------------------------------------------------*/
13341/* B1 resource switching */
13342/*------------------------------------------------------------------*/
13343
13344static byte b1_facilities_table[] =
13345{
13346 0x00, /* 0 No bchannel resources */
13347 0x00, /* 1 Codec (automatic law) */
13348 0x00, /* 2 Codec (A-law) */
13349 0x00, /* 3 Codec (y-law) */
13350 0x00, /* 4 HDLC for X.21 */
13351 0x00, /* 5 HDLC */
13352 0x00, /* 6 External Device 0 */
13353 0x00, /* 7 External Device 1 */
13354 0x00, /* 8 HDLC 56k */
13355 0x00, /* 9 Transparent */
13356 0x00, /* 10 Loopback to network */
13357 0x00, /* 11 Test pattern to net */
13358 0x00, /* 12 Rate adaptation sync */
13359 0x00, /* 13 Rate adaptation async */
13360 0x00, /* 14 R-Interface */
13361 0x00, /* 15 HDLC 128k leased line */
13362 0x00, /* 16 FAX */
13363 0x00, /* 17 Modem async */
13364 0x00, /* 18 Modem sync HDLC */
13365 0x00, /* 19 V.110 async HDLC */
13366 0x12, /* 20 Adv voice (Trans,mixer) */
13367 0x00, /* 21 Codec connected to IC */
13368 0x0c, /* 22 Trans,DTMF */
13369 0x1e, /* 23 Trans,DTMF+mixer */
13370 0x1f, /* 24 Trans,DTMF+mixer+local */
13371 0x13, /* 25 Trans,mixer+local */
13372 0x12, /* 26 HDLC,mixer */
13373 0x12, /* 27 HDLC 56k,mixer */
13374 0x2c, /* 28 Trans,LEC+DTMF */
13375 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13376 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13377 0x2c, /* 31 RTP,LEC+DTMF */
13378 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13379 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13380 0x00, /* 34 Signaling task */
13381 0x00, /* 35 PIAFS */
13382 0x0c, /* 36 Trans,DTMF+TONE */
13383 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13384 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13385};
13386
13387
13388static word get_b1_facilities (PLCI * plci, byte b1_resource)
13389{
13390 word b1_facilities;
13391
13392 b1_facilities = b1_facilities_table[b1_resource];
13393 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13394 {
13395
13396 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13397 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13398
13399 {
13400 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13401 b1_facilities |= B1_FACILITY_DTMFX;
13402 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13403 b1_facilities |= B1_FACILITY_DTMFR;
13404 }
13405 }
13406 if ((b1_resource == 17) || (b1_resource == 18))
13407 {
13408 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13409 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13410 }
13411/*
13412 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13413 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13414 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13415*/
13416 return (b1_facilities);
13417}
13418
13419
13420static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13421{
13422 byte b;
13423
13424 switch (b1_resource)
13425 {
13426 case 5:
13427 case 26:
13428 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13429 b = 26;
13430 else
13431 b = 5;
13432 break;
13433
13434 case 8:
13435 case 27:
13436 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13437 b = 27;
13438 else
13439 b = 8;
13440 break;
13441
13442 case 9:
13443 case 20:
13444 case 22:
13445 case 23:
13446 case 24:
13447 case 25:
13448 case 28:
13449 case 29:
13450 case 30:
13451 case 36:
13452 case 37:
13453 case 38:
13454 if (b1_facilities & B1_FACILITY_EC)
13455 {
13456 if (b1_facilities & B1_FACILITY_LOCAL)
13457 b = 30;
13458 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13459 b = 29;
13460 else
13461 b = 28;
13462 }
13463
13464 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13465 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13466 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13467 {
13468 if (b1_facilities & B1_FACILITY_LOCAL)
13469 b = 38;
13470 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13471 b = 37;
13472 else
13473 b = 36;
13474 }
13475
13476 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13477 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13478 || ((b1_facilities & B1_FACILITY_DTMFR)
13479 && ((b1_facilities & B1_FACILITY_MIXER)
13480 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13481 || ((b1_facilities & B1_FACILITY_DTMFX)
13482 && ((b1_facilities & B1_FACILITY_MIXER)
13483 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13484 {
13485 if (b1_facilities & B1_FACILITY_LOCAL)
13486 b = 24;
13487 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13488 b = 23;
13489 else
13490 b = 22;
13491 }
13492 else
13493 {
13494 if (b1_facilities & B1_FACILITY_LOCAL)
13495 b = 25;
13496 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13497 b = 20;
13498 else
13499 b = 9;
13500 }
13501 break;
13502
13503 case 31:
13504 case 32:
13505 case 33:
13506 if (b1_facilities & B1_FACILITY_LOCAL)
13507 b = 33;
13508 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13509 b = 32;
13510 else
13511 b = 31;
13512 break;
13513
13514 default:
13515 b = b1_resource;
13516 }
13517 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13518 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13519 (char *)(FILE_), __LINE__,
13520 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13521 return (b);
13522}
13523
13524
13525static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13526{
13527 word removed_facilities;
13528
13529 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13530 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13531 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13532 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13533
13534 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13535 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13536
13537 if (removed_facilities & B1_FACILITY_EC)
13538 ec_clear_config (plci);
13539
13540
13541 if (removed_facilities & B1_FACILITY_DTMFR)
13542 {
13543 dtmf_rec_clear_config (plci);
13544 dtmf_parameter_clear_config (plci);
13545 }
13546 if (removed_facilities & B1_FACILITY_DTMFX)
13547 dtmf_send_clear_config (plci);
13548
13549
13550 if (removed_facilities & B1_FACILITY_MIXER)
13551 mixer_clear_config (plci);
13552
13553 if (removed_facilities & B1_FACILITY_VOICE)
13554 adv_voice_clear_config (plci);
13555 plci->B1_facilities = new_b1_facilities;
13556}
13557
13558
13559static void adjust_b_clear (PLCI *plci)
13560{
13561
13562 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13563 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13564 (char *)(FILE_), __LINE__));
13565
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013566 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013567}
13568
13569
13570static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13571{
13572 word Info;
13573 byte b1_resource;
13574 NCCI * ncci_ptr;
13575 API_PARSE bp[2];
13576
13577 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13578 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13579
13580 Info = GOOD;
13581 switch (plci->adjust_b_state)
13582 {
13583 case ADJUST_B_START:
13584 if ((plci->adjust_b_parms_msg == NULL)
13585 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13586 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13587 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13588 {
13589 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13590 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13591 if (b1_resource == plci->B1_resource)
13592 {
13593 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13594 break;
13595 }
13596 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13597 {
13598 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13599 UnMapId (Id), (char *)(FILE_), __LINE__,
13600 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13601 Info = _WRONG_STATE;
13602 break;
13603 }
13604 }
13605 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13606 {
13607
13608 mixer_prepare_switch (Id, plci);
13609
13610
13611 dtmf_prepare_switch (Id, plci);
13612 dtmf_parameter_prepare_switch (Id, plci);
13613
13614
13615 ec_prepare_switch (Id, plci);
13616
13617 adv_voice_prepare_switch (Id, plci);
13618 }
13619 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13620 Rc = OK;
13621 case ADJUST_B_SAVE_MIXER_1:
13622 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13623 {
13624
13625 Info = mixer_save_config (Id, plci, Rc);
13626 if ((Info != GOOD) || plci->internal_command)
13627 break;
13628
13629 }
13630 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13631 Rc = OK;
13632 case ADJUST_B_SAVE_DTMF_1:
13633 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634 {
13635
13636 Info = dtmf_save_config (Id, plci, Rc);
13637 if ((Info != GOOD) || plci->internal_command)
13638 break;
13639
13640 }
13641 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13642 case ADJUST_B_REMOVE_L23_1:
13643 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13644 && plci->NL.Id && !plci->nl_remove_id)
13645 {
13646 plci->internal_command = plci->adjust_b_command;
13647 if (plci->adjust_b_ncci != 0)
13648 {
13649 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13650 while (ncci_ptr->data_pending)
13651 {
13652 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13653 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13654 }
13655 while (ncci_ptr->data_ack_pending)
13656 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13657 }
13658 nl_req_ncci (plci, REMOVE,
13659 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13660 send_req (plci);
13661 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13662 break;
13663 }
13664 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13665 Rc = OK;
13666 case ADJUST_B_REMOVE_L23_2:
13667 if ((Rc != OK) && (Rc != OK_FC))
13668 {
13669 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13670 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13671 Info = _WRONG_STATE;
13672 break;
13673 }
13674 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13675 {
13676 if (plci_nl_busy (plci))
13677 {
13678 plci->internal_command = plci->adjust_b_command;
13679 break;
13680 }
13681 }
13682 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13683 Rc = OK;
13684 case ADJUST_B_SAVE_EC_1:
13685 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13686 {
13687
13688 Info = ec_save_config (Id, plci, Rc);
13689 if ((Info != GOOD) || plci->internal_command)
13690 break;
13691
13692 }
13693 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13694 Rc = OK;
13695 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13696 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697 {
13698
13699 Info = dtmf_parameter_save_config (Id, plci, Rc);
13700 if ((Info != GOOD) || plci->internal_command)
13701 break;
13702
13703 }
13704 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13705 Rc = OK;
13706 case ADJUST_B_SAVE_VOICE_1:
13707 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708 {
13709 Info = adv_voice_save_config (Id, plci, Rc);
13710 if ((Info != GOOD) || plci->internal_command)
13711 break;
13712 }
13713 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13714 case ADJUST_B_SWITCH_L1_1:
13715 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13716 {
13717 if (plci->sig_req)
13718 {
13719 plci->internal_command = plci->adjust_b_command;
13720 break;
13721 }
13722 if (plci->adjust_b_parms_msg != NULL)
13723 api_load_msg (plci->adjust_b_parms_msg, bp);
13724 else
13725 api_load_msg (&plci->B_protocol, bp);
13726 Info = add_b1 (plci, bp,
13727 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13728 plci->adjust_b_facilities);
13729 if (Info != GOOD)
13730 {
13731 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13732 UnMapId (Id), (char *)(FILE_), __LINE__,
13733 plci->B1_resource, plci->adjust_b_facilities));
13734 break;
13735 }
13736 plci->internal_command = plci->adjust_b_command;
13737 sig_req (plci, RESOURCES, 0);
13738 send_req (plci);
13739 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13740 break;
13741 }
13742 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13743 Rc = OK;
13744 case ADJUST_B_SWITCH_L1_2:
13745 if ((Rc != OK) && (Rc != OK_FC))
13746 {
13747 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13748 UnMapId (Id), (char *)(FILE_), __LINE__,
13749 Rc, plci->B1_resource, plci->adjust_b_facilities));
13750 Info = _WRONG_STATE;
13751 break;
13752 }
13753 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13754 Rc = OK;
13755 case ADJUST_B_RESTORE_VOICE_1:
13756 case ADJUST_B_RESTORE_VOICE_2:
13757 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13758 {
13759 Info = adv_voice_restore_config (Id, plci, Rc);
13760 if ((Info != GOOD) || plci->internal_command)
13761 break;
13762 }
13763 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13764 Rc = OK;
13765 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13766 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13767 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13768 {
13769
13770 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13771 if ((Info != GOOD) || plci->internal_command)
13772 break;
13773
13774 }
13775 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13776 Rc = OK;
13777 case ADJUST_B_RESTORE_EC_1:
13778 case ADJUST_B_RESTORE_EC_2:
13779 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13780 {
13781
13782 Info = ec_restore_config (Id, plci, Rc);
13783 if ((Info != GOOD) || plci->internal_command)
13784 break;
13785
13786 }
13787 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13788 case ADJUST_B_ASSIGN_L23_1:
13789 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13790 {
13791 if (plci_nl_busy (plci))
13792 {
13793 plci->internal_command = plci->adjust_b_command;
13794 break;
13795 }
13796 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13797 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13798 if (plci->adjust_b_parms_msg != NULL)
13799 api_load_msg (plci->adjust_b_parms_msg, bp);
13800 else
13801 api_load_msg (&plci->B_protocol, bp);
13802 Info = add_b23 (plci, bp);
13803 if (Info != GOOD)
13804 {
13805 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13806 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13807 break;
13808 }
13809 plci->internal_command = plci->adjust_b_command;
13810 nl_req_ncci (plci, ASSIGN, 0);
13811 send_req (plci);
13812 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13813 break;
13814 }
13815 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13816 Rc = ASSIGN_OK;
13817 case ADJUST_B_ASSIGN_L23_2:
13818 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13819 {
13820 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13821 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13822 Info = _WRONG_STATE;
13823 break;
13824 }
13825 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13826 {
13827 if (Rc != ASSIGN_OK)
13828 {
13829 plci->internal_command = plci->adjust_b_command;
13830 break;
13831 }
13832 }
13833 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13834 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013835 plci->adjust_b_restore = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013836 break;
13837 }
13838 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13839 case ADJUST_B_CONNECT_1:
13840 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13841 {
13842 plci->internal_command = plci->adjust_b_command;
13843 if (plci_nl_busy (plci))
13844 break;
13845 nl_req_ncci (plci, N_CONNECT, 0);
13846 send_req (plci);
13847 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13848 break;
13849 }
13850 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13851 Rc = OK;
13852 case ADJUST_B_CONNECT_2:
13853 case ADJUST_B_CONNECT_3:
13854 case ADJUST_B_CONNECT_4:
13855 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13856 {
13857 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13858 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13859 Info = _WRONG_STATE;
13860 break;
13861 }
13862 if (Rc == OK)
13863 {
13864 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865 {
13866 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13867 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13868 }
13869 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13870 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13871 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13872 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13873 }
13874 else if (Rc == 0)
13875 {
13876 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13877 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13878 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13879 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13880 }
13881 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13882 {
13883 plci->internal_command = plci->adjust_b_command;
13884 break;
13885 }
13886 Rc = OK;
13887 case ADJUST_B_RESTORE_DTMF_1:
13888 case ADJUST_B_RESTORE_DTMF_2:
13889 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13890 {
13891
13892 Info = dtmf_restore_config (Id, plci, Rc);
13893 if ((Info != GOOD) || plci->internal_command)
13894 break;
13895
13896 }
13897 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13898 Rc = OK;
13899 case ADJUST_B_RESTORE_MIXER_1:
13900 case ADJUST_B_RESTORE_MIXER_2:
13901 case ADJUST_B_RESTORE_MIXER_3:
13902 case ADJUST_B_RESTORE_MIXER_4:
13903 case ADJUST_B_RESTORE_MIXER_5:
13904 case ADJUST_B_RESTORE_MIXER_6:
13905 case ADJUST_B_RESTORE_MIXER_7:
13906 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13907 {
13908
13909 Info = mixer_restore_config (Id, plci, Rc);
13910 if ((Info != GOOD) || plci->internal_command)
13911 break;
13912
13913 }
13914 plci->adjust_b_state = ADJUST_B_END;
13915 case ADJUST_B_END:
13916 break;
13917 }
13918 return (Info);
13919}
13920
13921
13922static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13923{
13924
13925 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13926 UnMapId (Id), (char *)(FILE_), __LINE__,
13927 plci->B1_resource, b1_facilities));
13928
13929 plci->adjust_b_parms_msg = bp_msg;
13930 plci->adjust_b_facilities = b1_facilities;
13931 plci->adjust_b_command = internal_command;
13932 plci->adjust_b_ncci = (word)(Id >> 16);
13933 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13934 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13935 else
13936 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13937 plci->adjust_b_state = ADJUST_B_START;
13938 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13939 UnMapId (Id), (char *)(FILE_), __LINE__,
13940 plci->B1_resource, b1_facilities));
13941}
13942
13943
13944static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13945{
13946 word internal_command;
13947
13948 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13949 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13950
13951 internal_command = plci->internal_command;
13952 plci->internal_command = 0;
13953 switch (internal_command)
13954 {
13955 default:
13956 plci->command = 0;
13957 if (plci->req_in != 0)
13958 {
13959 plci->internal_command = ADJUST_B_RESTORE_1;
13960 break;
13961 }
13962 Rc = OK;
13963 case ADJUST_B_RESTORE_1:
13964 if ((Rc != OK) && (Rc != OK_FC))
13965 {
13966 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13967 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13968 }
13969 plci->adjust_b_parms_msg = NULL;
13970 plci->adjust_b_facilities = plci->B1_facilities;
13971 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13972 plci->adjust_b_ncci = (word)(Id >> 16);
13973 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13974 plci->adjust_b_state = ADJUST_B_START;
13975 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13976 UnMapId (Id), (char *)(FILE_), __LINE__));
13977 case ADJUST_B_RESTORE_2:
13978 if (adjust_b_process (Id, plci, Rc) != GOOD)
13979 {
13980 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13981 UnMapId (Id), (char *)(FILE_), __LINE__));
13982 }
13983 if (plci->internal_command)
13984 break;
13985 break;
13986 }
13987}
13988
13989
13990static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13991{
13992 word Info;
13993 word internal_command;
13994
13995 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13996 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13997
13998 Info = GOOD;
13999 internal_command = plci->internal_command;
14000 plci->internal_command = 0;
14001 switch (internal_command)
14002 {
14003 default:
14004 plci->command = 0;
14005 plci->adjust_b_parms_msg = NULL;
14006 plci->adjust_b_facilities = plci->B1_facilities;
14007 plci->adjust_b_command = RESET_B3_COMMAND_1;
14008 plci->adjust_b_ncci = (word)(Id >> 16);
14009 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14010 plci->adjust_b_state = ADJUST_B_START;
14011 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14012 UnMapId (Id), (char *)(FILE_), __LINE__));
14013 case RESET_B3_COMMAND_1:
14014 Info = adjust_b_process (Id, plci, Rc);
14015 if (Info != GOOD)
14016 {
14017 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14018 UnMapId (Id), (char *)(FILE_), __LINE__));
14019 break;
14020 }
14021 if (plci->internal_command)
14022 return;
14023 break;
14024 }
14025/* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14026 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14027}
14028
14029
14030static void select_b_command (dword Id, PLCI *plci, byte Rc)
14031{
14032 word Info;
14033 word internal_command;
14034 byte esc_chi[3];
14035
14036 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14037 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14038
14039 Info = GOOD;
14040 internal_command = plci->internal_command;
14041 plci->internal_command = 0;
14042 switch (internal_command)
14043 {
14044 default:
14045 plci->command = 0;
14046 plci->adjust_b_parms_msg = &plci->saved_msg;
14047 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14048 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14049 else
14050 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14051 plci->adjust_b_command = SELECT_B_COMMAND_1;
14052 plci->adjust_b_ncci = (word)(Id >> 16);
14053 if (plci->saved_msg.parms[0].length == 0)
14054 {
14055 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14056 ADJUST_B_MODE_NO_RESOURCE;
14057 }
14058 else
14059 {
14060 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14062 }
14063 plci->adjust_b_state = ADJUST_B_START;
14064 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14065 UnMapId (Id), (char *)(FILE_), __LINE__));
14066 case SELECT_B_COMMAND_1:
14067 Info = adjust_b_process (Id, plci, Rc);
14068 if (Info != GOOD)
14069 {
14070 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14071 UnMapId (Id), (char *)(FILE_), __LINE__));
14072 break;
14073 }
14074 if (plci->internal_command)
14075 return;
14076 if (plci->tel == ADV_VOICE)
14077 {
14078 esc_chi[0] = 0x02;
14079 esc_chi[1] = 0x18;
14080 esc_chi[2] = plci->b_channel;
14081 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14082 }
14083 break;
14084 }
14085 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14086}
14087
14088
14089static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14090{
14091 word Info;
14092 word internal_command;
14093
14094 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14095 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14096
14097 Info = GOOD;
14098 internal_command = plci->internal_command;
14099 plci->internal_command = 0;
14100 switch (internal_command)
14101 {
14102 default:
14103 plci->command = 0;
14104 case FAX_CONNECT_ACK_COMMAND_1:
14105 if (plci_nl_busy (plci))
14106 {
14107 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14108 return;
14109 }
14110 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14111 plci->NData[0].P = plci->fax_connect_info_buffer;
14112 plci->NData[0].PLength = plci->fax_connect_info_length;
14113 plci->NL.X = plci->NData;
14114 plci->NL.ReqCh = 0;
14115 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14116 plci->adapter->request (&plci->NL);
14117 return;
14118 case FAX_CONNECT_ACK_COMMAND_2:
14119 if ((Rc != OK) && (Rc != OK_FC))
14120 {
14121 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14122 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14123 break;
14124 }
14125 }
14126 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14127 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14128 {
14129 if (plci->B3_prot == 4)
14130 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14131 else
14132 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14133 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14134 }
14135}
14136
14137
14138static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14139{
14140 word Info;
14141 word internal_command;
14142
14143 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14144 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14145
14146 Info = GOOD;
14147 internal_command = plci->internal_command;
14148 plci->internal_command = 0;
14149 switch (internal_command)
14150 {
14151 default:
14152 plci->command = 0;
14153 case FAX_EDATA_ACK_COMMAND_1:
14154 if (plci_nl_busy (plci))
14155 {
14156 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14157 return;
14158 }
14159 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14160 plci->NData[0].P = plci->fax_connect_info_buffer;
14161 plci->NData[0].PLength = plci->fax_edata_ack_length;
14162 plci->NL.X = plci->NData;
14163 plci->NL.ReqCh = 0;
14164 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14165 plci->adapter->request (&plci->NL);
14166 return;
14167 case FAX_EDATA_ACK_COMMAND_2:
14168 if ((Rc != OK) && (Rc != OK_FC))
14169 {
14170 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14171 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14172 break;
14173 }
14174 }
14175}
14176
14177
14178static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14179{
14180 word Info;
14181 word internal_command;
14182
14183 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14184 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14185
14186 Info = GOOD;
14187 internal_command = plci->internal_command;
14188 plci->internal_command = 0;
14189 switch (internal_command)
14190 {
14191 default:
14192 plci->command = 0;
14193 case FAX_CONNECT_INFO_COMMAND_1:
14194 if (plci_nl_busy (plci))
14195 {
14196 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14197 return;
14198 }
14199 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14200 plci->NData[0].P = plci->fax_connect_info_buffer;
14201 plci->NData[0].PLength = plci->fax_connect_info_length;
14202 plci->NL.X = plci->NData;
14203 plci->NL.ReqCh = 0;
14204 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14205 plci->adapter->request (&plci->NL);
14206 return;
14207 case FAX_CONNECT_INFO_COMMAND_2:
14208 if ((Rc != OK) && (Rc != OK_FC))
14209 {
14210 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14211 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14212 Info = _WRONG_STATE;
14213 break;
14214 }
14215 if (plci_nl_busy (plci))
14216 {
14217 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14218 return;
14219 }
14220 plci->command = _CONNECT_B3_R;
14221 nl_req_ncci (plci, N_CONNECT, 0);
14222 send_req (plci);
14223 return;
14224 }
14225 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14226}
14227
14228
14229static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14230{
14231 word Info;
14232 word internal_command;
14233
14234 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14235 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14236
14237 Info = GOOD;
14238 internal_command = plci->internal_command;
14239 plci->internal_command = 0;
14240 switch (internal_command)
14241 {
14242 default:
14243 plci->command = 0;
14244 plci->adjust_b_parms_msg = NULL;
14245 plci->adjust_b_facilities = plci->B1_facilities;
14246 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14247 plci->adjust_b_ncci = (word)(Id >> 16);
14248 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14249 plci->adjust_b_state = ADJUST_B_START;
14250 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14251 UnMapId (Id), (char *)(FILE_), __LINE__));
14252 case FAX_ADJUST_B23_COMMAND_1:
14253 Info = adjust_b_process (Id, plci, Rc);
14254 if (Info != GOOD)
14255 {
14256 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14257 UnMapId (Id), (char *)(FILE_), __LINE__));
14258 break;
14259 }
14260 if (plci->internal_command)
14261 return;
14262 case FAX_ADJUST_B23_COMMAND_2:
14263 if (plci_nl_busy (plci))
14264 {
14265 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14266 return;
14267 }
14268 plci->command = _CONNECT_B3_R;
14269 nl_req_ncci (plci, N_CONNECT, 0);
14270 send_req (plci);
14271 return;
14272 }
14273 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14274}
14275
14276
14277static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14278{
14279 word internal_command;
14280
14281 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14282 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14283
14284 internal_command = plci->internal_command;
14285 plci->internal_command = 0;
14286 switch (internal_command)
14287 {
14288 default:
14289 plci->command = 0;
14290 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14291 return;
14292 case FAX_DISCONNECT_COMMAND_1:
14293 case FAX_DISCONNECT_COMMAND_2:
14294 case FAX_DISCONNECT_COMMAND_3:
14295 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14296 {
14297 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14298 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14299 break;
14300 }
14301 if (Rc == OK)
14302 {
14303 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14304 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14305 {
14306 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14307 }
14308 }
14309 else if (Rc == 0)
14310 {
14311 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14312 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14313 }
14314 return;
14315 }
14316}
14317
14318
14319
14320static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14321{
14322 word Info;
14323 word internal_command;
14324
14325 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14326 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14327
14328 Info = GOOD;
14329 internal_command = plci->internal_command;
14330 plci->internal_command = 0;
14331 switch (internal_command)
14332 {
14333 default:
14334 plci->command = 0;
14335 case RTP_CONNECT_B3_REQ_COMMAND_1:
14336 if (plci_nl_busy (plci))
14337 {
14338 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14339 return;
14340 }
14341 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14342 nl_req_ncci (plci, N_CONNECT, 0);
14343 send_req (plci);
14344 return;
14345 case RTP_CONNECT_B3_REQ_COMMAND_2:
14346 if ((Rc != OK) && (Rc != OK_FC))
14347 {
14348 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14349 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14350 Info = _WRONG_STATE;
14351 break;
14352 }
14353 if (plci_nl_busy (plci))
14354 {
14355 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14356 return;
14357 }
14358 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14359 plci->NData[0].PLength = plci->internal_req_buffer[0];
14360 plci->NData[0].P = plci->internal_req_buffer + 1;
14361 plci->NL.X = plci->NData;
14362 plci->NL.ReqCh = 0;
14363 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14364 plci->adapter->request (&plci->NL);
14365 break;
14366 case RTP_CONNECT_B3_REQ_COMMAND_3:
14367 return;
14368 }
14369 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14370}
14371
14372
14373static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14374{
14375 word Info;
14376 word internal_command;
14377
14378 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14379 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14380
14381 Info = GOOD;
14382 internal_command = plci->internal_command;
14383 plci->internal_command = 0;
14384 switch (internal_command)
14385 {
14386 default:
14387 plci->command = 0;
14388 case RTP_CONNECT_B3_RES_COMMAND_1:
14389 if (plci_nl_busy (plci))
14390 {
14391 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14392 return;
14393 }
14394 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14395 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14396 send_req (plci);
14397 return;
14398 case RTP_CONNECT_B3_RES_COMMAND_2:
14399 if ((Rc != OK) && (Rc != OK_FC))
14400 {
14401 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14402 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14403 Info = _WRONG_STATE;
14404 break;
14405 }
14406 if (plci_nl_busy (plci))
14407 {
14408 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14409 return;
14410 }
14411 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14412 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14413 plci->NData[0].PLength = plci->internal_req_buffer[0];
14414 plci->NData[0].P = plci->internal_req_buffer + 1;
14415 plci->NL.X = plci->NData;
14416 plci->NL.ReqCh = 0;
14417 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14418 plci->adapter->request (&plci->NL);
14419 return;
14420 case RTP_CONNECT_B3_RES_COMMAND_3:
14421 return;
14422 }
14423}
14424
14425
14426
14427static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14428{
14429 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14430 word Info;
14431 word internal_command;
14432
14433 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14434 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14435
14436 Info = GOOD;
14437 internal_command = plci->internal_command;
14438 plci->internal_command = 0;
14439 switch (internal_command)
14440 {
14441 default:
14442 if (!plci->NL.Id)
14443 break;
14444 plci->command = 0;
14445 plci->adjust_b_parms_msg = NULL;
14446 plci->adjust_b_facilities = plci->B1_facilities;
14447 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14448 plci->adjust_b_ncci = (word)(Id >> 16);
14449 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14450 plci->adjust_b_state = ADJUST_B_START;
14451 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14452 UnMapId (Id), (char *)(FILE_), __LINE__));
14453 case HOLD_SAVE_COMMAND_1:
14454 Info = adjust_b_process (Id, plci, Rc);
14455 if (Info != GOOD)
14456 {
14457 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14458 UnMapId (Id), (char *)(FILE_), __LINE__));
14459 break;
14460 }
14461 if (plci->internal_command)
14462 return;
14463 }
14464 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14465}
14466
14467
14468static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14469{
14470 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14471 word Info;
14472 word internal_command;
14473
14474 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14475 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14476
14477 Info = GOOD;
14478 internal_command = plci->internal_command;
14479 plci->internal_command = 0;
14480 switch (internal_command)
14481 {
14482 default:
14483 plci->command = 0;
14484 plci->adjust_b_parms_msg = NULL;
14485 plci->adjust_b_facilities = plci->B1_facilities;
14486 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14487 plci->adjust_b_ncci = (word)(Id >> 16);
14488 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14489 plci->adjust_b_state = ADJUST_B_START;
14490 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14491 UnMapId (Id), (char *)(FILE_), __LINE__));
14492 case RETRIEVE_RESTORE_COMMAND_1:
14493 Info = adjust_b_process (Id, plci, Rc);
14494 if (Info != GOOD)
14495 {
14496 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14497 UnMapId (Id), (char *)(FILE_), __LINE__));
14498 break;
14499 }
14500 if (plci->internal_command)
14501 return;
14502 }
14503 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14504}
14505
14506
14507static void init_b1_config (PLCI *plci)
14508{
14509
14510 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14511 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14512 (char *)(FILE_), __LINE__));
14513
14514 plci->B1_resource = 0;
14515 plci->B1_facilities = 0;
14516
14517 plci->li_bchannel_id = 0;
14518 mixer_clear_config (plci);
14519
14520
14521 ec_clear_config (plci);
14522
14523
14524 dtmf_rec_clear_config (plci);
14525 dtmf_send_clear_config (plci);
14526 dtmf_parameter_clear_config (plci);
14527
14528 adv_voice_clear_config (plci);
14529 adjust_b_clear (plci);
14530}
14531
14532
14533static void clear_b1_config (PLCI *plci)
14534{
14535
14536 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14537 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14538 (char *)(FILE_), __LINE__));
14539
14540 adv_voice_clear_config (plci);
14541 adjust_b_clear (plci);
14542
14543 ec_clear_config (plci);
14544
14545
14546 dtmf_rec_clear_config (plci);
14547 dtmf_send_clear_config (plci);
14548 dtmf_parameter_clear_config (plci);
14549
14550
14551 if ((plci->li_bchannel_id != 0)
14552 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14553 {
14554 mixer_clear_config (plci);
14555 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14556 plci->li_bchannel_id = 0;
14557 }
14558
14559 plci->B1_resource = 0;
14560 plci->B1_facilities = 0;
14561}
14562
14563
14564/* -----------------------------------------------------------------
14565 XON protocol local helpers
14566 ----------------------------------------------------------------- */
14567static void channel_flow_control_remove (PLCI * plci) {
14568 DIVA_CAPI_ADAPTER * a = plci->adapter;
14569 word i;
14570 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14571 if (a->ch_flow_plci[i] == plci->Id) {
14572 a->ch_flow_plci[i] = 0;
14573 a->ch_flow_control[i] = 0;
14574 }
14575 }
14576}
14577
14578static void channel_x_on (PLCI * plci, byte ch) {
14579 DIVA_CAPI_ADAPTER * a = plci->adapter;
14580 if (a->ch_flow_control[ch] & N_XON_SENT) {
14581 a->ch_flow_control[ch] &= ~N_XON_SENT;
14582 }
14583}
14584
14585static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14586 DIVA_CAPI_ADAPTER * a = plci->adapter;
14587 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14588 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14589 a->ch_flow_plci[ch] = plci->Id;
14590 a->ch_flow_control_pending++;
14591 }
14592}
14593
14594static void channel_request_xon (PLCI * plci, byte ch) {
14595 DIVA_CAPI_ADAPTER * a = plci->adapter;
14596
14597 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14598 a->ch_flow_control[ch] |= N_XON_REQ;
14599 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14600 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14601 }
14602}
14603
14604static void channel_xmit_extended_xon (PLCI * plci) {
14605 DIVA_CAPI_ADAPTER * a;
14606 int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14607 int i, one_requested = 0;
14608
14609 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14610 return;
14611 }
14612
14613 for (i = 0; i < max_ch; i++) {
14614 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14615 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14616 (plci->Id == a->ch_flow_plci[i])) {
14617 channel_request_xon (plci, (byte)i);
14618 one_requested = 1;
14619 }
14620 }
14621
14622 if (one_requested) {
14623 channel_xmit_xon (plci);
14624 }
14625}
14626
14627/*
14628 Try to xmit next X_ON
14629 */
14630static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14631 int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14632 int i;
14633
14634 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14635 return (0);
14636 }
14637
14638 if (a->last_flow_control_ch >= max_ch) {
14639 a->last_flow_control_ch = 1;
14640 }
14641 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14642 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14643 (plci->Id == a->ch_flow_plci[i])) {
14644 a->last_flow_control_ch = i+1;
14645 return (i);
14646 }
14647 }
14648
14649 for (i = 1; i < a->last_flow_control_ch; i++) {
14650 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14651 (plci->Id == a->ch_flow_plci[i])) {
14652 a->last_flow_control_ch = i+1;
14653 return (i);
14654 }
14655 }
14656
14657 return (0);
14658}
14659
14660static void channel_xmit_xon (PLCI * plci) {
14661 DIVA_CAPI_ADAPTER * a = plci->adapter;
14662 byte ch;
14663
14664 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14665 return;
14666 }
14667 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14668 return;
14669 }
14670 a->ch_flow_control[ch] &= ~N_XON_REQ;
14671 a->ch_flow_control[ch] |= N_XON_SENT;
14672
14673 plci->NL.Req = plci->nl_req = (byte)N_XON;
14674 plci->NL.ReqCh = ch;
14675 plci->NL.X = plci->NData;
14676 plci->NL.XNum = 1;
14677 plci->NData[0].P = &plci->RBuffer[0];
14678 plci->NData[0].PLength = 0;
14679
14680 plci->adapter->request(&plci->NL);
14681}
14682
14683static int channel_can_xon (PLCI * plci, byte ch) {
14684 APPL * APPLptr;
14685 DIVA_CAPI_ADAPTER * a;
14686 word NCCIcode;
14687 dword count;
14688 word Num;
14689 word i;
14690
14691 APPLptr = plci->appl;
14692 a = plci->adapter;
14693
14694 if (!APPLptr)
14695 return (0);
14696
14697 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14698
14699 /* count all buffers within the Application pool */
14700 /* belonging to the same NCCI. XON if a first is */
14701 /* used. */
14702 count = 0;
14703 Num = 0xffff;
14704 for(i=0; i<APPLptr->MaxBuffer; i++) {
14705 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14706 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14707 }
14708 if ((count > 2) || (Num == 0xffff)) {
14709 return (0);
14710 }
14711 return (1);
14712}
14713
14714
14715/*------------------------------------------------------------------*/
14716
14717static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14718{
14719 return 1;
14720}
14721
14722
14723
14724/**********************************************************************************/
14725/* function groups the listening applications according to the CIP mask and the */
14726/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14727/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14728/* big problems on application level (one call, 30 Connect_Ind, ect). The */
14729/* function must be enabled by setting "a->group_optimization_enabled" from the */
14730/* OS specific part (per adapter). */
14731/**********************************************************************************/
14732static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14733{
14734 word i,j,k,busy,group_found;
14735 dword info_mask_group[MAX_CIP_TYPES];
14736 dword cip_mask_group[MAX_CIP_TYPES];
14737 word appl_number_group_type[MAX_APPL];
14738 PLCI *auxplci;
14739
14740 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14741
14742 if(!a->group_optimization_enabled)
14743 {
14744 dbug(1,dprintf("No group optimization"));
14745 return;
14746 }
14747
14748 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14749
14750 for(i=0;i<MAX_CIP_TYPES;i++)
14751 {
14752 info_mask_group[i] = 0;
14753 cip_mask_group [i] = 0;
14754 }
14755 for(i=0;i<MAX_APPL;i++)
14756 {
14757 appl_number_group_type[i] = 0;
14758 }
14759 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14760 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14761 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14762 {
14763 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14764 return; /* allow good application unfiltered access */
14765 }
14766 }
14767 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14768 {
14769 if(application[i].Id && a->CIP_Mask[i] )
14770 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014771 for(k=0,busy=false; k<a->max_plci; k++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014772 {
14773 if(a->plci[k].Id)
14774 {
14775 auxplci = &a->plci[k];
14776 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14777 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014778 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014779 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14780 }
14781 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14782 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014783 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014784 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14785 }
14786 }
14787 }
14788
14789 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14790 {
14791 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14792 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14793 appl_number_group_type[i] = MAX_CIP_TYPES;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014794 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014795 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14796 }
14797 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14798 { /* is group already present ? */
14799 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014800 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014801 dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14802 }
14803 else if(!info_mask_group[j])
14804 { /* establish a new group */
14805 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14806 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14807 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014808 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014809 dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14810 }
14811 }
14812 }
14813 }
14814
14815 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14816 {
14817 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14818 {
14819 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14820 {
14821 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14822 }
14823 else
14824 {
14825 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14826 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14827 {
14828 if(appl_number_group_type[i] == appl_number_group_type[j])
14829 {
14830 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14831 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14832 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14833 }
14834 }
14835 }
14836 }
14837 else /* application should not get a call */
14838 {
14839 clear_group_ind_mask_bit (plci, i);
14840 }
14841 }
14842
14843}
14844
14845
14846
14847/* OS notifies the driver about a application Capi_Register */
14848word CapiRegister(word id)
14849{
14850 word i,j,appls_found;
14851
14852 PLCI *plci;
14853 DIVA_CAPI_ADAPTER *a;
14854
14855 for(i=0,appls_found=0; i<max_appl; i++)
14856 {
14857 if( application[i].Id && (application[i].Id!=id) )
14858 {
14859 appls_found++; /* an application has been found */
14860 }
14861 }
14862
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014863 if(appls_found) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014864 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14865 {
14866 a = &adapter[i];
14867 if(a->request)
14868 {
14869 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14870 {
14871 if(!appls_found) /* first application does a capi register */
14872 {
14873 if((j=get_plci(a))) /* activate L1 of all adapters */
14874 {
14875 plci = &a->plci[j-1];
14876 plci->command = 0;
14877 add_p(plci,OAD,"\x01\xfd");
14878 add_p(plci,CAI,"\x01\x80");
14879 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14880 add_p(plci,SHIFT|6,NULL);
14881 add_p(plci,SIN,"\x02\x00\x00");
14882 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14883 sig_req(plci,ASSIGN,DSIG_ID);
14884 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14885 sig_req(plci,SIG_CTRL,0);
14886 send_req(plci);
14887 }
14888 }
14889 }
14890 }
14891 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014892 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014893}
14894
14895/*------------------------------------------------------------------*/
14896
14897/* Functions for virtual Switching e.g. Transfer by join, Conference */
14898
14899static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14900{
14901 word i;
14902 /* Format of vswitch_t:
14903 0 byte length
14904 1 byte VSWITCHIE
14905 2 byte VSWITCH_REQ/VSWITCH_IND
14906 3 byte reserved
14907 4 word VSwitchcommand
14908 6 word returnerror
14909 8... Params
14910 */
14911 if(!plci ||
14912 !plci->appl ||
14913 !plci->State ||
14914 plci->Sig.Ind==NCR_FACILITY
14915 )
14916 return;
14917
14918 for(i=0;i<MAX_MULTI_IE;i++)
14919 {
14920 if(!parms[i][0]) continue;
14921 if(parms[i][0]<7)
14922 {
14923 parms[i][0]=0; /* kill it */
14924 continue;
14925 }
14926 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14927 switch(parms[i][4])
14928 {
14929 case VSJOIN:
14930 if(!plci->relatedPTYPLCI ||
14931 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14932 { /* Error */
14933 break;
14934 }
14935 /* remember all necessary informations */
14936 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14937 {
14938 break;
14939 }
14940 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14941 { /* first indication after ECT-Request on Consultation Call */
14942 plci->vswitchstate=parms[i][9];
14943 parms[i][9]=2; /* State */
14944 /* now ask first Call to join */
14945 }
14946 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14947 { /* Answer of VSWITCH_REQ from first Call */
14948 plci->vswitchstate=parms[i][9];
14949 /* tell consultation call to join
14950 and the protocol capabilities of the first call */
14951 }
14952 else
14953 { /* Error */
14954 break;
14955 }
14956 plci->vsprot=parms[i][10]; /* protocol */
14957 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14958 /* send join request to related PLCI */
14959 parms[i][1]=VSWITCHIE;
14960 parms[i][2]=VSWITCH_REQ;
14961
14962 plci->relatedPTYPLCI->command = 0;
14963 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14964 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14965 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14966 send_req(plci->relatedPTYPLCI);
14967 break;
14968 case VSTRANSPORT:
14969 default:
14970 if(plci->relatedPTYPLCI &&
14971 plci->vswitchstate==3 &&
14972 plci->relatedPTYPLCI->vswitchstate==3)
14973 {
14974 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14975 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14976 send_req(plci->relatedPTYPLCI);
14977 }
14978 break;
14979 }
14980 parms[i][0]=0; /* kill it */
14981 }
14982}
14983
14984
14985/*------------------------------------------------------------------*/
14986
14987static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14988 ENTITY e;
14989 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14990
14991 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14992 return (-1);
14993 }
14994
14995 pReq->xdi_dma_descriptor_operation.Req = 0;
14996 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14997
14998 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14999 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15000 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15001 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15002
15003 e.user[0] = plci->adapter->Id - 1;
15004 plci->adapter->request((ENTITY*)pReq);
15005
15006 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15007 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15008 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15009 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15010 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15011 plci->adapter->Id,
15012 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15013 *dma_magic));
15014 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15015 } else {
15016 dbug(1,dprintf("dma_alloc failed"));
15017 return (-1);
15018 }
15019}
15020
15021static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15022 ENTITY e;
15023 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15024
15025 if (nr < 0) {
15026 return;
15027 }
15028
15029 pReq->xdi_dma_descriptor_operation.Req = 0;
15030 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15031
15032 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15033 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15034 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15035 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15036
15037 e.user[0] = plci->adapter->Id - 1;
15038 plci->adapter->request((ENTITY*)pReq);
15039
15040 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15041 dbug(1,dprintf("dma_free(%d)", nr));
15042 } else {
15043 dbug(1,dprintf("dma_free failed (%d)", nr));
15044 }
15045}
15046
15047/*------------------------------------------------------------------*/