blob: ccd35d047ec8c314dc337e827ca3ad58b45ae767 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 *
3 Copyright (c) Eicon Networks, 2002.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision : 2.1
9 *
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 *
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
19 *
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26
27
28
29
30#include "platform.h"
31#include "di_defs.h"
32#include "pc.h"
33#include "capi20.h"
34#include "divacapi.h"
35#include "mdm_msg.h"
36#include "divasync.h"
37
38
39
40#define FILE_ "MESSAGE.C"
41#define dprintf
42
43
44
45
46
47
48
49
50
51/*------------------------------------------------------------------*/
52/* This is options supported for all adapters that are server by */
53/* XDI driver. Allo it is not necessary to ask it from every adapter*/
54/* and it is not necessary to save it separate for every adapter */
55/* Macrose defined here have only local meaning */
56/*------------------------------------------------------------------*/
57static dword diva_xdi_extended_features = 0;
58
59#define DIVA_CAPI_USE_CMA 0x00000001
60#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
61#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
62#define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
63
64/*
65 CAPI can request to process all return codes self only if:
66 protocol code supports this && xdi supports this
67 */
68#define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&& ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70/*------------------------------------------------------------------*/
71/* local function prototypes */
72/*------------------------------------------------------------------*/
73
74static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci);
75static void set_group_ind_mask (PLCI *plci);
76static void clear_group_ind_mask_bit (PLCI *plci, word b);
77static byte test_group_ind_mask_bit (PLCI *plci, word b);
78void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79word CapiRelease(word);
80word CapiRegister(word);
81word api_put(APPL *, CAPI_MSG *);
82static word api_parse(byte *, word, byte *, API_PARSE *);
83static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84static void api_load_msg(API_SAVE *in, API_PARSE *out);
85
86word api_remove_start(void);
87void api_remove_complete(void);
88
89static void plci_remove(PLCI *);
90static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a);
91static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
92
93void callback(ENTITY *);
94
95static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96static void data_rc(PLCI *, byte);
97static void data_ack(PLCI *, byte);
98static void sig_ind(PLCI *);
99static void SendInfo(PLCI *, dword, byte * *, byte);
100static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte);
101static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms);
102
103static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
104
105static void nl_ind(PLCI *);
106
107static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131
132static word get_plci(DIVA_CAPI_ADAPTER *);
133static void add_p(PLCI *, byte, byte *);
134static void add_s(PLCI * plci, byte code, API_PARSE * p);
135static void add_ss(PLCI * plci, byte code, API_PARSE * p);
136static void add_ie(PLCI * plci, byte code, byte * p, word p_length);
137static void add_d(PLCI *, word, byte *);
138static void add_ai(PLCI *, API_PARSE *);
139static word add_b1(PLCI *, API_PARSE *, word, word);
140static word add_b23(PLCI *, API_PARSE *);
141static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms);
142static void sig_req(PLCI *, byte, byte);
143static void nl_req_ncci(PLCI *, byte, byte);
144static void send_req(PLCI *);
145static void send_data(PLCI *);
146static word plci_remove_check(PLCI *);
147static void listen_check(DIVA_CAPI_ADAPTER *);
148static byte AddInfo(byte **, byte **, byte *, byte *);
149static byte getChannel(API_PARSE *);
150static void IndParse(PLCI *, word *, byte **, byte);
151static byte ie_compare(byte *, byte *);
152static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word);
154
155/*
156 XON protocol helpers
157 */
158static void channel_flow_control_remove (PLCI * plci);
159static void channel_x_off (PLCI * plci, byte ch, byte flag);
160static void channel_x_on (PLCI * plci, byte ch);
161static void channel_request_xon (PLCI * plci, byte ch);
162static void channel_xmit_xon (PLCI * plci);
163static int channel_can_xon (PLCI * plci, byte ch);
164static void channel_xmit_extended_xon (PLCI * plci);
165
166static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse);
167static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * );
170static void VoiceChannelOff(PLCI *plci);
171static void adv_voice_write_coefs (PLCI *plci, word write_command);
172static void adv_voice_clear_config (PLCI *plci);
173
174static word get_b1_facilities (PLCI * plci, byte b1_resource);
175static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities);
176static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177static word adjust_b_process (dword Id, PLCI *plci, byte Rc);
178static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179static void adjust_b_restore (dword Id, PLCI *plci, byte Rc);
180static void reset_b3_command (dword Id, PLCI *plci, byte Rc);
181static void select_b_command (dword Id, PLCI *plci, byte Rc);
182static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc);
183static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc);
184static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc);
185static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc);
186static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc);
187static void hold_save_command (dword Id, PLCI *plci, byte Rc);
188static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc);
189static void init_b1_config (PLCI *plci);
190static void clear_b1_config (PLCI *plci);
191
192static void dtmf_command (dword Id, PLCI *plci, byte Rc);
193static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194static void dtmf_confirmation (dword Id, PLCI *plci);
195static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length);
196static void dtmf_parameter_write (PLCI *plci);
197
198
199static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id);
200static void mixer_set_bchannel_id (PLCI *plci, byte *chi);
201static void mixer_clear_config (PLCI *plci);
202static void mixer_notify_update (PLCI *plci, byte others);
203static void mixer_command (dword Id, PLCI *plci, byte Rc);
204static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205static void mixer_indication_coefs_set (dword Id, PLCI *plci);
206static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length);
207static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length);
208static void mixer_remove (PLCI *plci);
209
210
211static void ec_command (dword Id, PLCI *plci, byte Rc);
212static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213static void ec_indication (dword Id, PLCI *plci, byte *msg, word length);
214
215
216static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc);
217static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc);
218
219
220static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
221static void diva_free_dma_descriptor (PLCI *plci, int nr);
222
223/*------------------------------------------------------------------*/
224/* external function prototypes */
225/*------------------------------------------------------------------*/
226
227extern byte MapController (byte);
228extern byte UnMapController (byte);
229#define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230#define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232void sendf(APPL *, word, dword, word, byte *, ...);
233void * TransmitBufferSet(APPL * appl, dword ref);
234void * TransmitBufferGet(APPL * appl, void * p);
235void TransmitBufferFree(APPL * appl, void * p);
236void * ReceiveBufferGet(APPL * appl, int Num);
237
238int fax_head_line_time (char *buffer);
239
240
241/*------------------------------------------------------------------*/
242/* Global data definitions */
243/*------------------------------------------------------------------*/
244extern byte max_adapter;
245extern byte max_appl;
246extern DIVA_CAPI_ADAPTER * adapter;
247extern APPL * application;
248
249
250
251
252
253
254
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800255static byte remove_started = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256static PLCI dummy_plci;
257
258
259static struct _ftable {
260 word command;
261 byte * format;
262 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263} ftable[] = {
264 {_DATA_B3_R, "dwww", data_b3_req},
265 {_DATA_B3_I|RESPONSE, "w", data_b3_res},
266 {_INFO_R, "ss", info_req},
267 {_INFO_I|RESPONSE, "", info_res},
268 {_CONNECT_R, "wsssssssss", connect_req},
269 {_CONNECT_I|RESPONSE, "wsssss", connect_res},
270 {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res},
271 {_DISCONNECT_R, "s", disconnect_req},
272 {_DISCONNECT_I|RESPONSE, "", disconnect_res},
273 {_LISTEN_R, "dddss", listen_req},
274 {_ALERT_R, "s", alert_req},
275 {_FACILITY_R, "ws", facility_req},
276 {_FACILITY_I|RESPONSE, "ws", facility_res},
277 {_CONNECT_B3_R, "s", connect_b3_req},
278 {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res},
279 {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res},
280 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
281 {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res},
282 {_RESET_B3_R, "s", reset_b3_req},
283 {_RESET_B3_I|RESPONSE, "", reset_b3_res},
284 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res},
285 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res},
286 {_SELECT_B_REQ, "s", select_b_req},
287 {_MANUFACTURER_R, "dws", manufacturer_req},
288 {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res},
289 {_MANUFACTURER_I|RESPONSE, "", manufacturer_res}
290};
291
292static byte * cip_bc[29][2] = {
293 { "", "" }, /* 0 */
294 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
295 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
296 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
297 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
298 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
299 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
300 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
303 { "", "" }, /* 10 */
304 { "", "" }, /* 11 */
305 { "", "" }, /* 12 */
306 { "", "" }, /* 13 */
307 { "", "" }, /* 14 */
308 { "", "" }, /* 15 */
309
310 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
311 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
312 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
320 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
322 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
323};
324
325static byte * cip_hlc[29] = {
326 "", /* 0 */
327 "", /* 1 */
328 "", /* 2 */
329 "", /* 3 */
330 "", /* 4 */
331 "", /* 5 */
332 "", /* 6 */
333 "", /* 7 */
334 "", /* 8 */
335 "", /* 9 */
336 "", /* 10 */
337 "", /* 11 */
338 "", /* 12 */
339 "", /* 13 */
340 "", /* 14 */
341 "", /* 15 */
342
343 "\x02\x91\x81", /* 16 */
344 "\x02\x91\x84", /* 17 */
345 "\x02\x91\xa1", /* 18 */
346 "\x02\x91\xa4", /* 19 */
347 "\x02\x91\xa8", /* 20 */
348 "\x02\x91\xb1", /* 21 */
349 "\x02\x91\xb2", /* 22 */
350 "\x02\x91\xb5", /* 23 */
351 "\x02\x91\xb8", /* 24 */
352 "\x02\x91\xc1", /* 25 */
353 "\x02\x91\x81", /* 26 */
354 "\x03\x91\xe0\x01", /* 27 */
355 "\x03\x91\xe0\x02" /* 28 */
356};
357
358/*------------------------------------------------------------------*/
359
360#define V120_HEADER_LENGTH 1
361#define V120_HEADER_EXTEND_BIT 0x80
362#define V120_HEADER_BREAK_BIT 0x40
363#define V120_HEADER_C1_BIT 0x04
364#define V120_HEADER_C2_BIT 0x08
365#define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367static byte v120_default_header[] =
368{
369
370 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
371
372};
373
374static byte v120_break_header[] =
375{
376
377 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
378
379};
380
381
382/*------------------------------------------------------------------*/
383/* API_PUT function */
384/*------------------------------------------------------------------*/
385
386word api_put(APPL * appl, CAPI_MSG * msg)
387{
388 word i, j, k, l, n;
389 word ret;
390 byte c;
391 byte controller;
392 DIVA_CAPI_ADAPTER * a;
393 PLCI * plci;
394 NCCI * ncci_ptr;
395 word ncci;
396 CAPI_MSG *m;
397 API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399 if (msg->header.length < sizeof (msg->header) ||
400 msg->header.length > MAX_MSG_SIZE) {
401 dbug(1,dprintf("bad len"));
402 return _BAD_MSG;
403 }
404
405 controller = (byte)((msg->header.controller &0x7f)-1);
406
407 /* controller starts with 0 up to (max_adapter - 1) */
408 if ( controller >= max_adapter )
409 {
410 dbug(1,dprintf("invalid ctrl"));
411 return _BAD_MSG;
412 }
413
414 a = &adapter[controller];
415 plci = NULL;
416 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417 {
418 dbug(1,dprintf("plci=%x",msg->header.plci));
419 plci = &a->plci[msg->header.plci-1];
420 ncci = GET_WORD(&msg->header.ncci);
421 if (plci->Id
422 && (plci->appl
423 || (plci->State == INC_CON_PENDING)
424 || (plci->State == INC_CON_ALERT)
425 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426 && ((ncci == 0)
427 || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428 || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429 {
430 i = plci->msg_in_read_pos;
431 j = plci->msg_in_write_pos;
432 if (j >= i)
433 {
434 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435 i += MSG_IN_QUEUE_SIZE - j;
436 else
437 j = 0;
438 }
439 else
440 {
441
442 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444 if (i > MSG_IN_QUEUE_SIZE - n)
445 i = MSG_IN_QUEUE_SIZE - n + 1;
446 i -= j;
447 }
448
449 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451 {
452 dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453 msg->header.length, plci->msg_in_write_pos,
454 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456 return _QUEUE_FULL;
457 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800458 c = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461 {
462 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800463 c = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 }
465 if (msg->header.command == _DATA_B3_R)
466 {
467 if (msg->header.length < 20)
468 {
469 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470 return _BAD_MSG;
471 }
472 ncci_ptr = &(a->ncci[ncci]);
473 n = ncci_ptr->data_pending;
474 l = ncci_ptr->data_ack_pending;
475 k = plci->msg_in_read_pos;
476 while (k != plci->msg_in_write_pos)
477 {
478 if (k == plci->msg_in_wrap_pos)
479 k = 0;
480 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482 {
483 n++;
484 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485 l++;
486 }
487
488 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489 MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491 }
492 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493 {
494 dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497 return _QUEUE_FULL;
498 }
499 if (plci->req_in || plci->internal_command)
500 {
501 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503 {
504 dbug(0,dprintf("Q-FULL3(requeue)"));
505
506 return _QUEUE_FULL;
507 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800508 c = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
510 }
511 else
512 {
513 if (plci->req_in || plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800514 c = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 else
516 {
517 plci->command = msg->header.command;
518 plci->number = msg->header.number;
519 }
520 }
521 if (c)
522 {
523 dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524 msg->header.command, plci->req_in, plci->internal_command,
525 msg->header.length, plci->msg_in_write_pos,
526 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527 if (j == 0)
528 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530 for (i = 0; i < msg->header.length; i++)
531 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532 if (m->header.command == _DATA_B3_R)
533 {
534
Andrew Mortond3c8bdf2007-05-23 13:58:22 -0700535 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 }
538
539 j = (j + 3) & 0xfffc;
540
541 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543 return 0;
544 }
545 }
546 else
547 {
548 plci = NULL;
549 }
550 }
551 dbug(1,dprintf("com=%x",msg->header.command));
552
553 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554 for(i=0, ret = _BAD_MSG;
555 i<(sizeof(ftable)/sizeof(struct _ftable));
556 i++) {
557
558 if(ftable[i].command==msg->header.command) {
559 /* break loop if the message is correct, otherwise continue scan */
560 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
561 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
562 ret = 0;
563 break;
564 }
565 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
566 }
567 }
568 if(ret) {
569 dbug(1,dprintf("BAD_MSG"));
570 if(plci) plci->command = 0;
571 return ret;
572 }
573
574
575 c = ftable[i].function(GET_DWORD(&msg->header.controller),
576 msg->header.number,
577 a,
578 plci,
579 appl,
580 msg_parms);
581
582 channel_xmit_extended_xon (plci);
583
584 if(c==1) send_req(plci);
585 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586 if(plci && !plci->req_in) plci->command = 0;
587 return 0;
588}
589
590
591/*------------------------------------------------------------------*/
592/* api_parse function, check the format of api messages */
593/*------------------------------------------------------------------*/
594
595word api_parse(byte * msg, word length, byte * format, API_PARSE * parms)
596{
597 word i;
598 word p;
599
600 for(i=0,p=0; format[i]; i++) {
601 if(parms)
602 {
603 parms[i].info = &msg[p];
604 }
605 switch(format[i]) {
606 case 'b':
607 p +=1;
608 break;
609 case 'w':
610 p +=2;
611 break;
612 case 'd':
613 p +=4;
614 break;
615 case 's':
616 if(msg[p]==0xff) {
617 parms[i].info +=2;
618 parms[i].length = msg[p+1] + (msg[p+2]<<8);
619 p +=(parms[i].length +3);
620 }
621 else {
622 parms[i].length = msg[p];
623 p +=(parms[i].length +1);
624 }
625 break;
626 }
627
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800628 if(p>length) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 }
630 if(parms) parms[i].info = NULL;
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800631 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632}
633
634void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
635{
636 word i, j, n = 0;
637 byte *p;
638
639 p = out->info;
640 for (i = 0; format[i] != '\0'; i++)
641 {
642 out->parms[i].info = p;
643 out->parms[i].length = in[i].length;
644 switch (format[i])
645 {
646 case 'b':
647 n = 1;
648 break;
649 case 'w':
650 n = 2;
651 break;
652 case 'd':
653 n = 4;
654 break;
655 case 's':
656 n = in[i].length + 1;
657 break;
658 }
659 for (j = 0; j < n; j++)
660 *(p++) = in[i].info[j];
661 }
662 out->parms[i].info = NULL;
663 out->parms[i].length = 0;
664}
665
666void api_load_msg(API_SAVE *in, API_PARSE *out)
667{
668 word i;
669
670 i = 0;
671 do
672 {
673 out[i].info = in->parms[i].info;
674 out[i].length = in->parms[i].length;
675 } while (in->parms[i++].info);
676}
677
678
679/*------------------------------------------------------------------*/
680/* CAPI remove function */
681/*------------------------------------------------------------------*/
682
683word api_remove_start(void)
684{
685 word i;
686 word j;
687
688 if(!remove_started) {
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800689 remove_started = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 for(i=0;i<max_adapter;i++) {
691 if(adapter[i].request) {
692 for(j=0;j<adapter[i].max_plci;j++) {
693 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
694 }
695 }
696 }
697 return 1;
698 }
699 else {
700 for(i=0;i<max_adapter;i++) {
701 if(adapter[i].request) {
702 for(j=0;j<adapter[i].max_plci;j++) {
703 if(adapter[i].plci[j].Sig.Id) return 1;
704 }
705 }
706 }
707 }
708 api_remove_complete();
709 return 0;
710}
711
712
713/*------------------------------------------------------------------*/
714/* internal command queue */
715/*------------------------------------------------------------------*/
716
717static void init_internal_command_queue (PLCI *plci)
718{
719 word i;
720
721 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722 (char *)(FILE_), __LINE__));
723
724 plci->internal_command = 0;
725 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726 plci->internal_command_queue[i] = NULL;
727}
728
729
730static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
731{
732 word i;
733
734 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735 UnMapId (Id), (char *)(FILE_), __LINE__));
736
737 if (plci->internal_command == 0)
738 {
739 plci->internal_command_queue[0] = command_function;
740 (* command_function)(Id, plci, OK);
741 }
742 else
743 {
744 i = 1;
745 while (plci->internal_command_queue[i] != 0)
746 i++;
747 plci->internal_command_queue[i] = command_function;
748 }
749}
750
751
752static void next_internal_command (dword Id, PLCI *plci)
753{
754 word i;
755
756 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757 UnMapId (Id), (char *)(FILE_), __LINE__));
758
759 plci->internal_command = 0;
760 plci->internal_command_queue[0] = NULL;
761 while (plci->internal_command_queue[1] != 0)
762 {
763 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766 (*(plci->internal_command_queue[0]))(Id, plci, OK);
767 if (plci->internal_command != 0)
768 return;
769 plci->internal_command_queue[0] = NULL;
770 }
771}
772
773
774/*------------------------------------------------------------------*/
775/* NCCI allocate/remove function */
776/*------------------------------------------------------------------*/
777
778static dword ncci_mapping_bug = 0;
779
780static word get_ncci (PLCI *plci, byte ch, word force_ncci)
781{
782 DIVA_CAPI_ADAPTER *a;
783 word ncci, i, j, k;
784
785 a = plci->adapter;
786 if (!ch || a->ch_ncci[ch])
787 {
788 ncci_mapping_bug++;
789 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
791 ncci = ch;
792 }
793 else
794 {
795 if (force_ncci)
796 ncci = force_ncci;
797 else
798 {
799 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
800 ncci = ch;
801 else
802 {
803 ncci = 1;
804 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
805 ncci++;
806 if (ncci == MAX_NCCI+1)
807 {
808 ncci_mapping_bug++;
809 i = 1;
810 do
811 {
812 j = 1;
813 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
814 j++;
815 k = j;
816 if (j < MAX_NCCI+1)
817 {
818 do
819 {
820 j++;
821 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
822 }
823 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824 if (i < MAX_NL_CHANNEL+1)
825 {
826 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827 ncci_mapping_bug, ch, force_ncci, i, k, j));
828 }
829 else
830 {
831 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832 ncci_mapping_bug, ch, force_ncci));
833 }
834 ncci = ch;
835 }
836 }
837 a->ncci_plci[ncci] = plci->Id;
838 a->ncci_state[ncci] = IDLE;
839 if (!plci->ncci_ring_list)
840 plci->ncci_ring_list = ncci;
841 else
842 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
844 }
845 a->ncci_ch[ncci] = ch;
846 a->ch_ncci[ch] = (byte) ncci;
847 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848 ncci_mapping_bug, ch, force_ncci, ch, ncci));
849 }
850 return (ncci);
851}
852
853
854static void ncci_free_receive_buffers (PLCI *plci, word ncci)
855{
856 DIVA_CAPI_ADAPTER *a;
857 APPL *appl;
858 word i, ncci_code;
859 dword Id;
860
861 a = plci->adapter;
862 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863 if (ncci)
864 {
865 if (a->ncci_plci[ncci] == plci->Id)
866 {
867 if (!plci->appl)
868 {
869 ncci_mapping_bug++;
870 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871 ncci_mapping_bug, Id));
872 }
873 else
874 {
875 appl = plci->appl;
876 ncci_code = ncci | (((word) a->Id) << 8);
877 for (i = 0; i < appl->MaxBuffer; i++)
878 {
879 if ((appl->DataNCCI[i] == ncci_code)
880 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
881 {
882 appl->DataNCCI[i] = 0;
883 }
884 }
885 }
886 }
887 }
888 else
889 {
890 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
891 {
892 if (a->ncci_plci[ncci] == plci->Id)
893 {
894 if (!plci->appl)
895 {
896 ncci_mapping_bug++;
897 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898 ncci_mapping_bug, Id));
899 }
900 else
901 {
902 appl = plci->appl;
903 ncci_code = ncci | (((word) a->Id) << 8);
904 for (i = 0; i < appl->MaxBuffer; i++)
905 {
906 if ((appl->DataNCCI[i] == ncci_code)
907 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
908 {
909 appl->DataNCCI[i] = 0;
910 }
911 }
912 }
913 }
914 }
915 }
916}
917
918
919static void cleanup_ncci_data (PLCI *plci, word ncci)
920{
921 NCCI *ncci_ptr;
922
923 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
924 {
925 ncci_ptr = &(plci->adapter->ncci[ncci]);
926 if (plci->appl)
927 {
928 while (ncci_ptr->data_pending != 0)
929 {
930 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932 (ncci_ptr->data_out)++;
933 if (ncci_ptr->data_out == MAX_DATA_B3)
934 ncci_ptr->data_out = 0;
935 (ncci_ptr->data_pending)--;
936 }
937 }
938 ncci_ptr->data_out = 0;
939 ncci_ptr->data_pending = 0;
940 ncci_ptr->data_ack_out = 0;
941 ncci_ptr->data_ack_pending = 0;
942 }
943}
944
945
946static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
947{
948 DIVA_CAPI_ADAPTER *a;
949 dword Id;
950 word i;
951
952 a = plci->adapter;
953 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
954 if (!preserve_ncci)
955 ncci_free_receive_buffers (plci, ncci);
956 if (ncci)
957 {
958 if (a->ncci_plci[ncci] != plci->Id)
959 {
960 ncci_mapping_bug++;
961 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962 ncci_mapping_bug, Id, preserve_ncci));
963 }
964 else
965 {
966 cleanup_ncci_data (plci, ncci);
967 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969 a->ch_ncci[a->ncci_ch[ncci]] = 0;
970 if (!preserve_ncci)
971 {
972 a->ncci_ch[ncci] = 0;
973 a->ncci_plci[ncci] = 0;
974 a->ncci_state[ncci] = IDLE;
975 i = plci->ncci_ring_list;
976 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
977 i = a->ncci_next[i];
978 if ((i != 0) && (a->ncci_next[i] == ncci))
979 {
980 if (i == ncci)
981 plci->ncci_ring_list = 0;
982 else if (plci->ncci_ring_list == ncci)
983 plci->ncci_ring_list = i;
984 a->ncci_next[i] = a->ncci_next[ncci];
985 }
986 a->ncci_next[ncci] = 0;
987 }
988 }
989 }
990 else
991 {
992 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
993 {
994 if (a->ncci_plci[ncci] == plci->Id)
995 {
996 cleanup_ncci_data (plci, ncci);
997 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000 if (!preserve_ncci)
1001 {
1002 a->ncci_ch[ncci] = 0;
1003 a->ncci_plci[ncci] = 0;
1004 a->ncci_state[ncci] = IDLE;
1005 a->ncci_next[ncci] = 0;
1006 }
1007 }
1008 }
1009 if (!preserve_ncci)
1010 plci->ncci_ring_list = 0;
1011 }
1012}
1013
1014
1015/*------------------------------------------------------------------*/
1016/* PLCI remove function */
1017/*------------------------------------------------------------------*/
1018
1019static void plci_free_msg_in_queue (PLCI *plci)
1020{
1021 word i;
1022
1023 if (plci->appl)
1024 {
1025 i = plci->msg_in_read_pos;
1026 while (i != plci->msg_in_write_pos)
1027 {
1028 if (i == plci->msg_in_wrap_pos)
1029 i = 0;
1030 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031 {
1032
1033 TransmitBufferFree (plci->appl,
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07001034 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
1036 }
1037
1038 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1039 MSG_IN_OVERHEAD + 3) & 0xfffc;
1040
1041 }
1042 }
1043 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1046}
1047
1048
1049static void plci_remove(PLCI * plci)
1050{
1051
1052 if(!plci) {
1053 dbug(1,dprintf("plci_remove(no plci)"));
1054 return;
1055 }
1056 init_internal_command_queue (plci);
1057 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058 if(plci_remove_check(plci))
1059 {
1060 return;
1061 }
1062 if (plci->Sig.Id == 0xff)
1063 {
1064 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065 if (plci->NL.Id && !plci->nl_remove_id)
1066 {
1067 nl_req_ncci(plci,REMOVE,0);
1068 send_req(plci);
1069 }
1070 }
1071 else
1072 {
1073 if (!plci->sig_remove_id
1074 && (plci->Sig.Id
1075 || (plci->req_in!=plci->req_out)
1076 || (plci->nl_req || plci->sig_req)))
1077 {
1078 sig_req(plci,HANGUP,0);
1079 send_req(plci);
1080 }
1081 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001082 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 plci_free_msg_in_queue (plci);
1084
1085 plci->channels = 0;
1086 plci->appl = NULL;
1087 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088 plci->State = OUTG_DIS_PENDING;
1089}
1090
1091/*------------------------------------------------------------------*/
1092/* Application Group function helpers */
1093/*------------------------------------------------------------------*/
1094
1095static void set_group_ind_mask (PLCI *plci)
1096{
1097 word i;
1098
1099 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100 plci->group_optimization_mask_table[i] = 0xffffffffL;
1101}
1102
1103static void clear_group_ind_mask_bit (PLCI *plci, word b)
1104{
1105 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106}
1107
1108static byte test_group_ind_mask_bit (PLCI *plci, word b)
1109{
1110 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111}
1112
1113/*------------------------------------------------------------------*/
1114/* c_ind_mask operations for arbitrary MAX_APPL */
1115/*------------------------------------------------------------------*/
1116
1117static void clear_c_ind_mask (PLCI *plci)
1118{
1119 word i;
1120
1121 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122 plci->c_ind_mask_table[i] = 0;
1123}
1124
1125static byte c_ind_mask_empty (PLCI *plci)
1126{
1127 word i;
1128
1129 i = 0;
1130 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131 i++;
1132 return (i == C_IND_MASK_DWORDS);
1133}
1134
1135static void set_c_ind_mask_bit (PLCI *plci, word b)
1136{
1137 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138}
1139
1140static void clear_c_ind_mask_bit (PLCI *plci, word b)
1141{
1142 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143}
1144
1145static byte test_c_ind_mask_bit (PLCI *plci, word b)
1146{
1147 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148}
1149
1150static void dump_c_ind_mask (PLCI *plci)
1151{
1152static char hex_digit_table[0x10] =
1153 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154 word i, j, k;
1155 dword d;
1156 char *p;
1157 char buf[40];
1158
1159 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1160 {
1161 p = buf + 36;
1162 *p = '\0';
1163 for (j = 0; j < 4; j++)
1164 {
1165 if (i+j < C_IND_MASK_DWORDS)
1166 {
1167 d = plci->c_ind_mask_table[i+j];
1168 for (k = 0; k < 8; k++)
1169 {
1170 *(--p) = hex_digit_table[d & 0xf];
1171 d >>= 4;
1172 }
1173 }
1174 else if (i != 0)
1175 {
1176 for (k = 0; k < 8; k++)
1177 *(--p) = ' ';
1178 }
1179 *(--p) = ' ';
1180 }
1181 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1182 }
1183}
1184
1185
1186
1187
1188
1189#define dump_plcis(a)
1190
1191
1192
1193/*------------------------------------------------------------------*/
1194/* translation function for each message */
1195/*------------------------------------------------------------------*/
1196
1197byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1198{
1199 word ch;
1200 word i;
1201 word Info;
1202 word CIP;
1203 byte LinkLayer;
1204 API_PARSE * ai;
1205 API_PARSE * bp;
1206 API_PARSE ai_parms[5];
1207 word channel = 0;
1208 dword ch_mask;
1209 byte m;
1210 static byte esc_chi[35] = {0x02,0x18,0x01};
1211 static byte lli[2] = {0x01,0x00};
1212 byte noCh = 0;
1213 word dir = 0;
1214 byte *p_chi = "";
1215
1216 for(i=0;i<5;i++) ai_parms[i].length = 0;
1217
1218 dbug(1,dprintf("connect_req(%d)",parms->length));
1219 Info = _WRONG_IDENTIFIER;
1220 if(a)
1221 {
1222 if(a->adapter_disabled)
1223 {
1224 dbug(1,dprintf("adapter disabled"));
1225 Id = ((word)1<<8)|a->Id;
1226 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001228 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 }
1230 Info = _OUT_OF_PLCI;
1231 if((i=get_plci(a)))
1232 {
1233 Info = 0;
1234 plci = &a->plci[i-1];
1235 plci->appl = appl;
1236 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237 /* check 'external controller' bit for codec support */
1238 if(Id & EXT_CONTROLLER)
1239 {
1240 if(AdvCodecSupport(a, plci, appl, 0) )
1241 {
1242 plci->Id = 0;
1243 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1244 return 2;
1245 }
1246 }
1247 ai = &parms[9];
1248 bp = &parms[5];
1249 ch = 0;
1250 if(bp->length)LinkLayer = bp->info[3];
1251 else LinkLayer = 0;
1252 if(ai->length)
1253 {
1254 ch=0xffff;
1255 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1256 {
1257 ch = 0;
1258 if(ai_parms[0].length)
1259 {
1260 ch = GET_WORD(ai_parms[0].info+1);
1261 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262 if(ch==4) /* explizit CHI in message */
1263 {
1264 /* check length of B-CH struct */
1265 if((ai_parms[0].info)[3]>=1)
1266 {
1267 if((ai_parms[0].info)[4]==CHI)
1268 {
1269 p_chi = &((ai_parms[0].info)[5]);
1270 }
1271 else
1272 {
1273 p_chi = &((ai_parms[0].info)[3]);
1274 }
1275 if(p_chi[0]>35) /* check length of channel ID */
1276 {
1277 Info = _WRONG_MESSAGE_FORMAT;
1278 }
1279 }
1280 else Info = _WRONG_MESSAGE_FORMAT;
1281 }
1282
1283 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1284 {
1285 dir = GET_WORD(ai_parms[0].info+3);
1286 ch_mask = 0;
1287 m = 0x3f;
1288 for(i=0; i+5<=ai_parms[0].length; i++)
1289 {
1290 if(ai_parms[0].info[i+5]!=0)
1291 {
1292 if((ai_parms[0].info[i+5] | m) != 0xff)
1293 Info = _WRONG_MESSAGE_FORMAT;
1294 else
1295 {
1296 if (ch_mask == 0)
1297 channel = i;
1298 ch_mask |= 1L << i;
1299 }
1300 }
1301 m = 0;
1302 }
1303 if (ch_mask == 0)
1304 Info = _WRONG_MESSAGE_FORMAT;
1305 if (!Info)
1306 {
1307 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1308 {
1309 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310 for(i=0; i+5<=ai_parms[0].length; i++)
1311 esc_chi[i+3] = ai_parms[0].info[i+5];
1312 }
1313 else
1314 esc_chi[0] = 2;
1315 esc_chi[2] = (byte)channel;
1316 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317 add_p(plci,LLI,lli);
1318 add_p(plci,ESC,esc_chi);
1319 plci->State = LOCAL_CONNECT;
1320 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1321 }
1322 }
1323 }
1324 }
1325 else Info = _WRONG_MESSAGE_FORMAT;
1326 }
1327
1328 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329 plci->command = _CONNECT_R;
1330 plci->number = Number;
1331 /* x.31 or D-ch free SAPI in LinkLayer? */
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001332 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1334 {
1335 /* B-channel used for B3 connections (ch==0), or no B channel */
1336 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1337 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1338 else Info = add_b1(plci,&parms[5],ch,0);
1339 add_s(plci,OAD,&parms[2]);
1340 add_s(plci,OSA,&parms[4]);
1341 add_s(plci,BC,&parms[6]);
1342 add_s(plci,LLC,&parms[7]);
1343 add_s(plci,HLC,&parms[8]);
1344 CIP = GET_WORD(parms[0].info);
1345 if (a->Info_Mask[appl->Id-1] & 0x200)
1346 {
1347 /* early B3 connect (CIP mask bit 9) no release after a disc */
1348 add_p(plci,LLI,"\x01\x01");
1349 }
1350 if(GET_WORD(parms[0].info)<29) {
1351 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1353 }
1354 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355 sig_req(plci,ASSIGN,DSIG_ID);
1356 }
1357 else if(ch==1) {
1358
1359 /* D-Channel used for B3 connections */
1360 plci->Sig.Id = 0xff;
1361 Info = 0;
1362 }
1363
1364 if(!Info && ch!=2 && !noCh ) {
1365 Info = add_b23(plci,&parms[5]);
1366 if(!Info) {
1367 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1368 }
1369 }
1370
1371 if(!Info)
1372 {
1373 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1374 {
1375 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1376 {
1377 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378 plci->spoofed_msg = CALL_REQ;
1379 plci->internal_command = BLOCK_PLCI;
1380 plci->command = 0;
1381 dbug(1,dprintf("Spoof"));
1382 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001383 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 }
1385 if(ch==4)add_p(plci,CHI,p_chi);
1386 add_s(plci,CPN,&parms[1]);
1387 add_s(plci,DSA,&parms[3]);
1388 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1389 add_ai(plci,&parms[9]);
1390 if(!dir)sig_req(plci,CALL_REQ,0);
1391 else
1392 {
1393 plci->command = PERM_LIST_REQ;
1394 plci->appl = appl;
1395 sig_req(plci,LISTEN_REQ,0);
1396 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001397 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 }
1399 }
1400 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001401 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 }
1403 plci->Id = 0;
1404 }
1405 }
1406 sendf(appl,
1407 _CONNECT_R|CONFIRM,
1408 Id,
1409 Number,
1410 "w",Info);
1411 return 2;
1412}
1413
1414byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1415{
1416 word i, Info;
1417 word Reject;
1418 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420 API_PARSE * ai;
1421 API_PARSE ai_parms[5];
1422 word ch=0;
1423
1424 if(!plci) {
1425 dbug(1,dprintf("connect_res(no plci)"));
1426 return 0; /* no plci, no send */
1427 }
1428
1429 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430 for(i=0;i<5;i++) ai_parms[i].length = 0;
1431 ai = &parms[5];
1432 dbug(1,dprintf("ai->length=%d",ai->length));
1433
1434 if(ai->length)
1435 {
1436 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1437 {
1438 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439 ch = 0;
1440 if(ai_parms[0].length)
1441 {
1442 ch = GET_WORD(ai_parms[0].info+1);
1443 dbug(1,dprintf("BCH-I=0x%x",ch));
1444 }
1445 }
1446 }
1447
1448 if(plci->State==INC_CON_CONNECTED_ALERT)
1449 {
1450 dbug(1,dprintf("Connected Alert Call_Res"));
1451 if (a->Info_Mask[appl->Id-1] & 0x200)
1452 {
1453 /* early B3 connect (CIP mask bit 9) no release after a disc */
1454 add_p(plci,LLI,"\x01\x01");
1455 }
1456 add_s(plci, CONN_NR, &parms[2]);
1457 add_s(plci, LLC, &parms[4]);
1458 add_ai(plci, &parms[5]);
1459 plci->State = INC_CON_ACCEPT;
1460 sig_req(plci, CALL_RES,0);
1461 return 1;
1462 }
1463 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465 dump_c_ind_mask (plci);
1466 Reject = GET_WORD(parms[0].info);
1467 dbug(1,dprintf("Reject=0x%x",Reject));
1468 if(Reject)
1469 {
1470 if(c_ind_mask_empty (plci))
1471 {
1472 if((Reject&0xff00)==0x3400)
1473 {
1474 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475 add_p(plci,ESC,esc_t);
1476 add_ai(plci, &parms[5]);
1477 sig_req(plci,REJECT,0);
1478 }
1479 else if(Reject==1 || Reject>9)
1480 {
1481 add_ai(plci, &parms[5]);
1482 sig_req(plci,HANGUP,0);
1483 }
1484 else
1485 {
1486 esc_t[2] = cau_t[(Reject&0x000f)];
1487 add_p(plci,ESC,esc_t);
1488 add_ai(plci, &parms[5]);
1489 sig_req(plci,REJECT,0);
1490 }
1491 plci->appl = appl;
1492 }
1493 else
1494 {
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496 }
1497 }
1498 else {
1499 plci->appl = appl;
1500 if(Id & EXT_CONTROLLER){
1501 if(AdvCodecSupport(a, plci, appl, 0)){
1502 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503 sig_req(plci,HANGUP,0);
1504 return 1;
1505 }
1506 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1507 {
1508 Info = add_b23(plci, &parms[1]);
1509 if (Info)
1510 {
1511 dbug(1,dprintf("connect_res(error from add_b23)"));
1512 sig_req(plci,HANGUP,0);
1513 return 1;
1514 }
1515 if(plci->adv_nl)
1516 {
1517 nl_req_ncci(plci, ASSIGN, 0);
1518 }
1519 }
1520 }
1521 else
1522 {
1523 plci->tel = 0;
1524 if(ch!=2)
1525 {
1526 Info = add_b23(plci, &parms[1]);
1527 if (Info)
1528 {
1529 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530 sig_req(plci,HANGUP,0);
1531 return 1;
1532 }
1533 }
1534 nl_req_ncci(plci, ASSIGN, 0);
1535 }
1536
1537 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1538 {
1539 api_save_msg(parms, "wsssss", &plci->saved_msg);
1540 plci->spoofed_msg = CALL_RES;
1541 plci->internal_command = BLOCK_PLCI;
1542 plci->command = 0;
1543 dbug(1,dprintf("Spoof"));
1544 }
1545 else
1546 {
1547 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548 if (a->Info_Mask[appl->Id-1] & 0x200)
1549 {
1550 /* early B3 connect (CIP mask bit 9) no release after a disc */
1551 add_p(plci,LLI,"\x01\x01");
1552 }
1553 add_s(plci, CONN_NR, &parms[2]);
1554 add_s(plci, LLC, &parms[4]);
1555 add_ai(plci, &parms[5]);
1556 plci->State = INC_CON_ACCEPT;
1557 sig_req(plci, CALL_RES,0);
1558 }
1559
1560 for(i=0; i<max_appl; i++) {
1561 if(test_c_ind_mask_bit (plci, i)) {
1562 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563 }
1564 }
1565 }
1566 }
1567 return 1;
1568}
1569
1570byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1571{
1572 dbug(1,dprintf("connect_a_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001573 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574}
1575
1576byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1577{
1578 word Info;
1579 word i;
1580
1581 dbug(1,dprintf("disconnect_req"));
1582
1583 Info = _WRONG_IDENTIFIER;
1584
1585 if(plci)
1586 {
1587 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1588 {
1589 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1590 plci->appl = appl;
1591 for(i=0; i<max_appl; i++)
1592 {
1593 if(test_c_ind_mask_bit (plci, i))
1594 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595 }
1596 plci->State = OUTG_DIS_PENDING;
1597 }
1598 if(plci->Sig.Id && plci->appl)
1599 {
1600 Info = 0;
1601 if(plci->Sig.Id!=0xff)
1602 {
1603 if(plci->State!=INC_DIS_PENDING)
1604 {
1605 add_ai(plci, &msg[0]);
1606 sig_req(plci,HANGUP,0);
1607 plci->State = OUTG_DIS_PENDING;
1608 return 1;
1609 }
1610 }
1611 else
1612 {
1613 if (plci->NL.Id && !plci->nl_remove_id)
1614 {
1615 mixer_remove (plci);
1616 nl_req_ncci(plci,REMOVE,0);
1617 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619 plci->State = INC_DIS_PENDING;
1620 }
1621 return 1;
1622 }
1623 }
1624 }
1625
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001626 if(!appl) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001628 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629}
1630
1631byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1632{
1633 dbug(1,dprintf("disconnect_res"));
1634 if(plci)
1635 {
1636 /* clear ind mask bit, just in case of collsion of */
1637 /* DISCONNECT_IND and CONNECT_RES */
1638 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639 ncci_free_receive_buffers (plci, 0);
1640 if(plci_remove_check(plci))
1641 {
1642 return 0;
1643 }
1644 if(plci->State==INC_DIS_PENDING
1645 || plci->State==SUSPENDING) {
1646 if(c_ind_mask_empty (plci)) {
1647 if(plci->State!=SUSPENDING)plci->State = IDLE;
1648 dbug(1,dprintf("chs=%d",plci->channels));
1649 if(!plci->channels) {
1650 plci_remove(plci);
1651 }
1652 }
1653 }
1654 }
1655 return 0;
1656}
1657
1658byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1659{
1660 word Info;
1661 byte i;
1662
1663 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1664
1665 Info = _WRONG_IDENTIFIER;
1666 if(a) {
1667 Info = 0;
1668 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1669 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1670 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1671 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1672 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1673 }
1674
1675 /* check if external controller listen and switch listen on or off*/
1676 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1677 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1678 dummy_plci.State = IDLE;
1679 a->codec_listen[appl->Id-1] = &dummy_plci;
1680 a->TelOAD[0] = (byte)(parms[3].length);
1681 for(i=1;parms[3].length>=i && i<22;i++) {
1682 a->TelOAD[i] = parms[3].info[i];
1683 }
1684 a->TelOAD[i] = 0;
1685 a->TelOSA[0] = (byte)(parms[4].length);
1686 for(i=1;parms[4].length>=i && i<22;i++) {
1687 a->TelOSA[i] = parms[4].info[i];
1688 }
1689 a->TelOSA[i] = 0;
1690 }
1691 else Info = 0x2002; /* wrong controller, codec not supported */
1692 }
1693 else{ /* clear listen */
1694 a->codec_listen[appl->Id-1] = (PLCI *)0;
1695 }
1696 }
1697 sendf(appl,
1698 _LISTEN_R|CONFIRM,
1699 Id,
1700 Number,
1701 "w",Info);
1702
1703 if (a) listen_check(a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001704 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705}
1706
1707byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1708{
1709 word i;
1710 API_PARSE * ai;
1711 PLCI * rc_plci = NULL;
1712 API_PARSE ai_parms[5];
1713 word Info = 0;
1714
1715 dbug(1,dprintf("info_req"));
1716 for(i=0;i<5;i++) ai_parms[i].length = 0;
1717
1718 ai = &msg[1];
1719
1720 if(ai->length)
1721 {
1722 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1723 {
1724 dbug(1,dprintf("AddInfo wrong"));
1725 Info = _WRONG_MESSAGE_FORMAT;
1726 }
1727 }
1728 if(!a) Info = _WRONG_STATE;
1729
1730 if(!Info && plci)
1731 { /* no fac, with CPN, or KEY */
1732 rc_plci = plci;
1733 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1734 {
1735 /* overlap sending option */
1736 dbug(1,dprintf("OvlSnd"));
1737 add_s(plci,CPN,&msg[0]);
1738 add_s(plci,KEY,&ai_parms[1]);
1739 sig_req(plci,INFO_REQ,0);
1740 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001741 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 }
1743
1744 if(plci->State && ai_parms[2].length)
1745 {
1746 /* User_Info option */
1747 dbug(1,dprintf("UUI"));
1748 add_s(plci,UUI,&ai_parms[2]);
1749 sig_req(plci,USER_DATA,0);
1750 }
1751 else if(plci->State && ai_parms[3].length)
1752 {
1753 /* Facility option */
1754 dbug(1,dprintf("FAC"));
1755 add_s(plci,CPN,&msg[0]);
1756 add_ai(plci, &msg[1]);
1757 sig_req(plci,FACILITY_REQ,0);
1758 }
1759 else
1760 {
1761 Info = _WRONG_STATE;
1762 }
1763 }
1764 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1765 {
1766 /* NCR_Facility option -> send UUI and Keypad too */
1767 dbug(1,dprintf("NCR_FAC"));
1768 if((i=get_plci(a)))
1769 {
1770 rc_plci = &a->plci[i-1];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001771 appl->NullCREnable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 rc_plci->internal_command = C_NCR_FAC_REQ;
1773 rc_plci->appl = appl;
1774 add_p(rc_plci,CAI,"\x01\x80");
1775 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776 sig_req(rc_plci,ASSIGN,DSIG_ID);
1777 send_req(rc_plci);
1778 }
1779 else
1780 {
1781 Info = _OUT_OF_PLCI;
1782 }
1783
1784 if(!Info)
1785 {
1786 add_s(rc_plci,CPN,&msg[0]);
1787 add_ai(rc_plci, &msg[1]);
1788 sig_req(rc_plci,NCR_FACILITY,0);
1789 send_req(rc_plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001790 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 /* for application controlled supplementary services */
1792 }
1793 }
1794
1795 if (!rc_plci)
1796 {
1797 Info = _WRONG_MESSAGE_FORMAT;
1798 }
1799
1800 if(!Info)
1801 {
1802 send_req(rc_plci);
1803 }
1804 else
1805 { /* appl is not assigned to a PLCI or error condition */
1806 dbug(1,dprintf("localInfoCon"));
1807 sendf(appl,
1808 _INFO_R|CONFIRM,
1809 Id,
1810 Number,
1811 "w",Info);
1812 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001813 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814}
1815
1816byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1817{
1818 dbug(1,dprintf("info_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001819 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820}
1821
1822byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1823{
1824 word Info;
1825 byte ret;
1826
1827 dbug(1,dprintf("alert_req"));
1828
1829 Info = _WRONG_IDENTIFIER;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001830 ret = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 if(plci) {
1832 Info = _ALERT_IGNORED;
1833 if(plci->State!=INC_CON_ALERT) {
1834 Info = _WRONG_STATE;
1835 if(plci->State==INC_CON_PENDING) {
1836 Info = 0;
1837 plci->State=INC_CON_ALERT;
1838 add_ai(plci, &msg[0]);
1839 sig_req(plci,CALL_ALERT,0);
1840 ret = 1;
1841 }
1842 }
1843 }
1844 sendf(appl,
1845 _ALERT_R|CONFIRM,
1846 Id,
1847 Number,
1848 "w",Info);
1849 return ret;
1850}
1851
1852byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1853{
1854 word Info = 0;
1855 word i = 0;
1856
1857 word selector;
1858 word SSreq;
1859 long relatedPLCIvalue;
1860 DIVA_CAPI_ADAPTER * relatedadapter;
1861 byte * SSparms = "";
1862 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1863 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1864 API_PARSE * parms;
1865 API_PARSE ss_parms[11];
1866 PLCI *rplci;
1867 byte cai[15];
1868 dword d;
1869 API_PARSE dummy;
1870
1871 dbug(1,dprintf("facility_req"));
1872 for(i=0;i<9;i++) ss_parms[i].length = 0;
1873
1874 parms = &msg[1];
1875
1876 if(!a)
1877 {
1878 dbug(1,dprintf("wrong Ctrl"));
1879 Info = _WRONG_IDENTIFIER;
1880 }
1881
1882 selector = GET_WORD(msg[0].info);
1883
1884 if(!Info)
1885 {
1886 switch(selector)
1887 {
1888 case SELECTOR_HANDSET:
1889 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1890 break;
1891
1892 case SELECTOR_SU_SERV:
1893 if(!msg[1].length)
1894 {
1895 Info = _WRONG_MESSAGE_FORMAT;
1896 break;
1897 }
1898 SSreq = GET_WORD(&(msg[1].info[1]));
1899 PUT_WORD(&RCparms[1],SSreq);
1900 SSparms = RCparms;
1901 switch(SSreq)
1902 {
1903 case S_GET_SUPPORTED_SERVICES:
1904 if((i=get_plci(a)))
1905 {
1906 rplci = &a->plci[i-1];
1907 rplci->appl = appl;
1908 add_p(rplci,CAI,"\x01\x80");
1909 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910 sig_req(rplci,ASSIGN,DSIG_ID);
1911 send_req(rplci);
1912 }
1913 else
1914 {
1915 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916 SSparms = (byte *)SSstruct;
1917 break;
1918 }
1919 rplci->internal_command = GETSERV_REQ_PEND;
1920 rplci->number = Number;
1921 rplci->appl = appl;
1922 sig_req(rplci,S_SUPPORTED,0);
1923 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001924 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 break;
1926
1927 case S_LISTEN:
1928 if(parms->length==7)
1929 {
1930 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1931 {
1932 dbug(1,dprintf("format wrong"));
1933 Info = _WRONG_MESSAGE_FORMAT;
1934 break;
1935 }
1936 }
1937 else
1938 {
1939 Info = _WRONG_MESSAGE_FORMAT;
1940 break;
1941 }
1942 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1944 {
1945 if((i=get_plci(a)))
1946 {
1947 rplci = &a->plci[i-1];
1948 rplci->appl = appl;
1949 add_p(rplci,CAI,"\x01\x80");
1950 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951 sig_req(rplci,ASSIGN,DSIG_ID);
1952 send_req(rplci);
1953 }
1954 else
1955 {
1956 break;
1957 }
1958 rplci->internal_command = GET_MWI_STATE;
1959 rplci->number = Number;
1960 sig_req(rplci,MWI_POLL,0);
1961 send_req(rplci);
1962 }
1963 break;
1964
1965 case S_HOLD:
1966 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967 if(plci && plci->State && plci->SuppState==IDLE)
1968 {
1969 plci->SuppState = HOLD_REQUEST;
1970 plci->command = C_HOLD_REQ;
1971 add_s(plci,CAI,&ss_parms[1]);
1972 sig_req(plci,CALL_HOLD,0);
1973 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001974 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 }
1976 else Info = 0x3010; /* wrong state */
1977 break;
1978 case S_RETRIEVE:
1979 if(plci && plci->State && plci->SuppState==CALL_HELD)
1980 {
1981 if(Id & EXT_CONTROLLER)
1982 {
1983 if(AdvCodecSupport(a, plci, appl, 0))
1984 {
1985 Info = 0x3010; /* wrong state */
1986 break;
1987 }
1988 }
1989 else plci->tel = 0;
1990
1991 plci->SuppState = RETRIEVE_REQUEST;
1992 plci->command = C_RETRIEVE_REQ;
1993 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1994 {
1995 plci->spoofed_msg = CALL_RETRIEVE;
1996 plci->internal_command = BLOCK_PLCI;
1997 plci->command = 0;
1998 dbug(1,dprintf("Spoof"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001999 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 }
2001 else
2002 {
2003 sig_req(plci,CALL_RETRIEVE,0);
2004 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002005 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 }
2007 }
2008 else Info = 0x3010; /* wrong state */
2009 break;
2010 case S_SUSPEND:
2011 if(parms->length)
2012 {
2013 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2014 {
2015 dbug(1,dprintf("format wrong"));
2016 Info = _WRONG_MESSAGE_FORMAT;
2017 break;
2018 }
2019 }
2020 if(plci && plci->State)
2021 {
2022 add_s(plci,CAI,&ss_parms[2]);
2023 plci->command = SUSPEND_REQ;
2024 sig_req(plci,SUSPEND,0);
2025 plci->State = SUSPENDING;
2026 send_req(plci);
2027 }
2028 else Info = 0x3010; /* wrong state */
2029 break;
2030
2031 case S_RESUME:
2032 if(!(i=get_plci(a)) )
2033 {
2034 Info = _OUT_OF_PLCI;
2035 break;
2036 }
2037 rplci = &a->plci[i-1];
2038 rplci->appl = appl;
2039 rplci->number = Number;
2040 rplci->tel = 0;
2041 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042 /* check 'external controller' bit for codec support */
2043 if(Id & EXT_CONTROLLER)
2044 {
2045 if(AdvCodecSupport(a, rplci, appl, 0) )
2046 {
2047 rplci->Id = 0;
2048 Info = 0x300A;
2049 break;
2050 }
2051 }
2052 if(parms->length)
2053 {
2054 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2055 {
2056 dbug(1,dprintf("format wrong"));
2057 rplci->Id = 0;
2058 Info = _WRONG_MESSAGE_FORMAT;
2059 break;
2060 }
2061 }
2062 dummy.length = 0;
2063 dummy.info = "\x00";
2064 add_b1(rplci, &dummy, 0, 0);
2065 if (a->Info_Mask[appl->Id-1] & 0x200)
2066 {
2067 /* early B3 connect (CIP mask bit 9) no release after a disc */
2068 add_p(rplci,LLI,"\x01\x01");
2069 }
2070 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071 sig_req(rplci,ASSIGN,DSIG_ID);
2072 send_req(rplci);
2073 add_s(rplci,CAI,&ss_parms[2]);
2074 rplci->command = RESUME_REQ;
2075 sig_req(rplci,RESUME,0);
2076 rplci->State = RESUMING;
2077 send_req(rplci);
2078 break;
2079
2080 case S_CONF_BEGIN: /* Request */
2081 case S_CONF_DROP:
2082 case S_CONF_ISOLATE:
2083 case S_CONF_REATTACH:
2084 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2085 {
2086 dbug(1,dprintf("format wrong"));
2087 Info = _WRONG_MESSAGE_FORMAT;
2088 break;
2089 }
2090 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2091 {
2092 d = GET_DWORD(ss_parms[2].info);
2093 if(d>=0x80)
2094 {
2095 dbug(1,dprintf("format wrong"));
2096 Info = _WRONG_MESSAGE_FORMAT;
2097 break;
2098 }
2099 plci->ptyState = (byte)SSreq;
2100 plci->command = 0;
2101 cai[0] = 2;
2102 switch(SSreq)
2103 {
2104 case S_CONF_BEGIN:
2105 cai[1] = CONF_BEGIN;
2106 plci->internal_command = CONF_BEGIN_REQ_PEND;
2107 break;
2108 case S_CONF_DROP:
2109 cai[1] = CONF_DROP;
2110 plci->internal_command = CONF_DROP_REQ_PEND;
2111 break;
2112 case S_CONF_ISOLATE:
2113 cai[1] = CONF_ISOLATE;
2114 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2115 break;
2116 case S_CONF_REATTACH:
2117 cai[1] = CONF_REATTACH;
2118 plci->internal_command = CONF_REATTACH_REQ_PEND;
2119 break;
2120 }
2121 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122 add_p(plci,CAI,cai);
2123 sig_req(plci,S_SERVICE,0);
2124 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002125 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 }
2127 else Info = 0x3010; /* wrong state */
2128 break;
2129
2130 case S_ECT:
2131 case S_3PTY_BEGIN:
2132 case S_3PTY_END:
2133 case S_CONF_ADD:
2134 if(parms->length==7)
2135 {
2136 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2137 {
2138 dbug(1,dprintf("format wrong"));
2139 Info = _WRONG_MESSAGE_FORMAT;
2140 break;
2141 }
2142 }
2143 else if(parms->length==8) /* workaround for the T-View-S */
2144 {
2145 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2146 {
2147 dbug(1,dprintf("format wrong"));
2148 Info = _WRONG_MESSAGE_FORMAT;
2149 break;
2150 }
2151 }
2152 else
2153 {
2154 Info = _WRONG_MESSAGE_FORMAT;
2155 break;
2156 }
2157 if(!msg[1].length)
2158 {
2159 Info = _WRONG_MESSAGE_FORMAT;
2160 break;
2161 }
2162 if (!plci)
2163 {
2164 Info = _WRONG_IDENTIFIER;
2165 break;
2166 }
2167 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168 relatedPLCIvalue &= 0x0000FFFF;
2169 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170 /* controller starts with 0 up to (max_adapter - 1) */
2171 if (((relatedPLCIvalue & 0x7f) == 0)
2172 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2174 {
2175 if(SSreq==S_3PTY_END)
2176 {
2177 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2178 rplci = plci;
2179 }
2180 else
2181 {
2182 Info = 0x3010; /* wrong state */
2183 break;
2184 }
2185 }
2186 else
2187 {
2188 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189 relatedPLCIvalue >>=8;
2190 /* find PLCI PTR*/
2191 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2192 {
2193 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2194 {
2195 rplci = &relatedadapter->plci[i];
2196 }
2197 }
2198 if(!rplci || !relatedPLCIvalue)
2199 {
2200 if(SSreq==S_3PTY_END)
2201 {
2202 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2203 rplci = plci;
2204 }
2205 else
2206 {
2207 Info = 0x3010; /* wrong state */
2208 break;
2209 }
2210 }
2211 }
2212/*
2213 dbug(1,dprintf("rplci:%x",rplci));
2214 dbug(1,dprintf("plci:%x",plci));
2215 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217 dbug(1,dprintf("SSreq:%x",SSreq));
2218 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2221*/
2222 /* send PTY/ECT req, cannot check all states because of US stuff */
2223 if( !rplci->internal_command && rplci->appl )
2224 {
2225 plci->command = 0;
2226 rplci->relatedPTYPLCI = plci;
2227 plci->relatedPTYPLCI = rplci;
2228 rplci->ptyState = (byte)SSreq;
2229 if(SSreq==S_ECT)
2230 {
2231 rplci->internal_command = ECT_REQ_PEND;
2232 cai[1] = ECT_EXECUTE;
2233
2234 rplci->vswitchstate=0;
2235 rplci->vsprot=0;
2236 rplci->vsprotdialect=0;
2237 plci->vswitchstate=0;
2238 plci->vsprot=0;
2239 plci->vsprotdialect=0;
2240
2241 }
2242 else if(SSreq==S_CONF_ADD)
2243 {
2244 rplci->internal_command = CONF_ADD_REQ_PEND;
2245 cai[1] = CONF_ADD;
2246 }
2247 else
2248 {
2249 rplci->internal_command = PTY_REQ_PEND;
2250 cai[1] = (byte)(SSreq-3);
2251 }
2252 rplci->number = Number;
2253 if(plci!=rplci) /* explicit invocation */
2254 {
2255 cai[0] = 2;
2256 cai[2] = plci->Sig.Id;
2257 dbug(1,dprintf("explicit invocation"));
2258 }
2259 else
2260 {
2261 dbug(1,dprintf("implicit invocation"));
2262 cai[0] = 1;
2263 }
2264 add_p(rplci,CAI,cai);
2265 sig_req(rplci,S_SERVICE,0);
2266 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002267 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 }
2269 else
2270 {
2271 dbug(0,dprintf("Wrong line"));
2272 Info = 0x3010; /* wrong state */
2273 break;
2274 }
2275 break;
2276
2277 case S_CALL_DEFLECTION:
2278 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2279 {
2280 dbug(1,dprintf("format wrong"));
2281 Info = _WRONG_MESSAGE_FORMAT;
2282 break;
2283 }
2284 if (!plci)
2285 {
2286 Info = _WRONG_IDENTIFIER;
2287 break;
2288 }
2289 /* reuse unused screening indicator */
2290 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2291 plci->command = 0;
2292 plci->internal_command = CD_REQ_PEND;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002293 appl->CDEnable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 cai[0] = 1;
2295 cai[1] = CALL_DEFLECTION;
2296 add_p(plci,CAI,cai);
2297 add_p(plci,CPN,ss_parms[3].info);
2298 sig_req(plci,S_SERVICE,0);
2299 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002300 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 break;
2302
2303 case S_CALL_FORWARDING_START:
2304 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2305 {
2306 dbug(1,dprintf("format wrong"));
2307 Info = _WRONG_MESSAGE_FORMAT;
2308 break;
2309 }
2310
2311 if((i=get_plci(a)))
2312 {
2313 rplci = &a->plci[i-1];
2314 rplci->appl = appl;
2315 add_p(rplci,CAI,"\x01\x80");
2316 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317 sig_req(rplci,ASSIGN,DSIG_ID);
2318 send_req(rplci);
2319 }
2320 else
2321 {
2322 Info = _OUT_OF_PLCI;
2323 break;
2324 }
2325
2326 /* reuse unused screening indicator */
2327 rplci->internal_command = CF_START_PEND;
2328 rplci->appl = appl;
2329 rplci->number = Number;
2330 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2331 cai[0] = 2;
2332 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334 add_p(rplci,CAI,cai);
2335 add_p(rplci,OAD,ss_parms[5].info);
2336 add_p(rplci,CPN,ss_parms[6].info);
2337 sig_req(rplci,S_SERVICE,0);
2338 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002339 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 break;
2341
2342 case S_INTERROGATE_DIVERSION:
2343 case S_INTERROGATE_NUMBERS:
2344 case S_CALL_FORWARDING_STOP:
2345 case S_CCBS_REQUEST:
2346 case S_CCBS_DEACTIVATE:
2347 case S_CCBS_INTERROGATE:
2348 switch(SSreq)
2349 {
2350 case S_INTERROGATE_NUMBERS:
2351 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2352 {
2353 dbug(0,dprintf("format wrong"));
2354 Info = _WRONG_MESSAGE_FORMAT;
2355 }
2356 break;
2357 case S_CCBS_REQUEST:
2358 case S_CCBS_DEACTIVATE:
2359 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2360 {
2361 dbug(0,dprintf("format wrong"));
2362 Info = _WRONG_MESSAGE_FORMAT;
2363 }
2364 break;
2365 case S_CCBS_INTERROGATE:
2366 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2367 {
2368 dbug(0,dprintf("format wrong"));
2369 Info = _WRONG_MESSAGE_FORMAT;
2370 }
2371 break;
2372 default:
2373 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2374 {
2375 dbug(0,dprintf("format wrong"));
2376 Info = _WRONG_MESSAGE_FORMAT;
2377 break;
2378 }
2379 break;
2380 }
2381
2382 if(Info) break;
2383 if((i=get_plci(a)))
2384 {
2385 rplci = &a->plci[i-1];
2386 switch(SSreq)
2387 {
2388 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2391 break;
2392 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2395 break;
2396 case S_CALL_FORWARDING_STOP:
2397 rplci->internal_command = CF_STOP_PEND;
2398 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2399 break;
2400 case S_CCBS_REQUEST:
2401 cai[1] = CCBS_REQUEST;
2402 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2403 break;
2404 case S_CCBS_DEACTIVATE:
2405 cai[1] = CCBS_DEACTIVATE;
2406 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2407 break;
2408 case S_CCBS_INTERROGATE:
2409 cai[1] = CCBS_INTERROGATE;
2410 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2411 break;
2412 default:
2413 cai[1] = 0;
2414 break;
2415 }
2416 rplci->appl = appl;
2417 rplci->number = Number;
2418 add_p(rplci,CAI,"\x01\x80");
2419 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420 sig_req(rplci,ASSIGN,DSIG_ID);
2421 send_req(rplci);
2422 }
2423 else
2424 {
2425 Info = _OUT_OF_PLCI;
2426 break;
2427 }
2428
2429 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2430 switch(SSreq)
2431 {
2432 case S_INTERROGATE_NUMBERS:
2433 cai[0] = 1;
2434 add_p(rplci,CAI,cai);
2435 break;
2436 case S_CCBS_REQUEST:
2437 case S_CCBS_DEACTIVATE:
2438 cai[0] = 3;
2439 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440 add_p(rplci,CAI,cai);
2441 break;
2442 case S_CCBS_INTERROGATE:
2443 cai[0] = 3;
2444 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445 add_p(rplci,CAI,cai);
2446 add_p(rplci,OAD,ss_parms[4].info);
2447 break;
2448 default:
2449 cai[0] = 2;
2450 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451 add_p(rplci,CAI,cai);
2452 add_p(rplci,OAD,ss_parms[5].info);
2453 break;
2454 }
2455
2456 sig_req(rplci,S_SERVICE,0);
2457 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002458 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 break;
2460
2461 case S_MWI_ACTIVATE:
2462 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2463 {
2464 dbug(1,dprintf("format wrong"));
2465 Info = _WRONG_MESSAGE_FORMAT;
2466 break;
2467 }
2468 if(!plci)
2469 {
2470 if((i=get_plci(a)))
2471 {
2472 rplci = &a->plci[i-1];
2473 rplci->appl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002474 rplci->cr_enquiry=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 add_p(rplci,CAI,"\x01\x80");
2476 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477 sig_req(rplci,ASSIGN,DSIG_ID);
2478 send_req(rplci);
2479 }
2480 else
2481 {
2482 Info = _OUT_OF_PLCI;
2483 break;
2484 }
2485 }
2486 else
2487 {
2488 rplci = plci;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002489 rplci->cr_enquiry=false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 }
2491
2492 rplci->command = 0;
2493 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2494 rplci->appl = appl;
2495 rplci->number = Number;
2496
2497 cai[0] = 13;
2498 cai[1] = ACTIVATION_MWI; /* Function */
2499 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504 add_p(rplci,CAI,cai);
2505 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508 add_p(rplci,UID,ss_parms[10].info); /* Time */
2509 sig_req(rplci,S_SERVICE,0);
2510 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002511 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
2513 case S_MWI_DEACTIVATE:
2514 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2515 {
2516 dbug(1,dprintf("format wrong"));
2517 Info = _WRONG_MESSAGE_FORMAT;
2518 break;
2519 }
2520 if(!plci)
2521 {
2522 if((i=get_plci(a)))
2523 {
2524 rplci = &a->plci[i-1];
2525 rplci->appl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002526 rplci->cr_enquiry=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 add_p(rplci,CAI,"\x01\x80");
2528 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529 sig_req(rplci,ASSIGN,DSIG_ID);
2530 send_req(rplci);
2531 }
2532 else
2533 {
2534 Info = _OUT_OF_PLCI;
2535 break;
2536 }
2537 }
2538 else
2539 {
2540 rplci = plci;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002541 rplci->cr_enquiry=false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 }
2543
2544 rplci->command = 0;
2545 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2546 rplci->appl = appl;
2547 rplci->number = Number;
2548
2549 cai[0] = 5;
2550 cai[1] = DEACTIVATION_MWI; /* Function */
2551 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553 add_p(rplci,CAI,cai);
2554 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556 sig_req(rplci,S_SERVICE,0);
2557 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002558 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
2560 default:
2561 Info = 0x300E; /* not supported */
2562 break;
2563 }
2564 break; /* case SELECTOR_SU_SERV: end */
2565
2566
2567 case SELECTOR_DTMF:
2568 return (dtmf_request (Id, Number, a, plci, appl, msg));
2569
2570
2571
2572 case SELECTOR_LINE_INTERCONNECT:
2573 return (mixer_request (Id, Number, a, plci, appl, msg));
2574
2575
2576
2577 case PRIV_SELECTOR_ECHO_CANCELLER:
2578 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579 return (ec_request (Id, Number, a, plci, appl, msg));
2580
2581 case SELECTOR_ECHO_CANCELLER:
2582 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583 return (ec_request (Id, Number, a, plci, appl, msg));
2584
2585
2586 case SELECTOR_V42BIS:
2587 default:
2588 Info = _FACILITY_NOT_SUPPORTED;
2589 break;
2590 } /* end of switch(selector) */
2591 }
2592
2593 dbug(1,dprintf("SendFacRc"));
2594 sendf(appl,
2595 _FACILITY_R|CONFIRM,
2596 Id,
2597 Number,
2598 "wws",Info,selector,SSparms);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002599 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600}
2601
2602byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2603{
2604 dbug(1,dprintf("facility_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002605 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606}
2607
2608byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2609{
2610 word Info = 0;
2611 byte req;
2612 byte len;
2613 word w;
2614 word fax_control_bits, fax_feature_bits, fax_info_change;
2615 API_PARSE * ncpi;
2616 byte pvc[2];
2617
2618 API_PARSE fax_parms[9];
2619 word i;
2620
2621
2622 dbug(1,dprintf("connect_b3_req"));
2623 if(plci)
2624 {
2625 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2627 {
2628 Info = _WRONG_STATE;
2629 }
2630 else
2631 {
2632 /* local reply if assign unsuccessfull
2633 or B3 protocol allows only one layer 3 connection
2634 and already connected
2635 or B2 protocol not any LAPD
2636 and connect_b3_req contradicts originate/answer direction */
2637 if (!plci->NL.Id
2638 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639 && ((plci->channels != 0)
2640 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2642 {
2643 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645 Info = _WRONG_STATE;
2646 sendf(appl,
2647 _CONNECT_B3_R|CONFIRM,
2648 Id,
2649 Number,
2650 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002651 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 }
2653 plci->requested_options_conn = 0;
2654
2655 req = N_CONNECT;
2656 ncpi = &parms[0];
2657 if(plci->B3_prot==2 || plci->B3_prot==3)
2658 {
2659 if(ncpi->length>2)
2660 {
2661 /* check for PVC */
2662 if(ncpi->info[2] || ncpi->info[3])
2663 {
2664 pvc[0] = ncpi->info[3];
2665 pvc[1] = ncpi->info[2];
2666 add_d(plci,2,pvc);
2667 req = N_RESET;
2668 }
2669 else
2670 {
2671 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2673 }
2674 }
2675 }
2676 else if(plci->B3_prot==5)
2677 {
2678 if (plci->NL.Id && !plci->nl_remove_id)
2679 {
2680 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2681 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2682 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2684 {
2685 len = (byte)(&(((T30_INFO *) 0)->universal_6));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002686 fax_info_change = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 if (ncpi->length >= 4)
2688 {
2689 w = GET_WORD(&ncpi->info[3]);
2690 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2691 {
2692 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2693 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002695 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 }
2697 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698 if (w & 0x0002) /* Fax-polling request */
2699 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700 if ((w & 0x0004) /* Request to send / poll another document */
2701 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2702 {
2703 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2704 }
2705 if (ncpi->length >= 6)
2706 {
2707 w = GET_WORD(&ncpi->info[5]);
2708 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2709 {
2710 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002711 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 }
2713
2714 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2716 {
2717 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2718 }
2719 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2721 {
2722 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2723 }
2724 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2728 {
2729 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730 Info = _WRONG_MESSAGE_FORMAT;
2731 else
2732 {
2733 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2735 {
2736 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2739 }
2740 w = fax_parms[4].length;
2741 if (w > 20)
2742 w = 20;
2743 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744 for (i = 0; i < w; i++)
2745 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2748 w = fax_parms[5].length;
2749 if (w > 20)
2750 w = 20;
2751 plci->fax_connect_info_buffer[len++] = (byte) w;
2752 for (i = 0; i < w; i++)
2753 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754 w = fax_parms[6].length;
2755 if (w > 20)
2756 w = 20;
2757 plci->fax_connect_info_buffer[len++] = (byte) w;
2758 for (i = 0; i < w; i++)
2759 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2760 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761 & (1L << PRIVATE_FAX_NONSTANDARD))
2762 {
2763 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2764 {
2765 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766 plci->fax_connect_info_buffer[len++] = 0;
2767 }
2768 else
2769 {
2770 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773 for (i = 0; i < fax_parms[7].length; i++)
2774 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2775 }
2776 }
2777 }
2778 }
2779 else
2780 {
2781 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2782 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002783 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784
2785 }
2786 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2787 {
2788 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002789 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 }
2791 }
2792 if (Info == GOOD)
2793 {
2794 plci->fax_connect_info_length = len;
2795 if (fax_info_change)
2796 {
2797 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2798 {
2799 start_internal_command (Id, plci, fax_connect_info_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002800 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 }
2802 else
2803 {
2804 start_internal_command (Id, plci, fax_adjust_b23_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002805 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 }
2807 }
2808 }
2809 }
2810 else Info = _WRONG_STATE;
2811 }
2812 else Info = _WRONG_STATE;
2813 }
2814
2815 else if (plci->B3_prot == B3_RTP)
2816 {
2817 plci->internal_req_buffer[0] = ncpi->length + 1;
2818 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819 for (w = 0; w < ncpi->length; w++)
2820 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821 start_internal_command (Id, plci, rtp_connect_b3_req_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002822 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 }
2824
2825 if(!Info)
2826 {
2827 nl_req_ncci(plci,req,0);
2828 return 1;
2829 }
2830 }
2831 }
2832 else Info = _WRONG_IDENTIFIER;
2833
2834 sendf(appl,
2835 _CONNECT_B3_R|CONFIRM,
2836 Id,
2837 Number,
2838 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002839 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840}
2841
2842byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2843{
2844 word ncci;
2845 API_PARSE * ncpi;
2846 byte req;
2847
2848 word w;
2849
2850
2851 API_PARSE fax_parms[9];
2852 word i;
2853 byte len;
2854
2855
2856 dbug(1,dprintf("connect_b3_res"));
2857
2858 ncci = (word)(Id>>16);
2859 if(plci && ncci) {
2860 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861 if (GET_WORD (&parms[0].info[0]) != 0)
2862 {
2863 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864 channel_request_xon (plci, a->ncci_ch[ncci]);
2865 channel_xmit_xon (plci);
2866 cleanup_ncci_data (plci, ncci);
2867 nl_req_ncci(plci,N_DISC,(byte)ncci);
2868 return 1;
2869 }
2870 a->ncci_state[ncci] = INC_ACT_PENDING;
2871
2872 req = N_CONNECT_ACK;
2873 ncpi = &parms[1];
2874 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2875 {
2876
2877 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878 & (1L << PRIVATE_FAX_NONSTANDARD))
2879 {
2880 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2883 {
2884 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2885 if (plci->fax_connect_info_length < len)
2886 {
2887 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2889 }
2890 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2891 {
2892 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2893 }
2894 else
2895 {
2896 if (plci->fax_connect_info_length <= len)
2897 plci->fax_connect_info_buffer[len] = 0;
2898 len += 1 + plci->fax_connect_info_buffer[len];
2899 if (plci->fax_connect_info_length <= len)
2900 plci->fax_connect_info_buffer[len] = 0;
2901 len += 1 + plci->fax_connect_info_buffer[len];
2902 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905 for (i = 0; i < fax_parms[7].length; i++)
2906 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2907 }
2908 plci->fax_connect_info_length = len;
2909 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910 start_internal_command (Id, plci, fax_connect_ack_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002911 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 }
2913 }
2914
2915 nl_req_ncci(plci,req,(byte)ncci);
2916 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2918 {
2919 if (plci->B3_prot == 4)
2920 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2921 else
2922 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2924 }
2925 }
2926
2927 else if (plci->B3_prot == B3_RTP)
2928 {
2929 plci->internal_req_buffer[0] = ncpi->length + 1;
2930 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931 for (w = 0; w < ncpi->length; w++)
2932 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933 start_internal_command (Id, plci, rtp_connect_b3_res_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002934 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 }
2936
2937 else
2938 {
2939 if(ncpi->length>2) {
2940 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2942 }
2943 nl_req_ncci(plci,req,(byte)ncci);
2944 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945 if (plci->adjust_b_restore)
2946 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002947 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 start_internal_command (Id, plci, adjust_b_restore);
2949 }
2950 }
2951 return 1;
2952 }
2953 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002954 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955}
2956
2957byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2958{
2959 word ncci;
2960
2961 ncci = (word)(Id>>16);
2962 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2963
2964 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965 && (plci->State != OUTG_DIS_PENDING))
2966 {
2967 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968 a->ncci_state[ncci] = CONNECTED;
2969 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970 channel_request_xon (plci, a->ncci_ch[ncci]);
2971 channel_xmit_xon (plci);
2972 }
2973 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002974 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975}
2976
2977byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2978{
2979 word Info;
2980 word ncci;
2981 API_PARSE * ncpi;
2982
2983 dbug(1,dprintf("disconnect_b3_req"));
2984
2985 Info = _WRONG_IDENTIFIER;
2986 ncci = (word)(Id>>16);
2987 if (plci && ncci)
2988 {
2989 Info = _WRONG_STATE;
2990 if ((a->ncci_state[ncci] == CONNECTED)
2991 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992 || (a->ncci_state[ncci] == INC_CON_PENDING)
2993 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2994 {
2995 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996 channel_request_xon (plci, a->ncci_ch[ncci]);
2997 channel_xmit_xon (plci);
2998
2999 if (a->ncci[ncci].data_pending
3000 && ((plci->B3_prot == B3_TRANSPARENT)
3001 || (plci->B3_prot == B3_T30)
3002 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3003 {
3004 plci->send_disc = (byte)ncci;
3005 plci->command = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003006 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 }
3008 else
3009 {
3010 cleanup_ncci_data (plci, ncci);
3011
3012 if(plci->B3_prot==2 || plci->B3_prot==3)
3013 {
3014 ncpi = &parms[0];
3015 if(ncpi->length>3)
3016 {
3017 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3018 }
3019 }
3020 nl_req_ncci(plci,N_DISC,(byte)ncci);
3021 }
3022 return 1;
3023 }
3024 }
3025 sendf(appl,
3026 _DISCONNECT_B3_R|CONFIRM,
3027 Id,
3028 Number,
3029 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003030 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031}
3032
3033byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3034{
3035 word ncci;
3036 word i;
3037
3038 ncci = (word)(Id>>16);
3039 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3040 if(plci && ncci) {
3041 plci->requested_options_conn = 0;
3042 plci->fax_connect_info_length = 0;
3043 plci->ncpi_state = 0x00;
3044 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3046 {
3047 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3048 }
3049 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050 if(i<MAX_CHANNELS_PER_PLCI) {
3051 if(plci->channels)plci->channels--;
3052 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3054
3055 ncci_free_receive_buffers (plci, ncci);
3056
3057 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058 if(plci->State == SUSPENDING){
3059 sendf(plci->appl,
3060 _FACILITY_I,
3061 Id & 0xffffL,
3062 0,
3063 "ws", (word)3, "\x03\x04\x00\x00");
3064 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3065 }
3066 plci_remove(plci);
3067 plci->State=IDLE;
3068 }
3069 }
3070 else
3071 {
3072 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3075 {
3076 ncci_free_receive_buffers (plci, ncci);
3077
3078 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3079
3080 plci->adapter->ncci_state[ncci] = IDLE;
3081 start_internal_command (Id, plci, fax_disconnect_command);
3082 return 1;
3083 }
3084 }
3085 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003086 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087}
3088
3089byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3090{
3091 NCCI *ncci_ptr;
3092 DATA_B3_DESC *data;
3093 word Info;
3094 word ncci;
3095 word i;
3096
3097 dbug(1,dprintf("data_b3_req"));
3098
3099 Info = _WRONG_IDENTIFIER;
3100 ncci = (word)(Id>>16);
3101 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3102
3103 if (plci && ncci)
3104 {
3105 Info = _WRONG_STATE;
3106 if ((a->ncci_state[ncci] == CONNECTED)
3107 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3108 {
3109 /* queue data */
3110 ncci_ptr = &(a->ncci[ncci]);
3111 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112 if (i >= MAX_DATA_B3)
3113 i -= MAX_DATA_B3;
3114 data = &(ncci_ptr->DBuffer[i]);
3115 data->Number = Number;
3116 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3117 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3118 {
3119
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07003120 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121
3122 }
3123 else
3124 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125 data->Length = GET_WORD(parms[1].info);
3126 data->Handle = GET_WORD(parms[2].info);
3127 data->Flags = GET_WORD(parms[3].info);
3128 (ncci_ptr->data_pending)++;
3129
3130 /* check for delivery confirmation */
3131 if (data->Flags & 0x0004)
3132 {
3133 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134 if (i >= MAX_DATA_ACK)
3135 i -= MAX_DATA_ACK;
3136 ncci_ptr->DataAck[i].Number = data->Number;
3137 ncci_ptr->DataAck[i].Handle = data->Handle;
3138 (ncci_ptr->data_ack_pending)++;
3139 }
3140
3141 send_data(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003142 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 }
3144 }
3145 if (appl)
3146 {
3147 if (plci)
3148 {
3149 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3150 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3151 {
3152
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07003153 TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154
3155 }
3156 }
3157 sendf(appl,
3158 _DATA_B3_R|CONFIRM,
3159 Id,
3160 Number,
3161 "ww",GET_WORD(parms[2].info),Info);
3162 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003163 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164}
3165
3166byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3167{
3168 word n;
3169 word ncci;
3170 word NCCIcode;
3171
3172 dbug(1,dprintf("data_b3_res"));
3173
3174 ncci = (word)(Id>>16);
3175 if(plci && ncci) {
3176 n = GET_WORD(parms[0].info);
3177 dbug(1,dprintf("free(%d)",n));
3178 NCCIcode = ncci | (((word) a->Id) << 8);
3179 if(n<appl->MaxBuffer &&
3180 appl->DataNCCI[n]==NCCIcode &&
3181 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182 dbug(1,dprintf("found"));
3183 appl->DataNCCI[n] = 0;
3184
3185 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186 channel_request_xon (plci, a->ncci_ch[ncci]);
3187 }
3188 channel_xmit_xon (plci);
3189
3190 if(appl->DataFlags[n] &4) {
3191 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3192 return 1;
3193 }
3194 }
3195 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003196 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197}
3198
3199byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3200{
3201 word Info;
3202 word ncci;
3203
3204 dbug(1,dprintf("reset_b3_req"));
3205
3206 Info = _WRONG_IDENTIFIER;
3207 ncci = (word)(Id>>16);
3208 if(plci && ncci)
3209 {
3210 Info = _WRONG_STATE;
3211 switch (plci->B3_prot)
3212 {
3213 case B3_ISO8208:
3214 case B3_X25_DCE:
3215 if(a->ncci_state[ncci]==CONNECTED)
3216 {
3217 nl_req_ncci(plci,N_RESET,(byte)ncci);
3218 send_req(plci);
3219 Info = GOOD;
3220 }
3221 break;
3222 case B3_TRANSPARENT:
3223 if(a->ncci_state[ncci]==CONNECTED)
3224 {
3225 start_internal_command (Id, plci, reset_b3_command);
3226 Info = GOOD;
3227 }
3228 break;
3229 }
3230 }
3231 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3232 sendf(appl,
3233 _RESET_B3_R|CONFIRM,
3234 Id,
3235 Number,
3236 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003237 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238}
3239
3240byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3241{
3242 word ncci;
3243
3244 dbug(1,dprintf("reset_b3_res"));
3245
3246 ncci = (word)(Id>>16);
3247 if(plci && ncci) {
3248 switch (plci->B3_prot)
3249 {
3250 case B3_ISO8208:
3251 case B3_X25_DCE:
3252 if(a->ncci_state[ncci]==INC_RES_PENDING)
3253 {
3254 a->ncci_state[ncci] = CONNECTED;
3255 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003256 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 }
3258 break;
3259 }
3260 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003261 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262}
3263
3264byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3265{
3266 word ncci;
3267 API_PARSE * ncpi;
3268 byte req;
3269
3270 dbug(1,dprintf("connect_b3_t90_a_res"));
3271
3272 ncci = (word)(Id>>16);
3273 if(plci && ncci) {
3274 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275 a->ncci_state[ncci] = CONNECTED;
3276 }
3277 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278 a->ncci_state[ncci] = CONNECTED;
3279
3280 req = N_CONNECT_ACK;
3281
3282 /* parms[0]==0 for CAPI original message definition! */
3283 if(parms[0].info) {
3284 ncpi = &parms[1];
3285 if(ncpi->length>2) {
3286 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3288 }
3289 }
3290 nl_req_ncci(plci,req,(byte)ncci);
3291 return 1;
3292 }
3293 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003294 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295}
3296
3297
3298byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3299{
3300 word Info=0;
3301 word i;
3302 byte tel;
3303 API_PARSE bp_parms[7];
3304
3305 if(!plci || !msg)
3306 {
3307 Info = _WRONG_IDENTIFIER;
3308 }
3309 else
3310 {
3311 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313 dbug(1,dprintf("PlciState=0x%x",plci->State));
3314 for(i=0;i<7;i++) bp_parms[i].length = 0;
3315
3316 /* check if no channel is open, no B3 connected only */
3317 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3319 {
3320 Info = _WRONG_STATE;
3321 }
3322 /* check message format and fill bp_parms pointer */
3323 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3324 {
3325 Info = _WRONG_MESSAGE_FORMAT;
3326 }
3327 else
3328 {
3329 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331 if(Id & EXT_CONTROLLER)
3332 {
3333 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3334 return 0;
3335 }
3336 plci->State=INC_CON_CONNECTED_ALERT;
3337 plci->appl = appl;
3338 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339 dump_c_ind_mask (plci);
3340 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341 { /* its quasi a connect */
3342 if(test_c_ind_mask_bit (plci, i))
3343 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3344 }
3345 }
3346
3347 api_save_msg(msg, "s", &plci->saved_msg);
3348 tel = plci->tel;
3349 if(Id & EXT_CONTROLLER)
3350 {
3351 if(tel) /* external controller in use by this PLCI */
3352 {
3353 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3354 {
3355 dbug(1,dprintf("Ext_Ctrl in use 1"));
3356 Info = _WRONG_STATE;
3357 }
3358 }
3359 else /* external controller NOT in use by this PLCI ? */
3360 {
3361 if(a->AdvSignalPLCI)
3362 {
3363 dbug(1,dprintf("Ext_Ctrl in use 2"));
3364 Info = _WRONG_STATE;
3365 }
3366 else /* activate the codec */
3367 {
3368 dbug(1,dprintf("Ext_Ctrl start"));
3369 if(AdvCodecSupport(a, plci, appl, 0) )
3370 {
3371 dbug(1,dprintf("Error in codec procedures"));
3372 Info = _WRONG_STATE;
3373 }
3374 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3375 {
3376 plci->spoofed_msg = AWAITING_SELECT_B;
3377 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3378 plci->command = 0;
3379 dbug(1,dprintf("continue if codec loaded"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003380 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 }
3382 }
3383 }
3384 }
3385 else /* external controller bit is OFF */
3386 {
3387 if(tel) /* external controller in use, need to switch off */
3388 {
3389 if(a->AdvSignalAppl==appl)
3390 {
3391 CodecIdCheck(a, plci);
3392 plci->tel = 0;
3393 plci->adv_nl = 0;
3394 dbug(1,dprintf("Ext_Ctrl disable"));
3395 }
3396 else
3397 {
3398 dbug(1,dprintf("Ext_Ctrl not requested"));
3399 }
3400 }
3401 }
3402 if (!Info)
3403 {
3404 if (plci->call_dir & CALL_DIR_OUT)
3405 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406 else if (plci->call_dir & CALL_DIR_IN)
3407 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408 start_internal_command (Id, plci, select_b_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003409 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 }
3411 }
3412 }
3413 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003414 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415}
3416
3417byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3418{
3419 word command;
3420 word i;
3421 word ncci;
3422 API_PARSE * m;
3423 API_PARSE m_parms[5];
3424 word codec;
3425 byte req;
3426 byte ch;
3427 byte dir;
3428 static byte chi[2] = {0x01,0x00};
3429 static byte lli[2] = {0x01,0x00};
3430 static byte codec_cai[2] = {0x01,0x01};
3431 static byte null_msg = {0};
3432 static API_PARSE null_parms = { 0, &null_msg };
3433 PLCI * v_plci;
3434 word Info=0;
3435
3436 dbug(1,dprintf("manufacturer_req"));
3437 for(i=0;i<5;i++) m_parms[i].length = 0;
3438
3439 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3440 Info = _WRONG_MESSAGE_FORMAT;
3441 }
3442 command = GET_WORD(parms[1].info);
3443 m = &parms[2];
3444 if (!Info)
3445 {
3446 switch(command) {
3447 case _DI_ASSIGN_PLCI:
3448 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3449 Info = _WRONG_MESSAGE_FORMAT;
3450 break;
3451 }
3452 codec = GET_WORD(m_parms[0].info);
3453 ch = m_parms[1].info[0];
3454 dir = m_parms[2].info[0];
3455 if((i=get_plci(a))) {
3456 plci = &a->plci[i-1];
3457 plci->appl = appl;
3458 plci->command = _MANUFACTURER_R;
3459 plci->m_command = command;
3460 plci->number = Number;
3461 plci->State = LOCAL_CONNECT;
3462 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3463 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3464
3465 if((ch==1 || ch==2) && (dir<=2)) {
3466 chi[1] = (byte)(0x80|ch);
3467 lli[1] = 0;
3468 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3469 switch(codec)
3470 {
3471 case 0:
3472 Info = add_b1(plci,&m_parms[3],0,0);
3473 break;
3474 case 1:
3475 add_p(plci,CAI,codec_cai);
3476 break;
3477 /* manual 'swich on' to the codec support without signalling */
3478 /* first 'assign plci' with this function, then use */
3479 case 2:
3480 if(AdvCodecSupport(a, plci, appl, 0) ) {
3481 Info = _RESOURCE_ERROR;
3482 }
3483 else {
3484 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3485 lli[1] = 0x10; /* local call codec stream */
3486 }
3487 break;
3488 }
3489
3490 plci->State = LOCAL_CONNECT;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003491 plci->manufacturer = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 plci->command = _MANUFACTURER_R;
3493 plci->m_command = command;
3494 plci->number = Number;
3495
3496 if(!Info)
3497 {
3498 add_p(plci,LLI,lli);
3499 add_p(plci,CHI,chi);
3500 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3501 sig_req(plci,ASSIGN,DSIG_ID);
3502
3503 if(!codec)
3504 {
3505 Info = add_b23(plci,&m_parms[3]);
3506 if(!Info)
3507 {
3508 nl_req_ncci(plci,ASSIGN,0);
3509 send_req(plci);
3510 }
3511 }
3512 if(!Info)
3513 {
3514 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3515 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3516 {
3517 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3518 plci->spoofed_msg = AWAITING_MANUF_CON;
3519 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3520 plci->command = 0;
3521 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003522 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 }
3524 if(dir==1) {
3525 sig_req(plci,CALL_REQ,0);
3526 }
3527 else if(!dir){
3528 sig_req(plci,LISTEN_REQ,0);
3529 }
3530 send_req(plci);
3531 }
3532 else
3533 {
3534 sendf(appl,
3535 _MANUFACTURER_R|CONFIRM,
3536 Id,
3537 Number,
3538 "dww",_DI_MANU_ID,command,Info);
3539 return 2;
3540 }
3541 }
3542 }
3543 }
3544 else Info = _OUT_OF_PLCI;
3545 break;
3546
3547 case _DI_IDI_CTRL:
3548 if(!plci)
3549 {
3550 Info = _WRONG_IDENTIFIER;
3551 break;
3552 }
3553 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3554 Info = _WRONG_MESSAGE_FORMAT;
3555 break;
3556 }
3557 req = m_parms[0].info[0];
3558 plci->command = _MANUFACTURER_R;
3559 plci->m_command = command;
3560 plci->number = Number;
3561 if(req==CALL_REQ)
3562 {
3563 plci->b_channel = getChannel(&m_parms[1]);
3564 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3565 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3566 {
3567 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3568 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3569 plci->command = 0;
3570 break;
3571 }
3572 }
3573 else if(req==LAW_REQ)
3574 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003575 plci->cr_enquiry = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576 }
3577 add_ss(plci,FTY,&m_parms[1]);
3578 sig_req(plci,req,0);
3579 send_req(plci);
3580 if(req==HANGUP)
3581 {
3582 if (plci->NL.Id && !plci->nl_remove_id)
3583 {
3584 if (plci->channels)
3585 {
3586 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3587 {
3588 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3589 {
3590 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3591 cleanup_ncci_data (plci, ncci);
3592 nl_req_ncci(plci,N_DISC,(byte)ncci);
3593 }
3594 }
3595 }
3596 mixer_remove (plci);
3597 nl_req_ncci(plci,REMOVE,0);
3598 send_req(plci);
3599 }
3600 }
3601 break;
3602
3603 case _DI_SIG_CTRL:
3604 /* signalling control for loop activation B-channel */
3605 if(!plci)
3606 {
3607 Info = _WRONG_IDENTIFIER;
3608 break;
3609 }
3610 if(m->length){
3611 plci->command = _MANUFACTURER_R;
3612 plci->number = Number;
3613 add_ss(plci,FTY,m);
3614 sig_req(plci,SIG_CTRL,0);
3615 send_req(plci);
3616 }
3617 else Info = _WRONG_MESSAGE_FORMAT;
3618 break;
3619
3620 case _DI_RXT_CTRL:
3621 /* activation control for receiver/transmitter B-channel */
3622 if(!plci)
3623 {
3624 Info = _WRONG_IDENTIFIER;
3625 break;
3626 }
3627 if(m->length){
3628 plci->command = _MANUFACTURER_R;
3629 plci->number = Number;
3630 add_ss(plci,FTY,m);
3631 sig_req(plci,DSP_CTRL,0);
3632 send_req(plci);
3633 }
3634 else Info = _WRONG_MESSAGE_FORMAT;
3635 break;
3636
3637 case _DI_ADV_CODEC:
3638 case _DI_DSP_CTRL:
3639 /* TEL_CTRL commands to support non standard adjustments: */
3640 /* Ring on/off, Handset micro volume, external micro vol. */
3641 /* handset+external speaker volume, receiver+transm. gain,*/
3642 /* handsfree on (hookinfo off), set mixer command */
3643
3644 if(command == _DI_ADV_CODEC)
3645 {
3646 if(!a->AdvCodecPLCI) {
3647 Info = _WRONG_STATE;
3648 break;
3649 }
3650 v_plci = a->AdvCodecPLCI;
3651 }
3652 else
3653 {
3654 if (plci
3655 && (m->length >= 3)
3656 && (m->info[1] == 0x1c)
3657 && (m->info[2] >= 1))
3658 {
3659 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3660 {
3661 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3662 {
3663 Info = _WRONG_STATE;
3664 break;
3665 }
3666 a->adv_voice_coef_length = m->info[2] - 1;
3667 if (a->adv_voice_coef_length > m->length - 3)
3668 a->adv_voice_coef_length = (byte)(m->length - 3);
3669 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3670 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3671 for (i = 0; i < a->adv_voice_coef_length; i++)
3672 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3673 if (plci->B1_facilities & B1_FACILITY_VOICE)
3674 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3675 break;
3676 }
3677 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3678 {
3679 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3680 {
3681 Info = _FACILITY_NOT_SUPPORTED;
3682 break;
3683 }
3684
3685 plci->dtmf_parameter_length = m->info[2] - 1;
3686 if (plci->dtmf_parameter_length > m->length - 3)
3687 plci->dtmf_parameter_length = (byte)(m->length - 3);
3688 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3689 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3690 for (i = 0; i < plci->dtmf_parameter_length; i++)
3691 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3692 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3693 dtmf_parameter_write (plci);
3694 break;
3695
3696 }
3697 }
3698 v_plci = plci;
3699 }
3700
3701 if(!v_plci)
3702 {
3703 Info = _WRONG_IDENTIFIER;
3704 break;
3705 }
3706 if(m->length){
3707 add_ss(v_plci,FTY,m);
3708 sig_req(v_plci,TEL_CTRL,0);
3709 send_req(v_plci);
3710 }
3711 else Info = _WRONG_MESSAGE_FORMAT;
3712
3713 break;
3714
3715 case _DI_OPTIONS_REQUEST:
3716 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3717 Info = _WRONG_MESSAGE_FORMAT;
3718 break;
3719 }
3720 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3721 {
3722 Info = _FACILITY_NOT_SUPPORTED;
3723 break;
3724 }
3725 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3726 break;
3727
3728
3729
3730 default:
3731 Info = _WRONG_MESSAGE_FORMAT;
3732 break;
3733 }
3734 }
3735
3736 sendf(appl,
3737 _MANUFACTURER_R|CONFIRM,
3738 Id,
3739 Number,
3740 "dww",_DI_MANU_ID,command,Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003741 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742}
3743
3744
3745byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3746{
3747 word indication;
3748
3749 API_PARSE m_parms[3];
3750 API_PARSE *ncpi;
3751 API_PARSE fax_parms[9];
3752 word i;
3753 byte len;
3754
3755
3756 dbug(1,dprintf("manufacturer_res"));
3757
3758 if ((msg[0].length == 0)
3759 || (msg[1].length == 0)
3760 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3761 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003762 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 }
3764 indication = GET_WORD(msg[1].info);
3765 switch (indication)
3766 {
3767
3768 case _DI_NEGOTIATE_B3:
3769 if(!plci)
3770 break;
3771 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3772 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3773 {
3774 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3775 break;
3776 }
3777 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3778 {
3779 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3780 break;
3781 }
3782 ncpi = &m_parms[1];
3783 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3784 if (plci->fax_connect_info_length < len)
3785 {
3786 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3787 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3788 }
3789 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3790 {
3791 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3792 }
3793 else
3794 {
3795 if (plci->fax_connect_info_length <= len)
3796 plci->fax_connect_info_buffer[len] = 0;
3797 len += 1 + plci->fax_connect_info_buffer[len];
3798 if (plci->fax_connect_info_length <= len)
3799 plci->fax_connect_info_buffer[len] = 0;
3800 len += 1 + plci->fax_connect_info_buffer[len];
3801 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3802 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3803 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3804 for (i = 0; i < fax_parms[7].length; i++)
3805 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3806 }
3807 plci->fax_connect_info_length = len;
3808 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3809 start_internal_command (Id, plci, fax_edata_ack_command);
3810 break;
3811
3812 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003813 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814}
3815
3816/*------------------------------------------------------------------*/
3817/* IDI callback function */
3818/*------------------------------------------------------------------*/
3819
3820void callback(ENTITY * e)
3821{
3822 DIVA_CAPI_ADAPTER * a;
3823 APPL * appl;
3824 PLCI * plci;
3825 CAPI_MSG *m;
3826 word i, j;
3827 byte rc;
3828 byte ch;
3829 byte req;
3830 byte global_req;
3831 int no_cancel_rc;
3832
3833 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3834 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3835
3836 a = &(adapter[(byte)e->user[0]]);
3837 plci = &(a->plci[e->user[1]]);
3838 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3839
3840 /*
3841 If new protocol code and new XDI is used then CAPI should work
3842 fully in accordance with IDI cpec an look on callback field instead
3843 of Rc field for return codes.
3844 */
3845 if (((e->complete == 0xff) && no_cancel_rc) ||
3846 (e->Rc && !no_cancel_rc)) {
3847 rc = e->Rc;
3848 ch = e->RcCh;
3849 req = e->Req;
3850 e->Rc = 0;
3851
3852 if (e->user[0] & 0x8000)
3853 {
3854 /*
3855 If REMOVE request was sent then we have to wait until
3856 return code with Id set to zero arrives.
3857 All other return codes should be ignored.
3858 */
3859 if (req == REMOVE)
3860 {
3861 if (e->Id)
3862 {
3863 dbug(1,dprintf("cancel RC in REMOVE state"));
3864 return;
3865 }
3866 channel_flow_control_remove (plci);
3867 for (i = 0; i < 256; i++)
3868 {
3869 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3870 a->FlowControlIdTable[i] = 0;
3871 }
3872 plci->nl_remove_id = 0;
3873 if (plci->rx_dma_descriptor > 0) {
3874 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3875 plci->rx_dma_descriptor = 0;
3876 }
3877 }
3878 if (rc == OK_FC)
3879 {
3880 a->FlowControlIdTable[ch] = e->Id;
3881 a->FlowControlSkipTable[ch] = 0;
3882
3883 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3884 a->ch_flow_plci[ch] = plci->Id;
3885 plci->nl_req = 0;
3886 }
3887 else
3888 {
3889 /*
3890 Cancel return codes self, if feature was requested
3891 */
3892 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3893 a->FlowControlIdTable[ch] = 0;
3894 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3895 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3896 return;
3897 }
3898 }
3899
3900 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3901 {
3902 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3903 if (ch == e->ReqCh)
3904 plci->nl_req = 0;
3905 }
3906 else
3907 plci->nl_req = 0;
3908 }
3909 if (plci->nl_req)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003910 control_rc (plci, 0, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 else
3912 {
3913 if (req == N_XON)
3914 {
3915 channel_x_on (plci, ch);
3916 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003917 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 }
3919 else
3920 {
3921 if (plci->nl_global_req)
3922 {
3923 global_req = plci->nl_global_req;
3924 plci->nl_global_req = 0;
3925 if (rc != ASSIGN_OK) {
3926 e->Id = 0;
3927 if (plci->rx_dma_descriptor > 0) {
3928 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3929 plci->rx_dma_descriptor = 0;
3930 }
3931 }
3932 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003933 control_rc (plci, 0, rc, ch, global_req, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 }
3935 else if (plci->data_sent)
3936 {
3937 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003938 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 plci->NL.XNum = 1;
3940 data_rc (plci, ch);
3941 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003942 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 }
3944 else
3945 {
3946 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003947 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 }
3949 }
3950 }
3951 }
3952 else
3953 {
3954 /*
3955 If REMOVE request was sent then we have to wait until
3956 return code with Id set to zero arrives.
3957 All other return codes should be ignored.
3958 */
3959 if (req == REMOVE)
3960 {
3961 if (e->Id)
3962 {
3963 dbug(1,dprintf("cancel RC in REMOVE state"));
3964 return;
3965 }
3966 plci->sig_remove_id = 0;
3967 }
3968 plci->sig_req = 0;
3969 if (plci->sig_global_req)
3970 {
3971 global_req = plci->sig_global_req;
3972 plci->sig_global_req = 0;
3973 if (rc != ASSIGN_OK)
3974 e->Id = 0;
3975 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003976 control_rc (plci, 0, rc, ch, global_req, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 }
3978 else
3979 {
3980 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003981 control_rc (plci, req, rc, ch, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 }
3983 }
3984 /*
3985 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3986 same callback. Also if new XDI and protocol code used then jump
3987 direct to finish.
3988 */
3989 if (no_cancel_rc) {
3990 channel_xmit_xon(plci);
3991 goto capi_callback_suffix;
3992 }
3993 }
3994
3995 channel_xmit_xon(plci);
3996
3997 if (e->Ind) {
3998 if (e->user[0] &0x8000) {
3999 byte Ind = e->Ind & 0x0f;
4000 byte Ch = e->IndCh;
4001 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4002 (a->ch_flow_plci[Ch] == plci->Id)) {
4003 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4004 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4005 }
4006 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4007 }
4008 nl_ind(plci);
4009 if ((e->RNR != 1) &&
4010 (a->ch_flow_plci[Ch] == plci->Id) &&
4011 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4012 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4013 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4014 }
4015 } else {
4016 sig_ind(plci);
4017 }
4018 e->Ind = 0;
4019 }
4020
4021capi_callback_suffix:
4022
4023 while (!plci->req_in
4024 && !plci->internal_command
4025 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4026 {
4027 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4028
4029 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4030
4031 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4032 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4033 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4034 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4035 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4036 {
4037 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4038 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4039 }
4040 else
4041 {
4042 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4043 }
4044 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4045 {
4046 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4047 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4048 }
4049 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4050 {
4051 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4052 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4053 }
4054 i = api_put (appl, m);
4055 if (i != 0)
4056 {
4057 if (m->header.command == _DATA_B3_R)
4058
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07004059 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
4061 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4062 break;
4063 }
4064
4065 if (plci->li_notify_update)
4066 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004067 plci->li_notify_update = false;
4068 mixer_notify_update (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 }
4070
4071 }
4072 send_data(plci);
4073 send_req(plci);
4074}
4075
4076
4077void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4078{
4079 dword Id;
4080 dword rId;
4081 word Number;
4082 word Info=0;
4083 word i;
4084 word ncci;
4085 DIVA_CAPI_ADAPTER * a;
4086 APPL * appl;
4087 PLCI * rplci;
4088 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4089 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4090
4091 if (!plci) {
4092 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4093 return;
4094 }
4095 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4096 if(plci->req_in!=plci->req_out)
4097 {
4098 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4099 {
4100 dbug(1,dprintf("req_1return"));
4101 return;
4102 }
4103 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4104 }
4105 plci->req_in = plci->req_in_start = plci->req_out = 0;
4106 dbug(1,dprintf("control_rc"));
4107
4108 appl = plci->appl;
4109 a = plci->adapter;
4110 ncci = a->ch_ncci[ch];
4111 if(appl)
4112 {
4113 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4114 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4115 Number = plci->number;
4116 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));
4117 dbug(1,dprintf("channels=0x%x",plci->channels));
4118 if (plci_remove_check(plci))
4119 return;
4120 if(req==REMOVE && rc==ASSIGN_OK)
4121 {
4122 sig_req(plci,HANGUP,0);
4123 sig_req(plci,REMOVE,0);
4124 send_req(plci);
4125 }
4126 if(plci->command)
4127 {
4128 switch(plci->command)
4129 {
4130 case C_HOLD_REQ:
4131 dbug(1,dprintf("HoldRC=0x%x",rc));
4132 SSparms[1] = (byte)S_HOLD;
4133 if(rc!=OK)
4134 {
4135 plci->SuppState = IDLE;
4136 Info = 0x2001;
4137 }
4138 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4139 break;
4140
4141 case C_RETRIEVE_REQ:
4142 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4143 SSparms[1] = (byte)S_RETRIEVE;
4144 if(rc!=OK)
4145 {
4146 plci->SuppState = CALL_HELD;
4147 Info = 0x2001;
4148 }
4149 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4150 break;
4151
4152 case _INFO_R:
4153 dbug(1,dprintf("InfoRC=0x%x",rc));
4154 if(rc!=OK) Info=_WRONG_STATE;
4155 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4156 break;
4157
4158 case _CONNECT_R:
4159 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4160 if (plci->State == INC_DIS_PENDING)
4161 break;
4162 if(plci->Sig.Id!=0xff)
4163 {
4164 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4165 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4166 {
4167 dbug(1,dprintf("No more IDs/Call_Req failed"));
4168 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4169 plci_remove(plci);
4170 plci->State = IDLE;
4171 break;
4172 }
4173 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4174 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4175 }
4176 else /* D-ch activation */
4177 {
4178 if (rc != ASSIGN_OK)
4179 {
4180 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4181 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4182 plci_remove(plci);
4183 plci->State = IDLE;
4184 break;
4185 }
4186 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4187 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4188 plci->State = INC_ACT_PENDING;
4189 }
4190 break;
4191
4192 case _CONNECT_I|RESPONSE:
4193 if (plci->State != INC_DIS_PENDING)
4194 plci->State = INC_CON_ACCEPT;
4195 break;
4196
4197 case _DISCONNECT_R:
4198 if (plci->State == INC_DIS_PENDING)
4199 break;
4200 if(plci->Sig.Id!=0xff)
4201 {
4202 plci->State = OUTG_DIS_PENDING;
4203 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4204 }
4205 break;
4206
4207 case SUSPEND_REQ:
4208 break;
4209
4210 case RESUME_REQ:
4211 break;
4212
4213 case _CONNECT_B3_R:
4214 if(rc!=OK)
4215 {
4216 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4217 break;
4218 }
4219 ncci = get_ncci (plci, ch, 0);
4220 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4221 plci->channels++;
4222 if(req==N_RESET)
4223 {
4224 a->ncci_state[ncci] = INC_ACT_PENDING;
4225 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4226 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4227 }
4228 else
4229 {
4230 a->ncci_state[ncci] = OUTG_CON_PENDING;
4231 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4232 }
4233 break;
4234
4235 case _CONNECT_B3_I|RESPONSE:
4236 break;
4237
4238 case _RESET_B3_R:
4239/* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4240 break;
4241
4242 case _DISCONNECT_B3_R:
4243 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4244 break;
4245
4246 case _MANUFACTURER_R:
4247 break;
4248
4249 case PERM_LIST_REQ:
4250 if(rc!=OK)
4251 {
4252 Info = _WRONG_IDENTIFIER;
4253 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4254 plci_remove(plci);
4255 }
4256 else
4257 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4258 break;
4259
4260 default:
4261 break;
4262 }
4263 plci->command = 0;
4264 }
4265 else if (plci->internal_command)
4266 {
4267 switch(plci->internal_command)
4268 {
4269 case BLOCK_PLCI:
4270 return;
4271
4272 case GET_MWI_STATE:
4273 if(rc==OK) /* command supported, wait for indication */
4274 {
4275 return;
4276 }
4277 plci_remove(plci);
4278 break;
4279
4280 /* Get Supported Services */
4281 case GETSERV_REQ_PEND:
4282 if(rc==OK) /* command supported, wait for indication */
4283 {
4284 break;
4285 }
4286 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4287 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4288 plci_remove(plci);
4289 break;
4290
4291 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4292 case INTERR_NUMBERS_REQ_PEND:
4293 case CF_START_PEND: /* Call Forwarding Start pending */
4294 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4295 case CCBS_REQUEST_REQ_PEND:
4296 case CCBS_DEACTIVATE_REQ_PEND:
4297 case CCBS_INTERROGATE_REQ_PEND:
4298 switch(plci->internal_command)
4299 {
4300 case INTERR_DIVERSION_REQ_PEND:
4301 SSparms[1] = S_INTERROGATE_DIVERSION;
4302 break;
4303 case INTERR_NUMBERS_REQ_PEND:
4304 SSparms[1] = S_INTERROGATE_NUMBERS;
4305 break;
4306 case CF_START_PEND:
4307 SSparms[1] = S_CALL_FORWARDING_START;
4308 break;
4309 case CF_STOP_PEND:
4310 SSparms[1] = S_CALL_FORWARDING_STOP;
4311 break;
4312 case CCBS_REQUEST_REQ_PEND:
4313 SSparms[1] = S_CCBS_REQUEST;
4314 break;
4315 case CCBS_DEACTIVATE_REQ_PEND:
4316 SSparms[1] = S_CCBS_DEACTIVATE;
4317 break;
4318 case CCBS_INTERROGATE_REQ_PEND:
4319 SSparms[1] = S_CCBS_INTERROGATE;
4320 break;
4321 }
4322 if(global_req==ASSIGN)
4323 {
4324 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4325 return;
4326 }
4327 if(!plci->appl) break;
4328 if(rc==ISDN_GUARD_REJ)
4329 {
4330 Info = _CAPI_GUARD_ERROR;
4331 }
4332 else if(rc!=OK)
4333 {
4334 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4335 }
4336 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4337 plci->number,"wws",Info,(word)3,SSparms);
4338 if(Info) plci_remove(plci);
4339 break;
4340
4341 /* 3pty conference pending */
4342 case PTY_REQ_PEND:
4343 if(!plci->relatedPTYPLCI) break;
4344 rplci = plci->relatedPTYPLCI;
4345 SSparms[1] = plci->ptyState;
4346 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4347 if(rplci->tel) rId|=EXT_CONTROLLER;
4348 if(rc!=OK)
4349 {
4350 Info = 0x300E; /* not supported */
4351 plci->relatedPTYPLCI = NULL;
4352 plci->ptyState = 0;
4353 }
4354 sendf(rplci->appl,
4355 _FACILITY_R|CONFIRM,
4356 rId,
4357 plci->number,
4358 "wws",Info,(word)3,SSparms);
4359 break;
4360
4361 /* Explicit Call Transfer pending */
4362 case ECT_REQ_PEND:
4363 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4364 if(!plci->relatedPTYPLCI) break;
4365 rplci = plci->relatedPTYPLCI;
4366 SSparms[1] = S_ECT;
4367 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4368 if(rplci->tel) rId|=EXT_CONTROLLER;
4369 if(rc!=OK)
4370 {
4371 Info = 0x300E; /* not supported */
4372 plci->relatedPTYPLCI = NULL;
4373 plci->ptyState = 0;
4374 }
4375 sendf(rplci->appl,
4376 _FACILITY_R|CONFIRM,
4377 rId,
4378 plci->number,
4379 "wws",Info,(word)3,SSparms);
4380 break;
4381
4382 case _MANUFACTURER_R:
4383 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4384 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4385 {
4386 dbug(1,dprintf("No more IDs"));
4387 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4388 plci_remove(plci); /* after codec init, internal codec commands pending */
4389 }
4390 break;
4391
4392 case _CONNECT_R:
4393 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4394 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4395 {
4396 dbug(1,dprintf("No more IDs"));
4397 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4398 plci_remove(plci); /* after codec init, internal codec commands pending */
4399 }
4400 break;
4401
4402 case PERM_COD_HOOK: /* finished with Hook_Ind */
4403 return;
4404
4405 case PERM_COD_CALL:
4406 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4407 plci->internal_command = PERM_COD_CONN_PEND;
4408 return;
4409
4410 case PERM_COD_ASSIGN:
4411 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4412 if(rc!=ASSIGN_OK) break;
4413 sig_req(plci,CALL_REQ,0);
4414 send_req(plci);
4415 plci->internal_command = PERM_COD_CALL;
4416 return;
4417
4418 /* Null Call Reference Request pending */
4419 case C_NCR_FAC_REQ:
4420 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4421 if(global_req==ASSIGN)
4422 {
4423 if(rc==ASSIGN_OK)
4424 {
4425 return;
4426 }
4427 else
4428 {
4429 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004430 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 plci_remove(plci);
4432 }
4433 }
4434 else if(req==NCR_FACILITY)
4435 {
4436 if(rc==OK)
4437 {
4438 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4439 }
4440 else
4441 {
4442 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004443 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444 }
4445 plci_remove(plci);
4446 }
4447 break;
4448
4449 case HOOK_ON_REQ:
4450 if(plci->channels)
4451 {
4452 if(a->ncci_state[ncci]==CONNECTED)
4453 {
4454 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4455 cleanup_ncci_data (plci, ncci);
4456 nl_req_ncci(plci,N_DISC,(byte)ncci);
4457 }
4458 break;
4459 }
4460 break;
4461
4462 case HOOK_OFF_REQ:
4463 if (plci->State == INC_DIS_PENDING)
4464 break;
4465 sig_req(plci,CALL_REQ,0);
4466 send_req(plci);
4467 plci->State=OUTG_CON_PENDING;
4468 break;
4469
4470
4471 case MWI_ACTIVATE_REQ_PEND:
4472 case MWI_DEACTIVATE_REQ_PEND:
4473 if(global_req == ASSIGN && rc==ASSIGN_OK)
4474 {
4475 dbug(1,dprintf("MWI_REQ assigned"));
4476 return;
4477 }
4478 else if(rc!=OK)
4479 {
4480 if(rc==WRONG_IE)
4481 {
4482 Info = 0x2007; /* Illegal message parameter coding */
4483 dbug(1,dprintf("MWI_REQ invalid parameter"));
4484 }
4485 else
4486 {
4487 Info = 0x300B; /* not supported */
4488 dbug(1,dprintf("MWI_REQ not supported"));
4489 }
4490 /* 0x3010: Request not allowed in this state */
4491 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4492
4493 }
4494 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4495 {
4496 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4497 }
4498 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4499
4500 if(plci->cr_enquiry)
4501 {
4502 sendf(plci->appl,
4503 _FACILITY_R|CONFIRM,
4504 Id&0xf,
4505 plci->number,
4506 "wws",Info,(word)3,SSparms);
4507 if(rc!=OK) plci_remove(plci);
4508 }
4509 else
4510 {
4511 sendf(plci->appl,
4512 _FACILITY_R|CONFIRM,
4513 Id,
4514 plci->number,
4515 "wws",Info,(word)3,SSparms);
4516 }
4517 break;
4518
4519 case CONF_BEGIN_REQ_PEND:
4520 case CONF_ADD_REQ_PEND:
4521 case CONF_SPLIT_REQ_PEND:
4522 case CONF_DROP_REQ_PEND:
4523 case CONF_ISOLATE_REQ_PEND:
4524 case CONF_REATTACH_REQ_PEND:
4525 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4526 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4527 rplci = plci;
4528 rId = Id;
4529 switch(plci->internal_command)
4530 {
4531 case CONF_BEGIN_REQ_PEND:
4532 SSparms[1] = S_CONF_BEGIN;
4533 break;
4534 case CONF_ADD_REQ_PEND:
4535 SSparms[1] = S_CONF_ADD;
4536 rplci = plci->relatedPTYPLCI;
4537 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4538 break;
4539 case CONF_SPLIT_REQ_PEND:
4540 SSparms[1] = S_CONF_SPLIT;
4541 break;
4542 case CONF_DROP_REQ_PEND:
4543 SSparms[1] = S_CONF_DROP;
4544 break;
4545 case CONF_ISOLATE_REQ_PEND:
4546 SSparms[1] = S_CONF_ISOLATE;
4547 break;
4548 case CONF_REATTACH_REQ_PEND:
4549 SSparms[1] = S_CONF_REATTACH;
4550 break;
4551 }
4552
4553 if(rc!=OK)
4554 {
4555 Info = 0x300E; /* not supported */
4556 plci->relatedPTYPLCI = NULL;
4557 plci->ptyState = 0;
4558 }
4559 sendf(rplci->appl,
4560 _FACILITY_R|CONFIRM,
4561 rId,
4562 plci->number,
4563 "wws",Info,(word)3,SSparms);
4564 break;
4565
4566 case VSWITCH_REQ_PEND:
4567 if(rc!=OK)
4568 {
4569 if(plci->relatedPTYPLCI)
4570 {
4571 plci->relatedPTYPLCI->vswitchstate=0;
4572 plci->relatedPTYPLCI->vsprot=0;
4573 plci->relatedPTYPLCI->vsprotdialect=0;
4574 }
4575 plci->vswitchstate=0;
4576 plci->vsprot=0;
4577 plci->vsprotdialect=0;
4578 }
4579 else
4580 {
4581 if(plci->relatedPTYPLCI &&
4582 plci->vswitchstate==1 &&
4583 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4584 plci->vswitchstate=3;
4585 }
4586 break;
4587
4588 /* Call Deflection Request pending (SSCT) */
4589 case CD_REQ_PEND:
4590 SSparms[1] = S_CALL_DEFLECTION;
4591 if(rc!=OK)
4592 {
4593 Info = 0x300E; /* not supported */
4594 plci->appl->CDEnable = 0;
4595 }
4596 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4597 plci->number,"wws",Info,(word)3,SSparms);
4598 break;
4599
4600 case RTP_CONNECT_B3_REQ_COMMAND_2:
4601 if (rc == OK)
4602 {
4603 ncci = get_ncci (plci, ch, 0);
4604 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4605 plci->channels++;
4606 a->ncci_state[ncci] = OUTG_CON_PENDING;
4607 }
4608
4609 default:
4610 if (plci->internal_command_queue[0])
4611 {
4612 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4613 if (plci->internal_command)
4614 return;
4615 }
4616 break;
4617 }
4618 next_internal_command (Id, plci);
4619 }
4620 }
4621 else /* appl==0 */
4622 {
4623 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4624 if(plci->tel) Id|=EXT_CONTROLLER;
4625
4626 switch(plci->internal_command)
4627 {
4628 case BLOCK_PLCI:
4629 return;
4630
4631 case START_L1_SIG_ASSIGN_PEND:
4632 case REM_L1_SIG_ASSIGN_PEND:
4633 if(global_req == ASSIGN)
4634 {
4635 break;
4636 }
4637 else
4638 {
4639 dbug(1,dprintf("***L1 Req rem PLCI"));
4640 plci->internal_command = 0;
4641 sig_req(plci,REMOVE,0);
4642 send_req(plci);
4643 }
4644 break;
4645
4646 /* Call Deflection Request pending, just no appl ptr assigned */
4647 case CD_REQ_PEND:
4648 SSparms[1] = S_CALL_DEFLECTION;
4649 if(rc!=OK)
4650 {
4651 Info = 0x300E; /* not supported */
4652 }
4653 for(i=0; i<max_appl; i++)
4654 {
4655 if(application[i].CDEnable)
4656 {
4657 if(!application[i].Id) application[i].CDEnable = 0;
4658 else
4659 {
4660 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4661 plci->number,"wws",Info,(word)3,SSparms);
4662 if(Info) application[i].CDEnable = 0;
4663 }
4664 }
4665 }
4666 plci->internal_command = 0;
4667 break;
4668
4669 case PERM_COD_HOOK: /* finished with Hook_Ind */
4670 return;
4671
4672 case PERM_COD_CALL:
4673 plci->internal_command = PERM_COD_CONN_PEND;
4674 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4675 return;
4676
4677 case PERM_COD_ASSIGN:
4678 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4679 plci->internal_command = 0;
4680 if(rc!=ASSIGN_OK) break;
4681 plci->internal_command = PERM_COD_CALL;
4682 sig_req(plci,CALL_REQ,0);
4683 send_req(plci);
4684 return;
4685
4686 case LISTEN_SIG_ASSIGN_PEND:
4687 if(rc == ASSIGN_OK)
4688 {
4689 plci->internal_command = 0;
4690 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4691 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4692 sig_req(plci,INDICATE_REQ,0);
4693 send_req(plci);
4694 }
4695 else
4696 {
4697 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4698 a->listen_active--;
4699 plci_remove(plci);
4700 plci->State = IDLE;
4701 }
4702 break;
4703
4704 case USELAW_REQ:
4705 if(global_req == ASSIGN)
4706 {
4707 if (rc==ASSIGN_OK)
4708 {
4709 sig_req(plci,LAW_REQ,0);
4710 send_req(plci);
4711 dbug(1,dprintf("Auto-Law assigned"));
4712 }
4713 else
4714 {
4715 dbug(1,dprintf("Auto-Law assign failed"));
4716 a->automatic_law = 3;
4717 plci->internal_command = 0;
4718 a->automatic_lawPLCI = NULL;
4719 }
4720 break;
4721 }
4722 else if(req == LAW_REQ && rc==OK)
4723 {
4724 dbug(1,dprintf("Auto-Law initiated"));
4725 a->automatic_law = 2;
4726 plci->internal_command = 0;
4727 }
4728 else
4729 {
4730 dbug(1,dprintf("Auto-Law not supported"));
4731 a->automatic_law = 3;
4732 plci->internal_command = 0;
4733 sig_req(plci,REMOVE,0);
4734 send_req(plci);
4735 a->automatic_lawPLCI = NULL;
4736 }
4737 break;
4738 }
4739 plci_remove_check(plci);
4740 }
4741}
4742
4743void data_rc(PLCI * plci, byte ch)
4744{
4745 dword Id;
4746 DIVA_CAPI_ADAPTER * a;
4747 NCCI *ncci_ptr;
4748 DATA_B3_DESC *data;
4749 word ncci;
4750
4751 if (plci->appl)
4752 {
4753 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4754 a = plci->adapter;
4755 ncci = a->ch_ncci[ch];
4756 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4757 {
4758 ncci_ptr = &(a->ncci[ncci]);
4759 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4760 if (ncci_ptr->data_pending)
4761 {
4762 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4763 if (!(data->Flags &4) && a->ncci_state[ncci])
4764 {
4765 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4766 if(plci->tel) Id|=EXT_CONTROLLER;
4767 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4768 "ww",data->Handle,0);
4769 }
4770 (ncci_ptr->data_out)++;
4771 if (ncci_ptr->data_out == MAX_DATA_B3)
4772 ncci_ptr->data_out = 0;
4773 (ncci_ptr->data_pending)--;
4774 }
4775 }
4776 }
4777}
4778
4779void data_ack(PLCI * plci, byte ch)
4780{
4781 dword Id;
4782 DIVA_CAPI_ADAPTER * a;
4783 NCCI *ncci_ptr;
4784 word ncci;
4785
4786 a = plci->adapter;
4787 ncci = a->ch_ncci[ch];
4788 ncci_ptr = &(a->ncci[ncci]);
4789 if (ncci_ptr->data_ack_pending)
4790 {
4791 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4792 {
4793 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4794 if(plci->tel) Id|=EXT_CONTROLLER;
4795 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4796 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4797 }
4798 (ncci_ptr->data_ack_out)++;
4799 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4800 ncci_ptr->data_ack_out = 0;
4801 (ncci_ptr->data_ack_pending)--;
4802 }
4803}
4804
4805void sig_ind(PLCI * plci)
4806{
4807 dword x_Id;
4808 dword Id;
4809 dword rId;
4810 word Number = 0;
4811 word i;
4812 word cip;
4813 dword cip_mask;
4814 byte *ie;
4815 DIVA_CAPI_ADAPTER * a;
4816 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4817#define MAXPARMSIDS 31
4818 byte * parms[MAXPARMSIDS];
4819 byte * add_i[4];
4820 byte * multi_fac_parms[MAX_MULTI_IE];
4821 byte * multi_pi_parms [MAX_MULTI_IE];
4822 byte * multi_ssext_parms [MAX_MULTI_IE];
4823 byte * multi_CiPN_parms [MAX_MULTI_IE];
4824
4825 byte * multi_vswitch_parms [MAX_MULTI_IE];
4826
4827 byte ai_len;
4828 byte *esc_chi = "";
4829 byte *esc_law = "";
4830 byte *pty_cai = "";
4831 byte *esc_cr = "";
4832 byte *esc_profile = "";
4833
4834 byte facility[256];
4835 PLCI * tplci = NULL;
4836 byte chi[] = "\x02\x18\x01";
4837 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4838 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4839 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4840 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4841 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4842 /* (see Info_Mask Bit 4, first IE. then the message type) */
4843 word parms_id[] =
4844 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4845 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4846 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4847 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4848 /* 14 FTY repl by ESC_CHI */
4849 /* 18 PI repl by ESC_LAW */
4850 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4851 word multi_fac_id[] = {1, FTY};
4852 word multi_pi_id[] = {1, PI};
4853 word multi_CiPN_id[] = {1, OAD};
4854 word multi_ssext_id[] = {1, ESC_SSEXT};
4855
4856 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4857
4858 byte * cau;
4859 word ncci;
4860 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4861 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4862 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4863 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004864 byte force_mt_info = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004865 byte dir;
4866 dword d;
4867 word w;
4868
4869 a = plci->adapter;
4870 Id = ((word)plci->Id<<8)|a->Id;
4871 PUT_WORD(&SS_Ind[4],0x0000);
4872
4873 if (plci->sig_remove_id)
4874 {
4875 plci->Sig.RNR = 2; /* discard */
4876 dbug(1,dprintf("SIG discard while remove pending"));
4877 return;
4878 }
4879 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4880 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4881 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4882 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4883 {
4884 plci->Sig.RNR = 1;
4885 return;
4886 }
4887 if(plci->Sig.Ind==HANGUP && plci->channels)
4888 {
4889 plci->Sig.RNR = 1;
4890 plci->hangup_flow_ctrl_timer++;
4891 /* recover the network layer after timeout */
4892 if(plci->hangup_flow_ctrl_timer==100)
4893 {
4894 dbug(1,dprintf("Exceptional disc"));
4895 plci->Sig.RNR = 0;
4896 plci->hangup_flow_ctrl_timer = 0;
4897 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4898 {
4899 if (a->ncci_plci[ncci] == plci->Id)
4900 {
4901 cleanup_ncci_data (plci, ncci);
4902 if(plci->channels)plci->channels--;
4903 if (plci->appl)
4904 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4905 }
4906 }
4907 if (plci->appl)
4908 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4909 plci_remove(plci);
4910 plci->State=IDLE;
4911 }
4912 return;
4913 }
4914
4915 /* do first parse the info with no OAD in, because OAD will be converted */
4916 /* first the multiple facility IE, then mult. progress ind. */
4917 /* then the parameters for the info_ind + conn_ind */
4918 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4919 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4920 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4921
4922 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4923
4924 IndParse(plci,parms_id,parms,0);
4925 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4926 esc_chi = parms[14];
4927 esc_law = parms[18];
4928 pty_cai = parms[24];
4929 esc_cr = parms[25];
4930 esc_profile = parms[27];
4931 if(esc_cr[0] && plci)
4932 {
4933 if(plci->cr_enquiry && plci->appl)
4934 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004935 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936 /* d = MANU_ID */
4937 /* w = m_command */
4938 /* b = total length */
4939 /* b = indication type */
4940 /* b = length of all IEs */
4941 /* b = IE1 */
4942 /* S = IE1 length + cont. */
4943 /* b = IE2 */
4944 /* S = IE2 lenght + cont. */
4945 sendf(plci->appl,
4946 _MANUFACTURER_I,
4947 Id,
4948 0,
4949 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4950 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);
4951 }
4952 }
4953 /* create the additional info structure */
4954 add_i[1] = parms[15]; /* KEY of additional info */
4955 add_i[2] = parms[11]; /* UUI of additional info */
4956 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4957
4958 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4959 /* indication returns by the card if requested by the function */
4960 /* AutomaticLaw() after driver init */
4961 if (a->automatic_law<4)
4962 {
4963 if(esc_law[0]){
4964 if(esc_law[2]){
4965 dbug(0,dprintf("u-Law selected"));
4966 a->u_law = 1;
4967 }
4968 else {
4969 dbug(0,dprintf("a-Law selected"));
4970 a->u_law = 0;
4971 }
4972 a->automatic_law = 4;
4973 if(plci==a->automatic_lawPLCI) {
4974 plci->internal_command = 0;
4975 sig_req(plci,REMOVE,0);
4976 send_req(plci);
4977 a->automatic_lawPLCI = NULL;
4978 }
4979 }
4980 if (esc_profile[0])
4981 {
4982 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4983 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4984 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4985 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4986
4987 a->profile.Global_Options &= 0x000000ffL;
4988 a->profile.B1_Protocols &= 0x000003ffL;
4989 a->profile.B2_Protocols &= 0x00001fdfL;
4990 a->profile.B3_Protocols &= 0x000000b7L;
4991
4992 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4993 GL_BCHANNEL_OPERATION_SUPPORTED;
4994 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4995 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4996 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4997 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4998 a->man_profile.private_options = 0;
4999
5000 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5001 {
5002 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5003 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5004 }
5005
5006
5007 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5008 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5009 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5010 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5011
5012
5013 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5014 a->man_profile.private_options |= 1L << PRIVATE_T38;
5015
5016
5017 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5018 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5019
5020
5021 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5022 a->man_profile.private_options |= 1L << PRIVATE_V18;
5023
5024
5025 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5026 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5027
5028
5029 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5030 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5031
5032
5033 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5034 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5035
5036
5037 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5038 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5039
5040
5041 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5042 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5043
5044 }
5045 else
5046 {
5047 a->profile.Global_Options &= 0x0000007fL;
5048 a->profile.B1_Protocols &= 0x000003dfL;
5049 a->profile.B2_Protocols &= 0x00001adfL;
5050 a->profile.B3_Protocols &= 0x000000b7L;
5051 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5052 }
5053 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5054 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5055 {
5056 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5057 }
5058 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5059 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5060 UnMapController (a->Id), a->profile.Global_Options,
5061 a->profile.B1_Protocols, a->profile.B2_Protocols,
5062 a->profile.B3_Protocols, a->manufacturer_features));
5063 }
5064 /* codec plci for the handset/hook state support is just an internal id */
5065 if(plci!=a->AdvCodecPLCI)
5066 {
5067 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5068 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5069 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5070 SendInfo(plci,Id, parms, force_mt_info);
5071
5072 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5073
5074 }
5075
5076 /* switch the codec to the b-channel */
5077 if(esc_chi[0] && plci && !plci->SuppState){
5078 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5079 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5080 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5081 if(plci->tel==ADV_VOICE && plci->appl) {
5082 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5083 }
5084 }
5085
5086 if(plci->appl) Number = plci->appl->Number++;
5087
5088 switch(plci->Sig.Ind) {
5089 /* Response to Get_Supported_Services request */
5090 case S_SUPPORTED:
5091 dbug(1,dprintf("S_Supported"));
5092 if(!plci->appl) break;
5093 if(pty_cai[0]==4)
5094 {
5095 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5096 }
5097 else
5098 {
5099 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5100 }
5101 PUT_WORD (&CF_Ind[1], 0);
5102 PUT_WORD (&CF_Ind[4], 0);
5103 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5104 plci_remove(plci);
5105 break;
5106
5107 /* Supplementary Service rejected */
5108 case S_SERVICE_REJ:
5109 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5110 if(!pty_cai[0]) break;
5111 switch (pty_cai[5])
5112 {
5113 case ECT_EXECUTE:
5114 case THREE_PTY_END:
5115 case THREE_PTY_BEGIN:
5116 if(!plci->relatedPTYPLCI) break;
5117 tplci = plci->relatedPTYPLCI;
5118 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5119 if(tplci->tel) rId|=EXT_CONTROLLER;
5120 if(pty_cai[5]==ECT_EXECUTE)
5121 {
5122 PUT_WORD(&SS_Ind[1],S_ECT);
5123
5124 plci->vswitchstate=0;
5125 plci->relatedPTYPLCI->vswitchstate=0;
5126
5127 }
5128 else
5129 {
5130 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5131 }
5132 if(pty_cai[2]!=0xff)
5133 {
5134 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5135 }
5136 else
5137 {
5138 PUT_WORD(&SS_Ind[4],0x300E);
5139 }
5140 plci->relatedPTYPLCI = NULL;
5141 plci->ptyState = 0;
5142 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5143 break;
5144
5145 case CALL_DEFLECTION:
5146 if(pty_cai[2]!=0xff)
5147 {
5148 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5149 }
5150 else
5151 {
5152 PUT_WORD(&SS_Ind[4],0x300E);
5153 }
5154 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5155 for(i=0; i<max_appl; i++)
5156 {
5157 if(application[i].CDEnable)
5158 {
5159 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005160 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005161 }
5162 }
5163 break;
5164
5165 case DEACTIVATION_DIVERSION:
5166 case ACTIVATION_DIVERSION:
5167 case DIVERSION_INTERROGATE_CFU:
5168 case DIVERSION_INTERROGATE_CFB:
5169 case DIVERSION_INTERROGATE_CFNR:
5170 case DIVERSION_INTERROGATE_NUM:
5171 case CCBS_REQUEST:
5172 case CCBS_DEACTIVATE:
5173 case CCBS_INTERROGATE:
5174 if(!plci->appl) break;
5175 if(pty_cai[2]!=0xff)
5176 {
5177 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5178 }
5179 else
5180 {
5181 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5182 }
5183 switch (pty_cai[5])
5184 {
5185 case DEACTIVATION_DIVERSION:
5186 dbug(1,dprintf("Deact_Div"));
5187 Interr_Err_Ind[0]=0x9;
5188 Interr_Err_Ind[3]=0x6;
5189 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5190 break;
5191 case ACTIVATION_DIVERSION:
5192 dbug(1,dprintf("Act_Div"));
5193 Interr_Err_Ind[0]=0x9;
5194 Interr_Err_Ind[3]=0x6;
5195 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5196 break;
5197 case DIVERSION_INTERROGATE_CFU:
5198 case DIVERSION_INTERROGATE_CFB:
5199 case DIVERSION_INTERROGATE_CFNR:
5200 dbug(1,dprintf("Interr_Div"));
5201 Interr_Err_Ind[0]=0xa;
5202 Interr_Err_Ind[3]=0x7;
5203 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5204 break;
5205 case DIVERSION_INTERROGATE_NUM:
5206 dbug(1,dprintf("Interr_Num"));
5207 Interr_Err_Ind[0]=0xa;
5208 Interr_Err_Ind[3]=0x7;
5209 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5210 break;
5211 case CCBS_REQUEST:
5212 dbug(1,dprintf("CCBS Request"));
5213 Interr_Err_Ind[0]=0xd;
5214 Interr_Err_Ind[3]=0xa;
5215 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5216 break;
5217 case CCBS_DEACTIVATE:
5218 dbug(1,dprintf("CCBS Deactivate"));
5219 Interr_Err_Ind[0]=0x9;
5220 Interr_Err_Ind[3]=0x6;
5221 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5222 break;
5223 case CCBS_INTERROGATE:
5224 dbug(1,dprintf("CCBS Interrogate"));
5225 Interr_Err_Ind[0]=0xb;
5226 Interr_Err_Ind[3]=0x8;
5227 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5228 break;
5229 }
5230 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5231 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5232 plci_remove(plci);
5233 break;
5234 case ACTIVATION_MWI:
5235 case DEACTIVATION_MWI:
5236 if(pty_cai[5]==ACTIVATION_MWI)
5237 {
5238 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5239 }
5240 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5241
5242 if(pty_cai[2]!=0xff)
5243 {
5244 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5245 }
5246 else
5247 {
5248 PUT_WORD(&SS_Ind[4],0x300E);
5249 }
5250
5251 if(plci->cr_enquiry)
5252 {
5253 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5254 plci_remove(plci);
5255 }
5256 else
5257 {
5258 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5259 }
5260 break;
5261 case CONF_ADD: /* ERROR */
5262 case CONF_BEGIN:
5263 case CONF_DROP:
5264 case CONF_ISOLATE:
5265 case CONF_REATTACH:
5266 CONF_Ind[0]=9;
5267 CONF_Ind[3]=6;
5268 switch(pty_cai[5])
5269 {
5270 case CONF_BEGIN:
5271 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5272 plci->ptyState = 0;
5273 break;
5274 case CONF_DROP:
5275 CONF_Ind[0]=5;
5276 CONF_Ind[3]=2;
5277 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5278 plci->ptyState = CONNECTED;
5279 break;
5280 case CONF_ISOLATE:
5281 CONF_Ind[0]=5;
5282 CONF_Ind[3]=2;
5283 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5284 plci->ptyState = CONNECTED;
5285 break;
5286 case CONF_REATTACH:
5287 CONF_Ind[0]=5;
5288 CONF_Ind[3]=2;
5289 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5290 plci->ptyState = CONNECTED;
5291 break;
5292 case CONF_ADD:
5293 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5294 plci->relatedPTYPLCI = NULL;
5295 tplci=plci->relatedPTYPLCI;
5296 if(tplci) tplci->ptyState = CONNECTED;
5297 plci->ptyState = CONNECTED;
5298 break;
5299 }
5300
5301 if(pty_cai[2]!=0xff)
5302 {
5303 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5304 }
5305 else
5306 {
5307 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5308 within the required time */
5309 }
5310
5311 PUT_DWORD(&CONF_Ind[6],0x0);
5312 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5313 break;
5314 }
5315 break;
5316
5317 /* Supplementary Service indicates success */
5318 case S_SERVICE:
5319 dbug(1,dprintf("Service_Ind"));
5320 PUT_WORD (&CF_Ind[4], 0);
5321 switch (pty_cai[5])
5322 {
5323 case THREE_PTY_END:
5324 case THREE_PTY_BEGIN:
5325 case ECT_EXECUTE:
5326 if(!plci->relatedPTYPLCI) break;
5327 tplci = plci->relatedPTYPLCI;
5328 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5329 if(tplci->tel) rId|=EXT_CONTROLLER;
5330 if(pty_cai[5]==ECT_EXECUTE)
5331 {
5332 PUT_WORD(&SS_Ind[1],S_ECT);
5333
5334 if(plci->vswitchstate!=3)
5335 {
5336
5337 plci->ptyState = IDLE;
5338 plci->relatedPTYPLCI = NULL;
5339 plci->ptyState = 0;
5340
5341 }
5342
5343 dbug(1,dprintf("ECT OK"));
5344 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5345
5346
5347
5348 }
5349 else
5350 {
5351 switch (plci->ptyState)
5352 {
5353 case S_3PTY_BEGIN:
5354 plci->ptyState = CONNECTED;
5355 dbug(1,dprintf("3PTY ON"));
5356 break;
5357
5358 case S_3PTY_END:
5359 plci->ptyState = IDLE;
5360 plci->relatedPTYPLCI = NULL;
5361 plci->ptyState = 0;
5362 dbug(1,dprintf("3PTY OFF"));
5363 break;
5364 }
5365 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5366 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5367 }
5368 break;
5369
5370 case CALL_DEFLECTION:
5371 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5372 for(i=0; i<max_appl; i++)
5373 {
5374 if(application[i].CDEnable)
5375 {
5376 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005377 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378 }
5379 }
5380 break;
5381
5382 case DEACTIVATION_DIVERSION:
5383 case ACTIVATION_DIVERSION:
5384 if(!plci->appl) break;
5385 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5386 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5387 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5388 plci_remove(plci);
5389 break;
5390
5391 case DIVERSION_INTERROGATE_CFU:
5392 case DIVERSION_INTERROGATE_CFB:
5393 case DIVERSION_INTERROGATE_CFNR:
5394 case DIVERSION_INTERROGATE_NUM:
5395 case CCBS_REQUEST:
5396 case CCBS_DEACTIVATE:
5397 case CCBS_INTERROGATE:
5398 if(!plci->appl) break;
5399 switch (pty_cai[5])
5400 {
5401 case DIVERSION_INTERROGATE_CFU:
5402 case DIVERSION_INTERROGATE_CFB:
5403 case DIVERSION_INTERROGATE_CFNR:
5404 dbug(1,dprintf("Interr_Div"));
5405 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5406 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5407 break;
5408 case DIVERSION_INTERROGATE_NUM:
5409 dbug(1,dprintf("Interr_Num"));
5410 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5411 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5412 break;
5413 case CCBS_REQUEST:
5414 dbug(1,dprintf("CCBS Request"));
5415 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5416 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5417 break;
5418 case CCBS_DEACTIVATE:
5419 dbug(1,dprintf("CCBS Deactivate"));
5420 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5421 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5422 break;
5423 case CCBS_INTERROGATE:
5424 dbug(1,dprintf("CCBS Interrogate"));
5425 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5426 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5427 break;
5428 }
5429 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5430 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5431 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5432 plci_remove(plci);
5433 break;
5434
5435 case ACTIVATION_MWI:
5436 case DEACTIVATION_MWI:
5437 if(pty_cai[5]==ACTIVATION_MWI)
5438 {
5439 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5440 }
5441 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5442 if(plci->cr_enquiry)
5443 {
5444 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5445 plci_remove(plci);
5446 }
5447 else
5448 {
5449 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5450 }
5451 break;
5452 case MWI_INDICATION:
5453 if(pty_cai[0]>=0x12)
5454 {
5455 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5456 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5457 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5458 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5459 {
5460 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5461 {
5462 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5463 plci_remove(plci);
5464 return;
5465 }
5466 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5467 pty_cai[0]=0;
5468 }
5469 else
5470 {
5471 for(i=0; i<max_appl; i++)
5472 {
5473 if(a->Notification_Mask[i]&SMASK_MWI)
5474 {
5475 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5476 pty_cai[0]=0;
5477 }
5478 }
5479 }
5480
5481 if(!pty_cai[0])
5482 { /* acknowledge */
5483 facility[2]= 0; /* returncode */
5484 }
5485 else facility[2]= 0xff;
5486 }
5487 else
5488 {
5489 /* reject */
5490 facility[2]= 0xff; /* returncode */
5491 }
5492 facility[0]= 2;
5493 facility[1]= MWI_RESPONSE; /* Function */
5494 add_p(plci,CAI,facility);
5495 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5496 sig_req(plci,S_SERVICE,0);
5497 send_req(plci);
5498 plci->command = 0;
5499 next_internal_command (Id, plci);
5500 break;
5501 case CONF_ADD: /* OK */
5502 case CONF_BEGIN:
5503 case CONF_DROP:
5504 case CONF_ISOLATE:
5505 case CONF_REATTACH:
5506 case CONF_PARTYDISC:
5507 CONF_Ind[0]=9;
5508 CONF_Ind[3]=6;
5509 switch(pty_cai[5])
5510 {
5511 case CONF_BEGIN:
5512 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5513 if(pty_cai[0]==6)
5514 {
5515 d=pty_cai[6];
5516 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5517 }
5518 else
5519 {
5520 PUT_DWORD(&CONF_Ind[6],0x0);
5521 }
5522 break;
5523 case CONF_ISOLATE:
5524 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5525 CONF_Ind[0]=5;
5526 CONF_Ind[3]=2;
5527 break;
5528 case CONF_REATTACH:
5529 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5530 CONF_Ind[0]=5;
5531 CONF_Ind[3]=2;
5532 break;
5533 case CONF_DROP:
5534 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5535 CONF_Ind[0]=5;
5536 CONF_Ind[3]=2;
5537 break;
5538 case CONF_ADD:
5539 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5540 d=pty_cai[6];
5541 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5542 tplci=plci->relatedPTYPLCI;
5543 if(tplci) tplci->ptyState = CONNECTED;
5544 break;
5545 case CONF_PARTYDISC:
5546 CONF_Ind[0]=7;
5547 CONF_Ind[3]=4;
5548 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5549 d=pty_cai[6];
5550 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5551 break;
5552 }
5553 plci->ptyState = CONNECTED;
5554 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5555 break;
5556 case CCBS_INFO_RETAIN:
5557 case CCBS_ERASECALLLINKAGEID:
5558 case CCBS_STOP_ALERTING:
5559 CONF_Ind[0]=5;
5560 CONF_Ind[3]=2;
5561 switch(pty_cai[5])
5562 {
5563 case CCBS_INFO_RETAIN:
5564 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5565 break;
5566 case CCBS_STOP_ALERTING:
5567 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5568 break;
5569 case CCBS_ERASECALLLINKAGEID:
5570 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5571 CONF_Ind[0]=7;
5572 CONF_Ind[3]=4;
5573 CONF_Ind[6]=0;
5574 CONF_Ind[7]=0;
5575 break;
5576 }
5577 w=pty_cai[6];
5578 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5579
5580 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5581 {
5582 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5583 }
5584 else
5585 {
5586 for(i=0; i<max_appl; i++)
5587 if(a->Notification_Mask[i]&SMASK_CCBS)
5588 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5589 }
5590 break;
5591 }
5592 break;
5593 case CALL_HOLD_REJ:
5594 cau = parms[7];
5595 if(cau)
5596 {
5597 i = _L3_CAUSE | cau[2];
5598 if(cau[2]==0) i = 0x3603;
5599 }
5600 else
5601 {
5602 i = 0x3603;
5603 }
5604 PUT_WORD(&SS_Ind[1],S_HOLD);
5605 PUT_WORD(&SS_Ind[4],i);
5606 if(plci->SuppState == HOLD_REQUEST)
5607 {
5608 plci->SuppState = IDLE;
5609 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5610 }
5611 break;
5612
5613 case CALL_HOLD_ACK:
5614 if(plci->SuppState == HOLD_REQUEST)
5615 {
5616 plci->SuppState = CALL_HELD;
5617 CodecIdCheck(a, plci);
5618 start_internal_command (Id, plci, hold_save_command);
5619 }
5620 break;
5621
5622 case CALL_RETRIEVE_REJ:
5623 cau = parms[7];
5624 if(cau)
5625 {
5626 i = _L3_CAUSE | cau[2];
5627 if(cau[2]==0) i = 0x3603;
5628 }
5629 else
5630 {
5631 i = 0x3603;
5632 }
5633 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5634 PUT_WORD(&SS_Ind[4],i);
5635 if(plci->SuppState == RETRIEVE_REQUEST)
5636 {
5637 plci->SuppState = CALL_HELD;
5638 CodecIdCheck(a, plci);
5639 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5640 }
5641 break;
5642
5643 case CALL_RETRIEVE_ACK:
5644 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5645 if(plci->SuppState == RETRIEVE_REQUEST)
5646 {
5647 plci->SuppState = IDLE;
5648 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5649 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5650 if(plci->tel)
5651 {
5652 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5653 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5654 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5655 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5656 {
5657 dbug(1,dprintf("Get B-ch"));
5658 start_internal_command (Id, plci, retrieve_restore_command);
5659 }
5660 else
5661 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5662 }
5663 else
5664 start_internal_command (Id, plci, retrieve_restore_command);
5665 }
5666 break;
5667
5668 case INDICATE_IND:
5669 if(plci->State != LISTENING) {
5670 sig_req(plci,HANGUP,0);
5671 send_req(plci);
5672 break;
5673 }
5674 cip = find_cip(a,parms[4],parms[6]);
5675 cip_mask = 1L<<cip;
5676 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5677 clear_c_ind_mask (plci);
5678 if (!remove_started && !a->adapter_disabled)
5679 {
5680 set_c_ind_mask_bit (plci, MAX_APPL);
5681 group_optimization(a, plci);
5682 for(i=0; i<max_appl; i++) {
5683 if(application[i].Id
5684 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5685 && CPN_filter_ok(parms[0],a,i)
5686 && test_group_ind_mask_bit (plci, i) ) {
5687 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5688 set_c_ind_mask_bit (plci, i);
5689 dump_c_ind_mask (plci);
5690 plci->State = INC_CON_PENDING;
5691 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5692 CALL_DIR_IN | CALL_DIR_ANSWER;
5693 if(esc_chi[0]) {
5694 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5695 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5696 }
5697 /* if a listen on the ext controller is done, check if hook states */
5698 /* are supported or if just a on board codec must be activated */
5699 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5700 if(a->profile.Global_Options & HANDSET)
5701 plci->tel = ADV_VOICE;
5702 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5703 plci->tel = CODEC;
5704 if(plci->tel) Id|=EXT_CONTROLLER;
5705 a->codec_listen[i] = plci;
5706 }
5707
5708 sendf(&application[i],_CONNECT_I,Id,0,
5709 "wSSSSSSSbSSSSS", cip, /* CIP */
5710 parms[0], /* CalledPartyNumber */
5711 multi_CiPN_parms[0], /* CallingPartyNumber */
5712 parms[2], /* CalledPartySubad */
5713 parms[3], /* CallingPartySubad */
5714 parms[4], /* BearerCapability */
5715 parms[5], /* LowLC */
5716 parms[6], /* HighLC */
5717 ai_len, /* nested struct add_i */
5718 add_i[0], /* B channel info */
5719 add_i[1], /* keypad facility */
5720 add_i[2], /* user user data */
5721 add_i[3], /* nested facility */
5722 multi_CiPN_parms[1] /* second CiPN(SCR) */
5723 );
5724 SendSSExtInd(&application[i],
5725 plci,
5726 Id,
5727 multi_ssext_parms);
5728 SendSetupInfo(&application[i],
5729 plci,
5730 Id,
5731 parms,
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005732 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733 }
5734 }
5735 clear_c_ind_mask_bit (plci, MAX_APPL);
5736 dump_c_ind_mask (plci);
5737 }
5738 if(c_ind_mask_empty (plci)) {
5739 sig_req(plci,HANGUP,0);
5740 send_req(plci);
5741 plci->State = IDLE;
5742 }
5743 plci->notifiedcall = 0;
5744 a->listen_active--;
5745 listen_check(a);
5746 break;
5747
5748 case CALL_PEND_NOTIFY:
5749 plci->notifiedcall = 1;
5750 listen_check(a);
5751 break;
5752
5753 case CALL_IND:
5754 case CALL_CON:
5755 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5756 {
5757 if(plci->internal_command==PERM_COD_CONN_PEND)
5758 {
5759 if(plci->State==ADVANCED_VOICE_NOSIG)
5760 {
5761 dbug(1,dprintf("***Codec OK"));
5762 if(a->AdvSignalPLCI)
5763 {
5764 tplci = a->AdvSignalPLCI;
5765 if(tplci->spoofed_msg)
5766 {
5767 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5768 tplci->command = 0;
5769 tplci->internal_command = 0;
5770 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5771 switch (tplci->spoofed_msg)
5772 {
5773 case CALL_RES:
5774 tplci->command = _CONNECT_I|RESPONSE;
5775 api_load_msg (&tplci->saved_msg, saved_parms);
5776 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5777 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5778 {
5779 /* early B3 connect (CIP mask bit 9) no release after a disc */
5780 add_p(tplci,LLI,"\x01\x01");
5781 }
5782 add_s(tplci, CONN_NR, &saved_parms[2]);
5783 add_s(tplci, LLC, &saved_parms[4]);
5784 add_ai(tplci, &saved_parms[5]);
5785 tplci->State = INC_CON_ACCEPT;
5786 sig_req(tplci, CALL_RES,0);
5787 send_req(tplci);
5788 break;
5789
5790 case AWAITING_SELECT_B:
5791 dbug(1,dprintf("Select_B continue"));
5792 start_internal_command (x_Id, tplci, select_b_command);
5793 break;
5794
5795 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5796 if(!tplci->Sig.Id)
5797 {
5798 dbug(1,dprintf("No SigID!"));
5799 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5800 plci_remove(tplci);
5801 break;
5802 }
5803 tplci->command = _MANUFACTURER_R;
5804 api_load_msg (&tplci->saved_msg, saved_parms);
5805 dir = saved_parms[2].info[0];
5806 if(dir==1) {
5807 sig_req(tplci,CALL_REQ,0);
5808 }
5809 else if(!dir){
5810 sig_req(tplci,LISTEN_REQ,0);
5811 }
5812 send_req(tplci);
5813 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5814 break;
5815
5816 case (CALL_REQ|AWAITING_MANUF_CON):
5817 sig_req(tplci,CALL_REQ,0);
5818 send_req(tplci);
5819 break;
5820
5821 case CALL_REQ:
5822 if(!tplci->Sig.Id)
5823 {
5824 dbug(1,dprintf("No SigID!"));
5825 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5826 plci_remove(tplci);
5827 break;
5828 }
5829 tplci->command = _CONNECT_R;
5830 api_load_msg (&tplci->saved_msg, saved_parms);
5831 add_s(tplci,CPN,&saved_parms[1]);
5832 add_s(tplci,DSA,&saved_parms[3]);
5833 add_ai(tplci,&saved_parms[9]);
5834 sig_req(tplci,CALL_REQ,0);
5835 send_req(tplci);
5836 break;
5837
5838 case CALL_RETRIEVE:
5839 tplci->command = C_RETRIEVE_REQ;
5840 sig_req(tplci,CALL_RETRIEVE,0);
5841 send_req(tplci);
5842 break;
5843 }
5844 tplci->spoofed_msg = 0;
5845 if (tplci->internal_command == 0)
5846 next_internal_command (x_Id, tplci);
5847 }
5848 }
5849 next_internal_command (Id, plci);
5850 break;
5851 }
5852 dbug(1,dprintf("***Codec Hook Init Req"));
5853 plci->internal_command = PERM_COD_HOOK;
5854 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5855 sig_req(plci,TEL_CTRL,0);
5856 send_req(plci);
5857 }
5858 }
5859 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5860 && plci->State!=INC_ACT_PENDING)
5861 {
5862 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5863 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5864 {
5865 chi[2] = plci->b_channel;
5866 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5867 }
5868 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5869 plci->State = INC_ACT_PENDING;
5870 }
5871 break;
5872
5873 case TEL_CTRL:
5874 Number = 0;
5875 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5876 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5877 switch (ie[1]&0x91) {
5878 case 0x80: /* hook off */
5879 case 0x81:
5880 if(plci->internal_command==PERM_COD_HOOK)
5881 {
5882 dbug(1,dprintf("init:hook_off"));
5883 plci->hook_state = ie[1];
5884 next_internal_command (Id, plci);
5885 break;
5886 }
5887 else /* ignore doubled hook indications */
5888 {
5889 if( ((plci->hook_state)&0xf0)==0x80)
5890 {
5891 dbug(1,dprintf("ignore hook"));
5892 break;
5893 }
5894 plci->hook_state = ie[1]&0x91;
5895 }
5896 /* check for incoming call pending */
5897 /* and signal '+'.Appl must decide */
5898 /* with connect_res if call must */
5899 /* accepted or not */
5900 for(i=0, tplci=NULL;i<max_appl;i++){
5901 if(a->codec_listen[i]
5902 && (a->codec_listen[i]->State==INC_CON_PENDING
5903 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5904 tplci = a->codec_listen[i];
5905 tplci->appl = &application[i];
5906 }
5907 }
5908 /* no incoming call, do outgoing call */
5909 /* and signal '+' if outg. setup */
5910 if(!a->AdvSignalPLCI && !tplci){
5911 if((i=get_plci(a))) {
5912 a->AdvSignalPLCI = &a->plci[i-1];
5913 tplci = a->AdvSignalPLCI;
5914 tplci->tel = ADV_VOICE;
5915 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5916 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5917 /* early B3 connect (CIP mask bit 9) no release after a disc */
5918 add_p(tplci,LLI,"\x01\x01");
5919 }
5920 add_p(tplci, CAI, voice_cai);
5921 add_p(tplci, OAD, a->TelOAD);
5922 add_p(tplci, OSA, a->TelOSA);
5923 add_p(tplci,SHIFT|6,NULL);
5924 add_p(tplci,SIN,"\x02\x01\x00");
5925 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5926 sig_req(tplci,ASSIGN,DSIG_ID);
5927 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5928 a->AdvSignalPLCI->command = 0;
5929 tplci->appl = a->AdvSignalAppl;
5930 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5931 send_req(tplci);
5932 }
5933
5934 }
5935
5936 if(!tplci) break;
5937 Id = ((word)tplci->Id<<8)|a->Id;
5938 Id|=EXT_CONTROLLER;
5939 sendf(tplci->appl,
5940 _FACILITY_I,
5941 Id,
5942 0,
5943 "ws", (word)0, "\x01+");
5944 break;
5945
5946 case 0x90: /* hook on */
5947 case 0x91:
5948 if(plci->internal_command==PERM_COD_HOOK)
5949 {
5950 dbug(1,dprintf("init:hook_on"));
5951 plci->hook_state = ie[1]&0x91;
5952 next_internal_command (Id, plci);
5953 break;
5954 }
5955 else /* ignore doubled hook indications */
5956 {
5957 if( ((plci->hook_state)&0xf0)==0x90) break;
5958 plci->hook_state = ie[1]&0x91;
5959 }
5960 /* hangup the adv. voice call and signal '-' to the appl */
5961 if(a->AdvSignalPLCI) {
5962 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5963 if(plci->tel) Id|=EXT_CONTROLLER;
5964 sendf(a->AdvSignalAppl,
5965 _FACILITY_I,
5966 Id,
5967 0,
5968 "ws", (word)0, "\x01-");
5969 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5970 a->AdvSignalPLCI->command = 0;
5971 sig_req(a->AdvSignalPLCI,HANGUP,0);
5972 send_req(a->AdvSignalPLCI);
5973 }
5974 break;
5975 }
5976 }
5977 break;
5978
5979 case RESUME:
5980 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5981 PUT_WORD(&resume_cau[4],GOOD);
5982 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5983 break;
5984
5985 case SUSPEND:
5986 clear_c_ind_mask (plci);
5987
5988 if (plci->NL.Id && !plci->nl_remove_id) {
5989 mixer_remove (plci);
5990 nl_req_ncci(plci,REMOVE,0);
5991 }
5992 if (!plci->sig_remove_id) {
5993 plci->internal_command = 0;
5994 sig_req(plci,REMOVE,0);
5995 }
5996 send_req(plci);
5997 if(!plci->channels) {
5998 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5999 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6000 }
6001 break;
6002
6003 case SUSPEND_REJ:
6004 break;
6005
6006 case HANGUP:
6007 plci->hangup_flow_ctrl_timer=0;
6008 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6009 cau = parms[7];
6010 if(cau) {
6011 i = _L3_CAUSE | cau[2];
6012 if(cau[2]==0) i = 0;
6013 else if(cau[2]==8) i = _L1_ERROR;
6014 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6015 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6016 }
6017 else {
6018 i = _L3_ERROR;
6019 }
6020
6021 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6022 {
6023 for(i=0; i<max_appl; i++)
6024 {
6025 if(test_c_ind_mask_bit (plci, i))
6026 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6027 }
6028 }
6029 else
6030 {
6031 clear_c_ind_mask (plci);
6032 }
6033 if(!plci->appl)
6034 {
6035 if (plci->State == LISTENING)
6036 {
6037 plci->notifiedcall=0;
6038 a->listen_active--;
6039 }
6040 plci->State = INC_DIS_PENDING;
6041 if(c_ind_mask_empty (plci))
6042 {
6043 plci->State = IDLE;
6044 if (plci->NL.Id && !plci->nl_remove_id)
6045 {
6046 mixer_remove (plci);
6047 nl_req_ncci(plci,REMOVE,0);
6048 }
6049 if (!plci->sig_remove_id)
6050 {
6051 plci->internal_command = 0;
6052 sig_req(plci,REMOVE,0);
6053 }
6054 send_req(plci);
6055 }
6056 }
6057 else
6058 {
6059 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6060 /* result in a second HANGUP! Don't generate another */
6061 /* DISCONNECT */
6062 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6063 {
6064 if(plci->State==RESUMING)
6065 {
6066 PUT_WORD(&resume_cau[4],i);
6067 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6068 }
6069 plci->State = INC_DIS_PENDING;
6070 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6071 }
6072 }
6073 break;
6074
6075 case SSEXT_IND:
6076 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6077 break;
6078
6079 case VSWITCH_REQ:
6080 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6081 break;
6082 case VSWITCH_IND:
6083 if(plci->relatedPTYPLCI &&
6084 plci->vswitchstate==3 &&
6085 plci->relatedPTYPLCI->vswitchstate==3 &&
6086 parms[MAXPARMSIDS-1][0])
6087 {
6088 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6089 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6090 send_req(plci->relatedPTYPLCI);
6091 }
6092 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6093 break;
6094
6095 }
6096}
6097
6098
6099static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6100{
6101 word i;
6102 byte * ie;
6103 word Info_Number;
6104 byte * Info_Element;
6105 word Info_Mask = 0;
6106
6107 dbug(1,dprintf("SetupInfo"));
6108
6109 for(i=0; i<MAXPARMSIDS; i++) {
6110 ie = parms[i];
6111 Info_Number = 0;
6112 Info_Element = ie;
6113 if(ie[0]) {
6114 switch(i) {
6115 case 0:
6116 dbug(1,dprintf("CPN "));
6117 Info_Number = 0x0070;
6118 Info_Mask = 0x80;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006119 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120 break;
6121 case 8: /* display */
6122 dbug(1,dprintf("display(%d)",i));
6123 Info_Number = 0x0028;
6124 Info_Mask = 0x04;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006125 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126 break;
6127 case 16: /* Channel Id */
6128 dbug(1,dprintf("CHI"));
6129 Info_Number = 0x0018;
6130 Info_Mask = 0x100;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006131 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132 mixer_set_bchannel_id (plci, Info_Element);
6133 break;
6134 case 19: /* Redirected Number */
6135 dbug(1,dprintf("RDN"));
6136 Info_Number = 0x0074;
6137 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006138 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139 break;
6140 case 20: /* Redirected Number extended */
6141 dbug(1,dprintf("RDX"));
6142 Info_Number = 0x0073;
6143 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006144 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145 break;
6146 case 22: /* Redirecing Number */
6147 dbug(1,dprintf("RIN"));
6148 Info_Number = 0x0076;
6149 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006150 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151 break;
6152 default:
6153 Info_Number = 0;
6154 break;
6155 }
6156 }
6157
6158 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6159 Info_Number = 0x8000 |5;
6160 Info_Mask = 0x10;
6161 Info_Element = "";
6162 }
6163
6164 if(Info_Sent_Flag && Info_Number){
6165 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6166 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6167 }
6168 }
6169 }
6170}
6171
6172
6173void SendInfo(PLCI * plci, dword Id, byte * * parms, byte iesent)
6174{
6175 word i;
6176 word j;
6177 word k;
6178 byte * ie;
6179 word Info_Number;
6180 byte * Info_Element;
6181 word Info_Mask = 0;
6182 static byte charges[5] = {4,0,0,0,0};
6183 static byte cause[] = {0x02,0x80,0x00};
6184 APPL *appl;
6185
6186 dbug(1,dprintf("InfoParse "));
6187
6188 if(
6189 !plci->appl
6190 && !plci->State
6191 && plci->Sig.Ind!=NCR_FACILITY
6192 )
6193 {
6194 dbug(1,dprintf("NoParse "));
6195 return;
6196 }
6197 cause[2] = 0;
6198 for(i=0; i<MAXPARMSIDS; i++) {
6199 ie = parms[i];
6200 Info_Number = 0;
6201 Info_Element = ie;
6202 if(ie[0]) {
6203 switch(i) {
6204 case 0:
6205 dbug(1,dprintf("CPN "));
6206 Info_Number = 0x0070;
6207 Info_Mask = 0x80;
6208 break;
6209 case 7: /* ESC_CAU */
6210 dbug(1,dprintf("cau(0x%x)",ie[2]));
6211 Info_Number = 0x0008;
6212 Info_Mask = 0x00;
6213 cause[2] = ie[2];
6214 Info_Element = NULL;
6215 break;
6216 case 8: /* display */
6217 dbug(1,dprintf("display(%d)",i));
6218 Info_Number = 0x0028;
6219 Info_Mask = 0x04;
6220 break;
6221 case 9: /* Date display */
6222 dbug(1,dprintf("date(%d)",i));
6223 Info_Number = 0x0029;
6224 Info_Mask = 0x02;
6225 break;
6226 case 10: /* charges */
6227 for(j=0;j<4;j++) charges[1+j] = 0;
6228 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6229 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6230 Info_Number = 0x4000;
6231 Info_Mask = 0x40;
6232 Info_Element = charges;
6233 break;
6234 case 11: /* user user info */
6235 dbug(1,dprintf("uui"));
6236 Info_Number = 0x007E;
6237 Info_Mask = 0x08;
6238 break;
6239 case 12: /* congestion receiver ready */
6240 dbug(1,dprintf("clRDY"));
6241 Info_Number = 0x00B0;
6242 Info_Mask = 0x08;
6243 Info_Element = "";
6244 break;
6245 case 13: /* congestion receiver not ready */
6246 dbug(1,dprintf("clNRDY"));
6247 Info_Number = 0x00BF;
6248 Info_Mask = 0x08;
6249 Info_Element = "";
6250 break;
6251 case 15: /* Keypad Facility */
6252 dbug(1,dprintf("KEY"));
6253 Info_Number = 0x002C;
6254 Info_Mask = 0x20;
6255 break;
6256 case 16: /* Channel Id */
6257 dbug(1,dprintf("CHI"));
6258 Info_Number = 0x0018;
6259 Info_Mask = 0x100;
6260 mixer_set_bchannel_id (plci, Info_Element);
6261 break;
6262 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6263 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6264 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6265 Info_Number = 0x0008;
6266 Info_Mask = 0x01;
6267 if(cause[2] != ie[2]) Info_Element = cause;
6268 break;
6269 case 19: /* Redirected Number */
6270 dbug(1,dprintf("RDN"));
6271 Info_Number = 0x0074;
6272 Info_Mask = 0x400;
6273 break;
6274 case 22: /* Redirecing Number */
6275 dbug(1,dprintf("RIN"));
6276 Info_Number = 0x0076;
6277 Info_Mask = 0x400;
6278 break;
6279 case 23: /* Notification Indicator */
6280 dbug(1,dprintf("NI"));
6281 Info_Number = (word)NI;
6282 Info_Mask = 0x210;
6283 break;
6284 case 26: /* Call State */
6285 dbug(1,dprintf("CST"));
6286 Info_Number = (word)CST;
6287 Info_Mask = 0x01; /* do with cause i.e. for now */
6288 break;
6289 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6290 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6291 Info_Number = 0x8000 |ie[3];
6292 if(iesent) Info_Mask = 0xffff;
6293 else Info_Mask = 0x10;
6294 Info_Element = "";
6295 break;
6296 default:
6297 Info_Number = 0;
6298 Info_Mask = 0;
6299 Info_Element = "";
6300 break;
6301 }
6302 }
6303
6304 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6305 {
6306 for(j=0; j<max_appl; j++)
6307 {
6308 appl = &application[j];
6309 if(Info_Number
6310 && appl->Id
6311 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6312 {
6313 dbug(1,dprintf("NCR_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006314 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006315 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6316 }
6317 }
6318 }
6319 else if(!plci->appl)
6320 { /* overlap receiving broadcast */
6321 if(Info_Number==CPN
6322 || Info_Number==KEY
6323 || Info_Number==NI
6324 || Info_Number==DSP
6325 || Info_Number==UUI )
6326 {
6327 for(j=0; j<max_appl; j++)
6328 {
6329 if(test_c_ind_mask_bit (plci, j))
6330 {
6331 dbug(1,dprintf("Ovl_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006332 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006333 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6334 }
6335 }
6336 }
6337 } /* all other signalling states */
6338 else if(Info_Number
6339 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6340 {
6341 dbug(1,dprintf("Std_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006342 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006343 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6344 }
6345 }
6346}
6347
6348
6349byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse)
6350{
6351 word i;
6352 word j;
6353 byte * ie;
6354 word Info_Number;
6355 byte * Info_Element;
6356 APPL *appl;
6357 word Info_Mask = 0;
6358 byte iesent=0;
6359
6360 if(
6361 !plci->appl
6362 && !plci->State
6363 && plci->Sig.Ind!=NCR_FACILITY
6364 && !setupParse
6365 )
6366 {
6367 dbug(1,dprintf("NoM-IEParse "));
6368 return 0;
6369 }
6370 dbug(1,dprintf("M-IEParse "));
6371
6372 for(i=0; i<MAX_MULTI_IE; i++)
6373 {
6374 ie = parms[i];
6375 Info_Number = 0;
6376 Info_Element = ie;
6377 if(ie[0])
6378 {
6379 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6380 Info_Number = (word)ie_type;
6381 Info_Mask = (word)info_mask;
6382 }
6383
6384 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6385 {
6386 for(j=0; j<max_appl; j++)
6387 {
6388 appl = &application[j];
6389 if(Info_Number
6390 && appl->Id
6391 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6392 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006393 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006394 dbug(1,dprintf("Mlt_NCR_Ind"));
6395 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6396 }
6397 }
6398 }
6399 else if(!plci->appl && Info_Number)
6400 { /* overlap receiving broadcast */
6401 for(j=0; j<max_appl; j++)
6402 {
6403 if(test_c_ind_mask_bit (plci, j))
6404 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006405 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006406 dbug(1,dprintf("Mlt_Ovl_Ind"));
6407 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6408 }
6409 }
6410 } /* all other signalling states */
6411 else if(Info_Number
6412 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6413 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006414 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006415 dbug(1,dprintf("Mlt_Std_Ind"));
6416 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6417 }
6418 }
6419 return iesent;
6420}
6421
6422static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6423{
6424 word i;
6425 /* Format of multi_ssext_parms[i][]:
6426 0 byte length
6427 1 byte SSEXTIE
6428 2 byte SSEXT_REQ/SSEXT_IND
6429 3 byte length
6430 4 word SSExtCommand
6431 6... Params
6432 */
6433 if(
6434 plci
6435 && plci->State
6436 && plci->Sig.Ind!=NCR_FACILITY
6437 )
6438 for(i=0;i<MAX_MULTI_IE;i++)
6439 {
6440 if(parms[i][0]<6) continue;
6441 if(parms[i][2]==SSEXT_REQ) continue;
6442
6443 if(appl)
6444 {
6445 parms[i][0]=0; /* kill it */
6446 sendf(appl,_MANUFACTURER_I,
6447 Id,
6448 0,
6449 "dwS",
6450 _DI_MANU_ID,
6451 _DI_SSEXT_CTRL,
6452 &parms[i][3]);
6453 }
6454 else if(plci->appl)
6455 {
6456 parms[i][0]=0; /* kill it */
6457 sendf(plci->appl,_MANUFACTURER_I,
6458 Id,
6459 0,
6460 "dwS",
6461 _DI_MANU_ID,
6462 _DI_SSEXT_CTRL,
6463 &parms[i][3]);
6464 }
6465 }
6466};
6467
6468void nl_ind(PLCI * plci)
6469{
6470 byte ch;
6471 word ncci;
6472 dword Id;
6473 DIVA_CAPI_ADAPTER * a;
6474 word NCCIcode;
6475 APPL * APPLptr;
6476 word count;
6477 word Num;
6478 word i, ncpi_state;
6479 byte len, ncci_state;
6480 word msg;
6481 word info = 0;
6482 word fax_feature_bits;
6483 byte fax_send_edata_ack;
6484 static byte v120_header_buffer[2 + 3];
6485 static word fax_info[] = {
6486 0, /* T30_SUCCESS */
6487 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6488 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6489 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6490 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6491 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6492 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6493 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6494 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6495 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6496 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6497 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6498 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6499 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6500 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6501 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6502 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6503 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6504 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6505 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6507 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6511 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6519 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6520 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6521 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6523 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6524 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6525 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6526 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6531 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6532 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6533 };
6534
6535 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6536
6537
6538 static word rtp_info[] = {
6539 GOOD, /* RTP_SUCCESS */
6540 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6541 };
6542
6543 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6544 {
6545 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6546 0x00000000, 0x00000000, 0x00000000, 0x00000000
6547 };
6548
6549 ch = plci->NL.IndCh;
6550 a = plci->adapter;
6551 ncci = a->ch_ncci[ch];
6552 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6553 if(plci->tel) Id|=EXT_CONTROLLER;
6554 APPLptr = plci->appl;
6555 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",
6556 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6557
6558 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6559
6560 if (plci->nl_remove_id)
6561 {
6562 plci->NL.RNR = 2; /* discard */
6563 dbug(1,dprintf("NL discard while remove pending"));
6564 return;
6565 }
6566 if((plci->NL.Ind &0x0f)==N_CONNECT)
6567 {
6568 if(plci->State==INC_DIS_PENDING
6569 || plci->State==OUTG_DIS_PENDING
6570 || plci->State==IDLE)
6571 {
6572 plci->NL.RNR = 2; /* discard */
6573 dbug(1,dprintf("discard n_connect"));
6574 return;
6575 }
6576 if(plci->State < INC_ACT_PENDING)
6577 {
6578 plci->NL.RNR = 1; /* flow control */
6579 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6580 return;
6581 }
6582 }
6583
6584 if(!APPLptr) /* no application or invalid data */
6585 { /* while reloading the DSP */
6586 dbug(1,dprintf("discard1"));
6587 plci->NL.RNR = 2;
6588 return;
6589 }
6590
6591 if (((plci->NL.Ind &0x0f) == N_UDATA)
6592 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6593 || (plci->B2_prot == 7)
6594 || (plci->B3_prot == 7)) )
6595 {
6596 plci->ncpi_buffer[0] = 0;
6597
6598 ncpi_state = plci->ncpi_state;
6599 if (plci->NL.complete == 1)
6600 {
6601 byte * data = &plci->NL.RBuffer->P[0];
6602
6603 if ((plci->NL.RBuffer->length >= 12)
6604 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6605 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6606 {
6607 word conn_opt, ncpi_opt = 0x00;
6608/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6609
6610 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6611 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6612 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6613 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6614
6615 data++; /* indication code */
6616 data += 2; /* timestamp */
6617 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6618 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6619 data++; /* connected norm */
6620 conn_opt = GET_WORD(data);
6621 data += 2; /* connected options */
6622
6623 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6624
6625 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6626 {
6627 ncpi_opt |= MDM_NCPI_ECM_V42;
6628 }
6629 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6630 {
6631 ncpi_opt |= MDM_NCPI_ECM_MNP;
6632 }
6633 else
6634 {
6635 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6636 }
6637 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6638 {
6639 ncpi_opt |= MDM_NCPI_COMPRESSED;
6640 }
6641 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6642 plci->ncpi_buffer[0] = 4;
6643
6644 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6645 }
6646 }
6647 if (plci->B3_prot == 7)
6648 {
6649 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6650 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6651 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6652 {
6653 a->ncci_state[ncci] = INC_ACT_PENDING;
6654 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6655 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6656 }
6657 }
6658
6659 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6660 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6661 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6662 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6663
6664 {
6665 plci->NL.RNR = 2;
6666 return;
6667 }
6668 }
6669
6670 if(plci->NL.complete == 2)
6671 {
6672 if (((plci->NL.Ind &0x0f) == N_UDATA)
6673 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6674 {
6675 switch(plci->RData[0].P[0])
6676 {
6677
6678 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6679 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6680 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6681 break;
6682 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6683 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6684 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6685 break;
6686 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6687 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6688 break;
6689 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6690 dtmf_confirmation (Id, plci);
6691 break;
6692
6693
6694 case UDATA_INDICATION_MIXER_TAP_DATA:
6695 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6696 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6697 if (i != 0)
6698 {
6699 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6700 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6701 }
6702 break;
6703
6704
6705 case UDATA_INDICATION_MIXER_COEFS_SET:
6706 mixer_indication_coefs_set (Id, plci);
6707 break;
6708 case UDATA_INDICATION_XCONNECT_FROM:
6709 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6710 break;
6711 case UDATA_INDICATION_XCONNECT_TO:
6712 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6713 break;
6714
6715
6716 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6717 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6718 break;
6719
6720
6721
6722 default:
6723 break;
6724 }
6725 }
6726 else
6727 {
6728 if ((plci->RData[0].PLength != 0)
6729 && ((plci->B2_prot == B2_V120_ASYNC)
6730 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6731 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6732 {
6733
6734 sendf(plci->appl,_DATA_B3_I,Id,0,
6735 "dwww",
6736 plci->RData[1].P,
6737 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6738 plci->RNum,
6739 plci->RFlags);
6740
6741 }
6742 else
6743 {
6744
6745 sendf(plci->appl,_DATA_B3_I,Id,0,
6746 "dwww",
6747 plci->RData[0].P,
6748 plci->RData[0].PLength,
6749 plci->RNum,
6750 plci->RFlags);
6751
6752 }
6753 }
6754 return;
6755 }
6756
6757 fax_feature_bits = 0;
6758 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6759 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6760 (plci->NL.Ind &0x0f)==N_DISC ||
6761 (plci->NL.Ind &0x0f)==N_EDATA ||
6762 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6763 {
6764 info = 0;
6765 plci->ncpi_buffer[0] = 0;
6766 switch (plci->B3_prot) {
6767 case 0: /*XPARENT*/
6768 case 1: /*T.90 NL*/
6769 break; /* no network control protocol info - jfr */
6770 case 2: /*ISO8202*/
6771 case 3: /*X25 DCE*/
6772 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6773 plci->ncpi_buffer[0] = (byte)(i+3);
6774 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6775 plci->ncpi_buffer[2] = 0;
6776 plci->ncpi_buffer[3] = 0;
6777 break;
6778 case 4: /*T.30 - FAX*/
6779 case 5: /*T.30 - FAX*/
6780 if(plci->NL.RLength>=sizeof(T30_INFO))
6781 {
6782 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6783 len = 9;
6784 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6785 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6786 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6787 if (plci->B3_prot == 5)
6788 {
6789 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6790 i |= 0x8000; /* This is not an ECM connection */
6791 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6792 i |= 0x4000; /* This is a connection with MMR compression */
6793 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6794 i |= 0x2000; /* This is a connection with MR compression */
6795 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6796 i |= 0x0004; /* More documents */
6797 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6798 i |= 0x0002; /* Fax-polling indication */
6799 }
6800 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6801 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6802 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6803 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6804 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6805 plci->ncpi_buffer[len] = 0;
6806 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6807 {
6808 plci->ncpi_buffer[len] = 20;
6809 for (i = 0; i < 20; i++)
6810 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6811 }
6812 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6813 {
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -08006814 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006815 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6816 else
6817 info = _FAX_PROTOCOL_ERROR;
6818 }
6819
6820 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6821 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6822 {
6823 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6824 while (i < plci->NL.RBuffer->length)
6825 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6826 }
6827
6828 plci->ncpi_buffer[0] = len;
6829 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6830 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6831
6832 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6833 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6834 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6835 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6836 || (((plci->NL.Ind &0x0f) == N_EDATA)
6837 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6838 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6839 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6840 {
6841 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6842 }
6843 if (((plci->NL.Ind &0x0f) == N_DISC)
6844 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6845 || (((plci->NL.Ind &0x0f) == N_EDATA)
6846 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6847 {
6848 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6849 }
6850 }
6851 break;
6852
6853 case B3_RTP:
6854 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6855 {
6856 if (plci->NL.RLength != 0)
6857 {
6858 info = rtp_info[plci->NL.RBuffer->P[0]];
6859 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6860 for (i = 1; i < plci->NL.RLength; i++)
6861 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6862 }
6863 }
6864 break;
6865
6866 }
6867 plci->NL.RNR = 2;
6868 }
6869 switch(plci->NL.Ind &0x0f) {
6870 case N_EDATA:
6871 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6872 {
6873 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6874 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6875 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6876
6877 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6878 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6879 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6880 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6881 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6882 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6883 {
6884 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6885 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6886 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6887 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6888 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006889 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006890 }
6891
6892 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6893 {
6894 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6895 {
6896 case EDATA_T30_DIS:
6897 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6898 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6899 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6900 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6901 {
6902 a->ncci_state[ncci] = INC_ACT_PENDING;
6903 if (plci->B3_prot == 4)
6904 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6905 else
6906 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6907 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6908 }
6909 break;
6910
6911 case EDATA_T30_TRAIN_OK:
6912 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6913 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6914 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6915 {
6916 if (plci->B3_prot == 4)
6917 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6918 else
6919 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6920 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6921 }
6922 break;
6923
6924 case EDATA_T30_EOP_CAPI:
6925 if (a->ncci_state[ncci] == CONNECTED)
6926 {
6927 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6928 a->ncci_state[ncci] = INC_DIS_PENDING;
6929 plci->ncpi_state = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006930 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006931 }
6932 break;
6933 }
6934 }
6935 else
6936 {
6937 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6938 {
6939 case EDATA_T30_TRAIN_OK:
6940 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6941 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6942 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6943 {
6944 if (plci->B3_prot == 4)
6945 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6946 else
6947 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6948 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6949 }
6950 break;
6951 }
6952 }
6953 if (fax_send_edata_ack)
6954 {
6955 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6956 plci->fax_edata_ack_length = 1;
6957 start_internal_command (Id, plci, fax_edata_ack_command);
6958 }
6959 }
6960 else
6961 {
6962 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6963 }
6964 break;
6965 case N_CONNECT:
6966 if (!a->ch_ncci[ch])
6967 {
6968 ncci = get_ncci (plci, ch, 0);
6969 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6970 }
6971 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6972 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6973
6974 msg = _CONNECT_B3_I;
6975 if (a->ncci_state[ncci] == IDLE)
6976 plci->channels++;
6977 else if (plci->B3_prot == 1)
6978 msg = _CONNECT_B3_T90_ACTIVE_I;
6979
6980 a->ncci_state[ncci] = INC_CON_PENDING;
6981 if(plci->B3_prot == 4)
6982 sendf(plci->appl,msg,Id,0,"s","");
6983 else
6984 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6985 break;
6986 case N_CONNECT_ACK:
6987 dbug(1,dprintf("N_connect_Ack"));
6988 if (plci->internal_command_queue[0]
6989 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6990 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6991 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6992 {
6993 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6994 if (!plci->internal_command)
6995 next_internal_command (Id, plci);
6996 break;
6997 }
6998 msg = _CONNECT_B3_ACTIVE_I;
6999 if (plci->B3_prot == 1)
7000 {
7001 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7002 msg = _CONNECT_B3_T90_ACTIVE_I;
7003 a->ncci_state[ncci] = INC_ACT_PENDING;
7004 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7005 }
7006 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7007 {
7008 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7009 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7010 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7011 {
7012 a->ncci_state[ncci] = INC_ACT_PENDING;
7013 if (plci->B3_prot == 4)
7014 sendf(plci->appl,msg,Id,0,"s","");
7015 else
7016 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7017 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7018 }
7019 }
7020 else
7021 {
7022 a->ncci_state[ncci] = INC_ACT_PENDING;
7023 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7024 }
7025 if (plci->adjust_b_restore)
7026 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007027 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007028 start_internal_command (Id, plci, adjust_b_restore);
7029 }
7030 break;
7031 case N_DISC:
7032 case N_DISC_ACK:
7033 if (plci->internal_command_queue[0]
7034 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7035 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7036 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7037 {
7038 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7039 if (!plci->internal_command)
7040 next_internal_command (Id, plci);
7041 }
7042 ncci_state = a->ncci_state[ncci];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007043 ncci_remove (plci, ncci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007044
7045 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7046 /* channel, so we cannot store the state in ncci_state! The */
7047 /* information which channel we received a N_DISC is thus */
7048 /* stored in the inc_dis_ncci_table buffer. */
7049 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7050 plci->inc_dis_ncci_table[i] = (byte) ncci;
7051
7052 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7053 if (!plci->channels
7054 && (plci->B1_resource == 16)
7055 && (plci->State <= CONNECTED))
7056 {
7057 len = 9;
7058 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7059 PUT_WORD (&plci->ncpi_buffer[1], i);
7060 PUT_WORD (&plci->ncpi_buffer[3], 0);
7061 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7062 PUT_WORD (&plci->ncpi_buffer[5], i);
7063 PUT_WORD (&plci->ncpi_buffer[7], 0);
7064 plci->ncpi_buffer[len] = 0;
7065 plci->ncpi_buffer[0] = len;
7066 if(plci->B3_prot == 4)
7067 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7068 else
7069 {
7070
7071 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7072 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7073 {
7074 plci->ncpi_buffer[++len] = 0;
7075 plci->ncpi_buffer[++len] = 0;
7076 plci->ncpi_buffer[++len] = 0;
7077 plci->ncpi_buffer[0] = len;
7078 }
7079
7080 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7081 }
7082 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7083 plci->ncpi_state = 0;
7084 sig_req(plci,HANGUP,0);
7085 send_req(plci);
7086 plci->State = OUTG_DIS_PENDING;
7087 /* disc here */
7088 }
7089 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7090 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7091 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7092 {
7093 if (ncci_state == IDLE)
7094 {
7095 if (plci->channels)
7096 plci->channels--;
7097 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7098 if(plci->State == SUSPENDING){
7099 sendf(plci->appl,
7100 _FACILITY_I,
7101 Id & 0xffffL,
7102 0,
7103 "ws", (word)3, "\x03\x04\x00\x00");
7104 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7105 }
7106 plci_remove(plci);
7107 plci->State=IDLE;
7108 }
7109 }
7110 }
7111 else if (plci->channels)
7112 {
7113 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7114 plci->ncpi_state = 0;
7115 if ((ncci_state == OUTG_REJ_PENDING)
7116 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7117 {
7118 sig_req(plci,HANGUP,0);
7119 send_req(plci);
7120 plci->State = OUTG_DIS_PENDING;
7121 }
7122 }
7123 break;
7124 case N_RESET:
7125 a->ncci_state[ncci] = INC_RES_PENDING;
7126 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7127 break;
7128 case N_RESET_ACK:
7129 a->ncci_state[ncci] = CONNECTED;
7130 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7131 break;
7132
7133 case N_UDATA:
7134 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7135 {
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07007136 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007137 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7138 plci->NL.R = plci->RData;
7139 plci->NL.RNum = 1;
7140 return;
7141 }
7142 case N_BDATA:
7143 case N_DATA:
7144 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7145 || (a->ncci_state[ncci] == IDLE)
7146 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7147 {
7148 plci->NL.RNR = 2;
7149 break;
7150 }
7151 if ((a->ncci_state[ncci] != CONNECTED)
7152 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7153 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7154 {
7155 dbug(1,dprintf("flow control"));
7156 plci->NL.RNR = 1; /* flow control */
7157 channel_x_off (plci, ch, 0);
7158 break;
7159 }
7160
7161 NCCIcode = ncci | (((word)a->Id) << 8);
7162
7163 /* count all buffers within the Application pool */
7164 /* belonging to the same NCCI. If this is below the */
7165 /* number of buffers available per NCCI we accept */
7166 /* this packet, otherwise we reject it */
7167 count = 0;
7168 Num = 0xffff;
7169 for(i=0; i<APPLptr->MaxBuffer; i++) {
7170 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7171 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7172 }
7173
7174 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7175 {
7176 dbug(3,dprintf("Flow-Control"));
7177 plci->NL.RNR = 1;
7178 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7179 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7180 {
7181 plci->NL.RNR = 2;
7182 dbug(3,dprintf("DiscardData"));
7183 } else {
7184 channel_x_off (plci, ch, 0);
7185 }
7186 break;
7187 }
7188 else
7189 {
7190 APPLptr->NCCIDataFlowCtrlTimer = 0;
7191 }
7192
7193 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7194 if(!plci->RData[0].P) {
7195 plci->NL.RNR = 1;
7196 channel_x_off (plci, ch, 0);
7197 break;
7198 }
7199
7200 APPLptr->DataNCCI[Num] = NCCIcode;
7201 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7202 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7203
7204 plci->RNum = Num;
7205 plci->RFlags = plci->NL.Ind>>4;
7206 plci->RData[0].PLength = APPLptr->MaxDataLength;
7207 plci->NL.R = plci->RData;
7208 if ((plci->NL.RLength != 0)
7209 && ((plci->B2_prot == B2_V120_ASYNC)
7210 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7211 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7212 {
7213 plci->RData[1].P = plci->RData[0].P;
7214 plci->RData[1].PLength = plci->RData[0].PLength;
7215 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7216 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7217 plci->RData[0].PLength = 1;
7218 else
7219 plci->RData[0].PLength = 2;
7220 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7221 plci->RFlags |= 0x0010;
7222 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7223 plci->RFlags |= 0x8000;
7224 plci->NL.RNum = 2;
7225 }
7226 else
7227 {
7228 if((plci->NL.Ind &0x0f)==N_UDATA)
7229 plci->RFlags |= 0x0010;
7230
7231 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7232 plci->RFlags |= 0x0001;
7233
7234 plci->NL.RNum = 1;
7235 }
7236 break;
7237 case N_DATA_ACK:
7238 data_ack (plci, ch);
7239 break;
7240 default:
7241 plci->NL.RNR = 2;
7242 break;
7243 }
7244}
7245
7246/*------------------------------------------------------------------*/
7247/* find a free PLCI */
7248/*------------------------------------------------------------------*/
7249
7250word get_plci(DIVA_CAPI_ADAPTER * a)
7251{
7252 word i,j;
7253 PLCI * plci;
7254
7255 dump_plcis (a);
7256 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7257 if(i==a->max_plci) {
7258 dbug(1,dprintf("get_plci: out of PLCIs"));
7259 return 0;
7260 }
7261 plci = &a->plci[i];
7262 plci->Id = (byte)(i+1);
7263
7264 plci->Sig.Id = 0;
7265 plci->NL.Id = 0;
7266 plci->sig_req = 0;
7267 plci->nl_req = 0;
7268
7269 plci->appl = NULL;
7270 plci->relatedPTYPLCI = NULL;
7271 plci->State = IDLE;
7272 plci->SuppState = IDLE;
7273 plci->channels = 0;
7274 plci->tel = 0;
7275 plci->B1_resource = 0;
7276 plci->B2_prot = 0;
7277 plci->B3_prot = 0;
7278
7279 plci->command = 0;
7280 plci->m_command = 0;
7281 init_internal_command_queue (plci);
7282 plci->number = 0;
7283 plci->req_in_start = 0;
7284 plci->req_in = 0;
7285 plci->req_out = 0;
7286 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7287 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7288 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7289
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007290 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007291 plci->send_disc = 0;
7292 plci->sig_global_req = 0;
7293 plci->sig_remove_id = 0;
7294 plci->nl_global_req = 0;
7295 plci->nl_remove_id = 0;
7296 plci->adv_nl = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007297 plci->manufacturer = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007298 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7299 plci->spoofed_msg = 0;
7300 plci->ptyState = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007301 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302 plci->hangup_flow_ctrl_timer = 0;
7303
7304 plci->ncci_ring_list = 0;
7305 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7306 clear_c_ind_mask (plci);
7307 set_group_ind_mask (plci);
7308 plci->fax_connect_info_length = 0;
7309 plci->nsf_control_bits = 0;
7310 plci->ncpi_state = 0x00;
7311 plci->ncpi_buffer[0] = 0;
7312
7313 plci->requested_options_conn = 0;
7314 plci->requested_options = 0;
7315 plci->notifiedcall = 0;
7316 plci->vswitchstate = 0;
7317 plci->vsprot = 0;
7318 plci->vsprotdialect = 0;
7319 init_b1_config (plci);
7320 dbug(1,dprintf("get_plci(%x)",plci->Id));
7321 return i+1;
7322}
7323
7324/*------------------------------------------------------------------*/
7325/* put a parameter in the parameter buffer */
7326/*------------------------------------------------------------------*/
7327
7328static void add_p(PLCI * plci, byte code, byte * p)
7329{
7330 word p_length;
7331
7332 p_length = 0;
7333 if(p) p_length = p[0];
7334 add_ie(plci, code, p, p_length);
7335}
7336
7337/*------------------------------------------------------------------*/
7338/* put a structure in the parameter buffer */
7339/*------------------------------------------------------------------*/
7340static void add_s(PLCI * plci, byte code, API_PARSE * p)
7341{
7342 if(p) add_ie(plci, code, p->info, (word)p->length);
7343}
7344
7345/*------------------------------------------------------------------*/
7346/* put multiple structures in the parameter buffer */
7347/*------------------------------------------------------------------*/
7348static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7349{
7350 byte i;
7351
7352 if(p){
7353 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7354 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7355 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7356 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7357 }
7358 }
7359}
7360
7361/*------------------------------------------------------------------*/
7362/* return the channel number sent by the application in a esc_chi */
7363/*------------------------------------------------------------------*/
7364static byte getChannel(API_PARSE * p)
7365{
7366 byte i;
7367
7368 if(p){
7369 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7370 if(p->info[i]==2){
7371 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7372 }
7373 }
7374 }
7375 return 0;
7376}
7377
7378
7379/*------------------------------------------------------------------*/
7380/* put an information element in the parameter buffer */
7381/*------------------------------------------------------------------*/
7382
7383static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7384{
7385 word i;
7386
7387 if(!(code &0x80) && !p_length) return;
7388
7389 if(plci->req_in==plci->req_in_start) {
7390 plci->req_in +=2;
7391 }
7392 else {
7393 plci->req_in--;
7394 }
7395 plci->RBuffer[plci->req_in++] = code;
7396
7397 if(p) {
7398 plci->RBuffer[plci->req_in++] = (byte)p_length;
7399 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7400 }
7401
7402 plci->RBuffer[plci->req_in++] = 0;
7403}
7404
7405/*------------------------------------------------------------------*/
7406/* put a unstructured data into the buffer */
7407/*------------------------------------------------------------------*/
7408
7409void add_d(PLCI * plci, word length, byte * p)
7410{
7411 word i;
7412
7413 if(plci->req_in==plci->req_in_start) {
7414 plci->req_in +=2;
7415 }
7416 else {
7417 plci->req_in--;
7418 }
7419 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7420}
7421
7422/*------------------------------------------------------------------*/
7423/* put parameters from the Additional Info parameter in the */
7424/* parameter buffer */
7425/*------------------------------------------------------------------*/
7426
7427void add_ai(PLCI * plci, API_PARSE * ai)
7428{
7429 word i;
7430 API_PARSE ai_parms[5];
7431
7432 for(i=0;i<5;i++) ai_parms[i].length = 0;
7433
7434 if(!ai->length)
7435 return;
7436 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7437 return;
7438
7439 add_s (plci,KEY,&ai_parms[1]);
7440 add_s (plci,UUI,&ai_parms[2]);
7441 add_ss(plci,FTY,&ai_parms[3]);
7442}
7443
7444/*------------------------------------------------------------------*/
7445/* put parameter for b1 protocol in the parameter buffer */
7446/*------------------------------------------------------------------*/
7447
7448word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7449{
7450 API_PARSE bp_parms[8];
7451 API_PARSE mdm_cfg[9];
7452 API_PARSE global_config[2];
7453 byte cai[256];
7454 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7455 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7456 word i;
7457
7458 API_PARSE mdm_cfg_v18[4];
7459 word j, n, w;
7460 dword d;
7461
7462
7463 for(i=0;i<8;i++) bp_parms[i].length = 0;
7464 for(i=0;i<2;i++) global_config[i].length = 0;
7465
7466 dbug(1,dprintf("add_b1"));
7467 api_save_msg(bp, "s", &plci->B_protocol);
7468
7469 if(b_channel_info==2){
7470 plci->B1_resource = 0;
7471 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7472 add_p(plci, CAI, "\x01\x00");
7473 dbug(1,dprintf("Cai=1,0 (no resource)"));
7474 return 0;
7475 }
7476
7477 if(plci->tel == CODEC_PERMANENT) return 0;
7478 else if(plci->tel == CODEC){
7479 plci->B1_resource = 1;
7480 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7481 add_p(plci, CAI, "\x01\x01");
7482 dbug(1,dprintf("Cai=1,1 (Codec)"));
7483 return 0;
7484 }
7485 else if(plci->tel == ADV_VOICE){
7486 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7487 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7488 voice_cai[1] = plci->B1_resource;
7489 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7490 add_p(plci, CAI, voice_cai);
7491 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7492 return 0;
7493 }
7494 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7495 if (plci->call_dir & CALL_DIR_OUT)
7496 plci->call_dir |= CALL_DIR_ORIGINATE;
7497 else if (plci->call_dir & CALL_DIR_IN)
7498 plci->call_dir |= CALL_DIR_ANSWER;
7499
7500 if(!bp->length){
7501 plci->B1_resource = 0x5;
7502 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7503 add_p(plci, CAI, "\x01\x05");
7504 return 0;
7505 }
7506
7507 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7508 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7509 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7510 {
7511 bp_parms[6].length = 0;
7512 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7513 {
7514 dbug(1,dprintf("b-form.!"));
7515 return _WRONG_MESSAGE_FORMAT;
7516 }
7517 }
7518 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7519 {
7520 dbug(1,dprintf("b-form.!"));
7521 return _WRONG_MESSAGE_FORMAT;
7522 }
7523
7524 if(bp_parms[6].length)
7525 {
7526 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7527 {
7528 return _WRONG_MESSAGE_FORMAT;
7529 }
7530 switch(GET_WORD(global_config[0].info))
7531 {
7532 case 1:
7533 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7534 break;
7535 case 2:
7536 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7537 break;
7538 }
7539 }
7540 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7541
7542
7543 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7544 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7545 {
7546 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7547 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548 cai[1] = plci->B1_resource;
7549 cai[2] = 0;
7550 cai[3] = 0;
7551 cai[4] = 0;
7552 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7553 for (i = 0; i < bp_parms[3].length; i++)
7554 cai[7+i] = bp_parms[3].info[1+i];
7555 cai[0] = 6 + bp_parms[3].length;
7556 add_p(plci, CAI, cai);
7557 return 0;
7558 }
7559
7560
7561 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7562 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7563 {
7564 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7565 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 cai[1] = plci->B1_resource;
7567 cai[2] = 0;
7568 cai[3] = 0;
7569 cai[4] = 0;
7570 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7571 cai[0] = 6;
7572 add_p(plci, CAI, cai);
7573 return 0;
7574 }
7575
7576
7577 if ((GET_WORD(bp_parms[0].info) >= 32)
7578 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7579 && ((GET_WORD(bp_parms[0].info) != 3)
7580 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7581 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7582 {
7583 return _B1_NOT_SUPPORTED;
7584 }
7585 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7586 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588 cai[0] = 6;
7589 cai[1] = plci->B1_resource;
7590 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7591
7592 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7593 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7594 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7595 { /* B1 - modem */
7596 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7597
7598 if (bp_parms[3].length)
7599 {
7600 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7601 {
7602 return (_WRONG_MESSAGE_FORMAT);
7603 }
7604
7605 cai[2] = 0; /* Bit rate for adaptation */
7606
7607 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7608
7609 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7610 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7611 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7612 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7613
7614 cai[3] = 0; /* Async framing parameters */
7615 switch (GET_WORD (mdm_cfg[2].info))
7616 { /* Parity */
7617 case 1: /* odd parity */
7618 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7619 dbug(1,dprintf("MDM: odd parity"));
7620 break;
7621
7622 case 2: /* even parity */
7623 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7624 dbug(1,dprintf("MDM: even parity"));
7625 break;
7626
7627 default:
7628 dbug(1,dprintf("MDM: no parity"));
7629 break;
7630 }
7631
7632 switch (GET_WORD (mdm_cfg[3].info))
7633 { /* stop bits */
7634 case 1: /* 2 stop bits */
7635 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7636 dbug(1,dprintf("MDM: 2 stop bits"));
7637 break;
7638
7639 default:
7640 dbug(1,dprintf("MDM: 1 stop bit"));
7641 break;
7642 }
7643
7644 switch (GET_WORD (mdm_cfg[1].info))
7645 { /* char length */
7646 case 5:
7647 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7648 dbug(1,dprintf("MDM: 5 bits"));
7649 break;
7650
7651 case 6:
7652 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7653 dbug(1,dprintf("MDM: 6 bits"));
7654 break;
7655
7656 case 7:
7657 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7658 dbug(1,dprintf("MDM: 7 bits"));
7659 break;
7660
7661 default:
7662 dbug(1,dprintf("MDM: 8 bits"));
7663 break;
7664 }
7665
7666 cai[7] = 0; /* Line taking options */
7667 cai[8] = 0; /* Modulation negotiation options */
7668 cai[9] = 0; /* Modulation options */
7669
7670 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7671 {
7672 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7673 dbug(1, dprintf("MDM: Reverse direction"));
7674 }
7675
7676 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7677 {
7678 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7679 dbug(1, dprintf("MDM: Disable retrain"));
7680 }
7681
7682 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7683 {
7684 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7685 dbug(1, dprintf("MDM: Disable ring tone"));
7686 }
7687
7688 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7689 {
7690 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7691 dbug(1, dprintf("MDM: 1800 guard tone"));
7692 }
7693 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7694 {
7695 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7696 dbug(1, dprintf("MDM: 550 guard tone"));
7697 }
7698
7699 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7700 {
7701 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7702 dbug(1, dprintf("MDM: V100"));
7703 }
7704 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7705 {
7706 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7707 dbug(1, dprintf("MDM: IN CLASS"));
7708 }
7709 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7710 {
7711 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7712 dbug(1, dprintf("MDM: DISABLED"));
7713 }
7714 cai[0] = 20;
7715
7716 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7717 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7718 {
7719 plci->requested_options |= 1L << PRIVATE_V18;
7720 }
7721 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7722 plci->requested_options |= 1L << PRIVATE_VOWN;
7723
7724 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7725 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7726 {
7727 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7728 {
7729 i = 27;
7730 if (mdm_cfg[6].length >= 4)
7731 {
7732 d = GET_DWORD(&mdm_cfg[6].info[1]);
7733 cai[7] |= (byte) d; /* line taking options */
7734 cai[9] |= (byte)(d >> 8); /* modulation options */
7735 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7736 cai[++i] = (byte)(d >> 24);
7737 if (mdm_cfg[6].length >= 8)
7738 {
7739 d = GET_DWORD(&mdm_cfg[6].info[5]);
7740 cai[10] |= (byte) d; /* disabled modulations mask */
7741 cai[11] |= (byte)(d >> 8);
7742 if (mdm_cfg[6].length >= 12)
7743 {
7744 d = GET_DWORD(&mdm_cfg[6].info[9]);
7745 cai[12] = (byte) d; /* enabled modulations mask */
7746 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7747 cai[++i] = (byte)(d >> 16);
7748 cai[++i] = (byte)(d >> 24);
7749 cai[++i] = 0;
7750 if (mdm_cfg[6].length >= 14)
7751 {
7752 w = GET_WORD(&mdm_cfg[6].info[13]);
7753 if (w != 0)
7754 PUT_WORD(&cai[13], w); /* min tx speed */
7755 if (mdm_cfg[6].length >= 16)
7756 {
7757 w = GET_WORD(&mdm_cfg[6].info[15]);
7758 if (w != 0)
7759 PUT_WORD(&cai[15], w); /* max tx speed */
7760 if (mdm_cfg[6].length >= 18)
7761 {
7762 w = GET_WORD(&mdm_cfg[6].info[17]);
7763 if (w != 0)
7764 PUT_WORD(&cai[17], w); /* min rx speed */
7765 if (mdm_cfg[6].length >= 20)
7766 {
7767 w = GET_WORD(&mdm_cfg[6].info[19]);
7768 if (w != 0)
7769 PUT_WORD(&cai[19], w); /* max rx speed */
7770 if (mdm_cfg[6].length >= 22)
7771 {
7772 w = GET_WORD(&mdm_cfg[6].info[21]);
7773 cai[23] = (byte)(-((short) w)); /* transmit level */
7774 if (mdm_cfg[6].length >= 24)
7775 {
7776 w = GET_WORD(&mdm_cfg[6].info[23]);
7777 cai[22] |= (byte) w; /* info options mask */
7778 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7779 }
7780 }
7781 }
7782 }
7783 }
7784 }
7785 }
7786 }
7787 }
7788 cai[27] = i - 27;
7789 i++;
7790 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7791 {
7792 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7793 {
7794 for (n = 0; n < 3; n++)
7795 {
7796 cai[i] = (byte)(mdm_cfg_v18[n].length);
7797 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7798 cai[i+j] = mdm_cfg_v18[n].info[j];
7799 i += cai[i] + 1;
7800 }
7801 }
7802 }
7803 cai[0] = (byte)(i - 1);
7804 }
7805 }
7806
7807 }
7808 }
7809 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7810 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7811 {
7812 if(bp_parms[3].length){
7813 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7814 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7815 case 0:
7816 case 56000:
7817 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7818 dbug(1,dprintf("56k sync HSCX"));
7819 cai[1] = 8;
7820 cai[2] = 0;
7821 cai[3] = 0;
7822 }
7823 else if(GET_WORD(bp_parms[0].info)==2){
7824 dbug(1,dprintf("56k async DSP"));
7825 cai[2] = 9;
7826 }
7827 break;
7828 case 50: cai[2] = 1; break;
7829 case 75: cai[2] = 1; break;
7830 case 110: cai[2] = 1; break;
7831 case 150: cai[2] = 1; break;
7832 case 200: cai[2] = 1; break;
7833 case 300: cai[2] = 1; break;
7834 case 600: cai[2] = 1; break;
7835 case 1200: cai[2] = 2; break;
7836 case 2400: cai[2] = 3; break;
7837 case 4800: cai[2] = 4; break;
7838 case 7200: cai[2] = 10; break;
7839 case 9600: cai[2] = 5; break;
7840 case 12000: cai[2] = 13; break;
7841 case 24000: cai[2] = 0; break;
7842 case 14400: cai[2] = 11; break;
7843 case 19200: cai[2] = 6; break;
7844 case 28800: cai[2] = 12; break;
7845 case 38400: cai[2] = 7; break;
7846 case 48000: cai[2] = 8; break;
7847 case 76: cai[2] = 15; break; /* 75/1200 */
7848 case 1201: cai[2] = 14; break; /* 1200/75 */
7849 case 56001: cai[2] = 9; break; /* V.110 56000 */
7850
7851 default:
7852 return _B1_PARM_NOT_SUPPORTED;
7853 }
7854 cai[3] = 0;
7855 if (cai[1] == 13) /* v.110 async */
7856 {
7857 if (bp_parms[3].length >= 8)
7858 {
7859 switch (GET_WORD (&bp_parms[3].info[3]))
7860 { /* char length */
7861 case 5:
7862 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7863 break;
7864 case 6:
7865 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7866 break;
7867 case 7:
7868 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7869 break;
7870 }
7871 switch (GET_WORD (&bp_parms[3].info[5]))
7872 { /* Parity */
7873 case 1: /* odd parity */
7874 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7875 break;
7876 case 2: /* even parity */
7877 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7878 break;
7879 }
7880 switch (GET_WORD (&bp_parms[3].info[7]))
7881 { /* stop bits */
7882 case 1: /* 2 stop bits */
7883 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7884 break;
7885 }
7886 }
7887 }
7888 }
7889 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7890 dbug(1,dprintf("V.110 default 56k sync"));
7891 cai[1] = 8;
7892 cai[2] = 0;
7893 cai[3] = 0;
7894 }
7895 else {
7896 dbug(1,dprintf("V.110 default 9600 async"));
7897 cai[2] = 5;
7898 }
7899 }
7900 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7901 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]));
7902/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7903
7904 add_p(plci, CAI, cai);
7905 return 0;
7906}
7907
7908/*------------------------------------------------------------------*/
7909/* put parameter for b2 and B3 protocol in the parameter buffer */
7910/*------------------------------------------------------------------*/
7911
7912word add_b23(PLCI * plci, API_PARSE * bp)
7913{
7914 word i, fax_control_bits;
7915 byte pos, len;
7916 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7917 API_PARSE bp_parms[8];
7918 API_PARSE * b1_config;
7919 API_PARSE * b2_config;
7920 API_PARSE b2_config_parms[8];
7921 API_PARSE * b3_config;
7922 API_PARSE b3_config_parms[6];
7923 API_PARSE global_config[2];
7924
7925 static byte llc[3] = {2,0,0};
7926 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7927 static byte nlc[256];
7928 static byte lli[12] = {1,1};
7929
7930 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7931 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932
7933 const byte llc3[] = {4,3,2,2,6,6,0};
7934 const byte header[] = {0,2,3,3,0,0,0};
7935
7936 for(i=0;i<8;i++) bp_parms[i].length = 0;
7937 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7938 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7939
7940 lli[0] = 1;
7941 lli[1] = 1;
7942 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7943 lli[1] |= 2;
7944 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7945 lli[1] |= 4;
7946
7947 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7948 lli[1] |= 0x10;
7949 if (plci->rx_dma_descriptor <= 0) {
7950 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7951 if (plci->rx_dma_descriptor >= 0)
7952 plci->rx_dma_descriptor++;
7953 }
7954 if (plci->rx_dma_descriptor > 0) {
7955 lli[0] = 6;
7956 lli[1] |= 0x40;
7957 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7958 lli[3] = (byte)plci->rx_dma_magic;
7959 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7960 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7961 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7962 }
7963 }
7964
7965 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7966 lli[1] |= 0x20;
7967 }
7968
7969 dbug(1,dprintf("add_b23"));
7970 api_save_msg(bp, "s", &plci->B_protocol);
7971
7972 if(!bp->length && plci->tel)
7973 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007974 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007975 dbug(1,dprintf("Default adv.Nl"));
7976 add_p(plci,LLI,lli);
7977 plci->B2_prot = 1 /*XPARENT*/;
7978 plci->B3_prot = 0 /*XPARENT*/;
7979 llc[1] = 2;
7980 llc[2] = 4;
7981 add_p(plci, LLC, llc);
7982 dlc[0] = 2;
7983 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7984 add_p(plci, DLC, dlc);
7985 return 0;
7986 }
7987
7988 if(!bp->length) /*default*/
7989 {
7990 dbug(1,dprintf("ret default"));
7991 add_p(plci,LLI,lli);
7992 plci->B2_prot = 0 /*X.75 */;
7993 plci->B3_prot = 0 /*XPARENT*/;
7994 llc[1] = 1;
7995 llc[2] = 4;
7996 add_p(plci, LLC, llc);
7997 dlc[0] = 2;
7998 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7999 add_p(plci, DLC, dlc);
8000 return 0;
8001 }
8002 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8003 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8004
8005 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8006 {
8007 bp_parms[6].length = 0;
8008 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8009 {
8010 dbug(1,dprintf("b-form.!"));
8011 return _WRONG_MESSAGE_FORMAT;
8012 }
8013 }
8014 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8015 {
8016 dbug(1,dprintf("b-form.!"));
8017 return _WRONG_MESSAGE_FORMAT;
8018 }
8019
8020 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8021 {
8022 if(GET_WORD(bp_parms[1].info)!=1
8023 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008024 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008025 }
8026 else if(plci->tel) return _B2_NOT_SUPPORTED;
8027
8028
8029 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8030 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8031 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8032 {
8033 add_p(plci,LLI,lli);
8034 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8035 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8036 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8037 llc[2] = 4;
8038 add_p(plci, LLC, llc);
8039 dlc[0] = 2;
8040 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8041 dlc[3] = 3; /* Addr A */
8042 dlc[4] = 1; /* Addr B */
8043 dlc[5] = 7; /* modulo mode */
8044 dlc[6] = 7; /* window size */
8045 dlc[7] = 0; /* XID len Lo */
8046 dlc[8] = 0; /* XID len Hi */
8047 for (i = 0; i < bp_parms[4].length; i++)
8048 dlc[9+i] = bp_parms[4].info[1+i];
8049 dlc[0] = (byte)(8 + bp_parms[4].length);
8050 add_p(plci, DLC, dlc);
8051 for (i = 0; i < bp_parms[5].length; i++)
8052 nlc[1+i] = bp_parms[5].info[1+i];
8053 nlc[0] = (byte)(bp_parms[5].length);
8054 add_p(plci, NLC, nlc);
8055 return 0;
8056 }
8057
8058
8059
8060 if ((GET_WORD(bp_parms[1].info) >= 32)
8061 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8062 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8063 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8064
8065 {
8066 return _B2_NOT_SUPPORTED;
8067 }
8068 if ((GET_WORD(bp_parms[2].info) >= 32)
8069 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8070 {
8071 return _B3_NOT_SUPPORTED;
8072 }
8073 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8074 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8075 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8076 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8077 {
8078 return (add_modem_b23 (plci, bp_parms));
8079 }
8080
8081 add_p(plci,LLI,lli);
8082
8083 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8084 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8085 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8086
8087 if(bp_parms[6].length)
8088 {
8089 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8090 {
8091 return _WRONG_MESSAGE_FORMAT;
8092 }
8093 switch(GET_WORD(global_config[0].info))
8094 {
8095 case 1:
8096 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8097 break;
8098 case 2:
8099 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8100 break;
8101 }
8102 }
8103 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8104
8105
8106 if (plci->B2_prot == B2_PIAFS)
8107 llc[1] = PIAFS_CRC;
8108 else
8109/* IMPLEMENT_PIAFS */
8110 {
8111 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8112 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8113 }
8114 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8115
8116 add_p(plci, LLC, llc);
8117
8118 dlc[0] = 2;
8119 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8120 header[GET_WORD(bp_parms[2].info)]);
8121
8122 b1_config = &bp_parms[3];
8123 nlc[0] = 0;
8124 if(plci->B3_prot == 4
8125 || plci->B3_prot == 5)
8126 {
8127 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8128 nlc[0] = sizeof(T30_INFO);
8129 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8130 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8131 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8132 if(b1_config->length>=2)
8133 {
8134 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8135 }
8136 }
8137 b2_config = &bp_parms[4];
8138
8139
8140 if (llc[1] == PIAFS_CRC)
8141 {
8142 if (plci->B3_prot != B3_TRANSPARENT)
8143 {
8144 return _B_STACK_NOT_SUPPORTED;
8145 }
8146 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8147 return _WRONG_MESSAGE_FORMAT;
8148 }
8149 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8150 dlc[3] = 0; /* Addr A */
8151 dlc[4] = 0; /* Addr B */
8152 dlc[5] = 0; /* modulo mode */
8153 dlc[6] = 0; /* window size */
8154 if (b2_config->length >= 7){
8155 dlc[ 7] = 7;
8156 dlc[ 8] = 0;
8157 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8158 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8159 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8160 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8161 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8162 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8163 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8164 dlc[ 0] = 15;
8165 if(b2_config->length >= 8) { /* PIAFS control abilities */
8166 dlc[ 7] = 10;
8167 dlc[16] = 2; /* Length of PIAFS extention */
8168 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8169 dlc[18] = b2_config_parms[4].info[0]; /* value */
8170 dlc[ 0] = 18;
8171 }
8172 }
8173 else /* default values, 64K, variable, no compression */
8174 {
8175 dlc[ 7] = 7;
8176 dlc[ 8] = 0;
8177 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8178 dlc[10] = 0x03; /* V.42bis P0 */
8179 dlc[11] = 0; /* V.42bis P0 */
8180 dlc[12] = 0; /* V.42bis P1 */
8181 dlc[13] = 0; /* V.42bis P1 */
8182 dlc[14] = 0; /* V.42bis P2 */
8183 dlc[15] = 0; /* V.42bis P2 */
8184 dlc[ 0] = 15;
8185 }
8186 add_p(plci, DLC, dlc);
8187 }
8188 else
8189
8190 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8191 {
8192 if (plci->B3_prot != B3_TRANSPARENT)
8193 return _B_STACK_NOT_SUPPORTED;
8194
8195 dlc[0] = 6;
8196 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8197 dlc[3] = 0x08;
8198 dlc[4] = 0x01;
8199 dlc[5] = 127;
8200 dlc[6] = 7;
8201 if (b2_config->length != 0)
8202 {
8203 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8204 return _WRONG_MESSAGE_FORMAT;
8205 }
8206 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8207 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8208 if (b2_config->info[3] != 128)
8209 {
8210 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8211 return _B2_PARM_NOT_SUPPORTED;
8212 }
8213 dlc[5] = (byte)(b2_config->info[3] - 1);
8214 dlc[6] = b2_config->info[4];
8215 if(llc[1]==V120_V42BIS){
8216 if (b2_config->length >= 10){
8217 dlc[ 7] = 6;
8218 dlc[ 8] = 0;
8219 dlc[ 9] = b2_config_parms[4].info[0];
8220 dlc[10] = b2_config_parms[4].info[1];
8221 dlc[11] = b2_config_parms[5].info[0];
8222 dlc[12] = b2_config_parms[5].info[1];
8223 dlc[13] = b2_config_parms[6].info[0];
8224 dlc[14] = b2_config_parms[6].info[1];
8225 dlc[ 0] = 14;
8226 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8227 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8228 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8229 }
8230 else {
8231 dlc[ 6] = 14;
8232 }
8233 }
8234 }
8235 }
8236 else
8237 {
8238 if(b2_config->length)
8239 {
8240 dbug(1,dprintf("B2-Config"));
8241 if(llc[1]==X75_V42BIS){
8242 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8243 {
8244 return _WRONG_MESSAGE_FORMAT;
8245 }
8246 }
8247 else {
8248 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8249 {
8250 return _WRONG_MESSAGE_FORMAT;
8251 }
8252 }
8253 /* if B2 Protocol is LAPD, b2_config structure is different */
8254 if(llc[1]==6)
8255 {
8256 dlc[0] = 4;
8257 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8258 else dlc[2] = 0x01;
8259 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8260 {
8261 SAPI = b2_config->info[2]; /* SAPI */
8262 }
8263 dlc[1] = SAPI;
8264 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8265 {
8266 dlc[3] = 127; /* Mode */
8267 }
8268 else
8269 {
8270 dlc[3] = 7; /* Mode */
8271 }
8272
8273 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8274 else dlc[4] = 1;
8275 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8276 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8277 }
8278 else
8279 {
8280 dlc[0] = (byte)(b2_config_parms[4].length+6);
8281 dlc[3] = b2_config->info[1];
8282 dlc[4] = b2_config->info[2];
8283 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8284 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8285 return _B2_PARM_NOT_SUPPORTED;
8286 }
8287
8288 dlc[5] = (byte)(b2_config->info[3]-1);
8289 dlc[6] = b2_config->info[4];
8290 if(dlc[6]>dlc[5]){
8291 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]));
8292 return _B2_PARM_NOT_SUPPORTED;
8293 }
8294
8295 if(llc[1]==X75_V42BIS) {
8296 if (b2_config->length >= 10){
8297 dlc[ 7] = 6;
8298 dlc[ 8] = 0;
8299 dlc[ 9] = b2_config_parms[4].info[0];
8300 dlc[10] = b2_config_parms[4].info[1];
8301 dlc[11] = b2_config_parms[5].info[0];
8302 dlc[12] = b2_config_parms[5].info[1];
8303 dlc[13] = b2_config_parms[6].info[0];
8304 dlc[14] = b2_config_parms[6].info[1];
8305 dlc[ 0] = 14;
8306 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8307 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8308 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8309 }
8310 else {
8311 dlc[ 6] = 14;
8312 }
8313
8314 }
8315 else {
8316 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8317 for(i=0; i<b2_config_parms[4].length; i++)
8318 dlc[11+i] = b2_config_parms[4].info[1+i];
8319 }
8320 }
8321 }
8322 }
8323 add_p(plci, DLC, dlc);
8324
8325 b3_config = &bp_parms[5];
8326 if(b3_config->length)
8327 {
8328 if(plci->B3_prot == 4
8329 || plci->B3_prot == 5)
8330 {
8331 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8332 {
8333 return _WRONG_MESSAGE_FORMAT;
8334 }
8335 i = GET_WORD((byte *)(b3_config_parms[0].info));
8336 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8337 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8338 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8339 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8340 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8341 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8342 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8343 {
8344
8345 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8346 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8347 {
8348 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8349 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8350 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8351 }
8352
8353 ((T30_INFO *)&nlc[1])->recording_properties =
8354 T30_RECORDING_WIDTH_ISO_A3 |
8355 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8356 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8357 }
8358 if(plci->B3_prot == 5)
8359 {
8360 if (i & 0x0002) /* Accept incoming fax-polling requests */
8361 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8362 if (i & 0x2000) /* Do not use MR compression */
8363 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8364 if (i & 0x4000) /* Do not use MMR compression */
8365 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8366 if (i & 0x8000) /* Do not use ECM */
8367 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8368 if (plci->fax_connect_info_length != 0)
8369 {
8370 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8371 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8372 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8373 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8374 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8375 }
8376 }
8377 /* copy station id to NLC */
8378 for(i=0; i<20; i++)
8379 {
8380 if(i<b3_config_parms[2].length)
8381 {
8382 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8383 }
8384 else
8385 {
8386 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8387 }
8388 }
8389 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8390 /* copy head line to NLC */
8391 if(b3_config_parms[3].length)
8392 {
8393
8394 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8395 if (pos != 0)
8396 {
8397 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8398 pos = 0;
8399 else
8400 {
8401 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8402 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403 len = (byte)b3_config_parms[2].length;
8404 if (len > 20)
8405 len = 20;
8406 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8407 {
8408 for (i = 0; i < len; i++)
8409 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8410 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8411 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412 }
8413 }
8414 }
8415
8416 len = (byte)b3_config_parms[3].length;
8417 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8418 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8419 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8420 nlc[0] += (byte)(pos + len);
8421 for (i = 0; i < len; i++)
8422 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8423 }
8424 else
8425 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8426
8427 plci->nsf_control_bits = 0;
8428 if(plci->B3_prot == 5)
8429 {
8430 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8431 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8432 {
8433 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8434 }
8435 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8436 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8437 {
8438 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8439 }
8440 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8441 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8442 {
8443 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8444 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8445 {
8446 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8447 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8448 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8449 }
8450 len = nlc[0];
8451 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8452 if (pos < plci->fax_connect_info_length)
8453 {
8454 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8455 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8456 }
8457 else
8458 nlc[++len] = 0;
8459 if (pos < plci->fax_connect_info_length)
8460 {
8461 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8462 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8463 }
8464 else
8465 nlc[++len] = 0;
8466 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8467 & (1L << PRIVATE_FAX_NONSTANDARD))
8468 {
8469 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8470 {
8471 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8472 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8473 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8474 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8475 }
8476 else
8477 {
8478 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8479 {
8480 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8481 nlc[++len] = 0;
8482 }
8483 else
8484 {
8485 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8486 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8487 nlc[++len] = (byte)(b3_config_parms[4].length);
8488 for (i = 0; i < b3_config_parms[4].length; i++)
8489 nlc[++len] = b3_config_parms[4].info[1+i];
8490 }
8491 }
8492 }
8493 nlc[0] = len;
8494 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8495 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8496 {
8497 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8498 }
8499 }
8500 }
8501
8502 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8503 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8504 for (i = 0; i < len; i++)
8505 plci->fax_connect_info_buffer[i] = nlc[1+i];
8506 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8507 i += ((T30_INFO *)&nlc[1])->head_line_len;
8508 while (i < nlc[0])
8509 plci->fax_connect_info_buffer[len++] = nlc[++i];
8510 plci->fax_connect_info_length = len;
8511 }
8512 else
8513 {
8514 nlc[0] = 14;
8515 if(b3_config->length!=16)
8516 return _B3_PARM_NOT_SUPPORTED;
8517 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8518 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8519 return _B3_PARM_NOT_SUPPORTED;
8520 nlc[13] = b3_config->info[13];
8521 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8522 return _B3_PARM_NOT_SUPPORTED;
8523 nlc[14] = b3_config->info[15];
8524 }
8525 }
8526 else
8527 {
8528 if (plci->B3_prot == 4
8529 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8530 }
8531 add_p(plci, NLC, nlc);
8532 return 0;
8533}
8534
8535/*----------------------------------------------------------------*/
8536/* make the same as add_b23, but only for the modem related */
8537/* L2 and L3 B-Chan protocol. */
8538/* */
8539/* Enabled L2 and L3 Configurations: */
8540/* If L1 == Modem all negotiation */
8541/* only L2 == Modem with full negotiation is allowed */
8542/* If L1 == Modem async or sync */
8543/* only L2 == Transparent is allowed */
8544/* L3 == Modem or L3 == Transparent are allowed */
8545/* B2 Configuration for modem: */
8546/* word : enable/disable compression, bitoptions */
8547/* B3 Configuration for modem: */
8548/* empty */
8549/*----------------------------------------------------------------*/
8550static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8551{
8552 static byte lli[12] = {1,1};
8553 static byte llc[3] = {2,0,0};
8554 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8555 API_PARSE mdm_config[2];
8556 word i;
8557 word b2_config = 0;
8558
8559 for(i=0;i<2;i++) mdm_config[i].length = 0;
8560 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8561
8562 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8563 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8564 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8565 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8566 {
8567 return (_B_STACK_NOT_SUPPORTED);
8568 }
8569 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8570 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8571 {
8572 return (_B_STACK_NOT_SUPPORTED);
8573 }
8574
8575 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8576 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8577
8578 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8579 {
8580 if (api_parse (&bp_parms[4].info[1],
8581 (word)bp_parms[4].length, "w",
8582 mdm_config))
8583 {
8584 return (_WRONG_MESSAGE_FORMAT);
8585 }
8586 b2_config = GET_WORD(mdm_config[0].info);
8587 }
8588
8589 /* OK, L2 is modem */
8590
8591 lli[0] = 1;
8592 lli[1] = 1;
8593 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8594 lli[1] |= 2;
8595 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8596 lli[1] |= 4;
8597
8598 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8599 lli[1] |= 0x10;
8600 if (plci->rx_dma_descriptor <= 0) {
8601 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8602 if (plci->rx_dma_descriptor >= 0)
8603 plci->rx_dma_descriptor++;
8604 }
8605 if (plci->rx_dma_descriptor > 0) {
8606 lli[1] |= 0x40;
8607 lli[0] = 6;
8608 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8609 lli[3] = (byte)plci->rx_dma_magic;
8610 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8611 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8612 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8613 }
8614 }
8615
8616 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8617 lli[1] |= 0x20;
8618 }
8619
8620 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8621 /*V42*/ 10 : /*V42_IN*/ 9;
8622 llc[2] = 4; /* pass L3 always transparent */
8623 add_p(plci, LLI, lli);
8624 add_p(plci, LLC, llc);
8625 i = 1;
8626 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8627 i += 2;
8628 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8629 {
8630 if (bp_parms[4].length)
8631 {
8632 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8633 dlc[i++] = 3; /* Addr A */
8634 dlc[i++] = 1; /* Addr B */
8635 dlc[i++] = 7; /* modulo mode */
8636 dlc[i++] = 7; /* window size */
8637 dlc[i++] = 0; /* XID len Lo */
8638 dlc[i++] = 0; /* XID len Hi */
8639
8640 if (b2_config & MDM_B2_DISABLE_V42bis)
8641 {
8642 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8643 }
8644 if (b2_config & MDM_B2_DISABLE_MNP)
8645 {
8646 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8647 }
8648 if (b2_config & MDM_B2_DISABLE_TRANS)
8649 {
8650 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8651 }
8652 if (b2_config & MDM_B2_DISABLE_V42)
8653 {
8654 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8655 }
8656 if (b2_config & MDM_B2_DISABLE_COMP)
8657 {
8658 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8659 }
8660 i++;
8661 }
8662 }
8663 else
8664 {
8665 dlc[i++] = 3; /* Addr A */
8666 dlc[i++] = 1; /* Addr B */
8667 dlc[i++] = 7; /* modulo mode */
8668 dlc[i++] = 7; /* window size */
8669 dlc[i++] = 0; /* XID len Lo */
8670 dlc[i++] = 0; /* XID len Hi */
8671 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8672 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8673 DLC_MODEMPROT_DISABLE_V42_DETECT |
8674 DLC_MODEMPROT_DISABLE_COMPRESSION;
8675 }
8676 dlc[0] = (byte)(i - 1);
8677/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8678 add_p(plci, DLC, dlc);
8679 return (0);
8680}
8681
8682
8683/*------------------------------------------------------------------*/
8684/* send a request for the signaling entity */
8685/*------------------------------------------------------------------*/
8686
8687void sig_req(PLCI * plci, byte req, byte Id)
8688{
8689 if(!plci) return;
8690 if(plci->adapter->adapter_disabled) return;
8691 dbug(1,dprintf("sig_req(%x)",req));
8692 if (req == REMOVE)
8693 plci->sig_remove_id = plci->Sig.Id;
8694 if(plci->req_in==plci->req_in_start) {
8695 plci->req_in +=2;
8696 plci->RBuffer[plci->req_in++] = 0;
8697 }
8698 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8699 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8700 plci->RBuffer[plci->req_in++] = req; /* request */
8701 plci->RBuffer[plci->req_in++] = 0; /* channel */
8702 plci->req_in_start = plci->req_in;
8703}
8704
8705/*------------------------------------------------------------------*/
8706/* send a request for the network layer entity */
8707/*------------------------------------------------------------------*/
8708
8709void nl_req_ncci(PLCI * plci, byte req, byte ncci)
8710{
8711 if(!plci) return;
8712 if(plci->adapter->adapter_disabled) return;
8713 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8714 if (req == REMOVE)
8715 {
8716 plci->nl_remove_id = plci->NL.Id;
8717 ncci_remove (plci, 0, (byte)(ncci != 0));
8718 ncci = 0;
8719 }
8720 if(plci->req_in==plci->req_in_start) {
8721 plci->req_in +=2;
8722 plci->RBuffer[plci->req_in++] = 0;
8723 }
8724 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8725 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8726 plci->RBuffer[plci->req_in++] = req; /* request */
8727 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8728 plci->req_in_start = plci->req_in;
8729}
8730
8731void send_req(PLCI * plci)
8732{
8733 ENTITY * e;
8734 word l;
8735/* word i; */
8736
8737 if(!plci) return;
8738 if(plci->adapter->adapter_disabled) return;
8739 channel_xmit_xon (plci);
8740
8741 /* if nothing to do, return */
8742 if(plci->req_in==plci->req_out) return;
8743 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8744
8745 if(plci->nl_req || plci->sig_req) return;
8746
8747 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8748 plci->req_out += 2;
8749 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8750 plci->req_out += l;
8751 if(plci->RBuffer[plci->req_out]==1)
8752 {
8753 e = &plci->NL;
8754 plci->req_out++;
8755 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8756 e->ReqCh = plci->RBuffer[plci->req_out++];
8757 if(!(e->Id & 0x1f))
8758 {
8759 e->Id = NL_ID;
8760 plci->RBuffer[plci->req_out-4] = CAI;
8761 plci->RBuffer[plci->req_out-3] = 1;
8762 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8763 plci->RBuffer[plci->req_out-1] = 0;
8764 l+=3;
8765 plci->nl_global_req = plci->nl_req;
8766 }
8767 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8768 }
8769 else
8770 {
8771 e = &plci->Sig;
8772 if(plci->RBuffer[plci->req_out])
8773 e->Id = plci->RBuffer[plci->req_out];
8774 plci->req_out++;
8775 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8776 e->ReqCh = plci->RBuffer[plci->req_out++];
8777 if(!(e->Id & 0x1f))
8778 plci->sig_global_req = plci->sig_req;
8779 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8780 }
8781 plci->XData[0].PLength = l;
8782 e->X = plci->XData;
8783 plci->adapter->request(e);
8784 dbug(1,dprintf("send_ok"));
8785}
8786
8787void send_data(PLCI * plci)
8788{
8789 DIVA_CAPI_ADAPTER * a;
8790 DATA_B3_DESC * data;
8791 NCCI *ncci_ptr;
8792 word ncci;
8793
8794 if (!plci->nl_req && plci->ncci_ring_list)
8795 {
8796 a = plci->adapter;
8797 ncci = plci->ncci_ring_list;
8798 do
8799 {
8800 ncci = a->ncci_next[ncci];
8801 ncci_ptr = &(a->ncci[ncci]);
8802 if (!(a->ncci_ch[ncci]
8803 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8804 {
8805 if (ncci_ptr->data_pending)
8806 {
8807 if ((a->ncci_state[ncci] == CONNECTED)
8808 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8809 || (plci->send_disc == ncci))
8810 {
8811 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8812 if ((plci->B2_prot == B2_V120_ASYNC)
8813 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8814 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8815 {
8816 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8817 plci->NData[1].PLength = data->Length;
8818 if (data->Flags & 0x10)
8819 plci->NData[0].P = v120_break_header;
8820 else
8821 plci->NData[0].P = v120_default_header;
8822 plci->NData[0].PLength = 1 ;
8823 plci->NL.XNum = 2;
8824 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8825 }
8826 else
8827 {
8828 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8829 plci->NData[0].PLength = data->Length;
8830 if (data->Flags & 0x10)
8831 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8832
8833 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8834 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8835
8836 else
8837 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8838 }
8839 plci->NL.X = plci->NData;
8840 plci->NL.ReqCh = a->ncci_ch[ncci];
8841 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008842 plci->data_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008843 plci->data_sent_ptr = data->P;
8844 a->request(&plci->NL);
8845 }
8846 else {
8847 cleanup_ncci_data (plci, ncci);
8848 }
8849 }
8850 else if (plci->send_disc == ncci)
8851 {
8852 /* dprintf("N_DISC"); */
8853 plci->NData[0].PLength = 0;
8854 plci->NL.ReqCh = a->ncci_ch[ncci];
8855 plci->NL.Req = plci->nl_req = N_DISC;
8856 a->request(&plci->NL);
8857 plci->command = _DISCONNECT_B3_R;
8858 plci->send_disc = 0;
8859 }
8860 }
8861 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8862 plci->ncci_ring_list = ncci;
8863 }
8864}
8865
8866void listen_check(DIVA_CAPI_ADAPTER * a)
8867{
8868 word i,j;
8869 PLCI * plci;
8870 byte activnotifiedcalls = 0;
8871
8872 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8873 if (!remove_started && !a->adapter_disabled)
8874 {
8875 for(i=0;i<a->max_plci;i++)
8876 {
8877 plci = &(a->plci[i]);
8878 if(plci->notifiedcall) activnotifiedcalls++;
8879 }
8880 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8881
8882 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8883 if((j=get_plci(a))) {
8884 a->listen_active++;
8885 plci = &a->plci[j-1];
8886 plci->State = LISTENING;
8887
8888 add_p(plci,OAD,"\x01\xfd");
8889
8890 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8891
8892 add_p(plci,CAI,"\x01\xc0");
8893 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8894 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8895 add_p(plci,SHIFT|6,NULL);
8896 add_p(plci,SIN,"\x02\x00\x00");
8897 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8898 sig_req(plci,ASSIGN,DSIG_ID);
8899 send_req(plci);
8900 }
8901 }
8902 }
8903}
8904
8905/*------------------------------------------------------------------*/
8906/* functions for all parameters sent in INDs */
8907/*------------------------------------------------------------------*/
8908
8909void IndParse(PLCI * plci, word * parms_id, byte ** parms, byte multiIEsize)
8910{
8911 word ploc; /* points to current location within packet */
8912 byte w;
8913 byte wlen;
8914 byte codeset,lock;
8915 byte * in;
8916 word i;
8917 word code;
8918 word mIEindex = 0;
8919 ploc = 0;
8920 codeset = 0;
8921 lock = 0;
8922
8923 in = plci->Sig.RBuffer->P;
8924 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8925 { /* element but parms array is larger */
8926 parms[i] = (byte *)"";
8927 }
8928 for(i=0; i<multiIEsize; i++)
8929 {
8930 parms[i] = (byte *)"";
8931 }
8932
8933 while(ploc<plci->Sig.RBuffer->length-1) {
8934
8935 /* read information element id and length */
8936 w = in[ploc];
8937
8938 if(w & 0x80) {
8939/* w &=0xf0; removed, cannot detect congestion levels */
8940/* upper 4 bit masked with w==SHIFT now */
8941 wlen = 0;
8942 }
8943 else {
8944 wlen = (byte)(in[ploc+1]+1);
8945 }
8946 /* check if length valid (not exceeding end of packet) */
8947 if((ploc+wlen) > 270) return ;
8948 if(lock & 0x80) lock &=0x7f;
8949 else codeset = lock;
8950
8951 if((w&0xf0)==SHIFT) {
8952 codeset = in[ploc];
8953 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8954 codeset &=7;
8955 lock |=0x80;
8956 }
8957 else {
8958 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8959 else code = w;
8960 code |= (codeset<<8);
8961
8962 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8963
8964 if(i<parms_id[0]+1) {
8965 if(!multiIEsize) { /* with multiIEs use next field index, */
8966 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8967 }
8968
8969 parms[mIEindex] = &in[ploc+1];
8970 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8971 if(parms_id[i]==OAD
8972 || parms_id[i]==CONN_NR
8973 || parms_id[i]==CAD) {
8974 if(in[ploc+2] &0x80) {
8975 in[ploc+0] = (byte)(in[ploc+1]+1);
8976 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8977 in[ploc+2] = 0x80;
8978 parms[mIEindex] = &in[ploc];
8979 }
8980 }
8981 mIEindex++; /* effects multiIEs only */
8982 }
8983 }
8984
8985 ploc +=(wlen+1);
8986 }
8987 return ;
8988}
8989
8990/*------------------------------------------------------------------*/
8991/* try to match a cip from received BC and HLC */
8992/*------------------------------------------------------------------*/
8993
8994byte ie_compare(byte * ie1, byte * ie2)
8995{
8996 word i;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008997 if(!ie1 || ! ie2) return false;
8998 if(!ie1[0]) return false;
8999 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9000 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009001}
9002
9003word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc)
9004{
9005 word i;
9006 word j;
9007
9008 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9009
9010 for(j=16;j<29 &&
9011 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9012 if(j==29) return i;
9013 return j;
9014}
9015
9016
9017static byte AddInfo(byte **add_i,
9018 byte **fty_i,
9019 byte *esc_chi,
9020 byte *facility)
9021{
9022 byte i;
9023 byte j;
9024 byte k;
9025 byte flen;
9026 byte len=0;
9027 /* facility is a nested structure */
9028 /* FTY can be more than once */
9029
9030 if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9031 {
9032 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9033 }
9034
9035 else
9036 {
9037 add_i[0] = (byte *)"";
9038 }
9039 if(!fty_i[0][0])
9040 {
9041 add_i[3] = (byte *)"";
9042 }
9043 else
9044 { /* facility array found */
9045 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9046 {
9047 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9048 len += fty_i[i][0];
9049 len += 2;
9050 flen=fty_i[i][0];
9051 facility[j++]=0x1c; /* copy fac IE */
9052 for(k=0;k<=flen;k++,j++)
9053 {
9054 facility[j]=fty_i[i][k];
9055/* dbug(1,dprintf("%x ",facility[j])); */
9056 }
9057 }
9058 facility[0] = len;
9059 add_i[3] = facility;
9060 }
9061/* dbug(1,dprintf("FacArrLen=%d ",len)); */
9062 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9063 len += 4; /* calculate length of all */
9064 return(len);
9065}
9066
9067/*------------------------------------------------------------------*/
9068/* voice and codec features */
9069/*------------------------------------------------------------------*/
9070
9071void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER * a)
9072{
9073 byte voice_chi[] = "\x02\x18\x01";
9074 byte channel;
9075
9076 channel = chi[chi[0]]&0x3;
9077 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9078 voice_chi[2] = (channel) ? channel : 1;
9079 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9080 add_p(plci,ESC,voice_chi); /* Channel */
9081 sig_req(plci,TEL_CTRL,0);
9082 send_req(plci);
9083 if(a->AdvSignalPLCI)
9084 {
9085 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9086 }
9087}
9088
9089void VoiceChannelOff(PLCI *plci)
9090{
9091 dbug(1,dprintf("ExtDevOFF"));
9092 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9093 sig_req(plci,TEL_CTRL,0);
9094 send_req(plci);
9095 if(plci->adapter->AdvSignalPLCI)
9096 {
9097 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9098 }
9099}
9100
9101
9102word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte hook_listen)
9103{
9104 word j;
9105 PLCI *splci;
9106
9107 /* check if hardware supports handset with hook states (adv.codec) */
9108 /* or if just a on board codec is supported */
9109 /* the advanced codec plci is just for internal use */
9110
9111 /* diva Pro with on-board codec: */
9112 if(a->profile.Global_Options & HANDSET)
9113 {
9114 /* new call, but hook states are already signalled */
9115 if(a->AdvCodecFLAG)
9116 {
9117 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9118 {
9119 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9120 return 0x2001; /* codec in use by another application */
9121 }
9122 if(plci!=0)
9123 {
9124 a->AdvSignalPLCI = plci;
9125 plci->tel=ADV_VOICE;
9126 }
9127 return 0; /* adv codec still used */
9128 }
9129 if((j=get_plci(a)))
9130 {
9131 splci = &a->plci[j-1];
9132 splci->tel = CODEC_PERMANENT;
9133 /* hook_listen indicates if a facility_req with handset/hook support */
9134 /* was sent. Otherwise if just a call on an external device was made */
9135 /* the codec will be used but the hook info will be discarded (just */
9136 /* the external controller is in use */
9137 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9138 else
9139 {
9140 splci->State = ADVANCED_VOICE_NOSIG;
9141 if(plci)
9142 {
9143 plci->spoofed_msg = SPOOFING_REQUIRED;
9144 }
9145 /* indicate D-ch connect if */
9146 } /* codec is connected OK */
9147 if(plci!=0)
9148 {
9149 a->AdvSignalPLCI = plci;
9150 plci->tel=ADV_VOICE;
9151 }
9152 a->AdvSignalAppl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009153 a->AdvCodecFLAG = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009154 a->AdvCodecPLCI = splci;
9155 add_p(splci,CAI,"\x01\x15");
9156 add_p(splci,LLI,"\x01\x00");
9157 add_p(splci,ESC,"\x02\x18\x00");
9158 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9159 splci->internal_command = PERM_COD_ASSIGN;
9160 dbug(1,dprintf("Codec Assign"));
9161 sig_req(splci,ASSIGN,DSIG_ID);
9162 send_req(splci);
9163 }
9164 else
9165 {
9166 return 0x2001; /* wrong state, no more plcis */
9167 }
9168 }
9169 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9170 {
9171 if(hook_listen) return 0x300B; /* Facility not supported */
9172 /* no hook with SCOM */
9173 if(plci!=0) plci->tel = CODEC;
9174 dbug(1,dprintf("S/SCOM codec"));
9175 /* first time we use the scom-s codec we must shut down the internal */
9176 /* handset application of the card. This can be done by an assign with */
9177 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9178 if(!a->scom_appl_disable){
9179 if((j=get_plci(a))) {
9180 splci = &a->plci[j-1];
9181 add_p(splci,CAI,"\x01\x80");
9182 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9183 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9184 send_req(splci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009185 a->scom_appl_disable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009186 }
9187 else{
9188 return 0x2001; /* wrong state, no more plcis */
9189 }
9190 }
9191 }
9192 else return 0x300B; /* Facility not supported */
9193
9194 return 0;
9195}
9196
9197
9198void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9199{
9200
9201 dbug(1,dprintf("CodecIdCheck"));
9202
9203 if(a->AdvSignalPLCI == plci)
9204 {
9205 dbug(1,dprintf("PLCI owns codec"));
9206 VoiceChannelOff(a->AdvCodecPLCI);
9207 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9208 {
9209 dbug(1,dprintf("remove temp codec PLCI"));
9210 plci_remove(a->AdvCodecPLCI);
9211 a->AdvCodecFLAG = 0;
9212 a->AdvCodecPLCI = NULL;
9213 a->AdvSignalAppl = NULL;
9214 }
9215 a->AdvSignalPLCI = NULL;
9216 }
9217}
9218
9219/* -------------------------------------------------------------------
9220 Ask for physical address of card on PCI bus
9221 ------------------------------------------------------------------- */
9222static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9223 IDI_SYNC_REQ * preq) {
9224 a->sdram_bar = 0;
9225 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9226 ENTITY * e = (ENTITY *)preq;
9227
9228 e->user[0] = a->Id - 1;
9229 preq->xdi_sdram_bar.info.bar = 0;
9230 preq->xdi_sdram_bar.Req = 0;
9231 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9232
9233 (*(a->request))(e);
9234
9235 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9236 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9237 }
9238}
9239
9240/* -------------------------------------------------------------------
9241 Ask XDI about extended features
9242 ------------------------------------------------------------------- */
9243static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9244 IDI_SYNC_REQ * preq;
9245 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9246
9247 char features[4];
9248 preq = (IDI_SYNC_REQ *)&buffer[0];
9249
9250 if (!diva_xdi_extended_features) {
9251 ENTITY * e = (ENTITY *)preq;
9252 diva_xdi_extended_features |= 0x80000000;
9253
9254 e->user[0] = a->Id - 1;
9255 preq->xdi_extended_features.Req = 0;
9256 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9257 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9258 preq->xdi_extended_features.info.features = &features[0];
9259
9260 (*(a->request))(e);
9261
9262 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9263 /*
9264 Check features located in the byte '0'
9265 */
9266 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9267 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9268 }
9269 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9270 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9271 dbug(1,dprintf("XDI provides RxDMA"));
9272 }
9273 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9274 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9275 }
9276 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9277 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9278 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9279 }
9280
9281 }
9282 }
9283
9284 diva_ask_for_xdi_sdram_bar (a, preq);
9285}
9286
9287/*------------------------------------------------------------------*/
9288/* automatic law */
9289/*------------------------------------------------------------------*/
9290/* called from OS specific part after init time to get the Law */
9291/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9292void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9293{
9294 word j;
9295 PLCI *splci;
9296
9297 if(a->automatic_law) {
9298 return;
9299 }
9300 if((j=get_plci(a))) {
9301 diva_get_extended_adapter_features (a);
9302 splci = &a->plci[j-1];
9303 a->automatic_lawPLCI = splci;
9304 a->automatic_law = 1;
9305 add_p(splci,CAI,"\x01\x80");
9306 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9307 splci->internal_command = USELAW_REQ;
9308 splci->command = 0;
9309 splci->number = 0;
9310 sig_req(splci,ASSIGN,DSIG_ID);
9311 send_req(splci);
9312 }
9313}
9314
9315/* called from OS specific part if an application sends an Capi20Release */
9316word CapiRelease(word Id)
9317{
9318 word i, j, appls_found;
9319 PLCI *plci;
9320 APPL *this;
9321 DIVA_CAPI_ADAPTER *a;
9322
9323 if (!Id)
9324 {
9325 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9326 return (_WRONG_APPL_ID);
9327 }
9328
9329 this = &application[Id-1]; /* get application pointer */
9330
9331 for(i=0,appls_found=0; i<max_appl; i++)
9332 {
9333 if(application[i].Id) /* an application has been found */
9334 {
9335 appls_found++;
9336 }
9337 }
9338
9339 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9340 {
9341 a = &adapter[i];
9342 if (a->request)
9343 {
9344 a->Info_Mask[Id-1] = 0;
9345 a->CIP_Mask[Id-1] = 0;
9346 a->Notification_Mask[Id-1] = 0;
9347 a->codec_listen[Id-1] = NULL;
9348 a->requested_options_table[Id-1] = 0;
9349 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9350 { /* with this application */
9351 plci = &a->plci[j];
9352 if(plci->Id) /* if plci owns no application */
9353 { /* it may be not jet connected */
9354 if(plci->State==INC_CON_PENDING
9355 || plci->State==INC_CON_ALERT)
9356 {
9357 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9358 {
9359 clear_c_ind_mask_bit (plci, (word)(Id-1));
9360 if(c_ind_mask_empty (plci))
9361 {
9362 sig_req(plci,HANGUP,0);
9363 send_req(plci);
9364 plci->State = OUTG_DIS_PENDING;
9365 }
9366 }
9367 }
9368 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9369 {
9370 clear_c_ind_mask_bit (plci, (word)(Id-1));
9371 if(c_ind_mask_empty (plci))
9372 {
9373 if(!plci->appl)
9374 {
9375 plci_remove(plci);
9376 plci->State = IDLE;
9377 }
9378 }
9379 }
9380 if(plci->appl==this)
9381 {
9382 plci->appl = NULL;
9383 plci_remove(plci);
9384 plci->State = IDLE;
9385 }
9386 }
9387 }
9388 listen_check(a);
9389
9390 if(a->flag_dynamic_l1_down)
9391 {
9392 if(appls_found==1) /* last application does a capi release */
9393 {
9394 if((j=get_plci(a)))
9395 {
9396 plci = &a->plci[j-1];
9397 plci->command = 0;
9398 add_p(plci,OAD,"\x01\xfd");
9399 add_p(plci,CAI,"\x01\x80");
9400 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9401 add_p(plci,SHIFT|6,NULL);
9402 add_p(plci,SIN,"\x02\x00\x00");
9403 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9404 sig_req(plci,ASSIGN,DSIG_ID);
9405 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9406 sig_req(plci,SIG_CTRL,0);
9407 send_req(plci);
9408 }
9409 }
9410 }
9411 if(a->AdvSignalAppl==this)
9412 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009413 this->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009414 if (a->AdvCodecPLCI)
9415 {
9416 plci_remove(a->AdvCodecPLCI);
9417 a->AdvCodecPLCI->tel = 0;
9418 a->AdvCodecPLCI->adv_nl = 0;
9419 }
9420 a->AdvSignalAppl = NULL;
9421 a->AdvSignalPLCI = NULL;
9422 a->AdvCodecFLAG = 0;
9423 a->AdvCodecPLCI = NULL;
9424 }
9425 }
9426 }
9427
9428 this->Id = 0;
9429
9430 return GOOD;
9431}
9432
9433static word plci_remove_check(PLCI *plci)
9434{
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009435 if(!plci) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009436 if(!plci->NL.Id && c_ind_mask_empty (plci))
9437 {
9438 if(plci->Sig.Id == 0xff)
9439 plci->Sig.Id = 0;
9440 if(!plci->Sig.Id)
9441 {
9442 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9443 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9444 if (plci->Id)
9445 {
9446 CodecIdCheck(plci->adapter, plci);
9447 clear_b1_config (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009448 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009449 plci_free_msg_in_queue (plci);
9450 channel_flow_control_remove (plci);
9451 plci->Id = 0;
9452 plci->State = IDLE;
9453 plci->channels = 0;
9454 plci->appl = NULL;
9455 plci->notifiedcall = 0;
9456 }
9457 listen_check(plci->adapter);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009458 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009459 }
9460 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009461 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009462}
9463
9464
9465/*------------------------------------------------------------------*/
9466
9467static byte plci_nl_busy (PLCI *plci)
9468{
9469 /* only applicable for non-multiplexed protocols */
9470 return (plci->nl_req
9471 || (plci->ncci_ring_list
9472 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9473 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9474}
9475
9476
9477/*------------------------------------------------------------------*/
9478/* DTMF facilities */
9479/*------------------------------------------------------------------*/
9480
9481
9482static struct
9483{
9484 byte send_mask;
9485 byte listen_mask;
9486 byte character;
9487 byte code;
9488} dtmf_digit_map[] =
9489{
9490 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9491 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9492 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9493 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9494 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9495 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9496 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9497 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9498 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9499 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9500 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9501 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9502 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9503 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9504 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9505 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9506 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9507 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9508 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9509 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9510
9511 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9512 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9513 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9514 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9515 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9516 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9517 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9518 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9519 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9520 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9521 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9522 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9523 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9524 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9525 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9526 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9527 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9528 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9529 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9530 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9531 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9532 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9533 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9534 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9535 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9536 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9537 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9538 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9539 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9540 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9541 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9542 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9543 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9544 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9545 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9546 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9547 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9548 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9549 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9550 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9551 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9552 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9553 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9554 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9555 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9556 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9557 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9558 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9559 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9560 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9561 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9562 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9563
9564};
9565
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -08009566#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009567
9568
9569static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9570{
9571 word min_digit_duration, min_gap_duration;
9572
9573 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9574 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9575 (char *)(FILE_), __LINE__, enable_mask));
9576
9577 if (enable_mask != 0)
9578 {
9579 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9580 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9581 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9582 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9583 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9584 plci->NData[0].PLength = 5;
9585
9586 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9587 plci->NData[0].PLength += 2;
9588 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9589
9590 }
9591 else
9592 {
9593 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9594 plci->NData[0].PLength = 1;
9595
9596 capidtmf_recv_disable (&(plci->capidtmf_state));
9597
9598 }
9599 plci->NData[0].P = plci->internal_req_buffer;
9600 plci->NL.X = plci->NData;
9601 plci->NL.ReqCh = 0;
9602 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9603 plci->adapter->request (&plci->NL);
9604}
9605
9606
9607static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9608{
9609 word w, i;
9610
9611 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9612 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9613 (char *)(FILE_), __LINE__, digit_count));
9614
9615 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9616 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9617 PUT_WORD (&plci->internal_req_buffer[1], w);
9618 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9619 PUT_WORD (&plci->internal_req_buffer[3], w);
9620 for (i = 0; i < digit_count; i++)
9621 {
9622 w = 0;
9623 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9624 && (digit_buffer[i] != dtmf_digit_map[w].character))
9625 {
9626 w++;
9627 }
9628 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9629 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9630 }
9631 plci->NData[0].PLength = 5 + digit_count;
9632 plci->NData[0].P = plci->internal_req_buffer;
9633 plci->NL.X = plci->NData;
9634 plci->NL.ReqCh = 0;
9635 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9636 plci->adapter->request (&plci->NL);
9637}
9638
9639
9640static void dtmf_rec_clear_config (PLCI *plci)
9641{
9642
9643 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9644 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9645 (char *)(FILE_), __LINE__));
9646
9647 plci->dtmf_rec_active = 0;
9648 plci->dtmf_rec_pulse_ms = 0;
9649 plci->dtmf_rec_pause_ms = 0;
9650
9651 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9652
9653}
9654
9655
9656static void dtmf_send_clear_config (PLCI *plci)
9657{
9658
9659 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9660 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9661 (char *)(FILE_), __LINE__));
9662
9663 plci->dtmf_send_requests = 0;
9664 plci->dtmf_send_pulse_ms = 0;
9665 plci->dtmf_send_pause_ms = 0;
9666}
9667
9668
9669static void dtmf_prepare_switch (dword Id, PLCI *plci)
9670{
9671
9672 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9673 UnMapId (Id), (char *)(FILE_), __LINE__));
9674
9675 while (plci->dtmf_send_requests != 0)
9676 dtmf_confirmation (Id, plci);
9677}
9678
9679
9680static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9681{
9682
9683 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9684 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9685
9686 return (GOOD);
9687}
9688
9689
9690static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9691{
9692 word Info;
9693
9694 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9695 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9696
9697 Info = GOOD;
9698 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9699 {
9700 switch (plci->adjust_b_state)
9701 {
9702 case ADJUST_B_RESTORE_DTMF_1:
9703 plci->internal_command = plci->adjust_b_command;
9704 if (plci_nl_busy (plci))
9705 {
9706 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9707 break;
9708 }
9709 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9710 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9711 break;
9712 case ADJUST_B_RESTORE_DTMF_2:
9713 if ((Rc != OK) && (Rc != OK_FC))
9714 {
9715 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9716 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9717 Info = _WRONG_STATE;
9718 break;
9719 }
9720 break;
9721 }
9722 }
9723 return (Info);
9724}
9725
9726
9727static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9728{
9729 word internal_command, Info;
9730 byte mask;
9731 byte result[4];
9732
9733 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9734 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9735 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9736 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9737
9738 Info = GOOD;
9739 result[0] = 2;
9740 PUT_WORD (&result[1], DTMF_SUCCESS);
9741 internal_command = plci->internal_command;
9742 plci->internal_command = 0;
9743 mask = 0x01;
9744 switch (plci->dtmf_cmd)
9745 {
9746
9747 case DTMF_LISTEN_TONE_START:
9748 mask <<= 1;
9749 case DTMF_LISTEN_MF_START:
9750 mask <<= 1;
9751
9752 case DTMF_LISTEN_START:
9753 switch (internal_command)
9754 {
9755 default:
9756 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9757 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9758 case DTMF_COMMAND_1:
9759 if (adjust_b_process (Id, plci, Rc) != GOOD)
9760 {
9761 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9762 UnMapId (Id), (char *)(FILE_), __LINE__));
9763 Info = _FACILITY_NOT_SUPPORTED;
9764 break;
9765 }
9766 if (plci->internal_command)
9767 return;
9768 case DTMF_COMMAND_2:
9769 if (plci_nl_busy (plci))
9770 {
9771 plci->internal_command = DTMF_COMMAND_2;
9772 return;
9773 }
9774 plci->internal_command = DTMF_COMMAND_3;
9775 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9776 return;
9777 case DTMF_COMMAND_3:
9778 if ((Rc != OK) && (Rc != OK_FC))
9779 {
9780 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9781 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9782 Info = _FACILITY_NOT_SUPPORTED;
9783 break;
9784 }
9785
9786 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9787
9788 plci->dtmf_rec_active |= mask;
9789 break;
9790 }
9791 break;
9792
9793
9794 case DTMF_LISTEN_TONE_STOP:
9795 mask <<= 1;
9796 case DTMF_LISTEN_MF_STOP:
9797 mask <<= 1;
9798
9799 case DTMF_LISTEN_STOP:
9800 switch (internal_command)
9801 {
9802 default:
9803 plci->dtmf_rec_active &= ~mask;
9804 if (plci->dtmf_rec_active)
9805 break;
9806/*
9807 case DTMF_COMMAND_1:
9808 if (plci->dtmf_rec_active)
9809 {
9810 if (plci_nl_busy (plci))
9811 {
9812 plci->internal_command = DTMF_COMMAND_1;
9813 return;
9814 }
9815 plci->dtmf_rec_active &= ~mask;
9816 plci->internal_command = DTMF_COMMAND_2;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009817 dtmf_enable_receiver (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009818 return;
9819 }
9820 Rc = OK;
9821 case DTMF_COMMAND_2:
9822 if ((Rc != OK) && (Rc != OK_FC))
9823 {
9824 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9825 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9826 Info = _FACILITY_NOT_SUPPORTED;
9827 break;
9828 }
9829*/
9830 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9831 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9832 case DTMF_COMMAND_3:
9833 if (adjust_b_process (Id, plci, Rc) != GOOD)
9834 {
9835 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9836 UnMapId (Id), (char *)(FILE_), __LINE__));
9837 Info = _FACILITY_NOT_SUPPORTED;
9838 break;
9839 }
9840 if (plci->internal_command)
9841 return;
9842 break;
9843 }
9844 break;
9845
9846
9847 case DTMF_SEND_TONE:
9848 mask <<= 1;
9849 case DTMF_SEND_MF:
9850 mask <<= 1;
9851
9852 case DTMF_DIGITS_SEND:
9853 switch (internal_command)
9854 {
9855 default:
9856 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9857 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9858 DTMF_COMMAND_1);
9859 case DTMF_COMMAND_1:
9860 if (adjust_b_process (Id, plci, Rc) != GOOD)
9861 {
9862 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9863 UnMapId (Id), (char *)(FILE_), __LINE__));
9864 Info = _FACILITY_NOT_SUPPORTED;
9865 break;
9866 }
9867 if (plci->internal_command)
9868 return;
9869 case DTMF_COMMAND_2:
9870 if (plci_nl_busy (plci))
9871 {
9872 plci->internal_command = DTMF_COMMAND_2;
9873 return;
9874 }
9875 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9876 plci->internal_command = DTMF_COMMAND_3;
9877 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9878 return;
9879 case DTMF_COMMAND_3:
9880 if ((Rc != OK) && (Rc != OK_FC))
9881 {
9882 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9883 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9884 if (plci->dtmf_send_requests != 0)
9885 (plci->dtmf_send_requests)--;
9886 Info = _FACILITY_NOT_SUPPORTED;
9887 break;
9888 }
9889 return;
9890 }
9891 break;
9892 }
9893 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9894 "wws", Info, SELECTOR_DTMF, result);
9895}
9896
9897
9898static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9899{
9900 word Info;
9901 word i, j;
9902 byte mask;
9903 API_PARSE dtmf_parms[5];
9904 byte result[40];
9905
9906 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9907 UnMapId (Id), (char *)(FILE_), __LINE__));
9908
9909 Info = GOOD;
9910 result[0] = 2;
9911 PUT_WORD (&result[1], DTMF_SUCCESS);
9912 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9913 {
9914 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9915 UnMapId (Id), (char *)(FILE_), __LINE__));
9916 Info = _FACILITY_NOT_SUPPORTED;
9917 }
9918 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9919 {
9920 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9921 UnMapId (Id), (char *)(FILE_), __LINE__));
9922 Info = _WRONG_MESSAGE_FORMAT;
9923 }
9924
9925 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9926 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9927 {
9928 if (!((a->requested_options_table[appl->Id-1])
9929 & (1L << PRIVATE_DTMF_TONE)))
9930 {
9931 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9932 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9933 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9934 }
9935 else
9936 {
9937 for (i = 0; i < 32; i++)
9938 result[4 + i] = 0;
9939 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9940 {
9941 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9942 {
9943 if (dtmf_digit_map[i].listen_mask != 0)
9944 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9945 }
9946 }
9947 else
9948 {
9949 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9950 {
9951 if (dtmf_digit_map[i].send_mask != 0)
9952 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9953 }
9954 }
9955 result[0] = 3 + 32;
9956 result[3] = 32;
9957 }
9958 }
9959
9960 else if (plci == NULL)
9961 {
9962 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9963 UnMapId (Id), (char *)(FILE_), __LINE__));
9964 Info = _WRONG_IDENTIFIER;
9965 }
9966 else
9967 {
9968 if (!plci->State
9969 || !plci->NL.Id || plci->nl_remove_id)
9970 {
9971 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9972 UnMapId (Id), (char *)(FILE_), __LINE__));
9973 Info = _WRONG_STATE;
9974 }
9975 else
9976 {
9977 plci->command = 0;
9978 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9979 mask = 0x01;
9980 switch (plci->dtmf_cmd)
9981 {
9982
9983 case DTMF_LISTEN_TONE_START:
9984 case DTMF_LISTEN_TONE_STOP:
9985 mask <<= 1;
9986 case DTMF_LISTEN_MF_START:
9987 case DTMF_LISTEN_MF_STOP:
9988 mask <<= 1;
9989 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9990 & (1L << PRIVATE_DTMF_TONE)))
9991 {
9992 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9993 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9994 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9995 break;
9996 }
9997
9998 case DTMF_LISTEN_START:
9999 case DTMF_LISTEN_STOP:
10000 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10001 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10002 {
10003 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10004 UnMapId (Id), (char *)(FILE_), __LINE__));
10005 Info = _FACILITY_NOT_SUPPORTED;
10006 break;
10007 }
10008 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10009 {
10010 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10011 {
10012 plci->dtmf_rec_pulse_ms = 0;
10013 plci->dtmf_rec_pause_ms = 0;
10014 }
10015 else
10016 {
10017 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10018 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10019 }
10020 }
10021 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010022 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010023
10024
10025 case DTMF_SEND_TONE:
10026 mask <<= 1;
10027 case DTMF_SEND_MF:
10028 mask <<= 1;
10029 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10030 & (1L << PRIVATE_DTMF_TONE)))
10031 {
10032 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10033 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10034 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10035 break;
10036 }
10037
10038 case DTMF_DIGITS_SEND:
10039 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10040 {
10041 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10042 UnMapId (Id), (char *)(FILE_), __LINE__));
10043 Info = _WRONG_MESSAGE_FORMAT;
10044 break;
10045 }
10046 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10047 {
10048 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10049 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10050 }
10051 i = 0;
10052 j = 0;
10053 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10054 {
10055 j = 0;
10056 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10057 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10058 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10059 {
10060 j++;
10061 }
10062 i++;
10063 }
10064 if (j == DTMF_DIGIT_MAP_ENTRIES)
10065 {
10066 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10067 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10068 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10069 break;
10070 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080010071 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010072 {
10073 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10074 UnMapId (Id), (char *)(FILE_), __LINE__));
10075 Info = _WRONG_STATE;
10076 break;
10077 }
10078 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10079 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010080 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010081
10082 default:
10083 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10084 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10085 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10086 }
10087 }
10088 }
10089 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10090 "wws", Info, SELECTOR_DTMF, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010091 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010092}
10093
10094
10095static void dtmf_confirmation (dword Id, PLCI *plci)
10096{
10097 word Info;
10098 word i;
10099 byte result[4];
10100
10101 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10102 UnMapId (Id), (char *)(FILE_), __LINE__));
10103
10104 Info = GOOD;
10105 result[0] = 2;
10106 PUT_WORD (&result[1], DTMF_SUCCESS);
10107 if (plci->dtmf_send_requests != 0)
10108 {
10109 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10110 "wws", GOOD, SELECTOR_DTMF, result);
10111 (plci->dtmf_send_requests)--;
10112 for (i = 0; i < plci->dtmf_send_requests; i++)
10113 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10114 }
10115}
10116
10117
10118static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10119{
10120 word i, j, n;
10121
10122 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10123 UnMapId (Id), (char *)(FILE_), __LINE__));
10124
10125 n = 0;
10126 for (i = 1; i < length; i++)
10127 {
10128 j = 0;
10129 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10130 && ((msg[i] != dtmf_digit_map[j].code)
10131 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10132 {
10133 j++;
10134 }
10135 if (j < DTMF_DIGIT_MAP_ENTRIES)
10136 {
10137
10138 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10139 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10140 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10141 {
10142 if (n + 1 == i)
10143 {
10144 for (i = length; i > n + 1; i--)
10145 msg[i] = msg[i - 1];
10146 length++;
10147 i++;
10148 }
10149 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10150 }
10151 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10152
10153 msg[++n] = dtmf_digit_map[j].character;
10154 }
10155 }
10156 if (n != 0)
10157 {
10158 msg[0] = (byte) n;
10159 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10160 }
10161}
10162
10163
10164/*------------------------------------------------------------------*/
10165/* DTMF parameters */
10166/*------------------------------------------------------------------*/
10167
10168static void dtmf_parameter_write (PLCI *plci)
10169{
10170 word i;
10171 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10172
10173 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10174 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10175 (char *)(FILE_), __LINE__));
10176
10177 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10178 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10179 for (i = 0; i < plci->dtmf_parameter_length; i++)
10180 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10181 add_p (plci, FTY, parameter_buffer);
10182 sig_req (plci, TEL_CTRL, 0);
10183 send_req (plci);
10184}
10185
10186
10187static void dtmf_parameter_clear_config (PLCI *plci)
10188{
10189
10190 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10191 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10192 (char *)(FILE_), __LINE__));
10193
10194 plci->dtmf_parameter_length = 0;
10195}
10196
10197
10198static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10199{
10200
10201 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10202 UnMapId (Id), (char *)(FILE_), __LINE__));
10203
10204}
10205
10206
10207static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10208{
10209
10210 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10211 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10212
10213 return (GOOD);
10214}
10215
10216
10217static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10218{
10219 word Info;
10220
10221 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10222 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10223
10224 Info = GOOD;
10225 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10226 && (plci->dtmf_parameter_length != 0))
10227 {
10228 switch (plci->adjust_b_state)
10229 {
10230 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10231 plci->internal_command = plci->adjust_b_command;
10232 if (plci->sig_req)
10233 {
10234 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10235 break;
10236 }
10237 dtmf_parameter_write (plci);
10238 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10239 break;
10240 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10241 if ((Rc != OK) && (Rc != OK_FC))
10242 {
10243 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10244 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10245 Info = _WRONG_STATE;
10246 break;
10247 }
10248 break;
10249 }
10250 }
10251 return (Info);
10252}
10253
10254
10255/*------------------------------------------------------------------*/
10256/* Line interconnect facilities */
10257/*------------------------------------------------------------------*/
10258
10259
10260LI_CONFIG *li_config_table;
10261word li_total_channels;
10262
10263
10264/*------------------------------------------------------------------*/
10265/* translate a CHI information element to a channel number */
10266/* returns 0xff - any channel */
10267/* 0xfe - chi wrong coding */
10268/* 0xfd - D-channel */
10269/* 0x00 - no channel */
10270/* else channel number / PRI: timeslot */
10271/* if channels is provided we accept more than one channel. */
10272/*------------------------------------------------------------------*/
10273
10274static byte chi_to_channel (byte *chi, dword *pchannelmap)
10275{
10276 int p;
10277 int i;
10278 dword map;
10279 byte excl;
10280 byte ofs;
10281 byte ch;
10282
10283 if (pchannelmap) *pchannelmap = 0;
10284 if(!chi[0]) return 0xff;
10285 excl = 0;
10286
10287 if(chi[1] & 0x20) {
10288 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10289 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10290 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10291 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10292 if(chi[1] &0x08) excl = 0x40;
10293
10294 /* int. id present */
10295 if(chi[1] &0x40) {
10296 p=i+1;
10297 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10298 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10299 }
10300
10301 /* coding standard, Number/Map, Channel Type */
10302 p=i+1;
10303 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10304 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10305 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10306
10307 /* Number/Map */
10308 if(chi[p] &0x10) {
10309
10310 /* map */
10311 if((chi[0]-p)==4) ofs = 0;
10312 else if((chi[0]-p)==3) ofs = 1;
10313 else return 0xfe;
10314 ch = 0;
10315 map = 0;
10316 for(i=0; i<4 && p<chi[0]; i++) {
10317 p++;
10318 ch += 8;
10319 map <<= 8;
10320 if(chi[p]) {
10321 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10322 map |= chi[p];
10323 }
10324 }
10325 ch += ofs;
10326 map <<= ofs;
10327 }
10328 else {
10329
10330 /* number */
10331 p=i+1;
10332 ch = chi[p] &0x3f;
10333 if(pchannelmap) {
10334 if((byte)(chi[0]-p)>30) return 0xfe;
10335 map = 0;
10336 for(i=p; i<=chi[0]; i++) {
10337 if ((chi[i] &0x7f) > 31) return 0xfe;
10338 map |= (1L << (chi[i] &0x7f));
10339 }
10340 }
10341 else {
10342 if(p!=chi[0]) return 0xfe;
10343 if (ch > 31) return 0xfe;
10344 map = (1L << ch);
10345 }
10346 if(chi[p] &0x40) return 0xfe;
10347 }
10348 if (pchannelmap) *pchannelmap = map;
10349 else if (map != ((dword)(1L << ch))) return 0xfe;
10350 return (byte)(excl | ch);
10351 }
10352 else { /* not PRI */
10353 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10354 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10355 if(chi[1] &0x08) excl = 0x40;
10356
10357 switch(chi[1] |0x98) {
10358 case 0x98: return 0;
10359 case 0x99:
10360 if (pchannelmap) *pchannelmap = 2;
10361 return excl |1;
10362 case 0x9a:
10363 if (pchannelmap) *pchannelmap = 4;
10364 return excl |2;
10365 case 0x9b: return 0xff;
10366 case 0x9c: return 0xfd; /* d-ch */
10367 default: return 0xfe;
10368 }
10369 }
10370}
10371
10372
10373static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10374{
10375 DIVA_CAPI_ADAPTER *a;
10376 PLCI *splci;
10377 byte old_id;
10378
10379 a = plci->adapter;
10380 old_id = plci->li_bchannel_id;
10381 if (a->li_pri)
10382 {
10383 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10384 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10385 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10386 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10387 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10388 }
10389 else
10390 {
10391 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10392 {
10393 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10394 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10395 plci->li_bchannel_id = bchannel_id & 0x03;
10396 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10397 {
10398 splci = a->AdvSignalPLCI;
10399 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10400 {
10401 if ((splci->li_bchannel_id != 0)
10402 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10403 {
10404 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10405 }
10406 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10407 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10408 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10409 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10410 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10411 }
10412 }
10413 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10414 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10415 }
10416 }
10417 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10418 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10419 {
10420 mixer_clear_config (plci);
10421 }
10422 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10423 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10424 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10425}
10426
10427
10428static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10429{
10430 DIVA_CAPI_ADAPTER *a;
10431 PLCI *splci;
10432 byte ch, old_id;
10433
10434 a = plci->adapter;
10435 old_id = plci->li_bchannel_id;
10436 ch = chi_to_channel (chi, NULL);
10437 if (!(ch & 0x80))
10438 {
10439 if (a->li_pri)
10440 {
10441 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10442 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10443 plci->li_bchannel_id = (ch & 0x1f) + 1;
10444 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10445 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10446 }
10447 else
10448 {
10449 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10450 {
10451 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10452 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10453 plci->li_bchannel_id = ch & 0x1f;
10454 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10455 {
10456 splci = a->AdvSignalPLCI;
10457 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10458 {
10459 if ((splci->li_bchannel_id != 0)
10460 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10461 {
10462 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10463 }
10464 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10465 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10466 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10467 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10468 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10469 }
10470 }
10471 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10472 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10473 }
10474 }
10475 }
10476 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10477 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10478 {
10479 mixer_clear_config (plci);
10480 }
10481 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10482 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10483 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10484}
10485
10486
10487#define MIXER_MAX_DUMP_CHANNELS 34
10488
10489static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10490{
10491static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10492 word n, i, j;
10493 char *p;
10494 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10495
10496 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10497 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10498
10499 for (i = 0; i < li_total_channels; i++)
10500 {
10501 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10502 if (li_config_table[i].chflags != 0)
10503 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10504 else
10505 {
10506 for (j = 0; j < li_total_channels; j++)
10507 {
10508 if (((li_config_table[i].flag_table[j]) != 0)
10509 || ((li_config_table[j].flag_table[i]) != 0))
10510 {
10511 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10512 }
10513 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10514 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10515 {
10516 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10517 }
10518 }
10519 }
10520 }
10521 for (i = 0; i < li_total_channels; i++)
10522 {
10523 for (j = 0; j < li_total_channels; j++)
10524 {
10525 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10526 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10527 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10528 }
10529 }
10530 for (n = 0; n < li_total_channels; n++)
10531 {
10532 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10533 {
10534 for (i = 0; i < li_total_channels; i++)
10535 {
10536 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10537 {
10538 for (j = 0; j < li_total_channels; j++)
10539 {
10540 li_config_table[i].coef_table[j] |=
10541 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10542 }
10543 }
10544 }
10545 }
10546 }
10547 for (i = 0; i < li_total_channels; i++)
10548 {
10549 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10550 {
10551 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10552 for (j = 0; j < li_total_channels; j++)
10553 {
10554 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10555 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10556 }
10557 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10558 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10559 }
10560 }
10561 for (i = 0; i < li_total_channels; i++)
10562 {
10563 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10564 {
10565 for (j = 0; j < li_total_channels; j++)
10566 {
10567 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10568 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10569 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10570 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10571 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10572 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10573 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10574 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10575 }
10576 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10577 {
10578 for (j = 0; j < li_total_channels; j++)
10579 {
10580 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10581 {
10582 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10583 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10584 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10585 }
10586 }
10587 }
10588 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10589 {
10590 for (j = 0; j < li_total_channels; j++)
10591 {
10592 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10593 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10594 }
10595 }
10596 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10597 {
10598 for (j = 0; j < li_total_channels; j++)
10599 {
10600 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10601 {
10602 for (n = 0; n < li_total_channels; n++)
10603 {
10604 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10605 {
10606 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10607 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10608 {
10609 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10610 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10611 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10612 }
10613 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10614 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10615 }
10616 }
10617 }
10618 }
10619 }
10620 }
10621 }
10622 for (i = 0; i < li_total_channels; i++)
10623 {
10624 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10625 {
10626 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10627 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10628 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10629 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10630 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10631 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10632 for (j = 0; j < li_total_channels; j++)
10633 {
10634 if ((li_config_table[i].flag_table[j] &
10635 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10636 || (li_config_table[j].flag_table[i] &
10637 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10638 {
10639 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10640 }
10641 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10642 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10643 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10644 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10645 }
10646 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10647 {
10648 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10649 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10650 }
10651 }
10652 }
10653 for (i = 0; i < li_total_channels; i++)
10654 {
10655 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10656 {
10657 j = 0;
10658 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10659 j++;
10660 if (j < li_total_channels)
10661 {
10662 for (j = 0; j < li_total_channels; j++)
10663 {
10664 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10665 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10666 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10667 }
10668 }
10669 }
10670 }
10671 n = li_total_channels;
10672 if (n > MIXER_MAX_DUMP_CHANNELS)
10673 n = MIXER_MAX_DUMP_CHANNELS;
10674 p = hex_line;
10675 for (j = 0; j < n; j++)
10676 {
10677 if ((j & 0x7) == 0)
10678 *(p++) = ' ';
10679 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10680 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10681 }
10682 *p = '\0';
10683 dbug (1, dprintf ("[%06lx] CURRENT %s",
10684 (dword)(UnMapController (a->Id)), (char *) hex_line));
10685 p = hex_line;
10686 for (j = 0; j < n; j++)
10687 {
10688 if ((j & 0x7) == 0)
10689 *(p++) = ' ';
10690 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10691 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10692 }
10693 *p = '\0';
10694 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10695 (dword)(UnMapController (a->Id)), (char *) hex_line));
10696 p = hex_line;
10697 for (j = 0; j < n; j++)
10698 {
10699 if ((j & 0x7) == 0)
10700 *(p++) = ' ';
10701 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10702 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10703 }
10704 *p = '\0';
10705 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10706 (dword)(UnMapController (a->Id)), (char *) hex_line));
10707 for (i = 0; i < n; i++)
10708 {
10709 p = hex_line;
10710 for (j = 0; j < n; j++)
10711 {
10712 if ((j & 0x7) == 0)
10713 *(p++) = ' ';
10714 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10715 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10716 }
10717 *p = '\0';
10718 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10719 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10720 }
10721 for (i = 0; i < n; i++)
10722 {
10723 p = hex_line;
10724 for (j = 0; j < n; j++)
10725 {
10726 if ((j & 0x7) == 0)
10727 *(p++) = ' ';
10728 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10729 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10730 }
10731 *p = '\0';
10732 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10733 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10734 }
10735}
10736
10737
10738static struct
10739{
10740 byte mask;
10741 byte line_flags;
10742} mixer_write_prog_pri[] =
10743{
10744 { LI_COEF_CH_CH, 0 },
10745 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10746 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10747 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10748};
10749
10750static struct
10751{
10752 byte from_ch;
10753 byte to_ch;
10754 byte mask;
10755 byte xconnect_override;
10756} mixer_write_prog_bri[] =
10757{
10758 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10759 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10760 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10761 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10762 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10763 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10764 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10765 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10766 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10767 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10768 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10769 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10770 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10771 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10772 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10773 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10774 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10775 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10776 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10777 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10778 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10779 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10780 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10781 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10782 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10783 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10784 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10785 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10786 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10787 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10788 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10789 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10790 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10791 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10792 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10793 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10794};
10795
10796static byte mixer_swapped_index_bri[] =
10797{
10798 18, /* B to B */
10799 19, /* Alt B to B */
10800 20, /* PC to B */
10801 21, /* Alt PC to B */
10802 22, /* IC to B */
10803 23, /* Alt IC to B */
10804 24, /* B to PC */
10805 25, /* Alt B to PC */
10806 26, /* PC to PC */
10807 27, /* Alt PC to PC */
10808 28, /* IC to PC */
10809 29, /* Alt IC to PC */
10810 30, /* B to IC */
10811 31, /* Alt B to IC */
10812 32, /* PC to IC */
10813 33, /* Alt PC to IC */
10814 34, /* IC to IC */
10815 35, /* Alt IC to IC */
10816 0, /* Alt B to Alt B */
10817 1, /* B to Alt B */
10818 2, /* Alt PC to Alt B */
10819 3, /* PC to Alt B */
10820 4, /* Alt IC to Alt B */
10821 5, /* IC to Alt B */
10822 6, /* Alt B to Alt PC */
10823 7, /* B to Alt PC */
10824 8, /* Alt PC to Alt PC */
10825 9, /* PC to Alt PC */
10826 10, /* Alt IC to Alt PC */
10827 11, /* IC to Alt PC */
10828 12, /* Alt B to Alt IC */
10829 13, /* B to Alt IC */
10830 14, /* Alt PC to Alt IC */
10831 15, /* PC to Alt IC */
10832 16, /* Alt IC to Alt IC */
10833 17 /* IC to Alt IC */
10834};
10835
10836static struct
10837{
10838 byte mask;
10839 byte from_pc;
10840 byte to_pc;
10841} xconnect_write_prog[] =
10842{
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010843 { LI_COEF_CH_CH, false, false },
10844 { LI_COEF_CH_PC, false, true },
10845 { LI_COEF_PC_CH, true, false },
10846 { LI_COEF_PC_PC, true, true }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010847};
10848
10849
10850static void xconnect_query_addresses (PLCI *plci)
10851{
10852 DIVA_CAPI_ADAPTER *a;
10853 word w, ch;
10854 byte *p;
10855
10856 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10857 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10858 (char *)(FILE_), __LINE__));
10859
10860 a = plci->adapter;
10861 if (a->li_pri && ((plci->li_bchannel_id == 0)
10862 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10863 {
10864 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10865 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10866 (char *)(FILE_), __LINE__));
10867 return;
10868 }
10869 p = plci->internal_req_buffer;
10870 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10871 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10872 w = ch;
10873 *(p++) = (byte) w;
10874 *(p++) = (byte)(w >> 8);
10875 w = ch | XCONNECT_CHANNEL_PORT_PC;
10876 *(p++) = (byte) w;
10877 *(p++) = (byte)(w >> 8);
10878 plci->NData[0].P = plci->internal_req_buffer;
10879 plci->NData[0].PLength = p - plci->internal_req_buffer;
10880 plci->NL.X = plci->NData;
10881 plci->NL.ReqCh = 0;
10882 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10883 plci->adapter->request (&plci->NL);
10884}
10885
10886
10887static void xconnect_write_coefs (PLCI *plci, word internal_command)
10888{
10889
10890 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10891 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10892 (char *)(FILE_), __LINE__, internal_command));
10893
10894 plci->li_write_command = internal_command;
10895 plci->li_write_channel = 0;
10896}
10897
10898
10899static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10900{
10901 DIVA_CAPI_ADAPTER *a;
10902 word w, n, i, j, r, s, to_ch;
10903 dword d;
10904 byte *p;
10905 struct xconnect_transfer_address_s *transfer_address;
10906 byte ch_map[MIXER_CHANNELS_BRI];
10907
10908 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10909 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10910
10911 a = plci->adapter;
10912 if ((plci->li_bchannel_id == 0)
10913 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10914 {
10915 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10916 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010917 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010918 }
10919 i = a->li_base + (plci->li_bchannel_id - 1);
10920 j = plci->li_write_channel;
10921 p = plci->internal_req_buffer;
10922 if (j != 0)
10923 {
10924 if ((Rc != OK) && (Rc != OK_FC))
10925 {
10926 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10927 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010928 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010929 }
10930 }
10931 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10932 {
10933 r = 0;
10934 s = 0;
10935 if (j < li_total_channels)
10936 {
10937 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10938 {
10939 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10940 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10941 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10942 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10943 }
10944 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10945 while ((j < li_total_channels)
10946 && ((r == 0)
10947 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10948 || (!li_config_table[j].adapter->li_pri
10949 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10950 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10951 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10952 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10953 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10954 || ((li_config_table[j].adapter->li_base != a->li_base)
10955 && !(r & s &
10956 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10957 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10958 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10959 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10960 {
10961 j++;
10962 if (j < li_total_channels)
10963 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964 }
10965 }
10966 if (j < li_total_channels)
10967 {
10968 plci->internal_command = plci->li_write_command;
10969 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010970 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010971 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10972 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10973 do
10974 {
10975 if (li_config_table[j].adapter->li_base != a->li_base)
10976 {
10977 r &= s &
10978 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10979 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10980 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10981 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10982 }
10983 n = 0;
10984 do
10985 {
10986 if (r & xconnect_write_prog[n].mask)
10987 {
10988 if (xconnect_write_prog[n].from_pc)
10989 transfer_address = &(li_config_table[j].send_pc);
10990 else
10991 transfer_address = &(li_config_table[j].send_b);
10992 d = transfer_address->card_address.low;
10993 *(p++) = (byte) d;
10994 *(p++) = (byte)(d >> 8);
10995 *(p++) = (byte)(d >> 16);
10996 *(p++) = (byte)(d >> 24);
10997 d = transfer_address->card_address.high;
10998 *(p++) = (byte) d;
10999 *(p++) = (byte)(d >> 8);
11000 *(p++) = (byte)(d >> 16);
11001 *(p++) = (byte)(d >> 24);
11002 d = transfer_address->offset;
11003 *(p++) = (byte) d;
11004 *(p++) = (byte)(d >> 8);
11005 *(p++) = (byte)(d >> 16);
11006 *(p++) = (byte)(d >> 24);
11007 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11008 *(p++) = (byte) w;
11009 *(p++) = (byte)(w >> 8);
11010 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11011 (li_config_table[i].adapter->u_law ?
11012 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11013 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11014 *(p++) = (byte) w;
11015 *(p++) = (byte) 0;
11016 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11017 }
11018 n++;
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011019 } while ((n < ARRAY_SIZE(xconnect_write_prog))
Linus Torvalds1da177e2005-04-16 15:20:36 -070011020 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011021 if (n == ARRAY_SIZE(xconnect_write_prog))
Linus Torvalds1da177e2005-04-16 15:20:36 -070011022 {
11023 do
11024 {
11025 j++;
11026 if (j < li_total_channels)
11027 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11028 } while ((j < li_total_channels)
11029 && ((r == 0)
11030 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11031 || (!li_config_table[j].adapter->li_pri
11032 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11033 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11034 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11035 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11036 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11037 || ((li_config_table[j].adapter->li_base != a->li_base)
11038 && !(r & s &
11039 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11040 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11041 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11042 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11043 }
11044 } while ((j < li_total_channels)
11045 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11046 }
11047 else if (j == li_total_channels)
11048 {
11049 plci->internal_command = plci->li_write_command;
11050 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011051 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011052 if (a->li_pri)
11053 {
11054 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11055 w = 0;
11056 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11057 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11058 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11059 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11060 *(p++) = (byte) w;
11061 *(p++) = (byte)(w >> 8);
11062 }
11063 else
11064 {
11065 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11066 w = 0;
11067 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11068 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11069 {
11070 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11071 }
11072 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11073 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11074 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11075 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11076 *(p++) = (byte) w;
11077 *(p++) = (byte)(w >> 8);
11078 for (j = 0; j < sizeof(ch_map); j += 2)
11079 {
11080 if (plci->li_bchannel_id == 2)
11081 {
11082 ch_map[j] = (byte)(j+1);
11083 ch_map[j+1] = (byte) j;
11084 }
11085 else
11086 {
11087 ch_map[j] = (byte) j;
11088 ch_map[j+1] = (byte)(j+1);
11089 }
11090 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011091 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011092 {
11093 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11094 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11095 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11096 {
11097 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11098 mixer_write_prog_bri[n].xconnect_override :
11099 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11100 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11101 {
11102 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11103 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11104 }
11105 }
11106 else
11107 {
11108 *p = 0x00;
11109 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11110 {
11111 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11112 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11113 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11114 }
11115 }
11116 p++;
11117 }
11118 }
11119 j = li_total_channels + 1;
11120 }
11121 }
11122 else
11123 {
11124 if (j <= li_total_channels)
11125 {
11126 plci->internal_command = plci->li_write_command;
11127 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011128 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011129 if (j < a->li_base)
11130 j = a->li_base;
11131 if (a->li_pri)
11132 {
11133 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11134 w = 0;
11135 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11136 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11137 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11138 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11139 *(p++) = (byte) w;
11140 *(p++) = (byte)(w >> 8);
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011141 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011142 {
11143 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11144 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11145 {
11146 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11147 if (w & mixer_write_prog_pri[n].mask)
11148 {
11149 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11150 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11151 }
11152 else
11153 *(p++) = 0x00;
11154 }
11155 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11156 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11157 {
11158 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11159 if (w & mixer_write_prog_pri[n].mask)
11160 {
11161 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11163 }
11164 else
11165 *(p++) = 0x00;
11166 }
11167 }
11168 }
11169 else
11170 {
11171 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11172 w = 0;
11173 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11174 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11175 {
11176 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11177 }
11178 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11179 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11180 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11181 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11182 *(p++) = (byte) w;
11183 *(p++) = (byte)(w >> 8);
11184 for (j = 0; j < sizeof(ch_map); j += 2)
11185 {
11186 if (plci->li_bchannel_id == 2)
11187 {
11188 ch_map[j] = (byte)(j+1);
11189 ch_map[j+1] = (byte) j;
11190 }
11191 else
11192 {
11193 ch_map[j] = (byte) j;
11194 ch_map[j+1] = (byte)(j+1);
11195 }
11196 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011197 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011198 {
11199 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11200 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11201 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11202 {
11203 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11204 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11205 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11206 }
11207 else
11208 {
11209 *p = 0x00;
11210 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11211 {
11212 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11213 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11214 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11215 }
11216 }
11217 p++;
11218 }
11219 }
11220 j = li_total_channels + 1;
11221 }
11222 }
11223 plci->li_write_channel = j;
11224 if (p != plci->internal_req_buffer)
11225 {
11226 plci->NData[0].P = plci->internal_req_buffer;
11227 plci->NData[0].PLength = p - plci->internal_req_buffer;
11228 plci->NL.X = plci->NData;
11229 plci->NL.ReqCh = 0;
11230 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11231 plci->adapter->request (&plci->NL);
11232 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011233 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011234}
11235
11236
11237static void mixer_notify_update (PLCI *plci, byte others)
11238{
11239 DIVA_CAPI_ADAPTER *a;
11240 word i, w;
11241 PLCI *notify_plci;
11242 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11243
11244 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11245 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11246 (char *)(FILE_), __LINE__, others));
11247
11248 a = plci->adapter;
11249 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11250 {
11251 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011252 plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011253 i = 0;
11254 do
11255 {
11256 notify_plci = NULL;
11257 if (others)
11258 {
11259 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11260 i++;
11261 if (i < li_total_channels)
11262 notify_plci = li_config_table[i++].plci;
11263 }
11264 else
11265 {
11266 if ((plci->li_bchannel_id != 0)
11267 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11268 {
11269 notify_plci = plci;
11270 }
11271 }
11272 if ((notify_plci != NULL)
11273 && !notify_plci->li_notify_update
11274 && (notify_plci->appl != NULL)
11275 && (notify_plci->State)
11276 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11277 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011278 notify_plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011279 ((CAPI_MSG *) msg)->header.length = 18;
11280 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11281 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11282 ((CAPI_MSG *) msg)->header.number = 0;
11283 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11284 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11285 ((CAPI_MSG *) msg)->header.ncci = 0;
11286 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11287 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11288 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11289 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11290 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11291 if (w != _QUEUE_FULL)
11292 {
11293 if (w != 0)
11294 {
11295 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11296 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11297 (char *)(FILE_), __LINE__,
11298 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11299 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011300 notify_plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011301 }
11302 }
11303 } while (others && (notify_plci != NULL));
11304 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011305 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011306 }
11307}
11308
11309
11310static void mixer_clear_config (PLCI *plci)
11311{
11312 DIVA_CAPI_ADAPTER *a;
11313 word i, j;
11314
11315 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11316 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11317 (char *)(FILE_), __LINE__));
11318
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011319 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011320 plci->li_plci_b_write_pos = 0;
11321 plci->li_plci_b_read_pos = 0;
11322 plci->li_plci_b_req_pos = 0;
11323 a = plci->adapter;
11324 if ((plci->li_bchannel_id != 0)
11325 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11326 {
11327 i = a->li_base + (plci->li_bchannel_id - 1);
11328 li_config_table[i].curchnl = 0;
11329 li_config_table[i].channel = 0;
11330 li_config_table[i].chflags = 0;
11331 for (j = 0; j < li_total_channels; j++)
11332 {
11333 li_config_table[j].flag_table[i] = 0;
11334 li_config_table[i].flag_table[j] = 0;
11335 li_config_table[i].coef_table[j] = 0;
11336 li_config_table[j].coef_table[i] = 0;
11337 }
11338 if (!a->li_pri)
11339 {
11340 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11341 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11342 {
11343 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11344 li_config_table[i].curchnl = 0;
11345 li_config_table[i].channel = 0;
11346 li_config_table[i].chflags = 0;
11347 for (j = 0; j < li_total_channels; j++)
11348 {
11349 li_config_table[i].flag_table[j] = 0;
11350 li_config_table[j].flag_table[i] = 0;
11351 li_config_table[i].coef_table[j] = 0;
11352 li_config_table[j].coef_table[i] = 0;
11353 }
11354 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11355 {
11356 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11357 li_config_table[i].curchnl = 0;
11358 li_config_table[i].channel = 0;
11359 li_config_table[i].chflags = 0;
11360 for (j = 0; j < li_total_channels; j++)
11361 {
11362 li_config_table[i].flag_table[j] = 0;
11363 li_config_table[j].flag_table[i] = 0;
11364 li_config_table[i].coef_table[j] = 0;
11365 li_config_table[j].coef_table[i] = 0;
11366 }
11367 }
11368 }
11369 }
11370 }
11371}
11372
11373
11374static void mixer_prepare_switch (dword Id, PLCI *plci)
11375{
11376
11377 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11378 UnMapId (Id), (char *)(FILE_), __LINE__));
11379
11380 do
11381 {
11382 mixer_indication_coefs_set (Id, plci);
11383 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11384}
11385
11386
11387static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11388{
11389 DIVA_CAPI_ADAPTER *a;
11390 word i, j;
11391
11392 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11393 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11394
11395 a = plci->adapter;
11396 if ((plci->li_bchannel_id != 0)
11397 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11398 {
11399 i = a->li_base + (plci->li_bchannel_id - 1);
11400 for (j = 0; j < li_total_channels; j++)
11401 {
11402 li_config_table[i].coef_table[j] &= 0xf;
11403 li_config_table[j].coef_table[i] &= 0xf;
11404 }
11405 if (!a->li_pri)
11406 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11407 }
11408 return (GOOD);
11409}
11410
11411
11412static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11413{
11414 DIVA_CAPI_ADAPTER *a;
11415 word Info;
11416
11417 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11418 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11419
11420 Info = GOOD;
11421 a = plci->adapter;
11422 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11423 && (plci->li_bchannel_id != 0)
11424 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11425 {
11426 switch (plci->adjust_b_state)
11427 {
11428 case ADJUST_B_RESTORE_MIXER_1:
11429 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11430 {
11431 plci->internal_command = plci->adjust_b_command;
11432 if (plci_nl_busy (plci))
11433 {
11434 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11435 break;
11436 }
11437 xconnect_query_addresses (plci);
11438 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11439 break;
11440 }
11441 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11442 Rc = OK;
11443 case ADJUST_B_RESTORE_MIXER_2:
11444 case ADJUST_B_RESTORE_MIXER_3:
11445 case ADJUST_B_RESTORE_MIXER_4:
11446 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11447 {
11448 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11449 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11450 Info = _WRONG_STATE;
11451 break;
11452 }
11453 if (Rc == OK)
11454 {
11455 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11456 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11457 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11458 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11459 }
11460 else if (Rc == 0)
11461 {
11462 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11463 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11464 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11465 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11466 }
11467 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11468 {
11469 plci->internal_command = plci->adjust_b_command;
11470 break;
11471 }
11472 case ADJUST_B_RESTORE_MIXER_5:
11473 xconnect_write_coefs (plci, plci->adjust_b_command);
11474 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11475 Rc = OK;
11476 case ADJUST_B_RESTORE_MIXER_6:
11477 if (!xconnect_write_coefs_process (Id, plci, Rc))
11478 {
11479 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11480 UnMapId (Id), (char *)(FILE_), __LINE__));
11481 Info = _FACILITY_NOT_SUPPORTED;
11482 break;
11483 }
11484 if (plci->internal_command)
11485 break;
11486 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11487 case ADJUST_B_RESTORE_MIXER_7:
11488 break;
11489 }
11490 }
11491 return (Info);
11492}
11493
11494
11495static void mixer_command (dword Id, PLCI *plci, byte Rc)
11496{
11497 DIVA_CAPI_ADAPTER *a;
11498 word i, internal_command, Info;
11499
11500 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11501 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11502 plci->li_cmd));
11503
11504 Info = GOOD;
11505 a = plci->adapter;
11506 internal_command = plci->internal_command;
11507 plci->internal_command = 0;
11508 switch (plci->li_cmd)
11509 {
11510 case LI_REQ_CONNECT:
11511 case LI_REQ_DISCONNECT:
11512 case LI_REQ_SILENT_UPDATE:
11513 switch (internal_command)
11514 {
11515 default:
11516 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11517 {
11518 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11519 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11520 }
11521 case MIXER_COMMAND_1:
11522 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11523 {
11524 if (adjust_b_process (Id, plci, Rc) != GOOD)
11525 {
11526 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11527 UnMapId (Id), (char *)(FILE_), __LINE__));
11528 Info = _FACILITY_NOT_SUPPORTED;
11529 break;
11530 }
11531 if (plci->internal_command)
11532 return;
11533 }
11534 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11535 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11536 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11537 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11538 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11539 {
11540 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11541 }
11542 else
11543 {
11544 do
11545 {
11546 mixer_indication_coefs_set (Id, plci);
11547 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11548 }
11549 case MIXER_COMMAND_2:
11550 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11551 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11552 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11553 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11554 {
11555 if (!xconnect_write_coefs_process (Id, plci, Rc))
11556 {
11557 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11558 UnMapId (Id), (char *)(FILE_), __LINE__));
11559 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11560 {
11561 do
11562 {
11563 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11564 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11565 i = (plci->li_plci_b_write_pos == 0) ?
11566 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11567 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11568 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11569 }
11570 Info = _FACILITY_NOT_SUPPORTED;
11571 break;
11572 }
11573 if (plci->internal_command)
11574 return;
11575 }
11576 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11577 {
11578 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11579 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11580 }
11581 case MIXER_COMMAND_3:
11582 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11583 {
11584 if (adjust_b_process (Id, plci, Rc) != GOOD)
11585 {
11586 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11587 UnMapId (Id), (char *)(FILE_), __LINE__));
11588 Info = _FACILITY_NOT_SUPPORTED;
11589 break;
11590 }
11591 if (plci->internal_command)
11592 return;
11593 }
11594 break;
11595 }
11596 break;
11597 }
11598 if ((plci->li_bchannel_id == 0)
11599 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11600 {
11601 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11602 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11603 }
11604 else
11605 {
11606 i = a->li_base + (plci->li_bchannel_id - 1);
11607 li_config_table[i].curchnl = plci->li_channel_bits;
11608 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11609 {
11610 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11611 li_config_table[i].curchnl = plci->li_channel_bits;
11612 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11613 {
11614 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11615 li_config_table[i].curchnl = plci->li_channel_bits;
11616 }
11617 }
11618 }
11619}
11620
11621
11622static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11623 dword plci_b_id, byte connect, dword li_flags)
11624{
11625 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11626 PLCI *plci_b;
11627 DIVA_CAPI_ADAPTER *a_b;
11628
11629 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11630 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11631 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11632 if (!a->li_pri && (plci->tel == ADV_VOICE)
11633 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11634 {
11635 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11636 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11637 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11638 }
11639 else
11640 {
11641 ch_a_v = ch_a;
11642 ch_a_s = ch_a;
11643 }
11644 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11645 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11646 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11647 {
11648 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11649 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11650 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11651 }
11652 else
11653 {
11654 ch_b_v = ch_b;
11655 ch_b_s = ch_b;
11656 }
11657 if (connect)
11658 {
11659 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11660 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11661 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11662 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11663 }
11664 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11665 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11666 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11667 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668 if (ch_a_v == ch_b_v)
11669 {
11670 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11671 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11672 }
11673 else
11674 {
11675 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11676 {
11677 for (i = 0; i < li_total_channels; i++)
11678 {
11679 if (i != ch_a_v)
11680 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11681 }
11682 }
11683 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11684 {
11685 for (i = 0; i < li_total_channels; i++)
11686 {
11687 if (i != ch_a_s)
11688 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11689 }
11690 }
11691 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11692 {
11693 for (i = 0; i < li_total_channels; i++)
11694 {
11695 if (i != ch_a_v)
11696 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11697 }
11698 }
11699 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11700 {
11701 for (i = 0; i < li_total_channels; i++)
11702 {
11703 if (i != ch_a_s)
11704 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11705 }
11706 }
11707 }
11708 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11709 {
11710 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11711 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11712 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11713 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11714 }
11715 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11716 {
11717 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11718 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11721 }
11722 if (li_flags & LI_FLAG_MONITOR_A)
11723 {
11724 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11725 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11726 }
11727 if (li_flags & LI_FLAG_MONITOR_B)
11728 {
11729 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11730 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11731 }
11732 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11733 {
11734 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11735 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11736 }
11737 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11738 {
11739 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11740 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741 }
11742 if (li_flags & LI_FLAG_MIX_A)
11743 {
11744 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11745 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11746 }
11747 if (li_flags & LI_FLAG_MIX_B)
11748 {
11749 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11750 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11751 }
11752 if (ch_a_v != ch_a_s)
11753 {
11754 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11755 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11756 }
11757 if (ch_b_v != ch_b_s)
11758 {
11759 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11760 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11761 }
11762}
11763
11764
11765static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11766 dword plci_b_id, byte connect, dword li_flags)
11767{
11768 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11769 PLCI *plci_b;
11770 DIVA_CAPI_ADAPTER *a_b;
11771
11772 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11773 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11774 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11775 if (!a->li_pri && (plci->tel == ADV_VOICE)
11776 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11777 {
11778 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11779 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11780 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11781 }
11782 else
11783 {
11784 ch_a_v = ch_a;
11785 ch_a_s = ch_a;
11786 }
11787 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11788 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11789 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11790 {
11791 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11792 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11793 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11794 }
11795 else
11796 {
11797 ch_b_v = ch_b;
11798 ch_b_s = ch_b;
11799 }
11800 if (connect)
11801 {
11802 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11803 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11804 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11805 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11806 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11807 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11808 }
11809 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11810 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11811 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11818 {
11819 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11820 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11821 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11822 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11823 }
11824 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11825 {
11826 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11827 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11830 }
11831 if (li_flags & LI2_FLAG_MONITOR_B)
11832 {
11833 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11834 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11835 }
11836 if (li_flags & LI2_FLAG_MIX_B)
11837 {
11838 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11839 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11840 }
11841 if (li_flags & LI2_FLAG_MONITOR_X)
11842 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11843 if (li_flags & LI2_FLAG_MIX_X)
11844 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11845 if (li_flags & LI2_FLAG_LOOP_B)
11846 {
11847 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11848 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11849 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11850 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11851 }
11852 if (li_flags & LI2_FLAG_LOOP_PC)
11853 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11854 if (li_flags & LI2_FLAG_LOOP_X)
11855 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11856 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11857 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11858 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11859 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11860 if (ch_a_v != ch_a_s)
11861 {
11862 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11863 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11864 }
11865 if (ch_b_v != ch_b_s)
11866 {
11867 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11868 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11869 }
11870}
11871
11872
11873static word li_check_main_plci (dword Id, PLCI *plci)
11874{
11875 if (plci == NULL)
11876 {
11877 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11878 UnMapId (Id), (char *)(FILE_), __LINE__));
11879 return (_WRONG_IDENTIFIER);
11880 }
11881 if (!plci->State
11882 || !plci->NL.Id || plci->nl_remove_id
11883 || (plci->li_bchannel_id == 0))
11884 {
11885 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11886 UnMapId (Id), (char *)(FILE_), __LINE__));
11887 return (_WRONG_STATE);
11888 }
11889 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11890 return (GOOD);
11891}
11892
11893
11894static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11895 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11896{
11897 byte ctlr_b;
11898 PLCI *plci_b;
11899
11900 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11901 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11902 {
11903 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11904 UnMapId (Id), (char *)(FILE_), __LINE__));
11905 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11906 return (NULL);
11907 }
11908 ctlr_b = 0;
11909 if ((plci_b_id & 0x7f) != 0)
11910 {
11911 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11912 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11913 ctlr_b = 0;
11914 }
11915 if ((ctlr_b == 0)
11916 || (((plci_b_id >> 8) & 0xff) == 0)
11917 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11918 {
11919 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11920 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11921 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11922 return (NULL);
11923 }
11924 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11925 if (!plci_b->State
11926 || !plci_b->NL.Id || plci_b->nl_remove_id
11927 || (plci_b->li_bchannel_id == 0))
11928 {
11929 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11930 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11931 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11932 return (NULL);
11933 }
11934 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11935 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11936 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11937 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11938 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11939 {
11940 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11941 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11942 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11943 return (NULL);
11944 }
11945 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11946 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11947 {
11948 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11949 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11950 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11951 return (NULL);
11952 }
11953 return (plci_b);
11954}
11955
11956
11957static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11958 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11959{
11960 byte ctlr_b;
11961 PLCI *plci_b;
11962
11963 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11964 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11965 {
11966 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11967 UnMapId (Id), (char *)(FILE_), __LINE__));
11968 PUT_WORD (p_result, _WRONG_STATE);
11969 return (NULL);
11970 }
11971 ctlr_b = 0;
11972 if ((plci_b_id & 0x7f) != 0)
11973 {
11974 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11975 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11976 ctlr_b = 0;
11977 }
11978 if ((ctlr_b == 0)
11979 || (((plci_b_id >> 8) & 0xff) == 0)
11980 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11981 {
11982 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11983 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11984 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11985 return (NULL);
11986 }
11987 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11988 if (!plci_b->State
11989 || !plci_b->NL.Id || plci_b->nl_remove_id
11990 || (plci_b->li_bchannel_id == 0)
11991 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11992 {
11993 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11994 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11995 PUT_WORD (p_result, _WRONG_STATE);
11996 return (NULL);
11997 }
11998 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11999 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12000 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12001 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12002 {
12003 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12004 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12005 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12006 return (NULL);
12007 }
12008 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12009 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12010 {
12011 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12012 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12013 PUT_WORD (p_result, _WRONG_STATE);
12014 return (NULL);
12015 }
12016 return (plci_b);
12017}
12018
12019
12020static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12021{
12022 word Info;
12023 word i;
12024 dword d, li_flags, plci_b_id;
12025 PLCI *plci_b;
12026 API_PARSE li_parms[3];
12027 API_PARSE li_req_parms[3];
12028 API_PARSE li_participant_struct[2];
12029 API_PARSE li_participant_parms[3];
12030 word participant_parms_pos;
12031 byte result_buffer[32];
12032 byte *result;
12033 word result_pos;
12034 word plci_b_write_pos;
12035
12036 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12037 UnMapId (Id), (char *)(FILE_), __LINE__));
12038
12039 Info = GOOD;
12040 result = result_buffer;
12041 result_buffer[0] = 0;
12042 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12043 {
12044 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12045 UnMapId (Id), (char *)(FILE_), __LINE__));
12046 Info = _FACILITY_NOT_SUPPORTED;
12047 }
12048 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12049 {
12050 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12051 UnMapId (Id), (char *)(FILE_), __LINE__));
12052 Info = _WRONG_MESSAGE_FORMAT;
12053 }
12054 else
12055 {
12056 result_buffer[0] = 3;
12057 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12058 result_buffer[3] = 0;
12059 switch (GET_WORD (li_parms[0].info))
12060 {
12061 case LI_GET_SUPPORTED_SERVICES:
12062 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12063 {
12064 result_buffer[0] = 17;
12065 result_buffer[3] = 14;
12066 PUT_WORD (&result_buffer[4], GOOD);
12067 d = 0;
12068 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12069 d |= LI_CONFERENCING_SUPPORTED;
12070 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12071 d |= LI_MONITORING_SUPPORTED;
12072 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12073 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12074 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12075 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12076 PUT_DWORD (&result_buffer[6], d);
12077 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12078 {
12079 d = 0;
12080 for (i = 0; i < li_total_channels; i++)
12081 {
12082 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083 && (li_config_table[i].adapter->li_pri
12084 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12085 {
12086 d++;
12087 }
12088 }
12089 }
12090 else
12091 {
12092 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12093 }
12094 PUT_DWORD (&result_buffer[10], d / 2);
12095 PUT_DWORD (&result_buffer[14], d);
12096 }
12097 else
12098 {
12099 result_buffer[0] = 25;
12100 result_buffer[3] = 22;
12101 PUT_WORD (&result_buffer[4], GOOD);
12102 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12103 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12104 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12105 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12106 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12107 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12108 d |= LI2_PC_LOOPING_SUPPORTED;
12109 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12110 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12111 PUT_DWORD (&result_buffer[6], d);
12112 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12113 PUT_DWORD (&result_buffer[10], d / 2);
12114 PUT_DWORD (&result_buffer[14], d - 1);
12115 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12116 {
12117 d = 0;
12118 for (i = 0; i < li_total_channels; i++)
12119 {
12120 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12121 && (li_config_table[i].adapter->li_pri
12122 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12123 {
12124 d++;
12125 }
12126 }
12127 }
12128 PUT_DWORD (&result_buffer[18], d / 2);
12129 PUT_DWORD (&result_buffer[22], d - 1);
12130 }
12131 break;
12132
12133 case LI_REQ_CONNECT:
12134 if (li_parms[1].length == 8)
12135 {
12136 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12137 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12138 {
12139 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12140 UnMapId (Id), (char *)(FILE_), __LINE__));
12141 Info = _WRONG_MESSAGE_FORMAT;
12142 break;
12143 }
12144 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12145 li_flags = GET_DWORD (li_req_parms[1].info);
12146 Info = li_check_main_plci (Id, plci);
12147 result_buffer[0] = 9;
12148 result_buffer[3] = 6;
12149 PUT_DWORD (&result_buffer[4], plci_b_id);
12150 PUT_WORD (&result_buffer[8], GOOD);
12151 if (Info != GOOD)
12152 break;
12153 result = plci->saved_msg.info;
12154 for (i = 0; i <= result_buffer[0]; i++)
12155 result[i] = result_buffer[i];
12156 plci_b_write_pos = plci->li_plci_b_write_pos;
12157 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12158 if (plci_b == NULL)
12159 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012160 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012161 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12162 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12163 plci->li_plci_b_write_pos = plci_b_write_pos;
12164 }
12165 else
12166 {
12167 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12168 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12169 {
12170 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12171 UnMapId (Id), (char *)(FILE_), __LINE__));
12172 Info = _WRONG_MESSAGE_FORMAT;
12173 break;
12174 }
12175 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12176 Info = li_check_main_plci (Id, plci);
12177 result_buffer[0] = 7;
12178 result_buffer[3] = 4;
12179 PUT_WORD (&result_buffer[4], Info);
12180 result_buffer[6] = 0;
12181 if (Info != GOOD)
12182 break;
12183 result = plci->saved_msg.info;
12184 for (i = 0; i <= result_buffer[0]; i++)
12185 result[i] = result_buffer[i];
12186 plci_b_write_pos = plci->li_plci_b_write_pos;
12187 participant_parms_pos = 0;
12188 result_pos = 7;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012189 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012190 while (participant_parms_pos < li_req_parms[1].length)
12191 {
12192 result[result_pos] = 6;
12193 result_pos += 7;
12194 PUT_DWORD (&result[result_pos - 6], 0);
12195 PUT_WORD (&result[result_pos - 2], GOOD);
12196 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12197 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12198 {
12199 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12200 UnMapId (Id), (char *)(FILE_), __LINE__));
12201 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12202 break;
12203 }
12204 if (api_parse (&li_participant_struct[0].info[1],
12205 li_participant_struct[0].length, "dd", li_participant_parms))
12206 {
12207 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12208 UnMapId (Id), (char *)(FILE_), __LINE__));
12209 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210 break;
12211 }
12212 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12213 li_flags = GET_DWORD (li_participant_parms[1].info);
12214 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12215 if (sizeof(result) - result_pos < 7)
12216 {
12217 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12218 UnMapId (Id), (char *)(FILE_), __LINE__));
12219 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12220 break;
12221 }
12222 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12223 if (plci_b != NULL)
12224 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012225 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012226 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12227 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12228 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12229 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12230 }
12231 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12232 (&li_req_parms[1].info[1]));
12233 }
12234 result[0] = (byte)(result_pos - 1);
12235 result[3] = (byte)(result_pos - 4);
12236 result[6] = (byte)(result_pos - 7);
12237 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12238 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12239 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12240 {
12241 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12242 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12243 }
12244 else
12245 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12246 plci->li_plci_b_write_pos = plci_b_write_pos;
12247 }
12248 mixer_calculate_coefs (a);
12249 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012250 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012251 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12252 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12253 plci->command = 0;
12254 plci->li_cmd = GET_WORD (li_parms[0].info);
12255 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012256 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012257
12258 case LI_REQ_DISCONNECT:
12259 if (li_parms[1].length == 4)
12260 {
12261 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12262 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12263 {
12264 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12265 UnMapId (Id), (char *)(FILE_), __LINE__));
12266 Info = _WRONG_MESSAGE_FORMAT;
12267 break;
12268 }
12269 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12270 Info = li_check_main_plci (Id, plci);
12271 result_buffer[0] = 9;
12272 result_buffer[3] = 6;
12273 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12274 PUT_WORD (&result_buffer[8], GOOD);
12275 if (Info != GOOD)
12276 break;
12277 result = plci->saved_msg.info;
12278 for (i = 0; i <= result_buffer[0]; i++)
12279 result[i] = result_buffer[i];
12280 plci_b_write_pos = plci->li_plci_b_write_pos;
12281 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12282 if (plci_b == NULL)
12283 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012284 li_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012285 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12286 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12287 plci->li_plci_b_write_pos = plci_b_write_pos;
12288 }
12289 else
12290 {
12291 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12292 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12293 {
12294 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12295 UnMapId (Id), (char *)(FILE_), __LINE__));
12296 Info = _WRONG_MESSAGE_FORMAT;
12297 break;
12298 }
12299 Info = li_check_main_plci (Id, plci);
12300 result_buffer[0] = 7;
12301 result_buffer[3] = 4;
12302 PUT_WORD (&result_buffer[4], Info);
12303 result_buffer[6] = 0;
12304 if (Info != GOOD)
12305 break;
12306 result = plci->saved_msg.info;
12307 for (i = 0; i <= result_buffer[0]; i++)
12308 result[i] = result_buffer[i];
12309 plci_b_write_pos = plci->li_plci_b_write_pos;
12310 participant_parms_pos = 0;
12311 result_pos = 7;
12312 while (participant_parms_pos < li_req_parms[0].length)
12313 {
12314 result[result_pos] = 6;
12315 result_pos += 7;
12316 PUT_DWORD (&result[result_pos - 6], 0);
12317 PUT_WORD (&result[result_pos - 2], GOOD);
12318 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12319 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12320 {
12321 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12322 UnMapId (Id), (char *)(FILE_), __LINE__));
12323 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12324 break;
12325 }
12326 if (api_parse (&li_participant_struct[0].info[1],
12327 li_participant_struct[0].length, "d", li_participant_parms))
12328 {
12329 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12330 UnMapId (Id), (char *)(FILE_), __LINE__));
12331 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332 break;
12333 }
12334 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12335 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12336 if (sizeof(result) - result_pos < 7)
12337 {
12338 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12339 UnMapId (Id), (char *)(FILE_), __LINE__));
12340 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12341 break;
12342 }
12343 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12344 if (plci_b != NULL)
12345 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012346 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012347 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12348 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12349 }
12350 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12351 (&li_req_parms[0].info[1]));
12352 }
12353 result[0] = (byte)(result_pos - 1);
12354 result[3] = (byte)(result_pos - 4);
12355 result[6] = (byte)(result_pos - 7);
12356 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12357 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12358 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12359 {
12360 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12361 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12362 }
12363 else
12364 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12365 plci->li_plci_b_write_pos = plci_b_write_pos;
12366 }
12367 mixer_calculate_coefs (a);
12368 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012369 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012370 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12371 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12372 plci->command = 0;
12373 plci->li_cmd = GET_WORD (li_parms[0].info);
12374 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012375 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012376
12377 case LI_REQ_SILENT_UPDATE:
12378 if (!plci || !plci->State
12379 || !plci->NL.Id || plci->nl_remove_id
12380 || (plci->li_bchannel_id == 0)
12381 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12382 {
12383 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12384 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012385 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012386 }
12387 plci_b_write_pos = plci->li_plci_b_write_pos;
12388 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12389 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12390 {
12391 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12392 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012393 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012394 }
12395 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12396 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12397 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12398 {
12399 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12400 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12401 }
12402 else
12403 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12404 plci->li_plci_b_write_pos = plci_b_write_pos;
12405 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12406 plci->command = 0;
12407 plci->li_cmd = GET_WORD (li_parms[0].info);
12408 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012409 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012410
12411 default:
12412 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12413 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12414 Info = _FACILITY_NOT_SUPPORTED;
12415 }
12416 }
12417 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12418 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012419 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012420}
12421
12422
12423static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12424{
12425 dword d;
12426 DIVA_CAPI_ADAPTER *a;
12427 byte result[12];
12428
12429 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12430 UnMapId (Id), (char *)(FILE_), __LINE__));
12431
12432 a = plci->adapter;
12433 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12434 {
12435 do
12436 {
12437 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12438 if (!(d & LI_PLCI_B_SKIP_FLAG))
12439 {
12440 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12441 {
12442 if (d & LI_PLCI_B_DISC_FLAG)
12443 {
12444 result[0] = 5;
12445 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12446 result[3] = 2;
12447 PUT_WORD (&result[4], _LI_USER_INITIATED);
12448 }
12449 else
12450 {
12451 result[0] = 7;
12452 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12453 result[3] = 4;
12454 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12455 }
12456 }
12457 else
12458 {
12459 if (d & LI_PLCI_B_DISC_FLAG)
12460 {
12461 result[0] = 9;
12462 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12463 result[3] = 6;
12464 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12465 PUT_WORD (&result[8], _LI_USER_INITIATED);
12466 }
12467 else
12468 {
12469 result[0] = 7;
12470 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12471 result[3] = 4;
12472 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12473 }
12474 }
12475 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12476 "ws", SELECTOR_LINE_INTERCONNECT, result);
12477 }
12478 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12479 0 : plci->li_plci_b_read_pos + 1;
12480 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12481 }
12482}
12483
12484
12485static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12486{
12487 word i, j, ch;
12488 struct xconnect_transfer_address_s s, *p;
12489 DIVA_CAPI_ADAPTER *a;
12490
12491 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12492 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12493
12494 a = plci->adapter;
12495 i = 1;
12496 for (i = 1; i < length; i += 16)
12497 {
12498 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12499 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12500 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12501 ch = msg[i+12] | (msg[i+13] << 8);
12502 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12503 if (!a->li_pri && (plci->li_bchannel_id == 2))
12504 j = 1 - j;
12505 j += a->li_base;
12506 if (ch & XCONNECT_CHANNEL_PORT_PC)
12507 p = &(li_config_table[j].send_pc);
12508 else
12509 p = &(li_config_table[j].send_b);
12510 p->card_address.low = s.card_address.low;
12511 p->card_address.high = s.card_address.high;
12512 p->offset = s.offset;
12513 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12514 }
12515 if (plci->internal_command_queue[0]
12516 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12517 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12518 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12519 {
12520 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12521 if (!plci->internal_command)
12522 next_internal_command (Id, plci);
12523 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012524 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012525}
12526
12527
12528static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12529{
12530
12531 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12532 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12533
12534}
12535
12536
12537static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12538{
12539 word plci_b_write_pos;
12540
12541 plci_b_write_pos = plci->li_plci_b_write_pos;
12542 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12543 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12544 {
12545 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12546 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12547 (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012548 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012549 }
12550 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12551 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12552 plci->li_plci_b_write_pos = plci_b_write_pos;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012553 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012554}
12555
12556
12557static void mixer_remove (PLCI *plci)
12558{
12559 DIVA_CAPI_ADAPTER *a;
12560 PLCI *notify_plci;
12561 dword plci_b_id;
12562 word i, j;
12563
12564 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12565 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12566 (char *)(FILE_), __LINE__));
12567
12568 a = plci->adapter;
12569 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12570 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12571 {
12572 if ((plci->li_bchannel_id != 0)
12573 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12574 {
12575 i = a->li_base + (plci->li_bchannel_id - 1);
12576 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12577 {
12578 for (j = 0; j < li_total_channels; j++)
12579 {
12580 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12581 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12582 {
12583 notify_plci = li_config_table[j].plci;
12584 if ((notify_plci != NULL)
12585 && (notify_plci != plci)
12586 && (notify_plci->appl != NULL)
12587 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12588 && (notify_plci->State)
12589 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12590 {
12591 mixer_notify_source_removed (notify_plci, plci_b_id);
12592 }
12593 }
12594 }
12595 mixer_clear_config (plci);
12596 mixer_calculate_coefs (a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012597 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012598 }
12599 li_config_table[i].plci = NULL;
12600 plci->li_bchannel_id = 0;
12601 }
12602 }
12603}
12604
12605
12606/*------------------------------------------------------------------*/
12607/* Echo canceller facilities */
12608/*------------------------------------------------------------------*/
12609
12610
12611static void ec_write_parameters (PLCI *plci)
12612{
12613 word w;
12614 byte parameter_buffer[6];
12615
12616 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12617 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12618 (char *)(FILE_), __LINE__));
12619
12620 parameter_buffer[0] = 5;
12621 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12622 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12623 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12624 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12625 PUT_WORD (&parameter_buffer[4], w);
12626 add_p (plci, FTY, parameter_buffer);
12627 sig_req (plci, TEL_CTRL, 0);
12628 send_req (plci);
12629}
12630
12631
12632static void ec_clear_config (PLCI *plci)
12633{
12634
12635 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12636 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12637 (char *)(FILE_), __LINE__));
12638
12639 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12640 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12641 plci->ec_tail_length = 0;
12642}
12643
12644
12645static void ec_prepare_switch (dword Id, PLCI *plci)
12646{
12647
12648 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12649 UnMapId (Id), (char *)(FILE_), __LINE__));
12650
12651}
12652
12653
12654static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12655{
12656
12657 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12658 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12659
12660 return (GOOD);
12661}
12662
12663
12664static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12665{
12666 word Info;
12667
12668 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12669 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12670
12671 Info = GOOD;
12672 if (plci->B1_facilities & B1_FACILITY_EC)
12673 {
12674 switch (plci->adjust_b_state)
12675 {
12676 case ADJUST_B_RESTORE_EC_1:
12677 plci->internal_command = plci->adjust_b_command;
12678 if (plci->sig_req)
12679 {
12680 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12681 break;
12682 }
12683 ec_write_parameters (plci);
12684 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12685 break;
12686 case ADJUST_B_RESTORE_EC_2:
12687 if ((Rc != OK) && (Rc != OK_FC))
12688 {
12689 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12690 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12691 Info = _WRONG_STATE;
12692 break;
12693 }
12694 break;
12695 }
12696 }
12697 return (Info);
12698}
12699
12700
12701static void ec_command (dword Id, PLCI *plci, byte Rc)
12702{
12703 word internal_command, Info;
12704 byte result[8];
12705
12706 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12707 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12708 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12709
12710 Info = GOOD;
12711 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12712 {
12713 result[0] = 2;
12714 PUT_WORD (&result[1], EC_SUCCESS);
12715 }
12716 else
12717 {
12718 result[0] = 5;
12719 PUT_WORD (&result[1], plci->ec_cmd);
12720 result[3] = 2;
12721 PUT_WORD (&result[4], GOOD);
12722 }
12723 internal_command = plci->internal_command;
12724 plci->internal_command = 0;
12725 switch (plci->ec_cmd)
12726 {
12727 case EC_ENABLE_OPERATION:
12728 case EC_FREEZE_COEFFICIENTS:
12729 case EC_RESUME_COEFFICIENT_UPDATE:
12730 case EC_RESET_COEFFICIENTS:
12731 switch (internal_command)
12732 {
12733 default:
12734 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12735 B1_FACILITY_EC), EC_COMMAND_1);
12736 case EC_COMMAND_1:
12737 if (adjust_b_process (Id, plci, Rc) != GOOD)
12738 {
12739 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12740 UnMapId (Id), (char *)(FILE_), __LINE__));
12741 Info = _FACILITY_NOT_SUPPORTED;
12742 break;
12743 }
12744 if (plci->internal_command)
12745 return;
12746 case EC_COMMAND_2:
12747 if (plci->sig_req)
12748 {
12749 plci->internal_command = EC_COMMAND_2;
12750 return;
12751 }
12752 plci->internal_command = EC_COMMAND_3;
12753 ec_write_parameters (plci);
12754 return;
12755 case EC_COMMAND_3:
12756 if ((Rc != OK) && (Rc != OK_FC))
12757 {
12758 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12759 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12760 Info = _FACILITY_NOT_SUPPORTED;
12761 break;
12762 }
12763 break;
12764 }
12765 break;
12766
12767 case EC_DISABLE_OPERATION:
12768 switch (internal_command)
12769 {
12770 default:
12771 case EC_COMMAND_1:
12772 if (plci->B1_facilities & B1_FACILITY_EC)
12773 {
12774 if (plci->sig_req)
12775 {
12776 plci->internal_command = EC_COMMAND_1;
12777 return;
12778 }
12779 plci->internal_command = EC_COMMAND_2;
12780 ec_write_parameters (plci);
12781 return;
12782 }
12783 Rc = OK;
12784 case EC_COMMAND_2:
12785 if ((Rc != OK) && (Rc != OK_FC))
12786 {
12787 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12788 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12789 Info = _FACILITY_NOT_SUPPORTED;
12790 break;
12791 }
12792 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12793 ~B1_FACILITY_EC), EC_COMMAND_3);
12794 case EC_COMMAND_3:
12795 if (adjust_b_process (Id, plci, Rc) != GOOD)
12796 {
12797 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12798 UnMapId (Id), (char *)(FILE_), __LINE__));
12799 Info = _FACILITY_NOT_SUPPORTED;
12800 break;
12801 }
12802 if (plci->internal_command)
12803 return;
12804 break;
12805 }
12806 break;
12807 }
12808 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12809 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12810 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12811}
12812
12813
12814static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12815{
12816 word Info;
12817 word opt;
12818 API_PARSE ec_parms[3];
12819 byte result[16];
12820
12821 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12822 UnMapId (Id), (char *)(FILE_), __LINE__));
12823
12824 Info = GOOD;
12825 result[0] = 0;
12826 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12827 {
12828 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12829 UnMapId (Id), (char *)(FILE_), __LINE__));
12830 Info = _FACILITY_NOT_SUPPORTED;
12831 }
12832 else
12833 {
12834 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12835 {
12836 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12837 {
12838 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12839 UnMapId (Id), (char *)(FILE_), __LINE__));
12840 Info = _WRONG_MESSAGE_FORMAT;
12841 }
12842 else
12843 {
12844 if (plci == NULL)
12845 {
12846 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12847 UnMapId (Id), (char *)(FILE_), __LINE__));
12848 Info = _WRONG_IDENTIFIER;
12849 }
12850 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12851 {
12852 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12853 UnMapId (Id), (char *)(FILE_), __LINE__));
12854 Info = _WRONG_STATE;
12855 }
12856 else
12857 {
12858 plci->command = 0;
12859 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12860 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12861 result[0] = 2;
12862 PUT_WORD (&result[1], EC_SUCCESS);
12863 if (msg[1].length >= 4)
12864 {
12865 opt = GET_WORD (&ec_parms[0].info[2]);
12866 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12867 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12868 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12869 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12870 if (opt & EC_DETECT_DISABLE_TONE)
12871 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12872 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12873 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12874 if (msg[1].length >= 6)
12875 {
12876 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12877 }
12878 }
12879 switch (plci->ec_cmd)
12880 {
12881 case EC_ENABLE_OPERATION:
12882 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12883 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012884 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012885
12886 case EC_DISABLE_OPERATION:
12887 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12888 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12889 LEC_RESET_COEFFICIENTS;
12890 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012891 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012892
12893 case EC_FREEZE_COEFFICIENTS:
12894 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12895 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012896 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012897
12898 case EC_RESUME_COEFFICIENT_UPDATE:
12899 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12900 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012901 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012902
12903 case EC_RESET_COEFFICIENTS:
12904 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12905 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012906 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012907
12908 default:
12909 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12910 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12911 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12912 }
12913 }
12914 }
12915 }
12916 else
12917 {
12918 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12919 {
12920 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12921 UnMapId (Id), (char *)(FILE_), __LINE__));
12922 Info = _WRONG_MESSAGE_FORMAT;
12923 }
12924 else
12925 {
12926 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12927 {
12928 result[0] = 11;
12929 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12930 result[3] = 8;
12931 PUT_WORD (&result[4], GOOD);
12932 PUT_WORD (&result[6], 0x0007);
12933 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12934 PUT_WORD (&result[10], 0);
12935 }
12936 else if (plci == NULL)
12937 {
12938 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12939 UnMapId (Id), (char *)(FILE_), __LINE__));
12940 Info = _WRONG_IDENTIFIER;
12941 }
12942 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12943 {
12944 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12945 UnMapId (Id), (char *)(FILE_), __LINE__));
12946 Info = _WRONG_STATE;
12947 }
12948 else
12949 {
12950 plci->command = 0;
12951 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12952 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12953 result[0] = 5;
12954 PUT_WORD (&result[1], plci->ec_cmd);
12955 result[3] = 2;
12956 PUT_WORD (&result[4], GOOD);
12957 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12958 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12959 plci->ec_tail_length = 0;
12960 if (ec_parms[1].length >= 2)
12961 {
12962 opt = GET_WORD (&ec_parms[1].info[1]);
12963 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12964 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12965 if (opt & EC_DETECT_DISABLE_TONE)
12966 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12967 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12968 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12969 if (ec_parms[1].length >= 4)
12970 {
12971 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12972 }
12973 }
12974 switch (plci->ec_cmd)
12975 {
12976 case EC_ENABLE_OPERATION:
12977 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12978 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012979 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012980
12981 case EC_DISABLE_OPERATION:
12982 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12983 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12984 LEC_RESET_COEFFICIENTS;
12985 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012986 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012987
12988 default:
12989 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12990 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12991 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12992 }
12993 }
12994 }
12995 }
12996 }
12997 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12998 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12999 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013000 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013001}
13002
13003
13004static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13005{
13006 byte result[8];
13007
13008 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13009 UnMapId (Id), (char *)(FILE_), __LINE__));
13010
13011 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13012 {
13013 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13014 {
13015 result[0] = 2;
13016 PUT_WORD (&result[1], 0);
13017 switch (msg[1])
13018 {
13019 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13020 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13021 break;
13022 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13023 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13024 break;
13025 case LEC_DISABLE_RELEASED:
13026 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13027 break;
13028 }
13029 }
13030 else
13031 {
13032 result[0] = 5;
13033 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13034 result[3] = 2;
13035 PUT_WORD (&result[4], 0);
13036 switch (msg[1])
13037 {
13038 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13039 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13040 break;
13041 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13042 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13043 break;
13044 case LEC_DISABLE_RELEASED:
13045 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13046 break;
13047 }
13048 }
13049 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13050 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13051 }
13052}
13053
13054
13055
13056/*------------------------------------------------------------------*/
13057/* Advanced voice */
13058/*------------------------------------------------------------------*/
13059
13060static void adv_voice_write_coefs (PLCI *plci, word write_command)
13061{
13062 DIVA_CAPI_ADAPTER *a;
13063 word i;
13064 byte *p;
13065
13066 word w, n, j, k;
13067 byte ch_map[MIXER_CHANNELS_BRI];
13068
13069 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13070
13071 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13072 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13073 (char *)(FILE_), __LINE__, write_command));
13074
13075 a = plci->adapter;
13076 p = coef_buffer + 1;
13077 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13078 i = 0;
13079 while (i + sizeof(word) <= a->adv_voice_coef_length)
13080 {
13081 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13082 p += 2;
13083 i += 2;
13084 }
13085 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13086 {
13087 PUT_WORD (p, 0x8000);
13088 p += 2;
13089 i += 2;
13090 }
13091
13092 if (!a->li_pri && (plci->li_bchannel_id == 0))
13093 {
13094 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13095 {
13096 plci->li_bchannel_id = 1;
13097 li_config_table[a->li_base].plci = plci;
13098 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13099 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13100 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13101 }
13102 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13103 {
13104 plci->li_bchannel_id = 2;
13105 li_config_table[a->li_base + 1].plci = plci;
13106 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13107 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13108 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13109 }
13110 }
13111 if (!a->li_pri && (plci->li_bchannel_id != 0)
13112 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13113 {
13114 i = a->li_base + (plci->li_bchannel_id - 1);
13115 switch (write_command)
13116 {
13117 case ADV_VOICE_WRITE_ACTIVATION:
13118 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13119 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13120 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13121 {
13122 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13123 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13124 }
13125 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13126 {
13127 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13128 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13129 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13130 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13131 }
13132 mixer_calculate_coefs (a);
13133 li_config_table[i].curchnl = li_config_table[i].channel;
13134 li_config_table[j].curchnl = li_config_table[j].channel;
13135 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13136 li_config_table[k].curchnl = li_config_table[k].channel;
13137 break;
13138
13139 case ADV_VOICE_WRITE_DEACTIVATION:
13140 for (j = 0; j < li_total_channels; j++)
13141 {
13142 li_config_table[i].flag_table[j] = 0;
13143 li_config_table[j].flag_table[i] = 0;
13144 }
13145 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13146 for (j = 0; j < li_total_channels; j++)
13147 {
13148 li_config_table[k].flag_table[j] = 0;
13149 li_config_table[j].flag_table[k] = 0;
13150 }
13151 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13152 {
13153 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13154 for (j = 0; j < li_total_channels; j++)
13155 {
13156 li_config_table[k].flag_table[j] = 0;
13157 li_config_table[j].flag_table[k] = 0;
13158 }
13159 }
13160 mixer_calculate_coefs (a);
13161 break;
13162 }
13163 if (plci->B1_facilities & B1_FACILITY_MIXER)
13164 {
13165 w = 0;
13166 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13167 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13168 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13169 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13170 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13171 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13172 *(p++) = (byte) w;
13173 *(p++) = (byte)(w >> 8);
13174 for (j = 0; j < sizeof(ch_map); j += 2)
13175 {
13176 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13177 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13178 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080013179 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013180 {
13181 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13182 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13183 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13184 {
13185 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13186 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13187 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13188 }
13189 else
13190 {
13191 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13192 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13193 }
13194 }
13195 }
13196 else
13197 {
13198 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13199 *(p++) = a->adv_voice_coef_buffer[i];
13200 }
13201 }
13202 else
13203
13204 {
13205 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206 *(p++) = a->adv_voice_coef_buffer[i];
13207 }
13208 coef_buffer[0] = (p - coef_buffer) - 1;
13209 add_p (plci, FTY, coef_buffer);
13210 sig_req (plci, TEL_CTRL, 0);
13211 send_req (plci);
13212}
13213
13214
13215static void adv_voice_clear_config (PLCI *plci)
13216{
13217 DIVA_CAPI_ADAPTER *a;
13218
13219 word i, j;
13220
13221
13222 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13223 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13224 (char *)(FILE_), __LINE__));
13225
13226 a = plci->adapter;
13227 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13228 {
13229 a->adv_voice_coef_length = 0;
13230
13231 if (!a->li_pri && (plci->li_bchannel_id != 0)
13232 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13233 {
13234 i = a->li_base + (plci->li_bchannel_id - 1);
13235 li_config_table[i].curchnl = 0;
13236 li_config_table[i].channel = 0;
13237 li_config_table[i].chflags = 0;
13238 for (j = 0; j < li_total_channels; j++)
13239 {
13240 li_config_table[i].flag_table[j] = 0;
13241 li_config_table[j].flag_table[i] = 0;
13242 li_config_table[i].coef_table[j] = 0;
13243 li_config_table[j].coef_table[i] = 0;
13244 }
13245 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13246 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13247 li_config_table[i].curchnl = 0;
13248 li_config_table[i].channel = 0;
13249 li_config_table[i].chflags = 0;
13250 for (j = 0; j < li_total_channels; j++)
13251 {
13252 li_config_table[i].flag_table[j] = 0;
13253 li_config_table[j].flag_table[i] = 0;
13254 li_config_table[i].coef_table[j] = 0;
13255 li_config_table[j].coef_table[i] = 0;
13256 }
13257 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13258 {
13259 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13260 li_config_table[i].curchnl = 0;
13261 li_config_table[i].channel = 0;
13262 li_config_table[i].chflags = 0;
13263 for (j = 0; j < li_total_channels; j++)
13264 {
13265 li_config_table[i].flag_table[j] = 0;
13266 li_config_table[j].flag_table[i] = 0;
13267 li_config_table[i].coef_table[j] = 0;
13268 li_config_table[j].coef_table[i] = 0;
13269 }
13270 }
13271 }
13272
13273 }
13274}
13275
13276
13277static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13278{
13279
13280 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13281 UnMapId (Id), (char *)(FILE_), __LINE__));
13282
13283}
13284
13285
13286static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13287{
13288
13289 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13290 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13291
13292 return (GOOD);
13293}
13294
13295
13296static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13297{
13298 DIVA_CAPI_ADAPTER *a;
13299 word Info;
13300
13301 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13302 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13303
13304 Info = GOOD;
13305 a = plci->adapter;
13306 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13307 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13308 {
13309 switch (plci->adjust_b_state)
13310 {
13311 case ADJUST_B_RESTORE_VOICE_1:
13312 plci->internal_command = plci->adjust_b_command;
13313 if (plci->sig_req)
13314 {
13315 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13316 break;
13317 }
13318 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13319 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13320 break;
13321 case ADJUST_B_RESTORE_VOICE_2:
13322 if ((Rc != OK) && (Rc != OK_FC))
13323 {
13324 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13325 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13326 Info = _WRONG_STATE;
13327 break;
13328 }
13329 break;
13330 }
13331 }
13332 return (Info);
13333}
13334
13335
13336
13337
13338/*------------------------------------------------------------------*/
13339/* B1 resource switching */
13340/*------------------------------------------------------------------*/
13341
13342static byte b1_facilities_table[] =
13343{
13344 0x00, /* 0 No bchannel resources */
13345 0x00, /* 1 Codec (automatic law) */
13346 0x00, /* 2 Codec (A-law) */
13347 0x00, /* 3 Codec (y-law) */
13348 0x00, /* 4 HDLC for X.21 */
13349 0x00, /* 5 HDLC */
13350 0x00, /* 6 External Device 0 */
13351 0x00, /* 7 External Device 1 */
13352 0x00, /* 8 HDLC 56k */
13353 0x00, /* 9 Transparent */
13354 0x00, /* 10 Loopback to network */
13355 0x00, /* 11 Test pattern to net */
13356 0x00, /* 12 Rate adaptation sync */
13357 0x00, /* 13 Rate adaptation async */
13358 0x00, /* 14 R-Interface */
13359 0x00, /* 15 HDLC 128k leased line */
13360 0x00, /* 16 FAX */
13361 0x00, /* 17 Modem async */
13362 0x00, /* 18 Modem sync HDLC */
13363 0x00, /* 19 V.110 async HDLC */
13364 0x12, /* 20 Adv voice (Trans,mixer) */
13365 0x00, /* 21 Codec connected to IC */
13366 0x0c, /* 22 Trans,DTMF */
13367 0x1e, /* 23 Trans,DTMF+mixer */
13368 0x1f, /* 24 Trans,DTMF+mixer+local */
13369 0x13, /* 25 Trans,mixer+local */
13370 0x12, /* 26 HDLC,mixer */
13371 0x12, /* 27 HDLC 56k,mixer */
13372 0x2c, /* 28 Trans,LEC+DTMF */
13373 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13374 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13375 0x2c, /* 31 RTP,LEC+DTMF */
13376 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13377 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13378 0x00, /* 34 Signaling task */
13379 0x00, /* 35 PIAFS */
13380 0x0c, /* 36 Trans,DTMF+TONE */
13381 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13382 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13383};
13384
13385
13386static word get_b1_facilities (PLCI * plci, byte b1_resource)
13387{
13388 word b1_facilities;
13389
13390 b1_facilities = b1_facilities_table[b1_resource];
13391 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13392 {
13393
13394 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13395 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13396
13397 {
13398 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13399 b1_facilities |= B1_FACILITY_DTMFX;
13400 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13401 b1_facilities |= B1_FACILITY_DTMFR;
13402 }
13403 }
13404 if ((b1_resource == 17) || (b1_resource == 18))
13405 {
13406 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13407 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13408 }
13409/*
13410 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13411 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13412 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13413*/
13414 return (b1_facilities);
13415}
13416
13417
13418static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13419{
13420 byte b;
13421
13422 switch (b1_resource)
13423 {
13424 case 5:
13425 case 26:
13426 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13427 b = 26;
13428 else
13429 b = 5;
13430 break;
13431
13432 case 8:
13433 case 27:
13434 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13435 b = 27;
13436 else
13437 b = 8;
13438 break;
13439
13440 case 9:
13441 case 20:
13442 case 22:
13443 case 23:
13444 case 24:
13445 case 25:
13446 case 28:
13447 case 29:
13448 case 30:
13449 case 36:
13450 case 37:
13451 case 38:
13452 if (b1_facilities & B1_FACILITY_EC)
13453 {
13454 if (b1_facilities & B1_FACILITY_LOCAL)
13455 b = 30;
13456 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13457 b = 29;
13458 else
13459 b = 28;
13460 }
13461
13462 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13463 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13464 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13465 {
13466 if (b1_facilities & B1_FACILITY_LOCAL)
13467 b = 38;
13468 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13469 b = 37;
13470 else
13471 b = 36;
13472 }
13473
13474 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13475 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13476 || ((b1_facilities & B1_FACILITY_DTMFR)
13477 && ((b1_facilities & B1_FACILITY_MIXER)
13478 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13479 || ((b1_facilities & B1_FACILITY_DTMFX)
13480 && ((b1_facilities & B1_FACILITY_MIXER)
13481 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13482 {
13483 if (b1_facilities & B1_FACILITY_LOCAL)
13484 b = 24;
13485 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13486 b = 23;
13487 else
13488 b = 22;
13489 }
13490 else
13491 {
13492 if (b1_facilities & B1_FACILITY_LOCAL)
13493 b = 25;
13494 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13495 b = 20;
13496 else
13497 b = 9;
13498 }
13499 break;
13500
13501 case 31:
13502 case 32:
13503 case 33:
13504 if (b1_facilities & B1_FACILITY_LOCAL)
13505 b = 33;
13506 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13507 b = 32;
13508 else
13509 b = 31;
13510 break;
13511
13512 default:
13513 b = b1_resource;
13514 }
13515 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13516 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13517 (char *)(FILE_), __LINE__,
13518 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13519 return (b);
13520}
13521
13522
13523static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13524{
13525 word removed_facilities;
13526
13527 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13528 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13529 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13530 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13531
13532 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13533 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13534
13535 if (removed_facilities & B1_FACILITY_EC)
13536 ec_clear_config (plci);
13537
13538
13539 if (removed_facilities & B1_FACILITY_DTMFR)
13540 {
13541 dtmf_rec_clear_config (plci);
13542 dtmf_parameter_clear_config (plci);
13543 }
13544 if (removed_facilities & B1_FACILITY_DTMFX)
13545 dtmf_send_clear_config (plci);
13546
13547
13548 if (removed_facilities & B1_FACILITY_MIXER)
13549 mixer_clear_config (plci);
13550
13551 if (removed_facilities & B1_FACILITY_VOICE)
13552 adv_voice_clear_config (plci);
13553 plci->B1_facilities = new_b1_facilities;
13554}
13555
13556
13557static void adjust_b_clear (PLCI *plci)
13558{
13559
13560 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13561 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13562 (char *)(FILE_), __LINE__));
13563
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013564 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013565}
13566
13567
13568static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13569{
13570 word Info;
13571 byte b1_resource;
13572 NCCI * ncci_ptr;
13573 API_PARSE bp[2];
13574
13575 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13576 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13577
13578 Info = GOOD;
13579 switch (plci->adjust_b_state)
13580 {
13581 case ADJUST_B_START:
13582 if ((plci->adjust_b_parms_msg == NULL)
13583 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13584 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13585 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13586 {
13587 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13588 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13589 if (b1_resource == plci->B1_resource)
13590 {
13591 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13592 break;
13593 }
13594 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13595 {
13596 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13597 UnMapId (Id), (char *)(FILE_), __LINE__,
13598 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13599 Info = _WRONG_STATE;
13600 break;
13601 }
13602 }
13603 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13604 {
13605
13606 mixer_prepare_switch (Id, plci);
13607
13608
13609 dtmf_prepare_switch (Id, plci);
13610 dtmf_parameter_prepare_switch (Id, plci);
13611
13612
13613 ec_prepare_switch (Id, plci);
13614
13615 adv_voice_prepare_switch (Id, plci);
13616 }
13617 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13618 Rc = OK;
13619 case ADJUST_B_SAVE_MIXER_1:
13620 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13621 {
13622
13623 Info = mixer_save_config (Id, plci, Rc);
13624 if ((Info != GOOD) || plci->internal_command)
13625 break;
13626
13627 }
13628 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13629 Rc = OK;
13630 case ADJUST_B_SAVE_DTMF_1:
13631 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13632 {
13633
13634 Info = dtmf_save_config (Id, plci, Rc);
13635 if ((Info != GOOD) || plci->internal_command)
13636 break;
13637
13638 }
13639 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13640 case ADJUST_B_REMOVE_L23_1:
13641 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13642 && plci->NL.Id && !plci->nl_remove_id)
13643 {
13644 plci->internal_command = plci->adjust_b_command;
13645 if (plci->adjust_b_ncci != 0)
13646 {
13647 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13648 while (ncci_ptr->data_pending)
13649 {
13650 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13651 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13652 }
13653 while (ncci_ptr->data_ack_pending)
13654 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13655 }
13656 nl_req_ncci (plci, REMOVE,
13657 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13658 send_req (plci);
13659 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13660 break;
13661 }
13662 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13663 Rc = OK;
13664 case ADJUST_B_REMOVE_L23_2:
13665 if ((Rc != OK) && (Rc != OK_FC))
13666 {
13667 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13668 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13669 Info = _WRONG_STATE;
13670 break;
13671 }
13672 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13673 {
13674 if (plci_nl_busy (plci))
13675 {
13676 plci->internal_command = plci->adjust_b_command;
13677 break;
13678 }
13679 }
13680 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13681 Rc = OK;
13682 case ADJUST_B_SAVE_EC_1:
13683 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13684 {
13685
13686 Info = ec_save_config (Id, plci, Rc);
13687 if ((Info != GOOD) || plci->internal_command)
13688 break;
13689
13690 }
13691 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13692 Rc = OK;
13693 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13694 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13695 {
13696
13697 Info = dtmf_parameter_save_config (Id, plci, Rc);
13698 if ((Info != GOOD) || plci->internal_command)
13699 break;
13700
13701 }
13702 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13703 Rc = OK;
13704 case ADJUST_B_SAVE_VOICE_1:
13705 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13706 {
13707 Info = adv_voice_save_config (Id, plci, Rc);
13708 if ((Info != GOOD) || plci->internal_command)
13709 break;
13710 }
13711 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13712 case ADJUST_B_SWITCH_L1_1:
13713 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13714 {
13715 if (plci->sig_req)
13716 {
13717 plci->internal_command = plci->adjust_b_command;
13718 break;
13719 }
13720 if (plci->adjust_b_parms_msg != NULL)
13721 api_load_msg (plci->adjust_b_parms_msg, bp);
13722 else
13723 api_load_msg (&plci->B_protocol, bp);
13724 Info = add_b1 (plci, bp,
13725 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13726 plci->adjust_b_facilities);
13727 if (Info != GOOD)
13728 {
13729 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13730 UnMapId (Id), (char *)(FILE_), __LINE__,
13731 plci->B1_resource, plci->adjust_b_facilities));
13732 break;
13733 }
13734 plci->internal_command = plci->adjust_b_command;
13735 sig_req (plci, RESOURCES, 0);
13736 send_req (plci);
13737 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13738 break;
13739 }
13740 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13741 Rc = OK;
13742 case ADJUST_B_SWITCH_L1_2:
13743 if ((Rc != OK) && (Rc != OK_FC))
13744 {
13745 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13746 UnMapId (Id), (char *)(FILE_), __LINE__,
13747 Rc, plci->B1_resource, plci->adjust_b_facilities));
13748 Info = _WRONG_STATE;
13749 break;
13750 }
13751 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13752 Rc = OK;
13753 case ADJUST_B_RESTORE_VOICE_1:
13754 case ADJUST_B_RESTORE_VOICE_2:
13755 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13756 {
13757 Info = adv_voice_restore_config (Id, plci, Rc);
13758 if ((Info != GOOD) || plci->internal_command)
13759 break;
13760 }
13761 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13762 Rc = OK;
13763 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13764 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13765 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13766 {
13767
13768 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13769 if ((Info != GOOD) || plci->internal_command)
13770 break;
13771
13772 }
13773 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13774 Rc = OK;
13775 case ADJUST_B_RESTORE_EC_1:
13776 case ADJUST_B_RESTORE_EC_2:
13777 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13778 {
13779
13780 Info = ec_restore_config (Id, plci, Rc);
13781 if ((Info != GOOD) || plci->internal_command)
13782 break;
13783
13784 }
13785 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13786 case ADJUST_B_ASSIGN_L23_1:
13787 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13788 {
13789 if (plci_nl_busy (plci))
13790 {
13791 plci->internal_command = plci->adjust_b_command;
13792 break;
13793 }
13794 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13795 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13796 if (plci->adjust_b_parms_msg != NULL)
13797 api_load_msg (plci->adjust_b_parms_msg, bp);
13798 else
13799 api_load_msg (&plci->B_protocol, bp);
13800 Info = add_b23 (plci, bp);
13801 if (Info != GOOD)
13802 {
13803 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13804 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13805 break;
13806 }
13807 plci->internal_command = plci->adjust_b_command;
13808 nl_req_ncci (plci, ASSIGN, 0);
13809 send_req (plci);
13810 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13811 break;
13812 }
13813 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13814 Rc = ASSIGN_OK;
13815 case ADJUST_B_ASSIGN_L23_2:
13816 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13817 {
13818 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13819 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13820 Info = _WRONG_STATE;
13821 break;
13822 }
13823 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13824 {
13825 if (Rc != ASSIGN_OK)
13826 {
13827 plci->internal_command = plci->adjust_b_command;
13828 break;
13829 }
13830 }
13831 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13832 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013833 plci->adjust_b_restore = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013834 break;
13835 }
13836 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13837 case ADJUST_B_CONNECT_1:
13838 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13839 {
13840 plci->internal_command = plci->adjust_b_command;
13841 if (plci_nl_busy (plci))
13842 break;
13843 nl_req_ncci (plci, N_CONNECT, 0);
13844 send_req (plci);
13845 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13846 break;
13847 }
13848 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13849 Rc = OK;
13850 case ADJUST_B_CONNECT_2:
13851 case ADJUST_B_CONNECT_3:
13852 case ADJUST_B_CONNECT_4:
13853 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13854 {
13855 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13856 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13857 Info = _WRONG_STATE;
13858 break;
13859 }
13860 if (Rc == OK)
13861 {
13862 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13863 {
13864 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13865 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13866 }
13867 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13868 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13869 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13870 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13871 }
13872 else if (Rc == 0)
13873 {
13874 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13876 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13877 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878 }
13879 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13880 {
13881 plci->internal_command = plci->adjust_b_command;
13882 break;
13883 }
13884 Rc = OK;
13885 case ADJUST_B_RESTORE_DTMF_1:
13886 case ADJUST_B_RESTORE_DTMF_2:
13887 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13888 {
13889
13890 Info = dtmf_restore_config (Id, plci, Rc);
13891 if ((Info != GOOD) || plci->internal_command)
13892 break;
13893
13894 }
13895 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13896 Rc = OK;
13897 case ADJUST_B_RESTORE_MIXER_1:
13898 case ADJUST_B_RESTORE_MIXER_2:
13899 case ADJUST_B_RESTORE_MIXER_3:
13900 case ADJUST_B_RESTORE_MIXER_4:
13901 case ADJUST_B_RESTORE_MIXER_5:
13902 case ADJUST_B_RESTORE_MIXER_6:
13903 case ADJUST_B_RESTORE_MIXER_7:
13904 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13905 {
13906
13907 Info = mixer_restore_config (Id, plci, Rc);
13908 if ((Info != GOOD) || plci->internal_command)
13909 break;
13910
13911 }
13912 plci->adjust_b_state = ADJUST_B_END;
13913 case ADJUST_B_END:
13914 break;
13915 }
13916 return (Info);
13917}
13918
13919
13920static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13921{
13922
13923 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13924 UnMapId (Id), (char *)(FILE_), __LINE__,
13925 plci->B1_resource, b1_facilities));
13926
13927 plci->adjust_b_parms_msg = bp_msg;
13928 plci->adjust_b_facilities = b1_facilities;
13929 plci->adjust_b_command = internal_command;
13930 plci->adjust_b_ncci = (word)(Id >> 16);
13931 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13932 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13933 else
13934 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13935 plci->adjust_b_state = ADJUST_B_START;
13936 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13937 UnMapId (Id), (char *)(FILE_), __LINE__,
13938 plci->B1_resource, b1_facilities));
13939}
13940
13941
13942static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13943{
13944 word internal_command;
13945
13946 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13947 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13948
13949 internal_command = plci->internal_command;
13950 plci->internal_command = 0;
13951 switch (internal_command)
13952 {
13953 default:
13954 plci->command = 0;
13955 if (plci->req_in != 0)
13956 {
13957 plci->internal_command = ADJUST_B_RESTORE_1;
13958 break;
13959 }
13960 Rc = OK;
13961 case ADJUST_B_RESTORE_1:
13962 if ((Rc != OK) && (Rc != OK_FC))
13963 {
13964 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13965 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13966 }
13967 plci->adjust_b_parms_msg = NULL;
13968 plci->adjust_b_facilities = plci->B1_facilities;
13969 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13970 plci->adjust_b_ncci = (word)(Id >> 16);
13971 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13972 plci->adjust_b_state = ADJUST_B_START;
13973 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13974 UnMapId (Id), (char *)(FILE_), __LINE__));
13975 case ADJUST_B_RESTORE_2:
13976 if (adjust_b_process (Id, plci, Rc) != GOOD)
13977 {
13978 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13979 UnMapId (Id), (char *)(FILE_), __LINE__));
13980 }
13981 if (plci->internal_command)
13982 break;
13983 break;
13984 }
13985}
13986
13987
13988static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13989{
13990 word Info;
13991 word internal_command;
13992
13993 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13994 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13995
13996 Info = GOOD;
13997 internal_command = plci->internal_command;
13998 plci->internal_command = 0;
13999 switch (internal_command)
14000 {
14001 default:
14002 plci->command = 0;
14003 plci->adjust_b_parms_msg = NULL;
14004 plci->adjust_b_facilities = plci->B1_facilities;
14005 plci->adjust_b_command = RESET_B3_COMMAND_1;
14006 plci->adjust_b_ncci = (word)(Id >> 16);
14007 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14008 plci->adjust_b_state = ADJUST_B_START;
14009 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14010 UnMapId (Id), (char *)(FILE_), __LINE__));
14011 case RESET_B3_COMMAND_1:
14012 Info = adjust_b_process (Id, plci, Rc);
14013 if (Info != GOOD)
14014 {
14015 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14016 UnMapId (Id), (char *)(FILE_), __LINE__));
14017 break;
14018 }
14019 if (plci->internal_command)
14020 return;
14021 break;
14022 }
14023/* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14024 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14025}
14026
14027
14028static void select_b_command (dword Id, PLCI *plci, byte Rc)
14029{
14030 word Info;
14031 word internal_command;
14032 byte esc_chi[3];
14033
14034 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14035 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14036
14037 Info = GOOD;
14038 internal_command = plci->internal_command;
14039 plci->internal_command = 0;
14040 switch (internal_command)
14041 {
14042 default:
14043 plci->command = 0;
14044 plci->adjust_b_parms_msg = &plci->saved_msg;
14045 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14046 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14047 else
14048 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14049 plci->adjust_b_command = SELECT_B_COMMAND_1;
14050 plci->adjust_b_ncci = (word)(Id >> 16);
14051 if (plci->saved_msg.parms[0].length == 0)
14052 {
14053 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14054 ADJUST_B_MODE_NO_RESOURCE;
14055 }
14056 else
14057 {
14058 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14059 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14060 }
14061 plci->adjust_b_state = ADJUST_B_START;
14062 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14063 UnMapId (Id), (char *)(FILE_), __LINE__));
14064 case SELECT_B_COMMAND_1:
14065 Info = adjust_b_process (Id, plci, Rc);
14066 if (Info != GOOD)
14067 {
14068 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14069 UnMapId (Id), (char *)(FILE_), __LINE__));
14070 break;
14071 }
14072 if (plci->internal_command)
14073 return;
14074 if (plci->tel == ADV_VOICE)
14075 {
14076 esc_chi[0] = 0x02;
14077 esc_chi[1] = 0x18;
14078 esc_chi[2] = plci->b_channel;
14079 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14080 }
14081 break;
14082 }
14083 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14084}
14085
14086
14087static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14088{
14089 word Info;
14090 word internal_command;
14091
14092 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14093 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14094
14095 Info = GOOD;
14096 internal_command = plci->internal_command;
14097 plci->internal_command = 0;
14098 switch (internal_command)
14099 {
14100 default:
14101 plci->command = 0;
14102 case FAX_CONNECT_ACK_COMMAND_1:
14103 if (plci_nl_busy (plci))
14104 {
14105 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14106 return;
14107 }
14108 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14109 plci->NData[0].P = plci->fax_connect_info_buffer;
14110 plci->NData[0].PLength = plci->fax_connect_info_length;
14111 plci->NL.X = plci->NData;
14112 plci->NL.ReqCh = 0;
14113 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14114 plci->adapter->request (&plci->NL);
14115 return;
14116 case FAX_CONNECT_ACK_COMMAND_2:
14117 if ((Rc != OK) && (Rc != OK_FC))
14118 {
14119 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14120 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14121 break;
14122 }
14123 }
14124 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14125 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14126 {
14127 if (plci->B3_prot == 4)
14128 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14129 else
14130 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14131 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14132 }
14133}
14134
14135
14136static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14137{
14138 word Info;
14139 word internal_command;
14140
14141 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14142 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14143
14144 Info = GOOD;
14145 internal_command = plci->internal_command;
14146 plci->internal_command = 0;
14147 switch (internal_command)
14148 {
14149 default:
14150 plci->command = 0;
14151 case FAX_EDATA_ACK_COMMAND_1:
14152 if (plci_nl_busy (plci))
14153 {
14154 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14155 return;
14156 }
14157 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14158 plci->NData[0].P = plci->fax_connect_info_buffer;
14159 plci->NData[0].PLength = plci->fax_edata_ack_length;
14160 plci->NL.X = plci->NData;
14161 plci->NL.ReqCh = 0;
14162 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14163 plci->adapter->request (&plci->NL);
14164 return;
14165 case FAX_EDATA_ACK_COMMAND_2:
14166 if ((Rc != OK) && (Rc != OK_FC))
14167 {
14168 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14169 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14170 break;
14171 }
14172 }
14173}
14174
14175
14176static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14177{
14178 word Info;
14179 word internal_command;
14180
14181 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14182 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14183
14184 Info = GOOD;
14185 internal_command = plci->internal_command;
14186 plci->internal_command = 0;
14187 switch (internal_command)
14188 {
14189 default:
14190 plci->command = 0;
14191 case FAX_CONNECT_INFO_COMMAND_1:
14192 if (plci_nl_busy (plci))
14193 {
14194 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14195 return;
14196 }
14197 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14198 plci->NData[0].P = plci->fax_connect_info_buffer;
14199 plci->NData[0].PLength = plci->fax_connect_info_length;
14200 plci->NL.X = plci->NData;
14201 plci->NL.ReqCh = 0;
14202 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14203 plci->adapter->request (&plci->NL);
14204 return;
14205 case FAX_CONNECT_INFO_COMMAND_2:
14206 if ((Rc != OK) && (Rc != OK_FC))
14207 {
14208 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14209 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14210 Info = _WRONG_STATE;
14211 break;
14212 }
14213 if (plci_nl_busy (plci))
14214 {
14215 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14216 return;
14217 }
14218 plci->command = _CONNECT_B3_R;
14219 nl_req_ncci (plci, N_CONNECT, 0);
14220 send_req (plci);
14221 return;
14222 }
14223 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14224}
14225
14226
14227static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14228{
14229 word Info;
14230 word internal_command;
14231
14232 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14233 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14234
14235 Info = GOOD;
14236 internal_command = plci->internal_command;
14237 plci->internal_command = 0;
14238 switch (internal_command)
14239 {
14240 default:
14241 plci->command = 0;
14242 plci->adjust_b_parms_msg = NULL;
14243 plci->adjust_b_facilities = plci->B1_facilities;
14244 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14245 plci->adjust_b_ncci = (word)(Id >> 16);
14246 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14247 plci->adjust_b_state = ADJUST_B_START;
14248 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14249 UnMapId (Id), (char *)(FILE_), __LINE__));
14250 case FAX_ADJUST_B23_COMMAND_1:
14251 Info = adjust_b_process (Id, plci, Rc);
14252 if (Info != GOOD)
14253 {
14254 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14255 UnMapId (Id), (char *)(FILE_), __LINE__));
14256 break;
14257 }
14258 if (plci->internal_command)
14259 return;
14260 case FAX_ADJUST_B23_COMMAND_2:
14261 if (plci_nl_busy (plci))
14262 {
14263 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14264 return;
14265 }
14266 plci->command = _CONNECT_B3_R;
14267 nl_req_ncci (plci, N_CONNECT, 0);
14268 send_req (plci);
14269 return;
14270 }
14271 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14272}
14273
14274
14275static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14276{
14277 word internal_command;
14278
14279 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14280 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14281
14282 internal_command = plci->internal_command;
14283 plci->internal_command = 0;
14284 switch (internal_command)
14285 {
14286 default:
14287 plci->command = 0;
14288 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14289 return;
14290 case FAX_DISCONNECT_COMMAND_1:
14291 case FAX_DISCONNECT_COMMAND_2:
14292 case FAX_DISCONNECT_COMMAND_3:
14293 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14294 {
14295 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14296 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14297 break;
14298 }
14299 if (Rc == OK)
14300 {
14301 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14302 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14303 {
14304 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14305 }
14306 }
14307 else if (Rc == 0)
14308 {
14309 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14310 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14311 }
14312 return;
14313 }
14314}
14315
14316
14317
14318static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14319{
14320 word Info;
14321 word internal_command;
14322
14323 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14324 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14325
14326 Info = GOOD;
14327 internal_command = plci->internal_command;
14328 plci->internal_command = 0;
14329 switch (internal_command)
14330 {
14331 default:
14332 plci->command = 0;
14333 case RTP_CONNECT_B3_REQ_COMMAND_1:
14334 if (plci_nl_busy (plci))
14335 {
14336 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14337 return;
14338 }
14339 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14340 nl_req_ncci (plci, N_CONNECT, 0);
14341 send_req (plci);
14342 return;
14343 case RTP_CONNECT_B3_REQ_COMMAND_2:
14344 if ((Rc != OK) && (Rc != OK_FC))
14345 {
14346 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14347 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14348 Info = _WRONG_STATE;
14349 break;
14350 }
14351 if (plci_nl_busy (plci))
14352 {
14353 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14354 return;
14355 }
14356 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14357 plci->NData[0].PLength = plci->internal_req_buffer[0];
14358 plci->NData[0].P = plci->internal_req_buffer + 1;
14359 plci->NL.X = plci->NData;
14360 plci->NL.ReqCh = 0;
14361 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14362 plci->adapter->request (&plci->NL);
14363 break;
14364 case RTP_CONNECT_B3_REQ_COMMAND_3:
14365 return;
14366 }
14367 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14368}
14369
14370
14371static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14372{
14373 word Info;
14374 word internal_command;
14375
14376 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14377 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14378
14379 Info = GOOD;
14380 internal_command = plci->internal_command;
14381 plci->internal_command = 0;
14382 switch (internal_command)
14383 {
14384 default:
14385 plci->command = 0;
14386 case RTP_CONNECT_B3_RES_COMMAND_1:
14387 if (plci_nl_busy (plci))
14388 {
14389 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14390 return;
14391 }
14392 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14393 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14394 send_req (plci);
14395 return;
14396 case RTP_CONNECT_B3_RES_COMMAND_2:
14397 if ((Rc != OK) && (Rc != OK_FC))
14398 {
14399 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14400 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14401 Info = _WRONG_STATE;
14402 break;
14403 }
14404 if (plci_nl_busy (plci))
14405 {
14406 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14407 return;
14408 }
14409 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14410 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14411 plci->NData[0].PLength = plci->internal_req_buffer[0];
14412 plci->NData[0].P = plci->internal_req_buffer + 1;
14413 plci->NL.X = plci->NData;
14414 plci->NL.ReqCh = 0;
14415 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14416 plci->adapter->request (&plci->NL);
14417 return;
14418 case RTP_CONNECT_B3_RES_COMMAND_3:
14419 return;
14420 }
14421}
14422
14423
14424
14425static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14426{
14427 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14428 word Info;
14429 word internal_command;
14430
14431 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14432 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14433
14434 Info = GOOD;
14435 internal_command = plci->internal_command;
14436 plci->internal_command = 0;
14437 switch (internal_command)
14438 {
14439 default:
14440 if (!plci->NL.Id)
14441 break;
14442 plci->command = 0;
14443 plci->adjust_b_parms_msg = NULL;
14444 plci->adjust_b_facilities = plci->B1_facilities;
14445 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14446 plci->adjust_b_ncci = (word)(Id >> 16);
14447 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14448 plci->adjust_b_state = ADJUST_B_START;
14449 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14450 UnMapId (Id), (char *)(FILE_), __LINE__));
14451 case HOLD_SAVE_COMMAND_1:
14452 Info = adjust_b_process (Id, plci, Rc);
14453 if (Info != GOOD)
14454 {
14455 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14456 UnMapId (Id), (char *)(FILE_), __LINE__));
14457 break;
14458 }
14459 if (plci->internal_command)
14460 return;
14461 }
14462 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14463}
14464
14465
14466static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14467{
14468 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14469 word Info;
14470 word internal_command;
14471
14472 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14473 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14474
14475 Info = GOOD;
14476 internal_command = plci->internal_command;
14477 plci->internal_command = 0;
14478 switch (internal_command)
14479 {
14480 default:
14481 plci->command = 0;
14482 plci->adjust_b_parms_msg = NULL;
14483 plci->adjust_b_facilities = plci->B1_facilities;
14484 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14485 plci->adjust_b_ncci = (word)(Id >> 16);
14486 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14487 plci->adjust_b_state = ADJUST_B_START;
14488 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14489 UnMapId (Id), (char *)(FILE_), __LINE__));
14490 case RETRIEVE_RESTORE_COMMAND_1:
14491 Info = adjust_b_process (Id, plci, Rc);
14492 if (Info != GOOD)
14493 {
14494 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14495 UnMapId (Id), (char *)(FILE_), __LINE__));
14496 break;
14497 }
14498 if (plci->internal_command)
14499 return;
14500 }
14501 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14502}
14503
14504
14505static void init_b1_config (PLCI *plci)
14506{
14507
14508 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14509 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14510 (char *)(FILE_), __LINE__));
14511
14512 plci->B1_resource = 0;
14513 plci->B1_facilities = 0;
14514
14515 plci->li_bchannel_id = 0;
14516 mixer_clear_config (plci);
14517
14518
14519 ec_clear_config (plci);
14520
14521
14522 dtmf_rec_clear_config (plci);
14523 dtmf_send_clear_config (plci);
14524 dtmf_parameter_clear_config (plci);
14525
14526 adv_voice_clear_config (plci);
14527 adjust_b_clear (plci);
14528}
14529
14530
14531static void clear_b1_config (PLCI *plci)
14532{
14533
14534 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14535 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14536 (char *)(FILE_), __LINE__));
14537
14538 adv_voice_clear_config (plci);
14539 adjust_b_clear (plci);
14540
14541 ec_clear_config (plci);
14542
14543
14544 dtmf_rec_clear_config (plci);
14545 dtmf_send_clear_config (plci);
14546 dtmf_parameter_clear_config (plci);
14547
14548
14549 if ((plci->li_bchannel_id != 0)
14550 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14551 {
14552 mixer_clear_config (plci);
14553 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14554 plci->li_bchannel_id = 0;
14555 }
14556
14557 plci->B1_resource = 0;
14558 plci->B1_facilities = 0;
14559}
14560
14561
14562/* -----------------------------------------------------------------
14563 XON protocol local helpers
14564 ----------------------------------------------------------------- */
14565static void channel_flow_control_remove (PLCI * plci) {
14566 DIVA_CAPI_ADAPTER * a = plci->adapter;
14567 word i;
14568 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14569 if (a->ch_flow_plci[i] == plci->Id) {
14570 a->ch_flow_plci[i] = 0;
14571 a->ch_flow_control[i] = 0;
14572 }
14573 }
14574}
14575
14576static void channel_x_on (PLCI * plci, byte ch) {
14577 DIVA_CAPI_ADAPTER * a = plci->adapter;
14578 if (a->ch_flow_control[ch] & N_XON_SENT) {
14579 a->ch_flow_control[ch] &= ~N_XON_SENT;
14580 }
14581}
14582
14583static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14584 DIVA_CAPI_ADAPTER * a = plci->adapter;
14585 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14586 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14587 a->ch_flow_plci[ch] = plci->Id;
14588 a->ch_flow_control_pending++;
14589 }
14590}
14591
14592static void channel_request_xon (PLCI * plci, byte ch) {
14593 DIVA_CAPI_ADAPTER * a = plci->adapter;
14594
14595 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14596 a->ch_flow_control[ch] |= N_XON_REQ;
14597 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14598 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14599 }
14600}
14601
14602static void channel_xmit_extended_xon (PLCI * plci) {
14603 DIVA_CAPI_ADAPTER * a;
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080014604 int max_ch = ARRAY_SIZE(a->ch_flow_control);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014605 int i, one_requested = 0;
14606
14607 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14608 return;
14609 }
14610
14611 for (i = 0; i < max_ch; i++) {
14612 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14613 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14614 (plci->Id == a->ch_flow_plci[i])) {
14615 channel_request_xon (plci, (byte)i);
14616 one_requested = 1;
14617 }
14618 }
14619
14620 if (one_requested) {
14621 channel_xmit_xon (plci);
14622 }
14623}
14624
14625/*
14626 Try to xmit next X_ON
14627 */
14628static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080014629 int max_ch = ARRAY_SIZE(a->ch_flow_control);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014630 int i;
14631
14632 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14633 return (0);
14634 }
14635
14636 if (a->last_flow_control_ch >= max_ch) {
14637 a->last_flow_control_ch = 1;
14638 }
14639 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14640 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14641 (plci->Id == a->ch_flow_plci[i])) {
14642 a->last_flow_control_ch = i+1;
14643 return (i);
14644 }
14645 }
14646
14647 for (i = 1; i < a->last_flow_control_ch; i++) {
14648 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649 (plci->Id == a->ch_flow_plci[i])) {
14650 a->last_flow_control_ch = i+1;
14651 return (i);
14652 }
14653 }
14654
14655 return (0);
14656}
14657
14658static void channel_xmit_xon (PLCI * plci) {
14659 DIVA_CAPI_ADAPTER * a = plci->adapter;
14660 byte ch;
14661
14662 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14663 return;
14664 }
14665 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14666 return;
14667 }
14668 a->ch_flow_control[ch] &= ~N_XON_REQ;
14669 a->ch_flow_control[ch] |= N_XON_SENT;
14670
14671 plci->NL.Req = plci->nl_req = (byte)N_XON;
14672 plci->NL.ReqCh = ch;
14673 plci->NL.X = plci->NData;
14674 plci->NL.XNum = 1;
14675 plci->NData[0].P = &plci->RBuffer[0];
14676 plci->NData[0].PLength = 0;
14677
14678 plci->adapter->request(&plci->NL);
14679}
14680
14681static int channel_can_xon (PLCI * plci, byte ch) {
14682 APPL * APPLptr;
14683 DIVA_CAPI_ADAPTER * a;
14684 word NCCIcode;
14685 dword count;
14686 word Num;
14687 word i;
14688
14689 APPLptr = plci->appl;
14690 a = plci->adapter;
14691
14692 if (!APPLptr)
14693 return (0);
14694
14695 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14696
14697 /* count all buffers within the Application pool */
14698 /* belonging to the same NCCI. XON if a first is */
14699 /* used. */
14700 count = 0;
14701 Num = 0xffff;
14702 for(i=0; i<APPLptr->MaxBuffer; i++) {
14703 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14704 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14705 }
14706 if ((count > 2) || (Num == 0xffff)) {
14707 return (0);
14708 }
14709 return (1);
14710}
14711
14712
14713/*------------------------------------------------------------------*/
14714
14715static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14716{
14717 return 1;
14718}
14719
14720
14721
14722/**********************************************************************************/
14723/* function groups the listening applications according to the CIP mask and the */
14724/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14725/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14726/* big problems on application level (one call, 30 Connect_Ind, ect). The */
14727/* function must be enabled by setting "a->group_optimization_enabled" from the */
14728/* OS specific part (per adapter). */
14729/**********************************************************************************/
14730static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14731{
14732 word i,j,k,busy,group_found;
14733 dword info_mask_group[MAX_CIP_TYPES];
14734 dword cip_mask_group[MAX_CIP_TYPES];
14735 word appl_number_group_type[MAX_APPL];
14736 PLCI *auxplci;
14737
14738 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14739
14740 if(!a->group_optimization_enabled)
14741 {
14742 dbug(1,dprintf("No group optimization"));
14743 return;
14744 }
14745
14746 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14747
14748 for(i=0;i<MAX_CIP_TYPES;i++)
14749 {
14750 info_mask_group[i] = 0;
14751 cip_mask_group [i] = 0;
14752 }
14753 for(i=0;i<MAX_APPL;i++)
14754 {
14755 appl_number_group_type[i] = 0;
14756 }
14757 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14758 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14759 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14760 {
14761 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14762 return; /* allow good application unfiltered access */
14763 }
14764 }
14765 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14766 {
14767 if(application[i].Id && a->CIP_Mask[i] )
14768 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014769 for(k=0,busy=false; k<a->max_plci; k++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014770 {
14771 if(a->plci[k].Id)
14772 {
14773 auxplci = &a->plci[k];
14774 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14775 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014776 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014777 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14778 }
14779 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14780 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014781 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014782 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14783 }
14784 }
14785 }
14786
14787 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14788 {
14789 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14790 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14791 appl_number_group_type[i] = MAX_CIP_TYPES;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014792 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014793 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14794 }
14795 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14796 { /* is group already present ? */
14797 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014798 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014799 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]));
14800 }
14801 else if(!info_mask_group[j])
14802 { /* establish a new group */
14803 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14804 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14805 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014806 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014807 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]));
14808 }
14809 }
14810 }
14811 }
14812
14813 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14814 {
14815 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14816 {
14817 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14818 {
14819 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14820 }
14821 else
14822 {
14823 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14824 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14825 {
14826 if(appl_number_group_type[i] == appl_number_group_type[j])
14827 {
14828 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14829 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14830 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14831 }
14832 }
14833 }
14834 }
14835 else /* application should not get a call */
14836 {
14837 clear_group_ind_mask_bit (plci, i);
14838 }
14839 }
14840
14841}
14842
14843
14844
14845/* OS notifies the driver about a application Capi_Register */
14846word CapiRegister(word id)
14847{
14848 word i,j,appls_found;
14849
14850 PLCI *plci;
14851 DIVA_CAPI_ADAPTER *a;
14852
14853 for(i=0,appls_found=0; i<max_appl; i++)
14854 {
14855 if( application[i].Id && (application[i].Id!=id) )
14856 {
14857 appls_found++; /* an application has been found */
14858 }
14859 }
14860
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014861 if(appls_found) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014862 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14863 {
14864 a = &adapter[i];
14865 if(a->request)
14866 {
14867 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14868 {
14869 if(!appls_found) /* first application does a capi register */
14870 {
14871 if((j=get_plci(a))) /* activate L1 of all adapters */
14872 {
14873 plci = &a->plci[j-1];
14874 plci->command = 0;
14875 add_p(plci,OAD,"\x01\xfd");
14876 add_p(plci,CAI,"\x01\x80");
14877 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14878 add_p(plci,SHIFT|6,NULL);
14879 add_p(plci,SIN,"\x02\x00\x00");
14880 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14881 sig_req(plci,ASSIGN,DSIG_ID);
14882 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14883 sig_req(plci,SIG_CTRL,0);
14884 send_req(plci);
14885 }
14886 }
14887 }
14888 }
14889 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014890 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014891}
14892
14893/*------------------------------------------------------------------*/
14894
14895/* Functions for virtual Switching e.g. Transfer by join, Conference */
14896
14897static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14898{
14899 word i;
14900 /* Format of vswitch_t:
14901 0 byte length
14902 1 byte VSWITCHIE
14903 2 byte VSWITCH_REQ/VSWITCH_IND
14904 3 byte reserved
14905 4 word VSwitchcommand
14906 6 word returnerror
14907 8... Params
14908 */
14909 if(!plci ||
14910 !plci->appl ||
14911 !plci->State ||
14912 plci->Sig.Ind==NCR_FACILITY
14913 )
14914 return;
14915
14916 for(i=0;i<MAX_MULTI_IE;i++)
14917 {
14918 if(!parms[i][0]) continue;
14919 if(parms[i][0]<7)
14920 {
14921 parms[i][0]=0; /* kill it */
14922 continue;
14923 }
14924 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14925 switch(parms[i][4])
14926 {
14927 case VSJOIN:
14928 if(!plci->relatedPTYPLCI ||
14929 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14930 { /* Error */
14931 break;
14932 }
14933 /* remember all necessary informations */
14934 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14935 {
14936 break;
14937 }
14938 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14939 { /* first indication after ECT-Request on Consultation Call */
14940 plci->vswitchstate=parms[i][9];
14941 parms[i][9]=2; /* State */
14942 /* now ask first Call to join */
14943 }
14944 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14945 { /* Answer of VSWITCH_REQ from first Call */
14946 plci->vswitchstate=parms[i][9];
14947 /* tell consultation call to join
14948 and the protocol capabilities of the first call */
14949 }
14950 else
14951 { /* Error */
14952 break;
14953 }
14954 plci->vsprot=parms[i][10]; /* protocol */
14955 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14956 /* send join request to related PLCI */
14957 parms[i][1]=VSWITCHIE;
14958 parms[i][2]=VSWITCH_REQ;
14959
14960 plci->relatedPTYPLCI->command = 0;
14961 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14962 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14963 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14964 send_req(plci->relatedPTYPLCI);
14965 break;
14966 case VSTRANSPORT:
14967 default:
14968 if(plci->relatedPTYPLCI &&
14969 plci->vswitchstate==3 &&
14970 plci->relatedPTYPLCI->vswitchstate==3)
14971 {
14972 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14973 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14974 send_req(plci->relatedPTYPLCI);
14975 }
14976 break;
14977 }
14978 parms[i][0]=0; /* kill it */
14979 }
14980}
14981
14982
14983/*------------------------------------------------------------------*/
14984
14985static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14986 ENTITY e;
14987 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14988
14989 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14990 return (-1);
14991 }
14992
14993 pReq->xdi_dma_descriptor_operation.Req = 0;
14994 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14995
14996 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14997 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14998 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14999 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15000
15001 e.user[0] = plci->adapter->Id - 1;
15002 plci->adapter->request((ENTITY*)pReq);
15003
15004 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15005 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15006 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15007 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15008 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15009 plci->adapter->Id,
15010 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15011 *dma_magic));
15012 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15013 } else {
15014 dbug(1,dprintf("dma_alloc failed"));
15015 return (-1);
15016 }
15017}
15018
15019static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15020 ENTITY e;
15021 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15022
15023 if (nr < 0) {
15024 return;
15025 }
15026
15027 pReq->xdi_dma_descriptor_operation.Req = 0;
15028 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15029
15030 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15031 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15032 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15033 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15034
15035 e.user[0] = plci->adapter->Id - 1;
15036 plci->adapter->request((ENTITY*)pReq);
15037
15038 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15039 dbug(1,dprintf("dma_free(%d)", nr));
15040 } else {
15041 dbug(1,dprintf("dma_free failed (%d)", nr));
15042 }
15043}
15044
15045/*------------------------------------------------------------------*/