blob: 4cc94f200b724a2843333bb29a87c2bc4c5f0934 [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
Hannes Eder4ee59d52008-12-16 01:17:33 -0800595static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596{
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
Hannes Eder4ee59d52008-12-16 01:17:33 -0800634static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
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
Hannes Eder4ee59d52008-12-16 01:17:33 -0800666static void api_load_msg(API_SAVE *in, API_PARSE *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667{
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;
Harvey Harrisondd58c0d2008-04-28 02:14:39 -0700745 while (plci->internal_command_queue[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 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;
Harvey Harrisondd58c0d2008-04-28 02:14:39 -0700761 while (plci->internal_command_queue[1] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 {
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
Hannes Eder4ee59d52008-12-16 01:17:33 -08003417static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3418 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419{
3420 word command;
3421 word i;
3422 word ncci;
3423 API_PARSE * m;
3424 API_PARSE m_parms[5];
3425 word codec;
3426 byte req;
3427 byte ch;
3428 byte dir;
3429 static byte chi[2] = {0x01,0x00};
3430 static byte lli[2] = {0x01,0x00};
3431 static byte codec_cai[2] = {0x01,0x01};
3432 static byte null_msg = {0};
3433 static API_PARSE null_parms = { 0, &null_msg };
3434 PLCI * v_plci;
3435 word Info=0;
3436
3437 dbug(1,dprintf("manufacturer_req"));
3438 for(i=0;i<5;i++) m_parms[i].length = 0;
3439
3440 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441 Info = _WRONG_MESSAGE_FORMAT;
3442 }
3443 command = GET_WORD(parms[1].info);
3444 m = &parms[2];
3445 if (!Info)
3446 {
3447 switch(command) {
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
3451 break;
3452 }
3453 codec = GET_WORD(m_parms[0].info);
3454 ch = m_parms[1].info[0];
3455 dir = m_parms[2].info[0];
3456 if((i=get_plci(a))) {
3457 plci = &a->plci[i-1];
3458 plci->appl = appl;
3459 plci->command = _MANUFACTURER_R;
3460 plci->m_command = command;
3461 plci->number = Number;
3462 plci->State = LOCAL_CONNECT;
3463 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3465
3466 if((ch==1 || ch==2) && (dir<=2)) {
3467 chi[1] = (byte)(0x80|ch);
3468 lli[1] = 0;
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470 switch(codec)
3471 {
3472 case 0:
3473 Info = add_b1(plci,&m_parms[3],0,0);
3474 break;
3475 case 1:
3476 add_p(plci,CAI,codec_cai);
3477 break;
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3480 case 2:
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3483 }
3484 else {
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3487 }
3488 break;
3489 }
3490
3491 plci->State = LOCAL_CONNECT;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003492 plci->manufacturer = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
3496
3497 if(!Info)
3498 {
3499 add_p(plci,LLI,lli);
3500 add_p(plci,CHI,chi);
3501 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502 sig_req(plci,ASSIGN,DSIG_ID);
3503
3504 if(!codec)
3505 {
3506 Info = add_b23(plci,&m_parms[3]);
3507 if(!Info)
3508 {
3509 nl_req_ncci(plci,ASSIGN,0);
3510 send_req(plci);
3511 }
3512 }
3513 if(!Info)
3514 {
3515 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3517 {
3518 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519 plci->spoofed_msg = AWAITING_MANUF_CON;
3520 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521 plci->command = 0;
3522 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003523 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 }
3525 if(dir==1) {
3526 sig_req(plci,CALL_REQ,0);
3527 }
3528 else if(!dir){
3529 sig_req(plci,LISTEN_REQ,0);
3530 }
3531 send_req(plci);
3532 }
3533 else
3534 {
3535 sendf(appl,
3536 _MANUFACTURER_R|CONFIRM,
3537 Id,
3538 Number,
3539 "dww",_DI_MANU_ID,command,Info);
3540 return 2;
3541 }
3542 }
3543 }
3544 }
3545 else Info = _OUT_OF_PLCI;
3546 break;
3547
3548 case _DI_IDI_CTRL:
3549 if(!plci)
3550 {
3551 Info = _WRONG_IDENTIFIER;
3552 break;
3553 }
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3556 break;
3557 }
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
3562 if(req==CALL_REQ)
3563 {
3564 plci->b_channel = getChannel(&m_parms[1]);
3565 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3567 {
3568 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570 plci->command = 0;
3571 break;
3572 }
3573 }
3574 else if(req==LAW_REQ)
3575 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003576 plci->cr_enquiry = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 }
3578 add_ss(plci,FTY,&m_parms[1]);
3579 sig_req(plci,req,0);
3580 send_req(plci);
3581 if(req==HANGUP)
3582 {
3583 if (plci->NL.Id && !plci->nl_remove_id)
3584 {
3585 if (plci->channels)
3586 {
3587 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3588 {
3589 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3590 {
3591 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592 cleanup_ncci_data (plci, ncci);
3593 nl_req_ncci(plci,N_DISC,(byte)ncci);
3594 }
3595 }
3596 }
3597 mixer_remove (plci);
3598 nl_req_ncci(plci,REMOVE,0);
3599 send_req(plci);
3600 }
3601 }
3602 break;
3603
3604 case _DI_SIG_CTRL:
3605 /* signalling control for loop activation B-channel */
3606 if(!plci)
3607 {
3608 Info = _WRONG_IDENTIFIER;
3609 break;
3610 }
3611 if(m->length){
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3614 add_ss(plci,FTY,m);
3615 sig_req(plci,SIG_CTRL,0);
3616 send_req(plci);
3617 }
3618 else Info = _WRONG_MESSAGE_FORMAT;
3619 break;
3620
3621 case _DI_RXT_CTRL:
3622 /* activation control for receiver/transmitter B-channel */
3623 if(!plci)
3624 {
3625 Info = _WRONG_IDENTIFIER;
3626 break;
3627 }
3628 if(m->length){
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3631 add_ss(plci,FTY,m);
3632 sig_req(plci,DSP_CTRL,0);
3633 send_req(plci);
3634 }
3635 else Info = _WRONG_MESSAGE_FORMAT;
3636 break;
3637
3638 case _DI_ADV_CODEC:
3639 case _DI_DSP_CTRL:
3640 /* TEL_CTRL commands to support non standard adjustments: */
3641 /* Ring on/off, Handset micro volume, external micro vol. */
3642 /* handset+external speaker volume, receiver+transm. gain,*/
3643 /* handsfree on (hookinfo off), set mixer command */
3644
3645 if(command == _DI_ADV_CODEC)
3646 {
3647 if(!a->AdvCodecPLCI) {
3648 Info = _WRONG_STATE;
3649 break;
3650 }
3651 v_plci = a->AdvCodecPLCI;
3652 }
3653 else
3654 {
3655 if (plci
3656 && (m->length >= 3)
3657 && (m->info[1] == 0x1c)
3658 && (m->info[2] >= 1))
3659 {
3660 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3661 {
3662 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3663 {
3664 Info = _WRONG_STATE;
3665 break;
3666 }
3667 a->adv_voice_coef_length = m->info[2] - 1;
3668 if (a->adv_voice_coef_length > m->length - 3)
3669 a->adv_voice_coef_length = (byte)(m->length - 3);
3670 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672 for (i = 0; i < a->adv_voice_coef_length; i++)
3673 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674 if (plci->B1_facilities & B1_FACILITY_VOICE)
3675 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676 break;
3677 }
3678 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3679 {
3680 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3681 {
3682 Info = _FACILITY_NOT_SUPPORTED;
3683 break;
3684 }
3685
3686 plci->dtmf_parameter_length = m->info[2] - 1;
3687 if (plci->dtmf_parameter_length > m->length - 3)
3688 plci->dtmf_parameter_length = (byte)(m->length - 3);
3689 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691 for (i = 0; i < plci->dtmf_parameter_length; i++)
3692 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694 dtmf_parameter_write (plci);
3695 break;
3696
3697 }
3698 }
3699 v_plci = plci;
3700 }
3701
3702 if(!v_plci)
3703 {
3704 Info = _WRONG_IDENTIFIER;
3705 break;
3706 }
3707 if(m->length){
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3710 send_req(v_plci);
3711 }
3712 else Info = _WRONG_MESSAGE_FORMAT;
3713
3714 break;
3715
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3719 break;
3720 }
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3722 {
3723 Info = _FACILITY_NOT_SUPPORTED;
3724 break;
3725 }
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727 break;
3728
3729
3730
3731 default:
3732 Info = _WRONG_MESSAGE_FORMAT;
3733 break;
3734 }
3735 }
3736
3737 sendf(appl,
3738 _MANUFACTURER_R|CONFIRM,
3739 Id,
3740 Number,
3741 "dww",_DI_MANU_ID,command,Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003742 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743}
3744
3745
Hannes Eder4ee59d52008-12-16 01:17:33 -08003746static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3747 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748{
3749 word indication;
3750
3751 API_PARSE m_parms[3];
3752 API_PARSE *ncpi;
3753 API_PARSE fax_parms[9];
3754 word i;
3755 byte len;
3756
3757
3758 dbug(1,dprintf("manufacturer_res"));
3759
3760 if ((msg[0].length == 0)
3761 || (msg[1].length == 0)
3762 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3763 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003764 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 }
3766 indication = GET_WORD(msg[1].info);
3767 switch (indication)
3768 {
3769
3770 case _DI_NEGOTIATE_B3:
3771 if(!plci)
3772 break;
3773 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3774 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3775 {
3776 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3777 break;
3778 }
3779 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3780 {
3781 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3782 break;
3783 }
3784 ncpi = &m_parms[1];
3785 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3786 if (plci->fax_connect_info_length < len)
3787 {
3788 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3789 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3790 }
3791 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3792 {
3793 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3794 }
3795 else
3796 {
3797 if (plci->fax_connect_info_length <= len)
3798 plci->fax_connect_info_buffer[len] = 0;
3799 len += 1 + plci->fax_connect_info_buffer[len];
3800 if (plci->fax_connect_info_length <= len)
3801 plci->fax_connect_info_buffer[len] = 0;
3802 len += 1 + plci->fax_connect_info_buffer[len];
3803 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3804 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3805 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3806 for (i = 0; i < fax_parms[7].length; i++)
3807 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3808 }
3809 plci->fax_connect_info_length = len;
3810 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3811 start_internal_command (Id, plci, fax_edata_ack_command);
3812 break;
3813
3814 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003815 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816}
3817
3818/*------------------------------------------------------------------*/
3819/* IDI callback function */
3820/*------------------------------------------------------------------*/
3821
3822void callback(ENTITY * e)
3823{
3824 DIVA_CAPI_ADAPTER * a;
3825 APPL * appl;
3826 PLCI * plci;
3827 CAPI_MSG *m;
3828 word i, j;
3829 byte rc;
3830 byte ch;
3831 byte req;
3832 byte global_req;
3833 int no_cancel_rc;
3834
3835 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3836 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3837
3838 a = &(adapter[(byte)e->user[0]]);
3839 plci = &(a->plci[e->user[1]]);
3840 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3841
3842 /*
3843 If new protocol code and new XDI is used then CAPI should work
3844 fully in accordance with IDI cpec an look on callback field instead
3845 of Rc field for return codes.
3846 */
3847 if (((e->complete == 0xff) && no_cancel_rc) ||
3848 (e->Rc && !no_cancel_rc)) {
3849 rc = e->Rc;
3850 ch = e->RcCh;
3851 req = e->Req;
3852 e->Rc = 0;
3853
3854 if (e->user[0] & 0x8000)
3855 {
3856 /*
3857 If REMOVE request was sent then we have to wait until
3858 return code with Id set to zero arrives.
3859 All other return codes should be ignored.
3860 */
3861 if (req == REMOVE)
3862 {
3863 if (e->Id)
3864 {
3865 dbug(1,dprintf("cancel RC in REMOVE state"));
3866 return;
3867 }
3868 channel_flow_control_remove (plci);
3869 for (i = 0; i < 256; i++)
3870 {
3871 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3872 a->FlowControlIdTable[i] = 0;
3873 }
3874 plci->nl_remove_id = 0;
3875 if (plci->rx_dma_descriptor > 0) {
3876 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3877 plci->rx_dma_descriptor = 0;
3878 }
3879 }
3880 if (rc == OK_FC)
3881 {
3882 a->FlowControlIdTable[ch] = e->Id;
3883 a->FlowControlSkipTable[ch] = 0;
3884
3885 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3886 a->ch_flow_plci[ch] = plci->Id;
3887 plci->nl_req = 0;
3888 }
3889 else
3890 {
3891 /*
3892 Cancel return codes self, if feature was requested
3893 */
3894 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3895 a->FlowControlIdTable[ch] = 0;
3896 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3897 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3898 return;
3899 }
3900 }
3901
3902 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3903 {
3904 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3905 if (ch == e->ReqCh)
3906 plci->nl_req = 0;
3907 }
3908 else
3909 plci->nl_req = 0;
3910 }
3911 if (plci->nl_req)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003912 control_rc (plci, 0, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 else
3914 {
3915 if (req == N_XON)
3916 {
3917 channel_x_on (plci, ch);
3918 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003919 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 }
3921 else
3922 {
3923 if (plci->nl_global_req)
3924 {
3925 global_req = plci->nl_global_req;
3926 plci->nl_global_req = 0;
3927 if (rc != ASSIGN_OK) {
3928 e->Id = 0;
3929 if (plci->rx_dma_descriptor > 0) {
3930 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3931 plci->rx_dma_descriptor = 0;
3932 }
3933 }
3934 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003935 control_rc (plci, 0, rc, ch, global_req, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 }
3937 else if (plci->data_sent)
3938 {
3939 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003940 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 plci->NL.XNum = 1;
3942 data_rc (plci, ch);
3943 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003944 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 }
3946 else
3947 {
3948 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003949 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 }
3951 }
3952 }
3953 }
3954 else
3955 {
3956 /*
3957 If REMOVE request was sent then we have to wait until
3958 return code with Id set to zero arrives.
3959 All other return codes should be ignored.
3960 */
3961 if (req == REMOVE)
3962 {
3963 if (e->Id)
3964 {
3965 dbug(1,dprintf("cancel RC in REMOVE state"));
3966 return;
3967 }
3968 plci->sig_remove_id = 0;
3969 }
3970 plci->sig_req = 0;
3971 if (plci->sig_global_req)
3972 {
3973 global_req = plci->sig_global_req;
3974 plci->sig_global_req = 0;
3975 if (rc != ASSIGN_OK)
3976 e->Id = 0;
3977 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003978 control_rc (plci, 0, rc, ch, global_req, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 }
3980 else
3981 {
3982 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003983 control_rc (plci, req, rc, ch, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 }
3985 }
3986 /*
3987 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3988 same callback. Also if new XDI and protocol code used then jump
3989 direct to finish.
3990 */
3991 if (no_cancel_rc) {
3992 channel_xmit_xon(plci);
3993 goto capi_callback_suffix;
3994 }
3995 }
3996
3997 channel_xmit_xon(plci);
3998
3999 if (e->Ind) {
4000 if (e->user[0] &0x8000) {
4001 byte Ind = e->Ind & 0x0f;
4002 byte Ch = e->IndCh;
4003 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4004 (a->ch_flow_plci[Ch] == plci->Id)) {
4005 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4006 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4007 }
4008 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4009 }
4010 nl_ind(plci);
4011 if ((e->RNR != 1) &&
4012 (a->ch_flow_plci[Ch] == plci->Id) &&
4013 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4014 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4015 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4016 }
4017 } else {
4018 sig_ind(plci);
4019 }
4020 e->Ind = 0;
4021 }
4022
4023capi_callback_suffix:
4024
4025 while (!plci->req_in
4026 && !plci->internal_command
4027 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4028 {
4029 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4030
4031 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4032
4033 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4034 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4035 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4036 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4037 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4038 {
4039 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4040 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4041 }
4042 else
4043 {
4044 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4045 }
4046 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4047 {
4048 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4049 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4050 }
4051 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4052 {
4053 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4054 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4055 }
4056 i = api_put (appl, m);
4057 if (i != 0)
4058 {
4059 if (m->header.command == _DATA_B3_R)
4060
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07004061 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062
4063 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4064 break;
4065 }
4066
4067 if (plci->li_notify_update)
4068 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004069 plci->li_notify_update = false;
4070 mixer_notify_update (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 }
4072
4073 }
4074 send_data(plci);
4075 send_req(plci);
4076}
4077
4078
Hannes Eder4ee59d52008-12-16 01:17:33 -08004079static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4080 byte nl_rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081{
4082 dword Id;
4083 dword rId;
4084 word Number;
4085 word Info=0;
4086 word i;
4087 word ncci;
4088 DIVA_CAPI_ADAPTER * a;
4089 APPL * appl;
4090 PLCI * rplci;
4091 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4092 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4093
4094 if (!plci) {
4095 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4096 return;
4097 }
4098 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4099 if(plci->req_in!=plci->req_out)
4100 {
4101 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4102 {
4103 dbug(1,dprintf("req_1return"));
4104 return;
4105 }
4106 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4107 }
4108 plci->req_in = plci->req_in_start = plci->req_out = 0;
4109 dbug(1,dprintf("control_rc"));
4110
4111 appl = plci->appl;
4112 a = plci->adapter;
4113 ncci = a->ch_ncci[ch];
4114 if(appl)
4115 {
4116 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4117 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4118 Number = plci->number;
4119 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));
4120 dbug(1,dprintf("channels=0x%x",plci->channels));
4121 if (plci_remove_check(plci))
4122 return;
4123 if(req==REMOVE && rc==ASSIGN_OK)
4124 {
4125 sig_req(plci,HANGUP,0);
4126 sig_req(plci,REMOVE,0);
4127 send_req(plci);
4128 }
4129 if(plci->command)
4130 {
4131 switch(plci->command)
4132 {
4133 case C_HOLD_REQ:
4134 dbug(1,dprintf("HoldRC=0x%x",rc));
4135 SSparms[1] = (byte)S_HOLD;
4136 if(rc!=OK)
4137 {
4138 plci->SuppState = IDLE;
4139 Info = 0x2001;
4140 }
4141 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4142 break;
4143
4144 case C_RETRIEVE_REQ:
4145 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4146 SSparms[1] = (byte)S_RETRIEVE;
4147 if(rc!=OK)
4148 {
4149 plci->SuppState = CALL_HELD;
4150 Info = 0x2001;
4151 }
4152 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4153 break;
4154
4155 case _INFO_R:
4156 dbug(1,dprintf("InfoRC=0x%x",rc));
4157 if(rc!=OK) Info=_WRONG_STATE;
4158 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4159 break;
4160
4161 case _CONNECT_R:
4162 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4163 if (plci->State == INC_DIS_PENDING)
4164 break;
4165 if(plci->Sig.Id!=0xff)
4166 {
4167 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4168 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4169 {
4170 dbug(1,dprintf("No more IDs/Call_Req failed"));
4171 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4172 plci_remove(plci);
4173 plci->State = IDLE;
4174 break;
4175 }
4176 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4177 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4178 }
4179 else /* D-ch activation */
4180 {
4181 if (rc != ASSIGN_OK)
4182 {
4183 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4184 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4185 plci_remove(plci);
4186 plci->State = IDLE;
4187 break;
4188 }
4189 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4190 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4191 plci->State = INC_ACT_PENDING;
4192 }
4193 break;
4194
4195 case _CONNECT_I|RESPONSE:
4196 if (plci->State != INC_DIS_PENDING)
4197 plci->State = INC_CON_ACCEPT;
4198 break;
4199
4200 case _DISCONNECT_R:
4201 if (plci->State == INC_DIS_PENDING)
4202 break;
4203 if(plci->Sig.Id!=0xff)
4204 {
4205 plci->State = OUTG_DIS_PENDING;
4206 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4207 }
4208 break;
4209
4210 case SUSPEND_REQ:
4211 break;
4212
4213 case RESUME_REQ:
4214 break;
4215
4216 case _CONNECT_B3_R:
4217 if(rc!=OK)
4218 {
4219 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4220 break;
4221 }
4222 ncci = get_ncci (plci, ch, 0);
4223 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4224 plci->channels++;
4225 if(req==N_RESET)
4226 {
4227 a->ncci_state[ncci] = INC_ACT_PENDING;
4228 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4229 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4230 }
4231 else
4232 {
4233 a->ncci_state[ncci] = OUTG_CON_PENDING;
4234 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4235 }
4236 break;
4237
4238 case _CONNECT_B3_I|RESPONSE:
4239 break;
4240
4241 case _RESET_B3_R:
4242/* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4243 break;
4244
4245 case _DISCONNECT_B3_R:
4246 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4247 break;
4248
4249 case _MANUFACTURER_R:
4250 break;
4251
4252 case PERM_LIST_REQ:
4253 if(rc!=OK)
4254 {
4255 Info = _WRONG_IDENTIFIER;
4256 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4257 plci_remove(plci);
4258 }
4259 else
4260 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4261 break;
4262
4263 default:
4264 break;
4265 }
4266 plci->command = 0;
4267 }
4268 else if (plci->internal_command)
4269 {
4270 switch(plci->internal_command)
4271 {
4272 case BLOCK_PLCI:
4273 return;
4274
4275 case GET_MWI_STATE:
4276 if(rc==OK) /* command supported, wait for indication */
4277 {
4278 return;
4279 }
4280 plci_remove(plci);
4281 break;
4282
4283 /* Get Supported Services */
4284 case GETSERV_REQ_PEND:
4285 if(rc==OK) /* command supported, wait for indication */
4286 {
4287 break;
4288 }
4289 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4290 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4291 plci_remove(plci);
4292 break;
4293
4294 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4295 case INTERR_NUMBERS_REQ_PEND:
4296 case CF_START_PEND: /* Call Forwarding Start pending */
4297 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4298 case CCBS_REQUEST_REQ_PEND:
4299 case CCBS_DEACTIVATE_REQ_PEND:
4300 case CCBS_INTERROGATE_REQ_PEND:
4301 switch(plci->internal_command)
4302 {
4303 case INTERR_DIVERSION_REQ_PEND:
4304 SSparms[1] = S_INTERROGATE_DIVERSION;
4305 break;
4306 case INTERR_NUMBERS_REQ_PEND:
4307 SSparms[1] = S_INTERROGATE_NUMBERS;
4308 break;
4309 case CF_START_PEND:
4310 SSparms[1] = S_CALL_FORWARDING_START;
4311 break;
4312 case CF_STOP_PEND:
4313 SSparms[1] = S_CALL_FORWARDING_STOP;
4314 break;
4315 case CCBS_REQUEST_REQ_PEND:
4316 SSparms[1] = S_CCBS_REQUEST;
4317 break;
4318 case CCBS_DEACTIVATE_REQ_PEND:
4319 SSparms[1] = S_CCBS_DEACTIVATE;
4320 break;
4321 case CCBS_INTERROGATE_REQ_PEND:
4322 SSparms[1] = S_CCBS_INTERROGATE;
4323 break;
4324 }
4325 if(global_req==ASSIGN)
4326 {
4327 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4328 return;
4329 }
4330 if(!plci->appl) break;
4331 if(rc==ISDN_GUARD_REJ)
4332 {
4333 Info = _CAPI_GUARD_ERROR;
4334 }
4335 else if(rc!=OK)
4336 {
4337 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4338 }
4339 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4340 plci->number,"wws",Info,(word)3,SSparms);
4341 if(Info) plci_remove(plci);
4342 break;
4343
4344 /* 3pty conference pending */
4345 case PTY_REQ_PEND:
4346 if(!plci->relatedPTYPLCI) break;
4347 rplci = plci->relatedPTYPLCI;
4348 SSparms[1] = plci->ptyState;
4349 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4350 if(rplci->tel) rId|=EXT_CONTROLLER;
4351 if(rc!=OK)
4352 {
4353 Info = 0x300E; /* not supported */
4354 plci->relatedPTYPLCI = NULL;
4355 plci->ptyState = 0;
4356 }
4357 sendf(rplci->appl,
4358 _FACILITY_R|CONFIRM,
4359 rId,
4360 plci->number,
4361 "wws",Info,(word)3,SSparms);
4362 break;
4363
4364 /* Explicit Call Transfer pending */
4365 case ECT_REQ_PEND:
4366 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4367 if(!plci->relatedPTYPLCI) break;
4368 rplci = plci->relatedPTYPLCI;
4369 SSparms[1] = S_ECT;
4370 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4371 if(rplci->tel) rId|=EXT_CONTROLLER;
4372 if(rc!=OK)
4373 {
4374 Info = 0x300E; /* not supported */
4375 plci->relatedPTYPLCI = NULL;
4376 plci->ptyState = 0;
4377 }
4378 sendf(rplci->appl,
4379 _FACILITY_R|CONFIRM,
4380 rId,
4381 plci->number,
4382 "wws",Info,(word)3,SSparms);
4383 break;
4384
4385 case _MANUFACTURER_R:
4386 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4387 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4388 {
4389 dbug(1,dprintf("No more IDs"));
4390 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4391 plci_remove(plci); /* after codec init, internal codec commands pending */
4392 }
4393 break;
4394
4395 case _CONNECT_R:
4396 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4397 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4398 {
4399 dbug(1,dprintf("No more IDs"));
4400 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4401 plci_remove(plci); /* after codec init, internal codec commands pending */
4402 }
4403 break;
4404
4405 case PERM_COD_HOOK: /* finished with Hook_Ind */
4406 return;
4407
4408 case PERM_COD_CALL:
4409 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4410 plci->internal_command = PERM_COD_CONN_PEND;
4411 return;
4412
4413 case PERM_COD_ASSIGN:
4414 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4415 if(rc!=ASSIGN_OK) break;
4416 sig_req(plci,CALL_REQ,0);
4417 send_req(plci);
4418 plci->internal_command = PERM_COD_CALL;
4419 return;
4420
4421 /* Null Call Reference Request pending */
4422 case C_NCR_FAC_REQ:
4423 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4424 if(global_req==ASSIGN)
4425 {
4426 if(rc==ASSIGN_OK)
4427 {
4428 return;
4429 }
4430 else
4431 {
4432 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004433 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 plci_remove(plci);
4435 }
4436 }
4437 else if(req==NCR_FACILITY)
4438 {
4439 if(rc==OK)
4440 {
4441 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4442 }
4443 else
4444 {
4445 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004446 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447 }
4448 plci_remove(plci);
4449 }
4450 break;
4451
4452 case HOOK_ON_REQ:
4453 if(plci->channels)
4454 {
4455 if(a->ncci_state[ncci]==CONNECTED)
4456 {
4457 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4458 cleanup_ncci_data (plci, ncci);
4459 nl_req_ncci(plci,N_DISC,(byte)ncci);
4460 }
4461 break;
4462 }
4463 break;
4464
4465 case HOOK_OFF_REQ:
4466 if (plci->State == INC_DIS_PENDING)
4467 break;
4468 sig_req(plci,CALL_REQ,0);
4469 send_req(plci);
4470 plci->State=OUTG_CON_PENDING;
4471 break;
4472
4473
4474 case MWI_ACTIVATE_REQ_PEND:
4475 case MWI_DEACTIVATE_REQ_PEND:
4476 if(global_req == ASSIGN && rc==ASSIGN_OK)
4477 {
4478 dbug(1,dprintf("MWI_REQ assigned"));
4479 return;
4480 }
4481 else if(rc!=OK)
4482 {
4483 if(rc==WRONG_IE)
4484 {
4485 Info = 0x2007; /* Illegal message parameter coding */
4486 dbug(1,dprintf("MWI_REQ invalid parameter"));
4487 }
4488 else
4489 {
4490 Info = 0x300B; /* not supported */
4491 dbug(1,dprintf("MWI_REQ not supported"));
4492 }
4493 /* 0x3010: Request not allowed in this state */
4494 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4495
4496 }
4497 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4498 {
4499 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4500 }
4501 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4502
4503 if(plci->cr_enquiry)
4504 {
4505 sendf(plci->appl,
4506 _FACILITY_R|CONFIRM,
4507 Id&0xf,
4508 plci->number,
4509 "wws",Info,(word)3,SSparms);
4510 if(rc!=OK) plci_remove(plci);
4511 }
4512 else
4513 {
4514 sendf(plci->appl,
4515 _FACILITY_R|CONFIRM,
4516 Id,
4517 plci->number,
4518 "wws",Info,(word)3,SSparms);
4519 }
4520 break;
4521
4522 case CONF_BEGIN_REQ_PEND:
4523 case CONF_ADD_REQ_PEND:
4524 case CONF_SPLIT_REQ_PEND:
4525 case CONF_DROP_REQ_PEND:
4526 case CONF_ISOLATE_REQ_PEND:
4527 case CONF_REATTACH_REQ_PEND:
4528 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4529 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4530 rplci = plci;
4531 rId = Id;
4532 switch(plci->internal_command)
4533 {
4534 case CONF_BEGIN_REQ_PEND:
4535 SSparms[1] = S_CONF_BEGIN;
4536 break;
4537 case CONF_ADD_REQ_PEND:
4538 SSparms[1] = S_CONF_ADD;
4539 rplci = plci->relatedPTYPLCI;
4540 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4541 break;
4542 case CONF_SPLIT_REQ_PEND:
4543 SSparms[1] = S_CONF_SPLIT;
4544 break;
4545 case CONF_DROP_REQ_PEND:
4546 SSparms[1] = S_CONF_DROP;
4547 break;
4548 case CONF_ISOLATE_REQ_PEND:
4549 SSparms[1] = S_CONF_ISOLATE;
4550 break;
4551 case CONF_REATTACH_REQ_PEND:
4552 SSparms[1] = S_CONF_REATTACH;
4553 break;
4554 }
4555
4556 if(rc!=OK)
4557 {
4558 Info = 0x300E; /* not supported */
4559 plci->relatedPTYPLCI = NULL;
4560 plci->ptyState = 0;
4561 }
4562 sendf(rplci->appl,
4563 _FACILITY_R|CONFIRM,
4564 rId,
4565 plci->number,
4566 "wws",Info,(word)3,SSparms);
4567 break;
4568
4569 case VSWITCH_REQ_PEND:
4570 if(rc!=OK)
4571 {
4572 if(plci->relatedPTYPLCI)
4573 {
4574 plci->relatedPTYPLCI->vswitchstate=0;
4575 plci->relatedPTYPLCI->vsprot=0;
4576 plci->relatedPTYPLCI->vsprotdialect=0;
4577 }
4578 plci->vswitchstate=0;
4579 plci->vsprot=0;
4580 plci->vsprotdialect=0;
4581 }
4582 else
4583 {
4584 if(plci->relatedPTYPLCI &&
4585 plci->vswitchstate==1 &&
4586 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4587 plci->vswitchstate=3;
4588 }
4589 break;
4590
4591 /* Call Deflection Request pending (SSCT) */
4592 case CD_REQ_PEND:
4593 SSparms[1] = S_CALL_DEFLECTION;
4594 if(rc!=OK)
4595 {
4596 Info = 0x300E; /* not supported */
4597 plci->appl->CDEnable = 0;
4598 }
4599 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4600 plci->number,"wws",Info,(word)3,SSparms);
4601 break;
4602
4603 case RTP_CONNECT_B3_REQ_COMMAND_2:
4604 if (rc == OK)
4605 {
4606 ncci = get_ncci (plci, ch, 0);
4607 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4608 plci->channels++;
4609 a->ncci_state[ncci] = OUTG_CON_PENDING;
4610 }
4611
4612 default:
4613 if (plci->internal_command_queue[0])
4614 {
4615 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4616 if (plci->internal_command)
4617 return;
4618 }
4619 break;
4620 }
4621 next_internal_command (Id, plci);
4622 }
4623 }
4624 else /* appl==0 */
4625 {
4626 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4627 if(plci->tel) Id|=EXT_CONTROLLER;
4628
4629 switch(plci->internal_command)
4630 {
4631 case BLOCK_PLCI:
4632 return;
4633
4634 case START_L1_SIG_ASSIGN_PEND:
4635 case REM_L1_SIG_ASSIGN_PEND:
4636 if(global_req == ASSIGN)
4637 {
4638 break;
4639 }
4640 else
4641 {
4642 dbug(1,dprintf("***L1 Req rem PLCI"));
4643 plci->internal_command = 0;
4644 sig_req(plci,REMOVE,0);
4645 send_req(plci);
4646 }
4647 break;
4648
4649 /* Call Deflection Request pending, just no appl ptr assigned */
4650 case CD_REQ_PEND:
4651 SSparms[1] = S_CALL_DEFLECTION;
4652 if(rc!=OK)
4653 {
4654 Info = 0x300E; /* not supported */
4655 }
4656 for(i=0; i<max_appl; i++)
4657 {
4658 if(application[i].CDEnable)
4659 {
4660 if(!application[i].Id) application[i].CDEnable = 0;
4661 else
4662 {
4663 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4664 plci->number,"wws",Info,(word)3,SSparms);
4665 if(Info) application[i].CDEnable = 0;
4666 }
4667 }
4668 }
4669 plci->internal_command = 0;
4670 break;
4671
4672 case PERM_COD_HOOK: /* finished with Hook_Ind */
4673 return;
4674
4675 case PERM_COD_CALL:
4676 plci->internal_command = PERM_COD_CONN_PEND;
4677 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4678 return;
4679
4680 case PERM_COD_ASSIGN:
4681 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4682 plci->internal_command = 0;
4683 if(rc!=ASSIGN_OK) break;
4684 plci->internal_command = PERM_COD_CALL;
4685 sig_req(plci,CALL_REQ,0);
4686 send_req(plci);
4687 return;
4688
4689 case LISTEN_SIG_ASSIGN_PEND:
4690 if(rc == ASSIGN_OK)
4691 {
4692 plci->internal_command = 0;
4693 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4694 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4695 sig_req(plci,INDICATE_REQ,0);
4696 send_req(plci);
4697 }
4698 else
4699 {
4700 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4701 a->listen_active--;
4702 plci_remove(plci);
4703 plci->State = IDLE;
4704 }
4705 break;
4706
4707 case USELAW_REQ:
4708 if(global_req == ASSIGN)
4709 {
4710 if (rc==ASSIGN_OK)
4711 {
4712 sig_req(plci,LAW_REQ,0);
4713 send_req(plci);
4714 dbug(1,dprintf("Auto-Law assigned"));
4715 }
4716 else
4717 {
4718 dbug(1,dprintf("Auto-Law assign failed"));
4719 a->automatic_law = 3;
4720 plci->internal_command = 0;
4721 a->automatic_lawPLCI = NULL;
4722 }
4723 break;
4724 }
4725 else if(req == LAW_REQ && rc==OK)
4726 {
4727 dbug(1,dprintf("Auto-Law initiated"));
4728 a->automatic_law = 2;
4729 plci->internal_command = 0;
4730 }
4731 else
4732 {
4733 dbug(1,dprintf("Auto-Law not supported"));
4734 a->automatic_law = 3;
4735 plci->internal_command = 0;
4736 sig_req(plci,REMOVE,0);
4737 send_req(plci);
4738 a->automatic_lawPLCI = NULL;
4739 }
4740 break;
4741 }
4742 plci_remove_check(plci);
4743 }
4744}
4745
Hannes Eder4ee59d52008-12-16 01:17:33 -08004746static void data_rc(PLCI *plci, byte ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747{
4748 dword Id;
4749 DIVA_CAPI_ADAPTER * a;
4750 NCCI *ncci_ptr;
4751 DATA_B3_DESC *data;
4752 word ncci;
4753
4754 if (plci->appl)
4755 {
4756 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4757 a = plci->adapter;
4758 ncci = a->ch_ncci[ch];
4759 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4760 {
4761 ncci_ptr = &(a->ncci[ncci]);
4762 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4763 if (ncci_ptr->data_pending)
4764 {
4765 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4766 if (!(data->Flags &4) && a->ncci_state[ncci])
4767 {
4768 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4769 if(plci->tel) Id|=EXT_CONTROLLER;
4770 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4771 "ww",data->Handle,0);
4772 }
4773 (ncci_ptr->data_out)++;
4774 if (ncci_ptr->data_out == MAX_DATA_B3)
4775 ncci_ptr->data_out = 0;
4776 (ncci_ptr->data_pending)--;
4777 }
4778 }
4779 }
4780}
4781
Hannes Eder4ee59d52008-12-16 01:17:33 -08004782static void data_ack(PLCI *plci, byte ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783{
4784 dword Id;
4785 DIVA_CAPI_ADAPTER * a;
4786 NCCI *ncci_ptr;
4787 word ncci;
4788
4789 a = plci->adapter;
4790 ncci = a->ch_ncci[ch];
4791 ncci_ptr = &(a->ncci[ncci]);
4792 if (ncci_ptr->data_ack_pending)
4793 {
4794 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4795 {
4796 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4797 if(plci->tel) Id|=EXT_CONTROLLER;
4798 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4799 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4800 }
4801 (ncci_ptr->data_ack_out)++;
4802 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4803 ncci_ptr->data_ack_out = 0;
4804 (ncci_ptr->data_ack_pending)--;
4805 }
4806}
4807
Hannes Eder4ee59d52008-12-16 01:17:33 -08004808static void sig_ind(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809{
4810 dword x_Id;
4811 dword Id;
4812 dword rId;
4813 word Number = 0;
4814 word i;
4815 word cip;
4816 dword cip_mask;
4817 byte *ie;
4818 DIVA_CAPI_ADAPTER * a;
4819 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4820#define MAXPARMSIDS 31
4821 byte * parms[MAXPARMSIDS];
4822 byte * add_i[4];
4823 byte * multi_fac_parms[MAX_MULTI_IE];
4824 byte * multi_pi_parms [MAX_MULTI_IE];
4825 byte * multi_ssext_parms [MAX_MULTI_IE];
4826 byte * multi_CiPN_parms [MAX_MULTI_IE];
4827
4828 byte * multi_vswitch_parms [MAX_MULTI_IE];
4829
4830 byte ai_len;
4831 byte *esc_chi = "";
4832 byte *esc_law = "";
4833 byte *pty_cai = "";
4834 byte *esc_cr = "";
4835 byte *esc_profile = "";
4836
4837 byte facility[256];
4838 PLCI * tplci = NULL;
4839 byte chi[] = "\x02\x18\x01";
4840 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4841 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4842 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4843 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4844 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4845 /* (see Info_Mask Bit 4, first IE. then the message type) */
4846 word parms_id[] =
4847 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4848 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4849 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4850 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4851 /* 14 FTY repl by ESC_CHI */
4852 /* 18 PI repl by ESC_LAW */
4853 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4854 word multi_fac_id[] = {1, FTY};
4855 word multi_pi_id[] = {1, PI};
4856 word multi_CiPN_id[] = {1, OAD};
4857 word multi_ssext_id[] = {1, ESC_SSEXT};
4858
4859 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4860
4861 byte * cau;
4862 word ncci;
4863 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4864 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4865 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4866 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004867 byte force_mt_info = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868 byte dir;
4869 dword d;
4870 word w;
4871
4872 a = plci->adapter;
4873 Id = ((word)plci->Id<<8)|a->Id;
4874 PUT_WORD(&SS_Ind[4],0x0000);
4875
4876 if (plci->sig_remove_id)
4877 {
4878 plci->Sig.RNR = 2; /* discard */
4879 dbug(1,dprintf("SIG discard while remove pending"));
4880 return;
4881 }
4882 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4883 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4884 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4885 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4886 {
4887 plci->Sig.RNR = 1;
4888 return;
4889 }
4890 if(plci->Sig.Ind==HANGUP && plci->channels)
4891 {
4892 plci->Sig.RNR = 1;
4893 plci->hangup_flow_ctrl_timer++;
4894 /* recover the network layer after timeout */
4895 if(plci->hangup_flow_ctrl_timer==100)
4896 {
4897 dbug(1,dprintf("Exceptional disc"));
4898 plci->Sig.RNR = 0;
4899 plci->hangup_flow_ctrl_timer = 0;
4900 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4901 {
4902 if (a->ncci_plci[ncci] == plci->Id)
4903 {
4904 cleanup_ncci_data (plci, ncci);
4905 if(plci->channels)plci->channels--;
4906 if (plci->appl)
4907 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4908 }
4909 }
4910 if (plci->appl)
4911 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4912 plci_remove(plci);
4913 plci->State=IDLE;
4914 }
4915 return;
4916 }
4917
4918 /* do first parse the info with no OAD in, because OAD will be converted */
4919 /* first the multiple facility IE, then mult. progress ind. */
4920 /* then the parameters for the info_ind + conn_ind */
4921 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4922 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4923 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4924
4925 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4926
4927 IndParse(plci,parms_id,parms,0);
4928 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4929 esc_chi = parms[14];
4930 esc_law = parms[18];
4931 pty_cai = parms[24];
4932 esc_cr = parms[25];
4933 esc_profile = parms[27];
4934 if(esc_cr[0] && plci)
4935 {
4936 if(plci->cr_enquiry && plci->appl)
4937 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004938 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 /* d = MANU_ID */
4940 /* w = m_command */
4941 /* b = total length */
4942 /* b = indication type */
4943 /* b = length of all IEs */
4944 /* b = IE1 */
4945 /* S = IE1 length + cont. */
4946 /* b = IE2 */
Paulius Zaleckasefad798b2008-02-03 15:42:53 +02004947 /* S = IE2 length + cont. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948 sendf(plci->appl,
4949 _MANUFACTURER_I,
4950 Id,
4951 0,
4952 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4953 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);
4954 }
4955 }
4956 /* create the additional info structure */
4957 add_i[1] = parms[15]; /* KEY of additional info */
4958 add_i[2] = parms[11]; /* UUI of additional info */
4959 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4960
4961 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4962 /* indication returns by the card if requested by the function */
4963 /* AutomaticLaw() after driver init */
4964 if (a->automatic_law<4)
4965 {
4966 if(esc_law[0]){
4967 if(esc_law[2]){
4968 dbug(0,dprintf("u-Law selected"));
4969 a->u_law = 1;
4970 }
4971 else {
4972 dbug(0,dprintf("a-Law selected"));
4973 a->u_law = 0;
4974 }
4975 a->automatic_law = 4;
4976 if(plci==a->automatic_lawPLCI) {
4977 plci->internal_command = 0;
4978 sig_req(plci,REMOVE,0);
4979 send_req(plci);
4980 a->automatic_lawPLCI = NULL;
4981 }
4982 }
4983 if (esc_profile[0])
4984 {
4985 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4986 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4987 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4988 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4989
4990 a->profile.Global_Options &= 0x000000ffL;
4991 a->profile.B1_Protocols &= 0x000003ffL;
4992 a->profile.B2_Protocols &= 0x00001fdfL;
4993 a->profile.B3_Protocols &= 0x000000b7L;
4994
4995 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4996 GL_BCHANNEL_OPERATION_SUPPORTED;
4997 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4998 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4999 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5000 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5001 a->man_profile.private_options = 0;
5002
5003 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5004 {
5005 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5006 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5007 }
5008
5009
5010 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5011 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5012 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5013 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5014
5015
5016 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5017 a->man_profile.private_options |= 1L << PRIVATE_T38;
5018
5019
5020 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5021 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5022
5023
5024 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5025 a->man_profile.private_options |= 1L << PRIVATE_V18;
5026
5027
5028 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5029 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5030
5031
5032 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5033 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5034
5035
5036 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5037 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5038
5039
5040 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5041 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5042
5043
5044 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5045 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5046
5047 }
5048 else
5049 {
5050 a->profile.Global_Options &= 0x0000007fL;
5051 a->profile.B1_Protocols &= 0x000003dfL;
5052 a->profile.B2_Protocols &= 0x00001adfL;
5053 a->profile.B3_Protocols &= 0x000000b7L;
5054 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5055 }
5056 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5057 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5058 {
5059 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5060 }
5061 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5062 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5063 UnMapController (a->Id), a->profile.Global_Options,
5064 a->profile.B1_Protocols, a->profile.B2_Protocols,
5065 a->profile.B3_Protocols, a->manufacturer_features));
5066 }
5067 /* codec plci for the handset/hook state support is just an internal id */
5068 if(plci!=a->AdvCodecPLCI)
5069 {
5070 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5071 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5072 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5073 SendInfo(plci,Id, parms, force_mt_info);
5074
5075 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5076
5077 }
5078
5079 /* switch the codec to the b-channel */
5080 if(esc_chi[0] && plci && !plci->SuppState){
5081 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5082 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5083 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5084 if(plci->tel==ADV_VOICE && plci->appl) {
5085 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5086 }
5087 }
5088
5089 if(plci->appl) Number = plci->appl->Number++;
5090
5091 switch(plci->Sig.Ind) {
5092 /* Response to Get_Supported_Services request */
5093 case S_SUPPORTED:
5094 dbug(1,dprintf("S_Supported"));
5095 if(!plci->appl) break;
5096 if(pty_cai[0]==4)
5097 {
5098 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5099 }
5100 else
5101 {
5102 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5103 }
5104 PUT_WORD (&CF_Ind[1], 0);
5105 PUT_WORD (&CF_Ind[4], 0);
5106 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5107 plci_remove(plci);
5108 break;
5109
5110 /* Supplementary Service rejected */
5111 case S_SERVICE_REJ:
5112 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5113 if(!pty_cai[0]) break;
5114 switch (pty_cai[5])
5115 {
5116 case ECT_EXECUTE:
5117 case THREE_PTY_END:
5118 case THREE_PTY_BEGIN:
5119 if(!plci->relatedPTYPLCI) break;
5120 tplci = plci->relatedPTYPLCI;
5121 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5122 if(tplci->tel) rId|=EXT_CONTROLLER;
5123 if(pty_cai[5]==ECT_EXECUTE)
5124 {
5125 PUT_WORD(&SS_Ind[1],S_ECT);
5126
5127 plci->vswitchstate=0;
5128 plci->relatedPTYPLCI->vswitchstate=0;
5129
5130 }
5131 else
5132 {
5133 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5134 }
5135 if(pty_cai[2]!=0xff)
5136 {
5137 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5138 }
5139 else
5140 {
5141 PUT_WORD(&SS_Ind[4],0x300E);
5142 }
5143 plci->relatedPTYPLCI = NULL;
5144 plci->ptyState = 0;
5145 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5146 break;
5147
5148 case CALL_DEFLECTION:
5149 if(pty_cai[2]!=0xff)
5150 {
5151 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5152 }
5153 else
5154 {
5155 PUT_WORD(&SS_Ind[4],0x300E);
5156 }
5157 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5158 for(i=0; i<max_appl; i++)
5159 {
5160 if(application[i].CDEnable)
5161 {
5162 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005163 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164 }
5165 }
5166 break;
5167
5168 case DEACTIVATION_DIVERSION:
5169 case ACTIVATION_DIVERSION:
5170 case DIVERSION_INTERROGATE_CFU:
5171 case DIVERSION_INTERROGATE_CFB:
5172 case DIVERSION_INTERROGATE_CFNR:
5173 case DIVERSION_INTERROGATE_NUM:
5174 case CCBS_REQUEST:
5175 case CCBS_DEACTIVATE:
5176 case CCBS_INTERROGATE:
5177 if(!plci->appl) break;
5178 if(pty_cai[2]!=0xff)
5179 {
5180 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5181 }
5182 else
5183 {
5184 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5185 }
5186 switch (pty_cai[5])
5187 {
5188 case DEACTIVATION_DIVERSION:
5189 dbug(1,dprintf("Deact_Div"));
5190 Interr_Err_Ind[0]=0x9;
5191 Interr_Err_Ind[3]=0x6;
5192 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5193 break;
5194 case ACTIVATION_DIVERSION:
5195 dbug(1,dprintf("Act_Div"));
5196 Interr_Err_Ind[0]=0x9;
5197 Interr_Err_Ind[3]=0x6;
5198 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5199 break;
5200 case DIVERSION_INTERROGATE_CFU:
5201 case DIVERSION_INTERROGATE_CFB:
5202 case DIVERSION_INTERROGATE_CFNR:
5203 dbug(1,dprintf("Interr_Div"));
5204 Interr_Err_Ind[0]=0xa;
5205 Interr_Err_Ind[3]=0x7;
5206 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5207 break;
5208 case DIVERSION_INTERROGATE_NUM:
5209 dbug(1,dprintf("Interr_Num"));
5210 Interr_Err_Ind[0]=0xa;
5211 Interr_Err_Ind[3]=0x7;
5212 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5213 break;
5214 case CCBS_REQUEST:
5215 dbug(1,dprintf("CCBS Request"));
5216 Interr_Err_Ind[0]=0xd;
5217 Interr_Err_Ind[3]=0xa;
5218 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5219 break;
5220 case CCBS_DEACTIVATE:
5221 dbug(1,dprintf("CCBS Deactivate"));
5222 Interr_Err_Ind[0]=0x9;
5223 Interr_Err_Ind[3]=0x6;
5224 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5225 break;
5226 case CCBS_INTERROGATE:
5227 dbug(1,dprintf("CCBS Interrogate"));
5228 Interr_Err_Ind[0]=0xb;
5229 Interr_Err_Ind[3]=0x8;
5230 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5231 break;
5232 }
5233 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5234 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5235 plci_remove(plci);
5236 break;
5237 case ACTIVATION_MWI:
5238 case DEACTIVATION_MWI:
5239 if(pty_cai[5]==ACTIVATION_MWI)
5240 {
5241 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5242 }
5243 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5244
5245 if(pty_cai[2]!=0xff)
5246 {
5247 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5248 }
5249 else
5250 {
5251 PUT_WORD(&SS_Ind[4],0x300E);
5252 }
5253
5254 if(plci->cr_enquiry)
5255 {
5256 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5257 plci_remove(plci);
5258 }
5259 else
5260 {
5261 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5262 }
5263 break;
5264 case CONF_ADD: /* ERROR */
5265 case CONF_BEGIN:
5266 case CONF_DROP:
5267 case CONF_ISOLATE:
5268 case CONF_REATTACH:
5269 CONF_Ind[0]=9;
5270 CONF_Ind[3]=6;
5271 switch(pty_cai[5])
5272 {
5273 case CONF_BEGIN:
5274 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5275 plci->ptyState = 0;
5276 break;
5277 case CONF_DROP:
5278 CONF_Ind[0]=5;
5279 CONF_Ind[3]=2;
5280 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5281 plci->ptyState = CONNECTED;
5282 break;
5283 case CONF_ISOLATE:
5284 CONF_Ind[0]=5;
5285 CONF_Ind[3]=2;
5286 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5287 plci->ptyState = CONNECTED;
5288 break;
5289 case CONF_REATTACH:
5290 CONF_Ind[0]=5;
5291 CONF_Ind[3]=2;
5292 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5293 plci->ptyState = CONNECTED;
5294 break;
5295 case CONF_ADD:
5296 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5297 plci->relatedPTYPLCI = NULL;
5298 tplci=plci->relatedPTYPLCI;
5299 if(tplci) tplci->ptyState = CONNECTED;
5300 plci->ptyState = CONNECTED;
5301 break;
5302 }
5303
5304 if(pty_cai[2]!=0xff)
5305 {
5306 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5307 }
5308 else
5309 {
5310 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5311 within the required time */
5312 }
5313
5314 PUT_DWORD(&CONF_Ind[6],0x0);
5315 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5316 break;
5317 }
5318 break;
5319
5320 /* Supplementary Service indicates success */
5321 case S_SERVICE:
5322 dbug(1,dprintf("Service_Ind"));
5323 PUT_WORD (&CF_Ind[4], 0);
5324 switch (pty_cai[5])
5325 {
5326 case THREE_PTY_END:
5327 case THREE_PTY_BEGIN:
5328 case ECT_EXECUTE:
5329 if(!plci->relatedPTYPLCI) break;
5330 tplci = plci->relatedPTYPLCI;
5331 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5332 if(tplci->tel) rId|=EXT_CONTROLLER;
5333 if(pty_cai[5]==ECT_EXECUTE)
5334 {
5335 PUT_WORD(&SS_Ind[1],S_ECT);
5336
5337 if(plci->vswitchstate!=3)
5338 {
5339
5340 plci->ptyState = IDLE;
5341 plci->relatedPTYPLCI = NULL;
5342 plci->ptyState = 0;
5343
5344 }
5345
5346 dbug(1,dprintf("ECT OK"));
5347 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5348
5349
5350
5351 }
5352 else
5353 {
5354 switch (plci->ptyState)
5355 {
5356 case S_3PTY_BEGIN:
5357 plci->ptyState = CONNECTED;
5358 dbug(1,dprintf("3PTY ON"));
5359 break;
5360
5361 case S_3PTY_END:
5362 plci->ptyState = IDLE;
5363 plci->relatedPTYPLCI = NULL;
5364 plci->ptyState = 0;
5365 dbug(1,dprintf("3PTY OFF"));
5366 break;
5367 }
5368 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5369 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5370 }
5371 break;
5372
5373 case CALL_DEFLECTION:
5374 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5375 for(i=0; i<max_appl; i++)
5376 {
5377 if(application[i].CDEnable)
5378 {
5379 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005380 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 }
5382 }
5383 break;
5384
5385 case DEACTIVATION_DIVERSION:
5386 case ACTIVATION_DIVERSION:
5387 if(!plci->appl) break;
5388 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5389 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5390 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5391 plci_remove(plci);
5392 break;
5393
5394 case DIVERSION_INTERROGATE_CFU:
5395 case DIVERSION_INTERROGATE_CFB:
5396 case DIVERSION_INTERROGATE_CFNR:
5397 case DIVERSION_INTERROGATE_NUM:
5398 case CCBS_REQUEST:
5399 case CCBS_DEACTIVATE:
5400 case CCBS_INTERROGATE:
5401 if(!plci->appl) break;
5402 switch (pty_cai[5])
5403 {
5404 case DIVERSION_INTERROGATE_CFU:
5405 case DIVERSION_INTERROGATE_CFB:
5406 case DIVERSION_INTERROGATE_CFNR:
5407 dbug(1,dprintf("Interr_Div"));
5408 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5409 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5410 break;
5411 case DIVERSION_INTERROGATE_NUM:
5412 dbug(1,dprintf("Interr_Num"));
5413 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5414 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5415 break;
5416 case CCBS_REQUEST:
5417 dbug(1,dprintf("CCBS Request"));
5418 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5419 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5420 break;
5421 case CCBS_DEACTIVATE:
5422 dbug(1,dprintf("CCBS Deactivate"));
5423 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5424 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5425 break;
5426 case CCBS_INTERROGATE:
5427 dbug(1,dprintf("CCBS Interrogate"));
5428 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5429 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430 break;
5431 }
5432 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5433 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5434 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5435 plci_remove(plci);
5436 break;
5437
5438 case ACTIVATION_MWI:
5439 case DEACTIVATION_MWI:
5440 if(pty_cai[5]==ACTIVATION_MWI)
5441 {
5442 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5443 }
5444 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5445 if(plci->cr_enquiry)
5446 {
5447 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5448 plci_remove(plci);
5449 }
5450 else
5451 {
5452 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5453 }
5454 break;
5455 case MWI_INDICATION:
5456 if(pty_cai[0]>=0x12)
5457 {
5458 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5459 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5460 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5461 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5462 {
5463 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5464 {
5465 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5466 plci_remove(plci);
5467 return;
5468 }
5469 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5470 pty_cai[0]=0;
5471 }
5472 else
5473 {
5474 for(i=0; i<max_appl; i++)
5475 {
5476 if(a->Notification_Mask[i]&SMASK_MWI)
5477 {
5478 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5479 pty_cai[0]=0;
5480 }
5481 }
5482 }
5483
5484 if(!pty_cai[0])
5485 { /* acknowledge */
5486 facility[2]= 0; /* returncode */
5487 }
5488 else facility[2]= 0xff;
5489 }
5490 else
5491 {
5492 /* reject */
5493 facility[2]= 0xff; /* returncode */
5494 }
5495 facility[0]= 2;
5496 facility[1]= MWI_RESPONSE; /* Function */
5497 add_p(plci,CAI,facility);
5498 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5499 sig_req(plci,S_SERVICE,0);
5500 send_req(plci);
5501 plci->command = 0;
5502 next_internal_command (Id, plci);
5503 break;
5504 case CONF_ADD: /* OK */
5505 case CONF_BEGIN:
5506 case CONF_DROP:
5507 case CONF_ISOLATE:
5508 case CONF_REATTACH:
5509 case CONF_PARTYDISC:
5510 CONF_Ind[0]=9;
5511 CONF_Ind[3]=6;
5512 switch(pty_cai[5])
5513 {
5514 case CONF_BEGIN:
5515 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5516 if(pty_cai[0]==6)
5517 {
5518 d=pty_cai[6];
5519 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5520 }
5521 else
5522 {
5523 PUT_DWORD(&CONF_Ind[6],0x0);
5524 }
5525 break;
5526 case CONF_ISOLATE:
5527 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5528 CONF_Ind[0]=5;
5529 CONF_Ind[3]=2;
5530 break;
5531 case CONF_REATTACH:
5532 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5533 CONF_Ind[0]=5;
5534 CONF_Ind[3]=2;
5535 break;
5536 case CONF_DROP:
5537 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5538 CONF_Ind[0]=5;
5539 CONF_Ind[3]=2;
5540 break;
5541 case CONF_ADD:
5542 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5543 d=pty_cai[6];
5544 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5545 tplci=plci->relatedPTYPLCI;
5546 if(tplci) tplci->ptyState = CONNECTED;
5547 break;
5548 case CONF_PARTYDISC:
5549 CONF_Ind[0]=7;
5550 CONF_Ind[3]=4;
5551 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5552 d=pty_cai[6];
5553 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5554 break;
5555 }
5556 plci->ptyState = CONNECTED;
5557 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5558 break;
5559 case CCBS_INFO_RETAIN:
5560 case CCBS_ERASECALLLINKAGEID:
5561 case CCBS_STOP_ALERTING:
5562 CONF_Ind[0]=5;
5563 CONF_Ind[3]=2;
5564 switch(pty_cai[5])
5565 {
5566 case CCBS_INFO_RETAIN:
5567 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5568 break;
5569 case CCBS_STOP_ALERTING:
5570 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5571 break;
5572 case CCBS_ERASECALLLINKAGEID:
5573 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5574 CONF_Ind[0]=7;
5575 CONF_Ind[3]=4;
5576 CONF_Ind[6]=0;
5577 CONF_Ind[7]=0;
5578 break;
5579 }
5580 w=pty_cai[6];
5581 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5582
5583 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5584 {
5585 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5586 }
5587 else
5588 {
5589 for(i=0; i<max_appl; i++)
5590 if(a->Notification_Mask[i]&SMASK_CCBS)
5591 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5592 }
5593 break;
5594 }
5595 break;
5596 case CALL_HOLD_REJ:
5597 cau = parms[7];
5598 if(cau)
5599 {
5600 i = _L3_CAUSE | cau[2];
5601 if(cau[2]==0) i = 0x3603;
5602 }
5603 else
5604 {
5605 i = 0x3603;
5606 }
5607 PUT_WORD(&SS_Ind[1],S_HOLD);
5608 PUT_WORD(&SS_Ind[4],i);
5609 if(plci->SuppState == HOLD_REQUEST)
5610 {
5611 plci->SuppState = IDLE;
5612 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5613 }
5614 break;
5615
5616 case CALL_HOLD_ACK:
5617 if(plci->SuppState == HOLD_REQUEST)
5618 {
5619 plci->SuppState = CALL_HELD;
5620 CodecIdCheck(a, plci);
5621 start_internal_command (Id, plci, hold_save_command);
5622 }
5623 break;
5624
5625 case CALL_RETRIEVE_REJ:
5626 cau = parms[7];
5627 if(cau)
5628 {
5629 i = _L3_CAUSE | cau[2];
5630 if(cau[2]==0) i = 0x3603;
5631 }
5632 else
5633 {
5634 i = 0x3603;
5635 }
5636 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5637 PUT_WORD(&SS_Ind[4],i);
5638 if(plci->SuppState == RETRIEVE_REQUEST)
5639 {
5640 plci->SuppState = CALL_HELD;
5641 CodecIdCheck(a, plci);
5642 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5643 }
5644 break;
5645
5646 case CALL_RETRIEVE_ACK:
5647 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5648 if(plci->SuppState == RETRIEVE_REQUEST)
5649 {
5650 plci->SuppState = IDLE;
5651 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5652 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5653 if(plci->tel)
5654 {
5655 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5656 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5657 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5658 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5659 {
5660 dbug(1,dprintf("Get B-ch"));
5661 start_internal_command (Id, plci, retrieve_restore_command);
5662 }
5663 else
5664 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5665 }
5666 else
5667 start_internal_command (Id, plci, retrieve_restore_command);
5668 }
5669 break;
5670
5671 case INDICATE_IND:
5672 if(plci->State != LISTENING) {
5673 sig_req(plci,HANGUP,0);
5674 send_req(plci);
5675 break;
5676 }
5677 cip = find_cip(a,parms[4],parms[6]);
5678 cip_mask = 1L<<cip;
5679 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5680 clear_c_ind_mask (plci);
5681 if (!remove_started && !a->adapter_disabled)
5682 {
5683 set_c_ind_mask_bit (plci, MAX_APPL);
5684 group_optimization(a, plci);
5685 for(i=0; i<max_appl; i++) {
5686 if(application[i].Id
5687 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5688 && CPN_filter_ok(parms[0],a,i)
5689 && test_group_ind_mask_bit (plci, i) ) {
5690 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5691 set_c_ind_mask_bit (plci, i);
5692 dump_c_ind_mask (plci);
5693 plci->State = INC_CON_PENDING;
5694 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5695 CALL_DIR_IN | CALL_DIR_ANSWER;
5696 if(esc_chi[0]) {
5697 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5698 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5699 }
5700 /* if a listen on the ext controller is done, check if hook states */
5701 /* are supported or if just a on board codec must be activated */
5702 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5703 if(a->profile.Global_Options & HANDSET)
5704 plci->tel = ADV_VOICE;
5705 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5706 plci->tel = CODEC;
5707 if(plci->tel) Id|=EXT_CONTROLLER;
5708 a->codec_listen[i] = plci;
5709 }
5710
5711 sendf(&application[i],_CONNECT_I,Id,0,
5712 "wSSSSSSSbSSSSS", cip, /* CIP */
5713 parms[0], /* CalledPartyNumber */
5714 multi_CiPN_parms[0], /* CallingPartyNumber */
5715 parms[2], /* CalledPartySubad */
5716 parms[3], /* CallingPartySubad */
5717 parms[4], /* BearerCapability */
5718 parms[5], /* LowLC */
5719 parms[6], /* HighLC */
5720 ai_len, /* nested struct add_i */
5721 add_i[0], /* B channel info */
5722 add_i[1], /* keypad facility */
5723 add_i[2], /* user user data */
5724 add_i[3], /* nested facility */
5725 multi_CiPN_parms[1] /* second CiPN(SCR) */
5726 );
5727 SendSSExtInd(&application[i],
5728 plci,
5729 Id,
5730 multi_ssext_parms);
5731 SendSetupInfo(&application[i],
5732 plci,
5733 Id,
5734 parms,
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005735 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736 }
5737 }
5738 clear_c_ind_mask_bit (plci, MAX_APPL);
5739 dump_c_ind_mask (plci);
5740 }
5741 if(c_ind_mask_empty (plci)) {
5742 sig_req(plci,HANGUP,0);
5743 send_req(plci);
5744 plci->State = IDLE;
5745 }
5746 plci->notifiedcall = 0;
5747 a->listen_active--;
5748 listen_check(a);
5749 break;
5750
5751 case CALL_PEND_NOTIFY:
5752 plci->notifiedcall = 1;
5753 listen_check(a);
5754 break;
5755
5756 case CALL_IND:
5757 case CALL_CON:
5758 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5759 {
5760 if(plci->internal_command==PERM_COD_CONN_PEND)
5761 {
5762 if(plci->State==ADVANCED_VOICE_NOSIG)
5763 {
5764 dbug(1,dprintf("***Codec OK"));
5765 if(a->AdvSignalPLCI)
5766 {
5767 tplci = a->AdvSignalPLCI;
5768 if(tplci->spoofed_msg)
5769 {
5770 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5771 tplci->command = 0;
5772 tplci->internal_command = 0;
5773 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5774 switch (tplci->spoofed_msg)
5775 {
5776 case CALL_RES:
5777 tplci->command = _CONNECT_I|RESPONSE;
5778 api_load_msg (&tplci->saved_msg, saved_parms);
5779 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5780 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5781 {
5782 /* early B3 connect (CIP mask bit 9) no release after a disc */
5783 add_p(tplci,LLI,"\x01\x01");
5784 }
5785 add_s(tplci, CONN_NR, &saved_parms[2]);
5786 add_s(tplci, LLC, &saved_parms[4]);
5787 add_ai(tplci, &saved_parms[5]);
5788 tplci->State = INC_CON_ACCEPT;
5789 sig_req(tplci, CALL_RES,0);
5790 send_req(tplci);
5791 break;
5792
5793 case AWAITING_SELECT_B:
5794 dbug(1,dprintf("Select_B continue"));
5795 start_internal_command (x_Id, tplci, select_b_command);
5796 break;
5797
5798 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5799 if(!tplci->Sig.Id)
5800 {
5801 dbug(1,dprintf("No SigID!"));
5802 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5803 plci_remove(tplci);
5804 break;
5805 }
5806 tplci->command = _MANUFACTURER_R;
5807 api_load_msg (&tplci->saved_msg, saved_parms);
5808 dir = saved_parms[2].info[0];
5809 if(dir==1) {
5810 sig_req(tplci,CALL_REQ,0);
5811 }
5812 else if(!dir){
5813 sig_req(tplci,LISTEN_REQ,0);
5814 }
5815 send_req(tplci);
5816 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5817 break;
5818
5819 case (CALL_REQ|AWAITING_MANUF_CON):
5820 sig_req(tplci,CALL_REQ,0);
5821 send_req(tplci);
5822 break;
5823
5824 case CALL_REQ:
5825 if(!tplci->Sig.Id)
5826 {
5827 dbug(1,dprintf("No SigID!"));
5828 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5829 plci_remove(tplci);
5830 break;
5831 }
5832 tplci->command = _CONNECT_R;
5833 api_load_msg (&tplci->saved_msg, saved_parms);
5834 add_s(tplci,CPN,&saved_parms[1]);
5835 add_s(tplci,DSA,&saved_parms[3]);
5836 add_ai(tplci,&saved_parms[9]);
5837 sig_req(tplci,CALL_REQ,0);
5838 send_req(tplci);
5839 break;
5840
5841 case CALL_RETRIEVE:
5842 tplci->command = C_RETRIEVE_REQ;
5843 sig_req(tplci,CALL_RETRIEVE,0);
5844 send_req(tplci);
5845 break;
5846 }
5847 tplci->spoofed_msg = 0;
5848 if (tplci->internal_command == 0)
5849 next_internal_command (x_Id, tplci);
5850 }
5851 }
5852 next_internal_command (Id, plci);
5853 break;
5854 }
5855 dbug(1,dprintf("***Codec Hook Init Req"));
5856 plci->internal_command = PERM_COD_HOOK;
5857 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5858 sig_req(plci,TEL_CTRL,0);
5859 send_req(plci);
5860 }
5861 }
5862 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5863 && plci->State!=INC_ACT_PENDING)
5864 {
5865 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5866 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5867 {
5868 chi[2] = plci->b_channel;
5869 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5870 }
5871 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5872 plci->State = INC_ACT_PENDING;
5873 }
5874 break;
5875
5876 case TEL_CTRL:
5877 Number = 0;
5878 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5879 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5880 switch (ie[1]&0x91) {
5881 case 0x80: /* hook off */
5882 case 0x81:
5883 if(plci->internal_command==PERM_COD_HOOK)
5884 {
5885 dbug(1,dprintf("init:hook_off"));
5886 plci->hook_state = ie[1];
5887 next_internal_command (Id, plci);
5888 break;
5889 }
5890 else /* ignore doubled hook indications */
5891 {
5892 if( ((plci->hook_state)&0xf0)==0x80)
5893 {
5894 dbug(1,dprintf("ignore hook"));
5895 break;
5896 }
5897 plci->hook_state = ie[1]&0x91;
5898 }
5899 /* check for incoming call pending */
5900 /* and signal '+'.Appl must decide */
5901 /* with connect_res if call must */
5902 /* accepted or not */
5903 for(i=0, tplci=NULL;i<max_appl;i++){
5904 if(a->codec_listen[i]
5905 && (a->codec_listen[i]->State==INC_CON_PENDING
5906 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5907 tplci = a->codec_listen[i];
5908 tplci->appl = &application[i];
5909 }
5910 }
5911 /* no incoming call, do outgoing call */
5912 /* and signal '+' if outg. setup */
5913 if(!a->AdvSignalPLCI && !tplci){
5914 if((i=get_plci(a))) {
5915 a->AdvSignalPLCI = &a->plci[i-1];
5916 tplci = a->AdvSignalPLCI;
5917 tplci->tel = ADV_VOICE;
5918 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5919 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5920 /* early B3 connect (CIP mask bit 9) no release after a disc */
5921 add_p(tplci,LLI,"\x01\x01");
5922 }
5923 add_p(tplci, CAI, voice_cai);
5924 add_p(tplci, OAD, a->TelOAD);
5925 add_p(tplci, OSA, a->TelOSA);
5926 add_p(tplci,SHIFT|6,NULL);
5927 add_p(tplci,SIN,"\x02\x01\x00");
5928 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5929 sig_req(tplci,ASSIGN,DSIG_ID);
5930 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5931 a->AdvSignalPLCI->command = 0;
5932 tplci->appl = a->AdvSignalAppl;
5933 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5934 send_req(tplci);
5935 }
5936
5937 }
5938
5939 if(!tplci) break;
5940 Id = ((word)tplci->Id<<8)|a->Id;
5941 Id|=EXT_CONTROLLER;
5942 sendf(tplci->appl,
5943 _FACILITY_I,
5944 Id,
5945 0,
5946 "ws", (word)0, "\x01+");
5947 break;
5948
5949 case 0x90: /* hook on */
5950 case 0x91:
5951 if(plci->internal_command==PERM_COD_HOOK)
5952 {
5953 dbug(1,dprintf("init:hook_on"));
5954 plci->hook_state = ie[1]&0x91;
5955 next_internal_command (Id, plci);
5956 break;
5957 }
5958 else /* ignore doubled hook indications */
5959 {
5960 if( ((plci->hook_state)&0xf0)==0x90) break;
5961 plci->hook_state = ie[1]&0x91;
5962 }
5963 /* hangup the adv. voice call and signal '-' to the appl */
5964 if(a->AdvSignalPLCI) {
5965 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5966 if(plci->tel) Id|=EXT_CONTROLLER;
5967 sendf(a->AdvSignalAppl,
5968 _FACILITY_I,
5969 Id,
5970 0,
5971 "ws", (word)0, "\x01-");
5972 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5973 a->AdvSignalPLCI->command = 0;
5974 sig_req(a->AdvSignalPLCI,HANGUP,0);
5975 send_req(a->AdvSignalPLCI);
5976 }
5977 break;
5978 }
5979 }
5980 break;
5981
5982 case RESUME:
5983 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5984 PUT_WORD(&resume_cau[4],GOOD);
5985 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5986 break;
5987
5988 case SUSPEND:
5989 clear_c_ind_mask (plci);
5990
5991 if (plci->NL.Id && !plci->nl_remove_id) {
5992 mixer_remove (plci);
5993 nl_req_ncci(plci,REMOVE,0);
5994 }
5995 if (!plci->sig_remove_id) {
5996 plci->internal_command = 0;
5997 sig_req(plci,REMOVE,0);
5998 }
5999 send_req(plci);
6000 if(!plci->channels) {
6001 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6002 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6003 }
6004 break;
6005
6006 case SUSPEND_REJ:
6007 break;
6008
6009 case HANGUP:
6010 plci->hangup_flow_ctrl_timer=0;
6011 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6012 cau = parms[7];
6013 if(cau) {
6014 i = _L3_CAUSE | cau[2];
6015 if(cau[2]==0) i = 0;
6016 else if(cau[2]==8) i = _L1_ERROR;
6017 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6018 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6019 }
6020 else {
6021 i = _L3_ERROR;
6022 }
6023
6024 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6025 {
6026 for(i=0; i<max_appl; i++)
6027 {
6028 if(test_c_ind_mask_bit (plci, i))
6029 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6030 }
6031 }
6032 else
6033 {
6034 clear_c_ind_mask (plci);
6035 }
6036 if(!plci->appl)
6037 {
6038 if (plci->State == LISTENING)
6039 {
6040 plci->notifiedcall=0;
6041 a->listen_active--;
6042 }
6043 plci->State = INC_DIS_PENDING;
6044 if(c_ind_mask_empty (plci))
6045 {
6046 plci->State = IDLE;
6047 if (plci->NL.Id && !plci->nl_remove_id)
6048 {
6049 mixer_remove (plci);
6050 nl_req_ncci(plci,REMOVE,0);
6051 }
6052 if (!plci->sig_remove_id)
6053 {
6054 plci->internal_command = 0;
6055 sig_req(plci,REMOVE,0);
6056 }
6057 send_req(plci);
6058 }
6059 }
6060 else
6061 {
6062 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6063 /* result in a second HANGUP! Don't generate another */
6064 /* DISCONNECT */
6065 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6066 {
6067 if(plci->State==RESUMING)
6068 {
6069 PUT_WORD(&resume_cau[4],i);
6070 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6071 }
6072 plci->State = INC_DIS_PENDING;
6073 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6074 }
6075 }
6076 break;
6077
6078 case SSEXT_IND:
6079 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6080 break;
6081
6082 case VSWITCH_REQ:
6083 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6084 break;
6085 case VSWITCH_IND:
6086 if(plci->relatedPTYPLCI &&
6087 plci->vswitchstate==3 &&
6088 plci->relatedPTYPLCI->vswitchstate==3 &&
6089 parms[MAXPARMSIDS-1][0])
6090 {
6091 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6092 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6093 send_req(plci->relatedPTYPLCI);
6094 }
6095 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6096 break;
6097
6098 }
6099}
6100
6101
6102static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6103{
6104 word i;
6105 byte * ie;
6106 word Info_Number;
6107 byte * Info_Element;
6108 word Info_Mask = 0;
6109
6110 dbug(1,dprintf("SetupInfo"));
6111
6112 for(i=0; i<MAXPARMSIDS; i++) {
6113 ie = parms[i];
6114 Info_Number = 0;
6115 Info_Element = ie;
6116 if(ie[0]) {
6117 switch(i) {
6118 case 0:
6119 dbug(1,dprintf("CPN "));
6120 Info_Number = 0x0070;
6121 Info_Mask = 0x80;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006122 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123 break;
6124 case 8: /* display */
6125 dbug(1,dprintf("display(%d)",i));
6126 Info_Number = 0x0028;
6127 Info_Mask = 0x04;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006128 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129 break;
6130 case 16: /* Channel Id */
6131 dbug(1,dprintf("CHI"));
6132 Info_Number = 0x0018;
6133 Info_Mask = 0x100;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006134 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135 mixer_set_bchannel_id (plci, Info_Element);
6136 break;
6137 case 19: /* Redirected Number */
6138 dbug(1,dprintf("RDN"));
6139 Info_Number = 0x0074;
6140 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006141 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142 break;
6143 case 20: /* Redirected Number extended */
6144 dbug(1,dprintf("RDX"));
6145 Info_Number = 0x0073;
6146 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006147 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148 break;
6149 case 22: /* Redirecing Number */
6150 dbug(1,dprintf("RIN"));
6151 Info_Number = 0x0076;
6152 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006153 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006154 break;
6155 default:
6156 Info_Number = 0;
6157 break;
6158 }
6159 }
6160
6161 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6162 Info_Number = 0x8000 |5;
6163 Info_Mask = 0x10;
6164 Info_Element = "";
6165 }
6166
6167 if(Info_Sent_Flag && Info_Number){
6168 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6169 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6170 }
6171 }
6172 }
6173}
6174
6175
Hannes Eder4ee59d52008-12-16 01:17:33 -08006176static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006177{
6178 word i;
6179 word j;
6180 word k;
6181 byte * ie;
6182 word Info_Number;
6183 byte * Info_Element;
6184 word Info_Mask = 0;
6185 static byte charges[5] = {4,0,0,0,0};
6186 static byte cause[] = {0x02,0x80,0x00};
6187 APPL *appl;
6188
6189 dbug(1,dprintf("InfoParse "));
6190
6191 if(
6192 !plci->appl
6193 && !plci->State
6194 && plci->Sig.Ind!=NCR_FACILITY
6195 )
6196 {
6197 dbug(1,dprintf("NoParse "));
6198 return;
6199 }
6200 cause[2] = 0;
6201 for(i=0; i<MAXPARMSIDS; i++) {
6202 ie = parms[i];
6203 Info_Number = 0;
6204 Info_Element = ie;
6205 if(ie[0]) {
6206 switch(i) {
6207 case 0:
6208 dbug(1,dprintf("CPN "));
6209 Info_Number = 0x0070;
6210 Info_Mask = 0x80;
6211 break;
6212 case 7: /* ESC_CAU */
6213 dbug(1,dprintf("cau(0x%x)",ie[2]));
6214 Info_Number = 0x0008;
6215 Info_Mask = 0x00;
6216 cause[2] = ie[2];
6217 Info_Element = NULL;
6218 break;
6219 case 8: /* display */
6220 dbug(1,dprintf("display(%d)",i));
6221 Info_Number = 0x0028;
6222 Info_Mask = 0x04;
6223 break;
6224 case 9: /* Date display */
6225 dbug(1,dprintf("date(%d)",i));
6226 Info_Number = 0x0029;
6227 Info_Mask = 0x02;
6228 break;
6229 case 10: /* charges */
6230 for(j=0;j<4;j++) charges[1+j] = 0;
6231 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6232 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6233 Info_Number = 0x4000;
6234 Info_Mask = 0x40;
6235 Info_Element = charges;
6236 break;
6237 case 11: /* user user info */
6238 dbug(1,dprintf("uui"));
6239 Info_Number = 0x007E;
6240 Info_Mask = 0x08;
6241 break;
6242 case 12: /* congestion receiver ready */
6243 dbug(1,dprintf("clRDY"));
6244 Info_Number = 0x00B0;
6245 Info_Mask = 0x08;
6246 Info_Element = "";
6247 break;
6248 case 13: /* congestion receiver not ready */
6249 dbug(1,dprintf("clNRDY"));
6250 Info_Number = 0x00BF;
6251 Info_Mask = 0x08;
6252 Info_Element = "";
6253 break;
6254 case 15: /* Keypad Facility */
6255 dbug(1,dprintf("KEY"));
6256 Info_Number = 0x002C;
6257 Info_Mask = 0x20;
6258 break;
6259 case 16: /* Channel Id */
6260 dbug(1,dprintf("CHI"));
6261 Info_Number = 0x0018;
6262 Info_Mask = 0x100;
6263 mixer_set_bchannel_id (plci, Info_Element);
6264 break;
6265 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6266 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6267 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6268 Info_Number = 0x0008;
6269 Info_Mask = 0x01;
6270 if(cause[2] != ie[2]) Info_Element = cause;
6271 break;
6272 case 19: /* Redirected Number */
6273 dbug(1,dprintf("RDN"));
6274 Info_Number = 0x0074;
6275 Info_Mask = 0x400;
6276 break;
6277 case 22: /* Redirecing Number */
6278 dbug(1,dprintf("RIN"));
6279 Info_Number = 0x0076;
6280 Info_Mask = 0x400;
6281 break;
6282 case 23: /* Notification Indicator */
6283 dbug(1,dprintf("NI"));
6284 Info_Number = (word)NI;
6285 Info_Mask = 0x210;
6286 break;
6287 case 26: /* Call State */
6288 dbug(1,dprintf("CST"));
6289 Info_Number = (word)CST;
6290 Info_Mask = 0x01; /* do with cause i.e. for now */
6291 break;
6292 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6293 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6294 Info_Number = 0x8000 |ie[3];
6295 if(iesent) Info_Mask = 0xffff;
6296 else Info_Mask = 0x10;
6297 Info_Element = "";
6298 break;
6299 default:
6300 Info_Number = 0;
6301 Info_Mask = 0;
6302 Info_Element = "";
6303 break;
6304 }
6305 }
6306
6307 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6308 {
6309 for(j=0; j<max_appl; j++)
6310 {
6311 appl = &application[j];
6312 if(Info_Number
6313 && appl->Id
6314 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6315 {
6316 dbug(1,dprintf("NCR_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006317 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006318 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6319 }
6320 }
6321 }
6322 else if(!plci->appl)
6323 { /* overlap receiving broadcast */
6324 if(Info_Number==CPN
6325 || Info_Number==KEY
6326 || Info_Number==NI
6327 || Info_Number==DSP
6328 || Info_Number==UUI )
6329 {
6330 for(j=0; j<max_appl; j++)
6331 {
6332 if(test_c_ind_mask_bit (plci, j))
6333 {
6334 dbug(1,dprintf("Ovl_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006335 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6337 }
6338 }
6339 }
6340 } /* all other signalling states */
6341 else if(Info_Number
6342 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6343 {
6344 dbug(1,dprintf("Std_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006345 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6347 }
6348 }
6349}
6350
6351
Hannes Eder4ee59d52008-12-16 01:17:33 -08006352static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6353 dword info_mask, byte setupParse)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006354{
6355 word i;
6356 word j;
6357 byte * ie;
6358 word Info_Number;
6359 byte * Info_Element;
6360 APPL *appl;
6361 word Info_Mask = 0;
6362 byte iesent=0;
6363
6364 if(
6365 !plci->appl
6366 && !plci->State
6367 && plci->Sig.Ind!=NCR_FACILITY
6368 && !setupParse
6369 )
6370 {
6371 dbug(1,dprintf("NoM-IEParse "));
6372 return 0;
6373 }
6374 dbug(1,dprintf("M-IEParse "));
6375
6376 for(i=0; i<MAX_MULTI_IE; i++)
6377 {
6378 ie = parms[i];
6379 Info_Number = 0;
6380 Info_Element = ie;
6381 if(ie[0])
6382 {
6383 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6384 Info_Number = (word)ie_type;
6385 Info_Mask = (word)info_mask;
6386 }
6387
6388 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6389 {
6390 for(j=0; j<max_appl; j++)
6391 {
6392 appl = &application[j];
6393 if(Info_Number
6394 && appl->Id
6395 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6396 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006397 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006398 dbug(1,dprintf("Mlt_NCR_Ind"));
6399 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6400 }
6401 }
6402 }
6403 else if(!plci->appl && Info_Number)
6404 { /* overlap receiving broadcast */
6405 for(j=0; j<max_appl; j++)
6406 {
6407 if(test_c_ind_mask_bit (plci, j))
6408 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006409 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006410 dbug(1,dprintf("Mlt_Ovl_Ind"));
6411 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6412 }
6413 }
6414 } /* all other signalling states */
6415 else if(Info_Number
6416 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6417 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006418 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006419 dbug(1,dprintf("Mlt_Std_Ind"));
6420 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6421 }
6422 }
6423 return iesent;
6424}
6425
6426static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6427{
6428 word i;
6429 /* Format of multi_ssext_parms[i][]:
6430 0 byte length
6431 1 byte SSEXTIE
6432 2 byte SSEXT_REQ/SSEXT_IND
6433 3 byte length
6434 4 word SSExtCommand
6435 6... Params
6436 */
6437 if(
6438 plci
6439 && plci->State
6440 && plci->Sig.Ind!=NCR_FACILITY
6441 )
6442 for(i=0;i<MAX_MULTI_IE;i++)
6443 {
6444 if(parms[i][0]<6) continue;
6445 if(parms[i][2]==SSEXT_REQ) continue;
6446
6447 if(appl)
6448 {
6449 parms[i][0]=0; /* kill it */
6450 sendf(appl,_MANUFACTURER_I,
6451 Id,
6452 0,
6453 "dwS",
6454 _DI_MANU_ID,
6455 _DI_SSEXT_CTRL,
6456 &parms[i][3]);
6457 }
6458 else if(plci->appl)
6459 {
6460 parms[i][0]=0; /* kill it */
6461 sendf(plci->appl,_MANUFACTURER_I,
6462 Id,
6463 0,
6464 "dwS",
6465 _DI_MANU_ID,
6466 _DI_SSEXT_CTRL,
6467 &parms[i][3]);
6468 }
6469 }
6470};
6471
Hannes Eder4ee59d52008-12-16 01:17:33 -08006472static void nl_ind(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006473{
6474 byte ch;
6475 word ncci;
6476 dword Id;
6477 DIVA_CAPI_ADAPTER * a;
6478 word NCCIcode;
6479 APPL * APPLptr;
6480 word count;
6481 word Num;
6482 word i, ncpi_state;
6483 byte len, ncci_state;
6484 word msg;
6485 word info = 0;
6486 word fax_feature_bits;
6487 byte fax_send_edata_ack;
6488 static byte v120_header_buffer[2 + 3];
6489 static word fax_info[] = {
6490 0, /* T30_SUCCESS */
6491 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6492 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6493 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6494 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6495 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6496 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6497 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6498 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6499 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6500 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6501 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6502 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6503 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6504 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6505 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6506 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6509 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6511 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6523 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6524 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6525 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6527 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6528 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6529 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6530 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6535 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6536 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6537 };
6538
6539 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6540
6541
6542 static word rtp_info[] = {
6543 GOOD, /* RTP_SUCCESS */
6544 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6545 };
6546
6547 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6548 {
6549 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6550 0x00000000, 0x00000000, 0x00000000, 0x00000000
6551 };
6552
6553 ch = plci->NL.IndCh;
6554 a = plci->adapter;
6555 ncci = a->ch_ncci[ch];
6556 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6557 if(plci->tel) Id|=EXT_CONTROLLER;
6558 APPLptr = plci->appl;
6559 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",
6560 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6561
6562 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6563
6564 if (plci->nl_remove_id)
6565 {
6566 plci->NL.RNR = 2; /* discard */
6567 dbug(1,dprintf("NL discard while remove pending"));
6568 return;
6569 }
6570 if((plci->NL.Ind &0x0f)==N_CONNECT)
6571 {
6572 if(plci->State==INC_DIS_PENDING
6573 || plci->State==OUTG_DIS_PENDING
6574 || plci->State==IDLE)
6575 {
6576 plci->NL.RNR = 2; /* discard */
6577 dbug(1,dprintf("discard n_connect"));
6578 return;
6579 }
6580 if(plci->State < INC_ACT_PENDING)
6581 {
6582 plci->NL.RNR = 1; /* flow control */
6583 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6584 return;
6585 }
6586 }
6587
6588 if(!APPLptr) /* no application or invalid data */
6589 { /* while reloading the DSP */
6590 dbug(1,dprintf("discard1"));
6591 plci->NL.RNR = 2;
6592 return;
6593 }
6594
6595 if (((plci->NL.Ind &0x0f) == N_UDATA)
6596 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6597 || (plci->B2_prot == 7)
6598 || (plci->B3_prot == 7)) )
6599 {
6600 plci->ncpi_buffer[0] = 0;
6601
6602 ncpi_state = plci->ncpi_state;
6603 if (plci->NL.complete == 1)
6604 {
6605 byte * data = &plci->NL.RBuffer->P[0];
6606
6607 if ((plci->NL.RBuffer->length >= 12)
6608 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6609 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6610 {
6611 word conn_opt, ncpi_opt = 0x00;
6612/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6613
6614 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6615 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6616 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6617 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6618
6619 data++; /* indication code */
6620 data += 2; /* timestamp */
6621 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6622 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6623 data++; /* connected norm */
6624 conn_opt = GET_WORD(data);
6625 data += 2; /* connected options */
6626
6627 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6628
6629 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6630 {
6631 ncpi_opt |= MDM_NCPI_ECM_V42;
6632 }
6633 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6634 {
6635 ncpi_opt |= MDM_NCPI_ECM_MNP;
6636 }
6637 else
6638 {
6639 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6640 }
6641 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6642 {
6643 ncpi_opt |= MDM_NCPI_COMPRESSED;
6644 }
6645 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6646 plci->ncpi_buffer[0] = 4;
6647
6648 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6649 }
6650 }
6651 if (plci->B3_prot == 7)
6652 {
6653 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6654 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6655 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6656 {
6657 a->ncci_state[ncci] = INC_ACT_PENDING;
6658 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6659 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6660 }
6661 }
6662
6663 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6664 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6665 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6666 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6667
6668 {
6669 plci->NL.RNR = 2;
6670 return;
6671 }
6672 }
6673
6674 if(plci->NL.complete == 2)
6675 {
6676 if (((plci->NL.Ind &0x0f) == N_UDATA)
6677 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6678 {
6679 switch(plci->RData[0].P[0])
6680 {
6681
6682 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6683 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6684 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6685 break;
6686 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6687 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6688 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6689 break;
6690 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6691 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6692 break;
6693 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6694 dtmf_confirmation (Id, plci);
6695 break;
6696
6697
6698 case UDATA_INDICATION_MIXER_TAP_DATA:
6699 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6700 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6701 if (i != 0)
6702 {
6703 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6704 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6705 }
6706 break;
6707
6708
6709 case UDATA_INDICATION_MIXER_COEFS_SET:
6710 mixer_indication_coefs_set (Id, plci);
6711 break;
6712 case UDATA_INDICATION_XCONNECT_FROM:
6713 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714 break;
6715 case UDATA_INDICATION_XCONNECT_TO:
6716 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6717 break;
6718
6719
6720 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6721 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6722 break;
6723
6724
6725
6726 default:
6727 break;
6728 }
6729 }
6730 else
6731 {
6732 if ((plci->RData[0].PLength != 0)
6733 && ((plci->B2_prot == B2_V120_ASYNC)
6734 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6735 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6736 {
6737
6738 sendf(plci->appl,_DATA_B3_I,Id,0,
6739 "dwww",
6740 plci->RData[1].P,
6741 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6742 plci->RNum,
6743 plci->RFlags);
6744
6745 }
6746 else
6747 {
6748
6749 sendf(plci->appl,_DATA_B3_I,Id,0,
6750 "dwww",
6751 plci->RData[0].P,
6752 plci->RData[0].PLength,
6753 plci->RNum,
6754 plci->RFlags);
6755
6756 }
6757 }
6758 return;
6759 }
6760
6761 fax_feature_bits = 0;
6762 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6763 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6764 (plci->NL.Ind &0x0f)==N_DISC ||
6765 (plci->NL.Ind &0x0f)==N_EDATA ||
6766 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6767 {
6768 info = 0;
6769 plci->ncpi_buffer[0] = 0;
6770 switch (plci->B3_prot) {
6771 case 0: /*XPARENT*/
6772 case 1: /*T.90 NL*/
6773 break; /* no network control protocol info - jfr */
6774 case 2: /*ISO8202*/
6775 case 3: /*X25 DCE*/
6776 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6777 plci->ncpi_buffer[0] = (byte)(i+3);
6778 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6779 plci->ncpi_buffer[2] = 0;
6780 plci->ncpi_buffer[3] = 0;
6781 break;
6782 case 4: /*T.30 - FAX*/
6783 case 5: /*T.30 - FAX*/
6784 if(plci->NL.RLength>=sizeof(T30_INFO))
6785 {
6786 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6787 len = 9;
6788 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6789 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6790 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6791 if (plci->B3_prot == 5)
6792 {
6793 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6794 i |= 0x8000; /* This is not an ECM connection */
6795 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6796 i |= 0x4000; /* This is a connection with MMR compression */
6797 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6798 i |= 0x2000; /* This is a connection with MR compression */
6799 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6800 i |= 0x0004; /* More documents */
6801 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6802 i |= 0x0002; /* Fax-polling indication */
6803 }
6804 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6805 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6806 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6807 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6808 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6809 plci->ncpi_buffer[len] = 0;
6810 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6811 {
6812 plci->ncpi_buffer[len] = 20;
6813 for (i = 0; i < 20; i++)
6814 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6815 }
6816 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6817 {
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -08006818 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6820 else
6821 info = _FAX_PROTOCOL_ERROR;
6822 }
6823
6824 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6825 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6826 {
6827 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6828 while (i < plci->NL.RBuffer->length)
6829 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6830 }
6831
6832 plci->ncpi_buffer[0] = len;
6833 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6834 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6835
6836 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6837 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6838 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6839 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6840 || (((plci->NL.Ind &0x0f) == N_EDATA)
6841 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6842 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6843 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6844 {
6845 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6846 }
6847 if (((plci->NL.Ind &0x0f) == N_DISC)
6848 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6849 || (((plci->NL.Ind &0x0f) == N_EDATA)
6850 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6851 {
6852 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6853 }
6854 }
6855 break;
6856
6857 case B3_RTP:
6858 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6859 {
6860 if (plci->NL.RLength != 0)
6861 {
6862 info = rtp_info[plci->NL.RBuffer->P[0]];
6863 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6864 for (i = 1; i < plci->NL.RLength; i++)
6865 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6866 }
6867 }
6868 break;
6869
6870 }
6871 plci->NL.RNR = 2;
6872 }
6873 switch(plci->NL.Ind &0x0f) {
6874 case N_EDATA:
6875 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6876 {
6877 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6878 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6879 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6880
6881 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6882 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6883 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6884 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6885 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6886 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6887 {
6888 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6889 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6890 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6891 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6892 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006893 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006894 }
6895
6896 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6897 {
6898 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6899 {
6900 case EDATA_T30_DIS:
6901 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6902 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6903 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6904 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6905 {
6906 a->ncci_state[ncci] = INC_ACT_PENDING;
6907 if (plci->B3_prot == 4)
6908 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6909 else
6910 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6911 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6912 }
6913 break;
6914
6915 case EDATA_T30_TRAIN_OK:
6916 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6917 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6919 {
6920 if (plci->B3_prot == 4)
6921 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6922 else
6923 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6924 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6925 }
6926 break;
6927
6928 case EDATA_T30_EOP_CAPI:
6929 if (a->ncci_state[ncci] == CONNECTED)
6930 {
6931 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6932 a->ncci_state[ncci] = INC_DIS_PENDING;
6933 plci->ncpi_state = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006934 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935 }
6936 break;
6937 }
6938 }
6939 else
6940 {
6941 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6942 {
6943 case EDATA_T30_TRAIN_OK:
6944 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6945 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6946 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6947 {
6948 if (plci->B3_prot == 4)
6949 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6950 else
6951 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6952 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6953 }
6954 break;
6955 }
6956 }
6957 if (fax_send_edata_ack)
6958 {
6959 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6960 plci->fax_edata_ack_length = 1;
6961 start_internal_command (Id, plci, fax_edata_ack_command);
6962 }
6963 }
6964 else
6965 {
6966 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6967 }
6968 break;
6969 case N_CONNECT:
6970 if (!a->ch_ncci[ch])
6971 {
6972 ncci = get_ncci (plci, ch, 0);
6973 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6974 }
6975 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6976 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6977
6978 msg = _CONNECT_B3_I;
6979 if (a->ncci_state[ncci] == IDLE)
6980 plci->channels++;
6981 else if (plci->B3_prot == 1)
6982 msg = _CONNECT_B3_T90_ACTIVE_I;
6983
6984 a->ncci_state[ncci] = INC_CON_PENDING;
6985 if(plci->B3_prot == 4)
6986 sendf(plci->appl,msg,Id,0,"s","");
6987 else
6988 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6989 break;
6990 case N_CONNECT_ACK:
6991 dbug(1,dprintf("N_connect_Ack"));
6992 if (plci->internal_command_queue[0]
6993 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6994 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6995 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6996 {
6997 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6998 if (!plci->internal_command)
6999 next_internal_command (Id, plci);
7000 break;
7001 }
7002 msg = _CONNECT_B3_ACTIVE_I;
7003 if (plci->B3_prot == 1)
7004 {
7005 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7006 msg = _CONNECT_B3_T90_ACTIVE_I;
7007 a->ncci_state[ncci] = INC_ACT_PENDING;
7008 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7009 }
7010 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7011 {
7012 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7013 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7014 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7015 {
7016 a->ncci_state[ncci] = INC_ACT_PENDING;
7017 if (plci->B3_prot == 4)
7018 sendf(plci->appl,msg,Id,0,"s","");
7019 else
7020 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7021 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7022 }
7023 }
7024 else
7025 {
7026 a->ncci_state[ncci] = INC_ACT_PENDING;
7027 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7028 }
7029 if (plci->adjust_b_restore)
7030 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007031 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007032 start_internal_command (Id, plci, adjust_b_restore);
7033 }
7034 break;
7035 case N_DISC:
7036 case N_DISC_ACK:
7037 if (plci->internal_command_queue[0]
7038 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7039 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7040 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7041 {
7042 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7043 if (!plci->internal_command)
7044 next_internal_command (Id, plci);
7045 }
7046 ncci_state = a->ncci_state[ncci];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007047 ncci_remove (plci, ncci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007048
7049 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7050 /* channel, so we cannot store the state in ncci_state! The */
7051 /* information which channel we received a N_DISC is thus */
7052 /* stored in the inc_dis_ncci_table buffer. */
7053 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7054 plci->inc_dis_ncci_table[i] = (byte) ncci;
7055
7056 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7057 if (!plci->channels
7058 && (plci->B1_resource == 16)
7059 && (plci->State <= CONNECTED))
7060 {
7061 len = 9;
7062 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7063 PUT_WORD (&plci->ncpi_buffer[1], i);
7064 PUT_WORD (&plci->ncpi_buffer[3], 0);
7065 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7066 PUT_WORD (&plci->ncpi_buffer[5], i);
7067 PUT_WORD (&plci->ncpi_buffer[7], 0);
7068 plci->ncpi_buffer[len] = 0;
7069 plci->ncpi_buffer[0] = len;
7070 if(plci->B3_prot == 4)
7071 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7072 else
7073 {
7074
7075 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7076 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7077 {
7078 plci->ncpi_buffer[++len] = 0;
7079 plci->ncpi_buffer[++len] = 0;
7080 plci->ncpi_buffer[++len] = 0;
7081 plci->ncpi_buffer[0] = len;
7082 }
7083
7084 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7085 }
7086 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7087 plci->ncpi_state = 0;
7088 sig_req(plci,HANGUP,0);
7089 send_req(plci);
7090 plci->State = OUTG_DIS_PENDING;
7091 /* disc here */
7092 }
7093 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7094 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7095 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7096 {
7097 if (ncci_state == IDLE)
7098 {
7099 if (plci->channels)
7100 plci->channels--;
7101 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7102 if(plci->State == SUSPENDING){
7103 sendf(plci->appl,
7104 _FACILITY_I,
7105 Id & 0xffffL,
7106 0,
7107 "ws", (word)3, "\x03\x04\x00\x00");
7108 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7109 }
7110 plci_remove(plci);
7111 plci->State=IDLE;
7112 }
7113 }
7114 }
7115 else if (plci->channels)
7116 {
7117 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7118 plci->ncpi_state = 0;
7119 if ((ncci_state == OUTG_REJ_PENDING)
7120 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7121 {
7122 sig_req(plci,HANGUP,0);
7123 send_req(plci);
7124 plci->State = OUTG_DIS_PENDING;
7125 }
7126 }
7127 break;
7128 case N_RESET:
7129 a->ncci_state[ncci] = INC_RES_PENDING;
7130 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7131 break;
7132 case N_RESET_ACK:
7133 a->ncci_state[ncci] = CONNECTED;
7134 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7135 break;
7136
7137 case N_UDATA:
7138 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7139 {
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07007140 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007141 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7142 plci->NL.R = plci->RData;
7143 plci->NL.RNum = 1;
7144 return;
7145 }
7146 case N_BDATA:
7147 case N_DATA:
7148 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7149 || (a->ncci_state[ncci] == IDLE)
7150 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7151 {
7152 plci->NL.RNR = 2;
7153 break;
7154 }
7155 if ((a->ncci_state[ncci] != CONNECTED)
7156 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7157 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7158 {
7159 dbug(1,dprintf("flow control"));
7160 plci->NL.RNR = 1; /* flow control */
7161 channel_x_off (plci, ch, 0);
7162 break;
7163 }
7164
7165 NCCIcode = ncci | (((word)a->Id) << 8);
7166
7167 /* count all buffers within the Application pool */
7168 /* belonging to the same NCCI. If this is below the */
7169 /* number of buffers available per NCCI we accept */
7170 /* this packet, otherwise we reject it */
7171 count = 0;
7172 Num = 0xffff;
7173 for(i=0; i<APPLptr->MaxBuffer; i++) {
7174 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7175 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7176 }
7177
7178 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7179 {
7180 dbug(3,dprintf("Flow-Control"));
7181 plci->NL.RNR = 1;
7182 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7183 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7184 {
7185 plci->NL.RNR = 2;
7186 dbug(3,dprintf("DiscardData"));
7187 } else {
7188 channel_x_off (plci, ch, 0);
7189 }
7190 break;
7191 }
7192 else
7193 {
7194 APPLptr->NCCIDataFlowCtrlTimer = 0;
7195 }
7196
7197 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7198 if(!plci->RData[0].P) {
7199 plci->NL.RNR = 1;
7200 channel_x_off (plci, ch, 0);
7201 break;
7202 }
7203
7204 APPLptr->DataNCCI[Num] = NCCIcode;
7205 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7206 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7207
7208 plci->RNum = Num;
7209 plci->RFlags = plci->NL.Ind>>4;
7210 plci->RData[0].PLength = APPLptr->MaxDataLength;
7211 plci->NL.R = plci->RData;
7212 if ((plci->NL.RLength != 0)
7213 && ((plci->B2_prot == B2_V120_ASYNC)
7214 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7215 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7216 {
7217 plci->RData[1].P = plci->RData[0].P;
7218 plci->RData[1].PLength = plci->RData[0].PLength;
7219 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7220 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7221 plci->RData[0].PLength = 1;
7222 else
7223 plci->RData[0].PLength = 2;
7224 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7225 plci->RFlags |= 0x0010;
7226 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7227 plci->RFlags |= 0x8000;
7228 plci->NL.RNum = 2;
7229 }
7230 else
7231 {
7232 if((plci->NL.Ind &0x0f)==N_UDATA)
7233 plci->RFlags |= 0x0010;
7234
7235 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7236 plci->RFlags |= 0x0001;
7237
7238 plci->NL.RNum = 1;
7239 }
7240 break;
7241 case N_DATA_ACK:
7242 data_ack (plci, ch);
7243 break;
7244 default:
7245 plci->NL.RNR = 2;
7246 break;
7247 }
7248}
7249
7250/*------------------------------------------------------------------*/
7251/* find a free PLCI */
7252/*------------------------------------------------------------------*/
7253
Hannes Eder4ee59d52008-12-16 01:17:33 -08007254static word get_plci(DIVA_CAPI_ADAPTER *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255{
7256 word i,j;
7257 PLCI * plci;
7258
7259 dump_plcis (a);
7260 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7261 if(i==a->max_plci) {
7262 dbug(1,dprintf("get_plci: out of PLCIs"));
7263 return 0;
7264 }
7265 plci = &a->plci[i];
7266 plci->Id = (byte)(i+1);
7267
7268 plci->Sig.Id = 0;
7269 plci->NL.Id = 0;
7270 plci->sig_req = 0;
7271 plci->nl_req = 0;
7272
7273 plci->appl = NULL;
7274 plci->relatedPTYPLCI = NULL;
7275 plci->State = IDLE;
7276 plci->SuppState = IDLE;
7277 plci->channels = 0;
7278 plci->tel = 0;
7279 plci->B1_resource = 0;
7280 plci->B2_prot = 0;
7281 plci->B3_prot = 0;
7282
7283 plci->command = 0;
7284 plci->m_command = 0;
7285 init_internal_command_queue (plci);
7286 plci->number = 0;
7287 plci->req_in_start = 0;
7288 plci->req_in = 0;
7289 plci->req_out = 0;
7290 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7291 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7292 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7293
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007294 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007295 plci->send_disc = 0;
7296 plci->sig_global_req = 0;
7297 plci->sig_remove_id = 0;
7298 plci->nl_global_req = 0;
7299 plci->nl_remove_id = 0;
7300 plci->adv_nl = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007301 plci->manufacturer = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7303 plci->spoofed_msg = 0;
7304 plci->ptyState = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007305 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306 plci->hangup_flow_ctrl_timer = 0;
7307
7308 plci->ncci_ring_list = 0;
7309 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7310 clear_c_ind_mask (plci);
7311 set_group_ind_mask (plci);
7312 plci->fax_connect_info_length = 0;
7313 plci->nsf_control_bits = 0;
7314 plci->ncpi_state = 0x00;
7315 plci->ncpi_buffer[0] = 0;
7316
7317 plci->requested_options_conn = 0;
7318 plci->requested_options = 0;
7319 plci->notifiedcall = 0;
7320 plci->vswitchstate = 0;
7321 plci->vsprot = 0;
7322 plci->vsprotdialect = 0;
7323 init_b1_config (plci);
7324 dbug(1,dprintf("get_plci(%x)",plci->Id));
7325 return i+1;
7326}
7327
7328/*------------------------------------------------------------------*/
7329/* put a parameter in the parameter buffer */
7330/*------------------------------------------------------------------*/
7331
7332static void add_p(PLCI * plci, byte code, byte * p)
7333{
7334 word p_length;
7335
7336 p_length = 0;
7337 if(p) p_length = p[0];
7338 add_ie(plci, code, p, p_length);
7339}
7340
7341/*------------------------------------------------------------------*/
7342/* put a structure in the parameter buffer */
7343/*------------------------------------------------------------------*/
7344static void add_s(PLCI * plci, byte code, API_PARSE * p)
7345{
7346 if(p) add_ie(plci, code, p->info, (word)p->length);
7347}
7348
7349/*------------------------------------------------------------------*/
7350/* put multiple structures in the parameter buffer */
7351/*------------------------------------------------------------------*/
7352static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7353{
7354 byte i;
7355
7356 if(p){
7357 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7358 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7359 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7360 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7361 }
7362 }
7363}
7364
7365/*------------------------------------------------------------------*/
7366/* return the channel number sent by the application in a esc_chi */
7367/*------------------------------------------------------------------*/
7368static byte getChannel(API_PARSE * p)
7369{
7370 byte i;
7371
7372 if(p){
7373 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7374 if(p->info[i]==2){
7375 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7376 }
7377 }
7378 }
7379 return 0;
7380}
7381
7382
7383/*------------------------------------------------------------------*/
7384/* put an information element in the parameter buffer */
7385/*------------------------------------------------------------------*/
7386
7387static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7388{
7389 word i;
7390
7391 if(!(code &0x80) && !p_length) return;
7392
7393 if(plci->req_in==plci->req_in_start) {
7394 plci->req_in +=2;
7395 }
7396 else {
7397 plci->req_in--;
7398 }
7399 plci->RBuffer[plci->req_in++] = code;
7400
7401 if(p) {
7402 plci->RBuffer[plci->req_in++] = (byte)p_length;
7403 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7404 }
7405
7406 plci->RBuffer[plci->req_in++] = 0;
7407}
7408
7409/*------------------------------------------------------------------*/
7410/* put a unstructured data into the buffer */
7411/*------------------------------------------------------------------*/
7412
Hannes Eder4ee59d52008-12-16 01:17:33 -08007413static void add_d(PLCI *plci, word length, byte *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007414{
7415 word i;
7416
7417 if(plci->req_in==plci->req_in_start) {
7418 plci->req_in +=2;
7419 }
7420 else {
7421 plci->req_in--;
7422 }
7423 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7424}
7425
7426/*------------------------------------------------------------------*/
7427/* put parameters from the Additional Info parameter in the */
7428/* parameter buffer */
7429/*------------------------------------------------------------------*/
7430
Hannes Eder4ee59d52008-12-16 01:17:33 -08007431static void add_ai(PLCI *plci, API_PARSE *ai)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007432{
7433 word i;
7434 API_PARSE ai_parms[5];
7435
7436 for(i=0;i<5;i++) ai_parms[i].length = 0;
7437
7438 if(!ai->length)
7439 return;
7440 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7441 return;
7442
7443 add_s (plci,KEY,&ai_parms[1]);
7444 add_s (plci,UUI,&ai_parms[2]);
7445 add_ss(plci,FTY,&ai_parms[3]);
7446}
7447
7448/*------------------------------------------------------------------*/
7449/* put parameter for b1 protocol in the parameter buffer */
7450/*------------------------------------------------------------------*/
7451
Hannes Eder4ee59d52008-12-16 01:17:33 -08007452static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7453 word b1_facilities)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007454{
7455 API_PARSE bp_parms[8];
7456 API_PARSE mdm_cfg[9];
7457 API_PARSE global_config[2];
7458 byte cai[256];
7459 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7460 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7461 word i;
7462
7463 API_PARSE mdm_cfg_v18[4];
7464 word j, n, w;
7465 dword d;
7466
7467
7468 for(i=0;i<8;i++) bp_parms[i].length = 0;
7469 for(i=0;i<2;i++) global_config[i].length = 0;
7470
7471 dbug(1,dprintf("add_b1"));
7472 api_save_msg(bp, "s", &plci->B_protocol);
7473
7474 if(b_channel_info==2){
7475 plci->B1_resource = 0;
7476 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7477 add_p(plci, CAI, "\x01\x00");
7478 dbug(1,dprintf("Cai=1,0 (no resource)"));
7479 return 0;
7480 }
7481
7482 if(plci->tel == CODEC_PERMANENT) return 0;
7483 else if(plci->tel == CODEC){
7484 plci->B1_resource = 1;
7485 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7486 add_p(plci, CAI, "\x01\x01");
7487 dbug(1,dprintf("Cai=1,1 (Codec)"));
7488 return 0;
7489 }
7490 else if(plci->tel == ADV_VOICE){
7491 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7492 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7493 voice_cai[1] = plci->B1_resource;
7494 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7495 add_p(plci, CAI, voice_cai);
7496 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7497 return 0;
7498 }
7499 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7500 if (plci->call_dir & CALL_DIR_OUT)
7501 plci->call_dir |= CALL_DIR_ORIGINATE;
7502 else if (plci->call_dir & CALL_DIR_IN)
7503 plci->call_dir |= CALL_DIR_ANSWER;
7504
7505 if(!bp->length){
7506 plci->B1_resource = 0x5;
7507 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7508 add_p(plci, CAI, "\x01\x05");
7509 return 0;
7510 }
7511
7512 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7513 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7514 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7515 {
7516 bp_parms[6].length = 0;
7517 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7518 {
7519 dbug(1,dprintf("b-form.!"));
7520 return _WRONG_MESSAGE_FORMAT;
7521 }
7522 }
7523 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7524 {
7525 dbug(1,dprintf("b-form.!"));
7526 return _WRONG_MESSAGE_FORMAT;
7527 }
7528
7529 if(bp_parms[6].length)
7530 {
7531 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7532 {
7533 return _WRONG_MESSAGE_FORMAT;
7534 }
7535 switch(GET_WORD(global_config[0].info))
7536 {
7537 case 1:
7538 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7539 break;
7540 case 2:
7541 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7542 break;
7543 }
7544 }
7545 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7546
7547
7548 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7549 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7550 {
7551 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7552 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7553 cai[1] = plci->B1_resource;
7554 cai[2] = 0;
7555 cai[3] = 0;
7556 cai[4] = 0;
7557 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7558 for (i = 0; i < bp_parms[3].length; i++)
7559 cai[7+i] = bp_parms[3].info[1+i];
7560 cai[0] = 6 + bp_parms[3].length;
7561 add_p(plci, CAI, cai);
7562 return 0;
7563 }
7564
7565
7566 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7567 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7568 {
7569 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7570 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7571 cai[1] = plci->B1_resource;
7572 cai[2] = 0;
7573 cai[3] = 0;
7574 cai[4] = 0;
7575 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7576 cai[0] = 6;
7577 add_p(plci, CAI, cai);
7578 return 0;
7579 }
7580
7581
7582 if ((GET_WORD(bp_parms[0].info) >= 32)
7583 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7584 && ((GET_WORD(bp_parms[0].info) != 3)
7585 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7586 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7587 {
7588 return _B1_NOT_SUPPORTED;
7589 }
7590 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7591 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7592 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7593 cai[0] = 6;
7594 cai[1] = plci->B1_resource;
7595 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7596
7597 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7598 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7599 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7600 { /* B1 - modem */
7601 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7602
7603 if (bp_parms[3].length)
7604 {
7605 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7606 {
7607 return (_WRONG_MESSAGE_FORMAT);
7608 }
7609
7610 cai[2] = 0; /* Bit rate for adaptation */
7611
7612 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7613
7614 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7615 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7616 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7617 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7618
7619 cai[3] = 0; /* Async framing parameters */
7620 switch (GET_WORD (mdm_cfg[2].info))
7621 { /* Parity */
7622 case 1: /* odd parity */
7623 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7624 dbug(1,dprintf("MDM: odd parity"));
7625 break;
7626
7627 case 2: /* even parity */
7628 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7629 dbug(1,dprintf("MDM: even parity"));
7630 break;
7631
7632 default:
7633 dbug(1,dprintf("MDM: no parity"));
7634 break;
7635 }
7636
7637 switch (GET_WORD (mdm_cfg[3].info))
7638 { /* stop bits */
7639 case 1: /* 2 stop bits */
7640 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7641 dbug(1,dprintf("MDM: 2 stop bits"));
7642 break;
7643
7644 default:
7645 dbug(1,dprintf("MDM: 1 stop bit"));
7646 break;
7647 }
7648
7649 switch (GET_WORD (mdm_cfg[1].info))
7650 { /* char length */
7651 case 5:
7652 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7653 dbug(1,dprintf("MDM: 5 bits"));
7654 break;
7655
7656 case 6:
7657 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7658 dbug(1,dprintf("MDM: 6 bits"));
7659 break;
7660
7661 case 7:
7662 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7663 dbug(1,dprintf("MDM: 7 bits"));
7664 break;
7665
7666 default:
7667 dbug(1,dprintf("MDM: 8 bits"));
7668 break;
7669 }
7670
7671 cai[7] = 0; /* Line taking options */
7672 cai[8] = 0; /* Modulation negotiation options */
7673 cai[9] = 0; /* Modulation options */
7674
7675 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7676 {
7677 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7678 dbug(1, dprintf("MDM: Reverse direction"));
7679 }
7680
7681 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7682 {
7683 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7684 dbug(1, dprintf("MDM: Disable retrain"));
7685 }
7686
7687 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7688 {
7689 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7690 dbug(1, dprintf("MDM: Disable ring tone"));
7691 }
7692
7693 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7694 {
7695 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7696 dbug(1, dprintf("MDM: 1800 guard tone"));
7697 }
7698 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7699 {
7700 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7701 dbug(1, dprintf("MDM: 550 guard tone"));
7702 }
7703
7704 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7705 {
7706 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7707 dbug(1, dprintf("MDM: V100"));
7708 }
7709 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7710 {
7711 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7712 dbug(1, dprintf("MDM: IN CLASS"));
7713 }
7714 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7715 {
7716 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7717 dbug(1, dprintf("MDM: DISABLED"));
7718 }
7719 cai[0] = 20;
7720
7721 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7722 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7723 {
7724 plci->requested_options |= 1L << PRIVATE_V18;
7725 }
7726 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7727 plci->requested_options |= 1L << PRIVATE_VOWN;
7728
7729 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7730 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7731 {
7732 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7733 {
7734 i = 27;
7735 if (mdm_cfg[6].length >= 4)
7736 {
7737 d = GET_DWORD(&mdm_cfg[6].info[1]);
7738 cai[7] |= (byte) d; /* line taking options */
7739 cai[9] |= (byte)(d >> 8); /* modulation options */
7740 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7741 cai[++i] = (byte)(d >> 24);
7742 if (mdm_cfg[6].length >= 8)
7743 {
7744 d = GET_DWORD(&mdm_cfg[6].info[5]);
7745 cai[10] |= (byte) d; /* disabled modulations mask */
7746 cai[11] |= (byte)(d >> 8);
7747 if (mdm_cfg[6].length >= 12)
7748 {
7749 d = GET_DWORD(&mdm_cfg[6].info[9]);
7750 cai[12] = (byte) d; /* enabled modulations mask */
7751 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7752 cai[++i] = (byte)(d >> 16);
7753 cai[++i] = (byte)(d >> 24);
7754 cai[++i] = 0;
7755 if (mdm_cfg[6].length >= 14)
7756 {
7757 w = GET_WORD(&mdm_cfg[6].info[13]);
7758 if (w != 0)
7759 PUT_WORD(&cai[13], w); /* min tx speed */
7760 if (mdm_cfg[6].length >= 16)
7761 {
7762 w = GET_WORD(&mdm_cfg[6].info[15]);
7763 if (w != 0)
7764 PUT_WORD(&cai[15], w); /* max tx speed */
7765 if (mdm_cfg[6].length >= 18)
7766 {
7767 w = GET_WORD(&mdm_cfg[6].info[17]);
7768 if (w != 0)
7769 PUT_WORD(&cai[17], w); /* min rx speed */
7770 if (mdm_cfg[6].length >= 20)
7771 {
7772 w = GET_WORD(&mdm_cfg[6].info[19]);
7773 if (w != 0)
7774 PUT_WORD(&cai[19], w); /* max rx speed */
7775 if (mdm_cfg[6].length >= 22)
7776 {
7777 w = GET_WORD(&mdm_cfg[6].info[21]);
7778 cai[23] = (byte)(-((short) w)); /* transmit level */
7779 if (mdm_cfg[6].length >= 24)
7780 {
7781 w = GET_WORD(&mdm_cfg[6].info[23]);
7782 cai[22] |= (byte) w; /* info options mask */
7783 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7784 }
7785 }
7786 }
7787 }
7788 }
7789 }
7790 }
7791 }
7792 }
7793 cai[27] = i - 27;
7794 i++;
7795 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7796 {
7797 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7798 {
7799 for (n = 0; n < 3; n++)
7800 {
7801 cai[i] = (byte)(mdm_cfg_v18[n].length);
7802 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7803 cai[i+j] = mdm_cfg_v18[n].info[j];
7804 i += cai[i] + 1;
7805 }
7806 }
7807 }
7808 cai[0] = (byte)(i - 1);
7809 }
7810 }
7811
7812 }
7813 }
7814 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7815 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7816 {
7817 if(bp_parms[3].length){
7818 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7819 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7820 case 0:
7821 case 56000:
7822 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7823 dbug(1,dprintf("56k sync HSCX"));
7824 cai[1] = 8;
7825 cai[2] = 0;
7826 cai[3] = 0;
7827 }
7828 else if(GET_WORD(bp_parms[0].info)==2){
7829 dbug(1,dprintf("56k async DSP"));
7830 cai[2] = 9;
7831 }
7832 break;
7833 case 50: cai[2] = 1; break;
7834 case 75: cai[2] = 1; break;
7835 case 110: cai[2] = 1; break;
7836 case 150: cai[2] = 1; break;
7837 case 200: cai[2] = 1; break;
7838 case 300: cai[2] = 1; break;
7839 case 600: cai[2] = 1; break;
7840 case 1200: cai[2] = 2; break;
7841 case 2400: cai[2] = 3; break;
7842 case 4800: cai[2] = 4; break;
7843 case 7200: cai[2] = 10; break;
7844 case 9600: cai[2] = 5; break;
7845 case 12000: cai[2] = 13; break;
7846 case 24000: cai[2] = 0; break;
7847 case 14400: cai[2] = 11; break;
7848 case 19200: cai[2] = 6; break;
7849 case 28800: cai[2] = 12; break;
7850 case 38400: cai[2] = 7; break;
7851 case 48000: cai[2] = 8; break;
7852 case 76: cai[2] = 15; break; /* 75/1200 */
7853 case 1201: cai[2] = 14; break; /* 1200/75 */
7854 case 56001: cai[2] = 9; break; /* V.110 56000 */
7855
7856 default:
7857 return _B1_PARM_NOT_SUPPORTED;
7858 }
7859 cai[3] = 0;
7860 if (cai[1] == 13) /* v.110 async */
7861 {
7862 if (bp_parms[3].length >= 8)
7863 {
7864 switch (GET_WORD (&bp_parms[3].info[3]))
7865 { /* char length */
7866 case 5:
7867 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7868 break;
7869 case 6:
7870 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7871 break;
7872 case 7:
7873 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7874 break;
7875 }
7876 switch (GET_WORD (&bp_parms[3].info[5]))
7877 { /* Parity */
7878 case 1: /* odd parity */
7879 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7880 break;
7881 case 2: /* even parity */
7882 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7883 break;
7884 }
7885 switch (GET_WORD (&bp_parms[3].info[7]))
7886 { /* stop bits */
7887 case 1: /* 2 stop bits */
7888 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7889 break;
7890 }
7891 }
7892 }
7893 }
7894 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7895 dbug(1,dprintf("V.110 default 56k sync"));
7896 cai[1] = 8;
7897 cai[2] = 0;
7898 cai[3] = 0;
7899 }
7900 else {
7901 dbug(1,dprintf("V.110 default 9600 async"));
7902 cai[2] = 5;
7903 }
7904 }
7905 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7906 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]));
7907/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7908
7909 add_p(plci, CAI, cai);
7910 return 0;
7911}
7912
7913/*------------------------------------------------------------------*/
7914/* put parameter for b2 and B3 protocol in the parameter buffer */
7915/*------------------------------------------------------------------*/
7916
Hannes Eder4ee59d52008-12-16 01:17:33 -08007917static word add_b23(PLCI *plci, API_PARSE *bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007918{
7919 word i, fax_control_bits;
7920 byte pos, len;
7921 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7922 API_PARSE bp_parms[8];
7923 API_PARSE * b1_config;
7924 API_PARSE * b2_config;
7925 API_PARSE b2_config_parms[8];
7926 API_PARSE * b3_config;
7927 API_PARSE b3_config_parms[6];
7928 API_PARSE global_config[2];
7929
7930 static byte llc[3] = {2,0,0};
7931 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7932 static byte nlc[256];
7933 static byte lli[12] = {1,1};
7934
7935 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7936 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7937
7938 const byte llc3[] = {4,3,2,2,6,6,0};
7939 const byte header[] = {0,2,3,3,0,0,0};
7940
7941 for(i=0;i<8;i++) bp_parms[i].length = 0;
7942 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7943 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7944
7945 lli[0] = 1;
7946 lli[1] = 1;
7947 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7948 lli[1] |= 2;
7949 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7950 lli[1] |= 4;
7951
7952 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7953 lli[1] |= 0x10;
7954 if (plci->rx_dma_descriptor <= 0) {
7955 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7956 if (plci->rx_dma_descriptor >= 0)
7957 plci->rx_dma_descriptor++;
7958 }
7959 if (plci->rx_dma_descriptor > 0) {
7960 lli[0] = 6;
7961 lli[1] |= 0x40;
7962 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7963 lli[3] = (byte)plci->rx_dma_magic;
7964 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7965 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7966 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7967 }
7968 }
7969
7970 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7971 lli[1] |= 0x20;
7972 }
7973
7974 dbug(1,dprintf("add_b23"));
7975 api_save_msg(bp, "s", &plci->B_protocol);
7976
7977 if(!bp->length && plci->tel)
7978 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007979 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007980 dbug(1,dprintf("Default adv.Nl"));
7981 add_p(plci,LLI,lli);
7982 plci->B2_prot = 1 /*XPARENT*/;
7983 plci->B3_prot = 0 /*XPARENT*/;
7984 llc[1] = 2;
7985 llc[2] = 4;
7986 add_p(plci, LLC, llc);
7987 dlc[0] = 2;
7988 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7989 add_p(plci, DLC, dlc);
7990 return 0;
7991 }
7992
7993 if(!bp->length) /*default*/
7994 {
7995 dbug(1,dprintf("ret default"));
7996 add_p(plci,LLI,lli);
7997 plci->B2_prot = 0 /*X.75 */;
7998 plci->B3_prot = 0 /*XPARENT*/;
7999 llc[1] = 1;
8000 llc[2] = 4;
8001 add_p(plci, LLC, llc);
8002 dlc[0] = 2;
8003 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8004 add_p(plci, DLC, dlc);
8005 return 0;
8006 }
8007 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8008 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8009
8010 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8011 {
8012 bp_parms[6].length = 0;
8013 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8014 {
8015 dbug(1,dprintf("b-form.!"));
8016 return _WRONG_MESSAGE_FORMAT;
8017 }
8018 }
8019 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8020 {
8021 dbug(1,dprintf("b-form.!"));
8022 return _WRONG_MESSAGE_FORMAT;
8023 }
8024
8025 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8026 {
8027 if(GET_WORD(bp_parms[1].info)!=1
8028 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008029 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008030 }
8031 else if(plci->tel) return _B2_NOT_SUPPORTED;
8032
8033
8034 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8035 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8036 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8037 {
8038 add_p(plci,LLI,lli);
8039 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8040 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8041 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8042 llc[2] = 4;
8043 add_p(plci, LLC, llc);
8044 dlc[0] = 2;
8045 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8046 dlc[3] = 3; /* Addr A */
8047 dlc[4] = 1; /* Addr B */
8048 dlc[5] = 7; /* modulo mode */
8049 dlc[6] = 7; /* window size */
8050 dlc[7] = 0; /* XID len Lo */
8051 dlc[8] = 0; /* XID len Hi */
8052 for (i = 0; i < bp_parms[4].length; i++)
8053 dlc[9+i] = bp_parms[4].info[1+i];
8054 dlc[0] = (byte)(8 + bp_parms[4].length);
8055 add_p(plci, DLC, dlc);
8056 for (i = 0; i < bp_parms[5].length; i++)
8057 nlc[1+i] = bp_parms[5].info[1+i];
8058 nlc[0] = (byte)(bp_parms[5].length);
8059 add_p(plci, NLC, nlc);
8060 return 0;
8061 }
8062
8063
8064
8065 if ((GET_WORD(bp_parms[1].info) >= 32)
8066 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8067 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8068 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8069
8070 {
8071 return _B2_NOT_SUPPORTED;
8072 }
8073 if ((GET_WORD(bp_parms[2].info) >= 32)
8074 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8075 {
8076 return _B3_NOT_SUPPORTED;
8077 }
8078 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8079 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8080 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8081 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8082 {
8083 return (add_modem_b23 (plci, bp_parms));
8084 }
8085
8086 add_p(plci,LLI,lli);
8087
8088 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8089 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8090 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8091
8092 if(bp_parms[6].length)
8093 {
8094 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8095 {
8096 return _WRONG_MESSAGE_FORMAT;
8097 }
8098 switch(GET_WORD(global_config[0].info))
8099 {
8100 case 1:
8101 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8102 break;
8103 case 2:
8104 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8105 break;
8106 }
8107 }
8108 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8109
8110
8111 if (plci->B2_prot == B2_PIAFS)
8112 llc[1] = PIAFS_CRC;
8113 else
8114/* IMPLEMENT_PIAFS */
8115 {
8116 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8117 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8118 }
8119 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8120
8121 add_p(plci, LLC, llc);
8122
8123 dlc[0] = 2;
8124 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8125 header[GET_WORD(bp_parms[2].info)]);
8126
8127 b1_config = &bp_parms[3];
8128 nlc[0] = 0;
8129 if(plci->B3_prot == 4
8130 || plci->B3_prot == 5)
8131 {
8132 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8133 nlc[0] = sizeof(T30_INFO);
8134 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8135 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8136 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8137 if(b1_config->length>=2)
8138 {
8139 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8140 }
8141 }
8142 b2_config = &bp_parms[4];
8143
8144
8145 if (llc[1] == PIAFS_CRC)
8146 {
8147 if (plci->B3_prot != B3_TRANSPARENT)
8148 {
8149 return _B_STACK_NOT_SUPPORTED;
8150 }
8151 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8152 return _WRONG_MESSAGE_FORMAT;
8153 }
8154 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8155 dlc[3] = 0; /* Addr A */
8156 dlc[4] = 0; /* Addr B */
8157 dlc[5] = 0; /* modulo mode */
8158 dlc[6] = 0; /* window size */
8159 if (b2_config->length >= 7){
8160 dlc[ 7] = 7;
8161 dlc[ 8] = 0;
8162 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8163 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8164 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8165 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8166 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8167 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8168 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8169 dlc[ 0] = 15;
8170 if(b2_config->length >= 8) { /* PIAFS control abilities */
8171 dlc[ 7] = 10;
8172 dlc[16] = 2; /* Length of PIAFS extention */
8173 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8174 dlc[18] = b2_config_parms[4].info[0]; /* value */
8175 dlc[ 0] = 18;
8176 }
8177 }
8178 else /* default values, 64K, variable, no compression */
8179 {
8180 dlc[ 7] = 7;
8181 dlc[ 8] = 0;
8182 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8183 dlc[10] = 0x03; /* V.42bis P0 */
8184 dlc[11] = 0; /* V.42bis P0 */
8185 dlc[12] = 0; /* V.42bis P1 */
8186 dlc[13] = 0; /* V.42bis P1 */
8187 dlc[14] = 0; /* V.42bis P2 */
8188 dlc[15] = 0; /* V.42bis P2 */
8189 dlc[ 0] = 15;
8190 }
8191 add_p(plci, DLC, dlc);
8192 }
8193 else
8194
8195 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8196 {
8197 if (plci->B3_prot != B3_TRANSPARENT)
8198 return _B_STACK_NOT_SUPPORTED;
8199
8200 dlc[0] = 6;
8201 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8202 dlc[3] = 0x08;
8203 dlc[4] = 0x01;
8204 dlc[5] = 127;
8205 dlc[6] = 7;
8206 if (b2_config->length != 0)
8207 {
8208 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8209 return _WRONG_MESSAGE_FORMAT;
8210 }
8211 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8212 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8213 if (b2_config->info[3] != 128)
8214 {
8215 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8216 return _B2_PARM_NOT_SUPPORTED;
8217 }
8218 dlc[5] = (byte)(b2_config->info[3] - 1);
8219 dlc[6] = b2_config->info[4];
8220 if(llc[1]==V120_V42BIS){
8221 if (b2_config->length >= 10){
8222 dlc[ 7] = 6;
8223 dlc[ 8] = 0;
8224 dlc[ 9] = b2_config_parms[4].info[0];
8225 dlc[10] = b2_config_parms[4].info[1];
8226 dlc[11] = b2_config_parms[5].info[0];
8227 dlc[12] = b2_config_parms[5].info[1];
8228 dlc[13] = b2_config_parms[6].info[0];
8229 dlc[14] = b2_config_parms[6].info[1];
8230 dlc[ 0] = 14;
8231 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8232 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8233 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8234 }
8235 else {
8236 dlc[ 6] = 14;
8237 }
8238 }
8239 }
8240 }
8241 else
8242 {
8243 if(b2_config->length)
8244 {
8245 dbug(1,dprintf("B2-Config"));
8246 if(llc[1]==X75_V42BIS){
8247 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8248 {
8249 return _WRONG_MESSAGE_FORMAT;
8250 }
8251 }
8252 else {
8253 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8254 {
8255 return _WRONG_MESSAGE_FORMAT;
8256 }
8257 }
8258 /* if B2 Protocol is LAPD, b2_config structure is different */
8259 if(llc[1]==6)
8260 {
8261 dlc[0] = 4;
8262 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8263 else dlc[2] = 0x01;
8264 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8265 {
8266 SAPI = b2_config->info[2]; /* SAPI */
8267 }
8268 dlc[1] = SAPI;
8269 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8270 {
8271 dlc[3] = 127; /* Mode */
8272 }
8273 else
8274 {
8275 dlc[3] = 7; /* Mode */
8276 }
8277
8278 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8279 else dlc[4] = 1;
8280 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8281 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8282 }
8283 else
8284 {
8285 dlc[0] = (byte)(b2_config_parms[4].length+6);
8286 dlc[3] = b2_config->info[1];
8287 dlc[4] = b2_config->info[2];
8288 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8289 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8290 return _B2_PARM_NOT_SUPPORTED;
8291 }
8292
8293 dlc[5] = (byte)(b2_config->info[3]-1);
8294 dlc[6] = b2_config->info[4];
8295 if(dlc[6]>dlc[5]){
8296 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]));
8297 return _B2_PARM_NOT_SUPPORTED;
8298 }
8299
8300 if(llc[1]==X75_V42BIS) {
8301 if (b2_config->length >= 10){
8302 dlc[ 7] = 6;
8303 dlc[ 8] = 0;
8304 dlc[ 9] = b2_config_parms[4].info[0];
8305 dlc[10] = b2_config_parms[4].info[1];
8306 dlc[11] = b2_config_parms[5].info[0];
8307 dlc[12] = b2_config_parms[5].info[1];
8308 dlc[13] = b2_config_parms[6].info[0];
8309 dlc[14] = b2_config_parms[6].info[1];
8310 dlc[ 0] = 14;
8311 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8312 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8313 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8314 }
8315 else {
8316 dlc[ 6] = 14;
8317 }
8318
8319 }
8320 else {
8321 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8322 for(i=0; i<b2_config_parms[4].length; i++)
8323 dlc[11+i] = b2_config_parms[4].info[1+i];
8324 }
8325 }
8326 }
8327 }
8328 add_p(plci, DLC, dlc);
8329
8330 b3_config = &bp_parms[5];
8331 if(b3_config->length)
8332 {
8333 if(plci->B3_prot == 4
8334 || plci->B3_prot == 5)
8335 {
8336 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8337 {
8338 return _WRONG_MESSAGE_FORMAT;
8339 }
8340 i = GET_WORD((byte *)(b3_config_parms[0].info));
8341 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8342 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8343 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8344 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8345 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8346 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8347 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8348 {
8349
8350 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8351 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8352 {
8353 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8354 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8355 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8356 }
8357
8358 ((T30_INFO *)&nlc[1])->recording_properties =
8359 T30_RECORDING_WIDTH_ISO_A3 |
8360 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8361 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8362 }
8363 if(plci->B3_prot == 5)
8364 {
8365 if (i & 0x0002) /* Accept incoming fax-polling requests */
8366 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8367 if (i & 0x2000) /* Do not use MR compression */
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8369 if (i & 0x4000) /* Do not use MMR compression */
8370 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8371 if (i & 0x8000) /* Do not use ECM */
8372 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8373 if (plci->fax_connect_info_length != 0)
8374 {
8375 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8376 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8377 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8378 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8379 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8380 }
8381 }
8382 /* copy station id to NLC */
8383 for(i=0; i<20; i++)
8384 {
8385 if(i<b3_config_parms[2].length)
8386 {
8387 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8388 }
8389 else
8390 {
8391 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8392 }
8393 }
8394 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8395 /* copy head line to NLC */
8396 if(b3_config_parms[3].length)
8397 {
8398
8399 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8400 if (pos != 0)
8401 {
8402 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8403 pos = 0;
8404 else
8405 {
8406 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8407 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8408 len = (byte)b3_config_parms[2].length;
8409 if (len > 20)
8410 len = 20;
8411 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8412 {
8413 for (i = 0; i < len; i++)
8414 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8415 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8416 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8417 }
8418 }
8419 }
8420
8421 len = (byte)b3_config_parms[3].length;
8422 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8423 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8424 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8425 nlc[0] += (byte)(pos + len);
8426 for (i = 0; i < len; i++)
8427 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8428 }
8429 else
8430 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8431
8432 plci->nsf_control_bits = 0;
8433 if(plci->B3_prot == 5)
8434 {
8435 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8436 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8437 {
8438 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8439 }
8440 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8441 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8442 {
8443 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8444 }
8445 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8446 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8447 {
8448 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8449 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8450 {
8451 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8452 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8453 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8454 }
8455 len = nlc[0];
8456 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8457 if (pos < plci->fax_connect_info_length)
8458 {
8459 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8460 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8461 }
8462 else
8463 nlc[++len] = 0;
8464 if (pos < plci->fax_connect_info_length)
8465 {
8466 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8467 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8468 }
8469 else
8470 nlc[++len] = 0;
8471 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8472 & (1L << PRIVATE_FAX_NONSTANDARD))
8473 {
8474 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8475 {
8476 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8477 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8478 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8479 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8480 }
8481 else
8482 {
8483 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8484 {
8485 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8486 nlc[++len] = 0;
8487 }
8488 else
8489 {
8490 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8491 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8492 nlc[++len] = (byte)(b3_config_parms[4].length);
8493 for (i = 0; i < b3_config_parms[4].length; i++)
8494 nlc[++len] = b3_config_parms[4].info[1+i];
8495 }
8496 }
8497 }
8498 nlc[0] = len;
8499 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8500 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8501 {
8502 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8503 }
8504 }
8505 }
8506
8507 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8508 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8509 for (i = 0; i < len; i++)
8510 plci->fax_connect_info_buffer[i] = nlc[1+i];
8511 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8512 i += ((T30_INFO *)&nlc[1])->head_line_len;
8513 while (i < nlc[0])
8514 plci->fax_connect_info_buffer[len++] = nlc[++i];
8515 plci->fax_connect_info_length = len;
8516 }
8517 else
8518 {
8519 nlc[0] = 14;
8520 if(b3_config->length!=16)
8521 return _B3_PARM_NOT_SUPPORTED;
8522 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8523 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8524 return _B3_PARM_NOT_SUPPORTED;
8525 nlc[13] = b3_config->info[13];
8526 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8527 return _B3_PARM_NOT_SUPPORTED;
8528 nlc[14] = b3_config->info[15];
8529 }
8530 }
8531 else
8532 {
8533 if (plci->B3_prot == 4
8534 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8535 }
8536 add_p(plci, NLC, nlc);
8537 return 0;
8538}
8539
8540/*----------------------------------------------------------------*/
8541/* make the same as add_b23, but only for the modem related */
8542/* L2 and L3 B-Chan protocol. */
8543/* */
8544/* Enabled L2 and L3 Configurations: */
8545/* If L1 == Modem all negotiation */
8546/* only L2 == Modem with full negotiation is allowed */
8547/* If L1 == Modem async or sync */
8548/* only L2 == Transparent is allowed */
8549/* L3 == Modem or L3 == Transparent are allowed */
8550/* B2 Configuration for modem: */
8551/* word : enable/disable compression, bitoptions */
8552/* B3 Configuration for modem: */
8553/* empty */
8554/*----------------------------------------------------------------*/
8555static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8556{
8557 static byte lli[12] = {1,1};
8558 static byte llc[3] = {2,0,0};
8559 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8560 API_PARSE mdm_config[2];
8561 word i;
8562 word b2_config = 0;
8563
8564 for(i=0;i<2;i++) mdm_config[i].length = 0;
8565 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8566
8567 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8568 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8569 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8570 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8571 {
8572 return (_B_STACK_NOT_SUPPORTED);
8573 }
8574 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8575 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8576 {
8577 return (_B_STACK_NOT_SUPPORTED);
8578 }
8579
8580 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8581 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8582
8583 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8584 {
8585 if (api_parse (&bp_parms[4].info[1],
8586 (word)bp_parms[4].length, "w",
8587 mdm_config))
8588 {
8589 return (_WRONG_MESSAGE_FORMAT);
8590 }
8591 b2_config = GET_WORD(mdm_config[0].info);
8592 }
8593
8594 /* OK, L2 is modem */
8595
8596 lli[0] = 1;
8597 lli[1] = 1;
8598 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8599 lli[1] |= 2;
8600 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8601 lli[1] |= 4;
8602
8603 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8604 lli[1] |= 0x10;
8605 if (plci->rx_dma_descriptor <= 0) {
8606 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8607 if (plci->rx_dma_descriptor >= 0)
8608 plci->rx_dma_descriptor++;
8609 }
8610 if (plci->rx_dma_descriptor > 0) {
8611 lli[1] |= 0x40;
8612 lli[0] = 6;
8613 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8614 lli[3] = (byte)plci->rx_dma_magic;
8615 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8616 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8617 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8618 }
8619 }
8620
8621 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8622 lli[1] |= 0x20;
8623 }
8624
8625 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8626 /*V42*/ 10 : /*V42_IN*/ 9;
8627 llc[2] = 4; /* pass L3 always transparent */
8628 add_p(plci, LLI, lli);
8629 add_p(plci, LLC, llc);
8630 i = 1;
8631 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8632 i += 2;
8633 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8634 {
8635 if (bp_parms[4].length)
8636 {
8637 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8638 dlc[i++] = 3; /* Addr A */
8639 dlc[i++] = 1; /* Addr B */
8640 dlc[i++] = 7; /* modulo mode */
8641 dlc[i++] = 7; /* window size */
8642 dlc[i++] = 0; /* XID len Lo */
8643 dlc[i++] = 0; /* XID len Hi */
8644
8645 if (b2_config & MDM_B2_DISABLE_V42bis)
8646 {
8647 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8648 }
8649 if (b2_config & MDM_B2_DISABLE_MNP)
8650 {
8651 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8652 }
8653 if (b2_config & MDM_B2_DISABLE_TRANS)
8654 {
8655 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8656 }
8657 if (b2_config & MDM_B2_DISABLE_V42)
8658 {
8659 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8660 }
8661 if (b2_config & MDM_B2_DISABLE_COMP)
8662 {
8663 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8664 }
8665 i++;
8666 }
8667 }
8668 else
8669 {
8670 dlc[i++] = 3; /* Addr A */
8671 dlc[i++] = 1; /* Addr B */
8672 dlc[i++] = 7; /* modulo mode */
8673 dlc[i++] = 7; /* window size */
8674 dlc[i++] = 0; /* XID len Lo */
8675 dlc[i++] = 0; /* XID len Hi */
8676 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8677 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8678 DLC_MODEMPROT_DISABLE_V42_DETECT |
8679 DLC_MODEMPROT_DISABLE_COMPRESSION;
8680 }
8681 dlc[0] = (byte)(i - 1);
8682/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8683 add_p(plci, DLC, dlc);
8684 return (0);
8685}
8686
8687
8688/*------------------------------------------------------------------*/
8689/* send a request for the signaling entity */
8690/*------------------------------------------------------------------*/
8691
8692void sig_req(PLCI * plci, byte req, byte Id)
8693{
8694 if(!plci) return;
8695 if(plci->adapter->adapter_disabled) return;
8696 dbug(1,dprintf("sig_req(%x)",req));
8697 if (req == REMOVE)
8698 plci->sig_remove_id = plci->Sig.Id;
8699 if(plci->req_in==plci->req_in_start) {
8700 plci->req_in +=2;
8701 plci->RBuffer[plci->req_in++] = 0;
8702 }
8703 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8704 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8705 plci->RBuffer[plci->req_in++] = req; /* request */
8706 plci->RBuffer[plci->req_in++] = 0; /* channel */
8707 plci->req_in_start = plci->req_in;
8708}
8709
8710/*------------------------------------------------------------------*/
8711/* send a request for the network layer entity */
8712/*------------------------------------------------------------------*/
8713
Hannes Eder4ee59d52008-12-16 01:17:33 -08008714static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008715{
8716 if(!plci) return;
8717 if(plci->adapter->adapter_disabled) return;
8718 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8719 if (req == REMOVE)
8720 {
8721 plci->nl_remove_id = plci->NL.Id;
8722 ncci_remove (plci, 0, (byte)(ncci != 0));
8723 ncci = 0;
8724 }
8725 if(plci->req_in==plci->req_in_start) {
8726 plci->req_in +=2;
8727 plci->RBuffer[plci->req_in++] = 0;
8728 }
8729 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8730 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8731 plci->RBuffer[plci->req_in++] = req; /* request */
8732 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8733 plci->req_in_start = plci->req_in;
8734}
8735
Hannes Eder4ee59d52008-12-16 01:17:33 -08008736static void send_req(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008737{
8738 ENTITY * e;
8739 word l;
8740/* word i; */
8741
8742 if(!plci) return;
8743 if(plci->adapter->adapter_disabled) return;
8744 channel_xmit_xon (plci);
8745
8746 /* if nothing to do, return */
8747 if(plci->req_in==plci->req_out) return;
8748 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8749
8750 if(plci->nl_req || plci->sig_req) return;
8751
8752 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8753 plci->req_out += 2;
8754 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8755 plci->req_out += l;
8756 if(plci->RBuffer[plci->req_out]==1)
8757 {
8758 e = &plci->NL;
8759 plci->req_out++;
8760 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8761 e->ReqCh = plci->RBuffer[plci->req_out++];
8762 if(!(e->Id & 0x1f))
8763 {
8764 e->Id = NL_ID;
8765 plci->RBuffer[plci->req_out-4] = CAI;
8766 plci->RBuffer[plci->req_out-3] = 1;
8767 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8768 plci->RBuffer[plci->req_out-1] = 0;
8769 l+=3;
8770 plci->nl_global_req = plci->nl_req;
8771 }
8772 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8773 }
8774 else
8775 {
8776 e = &plci->Sig;
8777 if(plci->RBuffer[plci->req_out])
8778 e->Id = plci->RBuffer[plci->req_out];
8779 plci->req_out++;
8780 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8781 e->ReqCh = plci->RBuffer[plci->req_out++];
8782 if(!(e->Id & 0x1f))
8783 plci->sig_global_req = plci->sig_req;
8784 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8785 }
8786 plci->XData[0].PLength = l;
8787 e->X = plci->XData;
8788 plci->adapter->request(e);
8789 dbug(1,dprintf("send_ok"));
8790}
8791
8792void send_data(PLCI * plci)
8793{
8794 DIVA_CAPI_ADAPTER * a;
8795 DATA_B3_DESC * data;
8796 NCCI *ncci_ptr;
8797 word ncci;
8798
8799 if (!plci->nl_req && plci->ncci_ring_list)
8800 {
8801 a = plci->adapter;
8802 ncci = plci->ncci_ring_list;
8803 do
8804 {
8805 ncci = a->ncci_next[ncci];
8806 ncci_ptr = &(a->ncci[ncci]);
8807 if (!(a->ncci_ch[ncci]
8808 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8809 {
8810 if (ncci_ptr->data_pending)
8811 {
8812 if ((a->ncci_state[ncci] == CONNECTED)
8813 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8814 || (plci->send_disc == ncci))
8815 {
8816 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8817 if ((plci->B2_prot == B2_V120_ASYNC)
8818 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8819 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8820 {
8821 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8822 plci->NData[1].PLength = data->Length;
8823 if (data->Flags & 0x10)
8824 plci->NData[0].P = v120_break_header;
8825 else
8826 plci->NData[0].P = v120_default_header;
8827 plci->NData[0].PLength = 1 ;
8828 plci->NL.XNum = 2;
8829 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8830 }
8831 else
8832 {
8833 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8834 plci->NData[0].PLength = data->Length;
8835 if (data->Flags & 0x10)
8836 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8837
8838 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8839 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8840
8841 else
8842 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8843 }
8844 plci->NL.X = plci->NData;
8845 plci->NL.ReqCh = a->ncci_ch[ncci];
8846 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008847 plci->data_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008848 plci->data_sent_ptr = data->P;
8849 a->request(&plci->NL);
8850 }
8851 else {
8852 cleanup_ncci_data (plci, ncci);
8853 }
8854 }
8855 else if (plci->send_disc == ncci)
8856 {
8857 /* dprintf("N_DISC"); */
8858 plci->NData[0].PLength = 0;
8859 plci->NL.ReqCh = a->ncci_ch[ncci];
8860 plci->NL.Req = plci->nl_req = N_DISC;
8861 a->request(&plci->NL);
8862 plci->command = _DISCONNECT_B3_R;
8863 plci->send_disc = 0;
8864 }
8865 }
8866 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8867 plci->ncci_ring_list = ncci;
8868 }
8869}
8870
Hannes Eder4ee59d52008-12-16 01:17:33 -08008871static void listen_check(DIVA_CAPI_ADAPTER *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008872{
8873 word i,j;
8874 PLCI * plci;
8875 byte activnotifiedcalls = 0;
8876
8877 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8878 if (!remove_started && !a->adapter_disabled)
8879 {
8880 for(i=0;i<a->max_plci;i++)
8881 {
8882 plci = &(a->plci[i]);
8883 if(plci->notifiedcall) activnotifiedcalls++;
8884 }
8885 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8886
8887 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8888 if((j=get_plci(a))) {
8889 a->listen_active++;
8890 plci = &a->plci[j-1];
8891 plci->State = LISTENING;
8892
8893 add_p(plci,OAD,"\x01\xfd");
8894
8895 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8896
8897 add_p(plci,CAI,"\x01\xc0");
8898 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8899 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8900 add_p(plci,SHIFT|6,NULL);
8901 add_p(plci,SIN,"\x02\x00\x00");
8902 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8903 sig_req(plci,ASSIGN,DSIG_ID);
8904 send_req(plci);
8905 }
8906 }
8907 }
8908}
8909
8910/*------------------------------------------------------------------*/
8911/* functions for all parameters sent in INDs */
8912/*------------------------------------------------------------------*/
8913
Hannes Eder4ee59d52008-12-16 01:17:33 -08008914static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008915{
8916 word ploc; /* points to current location within packet */
8917 byte w;
8918 byte wlen;
8919 byte codeset,lock;
8920 byte * in;
8921 word i;
8922 word code;
8923 word mIEindex = 0;
8924 ploc = 0;
8925 codeset = 0;
8926 lock = 0;
8927
8928 in = plci->Sig.RBuffer->P;
8929 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8930 { /* element but parms array is larger */
8931 parms[i] = (byte *)"";
8932 }
8933 for(i=0; i<multiIEsize; i++)
8934 {
8935 parms[i] = (byte *)"";
8936 }
8937
8938 while(ploc<plci->Sig.RBuffer->length-1) {
8939
8940 /* read information element id and length */
8941 w = in[ploc];
8942
8943 if(w & 0x80) {
8944/* w &=0xf0; removed, cannot detect congestion levels */
8945/* upper 4 bit masked with w==SHIFT now */
8946 wlen = 0;
8947 }
8948 else {
8949 wlen = (byte)(in[ploc+1]+1);
8950 }
8951 /* check if length valid (not exceeding end of packet) */
8952 if((ploc+wlen) > 270) return ;
8953 if(lock & 0x80) lock &=0x7f;
8954 else codeset = lock;
8955
8956 if((w&0xf0)==SHIFT) {
8957 codeset = in[ploc];
8958 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8959 codeset &=7;
8960 lock |=0x80;
8961 }
8962 else {
8963 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8964 else code = w;
8965 code |= (codeset<<8);
8966
8967 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8968
8969 if(i<parms_id[0]+1) {
8970 if(!multiIEsize) { /* with multiIEs use next field index, */
8971 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8972 }
8973
8974 parms[mIEindex] = &in[ploc+1];
8975 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8976 if(parms_id[i]==OAD
8977 || parms_id[i]==CONN_NR
8978 || parms_id[i]==CAD) {
8979 if(in[ploc+2] &0x80) {
8980 in[ploc+0] = (byte)(in[ploc+1]+1);
8981 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8982 in[ploc+2] = 0x80;
8983 parms[mIEindex] = &in[ploc];
8984 }
8985 }
8986 mIEindex++; /* effects multiIEs only */
8987 }
8988 }
8989
8990 ploc +=(wlen+1);
8991 }
8992 return ;
8993}
8994
8995/*------------------------------------------------------------------*/
8996/* try to match a cip from received BC and HLC */
8997/*------------------------------------------------------------------*/
8998
Hannes Eder4ee59d52008-12-16 01:17:33 -08008999static byte ie_compare(byte *ie1, byte *ie2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009000{
9001 word i;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009002 if(!ie1 || ! ie2) return false;
9003 if(!ie1[0]) return false;
9004 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9005 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009006}
9007
Hannes Eder4ee59d52008-12-16 01:17:33 -08009008static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009009{
9010 word i;
9011 word j;
9012
9013 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9014
9015 for(j=16;j<29 &&
9016 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9017 if(j==29) return i;
9018 return j;
9019}
9020
9021
9022static byte AddInfo(byte **add_i,
9023 byte **fty_i,
9024 byte *esc_chi,
9025 byte *facility)
9026{
9027 byte i;
9028 byte j;
9029 byte k;
9030 byte flen;
9031 byte len=0;
9032 /* facility is a nested structure */
9033 /* FTY can be more than once */
9034
Roel Kluin3eb1a6f2008-02-06 01:38:30 -08009035 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
Linus Torvalds1da177e2005-04-16 15:20:36 -07009036 {
9037 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9038 }
9039
9040 else
9041 {
9042 add_i[0] = (byte *)"";
9043 }
9044 if(!fty_i[0][0])
9045 {
9046 add_i[3] = (byte *)"";
9047 }
9048 else
9049 { /* facility array found */
9050 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9051 {
9052 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9053 len += fty_i[i][0];
9054 len += 2;
9055 flen=fty_i[i][0];
9056 facility[j++]=0x1c; /* copy fac IE */
9057 for(k=0;k<=flen;k++,j++)
9058 {
9059 facility[j]=fty_i[i][k];
9060/* dbug(1,dprintf("%x ",facility[j])); */
9061 }
9062 }
9063 facility[0] = len;
9064 add_i[3] = facility;
9065 }
9066/* dbug(1,dprintf("FacArrLen=%d ",len)); */
9067 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9068 len += 4; /* calculate length of all */
9069 return(len);
9070}
9071
9072/*------------------------------------------------------------------*/
9073/* voice and codec features */
9074/*------------------------------------------------------------------*/
9075
Hannes Eder4ee59d52008-12-16 01:17:33 -08009076static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009077{
9078 byte voice_chi[] = "\x02\x18\x01";
9079 byte channel;
9080
9081 channel = chi[chi[0]]&0x3;
9082 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9083 voice_chi[2] = (channel) ? channel : 1;
9084 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9085 add_p(plci,ESC,voice_chi); /* Channel */
9086 sig_req(plci,TEL_CTRL,0);
9087 send_req(plci);
9088 if(a->AdvSignalPLCI)
9089 {
9090 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9091 }
9092}
9093
Hannes Eder4ee59d52008-12-16 01:17:33 -08009094static void VoiceChannelOff(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009095{
9096 dbug(1,dprintf("ExtDevOFF"));
9097 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9098 sig_req(plci,TEL_CTRL,0);
9099 send_req(plci);
9100 if(plci->adapter->AdvSignalPLCI)
9101 {
9102 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9103 }
9104}
9105
9106
Hannes Eder4ee59d52008-12-16 01:17:33 -08009107static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9108 byte hook_listen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009109{
9110 word j;
9111 PLCI *splci;
9112
9113 /* check if hardware supports handset with hook states (adv.codec) */
9114 /* or if just a on board codec is supported */
9115 /* the advanced codec plci is just for internal use */
9116
9117 /* diva Pro with on-board codec: */
9118 if(a->profile.Global_Options & HANDSET)
9119 {
9120 /* new call, but hook states are already signalled */
9121 if(a->AdvCodecFLAG)
9122 {
9123 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9124 {
9125 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9126 return 0x2001; /* codec in use by another application */
9127 }
Harvey Harrisondd58c0d2008-04-28 02:14:39 -07009128 if(plci!=NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009129 {
9130 a->AdvSignalPLCI = plci;
9131 plci->tel=ADV_VOICE;
9132 }
9133 return 0; /* adv codec still used */
9134 }
9135 if((j=get_plci(a)))
9136 {
9137 splci = &a->plci[j-1];
9138 splci->tel = CODEC_PERMANENT;
9139 /* hook_listen indicates if a facility_req with handset/hook support */
9140 /* was sent. Otherwise if just a call on an external device was made */
9141 /* the codec will be used but the hook info will be discarded (just */
9142 /* the external controller is in use */
9143 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9144 else
9145 {
9146 splci->State = ADVANCED_VOICE_NOSIG;
9147 if(plci)
9148 {
9149 plci->spoofed_msg = SPOOFING_REQUIRED;
9150 }
9151 /* indicate D-ch connect if */
9152 } /* codec is connected OK */
Harvey Harrisondd58c0d2008-04-28 02:14:39 -07009153 if(plci!=NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009154 {
9155 a->AdvSignalPLCI = plci;
9156 plci->tel=ADV_VOICE;
9157 }
9158 a->AdvSignalAppl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009159 a->AdvCodecFLAG = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009160 a->AdvCodecPLCI = splci;
9161 add_p(splci,CAI,"\x01\x15");
9162 add_p(splci,LLI,"\x01\x00");
9163 add_p(splci,ESC,"\x02\x18\x00");
9164 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9165 splci->internal_command = PERM_COD_ASSIGN;
9166 dbug(1,dprintf("Codec Assign"));
9167 sig_req(splci,ASSIGN,DSIG_ID);
9168 send_req(splci);
9169 }
9170 else
9171 {
9172 return 0x2001; /* wrong state, no more plcis */
9173 }
9174 }
9175 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9176 {
9177 if(hook_listen) return 0x300B; /* Facility not supported */
9178 /* no hook with SCOM */
Harvey Harrisondd58c0d2008-04-28 02:14:39 -07009179 if(plci!=NULL) plci->tel = CODEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009180 dbug(1,dprintf("S/SCOM codec"));
9181 /* first time we use the scom-s codec we must shut down the internal */
9182 /* handset application of the card. This can be done by an assign with */
9183 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9184 if(!a->scom_appl_disable){
9185 if((j=get_plci(a))) {
9186 splci = &a->plci[j-1];
9187 add_p(splci,CAI,"\x01\x80");
9188 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9189 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9190 send_req(splci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009191 a->scom_appl_disable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009192 }
9193 else{
9194 return 0x2001; /* wrong state, no more plcis */
9195 }
9196 }
9197 }
9198 else return 0x300B; /* Facility not supported */
9199
9200 return 0;
9201}
9202
9203
Hannes Eder4ee59d52008-12-16 01:17:33 -08009204static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009205{
9206
9207 dbug(1,dprintf("CodecIdCheck"));
9208
9209 if(a->AdvSignalPLCI == plci)
9210 {
9211 dbug(1,dprintf("PLCI owns codec"));
9212 VoiceChannelOff(a->AdvCodecPLCI);
9213 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9214 {
9215 dbug(1,dprintf("remove temp codec PLCI"));
9216 plci_remove(a->AdvCodecPLCI);
9217 a->AdvCodecFLAG = 0;
9218 a->AdvCodecPLCI = NULL;
9219 a->AdvSignalAppl = NULL;
9220 }
9221 a->AdvSignalPLCI = NULL;
9222 }
9223}
9224
9225/* -------------------------------------------------------------------
9226 Ask for physical address of card on PCI bus
9227 ------------------------------------------------------------------- */
9228static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9229 IDI_SYNC_REQ * preq) {
9230 a->sdram_bar = 0;
9231 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9232 ENTITY * e = (ENTITY *)preq;
9233
9234 e->user[0] = a->Id - 1;
9235 preq->xdi_sdram_bar.info.bar = 0;
9236 preq->xdi_sdram_bar.Req = 0;
9237 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9238
9239 (*(a->request))(e);
9240
9241 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9242 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9243 }
9244}
9245
9246/* -------------------------------------------------------------------
9247 Ask XDI about extended features
9248 ------------------------------------------------------------------- */
9249static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9250 IDI_SYNC_REQ * preq;
9251 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9252
9253 char features[4];
9254 preq = (IDI_SYNC_REQ *)&buffer[0];
9255
9256 if (!diva_xdi_extended_features) {
9257 ENTITY * e = (ENTITY *)preq;
9258 diva_xdi_extended_features |= 0x80000000;
9259
9260 e->user[0] = a->Id - 1;
9261 preq->xdi_extended_features.Req = 0;
9262 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9263 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9264 preq->xdi_extended_features.info.features = &features[0];
9265
9266 (*(a->request))(e);
9267
9268 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9269 /*
9270 Check features located in the byte '0'
9271 */
9272 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9273 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9274 }
9275 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9276 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9277 dbug(1,dprintf("XDI provides RxDMA"));
9278 }
9279 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9280 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9281 }
9282 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9283 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9284 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9285 }
9286
9287 }
9288 }
9289
9290 diva_ask_for_xdi_sdram_bar (a, preq);
9291}
9292
9293/*------------------------------------------------------------------*/
9294/* automatic law */
9295/*------------------------------------------------------------------*/
9296/* called from OS specific part after init time to get the Law */
9297/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9298void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9299{
9300 word j;
9301 PLCI *splci;
9302
9303 if(a->automatic_law) {
9304 return;
9305 }
9306 if((j=get_plci(a))) {
9307 diva_get_extended_adapter_features (a);
9308 splci = &a->plci[j-1];
9309 a->automatic_lawPLCI = splci;
9310 a->automatic_law = 1;
9311 add_p(splci,CAI,"\x01\x80");
9312 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9313 splci->internal_command = USELAW_REQ;
9314 splci->command = 0;
9315 splci->number = 0;
9316 sig_req(splci,ASSIGN,DSIG_ID);
9317 send_req(splci);
9318 }
9319}
9320
9321/* called from OS specific part if an application sends an Capi20Release */
9322word CapiRelease(word Id)
9323{
9324 word i, j, appls_found;
9325 PLCI *plci;
9326 APPL *this;
9327 DIVA_CAPI_ADAPTER *a;
9328
9329 if (!Id)
9330 {
9331 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9332 return (_WRONG_APPL_ID);
9333 }
9334
9335 this = &application[Id-1]; /* get application pointer */
9336
9337 for(i=0,appls_found=0; i<max_appl; i++)
9338 {
9339 if(application[i].Id) /* an application has been found */
9340 {
9341 appls_found++;
9342 }
9343 }
9344
9345 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9346 {
9347 a = &adapter[i];
9348 if (a->request)
9349 {
9350 a->Info_Mask[Id-1] = 0;
9351 a->CIP_Mask[Id-1] = 0;
9352 a->Notification_Mask[Id-1] = 0;
9353 a->codec_listen[Id-1] = NULL;
9354 a->requested_options_table[Id-1] = 0;
9355 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9356 { /* with this application */
9357 plci = &a->plci[j];
9358 if(plci->Id) /* if plci owns no application */
9359 { /* it may be not jet connected */
9360 if(plci->State==INC_CON_PENDING
9361 || plci->State==INC_CON_ALERT)
9362 {
9363 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9364 {
9365 clear_c_ind_mask_bit (plci, (word)(Id-1));
9366 if(c_ind_mask_empty (plci))
9367 {
9368 sig_req(plci,HANGUP,0);
9369 send_req(plci);
9370 plci->State = OUTG_DIS_PENDING;
9371 }
9372 }
9373 }
9374 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9375 {
9376 clear_c_ind_mask_bit (plci, (word)(Id-1));
9377 if(c_ind_mask_empty (plci))
9378 {
9379 if(!plci->appl)
9380 {
9381 plci_remove(plci);
9382 plci->State = IDLE;
9383 }
9384 }
9385 }
9386 if(plci->appl==this)
9387 {
9388 plci->appl = NULL;
9389 plci_remove(plci);
9390 plci->State = IDLE;
9391 }
9392 }
9393 }
9394 listen_check(a);
9395
9396 if(a->flag_dynamic_l1_down)
9397 {
9398 if(appls_found==1) /* last application does a capi release */
9399 {
9400 if((j=get_plci(a)))
9401 {
9402 plci = &a->plci[j-1];
9403 plci->command = 0;
9404 add_p(plci,OAD,"\x01\xfd");
9405 add_p(plci,CAI,"\x01\x80");
9406 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9407 add_p(plci,SHIFT|6,NULL);
9408 add_p(plci,SIN,"\x02\x00\x00");
9409 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9410 sig_req(plci,ASSIGN,DSIG_ID);
9411 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9412 sig_req(plci,SIG_CTRL,0);
9413 send_req(plci);
9414 }
9415 }
9416 }
9417 if(a->AdvSignalAppl==this)
9418 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009419 this->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420 if (a->AdvCodecPLCI)
9421 {
9422 plci_remove(a->AdvCodecPLCI);
9423 a->AdvCodecPLCI->tel = 0;
9424 a->AdvCodecPLCI->adv_nl = 0;
9425 }
9426 a->AdvSignalAppl = NULL;
9427 a->AdvSignalPLCI = NULL;
9428 a->AdvCodecFLAG = 0;
9429 a->AdvCodecPLCI = NULL;
9430 }
9431 }
9432 }
9433
9434 this->Id = 0;
9435
9436 return GOOD;
9437}
9438
9439static word plci_remove_check(PLCI *plci)
9440{
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009441 if(!plci) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009442 if(!plci->NL.Id && c_ind_mask_empty (plci))
9443 {
9444 if(plci->Sig.Id == 0xff)
9445 plci->Sig.Id = 0;
9446 if(!plci->Sig.Id)
9447 {
9448 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9449 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9450 if (plci->Id)
9451 {
9452 CodecIdCheck(plci->adapter, plci);
9453 clear_b1_config (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009454 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009455 plci_free_msg_in_queue (plci);
9456 channel_flow_control_remove (plci);
9457 plci->Id = 0;
9458 plci->State = IDLE;
9459 plci->channels = 0;
9460 plci->appl = NULL;
9461 plci->notifiedcall = 0;
9462 }
9463 listen_check(plci->adapter);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009464 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009465 }
9466 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009467 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009468}
9469
9470
9471/*------------------------------------------------------------------*/
9472
9473static byte plci_nl_busy (PLCI *plci)
9474{
9475 /* only applicable for non-multiplexed protocols */
9476 return (plci->nl_req
9477 || (plci->ncci_ring_list
9478 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9479 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9480}
9481
9482
9483/*------------------------------------------------------------------*/
9484/* DTMF facilities */
9485/*------------------------------------------------------------------*/
9486
9487
9488static struct
9489{
9490 byte send_mask;
9491 byte listen_mask;
9492 byte character;
9493 byte code;
9494} dtmf_digit_map[] =
9495{
9496 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9497 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9498 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9499 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9500 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9501 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9502 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9503 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9504 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9505 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9506 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9507 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9508 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9509 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9510 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9511 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9512 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9513 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9514 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9515 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9516
9517 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9518 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9519 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9520 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9521 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9522 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9523 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9524 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9525 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9526 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9527 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9528 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9529 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9530 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9531 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9532 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9533 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9534 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9535 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9536 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9537 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9538 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9539 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9540 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9541 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9542 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9543 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9544 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9545 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9546 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9547 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9548 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9549 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9550 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9551 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9552 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9553 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9554 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9555 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9556 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9557 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9558 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9559 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9560 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9561 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9562 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9563 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9564 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9565 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9566 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9567 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9568 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9569
9570};
9571
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -08009572#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009573
9574
9575static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9576{
9577 word min_digit_duration, min_gap_duration;
9578
9579 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9580 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9581 (char *)(FILE_), __LINE__, enable_mask));
9582
9583 if (enable_mask != 0)
9584 {
9585 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9586 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9587 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9588 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9589 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9590 plci->NData[0].PLength = 5;
9591
9592 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9593 plci->NData[0].PLength += 2;
9594 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9595
9596 }
9597 else
9598 {
9599 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9600 plci->NData[0].PLength = 1;
9601
9602 capidtmf_recv_disable (&(plci->capidtmf_state));
9603
9604 }
9605 plci->NData[0].P = plci->internal_req_buffer;
9606 plci->NL.X = plci->NData;
9607 plci->NL.ReqCh = 0;
9608 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9609 plci->adapter->request (&plci->NL);
9610}
9611
9612
9613static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9614{
9615 word w, i;
9616
9617 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9618 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9619 (char *)(FILE_), __LINE__, digit_count));
9620
9621 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9622 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9623 PUT_WORD (&plci->internal_req_buffer[1], w);
9624 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9625 PUT_WORD (&plci->internal_req_buffer[3], w);
9626 for (i = 0; i < digit_count; i++)
9627 {
9628 w = 0;
9629 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9630 && (digit_buffer[i] != dtmf_digit_map[w].character))
9631 {
9632 w++;
9633 }
9634 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9635 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9636 }
9637 plci->NData[0].PLength = 5 + digit_count;
9638 plci->NData[0].P = plci->internal_req_buffer;
9639 plci->NL.X = plci->NData;
9640 plci->NL.ReqCh = 0;
9641 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9642 plci->adapter->request (&plci->NL);
9643}
9644
9645
9646static void dtmf_rec_clear_config (PLCI *plci)
9647{
9648
9649 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9650 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9651 (char *)(FILE_), __LINE__));
9652
9653 plci->dtmf_rec_active = 0;
9654 plci->dtmf_rec_pulse_ms = 0;
9655 plci->dtmf_rec_pause_ms = 0;
9656
9657 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9658
9659}
9660
9661
9662static void dtmf_send_clear_config (PLCI *plci)
9663{
9664
9665 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9666 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9667 (char *)(FILE_), __LINE__));
9668
9669 plci->dtmf_send_requests = 0;
9670 plci->dtmf_send_pulse_ms = 0;
9671 plci->dtmf_send_pause_ms = 0;
9672}
9673
9674
9675static void dtmf_prepare_switch (dword Id, PLCI *plci)
9676{
9677
9678 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9679 UnMapId (Id), (char *)(FILE_), __LINE__));
9680
9681 while (plci->dtmf_send_requests != 0)
9682 dtmf_confirmation (Id, plci);
9683}
9684
9685
9686static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9687{
9688
9689 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9690 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9691
9692 return (GOOD);
9693}
9694
9695
9696static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9697{
9698 word Info;
9699
9700 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9701 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9702
9703 Info = GOOD;
9704 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9705 {
9706 switch (plci->adjust_b_state)
9707 {
9708 case ADJUST_B_RESTORE_DTMF_1:
9709 plci->internal_command = plci->adjust_b_command;
9710 if (plci_nl_busy (plci))
9711 {
9712 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9713 break;
9714 }
9715 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9716 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9717 break;
9718 case ADJUST_B_RESTORE_DTMF_2:
9719 if ((Rc != OK) && (Rc != OK_FC))
9720 {
9721 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9722 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9723 Info = _WRONG_STATE;
9724 break;
9725 }
9726 break;
9727 }
9728 }
9729 return (Info);
9730}
9731
9732
9733static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9734{
9735 word internal_command, Info;
9736 byte mask;
9737 byte result[4];
9738
9739 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9740 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9741 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9742 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9743
9744 Info = GOOD;
9745 result[0] = 2;
9746 PUT_WORD (&result[1], DTMF_SUCCESS);
9747 internal_command = plci->internal_command;
9748 plci->internal_command = 0;
9749 mask = 0x01;
9750 switch (plci->dtmf_cmd)
9751 {
9752
9753 case DTMF_LISTEN_TONE_START:
9754 mask <<= 1;
9755 case DTMF_LISTEN_MF_START:
9756 mask <<= 1;
9757
9758 case DTMF_LISTEN_START:
9759 switch (internal_command)
9760 {
9761 default:
9762 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9763 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9764 case DTMF_COMMAND_1:
9765 if (adjust_b_process (Id, plci, Rc) != GOOD)
9766 {
9767 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9768 UnMapId (Id), (char *)(FILE_), __LINE__));
9769 Info = _FACILITY_NOT_SUPPORTED;
9770 break;
9771 }
9772 if (plci->internal_command)
9773 return;
9774 case DTMF_COMMAND_2:
9775 if (plci_nl_busy (plci))
9776 {
9777 plci->internal_command = DTMF_COMMAND_2;
9778 return;
9779 }
9780 plci->internal_command = DTMF_COMMAND_3;
9781 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9782 return;
9783 case DTMF_COMMAND_3:
9784 if ((Rc != OK) && (Rc != OK_FC))
9785 {
9786 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9787 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9788 Info = _FACILITY_NOT_SUPPORTED;
9789 break;
9790 }
9791
9792 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9793
9794 plci->dtmf_rec_active |= mask;
9795 break;
9796 }
9797 break;
9798
9799
9800 case DTMF_LISTEN_TONE_STOP:
9801 mask <<= 1;
9802 case DTMF_LISTEN_MF_STOP:
9803 mask <<= 1;
9804
9805 case DTMF_LISTEN_STOP:
9806 switch (internal_command)
9807 {
9808 default:
9809 plci->dtmf_rec_active &= ~mask;
9810 if (plci->dtmf_rec_active)
9811 break;
9812/*
9813 case DTMF_COMMAND_1:
9814 if (plci->dtmf_rec_active)
9815 {
9816 if (plci_nl_busy (plci))
9817 {
9818 plci->internal_command = DTMF_COMMAND_1;
9819 return;
9820 }
9821 plci->dtmf_rec_active &= ~mask;
9822 plci->internal_command = DTMF_COMMAND_2;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009823 dtmf_enable_receiver (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009824 return;
9825 }
9826 Rc = OK;
9827 case DTMF_COMMAND_2:
9828 if ((Rc != OK) && (Rc != OK_FC))
9829 {
9830 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9831 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9832 Info = _FACILITY_NOT_SUPPORTED;
9833 break;
9834 }
9835*/
9836 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9837 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9838 case DTMF_COMMAND_3:
9839 if (adjust_b_process (Id, plci, Rc) != GOOD)
9840 {
9841 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9842 UnMapId (Id), (char *)(FILE_), __LINE__));
9843 Info = _FACILITY_NOT_SUPPORTED;
9844 break;
9845 }
9846 if (plci->internal_command)
9847 return;
9848 break;
9849 }
9850 break;
9851
9852
9853 case DTMF_SEND_TONE:
9854 mask <<= 1;
9855 case DTMF_SEND_MF:
9856 mask <<= 1;
9857
9858 case DTMF_DIGITS_SEND:
9859 switch (internal_command)
9860 {
9861 default:
9862 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9863 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9864 DTMF_COMMAND_1);
9865 case DTMF_COMMAND_1:
9866 if (adjust_b_process (Id, plci, Rc) != GOOD)
9867 {
9868 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9869 UnMapId (Id), (char *)(FILE_), __LINE__));
9870 Info = _FACILITY_NOT_SUPPORTED;
9871 break;
9872 }
9873 if (plci->internal_command)
9874 return;
9875 case DTMF_COMMAND_2:
9876 if (plci_nl_busy (plci))
9877 {
9878 plci->internal_command = DTMF_COMMAND_2;
9879 return;
9880 }
9881 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9882 plci->internal_command = DTMF_COMMAND_3;
9883 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9884 return;
9885 case DTMF_COMMAND_3:
9886 if ((Rc != OK) && (Rc != OK_FC))
9887 {
9888 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9889 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9890 if (plci->dtmf_send_requests != 0)
9891 (plci->dtmf_send_requests)--;
9892 Info = _FACILITY_NOT_SUPPORTED;
9893 break;
9894 }
9895 return;
9896 }
9897 break;
9898 }
9899 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9900 "wws", Info, SELECTOR_DTMF, result);
9901}
9902
9903
9904static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9905{
9906 word Info;
9907 word i, j;
9908 byte mask;
9909 API_PARSE dtmf_parms[5];
9910 byte result[40];
9911
9912 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9913 UnMapId (Id), (char *)(FILE_), __LINE__));
9914
9915 Info = GOOD;
9916 result[0] = 2;
9917 PUT_WORD (&result[1], DTMF_SUCCESS);
9918 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9919 {
9920 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9921 UnMapId (Id), (char *)(FILE_), __LINE__));
9922 Info = _FACILITY_NOT_SUPPORTED;
9923 }
9924 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9925 {
9926 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9927 UnMapId (Id), (char *)(FILE_), __LINE__));
9928 Info = _WRONG_MESSAGE_FORMAT;
9929 }
9930
9931 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9932 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9933 {
9934 if (!((a->requested_options_table[appl->Id-1])
9935 & (1L << PRIVATE_DTMF_TONE)))
9936 {
9937 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9938 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9939 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9940 }
9941 else
9942 {
9943 for (i = 0; i < 32; i++)
9944 result[4 + i] = 0;
9945 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9946 {
9947 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9948 {
9949 if (dtmf_digit_map[i].listen_mask != 0)
9950 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9951 }
9952 }
9953 else
9954 {
9955 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9956 {
9957 if (dtmf_digit_map[i].send_mask != 0)
9958 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9959 }
9960 }
9961 result[0] = 3 + 32;
9962 result[3] = 32;
9963 }
9964 }
9965
9966 else if (plci == NULL)
9967 {
9968 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9969 UnMapId (Id), (char *)(FILE_), __LINE__));
9970 Info = _WRONG_IDENTIFIER;
9971 }
9972 else
9973 {
9974 if (!plci->State
9975 || !plci->NL.Id || plci->nl_remove_id)
9976 {
9977 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9978 UnMapId (Id), (char *)(FILE_), __LINE__));
9979 Info = _WRONG_STATE;
9980 }
9981 else
9982 {
9983 plci->command = 0;
9984 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9985 mask = 0x01;
9986 switch (plci->dtmf_cmd)
9987 {
9988
9989 case DTMF_LISTEN_TONE_START:
9990 case DTMF_LISTEN_TONE_STOP:
9991 mask <<= 1;
9992 case DTMF_LISTEN_MF_START:
9993 case DTMF_LISTEN_MF_STOP:
9994 mask <<= 1;
9995 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9996 & (1L << PRIVATE_DTMF_TONE)))
9997 {
9998 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9999 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10000 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10001 break;
10002 }
10003
10004 case DTMF_LISTEN_START:
10005 case DTMF_LISTEN_STOP:
10006 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10007 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10008 {
10009 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10010 UnMapId (Id), (char *)(FILE_), __LINE__));
10011 Info = _FACILITY_NOT_SUPPORTED;
10012 break;
10013 }
10014 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10015 {
10016 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10017 {
10018 plci->dtmf_rec_pulse_ms = 0;
10019 plci->dtmf_rec_pause_ms = 0;
10020 }
10021 else
10022 {
10023 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10024 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10025 }
10026 }
10027 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010028 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010029
10030
10031 case DTMF_SEND_TONE:
10032 mask <<= 1;
10033 case DTMF_SEND_MF:
10034 mask <<= 1;
10035 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10036 & (1L << PRIVATE_DTMF_TONE)))
10037 {
10038 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10039 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10040 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10041 break;
10042 }
10043
10044 case DTMF_DIGITS_SEND:
10045 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10046 {
10047 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10048 UnMapId (Id), (char *)(FILE_), __LINE__));
10049 Info = _WRONG_MESSAGE_FORMAT;
10050 break;
10051 }
10052 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10053 {
10054 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10055 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10056 }
10057 i = 0;
10058 j = 0;
10059 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10060 {
10061 j = 0;
10062 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10063 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10064 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10065 {
10066 j++;
10067 }
10068 i++;
10069 }
10070 if (j == DTMF_DIGIT_MAP_ENTRIES)
10071 {
10072 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10073 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10074 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10075 break;
10076 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080010077 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010078 {
10079 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10080 UnMapId (Id), (char *)(FILE_), __LINE__));
10081 Info = _WRONG_STATE;
10082 break;
10083 }
10084 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10085 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010086 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010087
10088 default:
10089 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10090 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10091 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10092 }
10093 }
10094 }
10095 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10096 "wws", Info, SELECTOR_DTMF, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010097 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010098}
10099
10100
10101static void dtmf_confirmation (dword Id, PLCI *plci)
10102{
10103 word Info;
10104 word i;
10105 byte result[4];
10106
10107 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10108 UnMapId (Id), (char *)(FILE_), __LINE__));
10109
10110 Info = GOOD;
10111 result[0] = 2;
10112 PUT_WORD (&result[1], DTMF_SUCCESS);
10113 if (plci->dtmf_send_requests != 0)
10114 {
10115 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10116 "wws", GOOD, SELECTOR_DTMF, result);
10117 (plci->dtmf_send_requests)--;
10118 for (i = 0; i < plci->dtmf_send_requests; i++)
10119 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10120 }
10121}
10122
10123
10124static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10125{
10126 word i, j, n;
10127
10128 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10129 UnMapId (Id), (char *)(FILE_), __LINE__));
10130
10131 n = 0;
10132 for (i = 1; i < length; i++)
10133 {
10134 j = 0;
10135 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10136 && ((msg[i] != dtmf_digit_map[j].code)
10137 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10138 {
10139 j++;
10140 }
10141 if (j < DTMF_DIGIT_MAP_ENTRIES)
10142 {
10143
10144 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10145 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10146 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10147 {
10148 if (n + 1 == i)
10149 {
10150 for (i = length; i > n + 1; i--)
10151 msg[i] = msg[i - 1];
10152 length++;
10153 i++;
10154 }
10155 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10156 }
10157 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10158
10159 msg[++n] = dtmf_digit_map[j].character;
10160 }
10161 }
10162 if (n != 0)
10163 {
10164 msg[0] = (byte) n;
10165 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10166 }
10167}
10168
10169
10170/*------------------------------------------------------------------*/
10171/* DTMF parameters */
10172/*------------------------------------------------------------------*/
10173
10174static void dtmf_parameter_write (PLCI *plci)
10175{
10176 word i;
10177 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10178
10179 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10180 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10181 (char *)(FILE_), __LINE__));
10182
10183 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10184 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10185 for (i = 0; i < plci->dtmf_parameter_length; i++)
10186 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10187 add_p (plci, FTY, parameter_buffer);
10188 sig_req (plci, TEL_CTRL, 0);
10189 send_req (plci);
10190}
10191
10192
10193static void dtmf_parameter_clear_config (PLCI *plci)
10194{
10195
10196 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10197 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10198 (char *)(FILE_), __LINE__));
10199
10200 plci->dtmf_parameter_length = 0;
10201}
10202
10203
10204static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10205{
10206
10207 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10208 UnMapId (Id), (char *)(FILE_), __LINE__));
10209
10210}
10211
10212
10213static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10214{
10215
10216 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10217 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10218
10219 return (GOOD);
10220}
10221
10222
10223static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10224{
10225 word Info;
10226
10227 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10228 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10229
10230 Info = GOOD;
10231 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10232 && (plci->dtmf_parameter_length != 0))
10233 {
10234 switch (plci->adjust_b_state)
10235 {
10236 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10237 plci->internal_command = plci->adjust_b_command;
10238 if (plci->sig_req)
10239 {
10240 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10241 break;
10242 }
10243 dtmf_parameter_write (plci);
10244 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10245 break;
10246 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10247 if ((Rc != OK) && (Rc != OK_FC))
10248 {
10249 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10250 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10251 Info = _WRONG_STATE;
10252 break;
10253 }
10254 break;
10255 }
10256 }
10257 return (Info);
10258}
10259
10260
10261/*------------------------------------------------------------------*/
10262/* Line interconnect facilities */
10263/*------------------------------------------------------------------*/
10264
10265
10266LI_CONFIG *li_config_table;
10267word li_total_channels;
10268
10269
10270/*------------------------------------------------------------------*/
10271/* translate a CHI information element to a channel number */
10272/* returns 0xff - any channel */
10273/* 0xfe - chi wrong coding */
10274/* 0xfd - D-channel */
10275/* 0x00 - no channel */
10276/* else channel number / PRI: timeslot */
10277/* if channels is provided we accept more than one channel. */
10278/*------------------------------------------------------------------*/
10279
10280static byte chi_to_channel (byte *chi, dword *pchannelmap)
10281{
10282 int p;
10283 int i;
10284 dword map;
10285 byte excl;
10286 byte ofs;
10287 byte ch;
10288
10289 if (pchannelmap) *pchannelmap = 0;
10290 if(!chi[0]) return 0xff;
10291 excl = 0;
10292
10293 if(chi[1] & 0x20) {
10294 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10295 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10296 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10297 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10298 if(chi[1] &0x08) excl = 0x40;
10299
10300 /* int. id present */
10301 if(chi[1] &0x40) {
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 }
10306
10307 /* coding standard, Number/Map, Channel Type */
10308 p=i+1;
10309 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10310 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10311 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10312
10313 /* Number/Map */
10314 if(chi[p] &0x10) {
10315
10316 /* map */
10317 if((chi[0]-p)==4) ofs = 0;
10318 else if((chi[0]-p)==3) ofs = 1;
10319 else return 0xfe;
10320 ch = 0;
10321 map = 0;
10322 for(i=0; i<4 && p<chi[0]; i++) {
10323 p++;
10324 ch += 8;
10325 map <<= 8;
10326 if(chi[p]) {
10327 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10328 map |= chi[p];
10329 }
10330 }
10331 ch += ofs;
10332 map <<= ofs;
10333 }
10334 else {
10335
10336 /* number */
10337 p=i+1;
10338 ch = chi[p] &0x3f;
10339 if(pchannelmap) {
10340 if((byte)(chi[0]-p)>30) return 0xfe;
10341 map = 0;
10342 for(i=p; i<=chi[0]; i++) {
10343 if ((chi[i] &0x7f) > 31) return 0xfe;
10344 map |= (1L << (chi[i] &0x7f));
10345 }
10346 }
10347 else {
10348 if(p!=chi[0]) return 0xfe;
10349 if (ch > 31) return 0xfe;
10350 map = (1L << ch);
10351 }
10352 if(chi[p] &0x40) return 0xfe;
10353 }
10354 if (pchannelmap) *pchannelmap = map;
10355 else if (map != ((dword)(1L << ch))) return 0xfe;
10356 return (byte)(excl | ch);
10357 }
10358 else { /* not PRI */
10359 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10360 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10361 if(chi[1] &0x08) excl = 0x40;
10362
10363 switch(chi[1] |0x98) {
10364 case 0x98: return 0;
10365 case 0x99:
10366 if (pchannelmap) *pchannelmap = 2;
10367 return excl |1;
10368 case 0x9a:
10369 if (pchannelmap) *pchannelmap = 4;
10370 return excl |2;
10371 case 0x9b: return 0xff;
10372 case 0x9c: return 0xfd; /* d-ch */
10373 default: return 0xfe;
10374 }
10375 }
10376}
10377
10378
10379static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10380{
10381 DIVA_CAPI_ADAPTER *a;
10382 PLCI *splci;
10383 byte old_id;
10384
10385 a = plci->adapter;
10386 old_id = plci->li_bchannel_id;
10387 if (a->li_pri)
10388 {
10389 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10390 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10391 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10392 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10393 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10394 }
10395 else
10396 {
10397 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10398 {
10399 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10400 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10401 plci->li_bchannel_id = bchannel_id & 0x03;
10402 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10403 {
10404 splci = a->AdvSignalPLCI;
10405 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10406 {
10407 if ((splci->li_bchannel_id != 0)
10408 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10409 {
10410 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10411 }
10412 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10413 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10414 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10415 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10416 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10417 }
10418 }
10419 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10420 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10421 }
10422 }
10423 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10424 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10425 {
10426 mixer_clear_config (plci);
10427 }
10428 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10429 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10430 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10431}
10432
10433
10434static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10435{
10436 DIVA_CAPI_ADAPTER *a;
10437 PLCI *splci;
10438 byte ch, old_id;
10439
10440 a = plci->adapter;
10441 old_id = plci->li_bchannel_id;
10442 ch = chi_to_channel (chi, NULL);
10443 if (!(ch & 0x80))
10444 {
10445 if (a->li_pri)
10446 {
10447 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10448 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10449 plci->li_bchannel_id = (ch & 0x1f) + 1;
10450 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10451 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10452 }
10453 else
10454 {
10455 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10456 {
10457 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10458 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10459 plci->li_bchannel_id = ch & 0x1f;
10460 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10461 {
10462 splci = a->AdvSignalPLCI;
10463 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10464 {
10465 if ((splci->li_bchannel_id != 0)
10466 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10467 {
10468 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10469 }
10470 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10471 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10472 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10473 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10474 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10475 }
10476 }
10477 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10478 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10479 }
10480 }
10481 }
10482 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10483 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10484 {
10485 mixer_clear_config (plci);
10486 }
10487 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10488 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10489 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10490}
10491
10492
10493#define MIXER_MAX_DUMP_CHANNELS 34
10494
10495static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10496{
10497static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10498 word n, i, j;
10499 char *p;
10500 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10501
10502 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10503 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10504
10505 for (i = 0; i < li_total_channels; i++)
10506 {
10507 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10508 if (li_config_table[i].chflags != 0)
10509 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10510 else
10511 {
10512 for (j = 0; j < li_total_channels; j++)
10513 {
10514 if (((li_config_table[i].flag_table[j]) != 0)
10515 || ((li_config_table[j].flag_table[i]) != 0))
10516 {
10517 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10518 }
10519 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10520 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10521 {
10522 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10523 }
10524 }
10525 }
10526 }
10527 for (i = 0; i < li_total_channels; i++)
10528 {
10529 for (j = 0; j < li_total_channels; j++)
10530 {
10531 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10532 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10533 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10534 }
10535 }
10536 for (n = 0; n < li_total_channels; n++)
10537 {
10538 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10539 {
10540 for (i = 0; i < li_total_channels; i++)
10541 {
10542 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10543 {
10544 for (j = 0; j < li_total_channels; j++)
10545 {
10546 li_config_table[i].coef_table[j] |=
10547 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10548 }
10549 }
10550 }
10551 }
10552 }
10553 for (i = 0; i < li_total_channels; i++)
10554 {
10555 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10556 {
10557 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10558 for (j = 0; j < li_total_channels; j++)
10559 {
10560 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10561 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10562 }
10563 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10564 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10565 }
10566 }
10567 for (i = 0; i < li_total_channels; i++)
10568 {
10569 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10570 {
10571 for (j = 0; j < li_total_channels; j++)
10572 {
10573 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10574 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10575 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10576 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10577 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10578 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10579 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10580 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10581 }
10582 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10583 {
10584 for (j = 0; j < li_total_channels; j++)
10585 {
10586 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587 {
10588 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10589 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10590 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10591 }
10592 }
10593 }
10594 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10595 {
10596 for (j = 0; j < li_total_channels; j++)
10597 {
10598 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10599 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10600 }
10601 }
10602 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10603 {
10604 for (j = 0; j < li_total_channels; j++)
10605 {
10606 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10607 {
10608 for (n = 0; n < li_total_channels; n++)
10609 {
10610 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10611 {
10612 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10613 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10614 {
10615 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10616 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10617 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10618 }
10619 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10620 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10621 }
10622 }
10623 }
10624 }
10625 }
10626 }
10627 }
10628 for (i = 0; i < li_total_channels; i++)
10629 {
10630 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10631 {
10632 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10633 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10634 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10635 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10636 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10637 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10638 for (j = 0; j < li_total_channels; j++)
10639 {
10640 if ((li_config_table[i].flag_table[j] &
10641 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10642 || (li_config_table[j].flag_table[i] &
10643 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10644 {
10645 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10646 }
10647 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10648 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10650 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651 }
10652 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10653 {
10654 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10655 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10656 }
10657 }
10658 }
10659 for (i = 0; i < li_total_channels; i++)
10660 {
10661 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10662 {
10663 j = 0;
10664 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10665 j++;
10666 if (j < li_total_channels)
10667 {
10668 for (j = 0; j < li_total_channels; j++)
10669 {
10670 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10671 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10672 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10673 }
10674 }
10675 }
10676 }
10677 n = li_total_channels;
10678 if (n > MIXER_MAX_DUMP_CHANNELS)
10679 n = MIXER_MAX_DUMP_CHANNELS;
10680 p = hex_line;
10681 for (j = 0; j < n; j++)
10682 {
10683 if ((j & 0x7) == 0)
10684 *(p++) = ' ';
10685 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10686 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10687 }
10688 *p = '\0';
10689 dbug (1, dprintf ("[%06lx] CURRENT %s",
10690 (dword)(UnMapController (a->Id)), (char *) hex_line));
10691 p = hex_line;
10692 for (j = 0; j < n; j++)
10693 {
10694 if ((j & 0x7) == 0)
10695 *(p++) = ' ';
10696 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10697 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10698 }
10699 *p = '\0';
10700 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10701 (dword)(UnMapController (a->Id)), (char *) hex_line));
10702 p = hex_line;
10703 for (j = 0; j < n; j++)
10704 {
10705 if ((j & 0x7) == 0)
10706 *(p++) = ' ';
10707 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10708 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10709 }
10710 *p = '\0';
10711 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10712 (dword)(UnMapController (a->Id)), (char *) hex_line));
10713 for (i = 0; i < n; i++)
10714 {
10715 p = hex_line;
10716 for (j = 0; j < n; j++)
10717 {
10718 if ((j & 0x7) == 0)
10719 *(p++) = ' ';
10720 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10721 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10722 }
10723 *p = '\0';
10724 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10725 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10726 }
10727 for (i = 0; i < n; i++)
10728 {
10729 p = hex_line;
10730 for (j = 0; j < n; j++)
10731 {
10732 if ((j & 0x7) == 0)
10733 *(p++) = ' ';
10734 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10735 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10736 }
10737 *p = '\0';
10738 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10739 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10740 }
10741}
10742
10743
10744static struct
10745{
10746 byte mask;
10747 byte line_flags;
10748} mixer_write_prog_pri[] =
10749{
10750 { LI_COEF_CH_CH, 0 },
10751 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10752 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10753 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10754};
10755
10756static struct
10757{
10758 byte from_ch;
10759 byte to_ch;
10760 byte mask;
10761 byte xconnect_override;
10762} mixer_write_prog_bri[] =
10763{
10764 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10765 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10766 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10767 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10768 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10769 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10770 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10771 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10772 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10773 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10774 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10775 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10776 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10777 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10778 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10779 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10780 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10781 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10782 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10783 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10784 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10785 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10786 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10787 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10788 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10789 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10790 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10791 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10792 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10793 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10794 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10795 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10796 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10797 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10798 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10799 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10800};
10801
10802static byte mixer_swapped_index_bri[] =
10803{
10804 18, /* B to B */
10805 19, /* Alt B to B */
10806 20, /* PC to B */
10807 21, /* Alt PC to B */
10808 22, /* IC to B */
10809 23, /* Alt IC to B */
10810 24, /* B to PC */
10811 25, /* Alt B to PC */
10812 26, /* PC to PC */
10813 27, /* Alt PC to PC */
10814 28, /* IC to PC */
10815 29, /* Alt IC to PC */
10816 30, /* B to IC */
10817 31, /* Alt B to IC */
10818 32, /* PC to IC */
10819 33, /* Alt PC to IC */
10820 34, /* IC to IC */
10821 35, /* Alt IC to IC */
10822 0, /* Alt B to Alt B */
10823 1, /* B to Alt B */
10824 2, /* Alt PC to Alt B */
10825 3, /* PC to Alt B */
10826 4, /* Alt IC to Alt B */
10827 5, /* IC to Alt B */
10828 6, /* Alt B to Alt PC */
10829 7, /* B to Alt PC */
10830 8, /* Alt PC to Alt PC */
10831 9, /* PC to Alt PC */
10832 10, /* Alt IC to Alt PC */
10833 11, /* IC to Alt PC */
10834 12, /* Alt B to Alt IC */
10835 13, /* B to Alt IC */
10836 14, /* Alt PC to Alt IC */
10837 15, /* PC to Alt IC */
10838 16, /* Alt IC to Alt IC */
10839 17 /* IC to Alt IC */
10840};
10841
10842static struct
10843{
10844 byte mask;
10845 byte from_pc;
10846 byte to_pc;
10847} xconnect_write_prog[] =
10848{
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010849 { LI_COEF_CH_CH, false, false },
10850 { LI_COEF_CH_PC, false, true },
10851 { LI_COEF_PC_CH, true, false },
10852 { LI_COEF_PC_PC, true, true }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010853};
10854
10855
10856static void xconnect_query_addresses (PLCI *plci)
10857{
10858 DIVA_CAPI_ADAPTER *a;
10859 word w, ch;
10860 byte *p;
10861
10862 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10863 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10864 (char *)(FILE_), __LINE__));
10865
10866 a = plci->adapter;
10867 if (a->li_pri && ((plci->li_bchannel_id == 0)
10868 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10869 {
10870 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10871 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10872 (char *)(FILE_), __LINE__));
10873 return;
10874 }
10875 p = plci->internal_req_buffer;
10876 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10877 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10878 w = ch;
10879 *(p++) = (byte) w;
10880 *(p++) = (byte)(w >> 8);
10881 w = ch | XCONNECT_CHANNEL_PORT_PC;
10882 *(p++) = (byte) w;
10883 *(p++) = (byte)(w >> 8);
10884 plci->NData[0].P = plci->internal_req_buffer;
10885 plci->NData[0].PLength = p - plci->internal_req_buffer;
10886 plci->NL.X = plci->NData;
10887 plci->NL.ReqCh = 0;
10888 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10889 plci->adapter->request (&plci->NL);
10890}
10891
10892
10893static void xconnect_write_coefs (PLCI *plci, word internal_command)
10894{
10895
10896 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10897 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10898 (char *)(FILE_), __LINE__, internal_command));
10899
10900 plci->li_write_command = internal_command;
10901 plci->li_write_channel = 0;
10902}
10903
10904
10905static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10906{
10907 DIVA_CAPI_ADAPTER *a;
10908 word w, n, i, j, r, s, to_ch;
10909 dword d;
10910 byte *p;
10911 struct xconnect_transfer_address_s *transfer_address;
10912 byte ch_map[MIXER_CHANNELS_BRI];
10913
10914 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10915 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10916
10917 a = plci->adapter;
10918 if ((plci->li_bchannel_id == 0)
10919 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10920 {
10921 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10922 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010923 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010924 }
10925 i = a->li_base + (plci->li_bchannel_id - 1);
10926 j = plci->li_write_channel;
10927 p = plci->internal_req_buffer;
10928 if (j != 0)
10929 {
10930 if ((Rc != OK) && (Rc != OK_FC))
10931 {
10932 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10933 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010934 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010935 }
10936 }
10937 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10938 {
10939 r = 0;
10940 s = 0;
10941 if (j < li_total_channels)
10942 {
10943 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10944 {
10945 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10946 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10947 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10948 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10949 }
10950 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10951 while ((j < li_total_channels)
10952 && ((r == 0)
10953 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10954 || (!li_config_table[j].adapter->li_pri
10955 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10956 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10957 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10958 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10959 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10960 || ((li_config_table[j].adapter->li_base != a->li_base)
10961 && !(r & s &
10962 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10963 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10964 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10965 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10966 {
10967 j++;
10968 if (j < li_total_channels)
10969 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10970 }
10971 }
10972 if (j < li_total_channels)
10973 {
10974 plci->internal_command = plci->li_write_command;
10975 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010976 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010977 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10978 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10979 do
10980 {
10981 if (li_config_table[j].adapter->li_base != a->li_base)
10982 {
10983 r &= s &
10984 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10985 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10986 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10987 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10988 }
10989 n = 0;
10990 do
10991 {
10992 if (r & xconnect_write_prog[n].mask)
10993 {
10994 if (xconnect_write_prog[n].from_pc)
10995 transfer_address = &(li_config_table[j].send_pc);
10996 else
10997 transfer_address = &(li_config_table[j].send_b);
10998 d = transfer_address->card_address.low;
10999 *(p++) = (byte) d;
11000 *(p++) = (byte)(d >> 8);
11001 *(p++) = (byte)(d >> 16);
11002 *(p++) = (byte)(d >> 24);
11003 d = transfer_address->card_address.high;
11004 *(p++) = (byte) d;
11005 *(p++) = (byte)(d >> 8);
11006 *(p++) = (byte)(d >> 16);
11007 *(p++) = (byte)(d >> 24);
11008 d = transfer_address->offset;
11009 *(p++) = (byte) d;
11010 *(p++) = (byte)(d >> 8);
11011 *(p++) = (byte)(d >> 16);
11012 *(p++) = (byte)(d >> 24);
11013 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11014 *(p++) = (byte) w;
11015 *(p++) = (byte)(w >> 8);
11016 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11017 (li_config_table[i].adapter->u_law ?
11018 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11019 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11020 *(p++) = (byte) w;
11021 *(p++) = (byte) 0;
11022 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11023 }
11024 n++;
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011025 } while ((n < ARRAY_SIZE(xconnect_write_prog))
Linus Torvalds1da177e2005-04-16 15:20:36 -070011026 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011027 if (n == ARRAY_SIZE(xconnect_write_prog))
Linus Torvalds1da177e2005-04-16 15:20:36 -070011028 {
11029 do
11030 {
11031 j++;
11032 if (j < li_total_channels)
11033 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11034 } while ((j < li_total_channels)
11035 && ((r == 0)
11036 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11037 || (!li_config_table[j].adapter->li_pri
11038 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11039 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11040 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11041 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11042 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11043 || ((li_config_table[j].adapter->li_base != a->li_base)
11044 && !(r & s &
11045 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11046 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11047 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11048 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11049 }
11050 } while ((j < li_total_channels)
11051 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11052 }
11053 else if (j == li_total_channels)
11054 {
11055 plci->internal_command = plci->li_write_command;
11056 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011057 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011058 if (a->li_pri)
11059 {
11060 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11061 w = 0;
11062 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11063 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11064 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11065 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11066 *(p++) = (byte) w;
11067 *(p++) = (byte)(w >> 8);
11068 }
11069 else
11070 {
11071 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11072 w = 0;
11073 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11074 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11075 {
11076 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11077 }
11078 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11079 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11080 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11081 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11082 *(p++) = (byte) w;
11083 *(p++) = (byte)(w >> 8);
11084 for (j = 0; j < sizeof(ch_map); j += 2)
11085 {
11086 if (plci->li_bchannel_id == 2)
11087 {
11088 ch_map[j] = (byte)(j+1);
11089 ch_map[j+1] = (byte) j;
11090 }
11091 else
11092 {
11093 ch_map[j] = (byte) j;
11094 ch_map[j+1] = (byte)(j+1);
11095 }
11096 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011097 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011098 {
11099 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11100 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11101 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11102 {
11103 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11104 mixer_write_prog_bri[n].xconnect_override :
11105 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11106 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11107 {
11108 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11109 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11110 }
11111 }
11112 else
11113 {
11114 *p = 0x00;
11115 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11116 {
11117 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11118 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11119 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11120 }
11121 }
11122 p++;
11123 }
11124 }
11125 j = li_total_channels + 1;
11126 }
11127 }
11128 else
11129 {
11130 if (j <= li_total_channels)
11131 {
11132 plci->internal_command = plci->li_write_command;
11133 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011134 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011135 if (j < a->li_base)
11136 j = a->li_base;
11137 if (a->li_pri)
11138 {
11139 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11140 w = 0;
11141 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11142 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11143 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11144 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11145 *(p++) = (byte) w;
11146 *(p++) = (byte)(w >> 8);
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011147 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011148 {
11149 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11150 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11151 {
11152 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11153 if (w & mixer_write_prog_pri[n].mask)
11154 {
11155 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11156 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11157 }
11158 else
11159 *(p++) = 0x00;
11160 }
11161 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11162 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11163 {
11164 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11165 if (w & mixer_write_prog_pri[n].mask)
11166 {
11167 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11168 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11169 }
11170 else
11171 *(p++) = 0x00;
11172 }
11173 }
11174 }
11175 else
11176 {
11177 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11178 w = 0;
11179 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11180 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11181 {
11182 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11183 }
11184 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11185 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11186 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11187 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11188 *(p++) = (byte) w;
11189 *(p++) = (byte)(w >> 8);
11190 for (j = 0; j < sizeof(ch_map); j += 2)
11191 {
11192 if (plci->li_bchannel_id == 2)
11193 {
11194 ch_map[j] = (byte)(j+1);
11195 ch_map[j+1] = (byte) j;
11196 }
11197 else
11198 {
11199 ch_map[j] = (byte) j;
11200 ch_map[j+1] = (byte)(j+1);
11201 }
11202 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011203 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011204 {
11205 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11206 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11207 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11208 {
11209 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11210 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11211 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11212 }
11213 else
11214 {
11215 *p = 0x00;
11216 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11217 {
11218 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11219 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11220 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11221 }
11222 }
11223 p++;
11224 }
11225 }
11226 j = li_total_channels + 1;
11227 }
11228 }
11229 plci->li_write_channel = j;
11230 if (p != plci->internal_req_buffer)
11231 {
11232 plci->NData[0].P = plci->internal_req_buffer;
11233 plci->NData[0].PLength = p - plci->internal_req_buffer;
11234 plci->NL.X = plci->NData;
11235 plci->NL.ReqCh = 0;
11236 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11237 plci->adapter->request (&plci->NL);
11238 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011239 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011240}
11241
11242
11243static void mixer_notify_update (PLCI *plci, byte others)
11244{
11245 DIVA_CAPI_ADAPTER *a;
11246 word i, w;
11247 PLCI *notify_plci;
11248 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11249
11250 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11251 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11252 (char *)(FILE_), __LINE__, others));
11253
11254 a = plci->adapter;
11255 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11256 {
11257 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011258 plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011259 i = 0;
11260 do
11261 {
11262 notify_plci = NULL;
11263 if (others)
11264 {
11265 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11266 i++;
11267 if (i < li_total_channels)
11268 notify_plci = li_config_table[i++].plci;
11269 }
11270 else
11271 {
11272 if ((plci->li_bchannel_id != 0)
11273 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11274 {
11275 notify_plci = plci;
11276 }
11277 }
11278 if ((notify_plci != NULL)
11279 && !notify_plci->li_notify_update
11280 && (notify_plci->appl != NULL)
11281 && (notify_plci->State)
11282 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11283 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011284 notify_plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011285 ((CAPI_MSG *) msg)->header.length = 18;
11286 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11287 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11288 ((CAPI_MSG *) msg)->header.number = 0;
11289 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11290 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11291 ((CAPI_MSG *) msg)->header.ncci = 0;
11292 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11293 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11294 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11295 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11296 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11297 if (w != _QUEUE_FULL)
11298 {
11299 if (w != 0)
11300 {
11301 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11302 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11303 (char *)(FILE_), __LINE__,
11304 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11305 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011306 notify_plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011307 }
11308 }
11309 } while (others && (notify_plci != NULL));
11310 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011311 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011312 }
11313}
11314
11315
11316static void mixer_clear_config (PLCI *plci)
11317{
11318 DIVA_CAPI_ADAPTER *a;
11319 word i, j;
11320
11321 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11322 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11323 (char *)(FILE_), __LINE__));
11324
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011325 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011326 plci->li_plci_b_write_pos = 0;
11327 plci->li_plci_b_read_pos = 0;
11328 plci->li_plci_b_req_pos = 0;
11329 a = plci->adapter;
11330 if ((plci->li_bchannel_id != 0)
11331 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11332 {
11333 i = a->li_base + (plci->li_bchannel_id - 1);
11334 li_config_table[i].curchnl = 0;
11335 li_config_table[i].channel = 0;
11336 li_config_table[i].chflags = 0;
11337 for (j = 0; j < li_total_channels; j++)
11338 {
11339 li_config_table[j].flag_table[i] = 0;
11340 li_config_table[i].flag_table[j] = 0;
11341 li_config_table[i].coef_table[j] = 0;
11342 li_config_table[j].coef_table[i] = 0;
11343 }
11344 if (!a->li_pri)
11345 {
11346 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11347 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11348 {
11349 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11350 li_config_table[i].curchnl = 0;
11351 li_config_table[i].channel = 0;
11352 li_config_table[i].chflags = 0;
11353 for (j = 0; j < li_total_channels; j++)
11354 {
11355 li_config_table[i].flag_table[j] = 0;
11356 li_config_table[j].flag_table[i] = 0;
11357 li_config_table[i].coef_table[j] = 0;
11358 li_config_table[j].coef_table[i] = 0;
11359 }
11360 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11361 {
11362 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11363 li_config_table[i].curchnl = 0;
11364 li_config_table[i].channel = 0;
11365 li_config_table[i].chflags = 0;
11366 for (j = 0; j < li_total_channels; j++)
11367 {
11368 li_config_table[i].flag_table[j] = 0;
11369 li_config_table[j].flag_table[i] = 0;
11370 li_config_table[i].coef_table[j] = 0;
11371 li_config_table[j].coef_table[i] = 0;
11372 }
11373 }
11374 }
11375 }
11376 }
11377}
11378
11379
11380static void mixer_prepare_switch (dword Id, PLCI *plci)
11381{
11382
11383 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11384 UnMapId (Id), (char *)(FILE_), __LINE__));
11385
11386 do
11387 {
11388 mixer_indication_coefs_set (Id, plci);
11389 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11390}
11391
11392
11393static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11394{
11395 DIVA_CAPI_ADAPTER *a;
11396 word i, j;
11397
11398 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11399 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11400
11401 a = plci->adapter;
11402 if ((plci->li_bchannel_id != 0)
11403 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11404 {
11405 i = a->li_base + (plci->li_bchannel_id - 1);
11406 for (j = 0; j < li_total_channels; j++)
11407 {
11408 li_config_table[i].coef_table[j] &= 0xf;
11409 li_config_table[j].coef_table[i] &= 0xf;
11410 }
11411 if (!a->li_pri)
11412 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11413 }
11414 return (GOOD);
11415}
11416
11417
11418static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11419{
11420 DIVA_CAPI_ADAPTER *a;
11421 word Info;
11422
11423 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11424 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11425
11426 Info = GOOD;
11427 a = plci->adapter;
11428 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11429 && (plci->li_bchannel_id != 0)
11430 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11431 {
11432 switch (plci->adjust_b_state)
11433 {
11434 case ADJUST_B_RESTORE_MIXER_1:
11435 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11436 {
11437 plci->internal_command = plci->adjust_b_command;
11438 if (plci_nl_busy (plci))
11439 {
11440 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11441 break;
11442 }
11443 xconnect_query_addresses (plci);
11444 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11445 break;
11446 }
11447 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11448 Rc = OK;
11449 case ADJUST_B_RESTORE_MIXER_2:
11450 case ADJUST_B_RESTORE_MIXER_3:
11451 case ADJUST_B_RESTORE_MIXER_4:
11452 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11453 {
11454 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11455 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11456 Info = _WRONG_STATE;
11457 break;
11458 }
11459 if (Rc == OK)
11460 {
11461 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11462 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11463 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11464 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11465 }
11466 else if (Rc == 0)
11467 {
11468 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11469 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11470 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11471 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11472 }
11473 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11474 {
11475 plci->internal_command = plci->adjust_b_command;
11476 break;
11477 }
11478 case ADJUST_B_RESTORE_MIXER_5:
11479 xconnect_write_coefs (plci, plci->adjust_b_command);
11480 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11481 Rc = OK;
11482 case ADJUST_B_RESTORE_MIXER_6:
11483 if (!xconnect_write_coefs_process (Id, plci, Rc))
11484 {
11485 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11486 UnMapId (Id), (char *)(FILE_), __LINE__));
11487 Info = _FACILITY_NOT_SUPPORTED;
11488 break;
11489 }
11490 if (plci->internal_command)
11491 break;
11492 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11493 case ADJUST_B_RESTORE_MIXER_7:
11494 break;
11495 }
11496 }
11497 return (Info);
11498}
11499
11500
11501static void mixer_command (dword Id, PLCI *plci, byte Rc)
11502{
11503 DIVA_CAPI_ADAPTER *a;
11504 word i, internal_command, Info;
11505
11506 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11507 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11508 plci->li_cmd));
11509
11510 Info = GOOD;
11511 a = plci->adapter;
11512 internal_command = plci->internal_command;
11513 plci->internal_command = 0;
11514 switch (plci->li_cmd)
11515 {
11516 case LI_REQ_CONNECT:
11517 case LI_REQ_DISCONNECT:
11518 case LI_REQ_SILENT_UPDATE:
11519 switch (internal_command)
11520 {
11521 default:
11522 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11523 {
11524 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11525 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11526 }
11527 case MIXER_COMMAND_1:
11528 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11529 {
11530 if (adjust_b_process (Id, plci, Rc) != GOOD)
11531 {
11532 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11533 UnMapId (Id), (char *)(FILE_), __LINE__));
11534 Info = _FACILITY_NOT_SUPPORTED;
11535 break;
11536 }
11537 if (plci->internal_command)
11538 return;
11539 }
11540 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11541 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11543 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11544 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11545 {
11546 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11547 }
11548 else
11549 {
11550 do
11551 {
11552 mixer_indication_coefs_set (Id, plci);
11553 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11554 }
11555 case MIXER_COMMAND_2:
11556 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11557 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11558 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11559 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11560 {
11561 if (!xconnect_write_coefs_process (Id, plci, Rc))
11562 {
11563 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11564 UnMapId (Id), (char *)(FILE_), __LINE__));
11565 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11566 {
11567 do
11568 {
11569 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11570 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11571 i = (plci->li_plci_b_write_pos == 0) ?
11572 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11573 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11574 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11575 }
11576 Info = _FACILITY_NOT_SUPPORTED;
11577 break;
11578 }
11579 if (plci->internal_command)
11580 return;
11581 }
11582 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11583 {
11584 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11585 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11586 }
11587 case MIXER_COMMAND_3:
11588 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11589 {
11590 if (adjust_b_process (Id, plci, Rc) != GOOD)
11591 {
11592 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11593 UnMapId (Id), (char *)(FILE_), __LINE__));
11594 Info = _FACILITY_NOT_SUPPORTED;
11595 break;
11596 }
11597 if (plci->internal_command)
11598 return;
11599 }
11600 break;
11601 }
11602 break;
11603 }
11604 if ((plci->li_bchannel_id == 0)
11605 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11606 {
11607 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11608 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11609 }
11610 else
11611 {
11612 i = a->li_base + (plci->li_bchannel_id - 1);
11613 li_config_table[i].curchnl = plci->li_channel_bits;
11614 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11615 {
11616 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11617 li_config_table[i].curchnl = plci->li_channel_bits;
11618 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11619 {
11620 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11621 li_config_table[i].curchnl = plci->li_channel_bits;
11622 }
11623 }
11624 }
11625}
11626
11627
11628static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11629 dword plci_b_id, byte connect, dword li_flags)
11630{
11631 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11632 PLCI *plci_b;
11633 DIVA_CAPI_ADAPTER *a_b;
11634
11635 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11636 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11637 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11638 if (!a->li_pri && (plci->tel == ADV_VOICE)
11639 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11640 {
11641 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11642 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11643 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11644 }
11645 else
11646 {
11647 ch_a_v = ch_a;
11648 ch_a_s = ch_a;
11649 }
11650 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11651 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11652 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11653 {
11654 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11655 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11656 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11657 }
11658 else
11659 {
11660 ch_b_v = ch_b;
11661 ch_b_s = ch_b;
11662 }
11663 if (connect)
11664 {
11665 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11666 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11667 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669 }
11670 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11671 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11672 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11673 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11674 if (ch_a_v == ch_b_v)
11675 {
11676 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11677 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11678 }
11679 else
11680 {
11681 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11682 {
11683 for (i = 0; i < li_total_channels; i++)
11684 {
11685 if (i != ch_a_v)
11686 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11687 }
11688 }
11689 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11690 {
11691 for (i = 0; i < li_total_channels; i++)
11692 {
11693 if (i != ch_a_s)
11694 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11695 }
11696 }
11697 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11698 {
11699 for (i = 0; i < li_total_channels; i++)
11700 {
11701 if (i != ch_a_v)
11702 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11703 }
11704 }
11705 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11706 {
11707 for (i = 0; i < li_total_channels; i++)
11708 {
11709 if (i != ch_a_s)
11710 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11711 }
11712 }
11713 }
11714 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11715 {
11716 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11717 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11718 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11720 }
11721 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11722 {
11723 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11724 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11725 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11727 }
11728 if (li_flags & LI_FLAG_MONITOR_A)
11729 {
11730 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11731 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11732 }
11733 if (li_flags & LI_FLAG_MONITOR_B)
11734 {
11735 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11736 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11737 }
11738 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11739 {
11740 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742 }
11743 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11744 {
11745 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11746 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11747 }
11748 if (li_flags & LI_FLAG_MIX_A)
11749 {
11750 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11751 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11752 }
11753 if (li_flags & LI_FLAG_MIX_B)
11754 {
11755 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11756 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11757 }
11758 if (ch_a_v != ch_a_s)
11759 {
11760 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11761 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11762 }
11763 if (ch_b_v != ch_b_s)
11764 {
11765 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11766 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11767 }
11768}
11769
11770
11771static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11772 dword plci_b_id, byte connect, dword li_flags)
11773{
11774 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11775 PLCI *plci_b;
11776 DIVA_CAPI_ADAPTER *a_b;
11777
11778 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11779 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11780 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11781 if (!a->li_pri && (plci->tel == ADV_VOICE)
11782 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11783 {
11784 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11785 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11786 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11787 }
11788 else
11789 {
11790 ch_a_v = ch_a;
11791 ch_a_s = ch_a;
11792 }
11793 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11794 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11795 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11796 {
11797 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11798 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11799 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11800 }
11801 else
11802 {
11803 ch_b_v = ch_b;
11804 ch_b_s = ch_b;
11805 }
11806 if (connect)
11807 {
11808 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11809 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11810 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11811 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11812 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11813 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11814 }
11815 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11824 {
11825 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11826 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11827 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11829 }
11830 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11831 {
11832 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11833 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11834 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11836 }
11837 if (li_flags & LI2_FLAG_MONITOR_B)
11838 {
11839 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11840 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11841 }
11842 if (li_flags & LI2_FLAG_MIX_B)
11843 {
11844 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11845 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11846 }
11847 if (li_flags & LI2_FLAG_MONITOR_X)
11848 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11849 if (li_flags & LI2_FLAG_MIX_X)
11850 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11851 if (li_flags & LI2_FLAG_LOOP_B)
11852 {
11853 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11854 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11857 }
11858 if (li_flags & LI2_FLAG_LOOP_PC)
11859 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11860 if (li_flags & LI2_FLAG_LOOP_X)
11861 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11862 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11863 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11864 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11865 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11866 if (ch_a_v != ch_a_s)
11867 {
11868 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11869 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11870 }
11871 if (ch_b_v != ch_b_s)
11872 {
11873 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11874 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11875 }
11876}
11877
11878
11879static word li_check_main_plci (dword Id, PLCI *plci)
11880{
11881 if (plci == NULL)
11882 {
11883 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11884 UnMapId (Id), (char *)(FILE_), __LINE__));
11885 return (_WRONG_IDENTIFIER);
11886 }
11887 if (!plci->State
11888 || !plci->NL.Id || plci->nl_remove_id
11889 || (plci->li_bchannel_id == 0))
11890 {
11891 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11892 UnMapId (Id), (char *)(FILE_), __LINE__));
11893 return (_WRONG_STATE);
11894 }
11895 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11896 return (GOOD);
11897}
11898
11899
11900static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11901 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11902{
11903 byte ctlr_b;
11904 PLCI *plci_b;
11905
11906 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11907 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11908 {
11909 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11910 UnMapId (Id), (char *)(FILE_), __LINE__));
11911 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11912 return (NULL);
11913 }
11914 ctlr_b = 0;
11915 if ((plci_b_id & 0x7f) != 0)
11916 {
11917 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11918 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11919 ctlr_b = 0;
11920 }
11921 if ((ctlr_b == 0)
11922 || (((plci_b_id >> 8) & 0xff) == 0)
11923 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11924 {
11925 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11926 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11927 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11928 return (NULL);
11929 }
11930 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11931 if (!plci_b->State
11932 || !plci_b->NL.Id || plci_b->nl_remove_id
11933 || (plci_b->li_bchannel_id == 0))
11934 {
11935 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11936 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11937 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11938 return (NULL);
11939 }
11940 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11941 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11942 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11943 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11944 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11945 {
11946 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11947 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11948 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11949 return (NULL);
11950 }
11951 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11952 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11953 {
11954 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11955 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11956 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11957 return (NULL);
11958 }
11959 return (plci_b);
11960}
11961
11962
11963static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11964 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11965{
11966 byte ctlr_b;
11967 PLCI *plci_b;
11968
11969 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11970 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11971 {
11972 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11973 UnMapId (Id), (char *)(FILE_), __LINE__));
11974 PUT_WORD (p_result, _WRONG_STATE);
11975 return (NULL);
11976 }
11977 ctlr_b = 0;
11978 if ((plci_b_id & 0x7f) != 0)
11979 {
11980 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11981 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11982 ctlr_b = 0;
11983 }
11984 if ((ctlr_b == 0)
11985 || (((plci_b_id >> 8) & 0xff) == 0)
11986 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11987 {
11988 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11989 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11990 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11991 return (NULL);
11992 }
11993 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11994 if (!plci_b->State
11995 || !plci_b->NL.Id || plci_b->nl_remove_id
11996 || (plci_b->li_bchannel_id == 0)
11997 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11998 {
11999 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12000 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12001 PUT_WORD (p_result, _WRONG_STATE);
12002 return (NULL);
12003 }
12004 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12005 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12006 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12008 {
12009 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12010 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12011 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12012 return (NULL);
12013 }
12014 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12015 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12016 {
12017 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12018 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12019 PUT_WORD (p_result, _WRONG_STATE);
12020 return (NULL);
12021 }
12022 return (plci_b);
12023}
12024
12025
12026static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12027{
12028 word Info;
12029 word i;
12030 dword d, li_flags, plci_b_id;
12031 PLCI *plci_b;
12032 API_PARSE li_parms[3];
12033 API_PARSE li_req_parms[3];
12034 API_PARSE li_participant_struct[2];
12035 API_PARSE li_participant_parms[3];
12036 word participant_parms_pos;
12037 byte result_buffer[32];
12038 byte *result;
12039 word result_pos;
12040 word plci_b_write_pos;
12041
12042 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12043 UnMapId (Id), (char *)(FILE_), __LINE__));
12044
12045 Info = GOOD;
12046 result = result_buffer;
12047 result_buffer[0] = 0;
12048 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12049 {
12050 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12051 UnMapId (Id), (char *)(FILE_), __LINE__));
12052 Info = _FACILITY_NOT_SUPPORTED;
12053 }
12054 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12055 {
12056 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12057 UnMapId (Id), (char *)(FILE_), __LINE__));
12058 Info = _WRONG_MESSAGE_FORMAT;
12059 }
12060 else
12061 {
12062 result_buffer[0] = 3;
12063 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12064 result_buffer[3] = 0;
12065 switch (GET_WORD (li_parms[0].info))
12066 {
12067 case LI_GET_SUPPORTED_SERVICES:
12068 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12069 {
12070 result_buffer[0] = 17;
12071 result_buffer[3] = 14;
12072 PUT_WORD (&result_buffer[4], GOOD);
12073 d = 0;
12074 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12075 d |= LI_CONFERENCING_SUPPORTED;
12076 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12077 d |= LI_MONITORING_SUPPORTED;
12078 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12079 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12080 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12081 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12082 PUT_DWORD (&result_buffer[6], d);
12083 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084 {
12085 d = 0;
12086 for (i = 0; i < li_total_channels; i++)
12087 {
12088 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12089 && (li_config_table[i].adapter->li_pri
12090 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12091 {
12092 d++;
12093 }
12094 }
12095 }
12096 else
12097 {
12098 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12099 }
12100 PUT_DWORD (&result_buffer[10], d / 2);
12101 PUT_DWORD (&result_buffer[14], d);
12102 }
12103 else
12104 {
12105 result_buffer[0] = 25;
12106 result_buffer[3] = 22;
12107 PUT_WORD (&result_buffer[4], GOOD);
12108 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12109 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12110 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12111 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12112 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12113 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12114 d |= LI2_PC_LOOPING_SUPPORTED;
12115 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12116 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12117 PUT_DWORD (&result_buffer[6], d);
12118 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12119 PUT_DWORD (&result_buffer[10], d / 2);
12120 PUT_DWORD (&result_buffer[14], d - 1);
12121 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12122 {
12123 d = 0;
12124 for (i = 0; i < li_total_channels; i++)
12125 {
12126 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12127 && (li_config_table[i].adapter->li_pri
12128 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12129 {
12130 d++;
12131 }
12132 }
12133 }
12134 PUT_DWORD (&result_buffer[18], d / 2);
12135 PUT_DWORD (&result_buffer[22], d - 1);
12136 }
12137 break;
12138
12139 case LI_REQ_CONNECT:
12140 if (li_parms[1].length == 8)
12141 {
12142 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12143 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12144 {
12145 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12146 UnMapId (Id), (char *)(FILE_), __LINE__));
12147 Info = _WRONG_MESSAGE_FORMAT;
12148 break;
12149 }
12150 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12151 li_flags = GET_DWORD (li_req_parms[1].info);
12152 Info = li_check_main_plci (Id, plci);
12153 result_buffer[0] = 9;
12154 result_buffer[3] = 6;
12155 PUT_DWORD (&result_buffer[4], plci_b_id);
12156 PUT_WORD (&result_buffer[8], GOOD);
12157 if (Info != GOOD)
12158 break;
12159 result = plci->saved_msg.info;
12160 for (i = 0; i <= result_buffer[0]; i++)
12161 result[i] = result_buffer[i];
12162 plci_b_write_pos = plci->li_plci_b_write_pos;
12163 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12164 if (plci_b == NULL)
12165 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012166 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012167 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12168 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12169 plci->li_plci_b_write_pos = plci_b_write_pos;
12170 }
12171 else
12172 {
12173 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12174 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12175 {
12176 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12177 UnMapId (Id), (char *)(FILE_), __LINE__));
12178 Info = _WRONG_MESSAGE_FORMAT;
12179 break;
12180 }
12181 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12182 Info = li_check_main_plci (Id, plci);
12183 result_buffer[0] = 7;
12184 result_buffer[3] = 4;
12185 PUT_WORD (&result_buffer[4], Info);
12186 result_buffer[6] = 0;
12187 if (Info != GOOD)
12188 break;
12189 result = plci->saved_msg.info;
12190 for (i = 0; i <= result_buffer[0]; i++)
12191 result[i] = result_buffer[i];
12192 plci_b_write_pos = plci->li_plci_b_write_pos;
12193 participant_parms_pos = 0;
12194 result_pos = 7;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012195 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012196 while (participant_parms_pos < li_req_parms[1].length)
12197 {
12198 result[result_pos] = 6;
12199 result_pos += 7;
12200 PUT_DWORD (&result[result_pos - 6], 0);
12201 PUT_WORD (&result[result_pos - 2], GOOD);
12202 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12203 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12204 {
12205 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12206 UnMapId (Id), (char *)(FILE_), __LINE__));
12207 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12208 break;
12209 }
12210 if (api_parse (&li_participant_struct[0].info[1],
12211 li_participant_struct[0].length, "dd", li_participant_parms))
12212 {
12213 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12214 UnMapId (Id), (char *)(FILE_), __LINE__));
12215 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12216 break;
12217 }
12218 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12219 li_flags = GET_DWORD (li_participant_parms[1].info);
12220 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12221 if (sizeof(result) - result_pos < 7)
12222 {
12223 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12224 UnMapId (Id), (char *)(FILE_), __LINE__));
12225 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12226 break;
12227 }
12228 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12229 if (plci_b != NULL)
12230 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012231 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012232 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12233 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12234 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12235 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12236 }
12237 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12238 (&li_req_parms[1].info[1]));
12239 }
12240 result[0] = (byte)(result_pos - 1);
12241 result[3] = (byte)(result_pos - 4);
12242 result[6] = (byte)(result_pos - 7);
12243 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12244 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12245 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12246 {
12247 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12248 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12249 }
12250 else
12251 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12252 plci->li_plci_b_write_pos = plci_b_write_pos;
12253 }
12254 mixer_calculate_coefs (a);
12255 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012256 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012257 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12258 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12259 plci->command = 0;
12260 plci->li_cmd = GET_WORD (li_parms[0].info);
12261 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012262 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012263
12264 case LI_REQ_DISCONNECT:
12265 if (li_parms[1].length == 4)
12266 {
12267 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12268 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12269 {
12270 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12271 UnMapId (Id), (char *)(FILE_), __LINE__));
12272 Info = _WRONG_MESSAGE_FORMAT;
12273 break;
12274 }
12275 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12276 Info = li_check_main_plci (Id, plci);
12277 result_buffer[0] = 9;
12278 result_buffer[3] = 6;
12279 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12280 PUT_WORD (&result_buffer[8], GOOD);
12281 if (Info != GOOD)
12282 break;
12283 result = plci->saved_msg.info;
12284 for (i = 0; i <= result_buffer[0]; i++)
12285 result[i] = result_buffer[i];
12286 plci_b_write_pos = plci->li_plci_b_write_pos;
12287 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12288 if (plci_b == NULL)
12289 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012290 li_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012291 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12292 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12293 plci->li_plci_b_write_pos = plci_b_write_pos;
12294 }
12295 else
12296 {
12297 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12298 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12299 {
12300 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12301 UnMapId (Id), (char *)(FILE_), __LINE__));
12302 Info = _WRONG_MESSAGE_FORMAT;
12303 break;
12304 }
12305 Info = li_check_main_plci (Id, plci);
12306 result_buffer[0] = 7;
12307 result_buffer[3] = 4;
12308 PUT_WORD (&result_buffer[4], Info);
12309 result_buffer[6] = 0;
12310 if (Info != GOOD)
12311 break;
12312 result = plci->saved_msg.info;
12313 for (i = 0; i <= result_buffer[0]; i++)
12314 result[i] = result_buffer[i];
12315 plci_b_write_pos = plci->li_plci_b_write_pos;
12316 participant_parms_pos = 0;
12317 result_pos = 7;
12318 while (participant_parms_pos < li_req_parms[0].length)
12319 {
12320 result[result_pos] = 6;
12321 result_pos += 7;
12322 PUT_DWORD (&result[result_pos - 6], 0);
12323 PUT_WORD (&result[result_pos - 2], GOOD);
12324 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12325 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12326 {
12327 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12328 UnMapId (Id), (char *)(FILE_), __LINE__));
12329 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12330 break;
12331 }
12332 if (api_parse (&li_participant_struct[0].info[1],
12333 li_participant_struct[0].length, "d", li_participant_parms))
12334 {
12335 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12336 UnMapId (Id), (char *)(FILE_), __LINE__));
12337 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12338 break;
12339 }
12340 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12341 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12342 if (sizeof(result) - result_pos < 7)
12343 {
12344 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12345 UnMapId (Id), (char *)(FILE_), __LINE__));
12346 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12347 break;
12348 }
12349 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12350 if (plci_b != NULL)
12351 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012352 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012353 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12354 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12355 }
12356 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12357 (&li_req_parms[0].info[1]));
12358 }
12359 result[0] = (byte)(result_pos - 1);
12360 result[3] = (byte)(result_pos - 4);
12361 result[6] = (byte)(result_pos - 7);
12362 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12363 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12364 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12365 {
12366 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12367 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12368 }
12369 else
12370 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12371 plci->li_plci_b_write_pos = plci_b_write_pos;
12372 }
12373 mixer_calculate_coefs (a);
12374 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012375 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012376 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12377 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12378 plci->command = 0;
12379 plci->li_cmd = GET_WORD (li_parms[0].info);
12380 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012381 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012382
12383 case LI_REQ_SILENT_UPDATE:
12384 if (!plci || !plci->State
12385 || !plci->NL.Id || plci->nl_remove_id
12386 || (plci->li_bchannel_id == 0)
12387 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12388 {
12389 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12390 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012391 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012392 }
12393 plci_b_write_pos = plci->li_plci_b_write_pos;
12394 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12395 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12396 {
12397 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12398 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012399 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012400 }
12401 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12402 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12403 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12404 {
12405 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12406 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12407 }
12408 else
12409 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12410 plci->li_plci_b_write_pos = plci_b_write_pos;
12411 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12412 plci->command = 0;
12413 plci->li_cmd = GET_WORD (li_parms[0].info);
12414 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012415 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012416
12417 default:
12418 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12419 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12420 Info = _FACILITY_NOT_SUPPORTED;
12421 }
12422 }
12423 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12424 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012425 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012426}
12427
12428
12429static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12430{
12431 dword d;
12432 DIVA_CAPI_ADAPTER *a;
12433 byte result[12];
12434
12435 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12436 UnMapId (Id), (char *)(FILE_), __LINE__));
12437
12438 a = plci->adapter;
12439 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12440 {
12441 do
12442 {
12443 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12444 if (!(d & LI_PLCI_B_SKIP_FLAG))
12445 {
12446 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12447 {
12448 if (d & LI_PLCI_B_DISC_FLAG)
12449 {
12450 result[0] = 5;
12451 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12452 result[3] = 2;
12453 PUT_WORD (&result[4], _LI_USER_INITIATED);
12454 }
12455 else
12456 {
12457 result[0] = 7;
12458 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12459 result[3] = 4;
12460 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12461 }
12462 }
12463 else
12464 {
12465 if (d & LI_PLCI_B_DISC_FLAG)
12466 {
12467 result[0] = 9;
12468 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12469 result[3] = 6;
12470 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12471 PUT_WORD (&result[8], _LI_USER_INITIATED);
12472 }
12473 else
12474 {
12475 result[0] = 7;
12476 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12477 result[3] = 4;
12478 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12479 }
12480 }
12481 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12482 "ws", SELECTOR_LINE_INTERCONNECT, result);
12483 }
12484 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12485 0 : plci->li_plci_b_read_pos + 1;
12486 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12487 }
12488}
12489
12490
12491static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12492{
12493 word i, j, ch;
12494 struct xconnect_transfer_address_s s, *p;
12495 DIVA_CAPI_ADAPTER *a;
12496
12497 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12498 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12499
12500 a = plci->adapter;
12501 i = 1;
12502 for (i = 1; i < length; i += 16)
12503 {
12504 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12505 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12506 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12507 ch = msg[i+12] | (msg[i+13] << 8);
12508 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12509 if (!a->li_pri && (plci->li_bchannel_id == 2))
12510 j = 1 - j;
12511 j += a->li_base;
12512 if (ch & XCONNECT_CHANNEL_PORT_PC)
12513 p = &(li_config_table[j].send_pc);
12514 else
12515 p = &(li_config_table[j].send_b);
12516 p->card_address.low = s.card_address.low;
12517 p->card_address.high = s.card_address.high;
12518 p->offset = s.offset;
12519 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12520 }
12521 if (plci->internal_command_queue[0]
12522 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12523 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12524 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12525 {
12526 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12527 if (!plci->internal_command)
12528 next_internal_command (Id, plci);
12529 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012530 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012531}
12532
12533
12534static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12535{
12536
12537 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12538 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12539
12540}
12541
12542
12543static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12544{
12545 word plci_b_write_pos;
12546
12547 plci_b_write_pos = plci->li_plci_b_write_pos;
12548 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12549 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12550 {
12551 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12552 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12553 (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012554 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012555 }
12556 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12557 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12558 plci->li_plci_b_write_pos = plci_b_write_pos;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012559 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012560}
12561
12562
12563static void mixer_remove (PLCI *plci)
12564{
12565 DIVA_CAPI_ADAPTER *a;
12566 PLCI *notify_plci;
12567 dword plci_b_id;
12568 word i, j;
12569
12570 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12571 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12572 (char *)(FILE_), __LINE__));
12573
12574 a = plci->adapter;
12575 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12576 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12577 {
12578 if ((plci->li_bchannel_id != 0)
12579 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12580 {
12581 i = a->li_base + (plci->li_bchannel_id - 1);
12582 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12583 {
12584 for (j = 0; j < li_total_channels; j++)
12585 {
12586 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12587 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12588 {
12589 notify_plci = li_config_table[j].plci;
12590 if ((notify_plci != NULL)
12591 && (notify_plci != plci)
12592 && (notify_plci->appl != NULL)
12593 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12594 && (notify_plci->State)
12595 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12596 {
12597 mixer_notify_source_removed (notify_plci, plci_b_id);
12598 }
12599 }
12600 }
12601 mixer_clear_config (plci);
12602 mixer_calculate_coefs (a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012603 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012604 }
12605 li_config_table[i].plci = NULL;
12606 plci->li_bchannel_id = 0;
12607 }
12608 }
12609}
12610
12611
12612/*------------------------------------------------------------------*/
12613/* Echo canceller facilities */
12614/*------------------------------------------------------------------*/
12615
12616
12617static void ec_write_parameters (PLCI *plci)
12618{
12619 word w;
12620 byte parameter_buffer[6];
12621
12622 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12623 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12624 (char *)(FILE_), __LINE__));
12625
12626 parameter_buffer[0] = 5;
12627 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12628 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12629 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12630 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12631 PUT_WORD (&parameter_buffer[4], w);
12632 add_p (plci, FTY, parameter_buffer);
12633 sig_req (plci, TEL_CTRL, 0);
12634 send_req (plci);
12635}
12636
12637
12638static void ec_clear_config (PLCI *plci)
12639{
12640
12641 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12642 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12643 (char *)(FILE_), __LINE__));
12644
12645 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12646 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12647 plci->ec_tail_length = 0;
12648}
12649
12650
12651static void ec_prepare_switch (dword Id, PLCI *plci)
12652{
12653
12654 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12655 UnMapId (Id), (char *)(FILE_), __LINE__));
12656
12657}
12658
12659
12660static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12661{
12662
12663 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12664 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12665
12666 return (GOOD);
12667}
12668
12669
12670static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12671{
12672 word Info;
12673
12674 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12675 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12676
12677 Info = GOOD;
12678 if (plci->B1_facilities & B1_FACILITY_EC)
12679 {
12680 switch (plci->adjust_b_state)
12681 {
12682 case ADJUST_B_RESTORE_EC_1:
12683 plci->internal_command = plci->adjust_b_command;
12684 if (plci->sig_req)
12685 {
12686 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12687 break;
12688 }
12689 ec_write_parameters (plci);
12690 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12691 break;
12692 case ADJUST_B_RESTORE_EC_2:
12693 if ((Rc != OK) && (Rc != OK_FC))
12694 {
12695 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12697 Info = _WRONG_STATE;
12698 break;
12699 }
12700 break;
12701 }
12702 }
12703 return (Info);
12704}
12705
12706
12707static void ec_command (dword Id, PLCI *plci, byte Rc)
12708{
12709 word internal_command, Info;
12710 byte result[8];
12711
12712 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12713 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12714 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12715
12716 Info = GOOD;
12717 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12718 {
12719 result[0] = 2;
12720 PUT_WORD (&result[1], EC_SUCCESS);
12721 }
12722 else
12723 {
12724 result[0] = 5;
12725 PUT_WORD (&result[1], plci->ec_cmd);
12726 result[3] = 2;
12727 PUT_WORD (&result[4], GOOD);
12728 }
12729 internal_command = plci->internal_command;
12730 plci->internal_command = 0;
12731 switch (plci->ec_cmd)
12732 {
12733 case EC_ENABLE_OPERATION:
12734 case EC_FREEZE_COEFFICIENTS:
12735 case EC_RESUME_COEFFICIENT_UPDATE:
12736 case EC_RESET_COEFFICIENTS:
12737 switch (internal_command)
12738 {
12739 default:
12740 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12741 B1_FACILITY_EC), EC_COMMAND_1);
12742 case EC_COMMAND_1:
12743 if (adjust_b_process (Id, plci, Rc) != GOOD)
12744 {
12745 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12746 UnMapId (Id), (char *)(FILE_), __LINE__));
12747 Info = _FACILITY_NOT_SUPPORTED;
12748 break;
12749 }
12750 if (plci->internal_command)
12751 return;
12752 case EC_COMMAND_2:
12753 if (plci->sig_req)
12754 {
12755 plci->internal_command = EC_COMMAND_2;
12756 return;
12757 }
12758 plci->internal_command = EC_COMMAND_3;
12759 ec_write_parameters (plci);
12760 return;
12761 case EC_COMMAND_3:
12762 if ((Rc != OK) && (Rc != OK_FC))
12763 {
12764 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12765 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12766 Info = _FACILITY_NOT_SUPPORTED;
12767 break;
12768 }
12769 break;
12770 }
12771 break;
12772
12773 case EC_DISABLE_OPERATION:
12774 switch (internal_command)
12775 {
12776 default:
12777 case EC_COMMAND_1:
12778 if (plci->B1_facilities & B1_FACILITY_EC)
12779 {
12780 if (plci->sig_req)
12781 {
12782 plci->internal_command = EC_COMMAND_1;
12783 return;
12784 }
12785 plci->internal_command = EC_COMMAND_2;
12786 ec_write_parameters (plci);
12787 return;
12788 }
12789 Rc = OK;
12790 case EC_COMMAND_2:
12791 if ((Rc != OK) && (Rc != OK_FC))
12792 {
12793 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12794 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12795 Info = _FACILITY_NOT_SUPPORTED;
12796 break;
12797 }
12798 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12799 ~B1_FACILITY_EC), EC_COMMAND_3);
12800 case EC_COMMAND_3:
12801 if (adjust_b_process (Id, plci, Rc) != GOOD)
12802 {
12803 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12804 UnMapId (Id), (char *)(FILE_), __LINE__));
12805 Info = _FACILITY_NOT_SUPPORTED;
12806 break;
12807 }
12808 if (plci->internal_command)
12809 return;
12810 break;
12811 }
12812 break;
12813 }
12814 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12815 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12816 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12817}
12818
12819
12820static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12821{
12822 word Info;
12823 word opt;
12824 API_PARSE ec_parms[3];
12825 byte result[16];
12826
12827 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12828 UnMapId (Id), (char *)(FILE_), __LINE__));
12829
12830 Info = GOOD;
12831 result[0] = 0;
12832 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12833 {
12834 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12835 UnMapId (Id), (char *)(FILE_), __LINE__));
12836 Info = _FACILITY_NOT_SUPPORTED;
12837 }
12838 else
12839 {
12840 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12841 {
12842 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12843 {
12844 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12845 UnMapId (Id), (char *)(FILE_), __LINE__));
12846 Info = _WRONG_MESSAGE_FORMAT;
12847 }
12848 else
12849 {
12850 if (plci == NULL)
12851 {
12852 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12853 UnMapId (Id), (char *)(FILE_), __LINE__));
12854 Info = _WRONG_IDENTIFIER;
12855 }
12856 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12857 {
12858 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12859 UnMapId (Id), (char *)(FILE_), __LINE__));
12860 Info = _WRONG_STATE;
12861 }
12862 else
12863 {
12864 plci->command = 0;
12865 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12866 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12867 result[0] = 2;
12868 PUT_WORD (&result[1], EC_SUCCESS);
12869 if (msg[1].length >= 4)
12870 {
12871 opt = GET_WORD (&ec_parms[0].info[2]);
12872 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12873 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12874 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12875 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12876 if (opt & EC_DETECT_DISABLE_TONE)
12877 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12878 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12879 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12880 if (msg[1].length >= 6)
12881 {
12882 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12883 }
12884 }
12885 switch (plci->ec_cmd)
12886 {
12887 case EC_ENABLE_OPERATION:
12888 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12889 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012890 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012891
12892 case EC_DISABLE_OPERATION:
12893 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12894 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12895 LEC_RESET_COEFFICIENTS;
12896 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012897 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012898
12899 case EC_FREEZE_COEFFICIENTS:
12900 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12901 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012902 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012903
12904 case EC_RESUME_COEFFICIENT_UPDATE:
12905 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12906 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012907 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012908
12909 case EC_RESET_COEFFICIENTS:
12910 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12911 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012912 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012913
12914 default:
12915 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12916 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12917 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12918 }
12919 }
12920 }
12921 }
12922 else
12923 {
12924 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12925 {
12926 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12927 UnMapId (Id), (char *)(FILE_), __LINE__));
12928 Info = _WRONG_MESSAGE_FORMAT;
12929 }
12930 else
12931 {
12932 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12933 {
12934 result[0] = 11;
12935 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12936 result[3] = 8;
12937 PUT_WORD (&result[4], GOOD);
12938 PUT_WORD (&result[6], 0x0007);
12939 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12940 PUT_WORD (&result[10], 0);
12941 }
12942 else if (plci == NULL)
12943 {
12944 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12945 UnMapId (Id), (char *)(FILE_), __LINE__));
12946 Info = _WRONG_IDENTIFIER;
12947 }
12948 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12949 {
12950 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12951 UnMapId (Id), (char *)(FILE_), __LINE__));
12952 Info = _WRONG_STATE;
12953 }
12954 else
12955 {
12956 plci->command = 0;
12957 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12958 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12959 result[0] = 5;
12960 PUT_WORD (&result[1], plci->ec_cmd);
12961 result[3] = 2;
12962 PUT_WORD (&result[4], GOOD);
12963 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12964 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12965 plci->ec_tail_length = 0;
12966 if (ec_parms[1].length >= 2)
12967 {
12968 opt = GET_WORD (&ec_parms[1].info[1]);
12969 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12970 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12971 if (opt & EC_DETECT_DISABLE_TONE)
12972 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12973 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12974 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12975 if (ec_parms[1].length >= 4)
12976 {
12977 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12978 }
12979 }
12980 switch (plci->ec_cmd)
12981 {
12982 case EC_ENABLE_OPERATION:
12983 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12984 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012985 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012986
12987 case EC_DISABLE_OPERATION:
12988 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12989 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12990 LEC_RESET_COEFFICIENTS;
12991 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012992 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012993
12994 default:
12995 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12996 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12997 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12998 }
12999 }
13000 }
13001 }
13002 }
13003 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13004 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13005 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013006 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013007}
13008
13009
13010static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13011{
13012 byte result[8];
13013
13014 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13015 UnMapId (Id), (char *)(FILE_), __LINE__));
13016
13017 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13018 {
13019 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13020 {
13021 result[0] = 2;
13022 PUT_WORD (&result[1], 0);
13023 switch (msg[1])
13024 {
13025 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13026 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13027 break;
13028 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13029 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13030 break;
13031 case LEC_DISABLE_RELEASED:
13032 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13033 break;
13034 }
13035 }
13036 else
13037 {
13038 result[0] = 5;
13039 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13040 result[3] = 2;
13041 PUT_WORD (&result[4], 0);
13042 switch (msg[1])
13043 {
13044 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046 break;
13047 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049 break;
13050 case LEC_DISABLE_RELEASED:
13051 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13052 break;
13053 }
13054 }
13055 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13056 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13057 }
13058}
13059
13060
13061
13062/*------------------------------------------------------------------*/
13063/* Advanced voice */
13064/*------------------------------------------------------------------*/
13065
13066static void adv_voice_write_coefs (PLCI *plci, word write_command)
13067{
13068 DIVA_CAPI_ADAPTER *a;
13069 word i;
13070 byte *p;
13071
13072 word w, n, j, k;
13073 byte ch_map[MIXER_CHANNELS_BRI];
13074
13075 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13076
13077 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13078 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13079 (char *)(FILE_), __LINE__, write_command));
13080
13081 a = plci->adapter;
13082 p = coef_buffer + 1;
13083 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13084 i = 0;
13085 while (i + sizeof(word) <= a->adv_voice_coef_length)
13086 {
13087 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13088 p += 2;
13089 i += 2;
13090 }
13091 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13092 {
13093 PUT_WORD (p, 0x8000);
13094 p += 2;
13095 i += 2;
13096 }
13097
13098 if (!a->li_pri && (plci->li_bchannel_id == 0))
13099 {
13100 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13101 {
13102 plci->li_bchannel_id = 1;
13103 li_config_table[a->li_base].plci = plci;
13104 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13105 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13106 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13107 }
13108 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13109 {
13110 plci->li_bchannel_id = 2;
13111 li_config_table[a->li_base + 1].plci = plci;
13112 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13114 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13115 }
13116 }
13117 if (!a->li_pri && (plci->li_bchannel_id != 0)
13118 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13119 {
13120 i = a->li_base + (plci->li_bchannel_id - 1);
13121 switch (write_command)
13122 {
13123 case ADV_VOICE_WRITE_ACTIVATION:
13124 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13125 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13126 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13127 {
13128 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13130 }
13131 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13132 {
13133 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13134 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13135 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13136 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13137 }
13138 mixer_calculate_coefs (a);
13139 li_config_table[i].curchnl = li_config_table[i].channel;
13140 li_config_table[j].curchnl = li_config_table[j].channel;
13141 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13142 li_config_table[k].curchnl = li_config_table[k].channel;
13143 break;
13144
13145 case ADV_VOICE_WRITE_DEACTIVATION:
13146 for (j = 0; j < li_total_channels; j++)
13147 {
13148 li_config_table[i].flag_table[j] = 0;
13149 li_config_table[j].flag_table[i] = 0;
13150 }
13151 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13152 for (j = 0; j < li_total_channels; j++)
13153 {
13154 li_config_table[k].flag_table[j] = 0;
13155 li_config_table[j].flag_table[k] = 0;
13156 }
13157 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13158 {
13159 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13160 for (j = 0; j < li_total_channels; j++)
13161 {
13162 li_config_table[k].flag_table[j] = 0;
13163 li_config_table[j].flag_table[k] = 0;
13164 }
13165 }
13166 mixer_calculate_coefs (a);
13167 break;
13168 }
13169 if (plci->B1_facilities & B1_FACILITY_MIXER)
13170 {
13171 w = 0;
13172 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13173 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13174 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13175 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13176 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13177 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13178 *(p++) = (byte) w;
13179 *(p++) = (byte)(w >> 8);
13180 for (j = 0; j < sizeof(ch_map); j += 2)
13181 {
13182 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13183 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13184 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080013185 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013186 {
13187 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13188 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13189 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13190 {
13191 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13192 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13193 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13194 }
13195 else
13196 {
13197 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13198 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13199 }
13200 }
13201 }
13202 else
13203 {
13204 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13205 *(p++) = a->adv_voice_coef_buffer[i];
13206 }
13207 }
13208 else
13209
13210 {
13211 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212 *(p++) = a->adv_voice_coef_buffer[i];
13213 }
13214 coef_buffer[0] = (p - coef_buffer) - 1;
13215 add_p (plci, FTY, coef_buffer);
13216 sig_req (plci, TEL_CTRL, 0);
13217 send_req (plci);
13218}
13219
13220
13221static void adv_voice_clear_config (PLCI *plci)
13222{
13223 DIVA_CAPI_ADAPTER *a;
13224
13225 word i, j;
13226
13227
13228 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13229 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13230 (char *)(FILE_), __LINE__));
13231
13232 a = plci->adapter;
13233 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13234 {
13235 a->adv_voice_coef_length = 0;
13236
13237 if (!a->li_pri && (plci->li_bchannel_id != 0)
13238 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13239 {
13240 i = a->li_base + (plci->li_bchannel_id - 1);
13241 li_config_table[i].curchnl = 0;
13242 li_config_table[i].channel = 0;
13243 li_config_table[i].chflags = 0;
13244 for (j = 0; j < li_total_channels; j++)
13245 {
13246 li_config_table[i].flag_table[j] = 0;
13247 li_config_table[j].flag_table[i] = 0;
13248 li_config_table[i].coef_table[j] = 0;
13249 li_config_table[j].coef_table[i] = 0;
13250 }
13251 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13252 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13253 li_config_table[i].curchnl = 0;
13254 li_config_table[i].channel = 0;
13255 li_config_table[i].chflags = 0;
13256 for (j = 0; j < li_total_channels; j++)
13257 {
13258 li_config_table[i].flag_table[j] = 0;
13259 li_config_table[j].flag_table[i] = 0;
13260 li_config_table[i].coef_table[j] = 0;
13261 li_config_table[j].coef_table[i] = 0;
13262 }
13263 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13264 {
13265 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13266 li_config_table[i].curchnl = 0;
13267 li_config_table[i].channel = 0;
13268 li_config_table[i].chflags = 0;
13269 for (j = 0; j < li_total_channels; j++)
13270 {
13271 li_config_table[i].flag_table[j] = 0;
13272 li_config_table[j].flag_table[i] = 0;
13273 li_config_table[i].coef_table[j] = 0;
13274 li_config_table[j].coef_table[i] = 0;
13275 }
13276 }
13277 }
13278
13279 }
13280}
13281
13282
13283static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13284{
13285
13286 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13287 UnMapId (Id), (char *)(FILE_), __LINE__));
13288
13289}
13290
13291
13292static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13293{
13294
13295 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13296 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13297
13298 return (GOOD);
13299}
13300
13301
13302static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13303{
13304 DIVA_CAPI_ADAPTER *a;
13305 word Info;
13306
13307 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13308 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13309
13310 Info = GOOD;
13311 a = plci->adapter;
13312 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13313 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13314 {
13315 switch (plci->adjust_b_state)
13316 {
13317 case ADJUST_B_RESTORE_VOICE_1:
13318 plci->internal_command = plci->adjust_b_command;
13319 if (plci->sig_req)
13320 {
13321 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13322 break;
13323 }
13324 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13325 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13326 break;
13327 case ADJUST_B_RESTORE_VOICE_2:
13328 if ((Rc != OK) && (Rc != OK_FC))
13329 {
13330 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13331 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13332 Info = _WRONG_STATE;
13333 break;
13334 }
13335 break;
13336 }
13337 }
13338 return (Info);
13339}
13340
13341
13342
13343
13344/*------------------------------------------------------------------*/
13345/* B1 resource switching */
13346/*------------------------------------------------------------------*/
13347
13348static byte b1_facilities_table[] =
13349{
13350 0x00, /* 0 No bchannel resources */
13351 0x00, /* 1 Codec (automatic law) */
13352 0x00, /* 2 Codec (A-law) */
13353 0x00, /* 3 Codec (y-law) */
13354 0x00, /* 4 HDLC for X.21 */
13355 0x00, /* 5 HDLC */
13356 0x00, /* 6 External Device 0 */
13357 0x00, /* 7 External Device 1 */
13358 0x00, /* 8 HDLC 56k */
13359 0x00, /* 9 Transparent */
13360 0x00, /* 10 Loopback to network */
13361 0x00, /* 11 Test pattern to net */
13362 0x00, /* 12 Rate adaptation sync */
13363 0x00, /* 13 Rate adaptation async */
13364 0x00, /* 14 R-Interface */
13365 0x00, /* 15 HDLC 128k leased line */
13366 0x00, /* 16 FAX */
13367 0x00, /* 17 Modem async */
13368 0x00, /* 18 Modem sync HDLC */
13369 0x00, /* 19 V.110 async HDLC */
13370 0x12, /* 20 Adv voice (Trans,mixer) */
13371 0x00, /* 21 Codec connected to IC */
13372 0x0c, /* 22 Trans,DTMF */
13373 0x1e, /* 23 Trans,DTMF+mixer */
13374 0x1f, /* 24 Trans,DTMF+mixer+local */
13375 0x13, /* 25 Trans,mixer+local */
13376 0x12, /* 26 HDLC,mixer */
13377 0x12, /* 27 HDLC 56k,mixer */
13378 0x2c, /* 28 Trans,LEC+DTMF */
13379 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13380 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13381 0x2c, /* 31 RTP,LEC+DTMF */
13382 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13383 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13384 0x00, /* 34 Signaling task */
13385 0x00, /* 35 PIAFS */
13386 0x0c, /* 36 Trans,DTMF+TONE */
13387 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13388 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13389};
13390
13391
13392static word get_b1_facilities (PLCI * plci, byte b1_resource)
13393{
13394 word b1_facilities;
13395
13396 b1_facilities = b1_facilities_table[b1_resource];
13397 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13398 {
13399
13400 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13401 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13402
13403 {
13404 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13405 b1_facilities |= B1_FACILITY_DTMFX;
13406 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13407 b1_facilities |= B1_FACILITY_DTMFR;
13408 }
13409 }
13410 if ((b1_resource == 17) || (b1_resource == 18))
13411 {
13412 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13413 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13414 }
13415/*
13416 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13417 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13418 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13419*/
13420 return (b1_facilities);
13421}
13422
13423
13424static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13425{
13426 byte b;
13427
13428 switch (b1_resource)
13429 {
13430 case 5:
13431 case 26:
13432 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13433 b = 26;
13434 else
13435 b = 5;
13436 break;
13437
13438 case 8:
13439 case 27:
13440 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441 b = 27;
13442 else
13443 b = 8;
13444 break;
13445
13446 case 9:
13447 case 20:
13448 case 22:
13449 case 23:
13450 case 24:
13451 case 25:
13452 case 28:
13453 case 29:
13454 case 30:
13455 case 36:
13456 case 37:
13457 case 38:
13458 if (b1_facilities & B1_FACILITY_EC)
13459 {
13460 if (b1_facilities & B1_FACILITY_LOCAL)
13461 b = 30;
13462 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13463 b = 29;
13464 else
13465 b = 28;
13466 }
13467
13468 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13469 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13470 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13471 {
13472 if (b1_facilities & B1_FACILITY_LOCAL)
13473 b = 38;
13474 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13475 b = 37;
13476 else
13477 b = 36;
13478 }
13479
13480 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13481 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13482 || ((b1_facilities & B1_FACILITY_DTMFR)
13483 && ((b1_facilities & B1_FACILITY_MIXER)
13484 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13485 || ((b1_facilities & B1_FACILITY_DTMFX)
13486 && ((b1_facilities & B1_FACILITY_MIXER)
13487 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13488 {
13489 if (b1_facilities & B1_FACILITY_LOCAL)
13490 b = 24;
13491 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13492 b = 23;
13493 else
13494 b = 22;
13495 }
13496 else
13497 {
13498 if (b1_facilities & B1_FACILITY_LOCAL)
13499 b = 25;
13500 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13501 b = 20;
13502 else
13503 b = 9;
13504 }
13505 break;
13506
13507 case 31:
13508 case 32:
13509 case 33:
13510 if (b1_facilities & B1_FACILITY_LOCAL)
13511 b = 33;
13512 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13513 b = 32;
13514 else
13515 b = 31;
13516 break;
13517
13518 default:
13519 b = b1_resource;
13520 }
13521 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13522 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13523 (char *)(FILE_), __LINE__,
13524 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13525 return (b);
13526}
13527
13528
13529static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13530{
13531 word removed_facilities;
13532
13533 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13534 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13535 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13536 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13537
13538 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13539 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13540
13541 if (removed_facilities & B1_FACILITY_EC)
13542 ec_clear_config (plci);
13543
13544
13545 if (removed_facilities & B1_FACILITY_DTMFR)
13546 {
13547 dtmf_rec_clear_config (plci);
13548 dtmf_parameter_clear_config (plci);
13549 }
13550 if (removed_facilities & B1_FACILITY_DTMFX)
13551 dtmf_send_clear_config (plci);
13552
13553
13554 if (removed_facilities & B1_FACILITY_MIXER)
13555 mixer_clear_config (plci);
13556
13557 if (removed_facilities & B1_FACILITY_VOICE)
13558 adv_voice_clear_config (plci);
13559 plci->B1_facilities = new_b1_facilities;
13560}
13561
13562
13563static void adjust_b_clear (PLCI *plci)
13564{
13565
13566 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13567 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13568 (char *)(FILE_), __LINE__));
13569
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013570 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013571}
13572
13573
13574static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13575{
13576 word Info;
13577 byte b1_resource;
13578 NCCI * ncci_ptr;
13579 API_PARSE bp[2];
13580
13581 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13582 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13583
13584 Info = GOOD;
13585 switch (plci->adjust_b_state)
13586 {
13587 case ADJUST_B_START:
13588 if ((plci->adjust_b_parms_msg == NULL)
13589 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13590 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13591 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13592 {
13593 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13594 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13595 if (b1_resource == plci->B1_resource)
13596 {
13597 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13598 break;
13599 }
13600 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13601 {
13602 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13603 UnMapId (Id), (char *)(FILE_), __LINE__,
13604 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13605 Info = _WRONG_STATE;
13606 break;
13607 }
13608 }
13609 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13610 {
13611
13612 mixer_prepare_switch (Id, plci);
13613
13614
13615 dtmf_prepare_switch (Id, plci);
13616 dtmf_parameter_prepare_switch (Id, plci);
13617
13618
13619 ec_prepare_switch (Id, plci);
13620
13621 adv_voice_prepare_switch (Id, plci);
13622 }
13623 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13624 Rc = OK;
13625 case ADJUST_B_SAVE_MIXER_1:
13626 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13627 {
13628
13629 Info = mixer_save_config (Id, plci, Rc);
13630 if ((Info != GOOD) || plci->internal_command)
13631 break;
13632
13633 }
13634 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13635 Rc = OK;
13636 case ADJUST_B_SAVE_DTMF_1:
13637 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13638 {
13639
13640 Info = dtmf_save_config (Id, plci, Rc);
13641 if ((Info != GOOD) || plci->internal_command)
13642 break;
13643
13644 }
13645 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13646 case ADJUST_B_REMOVE_L23_1:
13647 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13648 && plci->NL.Id && !plci->nl_remove_id)
13649 {
13650 plci->internal_command = plci->adjust_b_command;
13651 if (plci->adjust_b_ncci != 0)
13652 {
13653 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13654 while (ncci_ptr->data_pending)
13655 {
13656 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13657 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13658 }
13659 while (ncci_ptr->data_ack_pending)
13660 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13661 }
13662 nl_req_ncci (plci, REMOVE,
13663 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13664 send_req (plci);
13665 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13666 break;
13667 }
13668 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13669 Rc = OK;
13670 case ADJUST_B_REMOVE_L23_2:
13671 if ((Rc != OK) && (Rc != OK_FC))
13672 {
13673 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13674 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13675 Info = _WRONG_STATE;
13676 break;
13677 }
13678 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13679 {
13680 if (plci_nl_busy (plci))
13681 {
13682 plci->internal_command = plci->adjust_b_command;
13683 break;
13684 }
13685 }
13686 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13687 Rc = OK;
13688 case ADJUST_B_SAVE_EC_1:
13689 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13690 {
13691
13692 Info = ec_save_config (Id, plci, Rc);
13693 if ((Info != GOOD) || plci->internal_command)
13694 break;
13695
13696 }
13697 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13698 Rc = OK;
13699 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13700 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13701 {
13702
13703 Info = dtmf_parameter_save_config (Id, plci, Rc);
13704 if ((Info != GOOD) || plci->internal_command)
13705 break;
13706
13707 }
13708 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13709 Rc = OK;
13710 case ADJUST_B_SAVE_VOICE_1:
13711 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13712 {
13713 Info = adv_voice_save_config (Id, plci, Rc);
13714 if ((Info != GOOD) || plci->internal_command)
13715 break;
13716 }
13717 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13718 case ADJUST_B_SWITCH_L1_1:
13719 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13720 {
13721 if (plci->sig_req)
13722 {
13723 plci->internal_command = plci->adjust_b_command;
13724 break;
13725 }
13726 if (plci->adjust_b_parms_msg != NULL)
13727 api_load_msg (plci->adjust_b_parms_msg, bp);
13728 else
13729 api_load_msg (&plci->B_protocol, bp);
13730 Info = add_b1 (plci, bp,
13731 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13732 plci->adjust_b_facilities);
13733 if (Info != GOOD)
13734 {
13735 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13736 UnMapId (Id), (char *)(FILE_), __LINE__,
13737 plci->B1_resource, plci->adjust_b_facilities));
13738 break;
13739 }
13740 plci->internal_command = plci->adjust_b_command;
13741 sig_req (plci, RESOURCES, 0);
13742 send_req (plci);
13743 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13744 break;
13745 }
13746 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13747 Rc = OK;
13748 case ADJUST_B_SWITCH_L1_2:
13749 if ((Rc != OK) && (Rc != OK_FC))
13750 {
13751 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13752 UnMapId (Id), (char *)(FILE_), __LINE__,
13753 Rc, plci->B1_resource, plci->adjust_b_facilities));
13754 Info = _WRONG_STATE;
13755 break;
13756 }
13757 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13758 Rc = OK;
13759 case ADJUST_B_RESTORE_VOICE_1:
13760 case ADJUST_B_RESTORE_VOICE_2:
13761 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13762 {
13763 Info = adv_voice_restore_config (Id, plci, Rc);
13764 if ((Info != GOOD) || plci->internal_command)
13765 break;
13766 }
13767 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13768 Rc = OK;
13769 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13771 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13772 {
13773
13774 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13775 if ((Info != GOOD) || plci->internal_command)
13776 break;
13777
13778 }
13779 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13780 Rc = OK;
13781 case ADJUST_B_RESTORE_EC_1:
13782 case ADJUST_B_RESTORE_EC_2:
13783 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13784 {
13785
13786 Info = ec_restore_config (Id, plci, Rc);
13787 if ((Info != GOOD) || plci->internal_command)
13788 break;
13789
13790 }
13791 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13792 case ADJUST_B_ASSIGN_L23_1:
13793 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13794 {
13795 if (plci_nl_busy (plci))
13796 {
13797 plci->internal_command = plci->adjust_b_command;
13798 break;
13799 }
13800 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13801 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13802 if (plci->adjust_b_parms_msg != NULL)
13803 api_load_msg (plci->adjust_b_parms_msg, bp);
13804 else
13805 api_load_msg (&plci->B_protocol, bp);
13806 Info = add_b23 (plci, bp);
13807 if (Info != GOOD)
13808 {
13809 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13810 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13811 break;
13812 }
13813 plci->internal_command = plci->adjust_b_command;
13814 nl_req_ncci (plci, ASSIGN, 0);
13815 send_req (plci);
13816 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13817 break;
13818 }
13819 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13820 Rc = ASSIGN_OK;
13821 case ADJUST_B_ASSIGN_L23_2:
13822 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13823 {
13824 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13825 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13826 Info = _WRONG_STATE;
13827 break;
13828 }
13829 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13830 {
13831 if (Rc != ASSIGN_OK)
13832 {
13833 plci->internal_command = plci->adjust_b_command;
13834 break;
13835 }
13836 }
13837 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13838 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013839 plci->adjust_b_restore = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013840 break;
13841 }
13842 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13843 case ADJUST_B_CONNECT_1:
13844 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13845 {
13846 plci->internal_command = plci->adjust_b_command;
13847 if (plci_nl_busy (plci))
13848 break;
13849 nl_req_ncci (plci, N_CONNECT, 0);
13850 send_req (plci);
13851 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13852 break;
13853 }
13854 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13855 Rc = OK;
13856 case ADJUST_B_CONNECT_2:
13857 case ADJUST_B_CONNECT_3:
13858 case ADJUST_B_CONNECT_4:
13859 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13860 {
13861 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13862 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13863 Info = _WRONG_STATE;
13864 break;
13865 }
13866 if (Rc == OK)
13867 {
13868 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13869 {
13870 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13871 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13872 }
13873 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13874 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13875 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13876 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13877 }
13878 else if (Rc == 0)
13879 {
13880 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13882 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13883 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13884 }
13885 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13886 {
13887 plci->internal_command = plci->adjust_b_command;
13888 break;
13889 }
13890 Rc = OK;
13891 case ADJUST_B_RESTORE_DTMF_1:
13892 case ADJUST_B_RESTORE_DTMF_2:
13893 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13894 {
13895
13896 Info = dtmf_restore_config (Id, plci, Rc);
13897 if ((Info != GOOD) || plci->internal_command)
13898 break;
13899
13900 }
13901 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13902 Rc = OK;
13903 case ADJUST_B_RESTORE_MIXER_1:
13904 case ADJUST_B_RESTORE_MIXER_2:
13905 case ADJUST_B_RESTORE_MIXER_3:
13906 case ADJUST_B_RESTORE_MIXER_4:
13907 case ADJUST_B_RESTORE_MIXER_5:
13908 case ADJUST_B_RESTORE_MIXER_6:
13909 case ADJUST_B_RESTORE_MIXER_7:
13910 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13911 {
13912
13913 Info = mixer_restore_config (Id, plci, Rc);
13914 if ((Info != GOOD) || plci->internal_command)
13915 break;
13916
13917 }
13918 plci->adjust_b_state = ADJUST_B_END;
13919 case ADJUST_B_END:
13920 break;
13921 }
13922 return (Info);
13923}
13924
13925
13926static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13927{
13928
13929 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13930 UnMapId (Id), (char *)(FILE_), __LINE__,
13931 plci->B1_resource, b1_facilities));
13932
13933 plci->adjust_b_parms_msg = bp_msg;
13934 plci->adjust_b_facilities = b1_facilities;
13935 plci->adjust_b_command = internal_command;
13936 plci->adjust_b_ncci = (word)(Id >> 16);
13937 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13938 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13939 else
13940 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13941 plci->adjust_b_state = ADJUST_B_START;
13942 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13943 UnMapId (Id), (char *)(FILE_), __LINE__,
13944 plci->B1_resource, b1_facilities));
13945}
13946
13947
13948static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13949{
13950 word internal_command;
13951
13952 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13953 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13954
13955 internal_command = plci->internal_command;
13956 plci->internal_command = 0;
13957 switch (internal_command)
13958 {
13959 default:
13960 plci->command = 0;
13961 if (plci->req_in != 0)
13962 {
13963 plci->internal_command = ADJUST_B_RESTORE_1;
13964 break;
13965 }
13966 Rc = OK;
13967 case ADJUST_B_RESTORE_1:
13968 if ((Rc != OK) && (Rc != OK_FC))
13969 {
13970 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13971 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13972 }
13973 plci->adjust_b_parms_msg = NULL;
13974 plci->adjust_b_facilities = plci->B1_facilities;
13975 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13976 plci->adjust_b_ncci = (word)(Id >> 16);
13977 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13978 plci->adjust_b_state = ADJUST_B_START;
13979 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13980 UnMapId (Id), (char *)(FILE_), __LINE__));
13981 case ADJUST_B_RESTORE_2:
13982 if (adjust_b_process (Id, plci, Rc) != GOOD)
13983 {
13984 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13985 UnMapId (Id), (char *)(FILE_), __LINE__));
13986 }
13987 if (plci->internal_command)
13988 break;
13989 break;
13990 }
13991}
13992
13993
13994static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13995{
13996 word Info;
13997 word internal_command;
13998
13999 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14000 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14001
14002 Info = GOOD;
14003 internal_command = plci->internal_command;
14004 plci->internal_command = 0;
14005 switch (internal_command)
14006 {
14007 default:
14008 plci->command = 0;
14009 plci->adjust_b_parms_msg = NULL;
14010 plci->adjust_b_facilities = plci->B1_facilities;
14011 plci->adjust_b_command = RESET_B3_COMMAND_1;
14012 plci->adjust_b_ncci = (word)(Id >> 16);
14013 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14014 plci->adjust_b_state = ADJUST_B_START;
14015 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14016 UnMapId (Id), (char *)(FILE_), __LINE__));
14017 case RESET_B3_COMMAND_1:
14018 Info = adjust_b_process (Id, plci, Rc);
14019 if (Info != GOOD)
14020 {
14021 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14022 UnMapId (Id), (char *)(FILE_), __LINE__));
14023 break;
14024 }
14025 if (plci->internal_command)
14026 return;
14027 break;
14028 }
14029/* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14030 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14031}
14032
14033
14034static void select_b_command (dword Id, PLCI *plci, byte Rc)
14035{
14036 word Info;
14037 word internal_command;
14038 byte esc_chi[3];
14039
14040 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14041 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14042
14043 Info = GOOD;
14044 internal_command = plci->internal_command;
14045 plci->internal_command = 0;
14046 switch (internal_command)
14047 {
14048 default:
14049 plci->command = 0;
14050 plci->adjust_b_parms_msg = &plci->saved_msg;
14051 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14052 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14053 else
14054 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14055 plci->adjust_b_command = SELECT_B_COMMAND_1;
14056 plci->adjust_b_ncci = (word)(Id >> 16);
14057 if (plci->saved_msg.parms[0].length == 0)
14058 {
14059 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060 ADJUST_B_MODE_NO_RESOURCE;
14061 }
14062 else
14063 {
14064 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14065 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14066 }
14067 plci->adjust_b_state = ADJUST_B_START;
14068 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14069 UnMapId (Id), (char *)(FILE_), __LINE__));
14070 case SELECT_B_COMMAND_1:
14071 Info = adjust_b_process (Id, plci, Rc);
14072 if (Info != GOOD)
14073 {
14074 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14075 UnMapId (Id), (char *)(FILE_), __LINE__));
14076 break;
14077 }
14078 if (plci->internal_command)
14079 return;
14080 if (plci->tel == ADV_VOICE)
14081 {
14082 esc_chi[0] = 0x02;
14083 esc_chi[1] = 0x18;
14084 esc_chi[2] = plci->b_channel;
14085 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14086 }
14087 break;
14088 }
14089 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14090}
14091
14092
14093static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14094{
14095 word Info;
14096 word internal_command;
14097
14098 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14099 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14100
14101 Info = GOOD;
14102 internal_command = plci->internal_command;
14103 plci->internal_command = 0;
14104 switch (internal_command)
14105 {
14106 default:
14107 plci->command = 0;
14108 case FAX_CONNECT_ACK_COMMAND_1:
14109 if (plci_nl_busy (plci))
14110 {
14111 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14112 return;
14113 }
14114 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14115 plci->NData[0].P = plci->fax_connect_info_buffer;
14116 plci->NData[0].PLength = plci->fax_connect_info_length;
14117 plci->NL.X = plci->NData;
14118 plci->NL.ReqCh = 0;
14119 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14120 plci->adapter->request (&plci->NL);
14121 return;
14122 case FAX_CONNECT_ACK_COMMAND_2:
14123 if ((Rc != OK) && (Rc != OK_FC))
14124 {
14125 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14126 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14127 break;
14128 }
14129 }
14130 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14131 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14132 {
14133 if (plci->B3_prot == 4)
14134 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14135 else
14136 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14137 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14138 }
14139}
14140
14141
14142static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14143{
14144 word Info;
14145 word internal_command;
14146
14147 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14148 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14149
14150 Info = GOOD;
14151 internal_command = plci->internal_command;
14152 plci->internal_command = 0;
14153 switch (internal_command)
14154 {
14155 default:
14156 plci->command = 0;
14157 case FAX_EDATA_ACK_COMMAND_1:
14158 if (plci_nl_busy (plci))
14159 {
14160 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14161 return;
14162 }
14163 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14164 plci->NData[0].P = plci->fax_connect_info_buffer;
14165 plci->NData[0].PLength = plci->fax_edata_ack_length;
14166 plci->NL.X = plci->NData;
14167 plci->NL.ReqCh = 0;
14168 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14169 plci->adapter->request (&plci->NL);
14170 return;
14171 case FAX_EDATA_ACK_COMMAND_2:
14172 if ((Rc != OK) && (Rc != OK_FC))
14173 {
14174 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14175 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14176 break;
14177 }
14178 }
14179}
14180
14181
14182static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14183{
14184 word Info;
14185 word internal_command;
14186
14187 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14188 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14189
14190 Info = GOOD;
14191 internal_command = plci->internal_command;
14192 plci->internal_command = 0;
14193 switch (internal_command)
14194 {
14195 default:
14196 plci->command = 0;
14197 case FAX_CONNECT_INFO_COMMAND_1:
14198 if (plci_nl_busy (plci))
14199 {
14200 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14201 return;
14202 }
14203 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14204 plci->NData[0].P = plci->fax_connect_info_buffer;
14205 plci->NData[0].PLength = plci->fax_connect_info_length;
14206 plci->NL.X = plci->NData;
14207 plci->NL.ReqCh = 0;
14208 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14209 plci->adapter->request (&plci->NL);
14210 return;
14211 case FAX_CONNECT_INFO_COMMAND_2:
14212 if ((Rc != OK) && (Rc != OK_FC))
14213 {
14214 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14215 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14216 Info = _WRONG_STATE;
14217 break;
14218 }
14219 if (plci_nl_busy (plci))
14220 {
14221 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14222 return;
14223 }
14224 plci->command = _CONNECT_B3_R;
14225 nl_req_ncci (plci, N_CONNECT, 0);
14226 send_req (plci);
14227 return;
14228 }
14229 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14230}
14231
14232
14233static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14234{
14235 word Info;
14236 word internal_command;
14237
14238 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14239 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14240
14241 Info = GOOD;
14242 internal_command = plci->internal_command;
14243 plci->internal_command = 0;
14244 switch (internal_command)
14245 {
14246 default:
14247 plci->command = 0;
14248 plci->adjust_b_parms_msg = NULL;
14249 plci->adjust_b_facilities = plci->B1_facilities;
14250 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14251 plci->adjust_b_ncci = (word)(Id >> 16);
14252 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14253 plci->adjust_b_state = ADJUST_B_START;
14254 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14255 UnMapId (Id), (char *)(FILE_), __LINE__));
14256 case FAX_ADJUST_B23_COMMAND_1:
14257 Info = adjust_b_process (Id, plci, Rc);
14258 if (Info != GOOD)
14259 {
14260 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14261 UnMapId (Id), (char *)(FILE_), __LINE__));
14262 break;
14263 }
14264 if (plci->internal_command)
14265 return;
14266 case FAX_ADJUST_B23_COMMAND_2:
14267 if (plci_nl_busy (plci))
14268 {
14269 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14270 return;
14271 }
14272 plci->command = _CONNECT_B3_R;
14273 nl_req_ncci (plci, N_CONNECT, 0);
14274 send_req (plci);
14275 return;
14276 }
14277 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14278}
14279
14280
14281static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14282{
14283 word internal_command;
14284
14285 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14286 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14287
14288 internal_command = plci->internal_command;
14289 plci->internal_command = 0;
14290 switch (internal_command)
14291 {
14292 default:
14293 plci->command = 0;
14294 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14295 return;
14296 case FAX_DISCONNECT_COMMAND_1:
14297 case FAX_DISCONNECT_COMMAND_2:
14298 case FAX_DISCONNECT_COMMAND_3:
14299 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14300 {
14301 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14302 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14303 break;
14304 }
14305 if (Rc == OK)
14306 {
14307 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14308 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14309 {
14310 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14311 }
14312 }
14313 else if (Rc == 0)
14314 {
14315 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14316 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14317 }
14318 return;
14319 }
14320}
14321
14322
14323
14324static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14325{
14326 word Info;
14327 word internal_command;
14328
14329 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14330 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14331
14332 Info = GOOD;
14333 internal_command = plci->internal_command;
14334 plci->internal_command = 0;
14335 switch (internal_command)
14336 {
14337 default:
14338 plci->command = 0;
14339 case RTP_CONNECT_B3_REQ_COMMAND_1:
14340 if (plci_nl_busy (plci))
14341 {
14342 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14343 return;
14344 }
14345 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14346 nl_req_ncci (plci, N_CONNECT, 0);
14347 send_req (plci);
14348 return;
14349 case RTP_CONNECT_B3_REQ_COMMAND_2:
14350 if ((Rc != OK) && (Rc != OK_FC))
14351 {
14352 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14353 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14354 Info = _WRONG_STATE;
14355 break;
14356 }
14357 if (plci_nl_busy (plci))
14358 {
14359 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14360 return;
14361 }
14362 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14363 plci->NData[0].PLength = plci->internal_req_buffer[0];
14364 plci->NData[0].P = plci->internal_req_buffer + 1;
14365 plci->NL.X = plci->NData;
14366 plci->NL.ReqCh = 0;
14367 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14368 plci->adapter->request (&plci->NL);
14369 break;
14370 case RTP_CONNECT_B3_REQ_COMMAND_3:
14371 return;
14372 }
14373 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14374}
14375
14376
14377static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14378{
14379 word Info;
14380 word internal_command;
14381
14382 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14383 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14384
14385 Info = GOOD;
14386 internal_command = plci->internal_command;
14387 plci->internal_command = 0;
14388 switch (internal_command)
14389 {
14390 default:
14391 plci->command = 0;
14392 case RTP_CONNECT_B3_RES_COMMAND_1:
14393 if (plci_nl_busy (plci))
14394 {
14395 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14396 return;
14397 }
14398 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14399 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14400 send_req (plci);
14401 return;
14402 case RTP_CONNECT_B3_RES_COMMAND_2:
14403 if ((Rc != OK) && (Rc != OK_FC))
14404 {
14405 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14406 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14407 Info = _WRONG_STATE;
14408 break;
14409 }
14410 if (plci_nl_busy (plci))
14411 {
14412 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14413 return;
14414 }
14415 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14416 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14417 plci->NData[0].PLength = plci->internal_req_buffer[0];
14418 plci->NData[0].P = plci->internal_req_buffer + 1;
14419 plci->NL.X = plci->NData;
14420 plci->NL.ReqCh = 0;
14421 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422 plci->adapter->request (&plci->NL);
14423 return;
14424 case RTP_CONNECT_B3_RES_COMMAND_3:
14425 return;
14426 }
14427}
14428
14429
14430
14431static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14432{
14433 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14434 word Info;
14435 word internal_command;
14436
14437 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14438 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14439
14440 Info = GOOD;
14441 internal_command = plci->internal_command;
14442 plci->internal_command = 0;
14443 switch (internal_command)
14444 {
14445 default:
14446 if (!plci->NL.Id)
14447 break;
14448 plci->command = 0;
14449 plci->adjust_b_parms_msg = NULL;
14450 plci->adjust_b_facilities = plci->B1_facilities;
14451 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14452 plci->adjust_b_ncci = (word)(Id >> 16);
14453 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14454 plci->adjust_b_state = ADJUST_B_START;
14455 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14456 UnMapId (Id), (char *)(FILE_), __LINE__));
14457 case HOLD_SAVE_COMMAND_1:
14458 Info = adjust_b_process (Id, plci, Rc);
14459 if (Info != GOOD)
14460 {
14461 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14462 UnMapId (Id), (char *)(FILE_), __LINE__));
14463 break;
14464 }
14465 if (plci->internal_command)
14466 return;
14467 }
14468 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14469}
14470
14471
14472static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14473{
14474 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14475 word Info;
14476 word internal_command;
14477
14478 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14480
14481 Info = GOOD;
14482 internal_command = plci->internal_command;
14483 plci->internal_command = 0;
14484 switch (internal_command)
14485 {
14486 default:
14487 plci->command = 0;
14488 plci->adjust_b_parms_msg = NULL;
14489 plci->adjust_b_facilities = plci->B1_facilities;
14490 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14491 plci->adjust_b_ncci = (word)(Id >> 16);
14492 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14493 plci->adjust_b_state = ADJUST_B_START;
14494 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14495 UnMapId (Id), (char *)(FILE_), __LINE__));
14496 case RETRIEVE_RESTORE_COMMAND_1:
14497 Info = adjust_b_process (Id, plci, Rc);
14498 if (Info != GOOD)
14499 {
14500 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14501 UnMapId (Id), (char *)(FILE_), __LINE__));
14502 break;
14503 }
14504 if (plci->internal_command)
14505 return;
14506 }
14507 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14508}
14509
14510
14511static void init_b1_config (PLCI *plci)
14512{
14513
14514 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14515 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14516 (char *)(FILE_), __LINE__));
14517
14518 plci->B1_resource = 0;
14519 plci->B1_facilities = 0;
14520
14521 plci->li_bchannel_id = 0;
14522 mixer_clear_config (plci);
14523
14524
14525 ec_clear_config (plci);
14526
14527
14528 dtmf_rec_clear_config (plci);
14529 dtmf_send_clear_config (plci);
14530 dtmf_parameter_clear_config (plci);
14531
14532 adv_voice_clear_config (plci);
14533 adjust_b_clear (plci);
14534}
14535
14536
14537static void clear_b1_config (PLCI *plci)
14538{
14539
14540 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14541 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14542 (char *)(FILE_), __LINE__));
14543
14544 adv_voice_clear_config (plci);
14545 adjust_b_clear (plci);
14546
14547 ec_clear_config (plci);
14548
14549
14550 dtmf_rec_clear_config (plci);
14551 dtmf_send_clear_config (plci);
14552 dtmf_parameter_clear_config (plci);
14553
14554
14555 if ((plci->li_bchannel_id != 0)
14556 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14557 {
14558 mixer_clear_config (plci);
14559 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560 plci->li_bchannel_id = 0;
14561 }
14562
14563 plci->B1_resource = 0;
14564 plci->B1_facilities = 0;
14565}
14566
14567
14568/* -----------------------------------------------------------------
14569 XON protocol local helpers
14570 ----------------------------------------------------------------- */
14571static void channel_flow_control_remove (PLCI * plci) {
14572 DIVA_CAPI_ADAPTER * a = plci->adapter;
14573 word i;
14574 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14575 if (a->ch_flow_plci[i] == plci->Id) {
14576 a->ch_flow_plci[i] = 0;
14577 a->ch_flow_control[i] = 0;
14578 }
14579 }
14580}
14581
14582static void channel_x_on (PLCI * plci, byte ch) {
14583 DIVA_CAPI_ADAPTER * a = plci->adapter;
14584 if (a->ch_flow_control[ch] & N_XON_SENT) {
14585 a->ch_flow_control[ch] &= ~N_XON_SENT;
14586 }
14587}
14588
14589static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14590 DIVA_CAPI_ADAPTER * a = plci->adapter;
14591 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593 a->ch_flow_plci[ch] = plci->Id;
14594 a->ch_flow_control_pending++;
14595 }
14596}
14597
14598static void channel_request_xon (PLCI * plci, byte ch) {
14599 DIVA_CAPI_ADAPTER * a = plci->adapter;
14600
14601 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602 a->ch_flow_control[ch] |= N_XON_REQ;
14603 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14604 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14605 }
14606}
14607
14608static void channel_xmit_extended_xon (PLCI * plci) {
14609 DIVA_CAPI_ADAPTER * a;
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080014610 int max_ch = ARRAY_SIZE(a->ch_flow_control);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014611 int i, one_requested = 0;
14612
Harvey Harrisondd58c0d2008-04-28 02:14:39 -070014613 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070014614 return;
14615 }
14616
14617 for (i = 0; i < max_ch; i++) {
14618 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620 (plci->Id == a->ch_flow_plci[i])) {
14621 channel_request_xon (plci, (byte)i);
14622 one_requested = 1;
14623 }
14624 }
14625
14626 if (one_requested) {
14627 channel_xmit_xon (plci);
14628 }
14629}
14630
14631/*
14632 Try to xmit next X_ON
14633 */
14634static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080014635 int max_ch = ARRAY_SIZE(a->ch_flow_control);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014636 int i;
14637
14638 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14639 return (0);
14640 }
14641
14642 if (a->last_flow_control_ch >= max_ch) {
14643 a->last_flow_control_ch = 1;
14644 }
14645 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14646 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647 (plci->Id == a->ch_flow_plci[i])) {
14648 a->last_flow_control_ch = i+1;
14649 return (i);
14650 }
14651 }
14652
14653 for (i = 1; i < a->last_flow_control_ch; i++) {
14654 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655 (plci->Id == a->ch_flow_plci[i])) {
14656 a->last_flow_control_ch = i+1;
14657 return (i);
14658 }
14659 }
14660
14661 return (0);
14662}
14663
14664static void channel_xmit_xon (PLCI * plci) {
14665 DIVA_CAPI_ADAPTER * a = plci->adapter;
14666 byte ch;
14667
14668 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14669 return;
14670 }
14671 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14672 return;
14673 }
14674 a->ch_flow_control[ch] &= ~N_XON_REQ;
14675 a->ch_flow_control[ch] |= N_XON_SENT;
14676
14677 plci->NL.Req = plci->nl_req = (byte)N_XON;
14678 plci->NL.ReqCh = ch;
14679 plci->NL.X = plci->NData;
14680 plci->NL.XNum = 1;
14681 plci->NData[0].P = &plci->RBuffer[0];
14682 plci->NData[0].PLength = 0;
14683
14684 plci->adapter->request(&plci->NL);
14685}
14686
14687static int channel_can_xon (PLCI * plci, byte ch) {
14688 APPL * APPLptr;
14689 DIVA_CAPI_ADAPTER * a;
14690 word NCCIcode;
14691 dword count;
14692 word Num;
14693 word i;
14694
14695 APPLptr = plci->appl;
14696 a = plci->adapter;
14697
14698 if (!APPLptr)
14699 return (0);
14700
14701 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14702
14703 /* count all buffers within the Application pool */
14704 /* belonging to the same NCCI. XON if a first is */
14705 /* used. */
14706 count = 0;
14707 Num = 0xffff;
14708 for(i=0; i<APPLptr->MaxBuffer; i++) {
14709 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14710 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14711 }
14712 if ((count > 2) || (Num == 0xffff)) {
14713 return (0);
14714 }
14715 return (1);
14716}
14717
14718
14719/*------------------------------------------------------------------*/
14720
14721static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14722{
14723 return 1;
14724}
14725
14726
14727
14728/**********************************************************************************/
14729/* function groups the listening applications according to the CIP mask and the */
14730/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732/* big problems on application level (one call, 30 Connect_Ind, ect). The */
14733/* function must be enabled by setting "a->group_optimization_enabled" from the */
14734/* OS specific part (per adapter). */
14735/**********************************************************************************/
14736static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14737{
14738 word i,j,k,busy,group_found;
14739 dword info_mask_group[MAX_CIP_TYPES];
14740 dword cip_mask_group[MAX_CIP_TYPES];
14741 word appl_number_group_type[MAX_APPL];
14742 PLCI *auxplci;
14743
14744 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14745
14746 if(!a->group_optimization_enabled)
14747 {
14748 dbug(1,dprintf("No group optimization"));
14749 return;
14750 }
14751
14752 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14753
14754 for(i=0;i<MAX_CIP_TYPES;i++)
14755 {
14756 info_mask_group[i] = 0;
14757 cip_mask_group [i] = 0;
14758 }
14759 for(i=0;i<MAX_APPL;i++)
14760 {
14761 appl_number_group_type[i] = 0;
14762 }
14763 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14764 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14766 {
14767 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14768 return; /* allow good application unfiltered access */
14769 }
14770 }
14771 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14772 {
14773 if(application[i].Id && a->CIP_Mask[i] )
14774 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014775 for(k=0,busy=false; k<a->max_plci; k++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014776 {
14777 if(a->plci[k].Id)
14778 {
14779 auxplci = &a->plci[k];
14780 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14781 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014782 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014783 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14784 }
14785 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14786 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014787 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014788 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14789 }
14790 }
14791 }
14792
14793 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14794 {
14795 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14796 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797 appl_number_group_type[i] = MAX_CIP_TYPES;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014798 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014799 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14800 }
14801 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14802 { /* is group already present ? */
14803 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014804 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014805 dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14806 }
14807 else if(!info_mask_group[j])
14808 { /* establish a new group */
14809 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14810 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14811 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014812 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014813 dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14814 }
14815 }
14816 }
14817 }
14818
14819 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14820 {
14821 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14822 {
14823 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14824 {
14825 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14826 }
14827 else
14828 {
14829 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14830 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14831 {
14832 if(appl_number_group_type[i] == appl_number_group_type[j])
14833 {
14834 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14835 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14836 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14837 }
14838 }
14839 }
14840 }
14841 else /* application should not get a call */
14842 {
14843 clear_group_ind_mask_bit (plci, i);
14844 }
14845 }
14846
14847}
14848
14849
14850
14851/* OS notifies the driver about a application Capi_Register */
14852word CapiRegister(word id)
14853{
14854 word i,j,appls_found;
14855
14856 PLCI *plci;
14857 DIVA_CAPI_ADAPTER *a;
14858
14859 for(i=0,appls_found=0; i<max_appl; i++)
14860 {
14861 if( application[i].Id && (application[i].Id!=id) )
14862 {
14863 appls_found++; /* an application has been found */
14864 }
14865 }
14866
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014867 if(appls_found) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014868 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14869 {
14870 a = &adapter[i];
14871 if(a->request)
14872 {
14873 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14874 {
14875 if(!appls_found) /* first application does a capi register */
14876 {
14877 if((j=get_plci(a))) /* activate L1 of all adapters */
14878 {
14879 plci = &a->plci[j-1];
14880 plci->command = 0;
14881 add_p(plci,OAD,"\x01\xfd");
14882 add_p(plci,CAI,"\x01\x80");
14883 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14884 add_p(plci,SHIFT|6,NULL);
14885 add_p(plci,SIN,"\x02\x00\x00");
14886 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14887 sig_req(plci,ASSIGN,DSIG_ID);
14888 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14889 sig_req(plci,SIG_CTRL,0);
14890 send_req(plci);
14891 }
14892 }
14893 }
14894 }
14895 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014896 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014897}
14898
14899/*------------------------------------------------------------------*/
14900
14901/* Functions for virtual Switching e.g. Transfer by join, Conference */
14902
14903static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14904{
14905 word i;
14906 /* Format of vswitch_t:
14907 0 byte length
14908 1 byte VSWITCHIE
14909 2 byte VSWITCH_REQ/VSWITCH_IND
14910 3 byte reserved
14911 4 word VSwitchcommand
14912 6 word returnerror
14913 8... Params
14914 */
14915 if(!plci ||
14916 !plci->appl ||
14917 !plci->State ||
14918 plci->Sig.Ind==NCR_FACILITY
14919 )
14920 return;
14921
14922 for(i=0;i<MAX_MULTI_IE;i++)
14923 {
14924 if(!parms[i][0]) continue;
14925 if(parms[i][0]<7)
14926 {
14927 parms[i][0]=0; /* kill it */
14928 continue;
14929 }
14930 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14931 switch(parms[i][4])
14932 {
14933 case VSJOIN:
14934 if(!plci->relatedPTYPLCI ||
14935 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14936 { /* Error */
14937 break;
14938 }
14939 /* remember all necessary informations */
14940 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14941 {
14942 break;
14943 }
14944 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14945 { /* first indication after ECT-Request on Consultation Call */
14946 plci->vswitchstate=parms[i][9];
14947 parms[i][9]=2; /* State */
14948 /* now ask first Call to join */
14949 }
14950 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14951 { /* Answer of VSWITCH_REQ from first Call */
14952 plci->vswitchstate=parms[i][9];
14953 /* tell consultation call to join
14954 and the protocol capabilities of the first call */
14955 }
14956 else
14957 { /* Error */
14958 break;
14959 }
14960 plci->vsprot=parms[i][10]; /* protocol */
14961 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14962 /* send join request to related PLCI */
14963 parms[i][1]=VSWITCHIE;
14964 parms[i][2]=VSWITCH_REQ;
14965
14966 plci->relatedPTYPLCI->command = 0;
14967 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14968 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14969 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14970 send_req(plci->relatedPTYPLCI);
14971 break;
14972 case VSTRANSPORT:
14973 default:
14974 if(plci->relatedPTYPLCI &&
14975 plci->vswitchstate==3 &&
14976 plci->relatedPTYPLCI->vswitchstate==3)
14977 {
14978 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14979 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14980 send_req(plci->relatedPTYPLCI);
14981 }
14982 break;
14983 }
14984 parms[i][0]=0; /* kill it */
14985 }
14986}
14987
14988
14989/*------------------------------------------------------------------*/
14990
14991static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14992 ENTITY e;
14993 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14994
14995 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14996 return (-1);
14997 }
14998
14999 pReq->xdi_dma_descriptor_operation.Req = 0;
15000 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15001
15002 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15003 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15004 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15006
15007 e.user[0] = plci->adapter->Id - 1;
15008 plci->adapter->request((ENTITY*)pReq);
15009
15010 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15015 plci->adapter->Id,
15016 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15017 *dma_magic));
15018 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15019 } else {
15020 dbug(1,dprintf("dma_alloc failed"));
15021 return (-1);
15022 }
15023}
15024
15025static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15026 ENTITY e;
15027 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15028
15029 if (nr < 0) {
15030 return;
15031 }
15032
15033 pReq->xdi_dma_descriptor_operation.Req = 0;
15034 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15035
15036 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15037 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15038 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15040
15041 e.user[0] = plci->adapter->Id - 1;
15042 plci->adapter->request((ENTITY*)pReq);
15043
15044 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045 dbug(1,dprintf("dma_free(%d)", nr));
15046 } else {
15047 dbug(1,dprintf("dma_free failed (%d)", nr));
15048 }
15049}
15050
15051/*------------------------------------------------------------------*/