blob: ae89fb89da64ae4d0a286ed7fe237f8e227f59fd [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;
Karsten Keilba2d6cc2009-07-24 18:26:08 +0200554 for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
556 if(ftable[i].command==msg->header.command) {
557 /* break loop if the message is correct, otherwise continue scan */
558 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
559 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
560 ret = 0;
561 break;
562 }
563 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
564 }
565 }
566 if(ret) {
567 dbug(1,dprintf("BAD_MSG"));
568 if(plci) plci->command = 0;
569 return ret;
570 }
571
572
573 c = ftable[i].function(GET_DWORD(&msg->header.controller),
574 msg->header.number,
575 a,
576 plci,
577 appl,
578 msg_parms);
579
580 channel_xmit_extended_xon (plci);
581
582 if(c==1) send_req(plci);
583 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584 if(plci && !plci->req_in) plci->command = 0;
585 return 0;
586}
587
588
589/*------------------------------------------------------------------*/
590/* api_parse function, check the format of api messages */
591/*------------------------------------------------------------------*/
592
Hannes Eder4ee59d52008-12-16 01:17:33 -0800593static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594{
595 word i;
596 word p;
597
598 for(i=0,p=0; format[i]; i++) {
599 if(parms)
600 {
601 parms[i].info = &msg[p];
602 }
603 switch(format[i]) {
604 case 'b':
605 p +=1;
606 break;
607 case 'w':
608 p +=2;
609 break;
610 case 'd':
611 p +=4;
612 break;
613 case 's':
614 if(msg[p]==0xff) {
615 parms[i].info +=2;
616 parms[i].length = msg[p+1] + (msg[p+2]<<8);
617 p +=(parms[i].length +3);
618 }
619 else {
620 parms[i].length = msg[p];
621 p +=(parms[i].length +1);
622 }
623 break;
624 }
625
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800626 if(p>length) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 }
628 if(parms) parms[i].info = NULL;
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800629 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630}
631
Hannes Eder4ee59d52008-12-16 01:17:33 -0800632static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
634 word i, j, n = 0;
635 byte *p;
636
637 p = out->info;
638 for (i = 0; format[i] != '\0'; i++)
639 {
640 out->parms[i].info = p;
641 out->parms[i].length = in[i].length;
642 switch (format[i])
643 {
644 case 'b':
645 n = 1;
646 break;
647 case 'w':
648 n = 2;
649 break;
650 case 'd':
651 n = 4;
652 break;
653 case 's':
654 n = in[i].length + 1;
655 break;
656 }
657 for (j = 0; j < n; j++)
658 *(p++) = in[i].info[j];
659 }
660 out->parms[i].info = NULL;
661 out->parms[i].length = 0;
662}
663
Hannes Eder4ee59d52008-12-16 01:17:33 -0800664static void api_load_msg(API_SAVE *in, API_PARSE *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665{
666 word i;
667
668 i = 0;
669 do
670 {
671 out[i].info = in->parms[i].info;
672 out[i].length = in->parms[i].length;
673 } while (in->parms[i++].info);
674}
675
676
677/*------------------------------------------------------------------*/
678/* CAPI remove function */
679/*------------------------------------------------------------------*/
680
681word api_remove_start(void)
682{
683 word i;
684 word j;
685
686 if(!remove_started) {
Richard Knutsson986c4bb2007-02-12 00:53:24 -0800687 remove_started = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 for(i=0;i<max_adapter;i++) {
689 if(adapter[i].request) {
690 for(j=0;j<adapter[i].max_plci;j++) {
691 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692 }
693 }
694 }
695 return 1;
696 }
697 else {
698 for(i=0;i<max_adapter;i++) {
699 if(adapter[i].request) {
700 for(j=0;j<adapter[i].max_plci;j++) {
701 if(adapter[i].plci[j].Sig.Id) return 1;
702 }
703 }
704 }
705 }
706 api_remove_complete();
707 return 0;
708}
709
710
711/*------------------------------------------------------------------*/
712/* internal command queue */
713/*------------------------------------------------------------------*/
714
715static void init_internal_command_queue (PLCI *plci)
716{
717 word i;
718
719 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
720 (char *)(FILE_), __LINE__));
721
722 plci->internal_command = 0;
723 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724 plci->internal_command_queue[i] = NULL;
725}
726
727
728static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
729{
730 word i;
731
732 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
733 UnMapId (Id), (char *)(FILE_), __LINE__));
734
735 if (plci->internal_command == 0)
736 {
737 plci->internal_command_queue[0] = command_function;
738 (* command_function)(Id, plci, OK);
739 }
740 else
741 {
742 i = 1;
Harvey Harrisondd58c0d2008-04-28 02:14:39 -0700743 while (plci->internal_command_queue[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 i++;
745 plci->internal_command_queue[i] = command_function;
746 }
747}
748
749
750static void next_internal_command (dword Id, PLCI *plci)
751{
752 word i;
753
754 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
755 UnMapId (Id), (char *)(FILE_), __LINE__));
756
757 plci->internal_command = 0;
758 plci->internal_command_queue[0] = NULL;
Harvey Harrisondd58c0d2008-04-28 02:14:39 -0700759 while (plci->internal_command_queue[1] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 {
761 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
763 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765 if (plci->internal_command != 0)
766 return;
767 plci->internal_command_queue[0] = NULL;
768 }
769}
770
771
772/*------------------------------------------------------------------*/
773/* NCCI allocate/remove function */
774/*------------------------------------------------------------------*/
775
776static dword ncci_mapping_bug = 0;
777
778static word get_ncci (PLCI *plci, byte ch, word force_ncci)
779{
780 DIVA_CAPI_ADAPTER *a;
781 word ncci, i, j, k;
782
783 a = plci->adapter;
784 if (!ch || a->ch_ncci[ch])
785 {
786 ncci_mapping_bug++;
787 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789 ncci = ch;
790 }
791 else
792 {
793 if (force_ncci)
794 ncci = force_ncci;
795 else
796 {
797 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
798 ncci = ch;
799 else
800 {
801 ncci = 1;
802 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
803 ncci++;
804 if (ncci == MAX_NCCI+1)
805 {
806 ncci_mapping_bug++;
807 i = 1;
808 do
809 {
810 j = 1;
811 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
812 j++;
813 k = j;
814 if (j < MAX_NCCI+1)
815 {
816 do
817 {
818 j++;
819 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
820 }
821 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
822 if (i < MAX_NL_CHANNEL+1)
823 {
824 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 ncci_mapping_bug, ch, force_ncci, i, k, j));
826 }
827 else
828 {
829 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
830 ncci_mapping_bug, ch, force_ncci));
831 }
832 ncci = ch;
833 }
834 }
835 a->ncci_plci[ncci] = plci->Id;
836 a->ncci_state[ncci] = IDLE;
837 if (!plci->ncci_ring_list)
838 plci->ncci_ring_list = ncci;
839 else
840 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842 }
843 a->ncci_ch[ncci] = ch;
844 a->ch_ncci[ch] = (byte) ncci;
845 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846 ncci_mapping_bug, ch, force_ncci, ch, ncci));
847 }
848 return (ncci);
849}
850
851
852static void ncci_free_receive_buffers (PLCI *plci, word ncci)
853{
854 DIVA_CAPI_ADAPTER *a;
855 APPL *appl;
856 word i, ncci_code;
857 dword Id;
858
859 a = plci->adapter;
860 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861 if (ncci)
862 {
863 if (a->ncci_plci[ncci] == plci->Id)
864 {
865 if (!plci->appl)
866 {
867 ncci_mapping_bug++;
868 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
869 ncci_mapping_bug, Id));
870 }
871 else
872 {
873 appl = plci->appl;
874 ncci_code = ncci | (((word) a->Id) << 8);
875 for (i = 0; i < appl->MaxBuffer; i++)
876 {
877 if ((appl->DataNCCI[i] == ncci_code)
878 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879 {
880 appl->DataNCCI[i] = 0;
881 }
882 }
883 }
884 }
885 }
886 else
887 {
888 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
889 {
890 if (a->ncci_plci[ncci] == plci->Id)
891 {
892 if (!plci->appl)
893 {
894 ncci_mapping_bug++;
895 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
896 ncci_mapping_bug, Id));
897 }
898 else
899 {
900 appl = plci->appl;
901 ncci_code = ncci | (((word) a->Id) << 8);
902 for (i = 0; i < appl->MaxBuffer; i++)
903 {
904 if ((appl->DataNCCI[i] == ncci_code)
905 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906 {
907 appl->DataNCCI[i] = 0;
908 }
909 }
910 }
911 }
912 }
913 }
914}
915
916
917static void cleanup_ncci_data (PLCI *plci, word ncci)
918{
919 NCCI *ncci_ptr;
920
921 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922 {
923 ncci_ptr = &(plci->adapter->ncci[ncci]);
924 if (plci->appl)
925 {
926 while (ncci_ptr->data_pending != 0)
927 {
928 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930 (ncci_ptr->data_out)++;
931 if (ncci_ptr->data_out == MAX_DATA_B3)
932 ncci_ptr->data_out = 0;
933 (ncci_ptr->data_pending)--;
934 }
935 }
936 ncci_ptr->data_out = 0;
937 ncci_ptr->data_pending = 0;
938 ncci_ptr->data_ack_out = 0;
939 ncci_ptr->data_ack_pending = 0;
940 }
941}
942
943
944static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
945{
946 DIVA_CAPI_ADAPTER *a;
947 dword Id;
948 word i;
949
950 a = plci->adapter;
951 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952 if (!preserve_ncci)
953 ncci_free_receive_buffers (plci, ncci);
954 if (ncci)
955 {
956 if (a->ncci_plci[ncci] != plci->Id)
957 {
958 ncci_mapping_bug++;
959 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 ncci_mapping_bug, Id, preserve_ncci));
961 }
962 else
963 {
964 cleanup_ncci_data (plci, ncci);
965 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967 a->ch_ncci[a->ncci_ch[ncci]] = 0;
968 if (!preserve_ncci)
969 {
970 a->ncci_ch[ncci] = 0;
971 a->ncci_plci[ncci] = 0;
972 a->ncci_state[ncci] = IDLE;
973 i = plci->ncci_ring_list;
974 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975 i = a->ncci_next[i];
976 if ((i != 0) && (a->ncci_next[i] == ncci))
977 {
978 if (i == ncci)
979 plci->ncci_ring_list = 0;
980 else if (plci->ncci_ring_list == ncci)
981 plci->ncci_ring_list = i;
982 a->ncci_next[i] = a->ncci_next[ncci];
983 }
984 a->ncci_next[ncci] = 0;
985 }
986 }
987 }
988 else
989 {
990 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
991 {
992 if (a->ncci_plci[ncci] == plci->Id)
993 {
994 cleanup_ncci_data (plci, ncci);
995 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997 a->ch_ncci[a->ncci_ch[ncci]] = 0;
998 if (!preserve_ncci)
999 {
1000 a->ncci_ch[ncci] = 0;
1001 a->ncci_plci[ncci] = 0;
1002 a->ncci_state[ncci] = IDLE;
1003 a->ncci_next[ncci] = 0;
1004 }
1005 }
1006 }
1007 if (!preserve_ncci)
1008 plci->ncci_ring_list = 0;
1009 }
1010}
1011
1012
1013/*------------------------------------------------------------------*/
1014/* PLCI remove function */
1015/*------------------------------------------------------------------*/
1016
1017static void plci_free_msg_in_queue (PLCI *plci)
1018{
1019 word i;
1020
1021 if (plci->appl)
1022 {
1023 i = plci->msg_in_read_pos;
1024 while (i != plci->msg_in_write_pos)
1025 {
1026 if (i == plci->msg_in_wrap_pos)
1027 i = 0;
1028 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029 {
1030
1031 TransmitBufferFree (plci->appl,
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07001032 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
1034 }
1035
1036 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037 MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039 }
1040 }
1041 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044}
1045
1046
1047static void plci_remove(PLCI * plci)
1048{
1049
1050 if(!plci) {
1051 dbug(1,dprintf("plci_remove(no plci)"));
1052 return;
1053 }
1054 init_internal_command_queue (plci);
1055 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1056 if(plci_remove_check(plci))
1057 {
1058 return;
1059 }
1060 if (plci->Sig.Id == 0xff)
1061 {
1062 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063 if (plci->NL.Id && !plci->nl_remove_id)
1064 {
1065 nl_req_ncci(plci,REMOVE,0);
1066 send_req(plci);
1067 }
1068 }
1069 else
1070 {
1071 if (!plci->sig_remove_id
1072 && (plci->Sig.Id
1073 || (plci->req_in!=plci->req_out)
1074 || (plci->nl_req || plci->sig_req)))
1075 {
1076 sig_req(plci,HANGUP,0);
1077 send_req(plci);
1078 }
1079 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001080 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 plci_free_msg_in_queue (plci);
1082
1083 plci->channels = 0;
1084 plci->appl = NULL;
1085 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086 plci->State = OUTG_DIS_PENDING;
1087}
1088
1089/*------------------------------------------------------------------*/
1090/* Application Group function helpers */
1091/*------------------------------------------------------------------*/
1092
1093static void set_group_ind_mask (PLCI *plci)
1094{
1095 word i;
1096
1097 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098 plci->group_optimization_mask_table[i] = 0xffffffffL;
1099}
1100
1101static void clear_group_ind_mask_bit (PLCI *plci, word b)
1102{
1103 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104}
1105
1106static byte test_group_ind_mask_bit (PLCI *plci, word b)
1107{
1108 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109}
1110
1111/*------------------------------------------------------------------*/
1112/* c_ind_mask operations for arbitrary MAX_APPL */
1113/*------------------------------------------------------------------*/
1114
1115static void clear_c_ind_mask (PLCI *plci)
1116{
1117 word i;
1118
1119 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120 plci->c_ind_mask_table[i] = 0;
1121}
1122
1123static byte c_ind_mask_empty (PLCI *plci)
1124{
1125 word i;
1126
1127 i = 0;
1128 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129 i++;
1130 return (i == C_IND_MASK_DWORDS);
1131}
1132
1133static void set_c_ind_mask_bit (PLCI *plci, word b)
1134{
1135 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136}
1137
1138static void clear_c_ind_mask_bit (PLCI *plci, word b)
1139{
1140 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141}
1142
1143static byte test_c_ind_mask_bit (PLCI *plci, word b)
1144{
1145 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146}
1147
1148static void dump_c_ind_mask (PLCI *plci)
1149{
1150static char hex_digit_table[0x10] =
1151 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1152 word i, j, k;
1153 dword d;
1154 char *p;
1155 char buf[40];
1156
1157 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158 {
1159 p = buf + 36;
1160 *p = '\0';
1161 for (j = 0; j < 4; j++)
1162 {
1163 if (i+j < C_IND_MASK_DWORDS)
1164 {
1165 d = plci->c_ind_mask_table[i+j];
1166 for (k = 0; k < 8; k++)
1167 {
1168 *(--p) = hex_digit_table[d & 0xf];
1169 d >>= 4;
1170 }
1171 }
1172 else if (i != 0)
1173 {
1174 for (k = 0; k < 8; k++)
1175 *(--p) = ' ';
1176 }
1177 *(--p) = ' ';
1178 }
1179 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1180 }
1181}
1182
1183
1184
1185
1186
1187#define dump_plcis(a)
1188
1189
1190
1191/*------------------------------------------------------------------*/
1192/* translation function for each message */
1193/*------------------------------------------------------------------*/
1194
Hannes Eder465e9852009-02-25 13:11:37 +00001195static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197{
1198 word ch;
1199 word i;
1200 word Info;
1201 word CIP;
1202 byte LinkLayer;
1203 API_PARSE * ai;
1204 API_PARSE * bp;
1205 API_PARSE ai_parms[5];
1206 word channel = 0;
1207 dword ch_mask;
1208 byte m;
1209 static byte esc_chi[35] = {0x02,0x18,0x01};
1210 static byte lli[2] = {0x01,0x00};
1211 byte noCh = 0;
1212 word dir = 0;
1213 byte *p_chi = "";
1214
1215 for(i=0;i<5;i++) ai_parms[i].length = 0;
1216
1217 dbug(1,dprintf("connect_req(%d)",parms->length));
1218 Info = _WRONG_IDENTIFIER;
1219 if(a)
1220 {
1221 if(a->adapter_disabled)
1222 {
1223 dbug(1,dprintf("adapter disabled"));
1224 Id = ((word)1<<8)|a->Id;
1225 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1226 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001227 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229 Info = _OUT_OF_PLCI;
1230 if((i=get_plci(a)))
1231 {
1232 Info = 0;
1233 plci = &a->plci[i-1];
1234 plci->appl = appl;
1235 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1236 /* check 'external controller' bit for codec support */
1237 if(Id & EXT_CONTROLLER)
1238 {
1239 if(AdvCodecSupport(a, plci, appl, 0) )
1240 {
1241 plci->Id = 0;
1242 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1243 return 2;
1244 }
1245 }
1246 ai = &parms[9];
1247 bp = &parms[5];
1248 ch = 0;
1249 if(bp->length)LinkLayer = bp->info[3];
1250 else LinkLayer = 0;
1251 if(ai->length)
1252 {
1253 ch=0xffff;
1254 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1255 {
1256 ch = 0;
1257 if(ai_parms[0].length)
1258 {
1259 ch = GET_WORD(ai_parms[0].info+1);
1260 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1261 if(ch==4) /* explizit CHI in message */
1262 {
1263 /* check length of B-CH struct */
1264 if((ai_parms[0].info)[3]>=1)
1265 {
1266 if((ai_parms[0].info)[4]==CHI)
1267 {
1268 p_chi = &((ai_parms[0].info)[5]);
1269 }
1270 else
1271 {
1272 p_chi = &((ai_parms[0].info)[3]);
1273 }
1274 if(p_chi[0]>35) /* check length of channel ID */
1275 {
1276 Info = _WRONG_MESSAGE_FORMAT;
1277 }
1278 }
1279 else Info = _WRONG_MESSAGE_FORMAT;
1280 }
1281
1282 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1283 {
1284 dir = GET_WORD(ai_parms[0].info+3);
1285 ch_mask = 0;
1286 m = 0x3f;
1287 for(i=0; i+5<=ai_parms[0].length; i++)
1288 {
1289 if(ai_parms[0].info[i+5]!=0)
1290 {
1291 if((ai_parms[0].info[i+5] | m) != 0xff)
1292 Info = _WRONG_MESSAGE_FORMAT;
1293 else
1294 {
1295 if (ch_mask == 0)
1296 channel = i;
1297 ch_mask |= 1L << i;
1298 }
1299 }
1300 m = 0;
1301 }
1302 if (ch_mask == 0)
1303 Info = _WRONG_MESSAGE_FORMAT;
1304 if (!Info)
1305 {
1306 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1307 {
1308 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1309 for(i=0; i+5<=ai_parms[0].length; i++)
1310 esc_chi[i+3] = ai_parms[0].info[i+5];
1311 }
1312 else
1313 esc_chi[0] = 2;
1314 esc_chi[2] = (byte)channel;
1315 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1316 add_p(plci,LLI,lli);
1317 add_p(plci,ESC,esc_chi);
1318 plci->State = LOCAL_CONNECT;
1319 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1320 }
1321 }
1322 }
1323 }
1324 else Info = _WRONG_MESSAGE_FORMAT;
1325 }
1326
1327 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1328 plci->command = _CONNECT_R;
1329 plci->number = Number;
1330 /* x.31 or D-ch free SAPI in LinkLayer? */
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001331 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1333 {
1334 /* B-channel used for B3 connections (ch==0), or no B channel */
1335 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1336 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1337 else Info = add_b1(plci,&parms[5],ch,0);
1338 add_s(plci,OAD,&parms[2]);
1339 add_s(plci,OSA,&parms[4]);
1340 add_s(plci,BC,&parms[6]);
1341 add_s(plci,LLC,&parms[7]);
1342 add_s(plci,HLC,&parms[8]);
1343 CIP = GET_WORD(parms[0].info);
1344 if (a->Info_Mask[appl->Id-1] & 0x200)
1345 {
1346 /* early B3 connect (CIP mask bit 9) no release after a disc */
1347 add_p(plci,LLI,"\x01\x01");
1348 }
1349 if(GET_WORD(parms[0].info)<29) {
1350 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1351 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1352 }
1353 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1354 sig_req(plci,ASSIGN,DSIG_ID);
1355 }
1356 else if(ch==1) {
1357
1358 /* D-Channel used for B3 connections */
1359 plci->Sig.Id = 0xff;
1360 Info = 0;
1361 }
1362
1363 if(!Info && ch!=2 && !noCh ) {
1364 Info = add_b23(plci,&parms[5]);
1365 if(!Info) {
1366 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1367 }
1368 }
1369
1370 if(!Info)
1371 {
1372 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1373 {
1374 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1375 {
1376 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1377 plci->spoofed_msg = CALL_REQ;
1378 plci->internal_command = BLOCK_PLCI;
1379 plci->command = 0;
1380 dbug(1,dprintf("Spoof"));
1381 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001382 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 }
1384 if(ch==4)add_p(plci,CHI,p_chi);
1385 add_s(plci,CPN,&parms[1]);
1386 add_s(plci,DSA,&parms[3]);
1387 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1388 add_ai(plci,&parms[9]);
1389 if(!dir)sig_req(plci,CALL_REQ,0);
1390 else
1391 {
1392 plci->command = PERM_LIST_REQ;
1393 plci->appl = appl;
1394 sig_req(plci,LISTEN_REQ,0);
1395 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001396 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 }
1398 }
1399 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001400 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 }
1402 plci->Id = 0;
1403 }
1404 }
1405 sendf(appl,
1406 _CONNECT_R|CONFIRM,
1407 Id,
1408 Number,
1409 "w",Info);
1410 return 2;
1411}
1412
Hannes Eder465e9852009-02-25 13:11:37 +00001413static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1414 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415{
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
Hannes Eder465e9852009-02-25 13:11:37 +00001570static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1571 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572{
1573 dbug(1,dprintf("connect_a_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001574 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575}
1576
Hannes Eder465e9852009-02-25 13:11:37 +00001577static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1578 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579{
1580 word Info;
1581 word i;
1582
1583 dbug(1,dprintf("disconnect_req"));
1584
1585 Info = _WRONG_IDENTIFIER;
1586
1587 if(plci)
1588 {
1589 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1590 {
1591 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1592 plci->appl = appl;
1593 for(i=0; i<max_appl; i++)
1594 {
1595 if(test_c_ind_mask_bit (plci, i))
1596 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1597 }
1598 plci->State = OUTG_DIS_PENDING;
1599 }
1600 if(plci->Sig.Id && plci->appl)
1601 {
1602 Info = 0;
1603 if(plci->Sig.Id!=0xff)
1604 {
1605 if(plci->State!=INC_DIS_PENDING)
1606 {
1607 add_ai(plci, &msg[0]);
1608 sig_req(plci,HANGUP,0);
1609 plci->State = OUTG_DIS_PENDING;
1610 return 1;
1611 }
1612 }
1613 else
1614 {
1615 if (plci->NL.Id && !plci->nl_remove_id)
1616 {
1617 mixer_remove (plci);
1618 nl_req_ncci(plci,REMOVE,0);
1619 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1620 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1621 plci->State = INC_DIS_PENDING;
1622 }
1623 return 1;
1624 }
1625 }
1626 }
1627
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001628 if(!appl) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001630 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631}
1632
Hannes Eder465e9852009-02-25 13:11:37 +00001633static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1634 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635{
1636 dbug(1,dprintf("disconnect_res"));
1637 if(plci)
1638 {
1639 /* clear ind mask bit, just in case of collsion of */
1640 /* DISCONNECT_IND and CONNECT_RES */
1641 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1642 ncci_free_receive_buffers (plci, 0);
1643 if(plci_remove_check(plci))
1644 {
1645 return 0;
1646 }
1647 if(plci->State==INC_DIS_PENDING
1648 || plci->State==SUSPENDING) {
1649 if(c_ind_mask_empty (plci)) {
1650 if(plci->State!=SUSPENDING)plci->State = IDLE;
1651 dbug(1,dprintf("chs=%d",plci->channels));
1652 if(!plci->channels) {
1653 plci_remove(plci);
1654 }
1655 }
1656 }
1657 }
1658 return 0;
1659}
1660
Hannes Eder465e9852009-02-25 13:11:37 +00001661static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1662 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663{
1664 word Info;
1665 byte i;
1666
1667 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1668
1669 Info = _WRONG_IDENTIFIER;
1670 if(a) {
1671 Info = 0;
1672 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1673 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1674 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1675 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1676 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1677 }
1678
1679 /* check if external controller listen and switch listen on or off*/
1680 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1681 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1682 dummy_plci.State = IDLE;
1683 a->codec_listen[appl->Id-1] = &dummy_plci;
1684 a->TelOAD[0] = (byte)(parms[3].length);
1685 for(i=1;parms[3].length>=i && i<22;i++) {
1686 a->TelOAD[i] = parms[3].info[i];
1687 }
1688 a->TelOAD[i] = 0;
1689 a->TelOSA[0] = (byte)(parms[4].length);
1690 for(i=1;parms[4].length>=i && i<22;i++) {
1691 a->TelOSA[i] = parms[4].info[i];
1692 }
1693 a->TelOSA[i] = 0;
1694 }
1695 else Info = 0x2002; /* wrong controller, codec not supported */
1696 }
1697 else{ /* clear listen */
1698 a->codec_listen[appl->Id-1] = (PLCI *)0;
1699 }
1700 }
1701 sendf(appl,
1702 _LISTEN_R|CONFIRM,
1703 Id,
1704 Number,
1705 "w",Info);
1706
1707 if (a) listen_check(a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001708 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709}
1710
Hannes Eder465e9852009-02-25 13:11:37 +00001711static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1712 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713{
1714 word i;
1715 API_PARSE * ai;
1716 PLCI * rc_plci = NULL;
1717 API_PARSE ai_parms[5];
1718 word Info = 0;
1719
1720 dbug(1,dprintf("info_req"));
1721 for(i=0;i<5;i++) ai_parms[i].length = 0;
1722
1723 ai = &msg[1];
1724
1725 if(ai->length)
1726 {
1727 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1728 {
1729 dbug(1,dprintf("AddInfo wrong"));
1730 Info = _WRONG_MESSAGE_FORMAT;
1731 }
1732 }
1733 if(!a) Info = _WRONG_STATE;
1734
1735 if(!Info && plci)
1736 { /* no fac, with CPN, or KEY */
1737 rc_plci = plci;
1738 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1739 {
1740 /* overlap sending option */
1741 dbug(1,dprintf("OvlSnd"));
1742 add_s(plci,CPN,&msg[0]);
1743 add_s(plci,KEY,&ai_parms[1]);
1744 sig_req(plci,INFO_REQ,0);
1745 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001746 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 }
1748
1749 if(plci->State && ai_parms[2].length)
1750 {
1751 /* User_Info option */
1752 dbug(1,dprintf("UUI"));
1753 add_s(plci,UUI,&ai_parms[2]);
1754 sig_req(plci,USER_DATA,0);
1755 }
1756 else if(plci->State && ai_parms[3].length)
1757 {
1758 /* Facility option */
1759 dbug(1,dprintf("FAC"));
1760 add_s(plci,CPN,&msg[0]);
1761 add_ai(plci, &msg[1]);
1762 sig_req(plci,FACILITY_REQ,0);
1763 }
1764 else
1765 {
1766 Info = _WRONG_STATE;
1767 }
1768 }
1769 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1770 {
1771 /* NCR_Facility option -> send UUI and Keypad too */
1772 dbug(1,dprintf("NCR_FAC"));
1773 if((i=get_plci(a)))
1774 {
1775 rc_plci = &a->plci[i-1];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001776 appl->NullCREnable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 rc_plci->internal_command = C_NCR_FAC_REQ;
1778 rc_plci->appl = appl;
1779 add_p(rc_plci,CAI,"\x01\x80");
1780 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1781 sig_req(rc_plci,ASSIGN,DSIG_ID);
1782 send_req(rc_plci);
1783 }
1784 else
1785 {
1786 Info = _OUT_OF_PLCI;
1787 }
1788
1789 if(!Info)
1790 {
1791 add_s(rc_plci,CPN,&msg[0]);
1792 add_ai(rc_plci, &msg[1]);
1793 sig_req(rc_plci,NCR_FACILITY,0);
1794 send_req(rc_plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001795 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 /* for application controlled supplementary services */
1797 }
1798 }
1799
1800 if (!rc_plci)
1801 {
1802 Info = _WRONG_MESSAGE_FORMAT;
1803 }
1804
1805 if(!Info)
1806 {
1807 send_req(rc_plci);
1808 }
1809 else
1810 { /* appl is not assigned to a PLCI or error condition */
1811 dbug(1,dprintf("localInfoCon"));
1812 sendf(appl,
1813 _INFO_R|CONFIRM,
1814 Id,
1815 Number,
1816 "w",Info);
1817 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001818 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819}
1820
Hannes Eder465e9852009-02-25 13:11:37 +00001821static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1822 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823{
1824 dbug(1,dprintf("info_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001825 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826}
1827
Hannes Eder465e9852009-02-25 13:11:37 +00001828static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1829 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
1831 word Info;
1832 byte ret;
1833
1834 dbug(1,dprintf("alert_req"));
1835
1836 Info = _WRONG_IDENTIFIER;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001837 ret = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 if(plci) {
1839 Info = _ALERT_IGNORED;
1840 if(plci->State!=INC_CON_ALERT) {
1841 Info = _WRONG_STATE;
1842 if(plci->State==INC_CON_PENDING) {
1843 Info = 0;
1844 plci->State=INC_CON_ALERT;
1845 add_ai(plci, &msg[0]);
1846 sig_req(plci,CALL_ALERT,0);
1847 ret = 1;
1848 }
1849 }
1850 }
1851 sendf(appl,
1852 _ALERT_R|CONFIRM,
1853 Id,
1854 Number,
1855 "w",Info);
1856 return ret;
1857}
1858
Hannes Eder465e9852009-02-25 13:11:37 +00001859static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1860 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
1862 word Info = 0;
1863 word i = 0;
1864
1865 word selector;
1866 word SSreq;
1867 long relatedPLCIvalue;
1868 DIVA_CAPI_ADAPTER * relatedadapter;
1869 byte * SSparms = "";
1870 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1871 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1872 API_PARSE * parms;
1873 API_PARSE ss_parms[11];
1874 PLCI *rplci;
1875 byte cai[15];
1876 dword d;
1877 API_PARSE dummy;
1878
1879 dbug(1,dprintf("facility_req"));
1880 for(i=0;i<9;i++) ss_parms[i].length = 0;
1881
1882 parms = &msg[1];
1883
1884 if(!a)
1885 {
1886 dbug(1,dprintf("wrong Ctrl"));
1887 Info = _WRONG_IDENTIFIER;
1888 }
1889
1890 selector = GET_WORD(msg[0].info);
1891
1892 if(!Info)
1893 {
1894 switch(selector)
1895 {
1896 case SELECTOR_HANDSET:
1897 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1898 break;
1899
1900 case SELECTOR_SU_SERV:
1901 if(!msg[1].length)
1902 {
1903 Info = _WRONG_MESSAGE_FORMAT;
1904 break;
1905 }
1906 SSreq = GET_WORD(&(msg[1].info[1]));
1907 PUT_WORD(&RCparms[1],SSreq);
1908 SSparms = RCparms;
1909 switch(SSreq)
1910 {
1911 case S_GET_SUPPORTED_SERVICES:
1912 if((i=get_plci(a)))
1913 {
1914 rplci = &a->plci[i-1];
1915 rplci->appl = appl;
1916 add_p(rplci,CAI,"\x01\x80");
1917 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1918 sig_req(rplci,ASSIGN,DSIG_ID);
1919 send_req(rplci);
1920 }
1921 else
1922 {
1923 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1924 SSparms = (byte *)SSstruct;
1925 break;
1926 }
1927 rplci->internal_command = GETSERV_REQ_PEND;
1928 rplci->number = Number;
1929 rplci->appl = appl;
1930 sig_req(rplci,S_SUPPORTED,0);
1931 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001932 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 break;
1934
1935 case S_LISTEN:
1936 if(parms->length==7)
1937 {
1938 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1939 {
1940 dbug(1,dprintf("format wrong"));
1941 Info = _WRONG_MESSAGE_FORMAT;
1942 break;
1943 }
1944 }
1945 else
1946 {
1947 Info = _WRONG_MESSAGE_FORMAT;
1948 break;
1949 }
1950 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1951 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1952 {
1953 if((i=get_plci(a)))
1954 {
1955 rplci = &a->plci[i-1];
1956 rplci->appl = appl;
1957 add_p(rplci,CAI,"\x01\x80");
1958 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1959 sig_req(rplci,ASSIGN,DSIG_ID);
1960 send_req(rplci);
1961 }
1962 else
1963 {
1964 break;
1965 }
1966 rplci->internal_command = GET_MWI_STATE;
1967 rplci->number = Number;
1968 sig_req(rplci,MWI_POLL,0);
1969 send_req(rplci);
1970 }
1971 break;
1972
1973 case S_HOLD:
1974 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1975 if(plci && plci->State && plci->SuppState==IDLE)
1976 {
1977 plci->SuppState = HOLD_REQUEST;
1978 plci->command = C_HOLD_REQ;
1979 add_s(plci,CAI,&ss_parms[1]);
1980 sig_req(plci,CALL_HOLD,0);
1981 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08001982 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 }
1984 else Info = 0x3010; /* wrong state */
1985 break;
1986 case S_RETRIEVE:
1987 if(plci && plci->State && plci->SuppState==CALL_HELD)
1988 {
1989 if(Id & EXT_CONTROLLER)
1990 {
1991 if(AdvCodecSupport(a, plci, appl, 0))
1992 {
1993 Info = 0x3010; /* wrong state */
1994 break;
1995 }
1996 }
1997 else plci->tel = 0;
1998
1999 plci->SuppState = RETRIEVE_REQUEST;
2000 plci->command = C_RETRIEVE_REQ;
2001 if(plci->spoofed_msg==SPOOFING_REQUIRED)
2002 {
2003 plci->spoofed_msg = CALL_RETRIEVE;
2004 plci->internal_command = BLOCK_PLCI;
2005 plci->command = 0;
2006 dbug(1,dprintf("Spoof"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002007 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 }
2009 else
2010 {
2011 sig_req(plci,CALL_RETRIEVE,0);
2012 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002013 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 }
2015 }
2016 else Info = 0x3010; /* wrong state */
2017 break;
2018 case S_SUSPEND:
2019 if(parms->length)
2020 {
2021 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2022 {
2023 dbug(1,dprintf("format wrong"));
2024 Info = _WRONG_MESSAGE_FORMAT;
2025 break;
2026 }
2027 }
2028 if(plci && plci->State)
2029 {
2030 add_s(plci,CAI,&ss_parms[2]);
2031 plci->command = SUSPEND_REQ;
2032 sig_req(plci,SUSPEND,0);
2033 plci->State = SUSPENDING;
2034 send_req(plci);
2035 }
2036 else Info = 0x3010; /* wrong state */
2037 break;
2038
2039 case S_RESUME:
2040 if(!(i=get_plci(a)) )
2041 {
2042 Info = _OUT_OF_PLCI;
2043 break;
2044 }
2045 rplci = &a->plci[i-1];
2046 rplci->appl = appl;
2047 rplci->number = Number;
2048 rplci->tel = 0;
2049 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2050 /* check 'external controller' bit for codec support */
2051 if(Id & EXT_CONTROLLER)
2052 {
2053 if(AdvCodecSupport(a, rplci, appl, 0) )
2054 {
2055 rplci->Id = 0;
2056 Info = 0x300A;
2057 break;
2058 }
2059 }
2060 if(parms->length)
2061 {
2062 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2063 {
2064 dbug(1,dprintf("format wrong"));
2065 rplci->Id = 0;
2066 Info = _WRONG_MESSAGE_FORMAT;
2067 break;
2068 }
2069 }
2070 dummy.length = 0;
2071 dummy.info = "\x00";
2072 add_b1(rplci, &dummy, 0, 0);
2073 if (a->Info_Mask[appl->Id-1] & 0x200)
2074 {
2075 /* early B3 connect (CIP mask bit 9) no release after a disc */
2076 add_p(rplci,LLI,"\x01\x01");
2077 }
2078 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2079 sig_req(rplci,ASSIGN,DSIG_ID);
2080 send_req(rplci);
2081 add_s(rplci,CAI,&ss_parms[2]);
2082 rplci->command = RESUME_REQ;
2083 sig_req(rplci,RESUME,0);
2084 rplci->State = RESUMING;
2085 send_req(rplci);
2086 break;
2087
2088 case S_CONF_BEGIN: /* Request */
2089 case S_CONF_DROP:
2090 case S_CONF_ISOLATE:
2091 case S_CONF_REATTACH:
2092 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2093 {
2094 dbug(1,dprintf("format wrong"));
2095 Info = _WRONG_MESSAGE_FORMAT;
2096 break;
2097 }
2098 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2099 {
2100 d = GET_DWORD(ss_parms[2].info);
2101 if(d>=0x80)
2102 {
2103 dbug(1,dprintf("format wrong"));
2104 Info = _WRONG_MESSAGE_FORMAT;
2105 break;
2106 }
2107 plci->ptyState = (byte)SSreq;
2108 plci->command = 0;
2109 cai[0] = 2;
2110 switch(SSreq)
2111 {
2112 case S_CONF_BEGIN:
2113 cai[1] = CONF_BEGIN;
2114 plci->internal_command = CONF_BEGIN_REQ_PEND;
2115 break;
2116 case S_CONF_DROP:
2117 cai[1] = CONF_DROP;
2118 plci->internal_command = CONF_DROP_REQ_PEND;
2119 break;
2120 case S_CONF_ISOLATE:
2121 cai[1] = CONF_ISOLATE;
2122 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2123 break;
2124 case S_CONF_REATTACH:
2125 cai[1] = CONF_REATTACH;
2126 plci->internal_command = CONF_REATTACH_REQ_PEND;
2127 break;
2128 }
2129 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2130 add_p(plci,CAI,cai);
2131 sig_req(plci,S_SERVICE,0);
2132 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002133 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 }
2135 else Info = 0x3010; /* wrong state */
2136 break;
2137
2138 case S_ECT:
2139 case S_3PTY_BEGIN:
2140 case S_3PTY_END:
2141 case S_CONF_ADD:
2142 if(parms->length==7)
2143 {
2144 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2145 {
2146 dbug(1,dprintf("format wrong"));
2147 Info = _WRONG_MESSAGE_FORMAT;
2148 break;
2149 }
2150 }
2151 else if(parms->length==8) /* workaround for the T-View-S */
2152 {
2153 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2154 {
2155 dbug(1,dprintf("format wrong"));
2156 Info = _WRONG_MESSAGE_FORMAT;
2157 break;
2158 }
2159 }
2160 else
2161 {
2162 Info = _WRONG_MESSAGE_FORMAT;
2163 break;
2164 }
2165 if(!msg[1].length)
2166 {
2167 Info = _WRONG_MESSAGE_FORMAT;
2168 break;
2169 }
2170 if (!plci)
2171 {
2172 Info = _WRONG_IDENTIFIER;
2173 break;
2174 }
2175 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2176 relatedPLCIvalue &= 0x0000FFFF;
2177 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2178 /* controller starts with 0 up to (max_adapter - 1) */
2179 if (((relatedPLCIvalue & 0x7f) == 0)
2180 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2181 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2182 {
2183 if(SSreq==S_3PTY_END)
2184 {
2185 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186 rplci = plci;
2187 }
2188 else
2189 {
2190 Info = 0x3010; /* wrong state */
2191 break;
2192 }
2193 }
2194 else
2195 {
2196 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2197 relatedPLCIvalue >>=8;
2198 /* find PLCI PTR*/
2199 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2200 {
2201 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2202 {
2203 rplci = &relatedadapter->plci[i];
2204 }
2205 }
2206 if(!rplci || !relatedPLCIvalue)
2207 {
2208 if(SSreq==S_3PTY_END)
2209 {
2210 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211 rplci = plci;
2212 }
2213 else
2214 {
2215 Info = 0x3010; /* wrong state */
2216 break;
2217 }
2218 }
2219 }
2220/*
2221 dbug(1,dprintf("rplci:%x",rplci));
2222 dbug(1,dprintf("plci:%x",plci));
2223 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2224 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2225 dbug(1,dprintf("SSreq:%x",SSreq));
2226 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2227 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2228 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2229*/
2230 /* send PTY/ECT req, cannot check all states because of US stuff */
2231 if( !rplci->internal_command && rplci->appl )
2232 {
2233 plci->command = 0;
2234 rplci->relatedPTYPLCI = plci;
2235 plci->relatedPTYPLCI = rplci;
2236 rplci->ptyState = (byte)SSreq;
2237 if(SSreq==S_ECT)
2238 {
2239 rplci->internal_command = ECT_REQ_PEND;
2240 cai[1] = ECT_EXECUTE;
2241
2242 rplci->vswitchstate=0;
2243 rplci->vsprot=0;
2244 rplci->vsprotdialect=0;
2245 plci->vswitchstate=0;
2246 plci->vsprot=0;
2247 plci->vsprotdialect=0;
2248
2249 }
2250 else if(SSreq==S_CONF_ADD)
2251 {
2252 rplci->internal_command = CONF_ADD_REQ_PEND;
2253 cai[1] = CONF_ADD;
2254 }
2255 else
2256 {
2257 rplci->internal_command = PTY_REQ_PEND;
2258 cai[1] = (byte)(SSreq-3);
2259 }
2260 rplci->number = Number;
2261 if(plci!=rplci) /* explicit invocation */
2262 {
2263 cai[0] = 2;
2264 cai[2] = plci->Sig.Id;
2265 dbug(1,dprintf("explicit invocation"));
2266 }
2267 else
2268 {
2269 dbug(1,dprintf("implicit invocation"));
2270 cai[0] = 1;
2271 }
2272 add_p(rplci,CAI,cai);
2273 sig_req(rplci,S_SERVICE,0);
2274 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002275 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 }
2277 else
2278 {
2279 dbug(0,dprintf("Wrong line"));
2280 Info = 0x3010; /* wrong state */
2281 break;
2282 }
2283 break;
2284
2285 case S_CALL_DEFLECTION:
2286 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2287 {
2288 dbug(1,dprintf("format wrong"));
2289 Info = _WRONG_MESSAGE_FORMAT;
2290 break;
2291 }
2292 if (!plci)
2293 {
2294 Info = _WRONG_IDENTIFIER;
2295 break;
2296 }
2297 /* reuse unused screening indicator */
2298 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2299 plci->command = 0;
2300 plci->internal_command = CD_REQ_PEND;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002301 appl->CDEnable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 cai[0] = 1;
2303 cai[1] = CALL_DEFLECTION;
2304 add_p(plci,CAI,cai);
2305 add_p(plci,CPN,ss_parms[3].info);
2306 sig_req(plci,S_SERVICE,0);
2307 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002308 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 break;
2310
2311 case S_CALL_FORWARDING_START:
2312 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2313 {
2314 dbug(1,dprintf("format wrong"));
2315 Info = _WRONG_MESSAGE_FORMAT;
2316 break;
2317 }
2318
2319 if((i=get_plci(a)))
2320 {
2321 rplci = &a->plci[i-1];
2322 rplci->appl = appl;
2323 add_p(rplci,CAI,"\x01\x80");
2324 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2325 sig_req(rplci,ASSIGN,DSIG_ID);
2326 send_req(rplci);
2327 }
2328 else
2329 {
2330 Info = _OUT_OF_PLCI;
2331 break;
2332 }
2333
2334 /* reuse unused screening indicator */
2335 rplci->internal_command = CF_START_PEND;
2336 rplci->appl = appl;
2337 rplci->number = Number;
2338 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2339 cai[0] = 2;
2340 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2341 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2342 add_p(rplci,CAI,cai);
2343 add_p(rplci,OAD,ss_parms[5].info);
2344 add_p(rplci,CPN,ss_parms[6].info);
2345 sig_req(rplci,S_SERVICE,0);
2346 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002347 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 break;
2349
2350 case S_INTERROGATE_DIVERSION:
2351 case S_INTERROGATE_NUMBERS:
2352 case S_CALL_FORWARDING_STOP:
2353 case S_CCBS_REQUEST:
2354 case S_CCBS_DEACTIVATE:
2355 case S_CCBS_INTERROGATE:
2356 switch(SSreq)
2357 {
2358 case S_INTERROGATE_NUMBERS:
2359 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2360 {
2361 dbug(0,dprintf("format wrong"));
2362 Info = _WRONG_MESSAGE_FORMAT;
2363 }
2364 break;
2365 case S_CCBS_REQUEST:
2366 case S_CCBS_DEACTIVATE:
2367 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2368 {
2369 dbug(0,dprintf("format wrong"));
2370 Info = _WRONG_MESSAGE_FORMAT;
2371 }
2372 break;
2373 case S_CCBS_INTERROGATE:
2374 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2375 {
2376 dbug(0,dprintf("format wrong"));
2377 Info = _WRONG_MESSAGE_FORMAT;
2378 }
2379 break;
2380 default:
2381 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2382 {
2383 dbug(0,dprintf("format wrong"));
2384 Info = _WRONG_MESSAGE_FORMAT;
2385 break;
2386 }
2387 break;
2388 }
2389
2390 if(Info) break;
2391 if((i=get_plci(a)))
2392 {
2393 rplci = &a->plci[i-1];
2394 switch(SSreq)
2395 {
2396 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2397 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2398 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2399 break;
2400 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2401 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2402 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2403 break;
2404 case S_CALL_FORWARDING_STOP:
2405 rplci->internal_command = CF_STOP_PEND;
2406 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2407 break;
2408 case S_CCBS_REQUEST:
2409 cai[1] = CCBS_REQUEST;
2410 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2411 break;
2412 case S_CCBS_DEACTIVATE:
2413 cai[1] = CCBS_DEACTIVATE;
2414 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2415 break;
2416 case S_CCBS_INTERROGATE:
2417 cai[1] = CCBS_INTERROGATE;
2418 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2419 break;
2420 default:
2421 cai[1] = 0;
2422 break;
2423 }
2424 rplci->appl = appl;
2425 rplci->number = Number;
2426 add_p(rplci,CAI,"\x01\x80");
2427 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2428 sig_req(rplci,ASSIGN,DSIG_ID);
2429 send_req(rplci);
2430 }
2431 else
2432 {
2433 Info = _OUT_OF_PLCI;
2434 break;
2435 }
2436
2437 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2438 switch(SSreq)
2439 {
2440 case S_INTERROGATE_NUMBERS:
2441 cai[0] = 1;
2442 add_p(rplci,CAI,cai);
2443 break;
2444 case S_CCBS_REQUEST:
2445 case S_CCBS_DEACTIVATE:
2446 cai[0] = 3;
2447 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2448 add_p(rplci,CAI,cai);
2449 break;
2450 case S_CCBS_INTERROGATE:
2451 cai[0] = 3;
2452 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2453 add_p(rplci,CAI,cai);
2454 add_p(rplci,OAD,ss_parms[4].info);
2455 break;
2456 default:
2457 cai[0] = 2;
2458 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2459 add_p(rplci,CAI,cai);
2460 add_p(rplci,OAD,ss_parms[5].info);
2461 break;
2462 }
2463
2464 sig_req(rplci,S_SERVICE,0);
2465 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002466 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 break;
2468
2469 case S_MWI_ACTIVATE:
2470 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2471 {
2472 dbug(1,dprintf("format wrong"));
2473 Info = _WRONG_MESSAGE_FORMAT;
2474 break;
2475 }
2476 if(!plci)
2477 {
2478 if((i=get_plci(a)))
2479 {
2480 rplci = &a->plci[i-1];
2481 rplci->appl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002482 rplci->cr_enquiry=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 add_p(rplci,CAI,"\x01\x80");
2484 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2485 sig_req(rplci,ASSIGN,DSIG_ID);
2486 send_req(rplci);
2487 }
2488 else
2489 {
2490 Info = _OUT_OF_PLCI;
2491 break;
2492 }
2493 }
2494 else
2495 {
2496 rplci = plci;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002497 rplci->cr_enquiry=false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 }
2499
2500 rplci->command = 0;
2501 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2502 rplci->appl = appl;
2503 rplci->number = Number;
2504
2505 cai[0] = 13;
2506 cai[1] = ACTIVATION_MWI; /* Function */
2507 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2508 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2509 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2510 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2511 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2512 add_p(rplci,CAI,cai);
2513 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2514 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2515 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2516 add_p(rplci,UID,ss_parms[10].info); /* Time */
2517 sig_req(rplci,S_SERVICE,0);
2518 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002519 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
2521 case S_MWI_DEACTIVATE:
2522 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2523 {
2524 dbug(1,dprintf("format wrong"));
2525 Info = _WRONG_MESSAGE_FORMAT;
2526 break;
2527 }
2528 if(!plci)
2529 {
2530 if((i=get_plci(a)))
2531 {
2532 rplci = &a->plci[i-1];
2533 rplci->appl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002534 rplci->cr_enquiry=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 add_p(rplci,CAI,"\x01\x80");
2536 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2537 sig_req(rplci,ASSIGN,DSIG_ID);
2538 send_req(rplci);
2539 }
2540 else
2541 {
2542 Info = _OUT_OF_PLCI;
2543 break;
2544 }
2545 }
2546 else
2547 {
2548 rplci = plci;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002549 rplci->cr_enquiry=false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 }
2551
2552 rplci->command = 0;
2553 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2554 rplci->appl = appl;
2555 rplci->number = Number;
2556
2557 cai[0] = 5;
2558 cai[1] = DEACTIVATION_MWI; /* Function */
2559 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2560 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2561 add_p(rplci,CAI,cai);
2562 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2563 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2564 sig_req(rplci,S_SERVICE,0);
2565 send_req(rplci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002566 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
2568 default:
2569 Info = 0x300E; /* not supported */
2570 break;
2571 }
2572 break; /* case SELECTOR_SU_SERV: end */
2573
2574
2575 case SELECTOR_DTMF:
2576 return (dtmf_request (Id, Number, a, plci, appl, msg));
2577
2578
2579
2580 case SELECTOR_LINE_INTERCONNECT:
2581 return (mixer_request (Id, Number, a, plci, appl, msg));
2582
2583
2584
2585 case PRIV_SELECTOR_ECHO_CANCELLER:
2586 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2587 return (ec_request (Id, Number, a, plci, appl, msg));
2588
2589 case SELECTOR_ECHO_CANCELLER:
2590 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2591 return (ec_request (Id, Number, a, plci, appl, msg));
2592
2593
2594 case SELECTOR_V42BIS:
2595 default:
2596 Info = _FACILITY_NOT_SUPPORTED;
2597 break;
2598 } /* end of switch(selector) */
2599 }
2600
2601 dbug(1,dprintf("SendFacRc"));
2602 sendf(appl,
2603 _FACILITY_R|CONFIRM,
2604 Id,
2605 Number,
2606 "wws",Info,selector,SSparms);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002607 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608}
2609
Hannes Eder465e9852009-02-25 13:11:37 +00002610static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2611 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612{
2613 dbug(1,dprintf("facility_res"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002614 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615}
2616
Hannes Eder465e9852009-02-25 13:11:37 +00002617static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2618 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619{
2620 word Info = 0;
2621 byte req;
2622 byte len;
2623 word w;
2624 word fax_control_bits, fax_feature_bits, fax_info_change;
2625 API_PARSE * ncpi;
2626 byte pvc[2];
2627
2628 API_PARSE fax_parms[9];
2629 word i;
2630
2631
2632 dbug(1,dprintf("connect_b3_req"));
2633 if(plci)
2634 {
2635 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2636 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2637 {
2638 Info = _WRONG_STATE;
2639 }
2640 else
2641 {
2642 /* local reply if assign unsuccessfull
2643 or B3 protocol allows only one layer 3 connection
2644 and already connected
2645 or B2 protocol not any LAPD
2646 and connect_b3_req contradicts originate/answer direction */
2647 if (!plci->NL.Id
2648 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2649 && ((plci->channels != 0)
2650 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2651 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2652 {
2653 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2654 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2655 Info = _WRONG_STATE;
2656 sendf(appl,
2657 _CONNECT_B3_R|CONFIRM,
2658 Id,
2659 Number,
2660 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002661 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 }
2663 plci->requested_options_conn = 0;
2664
2665 req = N_CONNECT;
2666 ncpi = &parms[0];
2667 if(plci->B3_prot==2 || plci->B3_prot==3)
2668 {
2669 if(ncpi->length>2)
2670 {
2671 /* check for PVC */
2672 if(ncpi->info[2] || ncpi->info[3])
2673 {
2674 pvc[0] = ncpi->info[3];
2675 pvc[1] = ncpi->info[2];
2676 add_d(plci,2,pvc);
2677 req = N_RESET;
2678 }
2679 else
2680 {
2681 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2682 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2683 }
2684 }
2685 }
2686 else if(plci->B3_prot==5)
2687 {
2688 if (plci->NL.Id && !plci->nl_remove_id)
2689 {
2690 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2691 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2692 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2693 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2694 {
Jiri Slaby1ea70842009-11-04 08:28:12 -08002695 len = offsetof(T30_INFO, universal_6);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002696 fax_info_change = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 if (ncpi->length >= 4)
2698 {
2699 w = GET_WORD(&ncpi->info[3]);
2700 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2701 {
2702 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2703 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2704 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002705 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 }
2707 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2708 if (w & 0x0002) /* Fax-polling request */
2709 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2710 if ((w & 0x0004) /* Request to send / poll another document */
2711 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2712 {
2713 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2714 }
2715 if (ncpi->length >= 6)
2716 {
2717 w = GET_WORD(&ncpi->info[5]);
2718 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2719 {
2720 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002721 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 }
2723
2724 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2725 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2726 {
2727 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2728 }
2729 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2730 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2731 {
2732 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2733 }
2734 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2735 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2736 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2737 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2738 {
2739 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2740 Info = _WRONG_MESSAGE_FORMAT;
2741 else
2742 {
2743 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2744 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2745 {
2746 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2747 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2748 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2749 }
2750 w = fax_parms[4].length;
2751 if (w > 20)
2752 w = 20;
2753 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2754 for (i = 0; i < w; i++)
2755 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2756 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
Jiri Slaby1ea70842009-11-04 08:28:12 -08002757 len = offsetof(T30_INFO, station_id) + 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 w = fax_parms[5].length;
2759 if (w > 20)
2760 w = 20;
2761 plci->fax_connect_info_buffer[len++] = (byte) w;
2762 for (i = 0; i < w; i++)
2763 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2764 w = fax_parms[6].length;
2765 if (w > 20)
2766 w = 20;
2767 plci->fax_connect_info_buffer[len++] = (byte) w;
2768 for (i = 0; i < w; i++)
2769 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2770 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2771 & (1L << PRIVATE_FAX_NONSTANDARD))
2772 {
2773 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2774 {
2775 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2776 plci->fax_connect_info_buffer[len++] = 0;
2777 }
2778 else
2779 {
2780 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2781 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2782 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2783 for (i = 0; i < fax_parms[7].length; i++)
2784 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2785 }
2786 }
2787 }
2788 }
2789 else
2790 {
Jiri Slaby1ea70842009-11-04 08:28:12 -08002791 len = offsetof(T30_INFO, universal_6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002793 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
2795 }
2796 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2797 {
2798 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002799 fax_info_change = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 }
2801 }
2802 if (Info == GOOD)
2803 {
2804 plci->fax_connect_info_length = len;
2805 if (fax_info_change)
2806 {
2807 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2808 {
2809 start_internal_command (Id, plci, fax_connect_info_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002810 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 }
2812 else
2813 {
2814 start_internal_command (Id, plci, fax_adjust_b23_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002815 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 }
2817 }
2818 }
2819 }
2820 else Info = _WRONG_STATE;
2821 }
2822 else Info = _WRONG_STATE;
2823 }
2824
2825 else if (plci->B3_prot == B3_RTP)
2826 {
2827 plci->internal_req_buffer[0] = ncpi->length + 1;
2828 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2829 for (w = 0; w < ncpi->length; w++)
2830 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2831 start_internal_command (Id, plci, rtp_connect_b3_req_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002832 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 }
2834
2835 if(!Info)
2836 {
2837 nl_req_ncci(plci,req,0);
2838 return 1;
2839 }
2840 }
2841 }
2842 else Info = _WRONG_IDENTIFIER;
2843
2844 sendf(appl,
2845 _CONNECT_B3_R|CONFIRM,
2846 Id,
2847 Number,
2848 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002849 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850}
2851
Hannes Eder465e9852009-02-25 13:11:37 +00002852static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2853 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854{
2855 word ncci;
2856 API_PARSE * ncpi;
2857 byte req;
2858
2859 word w;
2860
2861
2862 API_PARSE fax_parms[9];
2863 word i;
2864 byte len;
2865
2866
2867 dbug(1,dprintf("connect_b3_res"));
2868
2869 ncci = (word)(Id>>16);
2870 if(plci && ncci) {
2871 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2872 if (GET_WORD (&parms[0].info[0]) != 0)
2873 {
2874 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2875 channel_request_xon (plci, a->ncci_ch[ncci]);
2876 channel_xmit_xon (plci);
2877 cleanup_ncci_data (plci, ncci);
2878 nl_req_ncci(plci,N_DISC,(byte)ncci);
2879 return 1;
2880 }
2881 a->ncci_state[ncci] = INC_ACT_PENDING;
2882
2883 req = N_CONNECT_ACK;
2884 ncpi = &parms[1];
2885 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2886 {
2887
2888 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2889 & (1L << PRIVATE_FAX_NONSTANDARD))
2890 {
2891 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2892 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2893 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2894 {
Jiri Slaby1ea70842009-11-04 08:28:12 -08002895 len = offsetof(T30_INFO, station_id) + 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 if (plci->fax_connect_info_length < len)
2897 {
2898 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2899 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2900 }
2901 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2902 {
2903 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2904 }
2905 else
2906 {
2907 if (plci->fax_connect_info_length <= len)
2908 plci->fax_connect_info_buffer[len] = 0;
2909 len += 1 + plci->fax_connect_info_buffer[len];
2910 if (plci->fax_connect_info_length <= len)
2911 plci->fax_connect_info_buffer[len] = 0;
2912 len += 1 + plci->fax_connect_info_buffer[len];
2913 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2914 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2915 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2916 for (i = 0; i < fax_parms[7].length; i++)
2917 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2918 }
2919 plci->fax_connect_info_length = len;
2920 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2921 start_internal_command (Id, plci, fax_connect_ack_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002922 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 }
2924 }
2925
2926 nl_req_ncci(plci,req,(byte)ncci);
2927 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2928 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2929 {
2930 if (plci->B3_prot == 4)
2931 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2932 else
2933 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2934 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2935 }
2936 }
2937
2938 else if (plci->B3_prot == B3_RTP)
2939 {
2940 plci->internal_req_buffer[0] = ncpi->length + 1;
2941 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2942 for (w = 0; w < ncpi->length; w++)
2943 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2944 start_internal_command (Id, plci, rtp_connect_b3_res_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002945 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 }
2947
2948 else
2949 {
2950 if(ncpi->length>2) {
2951 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2952 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2953 }
2954 nl_req_ncci(plci,req,(byte)ncci);
2955 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2956 if (plci->adjust_b_restore)
2957 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002958 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 start_internal_command (Id, plci, adjust_b_restore);
2960 }
2961 }
2962 return 1;
2963 }
2964 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002965 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966}
2967
Hannes Eder465e9852009-02-25 13:11:37 +00002968static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2969 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970{
2971 word ncci;
2972
2973 ncci = (word)(Id>>16);
2974 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2975
2976 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2977 && (plci->State != OUTG_DIS_PENDING))
2978 {
2979 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2980 a->ncci_state[ncci] = CONNECTED;
2981 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2982 channel_request_xon (plci, a->ncci_ch[ncci]);
2983 channel_xmit_xon (plci);
2984 }
2985 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08002986 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987}
2988
Hannes Eder465e9852009-02-25 13:11:37 +00002989static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2990 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991{
2992 word Info;
2993 word ncci;
2994 API_PARSE * ncpi;
2995
2996 dbug(1,dprintf("disconnect_b3_req"));
2997
2998 Info = _WRONG_IDENTIFIER;
2999 ncci = (word)(Id>>16);
3000 if (plci && ncci)
3001 {
3002 Info = _WRONG_STATE;
3003 if ((a->ncci_state[ncci] == CONNECTED)
3004 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3005 || (a->ncci_state[ncci] == INC_CON_PENDING)
3006 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3007 {
3008 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3009 channel_request_xon (plci, a->ncci_ch[ncci]);
3010 channel_xmit_xon (plci);
3011
3012 if (a->ncci[ncci].data_pending
3013 && ((plci->B3_prot == B3_TRANSPARENT)
3014 || (plci->B3_prot == B3_T30)
3015 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3016 {
3017 plci->send_disc = (byte)ncci;
3018 plci->command = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003019 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 }
3021 else
3022 {
3023 cleanup_ncci_data (plci, ncci);
3024
3025 if(plci->B3_prot==2 || plci->B3_prot==3)
3026 {
3027 ncpi = &parms[0];
3028 if(ncpi->length>3)
3029 {
3030 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3031 }
3032 }
3033 nl_req_ncci(plci,N_DISC,(byte)ncci);
3034 }
3035 return 1;
3036 }
3037 }
3038 sendf(appl,
3039 _DISCONNECT_B3_R|CONFIRM,
3040 Id,
3041 Number,
3042 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003043 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044}
3045
Hannes Eder465e9852009-02-25 13:11:37 +00003046static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3047 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048{
3049 word ncci;
3050 word i;
3051
3052 ncci = (word)(Id>>16);
3053 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3054 if(plci && ncci) {
3055 plci->requested_options_conn = 0;
3056 plci->fax_connect_info_length = 0;
3057 plci->ncpi_state = 0x00;
3058 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3059 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3060 {
3061 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3062 }
3063 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3064 if(i<MAX_CHANNELS_PER_PLCI) {
3065 if(plci->channels)plci->channels--;
3066 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3067 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3068
3069 ncci_free_receive_buffers (plci, ncci);
3070
3071 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3072 if(plci->State == SUSPENDING){
3073 sendf(plci->appl,
3074 _FACILITY_I,
3075 Id & 0xffffL,
3076 0,
3077 "ws", (word)3, "\x03\x04\x00\x00");
3078 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3079 }
3080 plci_remove(plci);
3081 plci->State=IDLE;
3082 }
3083 }
3084 else
3085 {
3086 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3087 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3088 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3089 {
3090 ncci_free_receive_buffers (plci, ncci);
3091
3092 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3093
3094 plci->adapter->ncci_state[ncci] = IDLE;
3095 start_internal_command (Id, plci, fax_disconnect_command);
3096 return 1;
3097 }
3098 }
3099 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003100 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101}
3102
Hannes Eder465e9852009-02-25 13:11:37 +00003103static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3104 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105{
3106 NCCI *ncci_ptr;
3107 DATA_B3_DESC *data;
3108 word Info;
3109 word ncci;
3110 word i;
3111
3112 dbug(1,dprintf("data_b3_req"));
3113
3114 Info = _WRONG_IDENTIFIER;
3115 ncci = (word)(Id>>16);
3116 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3117
3118 if (plci && ncci)
3119 {
3120 Info = _WRONG_STATE;
3121 if ((a->ncci_state[ncci] == CONNECTED)
3122 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3123 {
3124 /* queue data */
3125 ncci_ptr = &(a->ncci[ncci]);
3126 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3127 if (i >= MAX_DATA_B3)
3128 i -= MAX_DATA_B3;
3129 data = &(ncci_ptr->DBuffer[i]);
3130 data->Number = Number;
3131 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3132 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3133 {
3134
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07003135 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136
3137 }
3138 else
3139 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3140 data->Length = GET_WORD(parms[1].info);
3141 data->Handle = GET_WORD(parms[2].info);
3142 data->Flags = GET_WORD(parms[3].info);
3143 (ncci_ptr->data_pending)++;
3144
3145 /* check for delivery confirmation */
3146 if (data->Flags & 0x0004)
3147 {
3148 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3149 if (i >= MAX_DATA_ACK)
3150 i -= MAX_DATA_ACK;
3151 ncci_ptr->DataAck[i].Number = data->Number;
3152 ncci_ptr->DataAck[i].Handle = data->Handle;
3153 (ncci_ptr->data_ack_pending)++;
3154 }
3155
3156 send_data(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003157 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 }
3159 }
3160 if (appl)
3161 {
3162 if (plci)
3163 {
3164 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3165 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3166 {
3167
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07003168 TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
3170 }
3171 }
3172 sendf(appl,
3173 _DATA_B3_R|CONFIRM,
3174 Id,
3175 Number,
3176 "ww",GET_WORD(parms[2].info),Info);
3177 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003178 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179}
3180
Hannes Eder465e9852009-02-25 13:11:37 +00003181static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3182 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183{
3184 word n;
3185 word ncci;
3186 word NCCIcode;
3187
3188 dbug(1,dprintf("data_b3_res"));
3189
3190 ncci = (word)(Id>>16);
3191 if(plci && ncci) {
3192 n = GET_WORD(parms[0].info);
3193 dbug(1,dprintf("free(%d)",n));
3194 NCCIcode = ncci | (((word) a->Id) << 8);
3195 if(n<appl->MaxBuffer &&
3196 appl->DataNCCI[n]==NCCIcode &&
3197 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3198 dbug(1,dprintf("found"));
3199 appl->DataNCCI[n] = 0;
3200
3201 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3202 channel_request_xon (plci, a->ncci_ch[ncci]);
3203 }
3204 channel_xmit_xon (plci);
3205
3206 if(appl->DataFlags[n] &4) {
3207 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3208 return 1;
3209 }
3210 }
3211 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003212 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213}
3214
Hannes Eder465e9852009-02-25 13:11:37 +00003215static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3216 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217{
3218 word Info;
3219 word ncci;
3220
3221 dbug(1,dprintf("reset_b3_req"));
3222
3223 Info = _WRONG_IDENTIFIER;
3224 ncci = (word)(Id>>16);
3225 if(plci && ncci)
3226 {
3227 Info = _WRONG_STATE;
3228 switch (plci->B3_prot)
3229 {
3230 case B3_ISO8208:
3231 case B3_X25_DCE:
3232 if(a->ncci_state[ncci]==CONNECTED)
3233 {
3234 nl_req_ncci(plci,N_RESET,(byte)ncci);
3235 send_req(plci);
3236 Info = GOOD;
3237 }
3238 break;
3239 case B3_TRANSPARENT:
3240 if(a->ncci_state[ncci]==CONNECTED)
3241 {
3242 start_internal_command (Id, plci, reset_b3_command);
3243 Info = GOOD;
3244 }
3245 break;
3246 }
3247 }
3248 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3249 sendf(appl,
3250 _RESET_B3_R|CONFIRM,
3251 Id,
3252 Number,
3253 "w",Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003254 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255}
3256
Hannes Eder465e9852009-02-25 13:11:37 +00003257static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3258 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259{
3260 word ncci;
3261
3262 dbug(1,dprintf("reset_b3_res"));
3263
3264 ncci = (word)(Id>>16);
3265 if(plci && ncci) {
3266 switch (plci->B3_prot)
3267 {
3268 case B3_ISO8208:
3269 case B3_X25_DCE:
3270 if(a->ncci_state[ncci]==INC_RES_PENDING)
3271 {
3272 a->ncci_state[ncci] = CONNECTED;
3273 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003274 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 }
3276 break;
3277 }
3278 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003279 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280}
3281
Hannes Eder465e9852009-02-25 13:11:37 +00003282static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3283 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284{
3285 word ncci;
3286 API_PARSE * ncpi;
3287 byte req;
3288
3289 dbug(1,dprintf("connect_b3_t90_a_res"));
3290
3291 ncci = (word)(Id>>16);
3292 if(plci && ncci) {
3293 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3294 a->ncci_state[ncci] = CONNECTED;
3295 }
3296 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3297 a->ncci_state[ncci] = CONNECTED;
3298
3299 req = N_CONNECT_ACK;
3300
3301 /* parms[0]==0 for CAPI original message definition! */
3302 if(parms[0].info) {
3303 ncpi = &parms[1];
3304 if(ncpi->length>2) {
3305 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3306 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3307 }
3308 }
3309 nl_req_ncci(plci,req,(byte)ncci);
3310 return 1;
3311 }
3312 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003313 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314}
3315
3316
Hannes Eder465e9852009-02-25 13:11:37 +00003317static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3318 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319{
3320 word Info=0;
3321 word i;
3322 byte tel;
3323 API_PARSE bp_parms[7];
3324
3325 if(!plci || !msg)
3326 {
3327 Info = _WRONG_IDENTIFIER;
3328 }
3329 else
3330 {
3331 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3332 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3333 dbug(1,dprintf("PlciState=0x%x",plci->State));
3334 for(i=0;i<7;i++) bp_parms[i].length = 0;
3335
3336 /* check if no channel is open, no B3 connected only */
3337 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3338 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3339 {
3340 Info = _WRONG_STATE;
3341 }
3342 /* check message format and fill bp_parms pointer */
3343 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3344 {
3345 Info = _WRONG_MESSAGE_FORMAT;
3346 }
3347 else
3348 {
3349 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3350 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3351 if(Id & EXT_CONTROLLER)
3352 {
3353 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3354 return 0;
3355 }
3356 plci->State=INC_CON_CONNECTED_ALERT;
3357 plci->appl = appl;
3358 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3359 dump_c_ind_mask (plci);
3360 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3361 { /* its quasi a connect */
3362 if(test_c_ind_mask_bit (plci, i))
3363 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3364 }
3365 }
3366
3367 api_save_msg(msg, "s", &plci->saved_msg);
3368 tel = plci->tel;
3369 if(Id & EXT_CONTROLLER)
3370 {
3371 if(tel) /* external controller in use by this PLCI */
3372 {
3373 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3374 {
3375 dbug(1,dprintf("Ext_Ctrl in use 1"));
3376 Info = _WRONG_STATE;
3377 }
3378 }
3379 else /* external controller NOT in use by this PLCI ? */
3380 {
3381 if(a->AdvSignalPLCI)
3382 {
3383 dbug(1,dprintf("Ext_Ctrl in use 2"));
3384 Info = _WRONG_STATE;
3385 }
3386 else /* activate the codec */
3387 {
3388 dbug(1,dprintf("Ext_Ctrl start"));
3389 if(AdvCodecSupport(a, plci, appl, 0) )
3390 {
3391 dbug(1,dprintf("Error in codec procedures"));
3392 Info = _WRONG_STATE;
3393 }
3394 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3395 {
3396 plci->spoofed_msg = AWAITING_SELECT_B;
3397 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3398 plci->command = 0;
3399 dbug(1,dprintf("continue if codec loaded"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003400 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 }
3402 }
3403 }
3404 }
3405 else /* external controller bit is OFF */
3406 {
3407 if(tel) /* external controller in use, need to switch off */
3408 {
3409 if(a->AdvSignalAppl==appl)
3410 {
3411 CodecIdCheck(a, plci);
3412 plci->tel = 0;
3413 plci->adv_nl = 0;
3414 dbug(1,dprintf("Ext_Ctrl disable"));
3415 }
3416 else
3417 {
3418 dbug(1,dprintf("Ext_Ctrl not requested"));
3419 }
3420 }
3421 }
3422 if (!Info)
3423 {
3424 if (plci->call_dir & CALL_DIR_OUT)
3425 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3426 else if (plci->call_dir & CALL_DIR_IN)
3427 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3428 start_internal_command (Id, plci, select_b_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003429 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 }
3431 }
3432 }
3433 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003434 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435}
3436
Hannes Eder4ee59d52008-12-16 01:17:33 -08003437static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3438 PLCI *plci, APPL *appl, API_PARSE *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439{
3440 word command;
3441 word i;
3442 word ncci;
3443 API_PARSE * m;
3444 API_PARSE m_parms[5];
3445 word codec;
3446 byte req;
3447 byte ch;
3448 byte dir;
3449 static byte chi[2] = {0x01,0x00};
3450 static byte lli[2] = {0x01,0x00};
3451 static byte codec_cai[2] = {0x01,0x01};
3452 static byte null_msg = {0};
3453 static API_PARSE null_parms = { 0, &null_msg };
3454 PLCI * v_plci;
3455 word Info=0;
3456
3457 dbug(1,dprintf("manufacturer_req"));
3458 for(i=0;i<5;i++) m_parms[i].length = 0;
3459
3460 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3461 Info = _WRONG_MESSAGE_FORMAT;
3462 }
3463 command = GET_WORD(parms[1].info);
3464 m = &parms[2];
3465 if (!Info)
3466 {
3467 switch(command) {
3468 case _DI_ASSIGN_PLCI:
3469 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3470 Info = _WRONG_MESSAGE_FORMAT;
3471 break;
3472 }
3473 codec = GET_WORD(m_parms[0].info);
3474 ch = m_parms[1].info[0];
3475 dir = m_parms[2].info[0];
3476 if((i=get_plci(a))) {
3477 plci = &a->plci[i-1];
3478 plci->appl = appl;
3479 plci->command = _MANUFACTURER_R;
3480 plci->m_command = command;
3481 plci->number = Number;
3482 plci->State = LOCAL_CONNECT;
3483 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3484 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3485
3486 if((ch==1 || ch==2) && (dir<=2)) {
3487 chi[1] = (byte)(0x80|ch);
3488 lli[1] = 0;
3489 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3490 switch(codec)
3491 {
3492 case 0:
3493 Info = add_b1(plci,&m_parms[3],0,0);
3494 break;
3495 case 1:
3496 add_p(plci,CAI,codec_cai);
3497 break;
3498 /* manual 'swich on' to the codec support without signalling */
3499 /* first 'assign plci' with this function, then use */
3500 case 2:
3501 if(AdvCodecSupport(a, plci, appl, 0) ) {
3502 Info = _RESOURCE_ERROR;
3503 }
3504 else {
3505 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3506 lli[1] = 0x10; /* local call codec stream */
3507 }
3508 break;
3509 }
3510
3511 plci->State = LOCAL_CONNECT;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003512 plci->manufacturer = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 plci->command = _MANUFACTURER_R;
3514 plci->m_command = command;
3515 plci->number = Number;
3516
3517 if(!Info)
3518 {
3519 add_p(plci,LLI,lli);
3520 add_p(plci,CHI,chi);
3521 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3522 sig_req(plci,ASSIGN,DSIG_ID);
3523
3524 if(!codec)
3525 {
3526 Info = add_b23(plci,&m_parms[3]);
3527 if(!Info)
3528 {
3529 nl_req_ncci(plci,ASSIGN,0);
3530 send_req(plci);
3531 }
3532 }
3533 if(!Info)
3534 {
3535 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3536 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3537 {
3538 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3539 plci->spoofed_msg = AWAITING_MANUF_CON;
3540 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3541 plci->command = 0;
3542 send_req(plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003543 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 }
3545 if(dir==1) {
3546 sig_req(plci,CALL_REQ,0);
3547 }
3548 else if(!dir){
3549 sig_req(plci,LISTEN_REQ,0);
3550 }
3551 send_req(plci);
3552 }
3553 else
3554 {
3555 sendf(appl,
3556 _MANUFACTURER_R|CONFIRM,
3557 Id,
3558 Number,
3559 "dww",_DI_MANU_ID,command,Info);
3560 return 2;
3561 }
3562 }
3563 }
3564 }
3565 else Info = _OUT_OF_PLCI;
3566 break;
3567
3568 case _DI_IDI_CTRL:
3569 if(!plci)
3570 {
3571 Info = _WRONG_IDENTIFIER;
3572 break;
3573 }
3574 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3575 Info = _WRONG_MESSAGE_FORMAT;
3576 break;
3577 }
3578 req = m_parms[0].info[0];
3579 plci->command = _MANUFACTURER_R;
3580 plci->m_command = command;
3581 plci->number = Number;
3582 if(req==CALL_REQ)
3583 {
3584 plci->b_channel = getChannel(&m_parms[1]);
3585 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3586 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3587 {
3588 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3589 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3590 plci->command = 0;
3591 break;
3592 }
3593 }
3594 else if(req==LAW_REQ)
3595 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003596 plci->cr_enquiry = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 }
3598 add_ss(plci,FTY,&m_parms[1]);
3599 sig_req(plci,req,0);
3600 send_req(plci);
3601 if(req==HANGUP)
3602 {
3603 if (plci->NL.Id && !plci->nl_remove_id)
3604 {
3605 if (plci->channels)
3606 {
3607 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3608 {
3609 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3610 {
3611 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3612 cleanup_ncci_data (plci, ncci);
3613 nl_req_ncci(plci,N_DISC,(byte)ncci);
3614 }
3615 }
3616 }
3617 mixer_remove (plci);
3618 nl_req_ncci(plci,REMOVE,0);
3619 send_req(plci);
3620 }
3621 }
3622 break;
3623
3624 case _DI_SIG_CTRL:
3625 /* signalling control for loop activation B-channel */
3626 if(!plci)
3627 {
3628 Info = _WRONG_IDENTIFIER;
3629 break;
3630 }
3631 if(m->length){
3632 plci->command = _MANUFACTURER_R;
3633 plci->number = Number;
3634 add_ss(plci,FTY,m);
3635 sig_req(plci,SIG_CTRL,0);
3636 send_req(plci);
3637 }
3638 else Info = _WRONG_MESSAGE_FORMAT;
3639 break;
3640
3641 case _DI_RXT_CTRL:
3642 /* activation control for receiver/transmitter B-channel */
3643 if(!plci)
3644 {
3645 Info = _WRONG_IDENTIFIER;
3646 break;
3647 }
3648 if(m->length){
3649 plci->command = _MANUFACTURER_R;
3650 plci->number = Number;
3651 add_ss(plci,FTY,m);
3652 sig_req(plci,DSP_CTRL,0);
3653 send_req(plci);
3654 }
3655 else Info = _WRONG_MESSAGE_FORMAT;
3656 break;
3657
3658 case _DI_ADV_CODEC:
3659 case _DI_DSP_CTRL:
3660 /* TEL_CTRL commands to support non standard adjustments: */
3661 /* Ring on/off, Handset micro volume, external micro vol. */
3662 /* handset+external speaker volume, receiver+transm. gain,*/
3663 /* handsfree on (hookinfo off), set mixer command */
3664
3665 if(command == _DI_ADV_CODEC)
3666 {
3667 if(!a->AdvCodecPLCI) {
3668 Info = _WRONG_STATE;
3669 break;
3670 }
3671 v_plci = a->AdvCodecPLCI;
3672 }
3673 else
3674 {
3675 if (plci
3676 && (m->length >= 3)
3677 && (m->info[1] == 0x1c)
3678 && (m->info[2] >= 1))
3679 {
3680 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3681 {
3682 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3683 {
3684 Info = _WRONG_STATE;
3685 break;
3686 }
3687 a->adv_voice_coef_length = m->info[2] - 1;
3688 if (a->adv_voice_coef_length > m->length - 3)
3689 a->adv_voice_coef_length = (byte)(m->length - 3);
3690 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3691 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3692 for (i = 0; i < a->adv_voice_coef_length; i++)
3693 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3694 if (plci->B1_facilities & B1_FACILITY_VOICE)
3695 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3696 break;
3697 }
3698 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3699 {
3700 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3701 {
3702 Info = _FACILITY_NOT_SUPPORTED;
3703 break;
3704 }
3705
3706 plci->dtmf_parameter_length = m->info[2] - 1;
3707 if (plci->dtmf_parameter_length > m->length - 3)
3708 plci->dtmf_parameter_length = (byte)(m->length - 3);
3709 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3710 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3711 for (i = 0; i < plci->dtmf_parameter_length; i++)
3712 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3713 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3714 dtmf_parameter_write (plci);
3715 break;
3716
3717 }
3718 }
3719 v_plci = plci;
3720 }
3721
3722 if(!v_plci)
3723 {
3724 Info = _WRONG_IDENTIFIER;
3725 break;
3726 }
3727 if(m->length){
3728 add_ss(v_plci,FTY,m);
3729 sig_req(v_plci,TEL_CTRL,0);
3730 send_req(v_plci);
3731 }
3732 else Info = _WRONG_MESSAGE_FORMAT;
3733
3734 break;
3735
3736 case _DI_OPTIONS_REQUEST:
3737 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3738 Info = _WRONG_MESSAGE_FORMAT;
3739 break;
3740 }
3741 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3742 {
3743 Info = _FACILITY_NOT_SUPPORTED;
3744 break;
3745 }
3746 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3747 break;
3748
3749
3750
3751 default:
3752 Info = _WRONG_MESSAGE_FORMAT;
3753 break;
3754 }
3755 }
3756
3757 sendf(appl,
3758 _MANUFACTURER_R|CONFIRM,
3759 Id,
3760 Number,
3761 "dww",_DI_MANU_ID,command,Info);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003762 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763}
3764
3765
Hannes Eder4ee59d52008-12-16 01:17:33 -08003766static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3767 PLCI *plci, APPL *appl, API_PARSE *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768{
3769 word indication;
3770
3771 API_PARSE m_parms[3];
3772 API_PARSE *ncpi;
3773 API_PARSE fax_parms[9];
3774 word i;
3775 byte len;
3776
3777
3778 dbug(1,dprintf("manufacturer_res"));
3779
3780 if ((msg[0].length == 0)
3781 || (msg[1].length == 0)
3782 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3783 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003784 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 }
3786 indication = GET_WORD(msg[1].info);
3787 switch (indication)
3788 {
3789
3790 case _DI_NEGOTIATE_B3:
3791 if(!plci)
3792 break;
3793 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3794 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3795 {
3796 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3797 break;
3798 }
3799 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3800 {
3801 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3802 break;
3803 }
3804 ncpi = &m_parms[1];
Jiri Slaby1ea70842009-11-04 08:28:12 -08003805 len = offsetof(T30_INFO, station_id) + 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 if (plci->fax_connect_info_length < len)
3807 {
3808 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3809 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3810 }
3811 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3812 {
3813 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3814 }
3815 else
3816 {
3817 if (plci->fax_connect_info_length <= len)
3818 plci->fax_connect_info_buffer[len] = 0;
3819 len += 1 + plci->fax_connect_info_buffer[len];
3820 if (plci->fax_connect_info_length <= len)
3821 plci->fax_connect_info_buffer[len] = 0;
3822 len += 1 + plci->fax_connect_info_buffer[len];
3823 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3824 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3825 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3826 for (i = 0; i < fax_parms[7].length; i++)
3827 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3828 }
3829 plci->fax_connect_info_length = len;
3830 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3831 start_internal_command (Id, plci, fax_edata_ack_command);
3832 break;
3833
3834 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003835 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836}
3837
3838/*------------------------------------------------------------------*/
3839/* IDI callback function */
3840/*------------------------------------------------------------------*/
3841
3842void callback(ENTITY * e)
3843{
3844 DIVA_CAPI_ADAPTER * a;
3845 APPL * appl;
3846 PLCI * plci;
3847 CAPI_MSG *m;
3848 word i, j;
3849 byte rc;
3850 byte ch;
3851 byte req;
3852 byte global_req;
3853 int no_cancel_rc;
3854
3855 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3856 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3857
3858 a = &(adapter[(byte)e->user[0]]);
3859 plci = &(a->plci[e->user[1]]);
3860 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3861
3862 /*
3863 If new protocol code and new XDI is used then CAPI should work
3864 fully in accordance with IDI cpec an look on callback field instead
3865 of Rc field for return codes.
3866 */
3867 if (((e->complete == 0xff) && no_cancel_rc) ||
3868 (e->Rc && !no_cancel_rc)) {
3869 rc = e->Rc;
3870 ch = e->RcCh;
3871 req = e->Req;
3872 e->Rc = 0;
3873
3874 if (e->user[0] & 0x8000)
3875 {
3876 /*
3877 If REMOVE request was sent then we have to wait until
3878 return code with Id set to zero arrives.
3879 All other return codes should be ignored.
3880 */
3881 if (req == REMOVE)
3882 {
3883 if (e->Id)
3884 {
3885 dbug(1,dprintf("cancel RC in REMOVE state"));
3886 return;
3887 }
3888 channel_flow_control_remove (plci);
3889 for (i = 0; i < 256; i++)
3890 {
3891 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3892 a->FlowControlIdTable[i] = 0;
3893 }
3894 plci->nl_remove_id = 0;
3895 if (plci->rx_dma_descriptor > 0) {
3896 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3897 plci->rx_dma_descriptor = 0;
3898 }
3899 }
3900 if (rc == OK_FC)
3901 {
3902 a->FlowControlIdTable[ch] = e->Id;
3903 a->FlowControlSkipTable[ch] = 0;
3904
3905 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3906 a->ch_flow_plci[ch] = plci->Id;
3907 plci->nl_req = 0;
3908 }
3909 else
3910 {
3911 /*
3912 Cancel return codes self, if feature was requested
3913 */
3914 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3915 a->FlowControlIdTable[ch] = 0;
3916 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3917 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3918 return;
3919 }
3920 }
3921
3922 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3923 {
3924 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3925 if (ch == e->ReqCh)
3926 plci->nl_req = 0;
3927 }
3928 else
3929 plci->nl_req = 0;
3930 }
3931 if (plci->nl_req)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003932 control_rc (plci, 0, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 else
3934 {
3935 if (req == N_XON)
3936 {
3937 channel_x_on (plci, ch);
3938 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003939 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 }
3941 else
3942 {
3943 if (plci->nl_global_req)
3944 {
3945 global_req = plci->nl_global_req;
3946 plci->nl_global_req = 0;
3947 if (rc != ASSIGN_OK) {
3948 e->Id = 0;
3949 if (plci->rx_dma_descriptor > 0) {
3950 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3951 plci->rx_dma_descriptor = 0;
3952 }
3953 }
3954 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003955 control_rc (plci, 0, rc, ch, global_req, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 }
3957 else if (plci->data_sent)
3958 {
3959 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003960 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 plci->NL.XNum = 1;
3962 data_rc (plci, ch);
3963 if (plci->internal_command)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003964 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 }
3966 else
3967 {
3968 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003969 control_rc (plci, req, rc, ch, 0, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 }
3971 }
3972 }
3973 }
3974 else
3975 {
3976 /*
3977 If REMOVE request was sent then we have to wait until
3978 return code with Id set to zero arrives.
3979 All other return codes should be ignored.
3980 */
3981 if (req == REMOVE)
3982 {
3983 if (e->Id)
3984 {
3985 dbug(1,dprintf("cancel RC in REMOVE state"));
3986 return;
3987 }
3988 plci->sig_remove_id = 0;
3989 }
3990 plci->sig_req = 0;
3991 if (plci->sig_global_req)
3992 {
3993 global_req = plci->sig_global_req;
3994 plci->sig_global_req = 0;
3995 if (rc != ASSIGN_OK)
3996 e->Id = 0;
3997 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08003998 control_rc (plci, 0, rc, ch, global_req, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 }
4000 else
4001 {
4002 channel_xmit_xon (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004003 control_rc (plci, req, rc, ch, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 }
4005 }
4006 /*
4007 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4008 same callback. Also if new XDI and protocol code used then jump
4009 direct to finish.
4010 */
4011 if (no_cancel_rc) {
4012 channel_xmit_xon(plci);
4013 goto capi_callback_suffix;
4014 }
4015 }
4016
4017 channel_xmit_xon(plci);
4018
4019 if (e->Ind) {
4020 if (e->user[0] &0x8000) {
4021 byte Ind = e->Ind & 0x0f;
4022 byte Ch = e->IndCh;
4023 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4024 (a->ch_flow_plci[Ch] == plci->Id)) {
4025 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4026 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4027 }
4028 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4029 }
4030 nl_ind(plci);
4031 if ((e->RNR != 1) &&
4032 (a->ch_flow_plci[Ch] == plci->Id) &&
4033 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4034 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4035 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4036 }
4037 } else {
4038 sig_ind(plci);
4039 }
4040 e->Ind = 0;
4041 }
4042
4043capi_callback_suffix:
4044
4045 while (!plci->req_in
4046 && !plci->internal_command
4047 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4048 {
4049 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4050
4051 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4052
4053 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4054 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4055 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4056 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4057 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4058 {
4059 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4060 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4061 }
4062 else
4063 {
4064 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4065 }
4066 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4067 {
4068 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4069 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070 }
4071 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4072 {
4073 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4074 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4075 }
4076 i = api_put (appl, m);
4077 if (i != 0)
4078 {
4079 if (m->header.command == _DATA_B3_R)
4080
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07004081 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
4083 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4084 break;
4085 }
4086
4087 if (plci->li_notify_update)
4088 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004089 plci->li_notify_update = false;
4090 mixer_notify_update (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 }
4092
4093 }
4094 send_data(plci);
4095 send_req(plci);
4096}
4097
4098
Hannes Eder4ee59d52008-12-16 01:17:33 -08004099static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4100 byte nl_rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101{
4102 dword Id;
4103 dword rId;
4104 word Number;
4105 word Info=0;
4106 word i;
4107 word ncci;
4108 DIVA_CAPI_ADAPTER * a;
4109 APPL * appl;
4110 PLCI * rplci;
4111 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4112 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4113
4114 if (!plci) {
4115 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4116 return;
4117 }
4118 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4119 if(plci->req_in!=plci->req_out)
4120 {
4121 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4122 {
4123 dbug(1,dprintf("req_1return"));
4124 return;
4125 }
4126 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4127 }
4128 plci->req_in = plci->req_in_start = plci->req_out = 0;
4129 dbug(1,dprintf("control_rc"));
4130
4131 appl = plci->appl;
4132 a = plci->adapter;
4133 ncci = a->ch_ncci[ch];
4134 if(appl)
4135 {
4136 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4137 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4138 Number = plci->number;
4139 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));
4140 dbug(1,dprintf("channels=0x%x",plci->channels));
4141 if (plci_remove_check(plci))
4142 return;
4143 if(req==REMOVE && rc==ASSIGN_OK)
4144 {
4145 sig_req(plci,HANGUP,0);
4146 sig_req(plci,REMOVE,0);
4147 send_req(plci);
4148 }
4149 if(plci->command)
4150 {
4151 switch(plci->command)
4152 {
4153 case C_HOLD_REQ:
4154 dbug(1,dprintf("HoldRC=0x%x",rc));
4155 SSparms[1] = (byte)S_HOLD;
4156 if(rc!=OK)
4157 {
4158 plci->SuppState = IDLE;
4159 Info = 0x2001;
4160 }
4161 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4162 break;
4163
4164 case C_RETRIEVE_REQ:
4165 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4166 SSparms[1] = (byte)S_RETRIEVE;
4167 if(rc!=OK)
4168 {
4169 plci->SuppState = CALL_HELD;
4170 Info = 0x2001;
4171 }
4172 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4173 break;
4174
4175 case _INFO_R:
4176 dbug(1,dprintf("InfoRC=0x%x",rc));
4177 if(rc!=OK) Info=_WRONG_STATE;
4178 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4179 break;
4180
4181 case _CONNECT_R:
4182 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4183 if (plci->State == INC_DIS_PENDING)
4184 break;
4185 if(plci->Sig.Id!=0xff)
4186 {
4187 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4188 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4189 {
4190 dbug(1,dprintf("No more IDs/Call_Req failed"));
4191 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4192 plci_remove(plci);
4193 plci->State = IDLE;
4194 break;
4195 }
4196 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4197 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4198 }
4199 else /* D-ch activation */
4200 {
4201 if (rc != ASSIGN_OK)
4202 {
4203 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4204 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4205 plci_remove(plci);
4206 plci->State = IDLE;
4207 break;
4208 }
4209 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4210 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4211 plci->State = INC_ACT_PENDING;
4212 }
4213 break;
4214
4215 case _CONNECT_I|RESPONSE:
4216 if (plci->State != INC_DIS_PENDING)
4217 plci->State = INC_CON_ACCEPT;
4218 break;
4219
4220 case _DISCONNECT_R:
4221 if (plci->State == INC_DIS_PENDING)
4222 break;
4223 if(plci->Sig.Id!=0xff)
4224 {
4225 plci->State = OUTG_DIS_PENDING;
4226 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4227 }
4228 break;
4229
4230 case SUSPEND_REQ:
4231 break;
4232
4233 case RESUME_REQ:
4234 break;
4235
4236 case _CONNECT_B3_R:
4237 if(rc!=OK)
4238 {
4239 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4240 break;
4241 }
4242 ncci = get_ncci (plci, ch, 0);
4243 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4244 plci->channels++;
4245 if(req==N_RESET)
4246 {
4247 a->ncci_state[ncci] = INC_ACT_PENDING;
4248 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4249 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4250 }
4251 else
4252 {
4253 a->ncci_state[ncci] = OUTG_CON_PENDING;
4254 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4255 }
4256 break;
4257
4258 case _CONNECT_B3_I|RESPONSE:
4259 break;
4260
4261 case _RESET_B3_R:
4262/* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4263 break;
4264
4265 case _DISCONNECT_B3_R:
4266 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4267 break;
4268
4269 case _MANUFACTURER_R:
4270 break;
4271
4272 case PERM_LIST_REQ:
4273 if(rc!=OK)
4274 {
4275 Info = _WRONG_IDENTIFIER;
4276 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4277 plci_remove(plci);
4278 }
4279 else
4280 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4281 break;
4282
4283 default:
4284 break;
4285 }
4286 plci->command = 0;
4287 }
4288 else if (plci->internal_command)
4289 {
4290 switch(plci->internal_command)
4291 {
4292 case BLOCK_PLCI:
4293 return;
4294
4295 case GET_MWI_STATE:
4296 if(rc==OK) /* command supported, wait for indication */
4297 {
4298 return;
4299 }
4300 plci_remove(plci);
4301 break;
4302
4303 /* Get Supported Services */
4304 case GETSERV_REQ_PEND:
4305 if(rc==OK) /* command supported, wait for indication */
4306 {
4307 break;
4308 }
4309 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4310 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4311 plci_remove(plci);
4312 break;
4313
4314 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4315 case INTERR_NUMBERS_REQ_PEND:
4316 case CF_START_PEND: /* Call Forwarding Start pending */
4317 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4318 case CCBS_REQUEST_REQ_PEND:
4319 case CCBS_DEACTIVATE_REQ_PEND:
4320 case CCBS_INTERROGATE_REQ_PEND:
4321 switch(plci->internal_command)
4322 {
4323 case INTERR_DIVERSION_REQ_PEND:
4324 SSparms[1] = S_INTERROGATE_DIVERSION;
4325 break;
4326 case INTERR_NUMBERS_REQ_PEND:
4327 SSparms[1] = S_INTERROGATE_NUMBERS;
4328 break;
4329 case CF_START_PEND:
4330 SSparms[1] = S_CALL_FORWARDING_START;
4331 break;
4332 case CF_STOP_PEND:
4333 SSparms[1] = S_CALL_FORWARDING_STOP;
4334 break;
4335 case CCBS_REQUEST_REQ_PEND:
4336 SSparms[1] = S_CCBS_REQUEST;
4337 break;
4338 case CCBS_DEACTIVATE_REQ_PEND:
4339 SSparms[1] = S_CCBS_DEACTIVATE;
4340 break;
4341 case CCBS_INTERROGATE_REQ_PEND:
4342 SSparms[1] = S_CCBS_INTERROGATE;
4343 break;
4344 }
4345 if(global_req==ASSIGN)
4346 {
4347 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4348 return;
4349 }
4350 if(!plci->appl) break;
4351 if(rc==ISDN_GUARD_REJ)
4352 {
4353 Info = _CAPI_GUARD_ERROR;
4354 }
4355 else if(rc!=OK)
4356 {
4357 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4358 }
4359 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4360 plci->number,"wws",Info,(word)3,SSparms);
4361 if(Info) plci_remove(plci);
4362 break;
4363
4364 /* 3pty conference pending */
4365 case PTY_REQ_PEND:
4366 if(!plci->relatedPTYPLCI) break;
4367 rplci = plci->relatedPTYPLCI;
4368 SSparms[1] = plci->ptyState;
4369 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4370 if(rplci->tel) rId|=EXT_CONTROLLER;
4371 if(rc!=OK)
4372 {
4373 Info = 0x300E; /* not supported */
4374 plci->relatedPTYPLCI = NULL;
4375 plci->ptyState = 0;
4376 }
4377 sendf(rplci->appl,
4378 _FACILITY_R|CONFIRM,
4379 rId,
4380 plci->number,
4381 "wws",Info,(word)3,SSparms);
4382 break;
4383
4384 /* Explicit Call Transfer pending */
4385 case ECT_REQ_PEND:
4386 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4387 if(!plci->relatedPTYPLCI) break;
4388 rplci = plci->relatedPTYPLCI;
4389 SSparms[1] = S_ECT;
4390 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4391 if(rplci->tel) rId|=EXT_CONTROLLER;
4392 if(rc!=OK)
4393 {
4394 Info = 0x300E; /* not supported */
4395 plci->relatedPTYPLCI = NULL;
4396 plci->ptyState = 0;
4397 }
4398 sendf(rplci->appl,
4399 _FACILITY_R|CONFIRM,
4400 rId,
4401 plci->number,
4402 "wws",Info,(word)3,SSparms);
4403 break;
4404
4405 case _MANUFACTURER_R:
4406 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4407 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4408 {
4409 dbug(1,dprintf("No more IDs"));
4410 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4411 plci_remove(plci); /* after codec init, internal codec commands pending */
4412 }
4413 break;
4414
4415 case _CONNECT_R:
4416 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4417 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4418 {
4419 dbug(1,dprintf("No more IDs"));
4420 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4421 plci_remove(plci); /* after codec init, internal codec commands pending */
4422 }
4423 break;
4424
4425 case PERM_COD_HOOK: /* finished with Hook_Ind */
4426 return;
4427
4428 case PERM_COD_CALL:
4429 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4430 plci->internal_command = PERM_COD_CONN_PEND;
4431 return;
4432
4433 case PERM_COD_ASSIGN:
4434 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4435 if(rc!=ASSIGN_OK) break;
4436 sig_req(plci,CALL_REQ,0);
4437 send_req(plci);
4438 plci->internal_command = PERM_COD_CALL;
4439 return;
4440
4441 /* Null Call Reference Request pending */
4442 case C_NCR_FAC_REQ:
4443 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4444 if(global_req==ASSIGN)
4445 {
4446 if(rc==ASSIGN_OK)
4447 {
4448 return;
4449 }
4450 else
4451 {
4452 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004453 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 plci_remove(plci);
4455 }
4456 }
4457 else if(req==NCR_FACILITY)
4458 {
4459 if(rc==OK)
4460 {
4461 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4462 }
4463 else
4464 {
4465 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004466 appl->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 }
4468 plci_remove(plci);
4469 }
4470 break;
4471
4472 case HOOK_ON_REQ:
4473 if(plci->channels)
4474 {
4475 if(a->ncci_state[ncci]==CONNECTED)
4476 {
4477 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4478 cleanup_ncci_data (plci, ncci);
4479 nl_req_ncci(plci,N_DISC,(byte)ncci);
4480 }
4481 break;
4482 }
4483 break;
4484
4485 case HOOK_OFF_REQ:
4486 if (plci->State == INC_DIS_PENDING)
4487 break;
4488 sig_req(plci,CALL_REQ,0);
4489 send_req(plci);
4490 plci->State=OUTG_CON_PENDING;
4491 break;
4492
4493
4494 case MWI_ACTIVATE_REQ_PEND:
4495 case MWI_DEACTIVATE_REQ_PEND:
4496 if(global_req == ASSIGN && rc==ASSIGN_OK)
4497 {
4498 dbug(1,dprintf("MWI_REQ assigned"));
4499 return;
4500 }
4501 else if(rc!=OK)
4502 {
4503 if(rc==WRONG_IE)
4504 {
4505 Info = 0x2007; /* Illegal message parameter coding */
4506 dbug(1,dprintf("MWI_REQ invalid parameter"));
4507 }
4508 else
4509 {
4510 Info = 0x300B; /* not supported */
4511 dbug(1,dprintf("MWI_REQ not supported"));
4512 }
4513 /* 0x3010: Request not allowed in this state */
4514 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4515
4516 }
4517 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4518 {
4519 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4520 }
4521 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4522
4523 if(plci->cr_enquiry)
4524 {
4525 sendf(plci->appl,
4526 _FACILITY_R|CONFIRM,
4527 Id&0xf,
4528 plci->number,
4529 "wws",Info,(word)3,SSparms);
4530 if(rc!=OK) plci_remove(plci);
4531 }
4532 else
4533 {
4534 sendf(plci->appl,
4535 _FACILITY_R|CONFIRM,
4536 Id,
4537 plci->number,
4538 "wws",Info,(word)3,SSparms);
4539 }
4540 break;
4541
4542 case CONF_BEGIN_REQ_PEND:
4543 case CONF_ADD_REQ_PEND:
4544 case CONF_SPLIT_REQ_PEND:
4545 case CONF_DROP_REQ_PEND:
4546 case CONF_ISOLATE_REQ_PEND:
4547 case CONF_REATTACH_REQ_PEND:
4548 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4549 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4550 rplci = plci;
4551 rId = Id;
4552 switch(plci->internal_command)
4553 {
4554 case CONF_BEGIN_REQ_PEND:
4555 SSparms[1] = S_CONF_BEGIN;
4556 break;
4557 case CONF_ADD_REQ_PEND:
4558 SSparms[1] = S_CONF_ADD;
4559 rplci = plci->relatedPTYPLCI;
4560 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4561 break;
4562 case CONF_SPLIT_REQ_PEND:
4563 SSparms[1] = S_CONF_SPLIT;
4564 break;
4565 case CONF_DROP_REQ_PEND:
4566 SSparms[1] = S_CONF_DROP;
4567 break;
4568 case CONF_ISOLATE_REQ_PEND:
4569 SSparms[1] = S_CONF_ISOLATE;
4570 break;
4571 case CONF_REATTACH_REQ_PEND:
4572 SSparms[1] = S_CONF_REATTACH;
4573 break;
4574 }
4575
4576 if(rc!=OK)
4577 {
4578 Info = 0x300E; /* not supported */
4579 plci->relatedPTYPLCI = NULL;
4580 plci->ptyState = 0;
4581 }
4582 sendf(rplci->appl,
4583 _FACILITY_R|CONFIRM,
4584 rId,
4585 plci->number,
4586 "wws",Info,(word)3,SSparms);
4587 break;
4588
4589 case VSWITCH_REQ_PEND:
4590 if(rc!=OK)
4591 {
4592 if(plci->relatedPTYPLCI)
4593 {
4594 plci->relatedPTYPLCI->vswitchstate=0;
4595 plci->relatedPTYPLCI->vsprot=0;
4596 plci->relatedPTYPLCI->vsprotdialect=0;
4597 }
4598 plci->vswitchstate=0;
4599 plci->vsprot=0;
4600 plci->vsprotdialect=0;
4601 }
4602 else
4603 {
4604 if(plci->relatedPTYPLCI &&
4605 plci->vswitchstate==1 &&
4606 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4607 plci->vswitchstate=3;
4608 }
4609 break;
4610
4611 /* Call Deflection Request pending (SSCT) */
4612 case CD_REQ_PEND:
4613 SSparms[1] = S_CALL_DEFLECTION;
4614 if(rc!=OK)
4615 {
4616 Info = 0x300E; /* not supported */
4617 plci->appl->CDEnable = 0;
4618 }
4619 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4620 plci->number,"wws",Info,(word)3,SSparms);
4621 break;
4622
4623 case RTP_CONNECT_B3_REQ_COMMAND_2:
4624 if (rc == OK)
4625 {
4626 ncci = get_ncci (plci, ch, 0);
4627 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4628 plci->channels++;
4629 a->ncci_state[ncci] = OUTG_CON_PENDING;
4630 }
4631
4632 default:
4633 if (plci->internal_command_queue[0])
4634 {
4635 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4636 if (plci->internal_command)
4637 return;
4638 }
4639 break;
4640 }
4641 next_internal_command (Id, plci);
4642 }
4643 }
4644 else /* appl==0 */
4645 {
4646 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4647 if(plci->tel) Id|=EXT_CONTROLLER;
4648
4649 switch(plci->internal_command)
4650 {
4651 case BLOCK_PLCI:
4652 return;
4653
4654 case START_L1_SIG_ASSIGN_PEND:
4655 case REM_L1_SIG_ASSIGN_PEND:
4656 if(global_req == ASSIGN)
4657 {
4658 break;
4659 }
4660 else
4661 {
4662 dbug(1,dprintf("***L1 Req rem PLCI"));
4663 plci->internal_command = 0;
4664 sig_req(plci,REMOVE,0);
4665 send_req(plci);
4666 }
4667 break;
4668
4669 /* Call Deflection Request pending, just no appl ptr assigned */
4670 case CD_REQ_PEND:
4671 SSparms[1] = S_CALL_DEFLECTION;
4672 if(rc!=OK)
4673 {
4674 Info = 0x300E; /* not supported */
4675 }
4676 for(i=0; i<max_appl; i++)
4677 {
4678 if(application[i].CDEnable)
4679 {
4680 if(!application[i].Id) application[i].CDEnable = 0;
4681 else
4682 {
4683 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4684 plci->number,"wws",Info,(word)3,SSparms);
4685 if(Info) application[i].CDEnable = 0;
4686 }
4687 }
4688 }
4689 plci->internal_command = 0;
4690 break;
4691
4692 case PERM_COD_HOOK: /* finished with Hook_Ind */
4693 return;
4694
4695 case PERM_COD_CALL:
4696 plci->internal_command = PERM_COD_CONN_PEND;
4697 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4698 return;
4699
4700 case PERM_COD_ASSIGN:
4701 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4702 plci->internal_command = 0;
4703 if(rc!=ASSIGN_OK) break;
4704 plci->internal_command = PERM_COD_CALL;
4705 sig_req(plci,CALL_REQ,0);
4706 send_req(plci);
4707 return;
4708
4709 case LISTEN_SIG_ASSIGN_PEND:
4710 if(rc == ASSIGN_OK)
4711 {
4712 plci->internal_command = 0;
4713 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4714 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4715 sig_req(plci,INDICATE_REQ,0);
4716 send_req(plci);
4717 }
4718 else
4719 {
4720 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4721 a->listen_active--;
4722 plci_remove(plci);
4723 plci->State = IDLE;
4724 }
4725 break;
4726
4727 case USELAW_REQ:
4728 if(global_req == ASSIGN)
4729 {
4730 if (rc==ASSIGN_OK)
4731 {
4732 sig_req(plci,LAW_REQ,0);
4733 send_req(plci);
4734 dbug(1,dprintf("Auto-Law assigned"));
4735 }
4736 else
4737 {
4738 dbug(1,dprintf("Auto-Law assign failed"));
4739 a->automatic_law = 3;
4740 plci->internal_command = 0;
4741 a->automatic_lawPLCI = NULL;
4742 }
4743 break;
4744 }
4745 else if(req == LAW_REQ && rc==OK)
4746 {
4747 dbug(1,dprintf("Auto-Law initiated"));
4748 a->automatic_law = 2;
4749 plci->internal_command = 0;
4750 }
4751 else
4752 {
4753 dbug(1,dprintf("Auto-Law not supported"));
4754 a->automatic_law = 3;
4755 plci->internal_command = 0;
4756 sig_req(plci,REMOVE,0);
4757 send_req(plci);
4758 a->automatic_lawPLCI = NULL;
4759 }
4760 break;
4761 }
4762 plci_remove_check(plci);
4763 }
4764}
4765
Hannes Eder4ee59d52008-12-16 01:17:33 -08004766static void data_rc(PLCI *plci, byte ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767{
4768 dword Id;
4769 DIVA_CAPI_ADAPTER * a;
4770 NCCI *ncci_ptr;
4771 DATA_B3_DESC *data;
4772 word ncci;
4773
4774 if (plci->appl)
4775 {
4776 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4777 a = plci->adapter;
4778 ncci = a->ch_ncci[ch];
4779 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4780 {
4781 ncci_ptr = &(a->ncci[ncci]);
4782 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4783 if (ncci_ptr->data_pending)
4784 {
4785 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4786 if (!(data->Flags &4) && a->ncci_state[ncci])
4787 {
4788 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4789 if(plci->tel) Id|=EXT_CONTROLLER;
4790 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4791 "ww",data->Handle,0);
4792 }
4793 (ncci_ptr->data_out)++;
4794 if (ncci_ptr->data_out == MAX_DATA_B3)
4795 ncci_ptr->data_out = 0;
4796 (ncci_ptr->data_pending)--;
4797 }
4798 }
4799 }
4800}
4801
Hannes Eder4ee59d52008-12-16 01:17:33 -08004802static void data_ack(PLCI *plci, byte ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803{
4804 dword Id;
4805 DIVA_CAPI_ADAPTER * a;
4806 NCCI *ncci_ptr;
4807 word ncci;
4808
4809 a = plci->adapter;
4810 ncci = a->ch_ncci[ch];
4811 ncci_ptr = &(a->ncci[ncci]);
4812 if (ncci_ptr->data_ack_pending)
4813 {
4814 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4815 {
4816 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4817 if(plci->tel) Id|=EXT_CONTROLLER;
4818 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4819 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4820 }
4821 (ncci_ptr->data_ack_out)++;
4822 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4823 ncci_ptr->data_ack_out = 0;
4824 (ncci_ptr->data_ack_pending)--;
4825 }
4826}
4827
Hannes Eder4ee59d52008-12-16 01:17:33 -08004828static void sig_ind(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829{
4830 dword x_Id;
4831 dword Id;
4832 dword rId;
4833 word Number = 0;
4834 word i;
4835 word cip;
4836 dword cip_mask;
4837 byte *ie;
4838 DIVA_CAPI_ADAPTER * a;
4839 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4840#define MAXPARMSIDS 31
4841 byte * parms[MAXPARMSIDS];
4842 byte * add_i[4];
4843 byte * multi_fac_parms[MAX_MULTI_IE];
4844 byte * multi_pi_parms [MAX_MULTI_IE];
4845 byte * multi_ssext_parms [MAX_MULTI_IE];
4846 byte * multi_CiPN_parms [MAX_MULTI_IE];
4847
4848 byte * multi_vswitch_parms [MAX_MULTI_IE];
4849
4850 byte ai_len;
4851 byte *esc_chi = "";
4852 byte *esc_law = "";
4853 byte *pty_cai = "";
4854 byte *esc_cr = "";
4855 byte *esc_profile = "";
4856
4857 byte facility[256];
4858 PLCI * tplci = NULL;
4859 byte chi[] = "\x02\x18\x01";
4860 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4861 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4862 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4863 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4864 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4865 /* (see Info_Mask Bit 4, first IE. then the message type) */
4866 word parms_id[] =
4867 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4868 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4869 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4870 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4871 /* 14 FTY repl by ESC_CHI */
4872 /* 18 PI repl by ESC_LAW */
4873 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4874 word multi_fac_id[] = {1, FTY};
4875 word multi_pi_id[] = {1, PI};
4876 word multi_CiPN_id[] = {1, OAD};
4877 word multi_ssext_id[] = {1, ESC_SSEXT};
4878
4879 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4880
4881 byte * cau;
4882 word ncci;
4883 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4884 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4885 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4886 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004887 byte force_mt_info = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888 byte dir;
4889 dword d;
4890 word w;
4891
4892 a = plci->adapter;
4893 Id = ((word)plci->Id<<8)|a->Id;
4894 PUT_WORD(&SS_Ind[4],0x0000);
4895
4896 if (plci->sig_remove_id)
4897 {
4898 plci->Sig.RNR = 2; /* discard */
4899 dbug(1,dprintf("SIG discard while remove pending"));
4900 return;
4901 }
4902 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4903 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4904 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4905 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4906 {
4907 plci->Sig.RNR = 1;
4908 return;
4909 }
4910 if(plci->Sig.Ind==HANGUP && plci->channels)
4911 {
4912 plci->Sig.RNR = 1;
4913 plci->hangup_flow_ctrl_timer++;
4914 /* recover the network layer after timeout */
4915 if(plci->hangup_flow_ctrl_timer==100)
4916 {
4917 dbug(1,dprintf("Exceptional disc"));
4918 plci->Sig.RNR = 0;
4919 plci->hangup_flow_ctrl_timer = 0;
4920 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4921 {
4922 if (a->ncci_plci[ncci] == plci->Id)
4923 {
4924 cleanup_ncci_data (plci, ncci);
4925 if(plci->channels)plci->channels--;
4926 if (plci->appl)
4927 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4928 }
4929 }
4930 if (plci->appl)
4931 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4932 plci_remove(plci);
4933 plci->State=IDLE;
4934 }
4935 return;
4936 }
4937
4938 /* do first parse the info with no OAD in, because OAD will be converted */
4939 /* first the multiple facility IE, then mult. progress ind. */
4940 /* then the parameters for the info_ind + conn_ind */
4941 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4942 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4943 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4944
4945 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4946
4947 IndParse(plci,parms_id,parms,0);
4948 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4949 esc_chi = parms[14];
4950 esc_law = parms[18];
4951 pty_cai = parms[24];
4952 esc_cr = parms[25];
4953 esc_profile = parms[27];
4954 if(esc_cr[0] && plci)
4955 {
4956 if(plci->cr_enquiry && plci->appl)
4957 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08004958 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 /* d = MANU_ID */
4960 /* w = m_command */
4961 /* b = total length */
4962 /* b = indication type */
4963 /* b = length of all IEs */
4964 /* b = IE1 */
4965 /* S = IE1 length + cont. */
4966 /* b = IE2 */
Paulius Zaleckasefad798b2008-02-03 15:42:53 +02004967 /* S = IE2 length + cont. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968 sendf(plci->appl,
4969 _MANUFACTURER_I,
4970 Id,
4971 0,
4972 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4973 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);
4974 }
4975 }
4976 /* create the additional info structure */
4977 add_i[1] = parms[15]; /* KEY of additional info */
4978 add_i[2] = parms[11]; /* UUI of additional info */
4979 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4980
4981 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4982 /* indication returns by the card if requested by the function */
4983 /* AutomaticLaw() after driver init */
4984 if (a->automatic_law<4)
4985 {
4986 if(esc_law[0]){
4987 if(esc_law[2]){
4988 dbug(0,dprintf("u-Law selected"));
4989 a->u_law = 1;
4990 }
4991 else {
4992 dbug(0,dprintf("a-Law selected"));
4993 a->u_law = 0;
4994 }
4995 a->automatic_law = 4;
4996 if(plci==a->automatic_lawPLCI) {
4997 plci->internal_command = 0;
4998 sig_req(plci,REMOVE,0);
4999 send_req(plci);
5000 a->automatic_lawPLCI = NULL;
5001 }
5002 }
5003 if (esc_profile[0])
5004 {
5005 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5006 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5007 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5008 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5009
5010 a->profile.Global_Options &= 0x000000ffL;
5011 a->profile.B1_Protocols &= 0x000003ffL;
5012 a->profile.B2_Protocols &= 0x00001fdfL;
5013 a->profile.B3_Protocols &= 0x000000b7L;
5014
5015 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5016 GL_BCHANNEL_OPERATION_SUPPORTED;
5017 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5018 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5019 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5020 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5021 a->man_profile.private_options = 0;
5022
5023 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5024 {
5025 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5026 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5027 }
5028
5029
5030 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5031 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5032 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5033 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5034
5035
5036 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5037 a->man_profile.private_options |= 1L << PRIVATE_T38;
5038
5039
5040 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5041 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5042
5043
5044 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5045 a->man_profile.private_options |= 1L << PRIVATE_V18;
5046
5047
5048 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5049 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5050
5051
5052 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5053 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5054
5055
5056 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5057 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5058
5059
5060 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5061 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5062
5063
5064 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5065 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5066
5067 }
5068 else
5069 {
5070 a->profile.Global_Options &= 0x0000007fL;
5071 a->profile.B1_Protocols &= 0x000003dfL;
5072 a->profile.B2_Protocols &= 0x00001adfL;
5073 a->profile.B3_Protocols &= 0x000000b7L;
5074 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5075 }
5076 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5077 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5078 {
5079 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5080 }
5081 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5082 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5083 UnMapController (a->Id), a->profile.Global_Options,
5084 a->profile.B1_Protocols, a->profile.B2_Protocols,
5085 a->profile.B3_Protocols, a->manufacturer_features));
5086 }
5087 /* codec plci for the handset/hook state support is just an internal id */
5088 if(plci!=a->AdvCodecPLCI)
5089 {
5090 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5091 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5092 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5093 SendInfo(plci,Id, parms, force_mt_info);
5094
5095 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5096
5097 }
5098
5099 /* switch the codec to the b-channel */
5100 if(esc_chi[0] && plci && !plci->SuppState){
5101 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5102 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5103 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5104 if(plci->tel==ADV_VOICE && plci->appl) {
5105 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5106 }
5107 }
5108
5109 if(plci->appl) Number = plci->appl->Number++;
5110
5111 switch(plci->Sig.Ind) {
5112 /* Response to Get_Supported_Services request */
5113 case S_SUPPORTED:
5114 dbug(1,dprintf("S_Supported"));
5115 if(!plci->appl) break;
5116 if(pty_cai[0]==4)
5117 {
5118 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5119 }
5120 else
5121 {
5122 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5123 }
5124 PUT_WORD (&CF_Ind[1], 0);
5125 PUT_WORD (&CF_Ind[4], 0);
5126 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5127 plci_remove(plci);
5128 break;
5129
5130 /* Supplementary Service rejected */
5131 case S_SERVICE_REJ:
5132 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5133 if(!pty_cai[0]) break;
5134 switch (pty_cai[5])
5135 {
5136 case ECT_EXECUTE:
5137 case THREE_PTY_END:
5138 case THREE_PTY_BEGIN:
5139 if(!plci->relatedPTYPLCI) break;
5140 tplci = plci->relatedPTYPLCI;
5141 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5142 if(tplci->tel) rId|=EXT_CONTROLLER;
5143 if(pty_cai[5]==ECT_EXECUTE)
5144 {
5145 PUT_WORD(&SS_Ind[1],S_ECT);
5146
5147 plci->vswitchstate=0;
5148 plci->relatedPTYPLCI->vswitchstate=0;
5149
5150 }
5151 else
5152 {
5153 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5154 }
5155 if(pty_cai[2]!=0xff)
5156 {
5157 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5158 }
5159 else
5160 {
5161 PUT_WORD(&SS_Ind[4],0x300E);
5162 }
5163 plci->relatedPTYPLCI = NULL;
5164 plci->ptyState = 0;
5165 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5166 break;
5167
5168 case CALL_DEFLECTION:
5169 if(pty_cai[2]!=0xff)
5170 {
5171 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5172 }
5173 else
5174 {
5175 PUT_WORD(&SS_Ind[4],0x300E);
5176 }
5177 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5178 for(i=0; i<max_appl; i++)
5179 {
5180 if(application[i].CDEnable)
5181 {
5182 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005183 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184 }
5185 }
5186 break;
5187
5188 case DEACTIVATION_DIVERSION:
5189 case ACTIVATION_DIVERSION:
5190 case DIVERSION_INTERROGATE_CFU:
5191 case DIVERSION_INTERROGATE_CFB:
5192 case DIVERSION_INTERROGATE_CFNR:
5193 case DIVERSION_INTERROGATE_NUM:
5194 case CCBS_REQUEST:
5195 case CCBS_DEACTIVATE:
5196 case CCBS_INTERROGATE:
5197 if(!plci->appl) break;
5198 if(pty_cai[2]!=0xff)
5199 {
5200 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5201 }
5202 else
5203 {
5204 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5205 }
5206 switch (pty_cai[5])
5207 {
5208 case DEACTIVATION_DIVERSION:
5209 dbug(1,dprintf("Deact_Div"));
5210 Interr_Err_Ind[0]=0x9;
5211 Interr_Err_Ind[3]=0x6;
5212 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5213 break;
5214 case ACTIVATION_DIVERSION:
5215 dbug(1,dprintf("Act_Div"));
5216 Interr_Err_Ind[0]=0x9;
5217 Interr_Err_Ind[3]=0x6;
5218 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5219 break;
5220 case DIVERSION_INTERROGATE_CFU:
5221 case DIVERSION_INTERROGATE_CFB:
5222 case DIVERSION_INTERROGATE_CFNR:
5223 dbug(1,dprintf("Interr_Div"));
5224 Interr_Err_Ind[0]=0xa;
5225 Interr_Err_Ind[3]=0x7;
5226 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5227 break;
5228 case DIVERSION_INTERROGATE_NUM:
5229 dbug(1,dprintf("Interr_Num"));
5230 Interr_Err_Ind[0]=0xa;
5231 Interr_Err_Ind[3]=0x7;
5232 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5233 break;
5234 case CCBS_REQUEST:
5235 dbug(1,dprintf("CCBS Request"));
5236 Interr_Err_Ind[0]=0xd;
5237 Interr_Err_Ind[3]=0xa;
5238 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5239 break;
5240 case CCBS_DEACTIVATE:
5241 dbug(1,dprintf("CCBS Deactivate"));
5242 Interr_Err_Ind[0]=0x9;
5243 Interr_Err_Ind[3]=0x6;
5244 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5245 break;
5246 case CCBS_INTERROGATE:
5247 dbug(1,dprintf("CCBS Interrogate"));
5248 Interr_Err_Ind[0]=0xb;
5249 Interr_Err_Ind[3]=0x8;
5250 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5251 break;
5252 }
5253 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5254 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5255 plci_remove(plci);
5256 break;
5257 case ACTIVATION_MWI:
5258 case DEACTIVATION_MWI:
5259 if(pty_cai[5]==ACTIVATION_MWI)
5260 {
5261 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5262 }
5263 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5264
5265 if(pty_cai[2]!=0xff)
5266 {
5267 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5268 }
5269 else
5270 {
5271 PUT_WORD(&SS_Ind[4],0x300E);
5272 }
5273
5274 if(plci->cr_enquiry)
5275 {
5276 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5277 plci_remove(plci);
5278 }
5279 else
5280 {
5281 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5282 }
5283 break;
5284 case CONF_ADD: /* ERROR */
5285 case CONF_BEGIN:
5286 case CONF_DROP:
5287 case CONF_ISOLATE:
5288 case CONF_REATTACH:
5289 CONF_Ind[0]=9;
5290 CONF_Ind[3]=6;
5291 switch(pty_cai[5])
5292 {
5293 case CONF_BEGIN:
5294 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5295 plci->ptyState = 0;
5296 break;
5297 case CONF_DROP:
5298 CONF_Ind[0]=5;
5299 CONF_Ind[3]=2;
5300 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5301 plci->ptyState = CONNECTED;
5302 break;
5303 case CONF_ISOLATE:
5304 CONF_Ind[0]=5;
5305 CONF_Ind[3]=2;
5306 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5307 plci->ptyState = CONNECTED;
5308 break;
5309 case CONF_REATTACH:
5310 CONF_Ind[0]=5;
5311 CONF_Ind[3]=2;
5312 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5313 plci->ptyState = CONNECTED;
5314 break;
5315 case CONF_ADD:
5316 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5317 plci->relatedPTYPLCI = NULL;
5318 tplci=plci->relatedPTYPLCI;
5319 if(tplci) tplci->ptyState = CONNECTED;
5320 plci->ptyState = CONNECTED;
5321 break;
5322 }
5323
5324 if(pty_cai[2]!=0xff)
5325 {
5326 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5327 }
5328 else
5329 {
5330 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5331 within the required time */
5332 }
5333
5334 PUT_DWORD(&CONF_Ind[6],0x0);
5335 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5336 break;
5337 }
5338 break;
5339
5340 /* Supplementary Service indicates success */
5341 case S_SERVICE:
5342 dbug(1,dprintf("Service_Ind"));
5343 PUT_WORD (&CF_Ind[4], 0);
5344 switch (pty_cai[5])
5345 {
5346 case THREE_PTY_END:
5347 case THREE_PTY_BEGIN:
5348 case ECT_EXECUTE:
5349 if(!plci->relatedPTYPLCI) break;
5350 tplci = plci->relatedPTYPLCI;
5351 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5352 if(tplci->tel) rId|=EXT_CONTROLLER;
5353 if(pty_cai[5]==ECT_EXECUTE)
5354 {
5355 PUT_WORD(&SS_Ind[1],S_ECT);
5356
5357 if(plci->vswitchstate!=3)
5358 {
5359
5360 plci->ptyState = IDLE;
5361 plci->relatedPTYPLCI = NULL;
5362 plci->ptyState = 0;
5363
5364 }
5365
5366 dbug(1,dprintf("ECT OK"));
5367 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368
5369
5370
5371 }
5372 else
5373 {
5374 switch (plci->ptyState)
5375 {
5376 case S_3PTY_BEGIN:
5377 plci->ptyState = CONNECTED;
5378 dbug(1,dprintf("3PTY ON"));
5379 break;
5380
5381 case S_3PTY_END:
5382 plci->ptyState = IDLE;
5383 plci->relatedPTYPLCI = NULL;
5384 plci->ptyState = 0;
5385 dbug(1,dprintf("3PTY OFF"));
5386 break;
5387 }
5388 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5389 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5390 }
5391 break;
5392
5393 case CALL_DEFLECTION:
5394 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5395 for(i=0; i<max_appl; i++)
5396 {
5397 if(application[i].CDEnable)
5398 {
5399 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005400 application[i].CDEnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 }
5402 }
5403 break;
5404
5405 case DEACTIVATION_DIVERSION:
5406 case ACTIVATION_DIVERSION:
5407 if(!plci->appl) break;
5408 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5409 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5410 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5411 plci_remove(plci);
5412 break;
5413
5414 case DIVERSION_INTERROGATE_CFU:
5415 case DIVERSION_INTERROGATE_CFB:
5416 case DIVERSION_INTERROGATE_CFNR:
5417 case DIVERSION_INTERROGATE_NUM:
5418 case CCBS_REQUEST:
5419 case CCBS_DEACTIVATE:
5420 case CCBS_INTERROGATE:
5421 if(!plci->appl) break;
5422 switch (pty_cai[5])
5423 {
5424 case DIVERSION_INTERROGATE_CFU:
5425 case DIVERSION_INTERROGATE_CFB:
5426 case DIVERSION_INTERROGATE_CFNR:
5427 dbug(1,dprintf("Interr_Div"));
5428 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5429 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430 break;
5431 case DIVERSION_INTERROGATE_NUM:
5432 dbug(1,dprintf("Interr_Num"));
5433 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5434 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5435 break;
5436 case CCBS_REQUEST:
5437 dbug(1,dprintf("CCBS Request"));
5438 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5439 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5440 break;
5441 case CCBS_DEACTIVATE:
5442 dbug(1,dprintf("CCBS Deactivate"));
5443 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5444 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5445 break;
5446 case CCBS_INTERROGATE:
5447 dbug(1,dprintf("CCBS Interrogate"));
5448 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5449 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5450 break;
5451 }
5452 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5453 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5454 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5455 plci_remove(plci);
5456 break;
5457
5458 case ACTIVATION_MWI:
5459 case DEACTIVATION_MWI:
5460 if(pty_cai[5]==ACTIVATION_MWI)
5461 {
5462 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5463 }
5464 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5465 if(plci->cr_enquiry)
5466 {
5467 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5468 plci_remove(plci);
5469 }
5470 else
5471 {
5472 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5473 }
5474 break;
5475 case MWI_INDICATION:
5476 if(pty_cai[0]>=0x12)
5477 {
5478 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5479 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5480 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5481 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5482 {
5483 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5484 {
5485 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5486 plci_remove(plci);
5487 return;
5488 }
5489 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5490 pty_cai[0]=0;
5491 }
5492 else
5493 {
5494 for(i=0; i<max_appl; i++)
5495 {
5496 if(a->Notification_Mask[i]&SMASK_MWI)
5497 {
5498 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5499 pty_cai[0]=0;
5500 }
5501 }
5502 }
5503
5504 if(!pty_cai[0])
5505 { /* acknowledge */
5506 facility[2]= 0; /* returncode */
5507 }
5508 else facility[2]= 0xff;
5509 }
5510 else
5511 {
5512 /* reject */
5513 facility[2]= 0xff; /* returncode */
5514 }
5515 facility[0]= 2;
5516 facility[1]= MWI_RESPONSE; /* Function */
5517 add_p(plci,CAI,facility);
5518 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5519 sig_req(plci,S_SERVICE,0);
5520 send_req(plci);
5521 plci->command = 0;
5522 next_internal_command (Id, plci);
5523 break;
5524 case CONF_ADD: /* OK */
5525 case CONF_BEGIN:
5526 case CONF_DROP:
5527 case CONF_ISOLATE:
5528 case CONF_REATTACH:
5529 case CONF_PARTYDISC:
5530 CONF_Ind[0]=9;
5531 CONF_Ind[3]=6;
5532 switch(pty_cai[5])
5533 {
5534 case CONF_BEGIN:
5535 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5536 if(pty_cai[0]==6)
5537 {
5538 d=pty_cai[6];
5539 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5540 }
5541 else
5542 {
5543 PUT_DWORD(&CONF_Ind[6],0x0);
5544 }
5545 break;
5546 case CONF_ISOLATE:
5547 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5548 CONF_Ind[0]=5;
5549 CONF_Ind[3]=2;
5550 break;
5551 case CONF_REATTACH:
5552 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5553 CONF_Ind[0]=5;
5554 CONF_Ind[3]=2;
5555 break;
5556 case CONF_DROP:
5557 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5558 CONF_Ind[0]=5;
5559 CONF_Ind[3]=2;
5560 break;
5561 case CONF_ADD:
5562 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5563 d=pty_cai[6];
5564 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5565 tplci=plci->relatedPTYPLCI;
5566 if(tplci) tplci->ptyState = CONNECTED;
5567 break;
5568 case CONF_PARTYDISC:
5569 CONF_Ind[0]=7;
5570 CONF_Ind[3]=4;
5571 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5572 d=pty_cai[6];
5573 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5574 break;
5575 }
5576 plci->ptyState = CONNECTED;
5577 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5578 break;
5579 case CCBS_INFO_RETAIN:
5580 case CCBS_ERASECALLLINKAGEID:
5581 case CCBS_STOP_ALERTING:
5582 CONF_Ind[0]=5;
5583 CONF_Ind[3]=2;
5584 switch(pty_cai[5])
5585 {
5586 case CCBS_INFO_RETAIN:
5587 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5588 break;
5589 case CCBS_STOP_ALERTING:
5590 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5591 break;
5592 case CCBS_ERASECALLLINKAGEID:
5593 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5594 CONF_Ind[0]=7;
5595 CONF_Ind[3]=4;
5596 CONF_Ind[6]=0;
5597 CONF_Ind[7]=0;
5598 break;
5599 }
5600 w=pty_cai[6];
5601 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5602
5603 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5604 {
5605 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5606 }
5607 else
5608 {
5609 for(i=0; i<max_appl; i++)
5610 if(a->Notification_Mask[i]&SMASK_CCBS)
5611 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5612 }
5613 break;
5614 }
5615 break;
5616 case CALL_HOLD_REJ:
5617 cau = parms[7];
5618 if(cau)
5619 {
5620 i = _L3_CAUSE | cau[2];
5621 if(cau[2]==0) i = 0x3603;
5622 }
5623 else
5624 {
5625 i = 0x3603;
5626 }
5627 PUT_WORD(&SS_Ind[1],S_HOLD);
5628 PUT_WORD(&SS_Ind[4],i);
5629 if(plci->SuppState == HOLD_REQUEST)
5630 {
5631 plci->SuppState = IDLE;
5632 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5633 }
5634 break;
5635
5636 case CALL_HOLD_ACK:
5637 if(plci->SuppState == HOLD_REQUEST)
5638 {
5639 plci->SuppState = CALL_HELD;
5640 CodecIdCheck(a, plci);
5641 start_internal_command (Id, plci, hold_save_command);
5642 }
5643 break;
5644
5645 case CALL_RETRIEVE_REJ:
5646 cau = parms[7];
5647 if(cau)
5648 {
5649 i = _L3_CAUSE | cau[2];
5650 if(cau[2]==0) i = 0x3603;
5651 }
5652 else
5653 {
5654 i = 0x3603;
5655 }
5656 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5657 PUT_WORD(&SS_Ind[4],i);
5658 if(plci->SuppState == RETRIEVE_REQUEST)
5659 {
5660 plci->SuppState = CALL_HELD;
5661 CodecIdCheck(a, plci);
5662 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663 }
5664 break;
5665
5666 case CALL_RETRIEVE_ACK:
5667 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5668 if(plci->SuppState == RETRIEVE_REQUEST)
5669 {
5670 plci->SuppState = IDLE;
5671 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5672 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5673 if(plci->tel)
5674 {
5675 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5676 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5677 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5678 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5679 {
5680 dbug(1,dprintf("Get B-ch"));
5681 start_internal_command (Id, plci, retrieve_restore_command);
5682 }
5683 else
5684 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5685 }
5686 else
5687 start_internal_command (Id, plci, retrieve_restore_command);
5688 }
5689 break;
5690
5691 case INDICATE_IND:
5692 if(plci->State != LISTENING) {
5693 sig_req(plci,HANGUP,0);
5694 send_req(plci);
5695 break;
5696 }
5697 cip = find_cip(a,parms[4],parms[6]);
5698 cip_mask = 1L<<cip;
5699 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5700 clear_c_ind_mask (plci);
5701 if (!remove_started && !a->adapter_disabled)
5702 {
5703 set_c_ind_mask_bit (plci, MAX_APPL);
5704 group_optimization(a, plci);
5705 for(i=0; i<max_appl; i++) {
5706 if(application[i].Id
5707 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5708 && CPN_filter_ok(parms[0],a,i)
5709 && test_group_ind_mask_bit (plci, i) ) {
5710 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5711 set_c_ind_mask_bit (plci, i);
5712 dump_c_ind_mask (plci);
5713 plci->State = INC_CON_PENDING;
5714 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5715 CALL_DIR_IN | CALL_DIR_ANSWER;
5716 if(esc_chi[0]) {
5717 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5718 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5719 }
5720 /* if a listen on the ext controller is done, check if hook states */
5721 /* are supported or if just a on board codec must be activated */
5722 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5723 if(a->profile.Global_Options & HANDSET)
5724 plci->tel = ADV_VOICE;
5725 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5726 plci->tel = CODEC;
5727 if(plci->tel) Id|=EXT_CONTROLLER;
5728 a->codec_listen[i] = plci;
5729 }
5730
5731 sendf(&application[i],_CONNECT_I,Id,0,
5732 "wSSSSSSSbSSSSS", cip, /* CIP */
5733 parms[0], /* CalledPartyNumber */
5734 multi_CiPN_parms[0], /* CallingPartyNumber */
5735 parms[2], /* CalledPartySubad */
5736 parms[3], /* CallingPartySubad */
5737 parms[4], /* BearerCapability */
5738 parms[5], /* LowLC */
5739 parms[6], /* HighLC */
5740 ai_len, /* nested struct add_i */
5741 add_i[0], /* B channel info */
5742 add_i[1], /* keypad facility */
5743 add_i[2], /* user user data */
5744 add_i[3], /* nested facility */
5745 multi_CiPN_parms[1] /* second CiPN(SCR) */
5746 );
5747 SendSSExtInd(&application[i],
5748 plci,
5749 Id,
5750 multi_ssext_parms);
5751 SendSetupInfo(&application[i],
5752 plci,
5753 Id,
5754 parms,
Richard Knutsson986c4bb2007-02-12 00:53:24 -08005755 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756 }
5757 }
5758 clear_c_ind_mask_bit (plci, MAX_APPL);
5759 dump_c_ind_mask (plci);
5760 }
5761 if(c_ind_mask_empty (plci)) {
5762 sig_req(plci,HANGUP,0);
5763 send_req(plci);
5764 plci->State = IDLE;
5765 }
5766 plci->notifiedcall = 0;
5767 a->listen_active--;
5768 listen_check(a);
5769 break;
5770
5771 case CALL_PEND_NOTIFY:
5772 plci->notifiedcall = 1;
5773 listen_check(a);
5774 break;
5775
5776 case CALL_IND:
5777 case CALL_CON:
5778 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5779 {
5780 if(plci->internal_command==PERM_COD_CONN_PEND)
5781 {
5782 if(plci->State==ADVANCED_VOICE_NOSIG)
5783 {
5784 dbug(1,dprintf("***Codec OK"));
5785 if(a->AdvSignalPLCI)
5786 {
5787 tplci = a->AdvSignalPLCI;
5788 if(tplci->spoofed_msg)
5789 {
5790 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5791 tplci->command = 0;
5792 tplci->internal_command = 0;
5793 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5794 switch (tplci->spoofed_msg)
5795 {
5796 case CALL_RES:
5797 tplci->command = _CONNECT_I|RESPONSE;
5798 api_load_msg (&tplci->saved_msg, saved_parms);
5799 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5800 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5801 {
5802 /* early B3 connect (CIP mask bit 9) no release after a disc */
5803 add_p(tplci,LLI,"\x01\x01");
5804 }
5805 add_s(tplci, CONN_NR, &saved_parms[2]);
5806 add_s(tplci, LLC, &saved_parms[4]);
5807 add_ai(tplci, &saved_parms[5]);
5808 tplci->State = INC_CON_ACCEPT;
5809 sig_req(tplci, CALL_RES,0);
5810 send_req(tplci);
5811 break;
5812
5813 case AWAITING_SELECT_B:
5814 dbug(1,dprintf("Select_B continue"));
5815 start_internal_command (x_Id, tplci, select_b_command);
5816 break;
5817
5818 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5819 if(!tplci->Sig.Id)
5820 {
5821 dbug(1,dprintf("No SigID!"));
5822 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5823 plci_remove(tplci);
5824 break;
5825 }
5826 tplci->command = _MANUFACTURER_R;
5827 api_load_msg (&tplci->saved_msg, saved_parms);
5828 dir = saved_parms[2].info[0];
5829 if(dir==1) {
5830 sig_req(tplci,CALL_REQ,0);
5831 }
5832 else if(!dir){
5833 sig_req(tplci,LISTEN_REQ,0);
5834 }
5835 send_req(tplci);
5836 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5837 break;
5838
5839 case (CALL_REQ|AWAITING_MANUF_CON):
5840 sig_req(tplci,CALL_REQ,0);
5841 send_req(tplci);
5842 break;
5843
5844 case CALL_REQ:
5845 if(!tplci->Sig.Id)
5846 {
5847 dbug(1,dprintf("No SigID!"));
5848 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5849 plci_remove(tplci);
5850 break;
5851 }
5852 tplci->command = _CONNECT_R;
5853 api_load_msg (&tplci->saved_msg, saved_parms);
5854 add_s(tplci,CPN,&saved_parms[1]);
5855 add_s(tplci,DSA,&saved_parms[3]);
5856 add_ai(tplci,&saved_parms[9]);
5857 sig_req(tplci,CALL_REQ,0);
5858 send_req(tplci);
5859 break;
5860
5861 case CALL_RETRIEVE:
5862 tplci->command = C_RETRIEVE_REQ;
5863 sig_req(tplci,CALL_RETRIEVE,0);
5864 send_req(tplci);
5865 break;
5866 }
5867 tplci->spoofed_msg = 0;
5868 if (tplci->internal_command == 0)
5869 next_internal_command (x_Id, tplci);
5870 }
5871 }
5872 next_internal_command (Id, plci);
5873 break;
5874 }
5875 dbug(1,dprintf("***Codec Hook Init Req"));
5876 plci->internal_command = PERM_COD_HOOK;
5877 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5878 sig_req(plci,TEL_CTRL,0);
5879 send_req(plci);
5880 }
5881 }
5882 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5883 && plci->State!=INC_ACT_PENDING)
5884 {
5885 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5886 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5887 {
5888 chi[2] = plci->b_channel;
5889 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5890 }
5891 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5892 plci->State = INC_ACT_PENDING;
5893 }
5894 break;
5895
5896 case TEL_CTRL:
5897 Number = 0;
5898 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5899 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5900 switch (ie[1]&0x91) {
5901 case 0x80: /* hook off */
5902 case 0x81:
5903 if(plci->internal_command==PERM_COD_HOOK)
5904 {
5905 dbug(1,dprintf("init:hook_off"));
5906 plci->hook_state = ie[1];
5907 next_internal_command (Id, plci);
5908 break;
5909 }
5910 else /* ignore doubled hook indications */
5911 {
5912 if( ((plci->hook_state)&0xf0)==0x80)
5913 {
5914 dbug(1,dprintf("ignore hook"));
5915 break;
5916 }
5917 plci->hook_state = ie[1]&0x91;
5918 }
5919 /* check for incoming call pending */
5920 /* and signal '+'.Appl must decide */
5921 /* with connect_res if call must */
5922 /* accepted or not */
5923 for(i=0, tplci=NULL;i<max_appl;i++){
5924 if(a->codec_listen[i]
5925 && (a->codec_listen[i]->State==INC_CON_PENDING
5926 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5927 tplci = a->codec_listen[i];
5928 tplci->appl = &application[i];
5929 }
5930 }
5931 /* no incoming call, do outgoing call */
5932 /* and signal '+' if outg. setup */
5933 if(!a->AdvSignalPLCI && !tplci){
5934 if((i=get_plci(a))) {
5935 a->AdvSignalPLCI = &a->plci[i-1];
5936 tplci = a->AdvSignalPLCI;
5937 tplci->tel = ADV_VOICE;
5938 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5939 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5940 /* early B3 connect (CIP mask bit 9) no release after a disc */
5941 add_p(tplci,LLI,"\x01\x01");
5942 }
5943 add_p(tplci, CAI, voice_cai);
5944 add_p(tplci, OAD, a->TelOAD);
5945 add_p(tplci, OSA, a->TelOSA);
5946 add_p(tplci,SHIFT|6,NULL);
5947 add_p(tplci,SIN,"\x02\x01\x00");
5948 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5949 sig_req(tplci,ASSIGN,DSIG_ID);
5950 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5951 a->AdvSignalPLCI->command = 0;
5952 tplci->appl = a->AdvSignalAppl;
5953 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5954 send_req(tplci);
5955 }
5956
5957 }
5958
5959 if(!tplci) break;
5960 Id = ((word)tplci->Id<<8)|a->Id;
5961 Id|=EXT_CONTROLLER;
5962 sendf(tplci->appl,
5963 _FACILITY_I,
5964 Id,
5965 0,
5966 "ws", (word)0, "\x01+");
5967 break;
5968
5969 case 0x90: /* hook on */
5970 case 0x91:
5971 if(plci->internal_command==PERM_COD_HOOK)
5972 {
5973 dbug(1,dprintf("init:hook_on"));
5974 plci->hook_state = ie[1]&0x91;
5975 next_internal_command (Id, plci);
5976 break;
5977 }
5978 else /* ignore doubled hook indications */
5979 {
5980 if( ((plci->hook_state)&0xf0)==0x90) break;
5981 plci->hook_state = ie[1]&0x91;
5982 }
5983 /* hangup the adv. voice call and signal '-' to the appl */
5984 if(a->AdvSignalPLCI) {
5985 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5986 if(plci->tel) Id|=EXT_CONTROLLER;
5987 sendf(a->AdvSignalAppl,
5988 _FACILITY_I,
5989 Id,
5990 0,
5991 "ws", (word)0, "\x01-");
5992 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5993 a->AdvSignalPLCI->command = 0;
5994 sig_req(a->AdvSignalPLCI,HANGUP,0);
5995 send_req(a->AdvSignalPLCI);
5996 }
5997 break;
5998 }
5999 }
6000 break;
6001
6002 case RESUME:
6003 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6004 PUT_WORD(&resume_cau[4],GOOD);
6005 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6006 break;
6007
6008 case SUSPEND:
6009 clear_c_ind_mask (plci);
6010
6011 if (plci->NL.Id && !plci->nl_remove_id) {
6012 mixer_remove (plci);
6013 nl_req_ncci(plci,REMOVE,0);
6014 }
6015 if (!plci->sig_remove_id) {
6016 plci->internal_command = 0;
6017 sig_req(plci,REMOVE,0);
6018 }
6019 send_req(plci);
6020 if(!plci->channels) {
6021 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6022 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6023 }
6024 break;
6025
6026 case SUSPEND_REJ:
6027 break;
6028
6029 case HANGUP:
6030 plci->hangup_flow_ctrl_timer=0;
6031 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6032 cau = parms[7];
6033 if(cau) {
6034 i = _L3_CAUSE | cau[2];
6035 if(cau[2]==0) i = 0;
6036 else if(cau[2]==8) i = _L1_ERROR;
6037 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6038 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6039 }
6040 else {
6041 i = _L3_ERROR;
6042 }
6043
6044 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6045 {
6046 for(i=0; i<max_appl; i++)
6047 {
6048 if(test_c_ind_mask_bit (plci, i))
6049 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6050 }
6051 }
6052 else
6053 {
6054 clear_c_ind_mask (plci);
6055 }
6056 if(!plci->appl)
6057 {
6058 if (plci->State == LISTENING)
6059 {
6060 plci->notifiedcall=0;
6061 a->listen_active--;
6062 }
6063 plci->State = INC_DIS_PENDING;
6064 if(c_ind_mask_empty (plci))
6065 {
6066 plci->State = IDLE;
6067 if (plci->NL.Id && !plci->nl_remove_id)
6068 {
6069 mixer_remove (plci);
6070 nl_req_ncci(plci,REMOVE,0);
6071 }
6072 if (!plci->sig_remove_id)
6073 {
6074 plci->internal_command = 0;
6075 sig_req(plci,REMOVE,0);
6076 }
6077 send_req(plci);
6078 }
6079 }
6080 else
6081 {
6082 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6083 /* result in a second HANGUP! Don't generate another */
6084 /* DISCONNECT */
6085 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6086 {
6087 if(plci->State==RESUMING)
6088 {
6089 PUT_WORD(&resume_cau[4],i);
6090 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6091 }
6092 plci->State = INC_DIS_PENDING;
6093 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6094 }
6095 }
6096 break;
6097
6098 case SSEXT_IND:
6099 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6100 break;
6101
6102 case VSWITCH_REQ:
6103 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6104 break;
6105 case VSWITCH_IND:
6106 if(plci->relatedPTYPLCI &&
6107 plci->vswitchstate==3 &&
6108 plci->relatedPTYPLCI->vswitchstate==3 &&
6109 parms[MAXPARMSIDS-1][0])
6110 {
6111 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6112 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6113 send_req(plci->relatedPTYPLCI);
6114 }
6115 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6116 break;
6117
6118 }
6119}
6120
6121
6122static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6123{
6124 word i;
6125 byte * ie;
6126 word Info_Number;
6127 byte * Info_Element;
6128 word Info_Mask = 0;
6129
6130 dbug(1,dprintf("SetupInfo"));
6131
6132 for(i=0; i<MAXPARMSIDS; i++) {
6133 ie = parms[i];
6134 Info_Number = 0;
6135 Info_Element = ie;
6136 if(ie[0]) {
6137 switch(i) {
6138 case 0:
6139 dbug(1,dprintf("CPN "));
6140 Info_Number = 0x0070;
6141 Info_Mask = 0x80;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006142 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143 break;
6144 case 8: /* display */
6145 dbug(1,dprintf("display(%d)",i));
6146 Info_Number = 0x0028;
6147 Info_Mask = 0x04;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006148 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149 break;
6150 case 16: /* Channel Id */
6151 dbug(1,dprintf("CHI"));
6152 Info_Number = 0x0018;
6153 Info_Mask = 0x100;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006154 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006155 mixer_set_bchannel_id (plci, Info_Element);
6156 break;
6157 case 19: /* Redirected Number */
6158 dbug(1,dprintf("RDN"));
6159 Info_Number = 0x0074;
6160 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006161 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162 break;
6163 case 20: /* Redirected Number extended */
6164 dbug(1,dprintf("RDX"));
6165 Info_Number = 0x0073;
6166 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006167 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006168 break;
6169 case 22: /* Redirecing Number */
6170 dbug(1,dprintf("RIN"));
6171 Info_Number = 0x0076;
6172 Info_Mask = 0x400;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006173 Info_Sent_Flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174 break;
6175 default:
6176 Info_Number = 0;
6177 break;
6178 }
6179 }
6180
6181 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6182 Info_Number = 0x8000 |5;
6183 Info_Mask = 0x10;
6184 Info_Element = "";
6185 }
6186
6187 if(Info_Sent_Flag && Info_Number){
6188 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6189 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6190 }
6191 }
6192 }
6193}
6194
6195
Hannes Eder4ee59d52008-12-16 01:17:33 -08006196static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197{
6198 word i;
6199 word j;
6200 word k;
6201 byte * ie;
6202 word Info_Number;
6203 byte * Info_Element;
6204 word Info_Mask = 0;
6205 static byte charges[5] = {4,0,0,0,0};
6206 static byte cause[] = {0x02,0x80,0x00};
6207 APPL *appl;
6208
6209 dbug(1,dprintf("InfoParse "));
6210
6211 if(
6212 !plci->appl
6213 && !plci->State
6214 && plci->Sig.Ind!=NCR_FACILITY
6215 )
6216 {
6217 dbug(1,dprintf("NoParse "));
6218 return;
6219 }
6220 cause[2] = 0;
6221 for(i=0; i<MAXPARMSIDS; i++) {
6222 ie = parms[i];
6223 Info_Number = 0;
6224 Info_Element = ie;
6225 if(ie[0]) {
6226 switch(i) {
6227 case 0:
6228 dbug(1,dprintf("CPN "));
6229 Info_Number = 0x0070;
6230 Info_Mask = 0x80;
6231 break;
6232 case 7: /* ESC_CAU */
6233 dbug(1,dprintf("cau(0x%x)",ie[2]));
6234 Info_Number = 0x0008;
6235 Info_Mask = 0x00;
6236 cause[2] = ie[2];
6237 Info_Element = NULL;
6238 break;
6239 case 8: /* display */
6240 dbug(1,dprintf("display(%d)",i));
6241 Info_Number = 0x0028;
6242 Info_Mask = 0x04;
6243 break;
6244 case 9: /* Date display */
6245 dbug(1,dprintf("date(%d)",i));
6246 Info_Number = 0x0029;
6247 Info_Mask = 0x02;
6248 break;
6249 case 10: /* charges */
6250 for(j=0;j<4;j++) charges[1+j] = 0;
6251 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6252 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6253 Info_Number = 0x4000;
6254 Info_Mask = 0x40;
6255 Info_Element = charges;
6256 break;
6257 case 11: /* user user info */
6258 dbug(1,dprintf("uui"));
6259 Info_Number = 0x007E;
6260 Info_Mask = 0x08;
6261 break;
6262 case 12: /* congestion receiver ready */
6263 dbug(1,dprintf("clRDY"));
6264 Info_Number = 0x00B0;
6265 Info_Mask = 0x08;
6266 Info_Element = "";
6267 break;
6268 case 13: /* congestion receiver not ready */
6269 dbug(1,dprintf("clNRDY"));
6270 Info_Number = 0x00BF;
6271 Info_Mask = 0x08;
6272 Info_Element = "";
6273 break;
6274 case 15: /* Keypad Facility */
6275 dbug(1,dprintf("KEY"));
6276 Info_Number = 0x002C;
6277 Info_Mask = 0x20;
6278 break;
6279 case 16: /* Channel Id */
6280 dbug(1,dprintf("CHI"));
6281 Info_Number = 0x0018;
6282 Info_Mask = 0x100;
6283 mixer_set_bchannel_id (plci, Info_Element);
6284 break;
6285 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6286 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6287 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6288 Info_Number = 0x0008;
6289 Info_Mask = 0x01;
6290 if(cause[2] != ie[2]) Info_Element = cause;
6291 break;
6292 case 19: /* Redirected Number */
6293 dbug(1,dprintf("RDN"));
6294 Info_Number = 0x0074;
6295 Info_Mask = 0x400;
6296 break;
6297 case 22: /* Redirecing Number */
6298 dbug(1,dprintf("RIN"));
6299 Info_Number = 0x0076;
6300 Info_Mask = 0x400;
6301 break;
6302 case 23: /* Notification Indicator */
6303 dbug(1,dprintf("NI"));
6304 Info_Number = (word)NI;
6305 Info_Mask = 0x210;
6306 break;
6307 case 26: /* Call State */
6308 dbug(1,dprintf("CST"));
6309 Info_Number = (word)CST;
6310 Info_Mask = 0x01; /* do with cause i.e. for now */
6311 break;
6312 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6313 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6314 Info_Number = 0x8000 |ie[3];
6315 if(iesent) Info_Mask = 0xffff;
6316 else Info_Mask = 0x10;
6317 Info_Element = "";
6318 break;
6319 default:
6320 Info_Number = 0;
6321 Info_Mask = 0;
6322 Info_Element = "";
6323 break;
6324 }
6325 }
6326
6327 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6328 {
6329 for(j=0; j<max_appl; j++)
6330 {
6331 appl = &application[j];
6332 if(Info_Number
6333 && appl->Id
6334 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6335 {
6336 dbug(1,dprintf("NCR_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006337 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6339 }
6340 }
6341 }
6342 else if(!plci->appl)
6343 { /* overlap receiving broadcast */
6344 if(Info_Number==CPN
6345 || Info_Number==KEY
6346 || Info_Number==NI
6347 || Info_Number==DSP
6348 || Info_Number==UUI )
6349 {
6350 for(j=0; j<max_appl; j++)
6351 {
6352 if(test_c_ind_mask_bit (plci, j))
6353 {
6354 dbug(1,dprintf("Ovl_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006355 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006356 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6357 }
6358 }
6359 }
6360 } /* all other signalling states */
6361 else if(Info_Number
6362 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6363 {
6364 dbug(1,dprintf("Std_Ind"));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006365 iesent=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006366 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6367 }
6368 }
6369}
6370
6371
Hannes Eder4ee59d52008-12-16 01:17:33 -08006372static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6373 dword info_mask, byte setupParse)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006374{
6375 word i;
6376 word j;
6377 byte * ie;
6378 word Info_Number;
6379 byte * Info_Element;
6380 APPL *appl;
6381 word Info_Mask = 0;
6382 byte iesent=0;
6383
6384 if(
6385 !plci->appl
6386 && !plci->State
6387 && plci->Sig.Ind!=NCR_FACILITY
6388 && !setupParse
6389 )
6390 {
6391 dbug(1,dprintf("NoM-IEParse "));
6392 return 0;
6393 }
6394 dbug(1,dprintf("M-IEParse "));
6395
6396 for(i=0; i<MAX_MULTI_IE; i++)
6397 {
6398 ie = parms[i];
6399 Info_Number = 0;
6400 Info_Element = ie;
6401 if(ie[0])
6402 {
6403 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6404 Info_Number = (word)ie_type;
6405 Info_Mask = (word)info_mask;
6406 }
6407
6408 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6409 {
6410 for(j=0; j<max_appl; j++)
6411 {
6412 appl = &application[j];
6413 if(Info_Number
6414 && appl->Id
6415 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6416 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006417 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006418 dbug(1,dprintf("Mlt_NCR_Ind"));
6419 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6420 }
6421 }
6422 }
6423 else if(!plci->appl && Info_Number)
6424 { /* overlap receiving broadcast */
6425 for(j=0; j<max_appl; j++)
6426 {
6427 if(test_c_ind_mask_bit (plci, j))
6428 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006429 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006430 dbug(1,dprintf("Mlt_Ovl_Ind"));
6431 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6432 }
6433 }
6434 } /* all other signalling states */
6435 else if(Info_Number
6436 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6437 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006438 iesent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439 dbug(1,dprintf("Mlt_Std_Ind"));
6440 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6441 }
6442 }
6443 return iesent;
6444}
6445
6446static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6447{
6448 word i;
6449 /* Format of multi_ssext_parms[i][]:
6450 0 byte length
6451 1 byte SSEXTIE
6452 2 byte SSEXT_REQ/SSEXT_IND
6453 3 byte length
6454 4 word SSExtCommand
6455 6... Params
6456 */
6457 if(
6458 plci
6459 && plci->State
6460 && plci->Sig.Ind!=NCR_FACILITY
6461 )
6462 for(i=0;i<MAX_MULTI_IE;i++)
6463 {
6464 if(parms[i][0]<6) continue;
6465 if(parms[i][2]==SSEXT_REQ) continue;
6466
6467 if(appl)
6468 {
6469 parms[i][0]=0; /* kill it */
6470 sendf(appl,_MANUFACTURER_I,
6471 Id,
6472 0,
6473 "dwS",
6474 _DI_MANU_ID,
6475 _DI_SSEXT_CTRL,
6476 &parms[i][3]);
6477 }
6478 else if(plci->appl)
6479 {
6480 parms[i][0]=0; /* kill it */
6481 sendf(plci->appl,_MANUFACTURER_I,
6482 Id,
6483 0,
6484 "dwS",
6485 _DI_MANU_ID,
6486 _DI_SSEXT_CTRL,
6487 &parms[i][3]);
6488 }
6489 }
6490};
6491
Hannes Eder4ee59d52008-12-16 01:17:33 -08006492static void nl_ind(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006493{
6494 byte ch;
6495 word ncci;
6496 dword Id;
6497 DIVA_CAPI_ADAPTER * a;
6498 word NCCIcode;
6499 APPL * APPLptr;
6500 word count;
6501 word Num;
6502 word i, ncpi_state;
6503 byte len, ncci_state;
6504 word msg;
6505 word info = 0;
6506 word fax_feature_bits;
6507 byte fax_send_edata_ack;
6508 static byte v120_header_buffer[2 + 3];
6509 static word fax_info[] = {
6510 0, /* T30_SUCCESS */
6511 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6516 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6517 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6518 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6519 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6520 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6521 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6522 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6523 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6524 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6525 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6529 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6531 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6537 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6538 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6539 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6540 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6541 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6542 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6543 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6544 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6545 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6546 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6547 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6548 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6549 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6550 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6551 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6552 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6553 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6554 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6555 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6556 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6557 };
6558
6559 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6560
6561
6562 static word rtp_info[] = {
6563 GOOD, /* RTP_SUCCESS */
6564 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6565 };
6566
6567 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6568 {
6569 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6570 0x00000000, 0x00000000, 0x00000000, 0x00000000
6571 };
6572
6573 ch = plci->NL.IndCh;
6574 a = plci->adapter;
6575 ncci = a->ch_ncci[ch];
6576 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6577 if(plci->tel) Id|=EXT_CONTROLLER;
6578 APPLptr = plci->appl;
6579 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",
6580 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6581
6582 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6583
6584 if (plci->nl_remove_id)
6585 {
6586 plci->NL.RNR = 2; /* discard */
6587 dbug(1,dprintf("NL discard while remove pending"));
6588 return;
6589 }
6590 if((plci->NL.Ind &0x0f)==N_CONNECT)
6591 {
6592 if(plci->State==INC_DIS_PENDING
6593 || plci->State==OUTG_DIS_PENDING
6594 || plci->State==IDLE)
6595 {
6596 plci->NL.RNR = 2; /* discard */
6597 dbug(1,dprintf("discard n_connect"));
6598 return;
6599 }
6600 if(plci->State < INC_ACT_PENDING)
6601 {
6602 plci->NL.RNR = 1; /* flow control */
6603 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6604 return;
6605 }
6606 }
6607
6608 if(!APPLptr) /* no application or invalid data */
6609 { /* while reloading the DSP */
6610 dbug(1,dprintf("discard1"));
6611 plci->NL.RNR = 2;
6612 return;
6613 }
6614
6615 if (((plci->NL.Ind &0x0f) == N_UDATA)
6616 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6617 || (plci->B2_prot == 7)
6618 || (plci->B3_prot == 7)) )
6619 {
6620 plci->ncpi_buffer[0] = 0;
6621
6622 ncpi_state = plci->ncpi_state;
6623 if (plci->NL.complete == 1)
6624 {
6625 byte * data = &plci->NL.RBuffer->P[0];
6626
6627 if ((plci->NL.RBuffer->length >= 12)
6628 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6629 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6630 {
6631 word conn_opt, ncpi_opt = 0x00;
6632/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6633
6634 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6635 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6636 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6637 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6638
6639 data++; /* indication code */
6640 data += 2; /* timestamp */
6641 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6642 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6643 data++; /* connected norm */
6644 conn_opt = GET_WORD(data);
6645 data += 2; /* connected options */
6646
6647 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6648
6649 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6650 {
6651 ncpi_opt |= MDM_NCPI_ECM_V42;
6652 }
6653 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6654 {
6655 ncpi_opt |= MDM_NCPI_ECM_MNP;
6656 }
6657 else
6658 {
6659 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6660 }
6661 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6662 {
6663 ncpi_opt |= MDM_NCPI_COMPRESSED;
6664 }
6665 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6666 plci->ncpi_buffer[0] = 4;
6667
6668 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6669 }
6670 }
6671 if (plci->B3_prot == 7)
6672 {
6673 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6674 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6675 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6676 {
6677 a->ncci_state[ncci] = INC_ACT_PENDING;
6678 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6679 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6680 }
6681 }
6682
6683 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6684 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6685 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6686 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6687
6688 {
6689 plci->NL.RNR = 2;
6690 return;
6691 }
6692 }
6693
6694 if(plci->NL.complete == 2)
6695 {
6696 if (((plci->NL.Ind &0x0f) == N_UDATA)
6697 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6698 {
6699 switch(plci->RData[0].P[0])
6700 {
6701
6702 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6703 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6705 break;
6706 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6707 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6708 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6709 break;
6710 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6711 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6712 break;
6713 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6714 dtmf_confirmation (Id, plci);
6715 break;
6716
6717
6718 case UDATA_INDICATION_MIXER_TAP_DATA:
6719 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6720 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6721 if (i != 0)
6722 {
6723 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6724 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6725 }
6726 break;
6727
6728
6729 case UDATA_INDICATION_MIXER_COEFS_SET:
6730 mixer_indication_coefs_set (Id, plci);
6731 break;
6732 case UDATA_INDICATION_XCONNECT_FROM:
6733 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6734 break;
6735 case UDATA_INDICATION_XCONNECT_TO:
6736 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6737 break;
6738
6739
6740 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6741 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6742 break;
6743
6744
6745
6746 default:
6747 break;
6748 }
6749 }
6750 else
6751 {
6752 if ((plci->RData[0].PLength != 0)
6753 && ((plci->B2_prot == B2_V120_ASYNC)
6754 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6755 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6756 {
6757
6758 sendf(plci->appl,_DATA_B3_I,Id,0,
6759 "dwww",
6760 plci->RData[1].P,
6761 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6762 plci->RNum,
6763 plci->RFlags);
6764
6765 }
6766 else
6767 {
6768
6769 sendf(plci->appl,_DATA_B3_I,Id,0,
6770 "dwww",
6771 plci->RData[0].P,
6772 plci->RData[0].PLength,
6773 plci->RNum,
6774 plci->RFlags);
6775
6776 }
6777 }
6778 return;
6779 }
6780
6781 fax_feature_bits = 0;
6782 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6783 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6784 (plci->NL.Ind &0x0f)==N_DISC ||
6785 (plci->NL.Ind &0x0f)==N_EDATA ||
6786 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6787 {
6788 info = 0;
6789 plci->ncpi_buffer[0] = 0;
6790 switch (plci->B3_prot) {
6791 case 0: /*XPARENT*/
6792 case 1: /*T.90 NL*/
6793 break; /* no network control protocol info - jfr */
6794 case 2: /*ISO8202*/
6795 case 3: /*X25 DCE*/
6796 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6797 plci->ncpi_buffer[0] = (byte)(i+3);
6798 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6799 plci->ncpi_buffer[2] = 0;
6800 plci->ncpi_buffer[3] = 0;
6801 break;
6802 case 4: /*T.30 - FAX*/
6803 case 5: /*T.30 - FAX*/
6804 if(plci->NL.RLength>=sizeof(T30_INFO))
6805 {
6806 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6807 len = 9;
6808 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6809 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6810 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6811 if (plci->B3_prot == 5)
6812 {
6813 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6814 i |= 0x8000; /* This is not an ECM connection */
6815 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6816 i |= 0x4000; /* This is a connection with MMR compression */
6817 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6818 i |= 0x2000; /* This is a connection with MR compression */
6819 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6820 i |= 0x0004; /* More documents */
6821 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6822 i |= 0x0002; /* Fax-polling indication */
6823 }
6824 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6825 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6826 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6827 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6828 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6829 plci->ncpi_buffer[len] = 0;
6830 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6831 {
6832 plci->ncpi_buffer[len] = 20;
6833 for (i = 0; i < 20; i++)
6834 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6835 }
6836 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6837 {
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -08006838 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006839 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6840 else
6841 info = _FAX_PROTOCOL_ERROR;
6842 }
6843
6844 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6845 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6846 {
Jiri Slaby1ea70842009-11-04 08:28:12 -08006847 i = offsetof(T30_INFO, station_id) + 20 + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006848 while (i < plci->NL.RBuffer->length)
6849 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6850 }
6851
6852 plci->ncpi_buffer[0] = len;
6853 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6854 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6855
6856 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6857 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6858 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6859 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6860 || (((plci->NL.Ind &0x0f) == N_EDATA)
6861 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6862 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6863 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6864 {
6865 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6866 }
6867 if (((plci->NL.Ind &0x0f) == N_DISC)
6868 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6869 || (((plci->NL.Ind &0x0f) == N_EDATA)
6870 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6871 {
6872 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6873 }
6874 }
6875 break;
6876
6877 case B3_RTP:
6878 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6879 {
6880 if (plci->NL.RLength != 0)
6881 {
6882 info = rtp_info[plci->NL.RBuffer->P[0]];
6883 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6884 for (i = 1; i < plci->NL.RLength; i++)
6885 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6886 }
6887 }
6888 break;
6889
6890 }
6891 plci->NL.RNR = 2;
6892 }
6893 switch(plci->NL.Ind &0x0f) {
6894 case N_EDATA:
6895 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6896 {
6897 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6898 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6899 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6900
6901 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6902 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6903 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6904 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6905 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6906 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6907 {
6908 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6909 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6910 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6911 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6912 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006913 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914 }
6915
6916 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6917 {
6918 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6919 {
6920 case EDATA_T30_DIS:
6921 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6922 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6923 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6924 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6925 {
6926 a->ncci_state[ncci] = INC_ACT_PENDING;
6927 if (plci->B3_prot == 4)
6928 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6929 else
6930 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6931 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6932 }
6933 break;
6934
6935 case EDATA_T30_TRAIN_OK:
6936 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6937 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6938 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6939 {
6940 if (plci->B3_prot == 4)
6941 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6942 else
6943 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6944 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6945 }
6946 break;
6947
6948 case EDATA_T30_EOP_CAPI:
6949 if (a->ncci_state[ncci] == CONNECTED)
6950 {
6951 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6952 a->ncci_state[ncci] = INC_DIS_PENDING;
6953 plci->ncpi_state = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08006954 fax_send_edata_ack = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006955 }
6956 break;
6957 }
6958 }
6959 else
6960 {
6961 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6962 {
6963 case EDATA_T30_TRAIN_OK:
6964 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6965 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6966 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6967 {
6968 if (plci->B3_prot == 4)
6969 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6970 else
6971 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6972 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6973 }
6974 break;
6975 }
6976 }
6977 if (fax_send_edata_ack)
6978 {
6979 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6980 plci->fax_edata_ack_length = 1;
6981 start_internal_command (Id, plci, fax_edata_ack_command);
6982 }
6983 }
6984 else
6985 {
6986 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6987 }
6988 break;
6989 case N_CONNECT:
6990 if (!a->ch_ncci[ch])
6991 {
6992 ncci = get_ncci (plci, ch, 0);
6993 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6994 }
6995 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6996 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6997
6998 msg = _CONNECT_B3_I;
6999 if (a->ncci_state[ncci] == IDLE)
7000 plci->channels++;
7001 else if (plci->B3_prot == 1)
7002 msg = _CONNECT_B3_T90_ACTIVE_I;
7003
7004 a->ncci_state[ncci] = INC_CON_PENDING;
7005 if(plci->B3_prot == 4)
7006 sendf(plci->appl,msg,Id,0,"s","");
7007 else
7008 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7009 break;
7010 case N_CONNECT_ACK:
7011 dbug(1,dprintf("N_connect_Ack"));
7012 if (plci->internal_command_queue[0]
7013 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7014 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7015 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7016 {
7017 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7018 if (!plci->internal_command)
7019 next_internal_command (Id, plci);
7020 break;
7021 }
7022 msg = _CONNECT_B3_ACTIVE_I;
7023 if (plci->B3_prot == 1)
7024 {
7025 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7026 msg = _CONNECT_B3_T90_ACTIVE_I;
7027 a->ncci_state[ncci] = INC_ACT_PENDING;
7028 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7029 }
7030 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7031 {
7032 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7033 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7034 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7035 {
7036 a->ncci_state[ncci] = INC_ACT_PENDING;
7037 if (plci->B3_prot == 4)
7038 sendf(plci->appl,msg,Id,0,"s","");
7039 else
7040 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7041 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7042 }
7043 }
7044 else
7045 {
7046 a->ncci_state[ncci] = INC_ACT_PENDING;
7047 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7048 }
7049 if (plci->adjust_b_restore)
7050 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007051 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007052 start_internal_command (Id, plci, adjust_b_restore);
7053 }
7054 break;
7055 case N_DISC:
7056 case N_DISC_ACK:
7057 if (plci->internal_command_queue[0]
7058 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7059 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7060 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7061 {
7062 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7063 if (!plci->internal_command)
7064 next_internal_command (Id, plci);
7065 }
7066 ncci_state = a->ncci_state[ncci];
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007067 ncci_remove (plci, ncci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068
7069 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7070 /* channel, so we cannot store the state in ncci_state! The */
7071 /* information which channel we received a N_DISC is thus */
7072 /* stored in the inc_dis_ncci_table buffer. */
7073 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7074 plci->inc_dis_ncci_table[i] = (byte) ncci;
7075
7076 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7077 if (!plci->channels
7078 && (plci->B1_resource == 16)
7079 && (plci->State <= CONNECTED))
7080 {
7081 len = 9;
7082 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7083 PUT_WORD (&plci->ncpi_buffer[1], i);
7084 PUT_WORD (&plci->ncpi_buffer[3], 0);
7085 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7086 PUT_WORD (&plci->ncpi_buffer[5], i);
7087 PUT_WORD (&plci->ncpi_buffer[7], 0);
7088 plci->ncpi_buffer[len] = 0;
7089 plci->ncpi_buffer[0] = len;
7090 if(plci->B3_prot == 4)
7091 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7092 else
7093 {
7094
7095 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7096 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7097 {
7098 plci->ncpi_buffer[++len] = 0;
7099 plci->ncpi_buffer[++len] = 0;
7100 plci->ncpi_buffer[++len] = 0;
7101 plci->ncpi_buffer[0] = len;
7102 }
7103
7104 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7105 }
7106 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7107 plci->ncpi_state = 0;
7108 sig_req(plci,HANGUP,0);
7109 send_req(plci);
7110 plci->State = OUTG_DIS_PENDING;
7111 /* disc here */
7112 }
7113 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7114 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7115 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7116 {
7117 if (ncci_state == IDLE)
7118 {
7119 if (plci->channels)
7120 plci->channels--;
7121 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7122 if(plci->State == SUSPENDING){
7123 sendf(plci->appl,
7124 _FACILITY_I,
7125 Id & 0xffffL,
7126 0,
7127 "ws", (word)3, "\x03\x04\x00\x00");
7128 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7129 }
7130 plci_remove(plci);
7131 plci->State=IDLE;
7132 }
7133 }
7134 }
7135 else if (plci->channels)
7136 {
7137 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7138 plci->ncpi_state = 0;
7139 if ((ncci_state == OUTG_REJ_PENDING)
7140 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7141 {
7142 sig_req(plci,HANGUP,0);
7143 send_req(plci);
7144 plci->State = OUTG_DIS_PENDING;
7145 }
7146 }
7147 break;
7148 case N_RESET:
7149 a->ncci_state[ncci] = INC_RES_PENDING;
7150 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7151 break;
7152 case N_RESET_ACK:
7153 a->ncci_state[ncci] = CONNECTED;
7154 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7155 break;
7156
7157 case N_UDATA:
7158 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7159 {
Andrew Mortond3c8bdf2007-05-23 13:58:22 -07007160 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007161 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7162 plci->NL.R = plci->RData;
7163 plci->NL.RNum = 1;
7164 return;
7165 }
7166 case N_BDATA:
7167 case N_DATA:
7168 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7169 || (a->ncci_state[ncci] == IDLE)
7170 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7171 {
7172 plci->NL.RNR = 2;
7173 break;
7174 }
7175 if ((a->ncci_state[ncci] != CONNECTED)
7176 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7177 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7178 {
7179 dbug(1,dprintf("flow control"));
7180 plci->NL.RNR = 1; /* flow control */
7181 channel_x_off (plci, ch, 0);
7182 break;
7183 }
7184
7185 NCCIcode = ncci | (((word)a->Id) << 8);
7186
7187 /* count all buffers within the Application pool */
7188 /* belonging to the same NCCI. If this is below the */
7189 /* number of buffers available per NCCI we accept */
7190 /* this packet, otherwise we reject it */
7191 count = 0;
7192 Num = 0xffff;
7193 for(i=0; i<APPLptr->MaxBuffer; i++) {
7194 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7195 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7196 }
7197
7198 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7199 {
7200 dbug(3,dprintf("Flow-Control"));
7201 plci->NL.RNR = 1;
7202 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7203 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7204 {
7205 plci->NL.RNR = 2;
7206 dbug(3,dprintf("DiscardData"));
7207 } else {
7208 channel_x_off (plci, ch, 0);
7209 }
7210 break;
7211 }
7212 else
7213 {
7214 APPLptr->NCCIDataFlowCtrlTimer = 0;
7215 }
7216
7217 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7218 if(!plci->RData[0].P) {
7219 plci->NL.RNR = 1;
7220 channel_x_off (plci, ch, 0);
7221 break;
7222 }
7223
7224 APPLptr->DataNCCI[Num] = NCCIcode;
7225 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7226 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7227
7228 plci->RNum = Num;
7229 plci->RFlags = plci->NL.Ind>>4;
7230 plci->RData[0].PLength = APPLptr->MaxDataLength;
7231 plci->NL.R = plci->RData;
7232 if ((plci->NL.RLength != 0)
7233 && ((plci->B2_prot == B2_V120_ASYNC)
7234 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7235 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7236 {
7237 plci->RData[1].P = plci->RData[0].P;
7238 plci->RData[1].PLength = plci->RData[0].PLength;
Jiri Slaby1ea70842009-11-04 08:28:12 -08007239 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007240 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7241 plci->RData[0].PLength = 1;
7242 else
7243 plci->RData[0].PLength = 2;
7244 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7245 plci->RFlags |= 0x0010;
7246 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7247 plci->RFlags |= 0x8000;
7248 plci->NL.RNum = 2;
7249 }
7250 else
7251 {
7252 if((plci->NL.Ind &0x0f)==N_UDATA)
7253 plci->RFlags |= 0x0010;
7254
7255 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7256 plci->RFlags |= 0x0001;
7257
7258 plci->NL.RNum = 1;
7259 }
7260 break;
7261 case N_DATA_ACK:
7262 data_ack (plci, ch);
7263 break;
7264 default:
7265 plci->NL.RNR = 2;
7266 break;
7267 }
7268}
7269
7270/*------------------------------------------------------------------*/
7271/* find a free PLCI */
7272/*------------------------------------------------------------------*/
7273
Hannes Eder4ee59d52008-12-16 01:17:33 -08007274static word get_plci(DIVA_CAPI_ADAPTER *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007275{
7276 word i,j;
7277 PLCI * plci;
7278
7279 dump_plcis (a);
7280 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7281 if(i==a->max_plci) {
7282 dbug(1,dprintf("get_plci: out of PLCIs"));
7283 return 0;
7284 }
7285 plci = &a->plci[i];
7286 plci->Id = (byte)(i+1);
7287
7288 plci->Sig.Id = 0;
7289 plci->NL.Id = 0;
7290 plci->sig_req = 0;
7291 plci->nl_req = 0;
7292
7293 plci->appl = NULL;
7294 plci->relatedPTYPLCI = NULL;
7295 plci->State = IDLE;
7296 plci->SuppState = IDLE;
7297 plci->channels = 0;
7298 plci->tel = 0;
7299 plci->B1_resource = 0;
7300 plci->B2_prot = 0;
7301 plci->B3_prot = 0;
7302
7303 plci->command = 0;
7304 plci->m_command = 0;
7305 init_internal_command_queue (plci);
7306 plci->number = 0;
7307 plci->req_in_start = 0;
7308 plci->req_in = 0;
7309 plci->req_out = 0;
7310 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7311 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7312 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7313
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007314 plci->data_sent = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315 plci->send_disc = 0;
7316 plci->sig_global_req = 0;
7317 plci->sig_remove_id = 0;
7318 plci->nl_global_req = 0;
7319 plci->nl_remove_id = 0;
7320 plci->adv_nl = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007321 plci->manufacturer = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007322 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7323 plci->spoofed_msg = 0;
7324 plci->ptyState = 0;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007325 plci->cr_enquiry = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007326 plci->hangup_flow_ctrl_timer = 0;
7327
7328 plci->ncci_ring_list = 0;
7329 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7330 clear_c_ind_mask (plci);
7331 set_group_ind_mask (plci);
7332 plci->fax_connect_info_length = 0;
7333 plci->nsf_control_bits = 0;
7334 plci->ncpi_state = 0x00;
7335 plci->ncpi_buffer[0] = 0;
7336
7337 plci->requested_options_conn = 0;
7338 plci->requested_options = 0;
7339 plci->notifiedcall = 0;
7340 plci->vswitchstate = 0;
7341 plci->vsprot = 0;
7342 plci->vsprotdialect = 0;
7343 init_b1_config (plci);
7344 dbug(1,dprintf("get_plci(%x)",plci->Id));
7345 return i+1;
7346}
7347
7348/*------------------------------------------------------------------*/
7349/* put a parameter in the parameter buffer */
7350/*------------------------------------------------------------------*/
7351
7352static void add_p(PLCI * plci, byte code, byte * p)
7353{
7354 word p_length;
7355
7356 p_length = 0;
7357 if(p) p_length = p[0];
7358 add_ie(plci, code, p, p_length);
7359}
7360
7361/*------------------------------------------------------------------*/
7362/* put a structure in the parameter buffer */
7363/*------------------------------------------------------------------*/
7364static void add_s(PLCI * plci, byte code, API_PARSE * p)
7365{
7366 if(p) add_ie(plci, code, p->info, (word)p->length);
7367}
7368
7369/*------------------------------------------------------------------*/
7370/* put multiple structures in the parameter buffer */
7371/*------------------------------------------------------------------*/
7372static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7373{
7374 byte i;
7375
7376 if(p){
7377 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7378 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7379 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7380 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7381 }
7382 }
7383}
7384
7385/*------------------------------------------------------------------*/
7386/* return the channel number sent by the application in a esc_chi */
7387/*------------------------------------------------------------------*/
7388static byte getChannel(API_PARSE * p)
7389{
7390 byte i;
7391
7392 if(p){
7393 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7394 if(p->info[i]==2){
7395 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7396 }
7397 }
7398 }
7399 return 0;
7400}
7401
7402
7403/*------------------------------------------------------------------*/
7404/* put an information element in the parameter buffer */
7405/*------------------------------------------------------------------*/
7406
7407static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7408{
7409 word i;
7410
7411 if(!(code &0x80) && !p_length) return;
7412
7413 if(plci->req_in==plci->req_in_start) {
7414 plci->req_in +=2;
7415 }
7416 else {
7417 plci->req_in--;
7418 }
7419 plci->RBuffer[plci->req_in++] = code;
7420
7421 if(p) {
7422 plci->RBuffer[plci->req_in++] = (byte)p_length;
7423 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7424 }
7425
7426 plci->RBuffer[plci->req_in++] = 0;
7427}
7428
7429/*------------------------------------------------------------------*/
7430/* put a unstructured data into the buffer */
7431/*------------------------------------------------------------------*/
7432
Hannes Eder4ee59d52008-12-16 01:17:33 -08007433static void add_d(PLCI *plci, word length, byte *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007434{
7435 word i;
7436
7437 if(plci->req_in==plci->req_in_start) {
7438 plci->req_in +=2;
7439 }
7440 else {
7441 plci->req_in--;
7442 }
7443 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7444}
7445
7446/*------------------------------------------------------------------*/
7447/* put parameters from the Additional Info parameter in the */
7448/* parameter buffer */
7449/*------------------------------------------------------------------*/
7450
Hannes Eder4ee59d52008-12-16 01:17:33 -08007451static void add_ai(PLCI *plci, API_PARSE *ai)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007452{
7453 word i;
7454 API_PARSE ai_parms[5];
7455
7456 for(i=0;i<5;i++) ai_parms[i].length = 0;
7457
7458 if(!ai->length)
7459 return;
7460 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7461 return;
7462
7463 add_s (plci,KEY,&ai_parms[1]);
7464 add_s (plci,UUI,&ai_parms[2]);
7465 add_ss(plci,FTY,&ai_parms[3]);
7466}
7467
7468/*------------------------------------------------------------------*/
7469/* put parameter for b1 protocol in the parameter buffer */
7470/*------------------------------------------------------------------*/
7471
Hannes Eder4ee59d52008-12-16 01:17:33 -08007472static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7473 word b1_facilities)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007474{
7475 API_PARSE bp_parms[8];
7476 API_PARSE mdm_cfg[9];
7477 API_PARSE global_config[2];
7478 byte cai[256];
7479 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7480 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7481 word i;
7482
7483 API_PARSE mdm_cfg_v18[4];
7484 word j, n, w;
7485 dword d;
7486
7487
7488 for(i=0;i<8;i++) bp_parms[i].length = 0;
7489 for(i=0;i<2;i++) global_config[i].length = 0;
7490
7491 dbug(1,dprintf("add_b1"));
7492 api_save_msg(bp, "s", &plci->B_protocol);
7493
7494 if(b_channel_info==2){
7495 plci->B1_resource = 0;
7496 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7497 add_p(plci, CAI, "\x01\x00");
7498 dbug(1,dprintf("Cai=1,0 (no resource)"));
7499 return 0;
7500 }
7501
7502 if(plci->tel == CODEC_PERMANENT) return 0;
7503 else if(plci->tel == CODEC){
7504 plci->B1_resource = 1;
7505 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7506 add_p(plci, CAI, "\x01\x01");
7507 dbug(1,dprintf("Cai=1,1 (Codec)"));
7508 return 0;
7509 }
7510 else if(plci->tel == ADV_VOICE){
7511 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7512 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7513 voice_cai[1] = plci->B1_resource;
7514 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7515 add_p(plci, CAI, voice_cai);
7516 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7517 return 0;
7518 }
7519 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7520 if (plci->call_dir & CALL_DIR_OUT)
7521 plci->call_dir |= CALL_DIR_ORIGINATE;
7522 else if (plci->call_dir & CALL_DIR_IN)
7523 plci->call_dir |= CALL_DIR_ANSWER;
7524
7525 if(!bp->length){
7526 plci->B1_resource = 0x5;
7527 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7528 add_p(plci, CAI, "\x01\x05");
7529 return 0;
7530 }
7531
7532 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7533 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7534 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7535 {
7536 bp_parms[6].length = 0;
7537 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7538 {
7539 dbug(1,dprintf("b-form.!"));
7540 return _WRONG_MESSAGE_FORMAT;
7541 }
7542 }
7543 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7544 {
7545 dbug(1,dprintf("b-form.!"));
7546 return _WRONG_MESSAGE_FORMAT;
7547 }
7548
7549 if(bp_parms[6].length)
7550 {
7551 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7552 {
7553 return _WRONG_MESSAGE_FORMAT;
7554 }
7555 switch(GET_WORD(global_config[0].info))
7556 {
7557 case 1:
7558 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7559 break;
7560 case 2:
7561 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7562 break;
7563 }
7564 }
7565 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7566
7567
7568 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7569 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7570 {
7571 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7572 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7573 cai[1] = plci->B1_resource;
7574 cai[2] = 0;
7575 cai[3] = 0;
7576 cai[4] = 0;
7577 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7578 for (i = 0; i < bp_parms[3].length; i++)
7579 cai[7+i] = bp_parms[3].info[1+i];
7580 cai[0] = 6 + bp_parms[3].length;
7581 add_p(plci, CAI, cai);
7582 return 0;
7583 }
7584
7585
7586 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7587 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7588 {
7589 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7590 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7591 cai[1] = plci->B1_resource;
7592 cai[2] = 0;
7593 cai[3] = 0;
7594 cai[4] = 0;
7595 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7596 cai[0] = 6;
7597 add_p(plci, CAI, cai);
7598 return 0;
7599 }
7600
7601
7602 if ((GET_WORD(bp_parms[0].info) >= 32)
7603 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7604 && ((GET_WORD(bp_parms[0].info) != 3)
7605 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7606 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7607 {
7608 return _B1_NOT_SUPPORTED;
7609 }
7610 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7611 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7612 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7613 cai[0] = 6;
7614 cai[1] = plci->B1_resource;
7615 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7616
7617 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7618 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7619 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7620 { /* B1 - modem */
7621 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7622
7623 if (bp_parms[3].length)
7624 {
7625 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7626 {
7627 return (_WRONG_MESSAGE_FORMAT);
7628 }
7629
7630 cai[2] = 0; /* Bit rate for adaptation */
7631
7632 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7633
7634 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7635 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7636 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7637 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7638
7639 cai[3] = 0; /* Async framing parameters */
7640 switch (GET_WORD (mdm_cfg[2].info))
7641 { /* Parity */
7642 case 1: /* odd parity */
7643 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7644 dbug(1,dprintf("MDM: odd parity"));
7645 break;
7646
7647 case 2: /* even parity */
7648 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7649 dbug(1,dprintf("MDM: even parity"));
7650 break;
7651
7652 default:
7653 dbug(1,dprintf("MDM: no parity"));
7654 break;
7655 }
7656
7657 switch (GET_WORD (mdm_cfg[3].info))
7658 { /* stop bits */
7659 case 1: /* 2 stop bits */
7660 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7661 dbug(1,dprintf("MDM: 2 stop bits"));
7662 break;
7663
7664 default:
7665 dbug(1,dprintf("MDM: 1 stop bit"));
7666 break;
7667 }
7668
7669 switch (GET_WORD (mdm_cfg[1].info))
7670 { /* char length */
7671 case 5:
7672 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7673 dbug(1,dprintf("MDM: 5 bits"));
7674 break;
7675
7676 case 6:
7677 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7678 dbug(1,dprintf("MDM: 6 bits"));
7679 break;
7680
7681 case 7:
7682 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7683 dbug(1,dprintf("MDM: 7 bits"));
7684 break;
7685
7686 default:
7687 dbug(1,dprintf("MDM: 8 bits"));
7688 break;
7689 }
7690
7691 cai[7] = 0; /* Line taking options */
7692 cai[8] = 0; /* Modulation negotiation options */
7693 cai[9] = 0; /* Modulation options */
7694
7695 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7696 {
7697 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7698 dbug(1, dprintf("MDM: Reverse direction"));
7699 }
7700
7701 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7702 {
7703 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7704 dbug(1, dprintf("MDM: Disable retrain"));
7705 }
7706
7707 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7708 {
7709 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7710 dbug(1, dprintf("MDM: Disable ring tone"));
7711 }
7712
7713 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7714 {
7715 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7716 dbug(1, dprintf("MDM: 1800 guard tone"));
7717 }
7718 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7719 {
7720 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7721 dbug(1, dprintf("MDM: 550 guard tone"));
7722 }
7723
7724 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7725 {
7726 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7727 dbug(1, dprintf("MDM: V100"));
7728 }
7729 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7730 {
7731 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7732 dbug(1, dprintf("MDM: IN CLASS"));
7733 }
7734 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7735 {
7736 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7737 dbug(1, dprintf("MDM: DISABLED"));
7738 }
7739 cai[0] = 20;
7740
7741 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7742 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7743 {
7744 plci->requested_options |= 1L << PRIVATE_V18;
7745 }
7746 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7747 plci->requested_options |= 1L << PRIVATE_VOWN;
7748
7749 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7750 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7751 {
7752 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7753 {
7754 i = 27;
7755 if (mdm_cfg[6].length >= 4)
7756 {
7757 d = GET_DWORD(&mdm_cfg[6].info[1]);
7758 cai[7] |= (byte) d; /* line taking options */
7759 cai[9] |= (byte)(d >> 8); /* modulation options */
7760 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7761 cai[++i] = (byte)(d >> 24);
7762 if (mdm_cfg[6].length >= 8)
7763 {
7764 d = GET_DWORD(&mdm_cfg[6].info[5]);
7765 cai[10] |= (byte) d; /* disabled modulations mask */
7766 cai[11] |= (byte)(d >> 8);
7767 if (mdm_cfg[6].length >= 12)
7768 {
7769 d = GET_DWORD(&mdm_cfg[6].info[9]);
7770 cai[12] = (byte) d; /* enabled modulations mask */
7771 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7772 cai[++i] = (byte)(d >> 16);
7773 cai[++i] = (byte)(d >> 24);
7774 cai[++i] = 0;
7775 if (mdm_cfg[6].length >= 14)
7776 {
7777 w = GET_WORD(&mdm_cfg[6].info[13]);
7778 if (w != 0)
7779 PUT_WORD(&cai[13], w); /* min tx speed */
7780 if (mdm_cfg[6].length >= 16)
7781 {
7782 w = GET_WORD(&mdm_cfg[6].info[15]);
7783 if (w != 0)
7784 PUT_WORD(&cai[15], w); /* max tx speed */
7785 if (mdm_cfg[6].length >= 18)
7786 {
7787 w = GET_WORD(&mdm_cfg[6].info[17]);
7788 if (w != 0)
7789 PUT_WORD(&cai[17], w); /* min rx speed */
7790 if (mdm_cfg[6].length >= 20)
7791 {
7792 w = GET_WORD(&mdm_cfg[6].info[19]);
7793 if (w != 0)
7794 PUT_WORD(&cai[19], w); /* max rx speed */
7795 if (mdm_cfg[6].length >= 22)
7796 {
7797 w = GET_WORD(&mdm_cfg[6].info[21]);
7798 cai[23] = (byte)(-((short) w)); /* transmit level */
7799 if (mdm_cfg[6].length >= 24)
7800 {
7801 w = GET_WORD(&mdm_cfg[6].info[23]);
7802 cai[22] |= (byte) w; /* info options mask */
7803 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7804 }
7805 }
7806 }
7807 }
7808 }
7809 }
7810 }
7811 }
7812 }
7813 cai[27] = i - 27;
7814 i++;
7815 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7816 {
7817 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7818 {
7819 for (n = 0; n < 3; n++)
7820 {
7821 cai[i] = (byte)(mdm_cfg_v18[n].length);
7822 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7823 cai[i+j] = mdm_cfg_v18[n].info[j];
7824 i += cai[i] + 1;
7825 }
7826 }
7827 }
7828 cai[0] = (byte)(i - 1);
7829 }
7830 }
7831
7832 }
7833 }
7834 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7835 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7836 {
7837 if(bp_parms[3].length){
7838 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7839 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7840 case 0:
7841 case 56000:
7842 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7843 dbug(1,dprintf("56k sync HSCX"));
7844 cai[1] = 8;
7845 cai[2] = 0;
7846 cai[3] = 0;
7847 }
7848 else if(GET_WORD(bp_parms[0].info)==2){
7849 dbug(1,dprintf("56k async DSP"));
7850 cai[2] = 9;
7851 }
7852 break;
7853 case 50: cai[2] = 1; break;
7854 case 75: cai[2] = 1; break;
7855 case 110: cai[2] = 1; break;
7856 case 150: cai[2] = 1; break;
7857 case 200: cai[2] = 1; break;
7858 case 300: cai[2] = 1; break;
7859 case 600: cai[2] = 1; break;
7860 case 1200: cai[2] = 2; break;
7861 case 2400: cai[2] = 3; break;
7862 case 4800: cai[2] = 4; break;
7863 case 7200: cai[2] = 10; break;
7864 case 9600: cai[2] = 5; break;
7865 case 12000: cai[2] = 13; break;
7866 case 24000: cai[2] = 0; break;
7867 case 14400: cai[2] = 11; break;
7868 case 19200: cai[2] = 6; break;
7869 case 28800: cai[2] = 12; break;
7870 case 38400: cai[2] = 7; break;
7871 case 48000: cai[2] = 8; break;
7872 case 76: cai[2] = 15; break; /* 75/1200 */
7873 case 1201: cai[2] = 14; break; /* 1200/75 */
7874 case 56001: cai[2] = 9; break; /* V.110 56000 */
7875
7876 default:
7877 return _B1_PARM_NOT_SUPPORTED;
7878 }
7879 cai[3] = 0;
7880 if (cai[1] == 13) /* v.110 async */
7881 {
7882 if (bp_parms[3].length >= 8)
7883 {
7884 switch (GET_WORD (&bp_parms[3].info[3]))
7885 { /* char length */
7886 case 5:
7887 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7888 break;
7889 case 6:
7890 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7891 break;
7892 case 7:
7893 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7894 break;
7895 }
7896 switch (GET_WORD (&bp_parms[3].info[5]))
7897 { /* Parity */
7898 case 1: /* odd parity */
7899 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7900 break;
7901 case 2: /* even parity */
7902 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7903 break;
7904 }
7905 switch (GET_WORD (&bp_parms[3].info[7]))
7906 { /* stop bits */
7907 case 1: /* 2 stop bits */
7908 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7909 break;
7910 }
7911 }
7912 }
7913 }
7914 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7915 dbug(1,dprintf("V.110 default 56k sync"));
7916 cai[1] = 8;
7917 cai[2] = 0;
7918 cai[3] = 0;
7919 }
7920 else {
7921 dbug(1,dprintf("V.110 default 9600 async"));
7922 cai[2] = 5;
7923 }
7924 }
7925 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7926 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]));
7927/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7928
7929 add_p(plci, CAI, cai);
7930 return 0;
7931}
7932
7933/*------------------------------------------------------------------*/
7934/* put parameter for b2 and B3 protocol in the parameter buffer */
7935/*------------------------------------------------------------------*/
7936
Hannes Eder4ee59d52008-12-16 01:17:33 -08007937static word add_b23(PLCI *plci, API_PARSE *bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007938{
7939 word i, fax_control_bits;
7940 byte pos, len;
7941 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7942 API_PARSE bp_parms[8];
7943 API_PARSE * b1_config;
7944 API_PARSE * b2_config;
7945 API_PARSE b2_config_parms[8];
7946 API_PARSE * b3_config;
7947 API_PARSE b3_config_parms[6];
7948 API_PARSE global_config[2];
7949
7950 static byte llc[3] = {2,0,0};
7951 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7952 static byte nlc[256];
7953 static byte lli[12] = {1,1};
7954
7955 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7956 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7957
7958 const byte llc3[] = {4,3,2,2,6,6,0};
7959 const byte header[] = {0,2,3,3,0,0,0};
7960
7961 for(i=0;i<8;i++) bp_parms[i].length = 0;
7962 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7963 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7964
7965 lli[0] = 1;
7966 lli[1] = 1;
7967 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7968 lli[1] |= 2;
7969 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7970 lli[1] |= 4;
7971
7972 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7973 lli[1] |= 0x10;
7974 if (plci->rx_dma_descriptor <= 0) {
7975 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7976 if (plci->rx_dma_descriptor >= 0)
7977 plci->rx_dma_descriptor++;
7978 }
7979 if (plci->rx_dma_descriptor > 0) {
7980 lli[0] = 6;
7981 lli[1] |= 0x40;
7982 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7983 lli[3] = (byte)plci->rx_dma_magic;
7984 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7985 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7986 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7987 }
7988 }
7989
7990 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7991 lli[1] |= 0x20;
7992 }
7993
7994 dbug(1,dprintf("add_b23"));
7995 api_save_msg(bp, "s", &plci->B_protocol);
7996
7997 if(!bp->length && plci->tel)
7998 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08007999 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008000 dbug(1,dprintf("Default adv.Nl"));
8001 add_p(plci,LLI,lli);
8002 plci->B2_prot = 1 /*XPARENT*/;
8003 plci->B3_prot = 0 /*XPARENT*/;
8004 llc[1] = 2;
8005 llc[2] = 4;
8006 add_p(plci, LLC, llc);
8007 dlc[0] = 2;
8008 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8009 add_p(plci, DLC, dlc);
8010 return 0;
8011 }
8012
8013 if(!bp->length) /*default*/
8014 {
8015 dbug(1,dprintf("ret default"));
8016 add_p(plci,LLI,lli);
8017 plci->B2_prot = 0 /*X.75 */;
8018 plci->B3_prot = 0 /*XPARENT*/;
8019 llc[1] = 1;
8020 llc[2] = 4;
8021 add_p(plci, LLC, llc);
8022 dlc[0] = 2;
8023 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8024 add_p(plci, DLC, dlc);
8025 return 0;
8026 }
8027 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8028 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8029
8030 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8031 {
8032 bp_parms[6].length = 0;
8033 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8034 {
8035 dbug(1,dprintf("b-form.!"));
8036 return _WRONG_MESSAGE_FORMAT;
8037 }
8038 }
8039 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8040 {
8041 dbug(1,dprintf("b-form.!"));
8042 return _WRONG_MESSAGE_FORMAT;
8043 }
8044
8045 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8046 {
8047 if(GET_WORD(bp_parms[1].info)!=1
8048 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008049 plci->adv_nl = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008050 }
8051 else if(plci->tel) return _B2_NOT_SUPPORTED;
8052
8053
8054 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8055 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8056 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8057 {
8058 add_p(plci,LLI,lli);
8059 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8060 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8061 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8062 llc[2] = 4;
8063 add_p(plci, LLC, llc);
8064 dlc[0] = 2;
8065 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8066 dlc[3] = 3; /* Addr A */
8067 dlc[4] = 1; /* Addr B */
8068 dlc[5] = 7; /* modulo mode */
8069 dlc[6] = 7; /* window size */
8070 dlc[7] = 0; /* XID len Lo */
8071 dlc[8] = 0; /* XID len Hi */
8072 for (i = 0; i < bp_parms[4].length; i++)
8073 dlc[9+i] = bp_parms[4].info[1+i];
8074 dlc[0] = (byte)(8 + bp_parms[4].length);
8075 add_p(plci, DLC, dlc);
8076 for (i = 0; i < bp_parms[5].length; i++)
8077 nlc[1+i] = bp_parms[5].info[1+i];
8078 nlc[0] = (byte)(bp_parms[5].length);
8079 add_p(plci, NLC, nlc);
8080 return 0;
8081 }
8082
8083
8084
8085 if ((GET_WORD(bp_parms[1].info) >= 32)
8086 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8087 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8088 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8089
8090 {
8091 return _B2_NOT_SUPPORTED;
8092 }
8093 if ((GET_WORD(bp_parms[2].info) >= 32)
8094 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8095 {
8096 return _B3_NOT_SUPPORTED;
8097 }
8098 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8099 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8100 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8101 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8102 {
8103 return (add_modem_b23 (plci, bp_parms));
8104 }
8105
8106 add_p(plci,LLI,lli);
8107
8108 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8109 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8110 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8111
8112 if(bp_parms[6].length)
8113 {
8114 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8115 {
8116 return _WRONG_MESSAGE_FORMAT;
8117 }
8118 switch(GET_WORD(global_config[0].info))
8119 {
8120 case 1:
8121 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8122 break;
8123 case 2:
8124 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8125 break;
8126 }
8127 }
8128 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8129
8130
8131 if (plci->B2_prot == B2_PIAFS)
8132 llc[1] = PIAFS_CRC;
8133 else
8134/* IMPLEMENT_PIAFS */
8135 {
8136 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8137 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8138 }
8139 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8140
8141 add_p(plci, LLC, llc);
8142
8143 dlc[0] = 2;
8144 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8145 header[GET_WORD(bp_parms[2].info)]);
8146
8147 b1_config = &bp_parms[3];
8148 nlc[0] = 0;
8149 if(plci->B3_prot == 4
8150 || plci->B3_prot == 5)
8151 {
8152 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8153 nlc[0] = sizeof(T30_INFO);
8154 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8155 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8156 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8157 if(b1_config->length>=2)
8158 {
8159 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8160 }
8161 }
8162 b2_config = &bp_parms[4];
8163
8164
8165 if (llc[1] == PIAFS_CRC)
8166 {
8167 if (plci->B3_prot != B3_TRANSPARENT)
8168 {
8169 return _B_STACK_NOT_SUPPORTED;
8170 }
8171 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8172 return _WRONG_MESSAGE_FORMAT;
8173 }
8174 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8175 dlc[3] = 0; /* Addr A */
8176 dlc[4] = 0; /* Addr B */
8177 dlc[5] = 0; /* modulo mode */
8178 dlc[6] = 0; /* window size */
8179 if (b2_config->length >= 7){
8180 dlc[ 7] = 7;
8181 dlc[ 8] = 0;
8182 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8183 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8184 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8185 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8186 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8187 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8188 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8189 dlc[ 0] = 15;
8190 if(b2_config->length >= 8) { /* PIAFS control abilities */
8191 dlc[ 7] = 10;
8192 dlc[16] = 2; /* Length of PIAFS extention */
8193 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8194 dlc[18] = b2_config_parms[4].info[0]; /* value */
8195 dlc[ 0] = 18;
8196 }
8197 }
8198 else /* default values, 64K, variable, no compression */
8199 {
8200 dlc[ 7] = 7;
8201 dlc[ 8] = 0;
8202 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8203 dlc[10] = 0x03; /* V.42bis P0 */
8204 dlc[11] = 0; /* V.42bis P0 */
8205 dlc[12] = 0; /* V.42bis P1 */
8206 dlc[13] = 0; /* V.42bis P1 */
8207 dlc[14] = 0; /* V.42bis P2 */
8208 dlc[15] = 0; /* V.42bis P2 */
8209 dlc[ 0] = 15;
8210 }
8211 add_p(plci, DLC, dlc);
8212 }
8213 else
8214
8215 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8216 {
8217 if (plci->B3_prot != B3_TRANSPARENT)
8218 return _B_STACK_NOT_SUPPORTED;
8219
8220 dlc[0] = 6;
8221 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8222 dlc[3] = 0x08;
8223 dlc[4] = 0x01;
8224 dlc[5] = 127;
8225 dlc[6] = 7;
8226 if (b2_config->length != 0)
8227 {
8228 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8229 return _WRONG_MESSAGE_FORMAT;
8230 }
8231 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8232 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8233 if (b2_config->info[3] != 128)
8234 {
8235 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8236 return _B2_PARM_NOT_SUPPORTED;
8237 }
8238 dlc[5] = (byte)(b2_config->info[3] - 1);
8239 dlc[6] = b2_config->info[4];
8240 if(llc[1]==V120_V42BIS){
8241 if (b2_config->length >= 10){
8242 dlc[ 7] = 6;
8243 dlc[ 8] = 0;
8244 dlc[ 9] = b2_config_parms[4].info[0];
8245 dlc[10] = b2_config_parms[4].info[1];
8246 dlc[11] = b2_config_parms[5].info[0];
8247 dlc[12] = b2_config_parms[5].info[1];
8248 dlc[13] = b2_config_parms[6].info[0];
8249 dlc[14] = b2_config_parms[6].info[1];
8250 dlc[ 0] = 14;
8251 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8252 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8253 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8254 }
8255 else {
8256 dlc[ 6] = 14;
8257 }
8258 }
8259 }
8260 }
8261 else
8262 {
8263 if(b2_config->length)
8264 {
8265 dbug(1,dprintf("B2-Config"));
8266 if(llc[1]==X75_V42BIS){
8267 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8268 {
8269 return _WRONG_MESSAGE_FORMAT;
8270 }
8271 }
8272 else {
8273 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8274 {
8275 return _WRONG_MESSAGE_FORMAT;
8276 }
8277 }
8278 /* if B2 Protocol is LAPD, b2_config structure is different */
8279 if(llc[1]==6)
8280 {
8281 dlc[0] = 4;
8282 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8283 else dlc[2] = 0x01;
8284 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8285 {
8286 SAPI = b2_config->info[2]; /* SAPI */
8287 }
8288 dlc[1] = SAPI;
8289 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8290 {
8291 dlc[3] = 127; /* Mode */
8292 }
8293 else
8294 {
8295 dlc[3] = 7; /* Mode */
8296 }
8297
8298 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8299 else dlc[4] = 1;
8300 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8301 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8302 }
8303 else
8304 {
8305 dlc[0] = (byte)(b2_config_parms[4].length+6);
8306 dlc[3] = b2_config->info[1];
8307 dlc[4] = b2_config->info[2];
8308 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8309 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8310 return _B2_PARM_NOT_SUPPORTED;
8311 }
8312
8313 dlc[5] = (byte)(b2_config->info[3]-1);
8314 dlc[6] = b2_config->info[4];
8315 if(dlc[6]>dlc[5]){
8316 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]));
8317 return _B2_PARM_NOT_SUPPORTED;
8318 }
8319
8320 if(llc[1]==X75_V42BIS) {
8321 if (b2_config->length >= 10){
8322 dlc[ 7] = 6;
8323 dlc[ 8] = 0;
8324 dlc[ 9] = b2_config_parms[4].info[0];
8325 dlc[10] = b2_config_parms[4].info[1];
8326 dlc[11] = b2_config_parms[5].info[0];
8327 dlc[12] = b2_config_parms[5].info[1];
8328 dlc[13] = b2_config_parms[6].info[0];
8329 dlc[14] = b2_config_parms[6].info[1];
8330 dlc[ 0] = 14;
8331 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8332 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8333 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8334 }
8335 else {
8336 dlc[ 6] = 14;
8337 }
8338
8339 }
8340 else {
8341 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8342 for(i=0; i<b2_config_parms[4].length; i++)
8343 dlc[11+i] = b2_config_parms[4].info[1+i];
8344 }
8345 }
8346 }
8347 }
8348 add_p(plci, DLC, dlc);
8349
8350 b3_config = &bp_parms[5];
8351 if(b3_config->length)
8352 {
8353 if(plci->B3_prot == 4
8354 || plci->B3_prot == 5)
8355 {
8356 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8357 {
8358 return _WRONG_MESSAGE_FORMAT;
8359 }
8360 i = GET_WORD((byte *)(b3_config_parms[0].info));
8361 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8362 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8363 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8364 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8365 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8366 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8367 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8368 {
8369
8370 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8371 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8372 {
8373 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8374 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8375 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8376 }
8377
8378 ((T30_INFO *)&nlc[1])->recording_properties =
8379 T30_RECORDING_WIDTH_ISO_A3 |
8380 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8381 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8382 }
8383 if(plci->B3_prot == 5)
8384 {
8385 if (i & 0x0002) /* Accept incoming fax-polling requests */
8386 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8387 if (i & 0x2000) /* Do not use MR compression */
8388 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8389 if (i & 0x4000) /* Do not use MMR compression */
8390 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8391 if (i & 0x8000) /* Do not use ECM */
8392 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8393 if (plci->fax_connect_info_length != 0)
8394 {
8395 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8396 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8397 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8398 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8399 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8400 }
8401 }
8402 /* copy station id to NLC */
8403 for(i=0; i<20; i++)
8404 {
8405 if(i<b3_config_parms[2].length)
8406 {
8407 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8408 }
8409 else
8410 {
8411 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8412 }
8413 }
8414 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8415 /* copy head line to NLC */
8416 if(b3_config_parms[3].length)
8417 {
8418
8419 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8420 if (pos != 0)
8421 {
8422 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8423 pos = 0;
8424 else
8425 {
8426 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8427 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8428 len = (byte)b3_config_parms[2].length;
8429 if (len > 20)
8430 len = 20;
8431 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8432 {
8433 for (i = 0; i < len; i++)
8434 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8435 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8436 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8437 }
8438 }
8439 }
8440
8441 len = (byte)b3_config_parms[3].length;
8442 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8443 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8444 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8445 nlc[0] += (byte)(pos + len);
8446 for (i = 0; i < len; i++)
8447 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8448 }
8449 else
8450 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8451
8452 plci->nsf_control_bits = 0;
8453 if(plci->B3_prot == 5)
8454 {
8455 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8456 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8457 {
8458 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8459 }
8460 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8461 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8462 {
8463 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8464 }
8465 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8466 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8467 {
8468 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8469 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8470 {
8471 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8472 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8473 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8474 }
8475 len = nlc[0];
Jiri Slaby1ea70842009-11-04 08:28:12 -08008476 pos = offsetof(T30_INFO, station_id) + 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008477 if (pos < plci->fax_connect_info_length)
8478 {
8479 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8481 }
8482 else
8483 nlc[++len] = 0;
8484 if (pos < plci->fax_connect_info_length)
8485 {
8486 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8487 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8488 }
8489 else
8490 nlc[++len] = 0;
8491 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8492 & (1L << PRIVATE_FAX_NONSTANDARD))
8493 {
8494 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8495 {
8496 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8497 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8498 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8499 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8500 }
8501 else
8502 {
8503 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8504 {
8505 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8506 nlc[++len] = 0;
8507 }
8508 else
8509 {
8510 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8511 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8512 nlc[++len] = (byte)(b3_config_parms[4].length);
8513 for (i = 0; i < b3_config_parms[4].length; i++)
8514 nlc[++len] = b3_config_parms[4].info[1+i];
8515 }
8516 }
8517 }
8518 nlc[0] = len;
8519 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8520 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8521 {
8522 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8523 }
8524 }
8525 }
8526
8527 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
Jiri Slaby1ea70842009-11-04 08:28:12 -08008528 len = offsetof(T30_INFO, station_id) + 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008529 for (i = 0; i < len; i++)
8530 plci->fax_connect_info_buffer[i] = nlc[1+i];
8531 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8532 i += ((T30_INFO *)&nlc[1])->head_line_len;
8533 while (i < nlc[0])
8534 plci->fax_connect_info_buffer[len++] = nlc[++i];
8535 plci->fax_connect_info_length = len;
8536 }
8537 else
8538 {
8539 nlc[0] = 14;
8540 if(b3_config->length!=16)
8541 return _B3_PARM_NOT_SUPPORTED;
8542 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8543 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8544 return _B3_PARM_NOT_SUPPORTED;
8545 nlc[13] = b3_config->info[13];
8546 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8547 return _B3_PARM_NOT_SUPPORTED;
8548 nlc[14] = b3_config->info[15];
8549 }
8550 }
8551 else
8552 {
8553 if (plci->B3_prot == 4
8554 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8555 }
8556 add_p(plci, NLC, nlc);
8557 return 0;
8558}
8559
8560/*----------------------------------------------------------------*/
8561/* make the same as add_b23, but only for the modem related */
8562/* L2 and L3 B-Chan protocol. */
8563/* */
8564/* Enabled L2 and L3 Configurations: */
8565/* If L1 == Modem all negotiation */
8566/* only L2 == Modem with full negotiation is allowed */
8567/* If L1 == Modem async or sync */
8568/* only L2 == Transparent is allowed */
8569/* L3 == Modem or L3 == Transparent are allowed */
8570/* B2 Configuration for modem: */
8571/* word : enable/disable compression, bitoptions */
8572/* B3 Configuration for modem: */
8573/* empty */
8574/*----------------------------------------------------------------*/
8575static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8576{
8577 static byte lli[12] = {1,1};
8578 static byte llc[3] = {2,0,0};
8579 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8580 API_PARSE mdm_config[2];
8581 word i;
8582 word b2_config = 0;
8583
8584 for(i=0;i<2;i++) mdm_config[i].length = 0;
8585 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8586
8587 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8588 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8589 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8590 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8591 {
8592 return (_B_STACK_NOT_SUPPORTED);
8593 }
8594 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8595 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8596 {
8597 return (_B_STACK_NOT_SUPPORTED);
8598 }
8599
8600 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8601 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8602
8603 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8604 {
8605 if (api_parse (&bp_parms[4].info[1],
8606 (word)bp_parms[4].length, "w",
8607 mdm_config))
8608 {
8609 return (_WRONG_MESSAGE_FORMAT);
8610 }
8611 b2_config = GET_WORD(mdm_config[0].info);
8612 }
8613
8614 /* OK, L2 is modem */
8615
8616 lli[0] = 1;
8617 lli[1] = 1;
8618 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8619 lli[1] |= 2;
8620 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8621 lli[1] |= 4;
8622
8623 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8624 lli[1] |= 0x10;
8625 if (plci->rx_dma_descriptor <= 0) {
8626 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8627 if (plci->rx_dma_descriptor >= 0)
8628 plci->rx_dma_descriptor++;
8629 }
8630 if (plci->rx_dma_descriptor > 0) {
8631 lli[1] |= 0x40;
8632 lli[0] = 6;
8633 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8634 lli[3] = (byte)plci->rx_dma_magic;
8635 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8636 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8637 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8638 }
8639 }
8640
8641 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8642 lli[1] |= 0x20;
8643 }
8644
8645 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8646 /*V42*/ 10 : /*V42_IN*/ 9;
8647 llc[2] = 4; /* pass L3 always transparent */
8648 add_p(plci, LLI, lli);
8649 add_p(plci, LLC, llc);
8650 i = 1;
8651 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8652 i += 2;
8653 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8654 {
8655 if (bp_parms[4].length)
8656 {
8657 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8658 dlc[i++] = 3; /* Addr A */
8659 dlc[i++] = 1; /* Addr B */
8660 dlc[i++] = 7; /* modulo mode */
8661 dlc[i++] = 7; /* window size */
8662 dlc[i++] = 0; /* XID len Lo */
8663 dlc[i++] = 0; /* XID len Hi */
8664
8665 if (b2_config & MDM_B2_DISABLE_V42bis)
8666 {
8667 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8668 }
8669 if (b2_config & MDM_B2_DISABLE_MNP)
8670 {
8671 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8672 }
8673 if (b2_config & MDM_B2_DISABLE_TRANS)
8674 {
8675 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8676 }
8677 if (b2_config & MDM_B2_DISABLE_V42)
8678 {
8679 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8680 }
8681 if (b2_config & MDM_B2_DISABLE_COMP)
8682 {
8683 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8684 }
8685 i++;
8686 }
8687 }
8688 else
8689 {
8690 dlc[i++] = 3; /* Addr A */
8691 dlc[i++] = 1; /* Addr B */
8692 dlc[i++] = 7; /* modulo mode */
8693 dlc[i++] = 7; /* window size */
8694 dlc[i++] = 0; /* XID len Lo */
8695 dlc[i++] = 0; /* XID len Hi */
8696 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8697 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8698 DLC_MODEMPROT_DISABLE_V42_DETECT |
8699 DLC_MODEMPROT_DISABLE_COMPRESSION;
8700 }
8701 dlc[0] = (byte)(i - 1);
8702/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8703 add_p(plci, DLC, dlc);
8704 return (0);
8705}
8706
8707
8708/*------------------------------------------------------------------*/
8709/* send a request for the signaling entity */
8710/*------------------------------------------------------------------*/
8711
Hannes Eder465e9852009-02-25 13:11:37 +00008712static void sig_req(PLCI *plci, byte req, byte Id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008713{
8714 if(!plci) return;
8715 if(plci->adapter->adapter_disabled) return;
8716 dbug(1,dprintf("sig_req(%x)",req));
8717 if (req == REMOVE)
8718 plci->sig_remove_id = plci->Sig.Id;
8719 if(plci->req_in==plci->req_in_start) {
8720 plci->req_in +=2;
8721 plci->RBuffer[plci->req_in++] = 0;
8722 }
8723 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8724 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8725 plci->RBuffer[plci->req_in++] = req; /* request */
8726 plci->RBuffer[plci->req_in++] = 0; /* channel */
8727 plci->req_in_start = plci->req_in;
8728}
8729
8730/*------------------------------------------------------------------*/
8731/* send a request for the network layer entity */
8732/*------------------------------------------------------------------*/
8733
Hannes Eder4ee59d52008-12-16 01:17:33 -08008734static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008735{
8736 if(!plci) return;
8737 if(plci->adapter->adapter_disabled) return;
8738 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8739 if (req == REMOVE)
8740 {
8741 plci->nl_remove_id = plci->NL.Id;
8742 ncci_remove (plci, 0, (byte)(ncci != 0));
8743 ncci = 0;
8744 }
8745 if(plci->req_in==plci->req_in_start) {
8746 plci->req_in +=2;
8747 plci->RBuffer[plci->req_in++] = 0;
8748 }
8749 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8750 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8751 plci->RBuffer[plci->req_in++] = req; /* request */
8752 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8753 plci->req_in_start = plci->req_in;
8754}
8755
Hannes Eder4ee59d52008-12-16 01:17:33 -08008756static void send_req(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008757{
8758 ENTITY * e;
8759 word l;
8760/* word i; */
8761
8762 if(!plci) return;
8763 if(plci->adapter->adapter_disabled) return;
8764 channel_xmit_xon (plci);
8765
8766 /* if nothing to do, return */
8767 if(plci->req_in==plci->req_out) return;
8768 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8769
8770 if(plci->nl_req || plci->sig_req) return;
8771
8772 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8773 plci->req_out += 2;
8774 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8775 plci->req_out += l;
8776 if(plci->RBuffer[plci->req_out]==1)
8777 {
8778 e = &plci->NL;
8779 plci->req_out++;
8780 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8781 e->ReqCh = plci->RBuffer[plci->req_out++];
8782 if(!(e->Id & 0x1f))
8783 {
8784 e->Id = NL_ID;
8785 plci->RBuffer[plci->req_out-4] = CAI;
8786 plci->RBuffer[plci->req_out-3] = 1;
8787 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8788 plci->RBuffer[plci->req_out-1] = 0;
8789 l+=3;
8790 plci->nl_global_req = plci->nl_req;
8791 }
8792 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8793 }
8794 else
8795 {
8796 e = &plci->Sig;
8797 if(plci->RBuffer[plci->req_out])
8798 e->Id = plci->RBuffer[plci->req_out];
8799 plci->req_out++;
8800 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8801 e->ReqCh = plci->RBuffer[plci->req_out++];
8802 if(!(e->Id & 0x1f))
8803 plci->sig_global_req = plci->sig_req;
8804 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8805 }
8806 plci->XData[0].PLength = l;
8807 e->X = plci->XData;
8808 plci->adapter->request(e);
8809 dbug(1,dprintf("send_ok"));
8810}
8811
Hannes Eder465e9852009-02-25 13:11:37 +00008812static void send_data(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008813{
8814 DIVA_CAPI_ADAPTER * a;
8815 DATA_B3_DESC * data;
8816 NCCI *ncci_ptr;
8817 word ncci;
8818
8819 if (!plci->nl_req && plci->ncci_ring_list)
8820 {
8821 a = plci->adapter;
8822 ncci = plci->ncci_ring_list;
8823 do
8824 {
8825 ncci = a->ncci_next[ncci];
8826 ncci_ptr = &(a->ncci[ncci]);
8827 if (!(a->ncci_ch[ncci]
8828 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8829 {
8830 if (ncci_ptr->data_pending)
8831 {
8832 if ((a->ncci_state[ncci] == CONNECTED)
8833 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8834 || (plci->send_disc == ncci))
8835 {
8836 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8837 if ((plci->B2_prot == B2_V120_ASYNC)
8838 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8839 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8840 {
8841 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8842 plci->NData[1].PLength = data->Length;
8843 if (data->Flags & 0x10)
8844 plci->NData[0].P = v120_break_header;
8845 else
8846 plci->NData[0].P = v120_default_header;
8847 plci->NData[0].PLength = 1 ;
8848 plci->NL.XNum = 2;
8849 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8850 }
8851 else
8852 {
8853 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8854 plci->NData[0].PLength = data->Length;
8855 if (data->Flags & 0x10)
8856 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8857
8858 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8859 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8860
8861 else
8862 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8863 }
8864 plci->NL.X = plci->NData;
8865 plci->NL.ReqCh = a->ncci_ch[ncci];
8866 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
Richard Knutsson986c4bb2007-02-12 00:53:24 -08008867 plci->data_sent = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008868 plci->data_sent_ptr = data->P;
8869 a->request(&plci->NL);
8870 }
8871 else {
8872 cleanup_ncci_data (plci, ncci);
8873 }
8874 }
8875 else if (plci->send_disc == ncci)
8876 {
8877 /* dprintf("N_DISC"); */
8878 plci->NData[0].PLength = 0;
8879 plci->NL.ReqCh = a->ncci_ch[ncci];
8880 plci->NL.Req = plci->nl_req = N_DISC;
8881 a->request(&plci->NL);
8882 plci->command = _DISCONNECT_B3_R;
8883 plci->send_disc = 0;
8884 }
8885 }
8886 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8887 plci->ncci_ring_list = ncci;
8888 }
8889}
8890
Hannes Eder4ee59d52008-12-16 01:17:33 -08008891static void listen_check(DIVA_CAPI_ADAPTER *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008892{
8893 word i,j;
8894 PLCI * plci;
8895 byte activnotifiedcalls = 0;
8896
8897 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8898 if (!remove_started && !a->adapter_disabled)
8899 {
8900 for(i=0;i<a->max_plci;i++)
8901 {
8902 plci = &(a->plci[i]);
8903 if(plci->notifiedcall) activnotifiedcalls++;
8904 }
8905 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8906
8907 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8908 if((j=get_plci(a))) {
8909 a->listen_active++;
8910 plci = &a->plci[j-1];
8911 plci->State = LISTENING;
8912
8913 add_p(plci,OAD,"\x01\xfd");
8914
8915 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8916
8917 add_p(plci,CAI,"\x01\xc0");
8918 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8919 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8920 add_p(plci,SHIFT|6,NULL);
8921 add_p(plci,SIN,"\x02\x00\x00");
8922 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8923 sig_req(plci,ASSIGN,DSIG_ID);
8924 send_req(plci);
8925 }
8926 }
8927 }
8928}
8929
8930/*------------------------------------------------------------------*/
8931/* functions for all parameters sent in INDs */
8932/*------------------------------------------------------------------*/
8933
Hannes Eder4ee59d52008-12-16 01:17:33 -08008934static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008935{
8936 word ploc; /* points to current location within packet */
8937 byte w;
8938 byte wlen;
8939 byte codeset,lock;
8940 byte * in;
8941 word i;
8942 word code;
8943 word mIEindex = 0;
8944 ploc = 0;
8945 codeset = 0;
8946 lock = 0;
8947
8948 in = plci->Sig.RBuffer->P;
8949 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8950 { /* element but parms array is larger */
8951 parms[i] = (byte *)"";
8952 }
8953 for(i=0; i<multiIEsize; i++)
8954 {
8955 parms[i] = (byte *)"";
8956 }
8957
8958 while(ploc<plci->Sig.RBuffer->length-1) {
8959
8960 /* read information element id and length */
8961 w = in[ploc];
8962
8963 if(w & 0x80) {
8964/* w &=0xf0; removed, cannot detect congestion levels */
8965/* upper 4 bit masked with w==SHIFT now */
8966 wlen = 0;
8967 }
8968 else {
8969 wlen = (byte)(in[ploc+1]+1);
8970 }
8971 /* check if length valid (not exceeding end of packet) */
8972 if((ploc+wlen) > 270) return ;
8973 if(lock & 0x80) lock &=0x7f;
8974 else codeset = lock;
8975
8976 if((w&0xf0)==SHIFT) {
8977 codeset = in[ploc];
8978 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8979 codeset &=7;
8980 lock |=0x80;
8981 }
8982 else {
8983 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8984 else code = w;
8985 code |= (codeset<<8);
8986
8987 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8988
8989 if(i<parms_id[0]+1) {
8990 if(!multiIEsize) { /* with multiIEs use next field index, */
8991 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8992 }
8993
8994 parms[mIEindex] = &in[ploc+1];
8995 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8996 if(parms_id[i]==OAD
8997 || parms_id[i]==CONN_NR
8998 || parms_id[i]==CAD) {
8999 if(in[ploc+2] &0x80) {
9000 in[ploc+0] = (byte)(in[ploc+1]+1);
9001 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9002 in[ploc+2] = 0x80;
9003 parms[mIEindex] = &in[ploc];
9004 }
9005 }
9006 mIEindex++; /* effects multiIEs only */
9007 }
9008 }
9009
9010 ploc +=(wlen+1);
9011 }
9012 return ;
9013}
9014
9015/*------------------------------------------------------------------*/
9016/* try to match a cip from received BC and HLC */
9017/*------------------------------------------------------------------*/
9018
Hannes Eder4ee59d52008-12-16 01:17:33 -08009019static byte ie_compare(byte *ie1, byte *ie2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009020{
9021 word i;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009022 if(!ie1 || ! ie2) return false;
9023 if(!ie1[0]) return false;
9024 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9025 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009026}
9027
Hannes Eder4ee59d52008-12-16 01:17:33 -08009028static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009029{
9030 word i;
9031 word j;
9032
9033 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9034
9035 for(j=16;j<29 &&
9036 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9037 if(j==29) return i;
9038 return j;
9039}
9040
9041
9042static byte AddInfo(byte **add_i,
9043 byte **fty_i,
9044 byte *esc_chi,
9045 byte *facility)
9046{
9047 byte i;
9048 byte j;
9049 byte k;
9050 byte flen;
9051 byte len=0;
9052 /* facility is a nested structure */
9053 /* FTY can be more than once */
9054
Roel Kluin3eb1a6f2008-02-06 01:38:30 -08009055 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
Linus Torvalds1da177e2005-04-16 15:20:36 -07009056 {
9057 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9058 }
9059
9060 else
9061 {
9062 add_i[0] = (byte *)"";
9063 }
9064 if(!fty_i[0][0])
9065 {
9066 add_i[3] = (byte *)"";
9067 }
9068 else
9069 { /* facility array found */
9070 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9071 {
9072 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9073 len += fty_i[i][0];
9074 len += 2;
9075 flen=fty_i[i][0];
9076 facility[j++]=0x1c; /* copy fac IE */
9077 for(k=0;k<=flen;k++,j++)
9078 {
9079 facility[j]=fty_i[i][k];
9080/* dbug(1,dprintf("%x ",facility[j])); */
9081 }
9082 }
9083 facility[0] = len;
9084 add_i[3] = facility;
9085 }
9086/* dbug(1,dprintf("FacArrLen=%d ",len)); */
9087 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9088 len += 4; /* calculate length of all */
9089 return(len);
9090}
9091
9092/*------------------------------------------------------------------*/
9093/* voice and codec features */
9094/*------------------------------------------------------------------*/
9095
Hannes Eder4ee59d52008-12-16 01:17:33 -08009096static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009097{
9098 byte voice_chi[] = "\x02\x18\x01";
9099 byte channel;
9100
9101 channel = chi[chi[0]]&0x3;
9102 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9103 voice_chi[2] = (channel) ? channel : 1;
9104 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9105 add_p(plci,ESC,voice_chi); /* Channel */
9106 sig_req(plci,TEL_CTRL,0);
9107 send_req(plci);
9108 if(a->AdvSignalPLCI)
9109 {
9110 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9111 }
9112}
9113
Hannes Eder4ee59d52008-12-16 01:17:33 -08009114static void VoiceChannelOff(PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009115{
9116 dbug(1,dprintf("ExtDevOFF"));
9117 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9118 sig_req(plci,TEL_CTRL,0);
9119 send_req(plci);
9120 if(plci->adapter->AdvSignalPLCI)
9121 {
9122 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9123 }
9124}
9125
9126
Hannes Eder4ee59d52008-12-16 01:17:33 -08009127static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9128 byte hook_listen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009129{
9130 word j;
9131 PLCI *splci;
9132
9133 /* check if hardware supports handset with hook states (adv.codec) */
9134 /* or if just a on board codec is supported */
9135 /* the advanced codec plci is just for internal use */
9136
9137 /* diva Pro with on-board codec: */
9138 if(a->profile.Global_Options & HANDSET)
9139 {
9140 /* new call, but hook states are already signalled */
9141 if(a->AdvCodecFLAG)
9142 {
9143 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9144 {
9145 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9146 return 0x2001; /* codec in use by another application */
9147 }
Harvey Harrisondd58c0d2008-04-28 02:14:39 -07009148 if(plci!=NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009149 {
9150 a->AdvSignalPLCI = plci;
9151 plci->tel=ADV_VOICE;
9152 }
9153 return 0; /* adv codec still used */
9154 }
9155 if((j=get_plci(a)))
9156 {
9157 splci = &a->plci[j-1];
9158 splci->tel = CODEC_PERMANENT;
9159 /* hook_listen indicates if a facility_req with handset/hook support */
9160 /* was sent. Otherwise if just a call on an external device was made */
9161 /* the codec will be used but the hook info will be discarded (just */
9162 /* the external controller is in use */
9163 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9164 else
9165 {
9166 splci->State = ADVANCED_VOICE_NOSIG;
9167 if(plci)
9168 {
9169 plci->spoofed_msg = SPOOFING_REQUIRED;
9170 }
9171 /* indicate D-ch connect if */
9172 } /* codec is connected OK */
Harvey Harrisondd58c0d2008-04-28 02:14:39 -07009173 if(plci!=NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009174 {
9175 a->AdvSignalPLCI = plci;
9176 plci->tel=ADV_VOICE;
9177 }
9178 a->AdvSignalAppl = appl;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009179 a->AdvCodecFLAG = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009180 a->AdvCodecPLCI = splci;
9181 add_p(splci,CAI,"\x01\x15");
9182 add_p(splci,LLI,"\x01\x00");
9183 add_p(splci,ESC,"\x02\x18\x00");
9184 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9185 splci->internal_command = PERM_COD_ASSIGN;
9186 dbug(1,dprintf("Codec Assign"));
9187 sig_req(splci,ASSIGN,DSIG_ID);
9188 send_req(splci);
9189 }
9190 else
9191 {
9192 return 0x2001; /* wrong state, no more plcis */
9193 }
9194 }
9195 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9196 {
9197 if(hook_listen) return 0x300B; /* Facility not supported */
9198 /* no hook with SCOM */
Harvey Harrisondd58c0d2008-04-28 02:14:39 -07009199 if(plci!=NULL) plci->tel = CODEC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009200 dbug(1,dprintf("S/SCOM codec"));
9201 /* first time we use the scom-s codec we must shut down the internal */
9202 /* handset application of the card. This can be done by an assign with */
9203 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9204 if(!a->scom_appl_disable){
9205 if((j=get_plci(a))) {
9206 splci = &a->plci[j-1];
9207 add_p(splci,CAI,"\x01\x80");
9208 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9209 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9210 send_req(splci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009211 a->scom_appl_disable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009212 }
9213 else{
9214 return 0x2001; /* wrong state, no more plcis */
9215 }
9216 }
9217 }
9218 else return 0x300B; /* Facility not supported */
9219
9220 return 0;
9221}
9222
9223
Hannes Eder4ee59d52008-12-16 01:17:33 -08009224static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009225{
9226
9227 dbug(1,dprintf("CodecIdCheck"));
9228
9229 if(a->AdvSignalPLCI == plci)
9230 {
9231 dbug(1,dprintf("PLCI owns codec"));
9232 VoiceChannelOff(a->AdvCodecPLCI);
9233 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9234 {
9235 dbug(1,dprintf("remove temp codec PLCI"));
9236 plci_remove(a->AdvCodecPLCI);
9237 a->AdvCodecFLAG = 0;
9238 a->AdvCodecPLCI = NULL;
9239 a->AdvSignalAppl = NULL;
9240 }
9241 a->AdvSignalPLCI = NULL;
9242 }
9243}
9244
9245/* -------------------------------------------------------------------
9246 Ask for physical address of card on PCI bus
9247 ------------------------------------------------------------------- */
9248static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9249 IDI_SYNC_REQ * preq) {
9250 a->sdram_bar = 0;
9251 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9252 ENTITY * e = (ENTITY *)preq;
9253
9254 e->user[0] = a->Id - 1;
9255 preq->xdi_sdram_bar.info.bar = 0;
9256 preq->xdi_sdram_bar.Req = 0;
9257 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9258
9259 (*(a->request))(e);
9260
9261 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9262 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9263 }
9264}
9265
9266/* -------------------------------------------------------------------
9267 Ask XDI about extended features
9268 ------------------------------------------------------------------- */
9269static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9270 IDI_SYNC_REQ * preq;
9271 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9272
9273 char features[4];
9274 preq = (IDI_SYNC_REQ *)&buffer[0];
9275
9276 if (!diva_xdi_extended_features) {
9277 ENTITY * e = (ENTITY *)preq;
9278 diva_xdi_extended_features |= 0x80000000;
9279
9280 e->user[0] = a->Id - 1;
9281 preq->xdi_extended_features.Req = 0;
9282 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9283 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9284 preq->xdi_extended_features.info.features = &features[0];
9285
9286 (*(a->request))(e);
9287
9288 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9289 /*
9290 Check features located in the byte '0'
9291 */
9292 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9293 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9294 }
9295 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9296 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9297 dbug(1,dprintf("XDI provides RxDMA"));
9298 }
9299 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9300 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9301 }
9302 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9303 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9304 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9305 }
9306
9307 }
9308 }
9309
9310 diva_ask_for_xdi_sdram_bar (a, preq);
9311}
9312
9313/*------------------------------------------------------------------*/
9314/* automatic law */
9315/*------------------------------------------------------------------*/
9316/* called from OS specific part after init time to get the Law */
9317/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9318void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9319{
9320 word j;
9321 PLCI *splci;
9322
9323 if(a->automatic_law) {
9324 return;
9325 }
9326 if((j=get_plci(a))) {
9327 diva_get_extended_adapter_features (a);
9328 splci = &a->plci[j-1];
9329 a->automatic_lawPLCI = splci;
9330 a->automatic_law = 1;
9331 add_p(splci,CAI,"\x01\x80");
9332 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9333 splci->internal_command = USELAW_REQ;
9334 splci->command = 0;
9335 splci->number = 0;
9336 sig_req(splci,ASSIGN,DSIG_ID);
9337 send_req(splci);
9338 }
9339}
9340
9341/* called from OS specific part if an application sends an Capi20Release */
9342word CapiRelease(word Id)
9343{
9344 word i, j, appls_found;
9345 PLCI *plci;
9346 APPL *this;
9347 DIVA_CAPI_ADAPTER *a;
9348
9349 if (!Id)
9350 {
9351 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9352 return (_WRONG_APPL_ID);
9353 }
9354
9355 this = &application[Id-1]; /* get application pointer */
9356
9357 for(i=0,appls_found=0; i<max_appl; i++)
9358 {
9359 if(application[i].Id) /* an application has been found */
9360 {
9361 appls_found++;
9362 }
9363 }
9364
9365 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9366 {
9367 a = &adapter[i];
9368 if (a->request)
9369 {
9370 a->Info_Mask[Id-1] = 0;
9371 a->CIP_Mask[Id-1] = 0;
9372 a->Notification_Mask[Id-1] = 0;
9373 a->codec_listen[Id-1] = NULL;
9374 a->requested_options_table[Id-1] = 0;
9375 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9376 { /* with this application */
9377 plci = &a->plci[j];
9378 if(plci->Id) /* if plci owns no application */
9379 { /* it may be not jet connected */
9380 if(plci->State==INC_CON_PENDING
9381 || plci->State==INC_CON_ALERT)
9382 {
9383 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9384 {
9385 clear_c_ind_mask_bit (plci, (word)(Id-1));
9386 if(c_ind_mask_empty (plci))
9387 {
9388 sig_req(plci,HANGUP,0);
9389 send_req(plci);
9390 plci->State = OUTG_DIS_PENDING;
9391 }
9392 }
9393 }
9394 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9395 {
9396 clear_c_ind_mask_bit (plci, (word)(Id-1));
9397 if(c_ind_mask_empty (plci))
9398 {
9399 if(!plci->appl)
9400 {
9401 plci_remove(plci);
9402 plci->State = IDLE;
9403 }
9404 }
9405 }
9406 if(plci->appl==this)
9407 {
9408 plci->appl = NULL;
9409 plci_remove(plci);
9410 plci->State = IDLE;
9411 }
9412 }
9413 }
9414 listen_check(a);
9415
9416 if(a->flag_dynamic_l1_down)
9417 {
9418 if(appls_found==1) /* last application does a capi release */
9419 {
9420 if((j=get_plci(a)))
9421 {
9422 plci = &a->plci[j-1];
9423 plci->command = 0;
9424 add_p(plci,OAD,"\x01\xfd");
9425 add_p(plci,CAI,"\x01\x80");
9426 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9427 add_p(plci,SHIFT|6,NULL);
9428 add_p(plci,SIN,"\x02\x00\x00");
9429 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9430 sig_req(plci,ASSIGN,DSIG_ID);
9431 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9432 sig_req(plci,SIG_CTRL,0);
9433 send_req(plci);
9434 }
9435 }
9436 }
9437 if(a->AdvSignalAppl==this)
9438 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009439 this->NullCREnable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009440 if (a->AdvCodecPLCI)
9441 {
9442 plci_remove(a->AdvCodecPLCI);
9443 a->AdvCodecPLCI->tel = 0;
9444 a->AdvCodecPLCI->adv_nl = 0;
9445 }
9446 a->AdvSignalAppl = NULL;
9447 a->AdvSignalPLCI = NULL;
9448 a->AdvCodecFLAG = 0;
9449 a->AdvCodecPLCI = NULL;
9450 }
9451 }
9452 }
9453
9454 this->Id = 0;
9455
9456 return GOOD;
9457}
9458
9459static word plci_remove_check(PLCI *plci)
9460{
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009461 if(!plci) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009462 if(!plci->NL.Id && c_ind_mask_empty (plci))
9463 {
9464 if(plci->Sig.Id == 0xff)
9465 plci->Sig.Id = 0;
9466 if(!plci->Sig.Id)
9467 {
9468 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9469 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9470 if (plci->Id)
9471 {
9472 CodecIdCheck(plci->adapter, plci);
9473 clear_b1_config (plci);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009474 ncci_remove (plci, 0, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009475 plci_free_msg_in_queue (plci);
9476 channel_flow_control_remove (plci);
9477 plci->Id = 0;
9478 plci->State = IDLE;
9479 plci->channels = 0;
9480 plci->appl = NULL;
9481 plci->notifiedcall = 0;
9482 }
9483 listen_check(plci->adapter);
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009484 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009485 }
9486 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009487 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009488}
9489
9490
9491/*------------------------------------------------------------------*/
9492
9493static byte plci_nl_busy (PLCI *plci)
9494{
9495 /* only applicable for non-multiplexed protocols */
9496 return (plci->nl_req
9497 || (plci->ncci_ring_list
9498 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9499 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9500}
9501
9502
9503/*------------------------------------------------------------------*/
9504/* DTMF facilities */
9505/*------------------------------------------------------------------*/
9506
9507
9508static struct
9509{
9510 byte send_mask;
9511 byte listen_mask;
9512 byte character;
9513 byte code;
9514} dtmf_digit_map[] =
9515{
9516 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9517 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9518 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9519 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9520 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9521 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9522 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9523 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9524 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9525 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9526 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9527 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9528 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9529 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9530 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9531 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9532 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9533 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9534 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9535 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9536
9537 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9538 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9539 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9540 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9541 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9542 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9543 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9544 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9545 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9546 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9547 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9548 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9549 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9550 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9551 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9552 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9553 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9554 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9555 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9556 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9557 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9558 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9559 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9560 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9561 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9562 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9563 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9564 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9565 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9566 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9567 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9568 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9569 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9570 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9571 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9572 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9573 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9574 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9575 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9576 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9577 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9578 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9579 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9580 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9581 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9582 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9583 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9584 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9585 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9586 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9587 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9588 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9589
9590};
9591
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -08009592#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009593
9594
9595static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9596{
9597 word min_digit_duration, min_gap_duration;
9598
9599 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9600 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9601 (char *)(FILE_), __LINE__, enable_mask));
9602
9603 if (enable_mask != 0)
9604 {
9605 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9606 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9607 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9608 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9609 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9610 plci->NData[0].PLength = 5;
9611
9612 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9613 plci->NData[0].PLength += 2;
9614 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9615
9616 }
9617 else
9618 {
9619 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9620 plci->NData[0].PLength = 1;
9621
9622 capidtmf_recv_disable (&(plci->capidtmf_state));
9623
9624 }
9625 plci->NData[0].P = plci->internal_req_buffer;
9626 plci->NL.X = plci->NData;
9627 plci->NL.ReqCh = 0;
9628 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9629 plci->adapter->request (&plci->NL);
9630}
9631
9632
9633static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9634{
9635 word w, i;
9636
9637 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9638 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9639 (char *)(FILE_), __LINE__, digit_count));
9640
9641 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9642 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9643 PUT_WORD (&plci->internal_req_buffer[1], w);
9644 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9645 PUT_WORD (&plci->internal_req_buffer[3], w);
9646 for (i = 0; i < digit_count; i++)
9647 {
9648 w = 0;
9649 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9650 && (digit_buffer[i] != dtmf_digit_map[w].character))
9651 {
9652 w++;
9653 }
9654 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9655 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9656 }
9657 plci->NData[0].PLength = 5 + digit_count;
9658 plci->NData[0].P = plci->internal_req_buffer;
9659 plci->NL.X = plci->NData;
9660 plci->NL.ReqCh = 0;
9661 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9662 plci->adapter->request (&plci->NL);
9663}
9664
9665
9666static void dtmf_rec_clear_config (PLCI *plci)
9667{
9668
9669 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9670 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9671 (char *)(FILE_), __LINE__));
9672
9673 plci->dtmf_rec_active = 0;
9674 plci->dtmf_rec_pulse_ms = 0;
9675 plci->dtmf_rec_pause_ms = 0;
9676
9677 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9678
9679}
9680
9681
9682static void dtmf_send_clear_config (PLCI *plci)
9683{
9684
9685 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9686 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9687 (char *)(FILE_), __LINE__));
9688
9689 plci->dtmf_send_requests = 0;
9690 plci->dtmf_send_pulse_ms = 0;
9691 plci->dtmf_send_pause_ms = 0;
9692}
9693
9694
9695static void dtmf_prepare_switch (dword Id, PLCI *plci)
9696{
9697
9698 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9699 UnMapId (Id), (char *)(FILE_), __LINE__));
9700
9701 while (plci->dtmf_send_requests != 0)
9702 dtmf_confirmation (Id, plci);
9703}
9704
9705
9706static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9707{
9708
9709 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9710 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9711
9712 return (GOOD);
9713}
9714
9715
9716static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9717{
9718 word Info;
9719
9720 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9721 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9722
9723 Info = GOOD;
9724 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9725 {
9726 switch (plci->adjust_b_state)
9727 {
9728 case ADJUST_B_RESTORE_DTMF_1:
9729 plci->internal_command = plci->adjust_b_command;
9730 if (plci_nl_busy (plci))
9731 {
9732 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9733 break;
9734 }
9735 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9736 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9737 break;
9738 case ADJUST_B_RESTORE_DTMF_2:
9739 if ((Rc != OK) && (Rc != OK_FC))
9740 {
9741 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9742 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9743 Info = _WRONG_STATE;
9744 break;
9745 }
9746 break;
9747 }
9748 }
9749 return (Info);
9750}
9751
9752
9753static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9754{
9755 word internal_command, Info;
9756 byte mask;
9757 byte result[4];
9758
9759 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9760 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9761 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9762 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9763
9764 Info = GOOD;
9765 result[0] = 2;
9766 PUT_WORD (&result[1], DTMF_SUCCESS);
9767 internal_command = plci->internal_command;
9768 plci->internal_command = 0;
9769 mask = 0x01;
9770 switch (plci->dtmf_cmd)
9771 {
9772
9773 case DTMF_LISTEN_TONE_START:
9774 mask <<= 1;
9775 case DTMF_LISTEN_MF_START:
9776 mask <<= 1;
9777
9778 case DTMF_LISTEN_START:
9779 switch (internal_command)
9780 {
9781 default:
9782 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9783 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9784 case DTMF_COMMAND_1:
9785 if (adjust_b_process (Id, plci, Rc) != GOOD)
9786 {
9787 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9788 UnMapId (Id), (char *)(FILE_), __LINE__));
9789 Info = _FACILITY_NOT_SUPPORTED;
9790 break;
9791 }
9792 if (plci->internal_command)
9793 return;
9794 case DTMF_COMMAND_2:
9795 if (plci_nl_busy (plci))
9796 {
9797 plci->internal_command = DTMF_COMMAND_2;
9798 return;
9799 }
9800 plci->internal_command = DTMF_COMMAND_3;
9801 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9802 return;
9803 case DTMF_COMMAND_3:
9804 if ((Rc != OK) && (Rc != OK_FC))
9805 {
9806 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9807 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9808 Info = _FACILITY_NOT_SUPPORTED;
9809 break;
9810 }
9811
9812 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9813
9814 plci->dtmf_rec_active |= mask;
9815 break;
9816 }
9817 break;
9818
9819
9820 case DTMF_LISTEN_TONE_STOP:
9821 mask <<= 1;
9822 case DTMF_LISTEN_MF_STOP:
9823 mask <<= 1;
9824
9825 case DTMF_LISTEN_STOP:
9826 switch (internal_command)
9827 {
9828 default:
9829 plci->dtmf_rec_active &= ~mask;
9830 if (plci->dtmf_rec_active)
9831 break;
9832/*
9833 case DTMF_COMMAND_1:
9834 if (plci->dtmf_rec_active)
9835 {
9836 if (plci_nl_busy (plci))
9837 {
9838 plci->internal_command = DTMF_COMMAND_1;
9839 return;
9840 }
9841 plci->dtmf_rec_active &= ~mask;
9842 plci->internal_command = DTMF_COMMAND_2;
Richard Knutsson986c4bb2007-02-12 00:53:24 -08009843 dtmf_enable_receiver (plci, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009844 return;
9845 }
9846 Rc = OK;
9847 case DTMF_COMMAND_2:
9848 if ((Rc != OK) && (Rc != OK_FC))
9849 {
9850 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9851 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9852 Info = _FACILITY_NOT_SUPPORTED;
9853 break;
9854 }
9855*/
9856 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9857 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9858 case DTMF_COMMAND_3:
9859 if (adjust_b_process (Id, plci, Rc) != GOOD)
9860 {
9861 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9862 UnMapId (Id), (char *)(FILE_), __LINE__));
9863 Info = _FACILITY_NOT_SUPPORTED;
9864 break;
9865 }
9866 if (plci->internal_command)
9867 return;
9868 break;
9869 }
9870 break;
9871
9872
9873 case DTMF_SEND_TONE:
9874 mask <<= 1;
9875 case DTMF_SEND_MF:
9876 mask <<= 1;
9877
9878 case DTMF_DIGITS_SEND:
9879 switch (internal_command)
9880 {
9881 default:
9882 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9883 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9884 DTMF_COMMAND_1);
9885 case DTMF_COMMAND_1:
9886 if (adjust_b_process (Id, plci, Rc) != GOOD)
9887 {
9888 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9889 UnMapId (Id), (char *)(FILE_), __LINE__));
9890 Info = _FACILITY_NOT_SUPPORTED;
9891 break;
9892 }
9893 if (plci->internal_command)
9894 return;
9895 case DTMF_COMMAND_2:
9896 if (plci_nl_busy (plci))
9897 {
9898 plci->internal_command = DTMF_COMMAND_2;
9899 return;
9900 }
9901 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9902 plci->internal_command = DTMF_COMMAND_3;
9903 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9904 return;
9905 case DTMF_COMMAND_3:
9906 if ((Rc != OK) && (Rc != OK_FC))
9907 {
9908 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9909 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9910 if (plci->dtmf_send_requests != 0)
9911 (plci->dtmf_send_requests)--;
9912 Info = _FACILITY_NOT_SUPPORTED;
9913 break;
9914 }
9915 return;
9916 }
9917 break;
9918 }
9919 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9920 "wws", Info, SELECTOR_DTMF, result);
9921}
9922
9923
9924static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9925{
9926 word Info;
9927 word i, j;
9928 byte mask;
9929 API_PARSE dtmf_parms[5];
9930 byte result[40];
9931
9932 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9933 UnMapId (Id), (char *)(FILE_), __LINE__));
9934
9935 Info = GOOD;
9936 result[0] = 2;
9937 PUT_WORD (&result[1], DTMF_SUCCESS);
9938 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9939 {
9940 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9941 UnMapId (Id), (char *)(FILE_), __LINE__));
9942 Info = _FACILITY_NOT_SUPPORTED;
9943 }
9944 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9945 {
9946 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9947 UnMapId (Id), (char *)(FILE_), __LINE__));
9948 Info = _WRONG_MESSAGE_FORMAT;
9949 }
9950
9951 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9952 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9953 {
9954 if (!((a->requested_options_table[appl->Id-1])
9955 & (1L << PRIVATE_DTMF_TONE)))
9956 {
9957 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9958 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9959 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9960 }
9961 else
9962 {
9963 for (i = 0; i < 32; i++)
9964 result[4 + i] = 0;
9965 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9966 {
9967 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9968 {
9969 if (dtmf_digit_map[i].listen_mask != 0)
9970 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9971 }
9972 }
9973 else
9974 {
9975 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9976 {
9977 if (dtmf_digit_map[i].send_mask != 0)
9978 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9979 }
9980 }
9981 result[0] = 3 + 32;
9982 result[3] = 32;
9983 }
9984 }
9985
9986 else if (plci == NULL)
9987 {
9988 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9989 UnMapId (Id), (char *)(FILE_), __LINE__));
9990 Info = _WRONG_IDENTIFIER;
9991 }
9992 else
9993 {
9994 if (!plci->State
9995 || !plci->NL.Id || plci->nl_remove_id)
9996 {
9997 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9998 UnMapId (Id), (char *)(FILE_), __LINE__));
9999 Info = _WRONG_STATE;
10000 }
10001 else
10002 {
10003 plci->command = 0;
10004 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10005 mask = 0x01;
10006 switch (plci->dtmf_cmd)
10007 {
10008
10009 case DTMF_LISTEN_TONE_START:
10010 case DTMF_LISTEN_TONE_STOP:
10011 mask <<= 1;
10012 case DTMF_LISTEN_MF_START:
10013 case DTMF_LISTEN_MF_STOP:
10014 mask <<= 1;
10015 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10016 & (1L << PRIVATE_DTMF_TONE)))
10017 {
10018 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10019 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10020 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10021 break;
10022 }
10023
10024 case DTMF_LISTEN_START:
10025 case DTMF_LISTEN_STOP:
10026 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10027 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10028 {
10029 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10030 UnMapId (Id), (char *)(FILE_), __LINE__));
10031 Info = _FACILITY_NOT_SUPPORTED;
10032 break;
10033 }
10034 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10035 {
10036 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10037 {
10038 plci->dtmf_rec_pulse_ms = 0;
10039 plci->dtmf_rec_pause_ms = 0;
10040 }
10041 else
10042 {
10043 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10044 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10045 }
10046 }
10047 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010048 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010049
10050
10051 case DTMF_SEND_TONE:
10052 mask <<= 1;
10053 case DTMF_SEND_MF:
10054 mask <<= 1;
10055 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10056 & (1L << PRIVATE_DTMF_TONE)))
10057 {
10058 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10059 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10060 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10061 break;
10062 }
10063
10064 case DTMF_DIGITS_SEND:
10065 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10066 {
10067 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10068 UnMapId (Id), (char *)(FILE_), __LINE__));
10069 Info = _WRONG_MESSAGE_FORMAT;
10070 break;
10071 }
10072 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10073 {
10074 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10075 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10076 }
10077 i = 0;
10078 j = 0;
10079 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10080 {
10081 j = 0;
10082 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10083 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10084 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10085 {
10086 j++;
10087 }
10088 i++;
10089 }
10090 if (j == DTMF_DIGIT_MAP_ENTRIES)
10091 {
10092 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10093 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10094 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10095 break;
10096 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080010097 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010098 {
10099 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10100 UnMapId (Id), (char *)(FILE_), __LINE__));
10101 Info = _WRONG_STATE;
10102 break;
10103 }
10104 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10105 start_internal_command (Id, plci, dtmf_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010106 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010107
10108 default:
10109 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10110 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10111 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10112 }
10113 }
10114 }
10115 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10116 "wws", Info, SELECTOR_DTMF, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010117 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010118}
10119
10120
10121static void dtmf_confirmation (dword Id, PLCI *plci)
10122{
10123 word Info;
10124 word i;
10125 byte result[4];
10126
10127 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10128 UnMapId (Id), (char *)(FILE_), __LINE__));
10129
10130 Info = GOOD;
10131 result[0] = 2;
10132 PUT_WORD (&result[1], DTMF_SUCCESS);
10133 if (plci->dtmf_send_requests != 0)
10134 {
10135 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10136 "wws", GOOD, SELECTOR_DTMF, result);
10137 (plci->dtmf_send_requests)--;
10138 for (i = 0; i < plci->dtmf_send_requests; i++)
10139 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10140 }
10141}
10142
10143
10144static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10145{
10146 word i, j, n;
10147
10148 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10149 UnMapId (Id), (char *)(FILE_), __LINE__));
10150
10151 n = 0;
10152 for (i = 1; i < length; i++)
10153 {
10154 j = 0;
10155 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10156 && ((msg[i] != dtmf_digit_map[j].code)
10157 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10158 {
10159 j++;
10160 }
10161 if (j < DTMF_DIGIT_MAP_ENTRIES)
10162 {
10163
10164 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10165 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10166 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10167 {
10168 if (n + 1 == i)
10169 {
10170 for (i = length; i > n + 1; i--)
10171 msg[i] = msg[i - 1];
10172 length++;
10173 i++;
10174 }
10175 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10176 }
10177 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10178
10179 msg[++n] = dtmf_digit_map[j].character;
10180 }
10181 }
10182 if (n != 0)
10183 {
10184 msg[0] = (byte) n;
10185 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10186 }
10187}
10188
10189
10190/*------------------------------------------------------------------*/
10191/* DTMF parameters */
10192/*------------------------------------------------------------------*/
10193
10194static void dtmf_parameter_write (PLCI *plci)
10195{
10196 word i;
10197 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10198
10199 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10200 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10201 (char *)(FILE_), __LINE__));
10202
10203 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10204 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10205 for (i = 0; i < plci->dtmf_parameter_length; i++)
10206 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10207 add_p (plci, FTY, parameter_buffer);
10208 sig_req (plci, TEL_CTRL, 0);
10209 send_req (plci);
10210}
10211
10212
10213static void dtmf_parameter_clear_config (PLCI *plci)
10214{
10215
10216 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10217 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10218 (char *)(FILE_), __LINE__));
10219
10220 plci->dtmf_parameter_length = 0;
10221}
10222
10223
10224static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10225{
10226
10227 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10228 UnMapId (Id), (char *)(FILE_), __LINE__));
10229
10230}
10231
10232
10233static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10234{
10235
10236 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10237 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10238
10239 return (GOOD);
10240}
10241
10242
10243static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10244{
10245 word Info;
10246
10247 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10248 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10249
10250 Info = GOOD;
10251 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10252 && (plci->dtmf_parameter_length != 0))
10253 {
10254 switch (plci->adjust_b_state)
10255 {
10256 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10257 plci->internal_command = plci->adjust_b_command;
10258 if (plci->sig_req)
10259 {
10260 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10261 break;
10262 }
10263 dtmf_parameter_write (plci);
10264 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10265 break;
10266 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10267 if ((Rc != OK) && (Rc != OK_FC))
10268 {
10269 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10270 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10271 Info = _WRONG_STATE;
10272 break;
10273 }
10274 break;
10275 }
10276 }
10277 return (Info);
10278}
10279
10280
10281/*------------------------------------------------------------------*/
10282/* Line interconnect facilities */
10283/*------------------------------------------------------------------*/
10284
10285
10286LI_CONFIG *li_config_table;
10287word li_total_channels;
10288
10289
10290/*------------------------------------------------------------------*/
10291/* translate a CHI information element to a channel number */
10292/* returns 0xff - any channel */
10293/* 0xfe - chi wrong coding */
10294/* 0xfd - D-channel */
10295/* 0x00 - no channel */
10296/* else channel number / PRI: timeslot */
10297/* if channels is provided we accept more than one channel. */
10298/*------------------------------------------------------------------*/
10299
10300static byte chi_to_channel (byte *chi, dword *pchannelmap)
10301{
10302 int p;
10303 int i;
10304 dword map;
10305 byte excl;
10306 byte ofs;
10307 byte ch;
10308
10309 if (pchannelmap) *pchannelmap = 0;
10310 if(!chi[0]) return 0xff;
10311 excl = 0;
10312
10313 if(chi[1] & 0x20) {
10314 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10315 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10316 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10317 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10318 if(chi[1] &0x08) excl = 0x40;
10319
10320 /* int. id present */
10321 if(chi[1] &0x40) {
10322 p=i+1;
10323 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10324 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10325 }
10326
10327 /* coding standard, Number/Map, Channel Type */
10328 p=i+1;
10329 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10330 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10331 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10332
10333 /* Number/Map */
10334 if(chi[p] &0x10) {
10335
10336 /* map */
10337 if((chi[0]-p)==4) ofs = 0;
10338 else if((chi[0]-p)==3) ofs = 1;
10339 else return 0xfe;
10340 ch = 0;
10341 map = 0;
10342 for(i=0; i<4 && p<chi[0]; i++) {
10343 p++;
10344 ch += 8;
10345 map <<= 8;
10346 if(chi[p]) {
10347 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10348 map |= chi[p];
10349 }
10350 }
10351 ch += ofs;
10352 map <<= ofs;
10353 }
10354 else {
10355
10356 /* number */
10357 p=i+1;
10358 ch = chi[p] &0x3f;
10359 if(pchannelmap) {
10360 if((byte)(chi[0]-p)>30) return 0xfe;
10361 map = 0;
10362 for(i=p; i<=chi[0]; i++) {
10363 if ((chi[i] &0x7f) > 31) return 0xfe;
10364 map |= (1L << (chi[i] &0x7f));
10365 }
10366 }
10367 else {
10368 if(p!=chi[0]) return 0xfe;
10369 if (ch > 31) return 0xfe;
10370 map = (1L << ch);
10371 }
10372 if(chi[p] &0x40) return 0xfe;
10373 }
10374 if (pchannelmap) *pchannelmap = map;
10375 else if (map != ((dword)(1L << ch))) return 0xfe;
10376 return (byte)(excl | ch);
10377 }
10378 else { /* not PRI */
10379 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10380 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10381 if(chi[1] &0x08) excl = 0x40;
10382
10383 switch(chi[1] |0x98) {
10384 case 0x98: return 0;
10385 case 0x99:
10386 if (pchannelmap) *pchannelmap = 2;
10387 return excl |1;
10388 case 0x9a:
10389 if (pchannelmap) *pchannelmap = 4;
10390 return excl |2;
10391 case 0x9b: return 0xff;
10392 case 0x9c: return 0xfd; /* d-ch */
10393 default: return 0xfe;
10394 }
10395 }
10396}
10397
10398
10399static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10400{
10401 DIVA_CAPI_ADAPTER *a;
10402 PLCI *splci;
10403 byte old_id;
10404
10405 a = plci->adapter;
10406 old_id = plci->li_bchannel_id;
10407 if (a->li_pri)
10408 {
10409 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10410 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10411 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10412 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10413 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10414 }
10415 else
10416 {
10417 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10418 {
10419 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10420 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10421 plci->li_bchannel_id = bchannel_id & 0x03;
10422 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10423 {
10424 splci = a->AdvSignalPLCI;
10425 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10426 {
10427 if ((splci->li_bchannel_id != 0)
10428 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10429 {
10430 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10431 }
10432 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10433 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10434 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10435 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10436 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10437 }
10438 }
10439 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10440 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10441 }
10442 }
10443 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10444 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10445 {
10446 mixer_clear_config (plci);
10447 }
10448 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10449 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10450 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10451}
10452
10453
10454static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10455{
10456 DIVA_CAPI_ADAPTER *a;
10457 PLCI *splci;
10458 byte ch, old_id;
10459
10460 a = plci->adapter;
10461 old_id = plci->li_bchannel_id;
10462 ch = chi_to_channel (chi, NULL);
10463 if (!(ch & 0x80))
10464 {
10465 if (a->li_pri)
10466 {
10467 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10468 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10469 plci->li_bchannel_id = (ch & 0x1f) + 1;
10470 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10471 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10472 }
10473 else
10474 {
10475 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10476 {
10477 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10478 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10479 plci->li_bchannel_id = ch & 0x1f;
10480 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10481 {
10482 splci = a->AdvSignalPLCI;
10483 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10484 {
10485 if ((splci->li_bchannel_id != 0)
10486 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10487 {
10488 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10489 }
10490 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10491 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10492 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10493 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10494 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10495 }
10496 }
10497 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10498 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10499 }
10500 }
10501 }
10502 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10503 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10504 {
10505 mixer_clear_config (plci);
10506 }
10507 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10508 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10509 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10510}
10511
10512
10513#define MIXER_MAX_DUMP_CHANNELS 34
10514
10515static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10516{
10517static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10518 word n, i, j;
10519 char *p;
10520 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10521
10522 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10523 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10524
10525 for (i = 0; i < li_total_channels; i++)
10526 {
10527 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10528 if (li_config_table[i].chflags != 0)
10529 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10530 else
10531 {
10532 for (j = 0; j < li_total_channels; j++)
10533 {
10534 if (((li_config_table[i].flag_table[j]) != 0)
10535 || ((li_config_table[j].flag_table[i]) != 0))
10536 {
10537 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10538 }
10539 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10540 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10541 {
10542 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10543 }
10544 }
10545 }
10546 }
10547 for (i = 0; i < li_total_channels; i++)
10548 {
10549 for (j = 0; j < li_total_channels; j++)
10550 {
10551 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10552 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10553 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10554 }
10555 }
10556 for (n = 0; n < li_total_channels; n++)
10557 {
10558 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10559 {
10560 for (i = 0; i < li_total_channels; i++)
10561 {
10562 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10563 {
10564 for (j = 0; j < li_total_channels; j++)
10565 {
10566 li_config_table[i].coef_table[j] |=
10567 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10568 }
10569 }
10570 }
10571 }
10572 }
10573 for (i = 0; i < li_total_channels; i++)
10574 {
10575 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10576 {
10577 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10578 for (j = 0; j < li_total_channels; j++)
10579 {
10580 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10581 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10582 }
10583 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10584 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10585 }
10586 }
10587 for (i = 0; i < li_total_channels; i++)
10588 {
10589 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10590 {
10591 for (j = 0; j < li_total_channels; j++)
10592 {
10593 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10594 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10595 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10596 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10597 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10598 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10599 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10600 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10601 }
10602 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
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 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10609 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10610 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10611 }
10612 }
10613 }
10614 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10615 {
10616 for (j = 0; j < li_total_channels; j++)
10617 {
10618 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10619 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10620 }
10621 }
10622 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10623 {
10624 for (j = 0; j < li_total_channels; j++)
10625 {
10626 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10627 {
10628 for (n = 0; n < li_total_channels; n++)
10629 {
10630 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10631 {
10632 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10633 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10634 {
10635 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10636 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10637 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10638 }
10639 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10640 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10641 }
10642 }
10643 }
10644 }
10645 }
10646 }
10647 }
10648 for (i = 0; i < li_total_channels; i++)
10649 {
10650 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10651 {
10652 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10653 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10654 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10655 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10656 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10657 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10658 for (j = 0; j < li_total_channels; j++)
10659 {
10660 if ((li_config_table[i].flag_table[j] &
10661 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10662 || (li_config_table[j].flag_table[i] &
10663 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10664 {
10665 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10666 }
10667 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10668 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10669 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10670 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10671 }
10672 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10673 {
10674 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10675 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10676 }
10677 }
10678 }
10679 for (i = 0; i < li_total_channels; i++)
10680 {
10681 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10682 {
10683 j = 0;
10684 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10685 j++;
10686 if (j < li_total_channels)
10687 {
10688 for (j = 0; j < li_total_channels; j++)
10689 {
10690 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10691 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10692 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10693 }
10694 }
10695 }
10696 }
10697 n = li_total_channels;
10698 if (n > MIXER_MAX_DUMP_CHANNELS)
10699 n = MIXER_MAX_DUMP_CHANNELS;
10700 p = hex_line;
10701 for (j = 0; j < n; j++)
10702 {
10703 if ((j & 0x7) == 0)
10704 *(p++) = ' ';
10705 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10706 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10707 }
10708 *p = '\0';
10709 dbug (1, dprintf ("[%06lx] CURRENT %s",
10710 (dword)(UnMapController (a->Id)), (char *) hex_line));
10711 p = hex_line;
10712 for (j = 0; j < n; j++)
10713 {
10714 if ((j & 0x7) == 0)
10715 *(p++) = ' ';
10716 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10717 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10718 }
10719 *p = '\0';
10720 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10721 (dword)(UnMapController (a->Id)), (char *) hex_line));
10722 p = hex_line;
10723 for (j = 0; j < n; j++)
10724 {
10725 if ((j & 0x7) == 0)
10726 *(p++) = ' ';
10727 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10728 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10729 }
10730 *p = '\0';
10731 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10732 (dword)(UnMapController (a->Id)), (char *) hex_line));
10733 for (i = 0; i < n; i++)
10734 {
10735 p = hex_line;
10736 for (j = 0; j < n; j++)
10737 {
10738 if ((j & 0x7) == 0)
10739 *(p++) = ' ';
10740 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10741 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10742 }
10743 *p = '\0';
10744 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10745 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10746 }
10747 for (i = 0; i < n; i++)
10748 {
10749 p = hex_line;
10750 for (j = 0; j < n; j++)
10751 {
10752 if ((j & 0x7) == 0)
10753 *(p++) = ' ';
10754 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10755 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10756 }
10757 *p = '\0';
10758 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10759 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10760 }
10761}
10762
10763
10764static struct
10765{
10766 byte mask;
10767 byte line_flags;
10768} mixer_write_prog_pri[] =
10769{
10770 { LI_COEF_CH_CH, 0 },
10771 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10772 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10773 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10774};
10775
10776static struct
10777{
10778 byte from_ch;
10779 byte to_ch;
10780 byte mask;
10781 byte xconnect_override;
10782} mixer_write_prog_bri[] =
10783{
10784 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10785 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10786 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10787 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10788 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10789 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10790 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10791 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10792 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10793 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10794 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10795 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10796 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10797 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10798 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10799 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10800 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10801 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10802 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10803 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10804 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10805 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10806 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10807 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10808 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10809 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10810 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10811 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10812 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10813 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10814 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10815 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10816 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10817 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10818 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10819 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10820};
10821
10822static byte mixer_swapped_index_bri[] =
10823{
10824 18, /* B to B */
10825 19, /* Alt B to B */
10826 20, /* PC to B */
10827 21, /* Alt PC to B */
10828 22, /* IC to B */
10829 23, /* Alt IC to B */
10830 24, /* B to PC */
10831 25, /* Alt B to PC */
10832 26, /* PC to PC */
10833 27, /* Alt PC to PC */
10834 28, /* IC to PC */
10835 29, /* Alt IC to PC */
10836 30, /* B to IC */
10837 31, /* Alt B to IC */
10838 32, /* PC to IC */
10839 33, /* Alt PC to IC */
10840 34, /* IC to IC */
10841 35, /* Alt IC to IC */
10842 0, /* Alt B to Alt B */
10843 1, /* B to Alt B */
10844 2, /* Alt PC to Alt B */
10845 3, /* PC to Alt B */
10846 4, /* Alt IC to Alt B */
10847 5, /* IC to Alt B */
10848 6, /* Alt B to Alt PC */
10849 7, /* B to Alt PC */
10850 8, /* Alt PC to Alt PC */
10851 9, /* PC to Alt PC */
10852 10, /* Alt IC to Alt PC */
10853 11, /* IC to Alt PC */
10854 12, /* Alt B to Alt IC */
10855 13, /* B to Alt IC */
10856 14, /* Alt PC to Alt IC */
10857 15, /* PC to Alt IC */
10858 16, /* Alt IC to Alt IC */
10859 17 /* IC to Alt IC */
10860};
10861
10862static struct
10863{
10864 byte mask;
10865 byte from_pc;
10866 byte to_pc;
10867} xconnect_write_prog[] =
10868{
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010869 { LI_COEF_CH_CH, false, false },
10870 { LI_COEF_CH_PC, false, true },
10871 { LI_COEF_PC_CH, true, false },
10872 { LI_COEF_PC_PC, true, true }
Linus Torvalds1da177e2005-04-16 15:20:36 -070010873};
10874
10875
10876static void xconnect_query_addresses (PLCI *plci)
10877{
10878 DIVA_CAPI_ADAPTER *a;
10879 word w, ch;
10880 byte *p;
10881
10882 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10883 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10884 (char *)(FILE_), __LINE__));
10885
10886 a = plci->adapter;
10887 if (a->li_pri && ((plci->li_bchannel_id == 0)
10888 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10889 {
10890 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10891 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10892 (char *)(FILE_), __LINE__));
10893 return;
10894 }
10895 p = plci->internal_req_buffer;
10896 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10897 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10898 w = ch;
10899 *(p++) = (byte) w;
10900 *(p++) = (byte)(w >> 8);
10901 w = ch | XCONNECT_CHANNEL_PORT_PC;
10902 *(p++) = (byte) w;
10903 *(p++) = (byte)(w >> 8);
10904 plci->NData[0].P = plci->internal_req_buffer;
10905 plci->NData[0].PLength = p - plci->internal_req_buffer;
10906 plci->NL.X = plci->NData;
10907 plci->NL.ReqCh = 0;
10908 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10909 plci->adapter->request (&plci->NL);
10910}
10911
10912
10913static void xconnect_write_coefs (PLCI *plci, word internal_command)
10914{
10915
10916 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10917 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10918 (char *)(FILE_), __LINE__, internal_command));
10919
10920 plci->li_write_command = internal_command;
10921 plci->li_write_channel = 0;
10922}
10923
10924
10925static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10926{
10927 DIVA_CAPI_ADAPTER *a;
10928 word w, n, i, j, r, s, to_ch;
10929 dword d;
10930 byte *p;
10931 struct xconnect_transfer_address_s *transfer_address;
10932 byte ch_map[MIXER_CHANNELS_BRI];
10933
10934 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10935 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10936
10937 a = plci->adapter;
10938 if ((plci->li_bchannel_id == 0)
10939 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10940 {
10941 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10942 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010943 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010944 }
10945 i = a->li_base + (plci->li_bchannel_id - 1);
10946 j = plci->li_write_channel;
10947 p = plci->internal_req_buffer;
10948 if (j != 0)
10949 {
10950 if ((Rc != OK) && (Rc != OK_FC))
10951 {
10952 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10953 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010954 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010955 }
10956 }
10957 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10958 {
10959 r = 0;
10960 s = 0;
10961 if (j < li_total_channels)
10962 {
10963 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10964 {
10965 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10966 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10967 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10968 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10969 }
10970 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10971 while ((j < li_total_channels)
10972 && ((r == 0)
10973 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10974 || (!li_config_table[j].adapter->li_pri
10975 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10976 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10977 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10978 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10979 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10980 || ((li_config_table[j].adapter->li_base != a->li_base)
10981 && !(r & s &
10982 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10983 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10984 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10985 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10986 {
10987 j++;
10988 if (j < li_total_channels)
10989 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10990 }
10991 }
10992 if (j < li_total_channels)
10993 {
10994 plci->internal_command = plci->li_write_command;
10995 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080010996 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010997 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10998 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10999 do
11000 {
11001 if (li_config_table[j].adapter->li_base != a->li_base)
11002 {
11003 r &= s &
11004 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11005 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11006 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11007 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11008 }
11009 n = 0;
11010 do
11011 {
11012 if (r & xconnect_write_prog[n].mask)
11013 {
11014 if (xconnect_write_prog[n].from_pc)
11015 transfer_address = &(li_config_table[j].send_pc);
11016 else
11017 transfer_address = &(li_config_table[j].send_b);
11018 d = transfer_address->card_address.low;
11019 *(p++) = (byte) d;
11020 *(p++) = (byte)(d >> 8);
11021 *(p++) = (byte)(d >> 16);
11022 *(p++) = (byte)(d >> 24);
11023 d = transfer_address->card_address.high;
11024 *(p++) = (byte) d;
11025 *(p++) = (byte)(d >> 8);
11026 *(p++) = (byte)(d >> 16);
11027 *(p++) = (byte)(d >> 24);
11028 d = transfer_address->offset;
11029 *(p++) = (byte) d;
11030 *(p++) = (byte)(d >> 8);
11031 *(p++) = (byte)(d >> 16);
11032 *(p++) = (byte)(d >> 24);
11033 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11034 *(p++) = (byte) w;
11035 *(p++) = (byte)(w >> 8);
11036 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11037 (li_config_table[i].adapter->u_law ?
11038 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11039 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11040 *(p++) = (byte) w;
11041 *(p++) = (byte) 0;
11042 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11043 }
11044 n++;
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011045 } while ((n < ARRAY_SIZE(xconnect_write_prog))
Linus Torvalds1da177e2005-04-16 15:20:36 -070011046 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011047 if (n == ARRAY_SIZE(xconnect_write_prog))
Linus Torvalds1da177e2005-04-16 15:20:36 -070011048 {
11049 do
11050 {
11051 j++;
11052 if (j < li_total_channels)
11053 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11054 } while ((j < li_total_channels)
11055 && ((r == 0)
11056 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11057 || (!li_config_table[j].adapter->li_pri
11058 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11059 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11060 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11061 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11062 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11063 || ((li_config_table[j].adapter->li_base != a->li_base)
11064 && !(r & s &
11065 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11066 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11067 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11068 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11069 }
11070 } while ((j < li_total_channels)
11071 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11072 }
11073 else if (j == li_total_channels)
11074 {
11075 plci->internal_command = plci->li_write_command;
11076 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011077 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011078 if (a->li_pri)
11079 {
11080 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11081 w = 0;
11082 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11083 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11084 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11085 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11086 *(p++) = (byte) w;
11087 *(p++) = (byte)(w >> 8);
11088 }
11089 else
11090 {
11091 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11092 w = 0;
11093 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11094 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11095 {
11096 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11097 }
11098 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11099 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11100 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11101 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11102 *(p++) = (byte) w;
11103 *(p++) = (byte)(w >> 8);
11104 for (j = 0; j < sizeof(ch_map); j += 2)
11105 {
11106 if (plci->li_bchannel_id == 2)
11107 {
11108 ch_map[j] = (byte)(j+1);
11109 ch_map[j+1] = (byte) j;
11110 }
11111 else
11112 {
11113 ch_map[j] = (byte) j;
11114 ch_map[j+1] = (byte)(j+1);
11115 }
11116 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011117 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011118 {
11119 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11120 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11121 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11122 {
11123 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11124 mixer_write_prog_bri[n].xconnect_override :
11125 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11126 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11127 {
11128 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11129 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11130 }
11131 }
11132 else
11133 {
11134 *p = 0x00;
11135 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11136 {
11137 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11138 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11139 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11140 }
11141 }
11142 p++;
11143 }
11144 }
11145 j = li_total_channels + 1;
11146 }
11147 }
11148 else
11149 {
11150 if (j <= li_total_channels)
11151 {
11152 plci->internal_command = plci->li_write_command;
11153 if (plci_nl_busy (plci))
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011154 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011155 if (j < a->li_base)
11156 j = a->li_base;
11157 if (a->li_pri)
11158 {
11159 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11160 w = 0;
11161 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11162 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11163 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11164 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11165 *(p++) = (byte) w;
11166 *(p++) = (byte)(w >> 8);
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011167 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011168 {
11169 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11170 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11171 {
11172 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11173 if (w & mixer_write_prog_pri[n].mask)
11174 {
11175 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11176 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11177 }
11178 else
11179 *(p++) = 0x00;
11180 }
11181 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11182 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11183 {
11184 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11185 if (w & mixer_write_prog_pri[n].mask)
11186 {
11187 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11188 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11189 }
11190 else
11191 *(p++) = 0x00;
11192 }
11193 }
11194 }
11195 else
11196 {
11197 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11198 w = 0;
11199 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11200 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11201 {
11202 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11203 }
11204 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11205 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11206 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11207 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11208 *(p++) = (byte) w;
11209 *(p++) = (byte)(w >> 8);
11210 for (j = 0; j < sizeof(ch_map); j += 2)
11211 {
11212 if (plci->li_bchannel_id == 2)
11213 {
11214 ch_map[j] = (byte)(j+1);
11215 ch_map[j+1] = (byte) j;
11216 }
11217 else
11218 {
11219 ch_map[j] = (byte) j;
11220 ch_map[j+1] = (byte)(j+1);
11221 }
11222 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080011223 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011224 {
11225 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11226 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11227 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11228 {
11229 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11230 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11231 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11232 }
11233 else
11234 {
11235 *p = 0x00;
11236 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11237 {
11238 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11239 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11240 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11241 }
11242 }
11243 p++;
11244 }
11245 }
11246 j = li_total_channels + 1;
11247 }
11248 }
11249 plci->li_write_channel = j;
11250 if (p != plci->internal_req_buffer)
11251 {
11252 plci->NData[0].P = plci->internal_req_buffer;
11253 plci->NData[0].PLength = p - plci->internal_req_buffer;
11254 plci->NL.X = plci->NData;
11255 plci->NL.ReqCh = 0;
11256 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11257 plci->adapter->request (&plci->NL);
11258 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011259 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011260}
11261
11262
11263static void mixer_notify_update (PLCI *plci, byte others)
11264{
11265 DIVA_CAPI_ADAPTER *a;
11266 word i, w;
11267 PLCI *notify_plci;
11268 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11269
11270 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11271 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11272 (char *)(FILE_), __LINE__, others));
11273
11274 a = plci->adapter;
11275 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11276 {
11277 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011278 plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011279 i = 0;
11280 do
11281 {
11282 notify_plci = NULL;
11283 if (others)
11284 {
11285 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11286 i++;
11287 if (i < li_total_channels)
11288 notify_plci = li_config_table[i++].plci;
11289 }
11290 else
11291 {
11292 if ((plci->li_bchannel_id != 0)
11293 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11294 {
11295 notify_plci = plci;
11296 }
11297 }
11298 if ((notify_plci != NULL)
11299 && !notify_plci->li_notify_update
11300 && (notify_plci->appl != NULL)
11301 && (notify_plci->State)
11302 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11303 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011304 notify_plci->li_notify_update = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011305 ((CAPI_MSG *) msg)->header.length = 18;
11306 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11307 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11308 ((CAPI_MSG *) msg)->header.number = 0;
11309 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11310 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11311 ((CAPI_MSG *) msg)->header.ncci = 0;
11312 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11313 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11314 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11315 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11316 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11317 if (w != _QUEUE_FULL)
11318 {
11319 if (w != 0)
11320 {
11321 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11322 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11323 (char *)(FILE_), __LINE__,
11324 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11325 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011326 notify_plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011327 }
11328 }
11329 } while (others && (notify_plci != NULL));
11330 if (others)
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011331 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011332 }
11333}
11334
11335
11336static void mixer_clear_config (PLCI *plci)
11337{
11338 DIVA_CAPI_ADAPTER *a;
11339 word i, j;
11340
11341 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11342 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11343 (char *)(FILE_), __LINE__));
11344
Richard Knutsson986c4bb2007-02-12 00:53:24 -080011345 plci->li_notify_update = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011346 plci->li_plci_b_write_pos = 0;
11347 plci->li_plci_b_read_pos = 0;
11348 plci->li_plci_b_req_pos = 0;
11349 a = plci->adapter;
11350 if ((plci->li_bchannel_id != 0)
11351 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11352 {
11353 i = a->li_base + (plci->li_bchannel_id - 1);
11354 li_config_table[i].curchnl = 0;
11355 li_config_table[i].channel = 0;
11356 li_config_table[i].chflags = 0;
11357 for (j = 0; j < li_total_channels; j++)
11358 {
11359 li_config_table[j].flag_table[i] = 0;
11360 li_config_table[i].flag_table[j] = 0;
11361 li_config_table[i].coef_table[j] = 0;
11362 li_config_table[j].coef_table[i] = 0;
11363 }
11364 if (!a->li_pri)
11365 {
11366 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11367 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11368 {
11369 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11370 li_config_table[i].curchnl = 0;
11371 li_config_table[i].channel = 0;
11372 li_config_table[i].chflags = 0;
11373 for (j = 0; j < li_total_channels; j++)
11374 {
11375 li_config_table[i].flag_table[j] = 0;
11376 li_config_table[j].flag_table[i] = 0;
11377 li_config_table[i].coef_table[j] = 0;
11378 li_config_table[j].coef_table[i] = 0;
11379 }
11380 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11381 {
11382 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11383 li_config_table[i].curchnl = 0;
11384 li_config_table[i].channel = 0;
11385 li_config_table[i].chflags = 0;
11386 for (j = 0; j < li_total_channels; j++)
11387 {
11388 li_config_table[i].flag_table[j] = 0;
11389 li_config_table[j].flag_table[i] = 0;
11390 li_config_table[i].coef_table[j] = 0;
11391 li_config_table[j].coef_table[i] = 0;
11392 }
11393 }
11394 }
11395 }
11396 }
11397}
11398
11399
11400static void mixer_prepare_switch (dword Id, PLCI *plci)
11401{
11402
11403 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11404 UnMapId (Id), (char *)(FILE_), __LINE__));
11405
11406 do
11407 {
11408 mixer_indication_coefs_set (Id, plci);
11409 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11410}
11411
11412
11413static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11414{
11415 DIVA_CAPI_ADAPTER *a;
11416 word i, j;
11417
11418 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11419 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11420
11421 a = plci->adapter;
11422 if ((plci->li_bchannel_id != 0)
11423 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11424 {
11425 i = a->li_base + (plci->li_bchannel_id - 1);
11426 for (j = 0; j < li_total_channels; j++)
11427 {
11428 li_config_table[i].coef_table[j] &= 0xf;
11429 li_config_table[j].coef_table[i] &= 0xf;
11430 }
11431 if (!a->li_pri)
11432 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11433 }
11434 return (GOOD);
11435}
11436
11437
11438static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11439{
11440 DIVA_CAPI_ADAPTER *a;
11441 word Info;
11442
11443 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11444 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11445
11446 Info = GOOD;
11447 a = plci->adapter;
11448 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11449 && (plci->li_bchannel_id != 0)
11450 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11451 {
11452 switch (plci->adjust_b_state)
11453 {
11454 case ADJUST_B_RESTORE_MIXER_1:
11455 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11456 {
11457 plci->internal_command = plci->adjust_b_command;
11458 if (plci_nl_busy (plci))
11459 {
11460 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11461 break;
11462 }
11463 xconnect_query_addresses (plci);
11464 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11465 break;
11466 }
11467 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468 Rc = OK;
11469 case ADJUST_B_RESTORE_MIXER_2:
11470 case ADJUST_B_RESTORE_MIXER_3:
11471 case ADJUST_B_RESTORE_MIXER_4:
11472 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11473 {
11474 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11475 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11476 Info = _WRONG_STATE;
11477 break;
11478 }
11479 if (Rc == OK)
11480 {
11481 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11482 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11483 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11484 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11485 }
11486 else if (Rc == 0)
11487 {
11488 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11489 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11490 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11491 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11492 }
11493 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11494 {
11495 plci->internal_command = plci->adjust_b_command;
11496 break;
11497 }
11498 case ADJUST_B_RESTORE_MIXER_5:
11499 xconnect_write_coefs (plci, plci->adjust_b_command);
11500 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11501 Rc = OK;
11502 case ADJUST_B_RESTORE_MIXER_6:
11503 if (!xconnect_write_coefs_process (Id, plci, Rc))
11504 {
11505 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11506 UnMapId (Id), (char *)(FILE_), __LINE__));
11507 Info = _FACILITY_NOT_SUPPORTED;
11508 break;
11509 }
11510 if (plci->internal_command)
11511 break;
11512 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11513 case ADJUST_B_RESTORE_MIXER_7:
11514 break;
11515 }
11516 }
11517 return (Info);
11518}
11519
11520
11521static void mixer_command (dword Id, PLCI *plci, byte Rc)
11522{
11523 DIVA_CAPI_ADAPTER *a;
11524 word i, internal_command, Info;
11525
11526 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11527 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11528 plci->li_cmd));
11529
11530 Info = GOOD;
11531 a = plci->adapter;
11532 internal_command = plci->internal_command;
11533 plci->internal_command = 0;
11534 switch (plci->li_cmd)
11535 {
11536 case LI_REQ_CONNECT:
11537 case LI_REQ_DISCONNECT:
11538 case LI_REQ_SILENT_UPDATE:
11539 switch (internal_command)
11540 {
11541 default:
11542 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11543 {
11544 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11545 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11546 }
11547 case MIXER_COMMAND_1:
11548 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11549 {
11550 if (adjust_b_process (Id, plci, Rc) != GOOD)
11551 {
11552 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11553 UnMapId (Id), (char *)(FILE_), __LINE__));
11554 Info = _FACILITY_NOT_SUPPORTED;
11555 break;
11556 }
11557 if (plci->internal_command)
11558 return;
11559 }
11560 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11561 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11562 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11563 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11564 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11565 {
11566 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11567 }
11568 else
11569 {
11570 do
11571 {
11572 mixer_indication_coefs_set (Id, plci);
11573 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11574 }
11575 case MIXER_COMMAND_2:
11576 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11577 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11578 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11579 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11580 {
11581 if (!xconnect_write_coefs_process (Id, plci, Rc))
11582 {
11583 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11584 UnMapId (Id), (char *)(FILE_), __LINE__));
11585 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11586 {
11587 do
11588 {
11589 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11590 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11591 i = (plci->li_plci_b_write_pos == 0) ?
11592 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11593 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11594 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11595 }
11596 Info = _FACILITY_NOT_SUPPORTED;
11597 break;
11598 }
11599 if (plci->internal_command)
11600 return;
11601 }
11602 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11603 {
11604 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11605 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11606 }
11607 case MIXER_COMMAND_3:
11608 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11609 {
11610 if (adjust_b_process (Id, plci, Rc) != GOOD)
11611 {
11612 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11613 UnMapId (Id), (char *)(FILE_), __LINE__));
11614 Info = _FACILITY_NOT_SUPPORTED;
11615 break;
11616 }
11617 if (plci->internal_command)
11618 return;
11619 }
11620 break;
11621 }
11622 break;
11623 }
11624 if ((plci->li_bchannel_id == 0)
11625 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11626 {
11627 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11628 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11629 }
11630 else
11631 {
11632 i = a->li_base + (plci->li_bchannel_id - 1);
11633 li_config_table[i].curchnl = plci->li_channel_bits;
11634 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11635 {
11636 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11637 li_config_table[i].curchnl = plci->li_channel_bits;
11638 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11639 {
11640 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11641 li_config_table[i].curchnl = plci->li_channel_bits;
11642 }
11643 }
11644 }
11645}
11646
11647
11648static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11649 dword plci_b_id, byte connect, dword li_flags)
11650{
11651 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11652 PLCI *plci_b;
11653 DIVA_CAPI_ADAPTER *a_b;
11654
11655 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11656 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11657 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11658 if (!a->li_pri && (plci->tel == ADV_VOICE)
11659 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11660 {
11661 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11662 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11663 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11664 }
11665 else
11666 {
11667 ch_a_v = ch_a;
11668 ch_a_s = ch_a;
11669 }
11670 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11671 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11672 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11673 {
11674 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11675 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11676 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11677 }
11678 else
11679 {
11680 ch_b_v = ch_b;
11681 ch_b_s = ch_b;
11682 }
11683 if (connect)
11684 {
11685 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11686 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11687 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11688 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11689 }
11690 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11691 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11692 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11693 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11694 if (ch_a_v == ch_b_v)
11695 {
11696 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11697 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11698 }
11699 else
11700 {
11701 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11702 {
11703 for (i = 0; i < li_total_channels; i++)
11704 {
11705 if (i != ch_a_v)
11706 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11707 }
11708 }
11709 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11710 {
11711 for (i = 0; i < li_total_channels; i++)
11712 {
11713 if (i != ch_a_s)
11714 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11715 }
11716 }
11717 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11718 {
11719 for (i = 0; i < li_total_channels; i++)
11720 {
11721 if (i != ch_a_v)
11722 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11723 }
11724 }
11725 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11726 {
11727 for (i = 0; i < li_total_channels; i++)
11728 {
11729 if (i != ch_a_s)
11730 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11731 }
11732 }
11733 }
11734 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11735 {
11736 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11737 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11738 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11739 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11740 }
11741 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11742 {
11743 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11744 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11745 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11746 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11747 }
11748 if (li_flags & LI_FLAG_MONITOR_A)
11749 {
11750 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11751 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11752 }
11753 if (li_flags & LI_FLAG_MONITOR_B)
11754 {
11755 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11756 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11757 }
11758 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11759 {
11760 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11761 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11762 }
11763 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11764 {
11765 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11766 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11767 }
11768 if (li_flags & LI_FLAG_MIX_A)
11769 {
11770 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11771 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11772 }
11773 if (li_flags & LI_FLAG_MIX_B)
11774 {
11775 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11776 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11777 }
11778 if (ch_a_v != ch_a_s)
11779 {
11780 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11781 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11782 }
11783 if (ch_b_v != ch_b_s)
11784 {
11785 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11786 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11787 }
11788}
11789
11790
11791static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11792 dword plci_b_id, byte connect, dword li_flags)
11793{
11794 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11795 PLCI *plci_b;
11796 DIVA_CAPI_ADAPTER *a_b;
11797
11798 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11799 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11800 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11801 if (!a->li_pri && (plci->tel == ADV_VOICE)
11802 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11803 {
11804 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11805 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11806 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11807 }
11808 else
11809 {
11810 ch_a_v = ch_a;
11811 ch_a_s = ch_a;
11812 }
11813 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11814 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11815 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11816 {
11817 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11818 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11819 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11820 }
11821 else
11822 {
11823 ch_b_v = ch_b;
11824 ch_b_s = ch_b;
11825 }
11826 if (connect)
11827 {
11828 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11829 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11830 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11831 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11832 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11833 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11834 }
11835 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11836 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11837 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11843 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11844 {
11845 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11846 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11847 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11848 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11849 }
11850 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11851 {
11852 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11853 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11854 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856 }
11857 if (li_flags & LI2_FLAG_MONITOR_B)
11858 {
11859 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11860 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11861 }
11862 if (li_flags & LI2_FLAG_MIX_B)
11863 {
11864 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11865 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11866 }
11867 if (li_flags & LI2_FLAG_MONITOR_X)
11868 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11869 if (li_flags & LI2_FLAG_MIX_X)
11870 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11871 if (li_flags & LI2_FLAG_LOOP_B)
11872 {
11873 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11874 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11875 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11876 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11877 }
11878 if (li_flags & LI2_FLAG_LOOP_PC)
11879 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11880 if (li_flags & LI2_FLAG_LOOP_X)
11881 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11882 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11883 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11884 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11885 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11886 if (ch_a_v != ch_a_s)
11887 {
11888 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11889 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11890 }
11891 if (ch_b_v != ch_b_s)
11892 {
11893 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11894 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11895 }
11896}
11897
11898
11899static word li_check_main_plci (dword Id, PLCI *plci)
11900{
11901 if (plci == NULL)
11902 {
11903 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11904 UnMapId (Id), (char *)(FILE_), __LINE__));
11905 return (_WRONG_IDENTIFIER);
11906 }
11907 if (!plci->State
11908 || !plci->NL.Id || plci->nl_remove_id
11909 || (plci->li_bchannel_id == 0))
11910 {
11911 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11912 UnMapId (Id), (char *)(FILE_), __LINE__));
11913 return (_WRONG_STATE);
11914 }
11915 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11916 return (GOOD);
11917}
11918
11919
11920static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11921 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11922{
11923 byte ctlr_b;
11924 PLCI *plci_b;
11925
11926 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11927 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11928 {
11929 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11930 UnMapId (Id), (char *)(FILE_), __LINE__));
11931 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11932 return (NULL);
11933 }
11934 ctlr_b = 0;
11935 if ((plci_b_id & 0x7f) != 0)
11936 {
11937 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11938 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11939 ctlr_b = 0;
11940 }
11941 if ((ctlr_b == 0)
11942 || (((plci_b_id >> 8) & 0xff) == 0)
11943 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11944 {
11945 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11946 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11947 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11948 return (NULL);
11949 }
11950 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11951 if (!plci_b->State
11952 || !plci_b->NL.Id || plci_b->nl_remove_id
11953 || (plci_b->li_bchannel_id == 0))
11954 {
11955 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11956 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11957 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11958 return (NULL);
11959 }
11960 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11961 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11962 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11963 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11964 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11965 {
11966 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11967 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11968 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11969 return (NULL);
11970 }
11971 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11972 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11973 {
11974 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11975 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11976 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11977 return (NULL);
11978 }
11979 return (plci_b);
11980}
11981
11982
11983static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11984 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11985{
11986 byte ctlr_b;
11987 PLCI *plci_b;
11988
11989 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11990 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11991 {
11992 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11993 UnMapId (Id), (char *)(FILE_), __LINE__));
11994 PUT_WORD (p_result, _WRONG_STATE);
11995 return (NULL);
11996 }
11997 ctlr_b = 0;
11998 if ((plci_b_id & 0x7f) != 0)
11999 {
12000 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12001 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12002 ctlr_b = 0;
12003 }
12004 if ((ctlr_b == 0)
12005 || (((plci_b_id >> 8) & 0xff) == 0)
12006 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12007 {
12008 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12009 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12010 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12011 return (NULL);
12012 }
12013 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12014 if (!plci_b->State
12015 || !plci_b->NL.Id || plci_b->nl_remove_id
12016 || (plci_b->li_bchannel_id == 0)
12017 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12018 {
12019 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12020 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12021 PUT_WORD (p_result, _WRONG_STATE);
12022 return (NULL);
12023 }
12024 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12025 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12026 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12027 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12028 {
12029 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12030 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12031 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12032 return (NULL);
12033 }
12034 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12035 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12036 {
12037 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12038 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12039 PUT_WORD (p_result, _WRONG_STATE);
12040 return (NULL);
12041 }
12042 return (plci_b);
12043}
12044
12045
12046static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12047{
12048 word Info;
12049 word i;
12050 dword d, li_flags, plci_b_id;
12051 PLCI *plci_b;
12052 API_PARSE li_parms[3];
12053 API_PARSE li_req_parms[3];
12054 API_PARSE li_participant_struct[2];
12055 API_PARSE li_participant_parms[3];
12056 word participant_parms_pos;
12057 byte result_buffer[32];
12058 byte *result;
12059 word result_pos;
12060 word plci_b_write_pos;
12061
12062 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12063 UnMapId (Id), (char *)(FILE_), __LINE__));
12064
12065 Info = GOOD;
12066 result = result_buffer;
12067 result_buffer[0] = 0;
12068 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12069 {
12070 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12071 UnMapId (Id), (char *)(FILE_), __LINE__));
12072 Info = _FACILITY_NOT_SUPPORTED;
12073 }
12074 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12075 {
12076 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12077 UnMapId (Id), (char *)(FILE_), __LINE__));
12078 Info = _WRONG_MESSAGE_FORMAT;
12079 }
12080 else
12081 {
12082 result_buffer[0] = 3;
12083 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12084 result_buffer[3] = 0;
12085 switch (GET_WORD (li_parms[0].info))
12086 {
12087 case LI_GET_SUPPORTED_SERVICES:
12088 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12089 {
12090 result_buffer[0] = 17;
12091 result_buffer[3] = 14;
12092 PUT_WORD (&result_buffer[4], GOOD);
12093 d = 0;
12094 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12095 d |= LI_CONFERENCING_SUPPORTED;
12096 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12097 d |= LI_MONITORING_SUPPORTED;
12098 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12099 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12100 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12101 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12102 PUT_DWORD (&result_buffer[6], d);
12103 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12104 {
12105 d = 0;
12106 for (i = 0; i < li_total_channels; i++)
12107 {
12108 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12109 && (li_config_table[i].adapter->li_pri
12110 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12111 {
12112 d++;
12113 }
12114 }
12115 }
12116 else
12117 {
12118 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12119 }
12120 PUT_DWORD (&result_buffer[10], d / 2);
12121 PUT_DWORD (&result_buffer[14], d);
12122 }
12123 else
12124 {
12125 result_buffer[0] = 25;
12126 result_buffer[3] = 22;
12127 PUT_WORD (&result_buffer[4], GOOD);
12128 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12129 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12130 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12131 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12132 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12133 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12134 d |= LI2_PC_LOOPING_SUPPORTED;
12135 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12136 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12137 PUT_DWORD (&result_buffer[6], d);
12138 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12139 PUT_DWORD (&result_buffer[10], d / 2);
12140 PUT_DWORD (&result_buffer[14], d - 1);
12141 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12142 {
12143 d = 0;
12144 for (i = 0; i < li_total_channels; i++)
12145 {
12146 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12147 && (li_config_table[i].adapter->li_pri
12148 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12149 {
12150 d++;
12151 }
12152 }
12153 }
12154 PUT_DWORD (&result_buffer[18], d / 2);
12155 PUT_DWORD (&result_buffer[22], d - 1);
12156 }
12157 break;
12158
12159 case LI_REQ_CONNECT:
12160 if (li_parms[1].length == 8)
12161 {
12162 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12163 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12164 {
12165 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12166 UnMapId (Id), (char *)(FILE_), __LINE__));
12167 Info = _WRONG_MESSAGE_FORMAT;
12168 break;
12169 }
12170 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12171 li_flags = GET_DWORD (li_req_parms[1].info);
12172 Info = li_check_main_plci (Id, plci);
12173 result_buffer[0] = 9;
12174 result_buffer[3] = 6;
12175 PUT_DWORD (&result_buffer[4], plci_b_id);
12176 PUT_WORD (&result_buffer[8], GOOD);
12177 if (Info != GOOD)
12178 break;
12179 result = plci->saved_msg.info;
12180 for (i = 0; i <= result_buffer[0]; i++)
12181 result[i] = result_buffer[i];
12182 plci_b_write_pos = plci->li_plci_b_write_pos;
12183 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12184 if (plci_b == NULL)
12185 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012186 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012187 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12188 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12189 plci->li_plci_b_write_pos = plci_b_write_pos;
12190 }
12191 else
12192 {
12193 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12194 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12195 {
12196 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12197 UnMapId (Id), (char *)(FILE_), __LINE__));
12198 Info = _WRONG_MESSAGE_FORMAT;
12199 break;
12200 }
12201 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12202 Info = li_check_main_plci (Id, plci);
12203 result_buffer[0] = 7;
12204 result_buffer[3] = 4;
12205 PUT_WORD (&result_buffer[4], Info);
12206 result_buffer[6] = 0;
12207 if (Info != GOOD)
12208 break;
12209 result = plci->saved_msg.info;
12210 for (i = 0; i <= result_buffer[0]; i++)
12211 result[i] = result_buffer[i];
12212 plci_b_write_pos = plci->li_plci_b_write_pos;
12213 participant_parms_pos = 0;
12214 result_pos = 7;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012215 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012216 while (participant_parms_pos < li_req_parms[1].length)
12217 {
12218 result[result_pos] = 6;
12219 result_pos += 7;
12220 PUT_DWORD (&result[result_pos - 6], 0);
12221 PUT_WORD (&result[result_pos - 2], GOOD);
12222 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12223 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12224 {
12225 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12226 UnMapId (Id), (char *)(FILE_), __LINE__));
12227 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12228 break;
12229 }
12230 if (api_parse (&li_participant_struct[0].info[1],
12231 li_participant_struct[0].length, "dd", li_participant_parms))
12232 {
12233 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12234 UnMapId (Id), (char *)(FILE_), __LINE__));
12235 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12236 break;
12237 }
12238 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12239 li_flags = GET_DWORD (li_participant_parms[1].info);
12240 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12241 if (sizeof(result) - result_pos < 7)
12242 {
12243 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12244 UnMapId (Id), (char *)(FILE_), __LINE__));
12245 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12246 break;
12247 }
12248 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12249 if (plci_b != NULL)
12250 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012251 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012252 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12253 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12254 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12255 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12256 }
12257 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12258 (&li_req_parms[1].info[1]));
12259 }
12260 result[0] = (byte)(result_pos - 1);
12261 result[3] = (byte)(result_pos - 4);
12262 result[6] = (byte)(result_pos - 7);
12263 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12264 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12265 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12266 {
12267 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12268 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12269 }
12270 else
12271 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12272 plci->li_plci_b_write_pos = plci_b_write_pos;
12273 }
12274 mixer_calculate_coefs (a);
12275 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012276 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012277 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12278 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12279 plci->command = 0;
12280 plci->li_cmd = GET_WORD (li_parms[0].info);
12281 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012282 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012283
12284 case LI_REQ_DISCONNECT:
12285 if (li_parms[1].length == 4)
12286 {
12287 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12288 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12289 {
12290 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12291 UnMapId (Id), (char *)(FILE_), __LINE__));
12292 Info = _WRONG_MESSAGE_FORMAT;
12293 break;
12294 }
12295 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12296 Info = li_check_main_plci (Id, plci);
12297 result_buffer[0] = 9;
12298 result_buffer[3] = 6;
12299 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12300 PUT_WORD (&result_buffer[8], GOOD);
12301 if (Info != GOOD)
12302 break;
12303 result = plci->saved_msg.info;
12304 for (i = 0; i <= result_buffer[0]; i++)
12305 result[i] = result_buffer[i];
12306 plci_b_write_pos = plci->li_plci_b_write_pos;
12307 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12308 if (plci_b == NULL)
12309 break;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012310 li_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012311 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12312 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12313 plci->li_plci_b_write_pos = plci_b_write_pos;
12314 }
12315 else
12316 {
12317 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12318 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12319 {
12320 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12321 UnMapId (Id), (char *)(FILE_), __LINE__));
12322 Info = _WRONG_MESSAGE_FORMAT;
12323 break;
12324 }
12325 Info = li_check_main_plci (Id, plci);
12326 result_buffer[0] = 7;
12327 result_buffer[3] = 4;
12328 PUT_WORD (&result_buffer[4], Info);
12329 result_buffer[6] = 0;
12330 if (Info != GOOD)
12331 break;
12332 result = plci->saved_msg.info;
12333 for (i = 0; i <= result_buffer[0]; i++)
12334 result[i] = result_buffer[i];
12335 plci_b_write_pos = plci->li_plci_b_write_pos;
12336 participant_parms_pos = 0;
12337 result_pos = 7;
12338 while (participant_parms_pos < li_req_parms[0].length)
12339 {
12340 result[result_pos] = 6;
12341 result_pos += 7;
12342 PUT_DWORD (&result[result_pos - 6], 0);
12343 PUT_WORD (&result[result_pos - 2], GOOD);
12344 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12345 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12346 {
12347 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12348 UnMapId (Id), (char *)(FILE_), __LINE__));
12349 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12350 break;
12351 }
12352 if (api_parse (&li_participant_struct[0].info[1],
12353 li_participant_struct[0].length, "d", li_participant_parms))
12354 {
12355 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12356 UnMapId (Id), (char *)(FILE_), __LINE__));
12357 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12358 break;
12359 }
12360 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12361 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12362 if (sizeof(result) - result_pos < 7)
12363 {
12364 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12365 UnMapId (Id), (char *)(FILE_), __LINE__));
12366 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12367 break;
12368 }
12369 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12370 if (plci_b != NULL)
12371 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012372 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012373 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12374 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12375 }
12376 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12377 (&li_req_parms[0].info[1]));
12378 }
12379 result[0] = (byte)(result_pos - 1);
12380 result[3] = (byte)(result_pos - 4);
12381 result[6] = (byte)(result_pos - 7);
12382 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12383 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12384 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12385 {
12386 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12387 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12388 }
12389 else
12390 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12391 plci->li_plci_b_write_pos = plci_b_write_pos;
12392 }
12393 mixer_calculate_coefs (a);
12394 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012395 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012396 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12397 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12398 plci->command = 0;
12399 plci->li_cmd = GET_WORD (li_parms[0].info);
12400 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012401 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012402
12403 case LI_REQ_SILENT_UPDATE:
12404 if (!plci || !plci->State
12405 || !plci->NL.Id || plci->nl_remove_id
12406 || (plci->li_bchannel_id == 0)
12407 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12408 {
12409 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12410 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012411 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012412 }
12413 plci_b_write_pos = plci->li_plci_b_write_pos;
12414 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12415 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12416 {
12417 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12418 UnMapId (Id), (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012419 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012420 }
12421 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12422 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12423 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12424 {
12425 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12426 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12427 }
12428 else
12429 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12430 plci->li_plci_b_write_pos = plci_b_write_pos;
12431 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12432 plci->command = 0;
12433 plci->li_cmd = GET_WORD (li_parms[0].info);
12434 start_internal_command (Id, plci, mixer_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012435 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012436
12437 default:
12438 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12439 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12440 Info = _FACILITY_NOT_SUPPORTED;
12441 }
12442 }
12443 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12444 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012445 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012446}
12447
12448
12449static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12450{
12451 dword d;
12452 DIVA_CAPI_ADAPTER *a;
12453 byte result[12];
12454
12455 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12456 UnMapId (Id), (char *)(FILE_), __LINE__));
12457
12458 a = plci->adapter;
12459 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12460 {
12461 do
12462 {
12463 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12464 if (!(d & LI_PLCI_B_SKIP_FLAG))
12465 {
12466 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12467 {
12468 if (d & LI_PLCI_B_DISC_FLAG)
12469 {
12470 result[0] = 5;
12471 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12472 result[3] = 2;
12473 PUT_WORD (&result[4], _LI_USER_INITIATED);
12474 }
12475 else
12476 {
12477 result[0] = 7;
12478 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12479 result[3] = 4;
12480 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12481 }
12482 }
12483 else
12484 {
12485 if (d & LI_PLCI_B_DISC_FLAG)
12486 {
12487 result[0] = 9;
12488 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12489 result[3] = 6;
12490 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12491 PUT_WORD (&result[8], _LI_USER_INITIATED);
12492 }
12493 else
12494 {
12495 result[0] = 7;
12496 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12497 result[3] = 4;
12498 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12499 }
12500 }
12501 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12502 "ws", SELECTOR_LINE_INTERCONNECT, result);
12503 }
12504 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12505 0 : plci->li_plci_b_read_pos + 1;
12506 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12507 }
12508}
12509
12510
12511static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12512{
12513 word i, j, ch;
12514 struct xconnect_transfer_address_s s, *p;
12515 DIVA_CAPI_ADAPTER *a;
12516
12517 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12518 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12519
12520 a = plci->adapter;
12521 i = 1;
12522 for (i = 1; i < length; i += 16)
12523 {
12524 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12525 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12526 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12527 ch = msg[i+12] | (msg[i+13] << 8);
12528 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12529 if (!a->li_pri && (plci->li_bchannel_id == 2))
12530 j = 1 - j;
12531 j += a->li_base;
12532 if (ch & XCONNECT_CHANNEL_PORT_PC)
12533 p = &(li_config_table[j].send_pc);
12534 else
12535 p = &(li_config_table[j].send_b);
12536 p->card_address.low = s.card_address.low;
12537 p->card_address.high = s.card_address.high;
12538 p->offset = s.offset;
12539 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12540 }
12541 if (plci->internal_command_queue[0]
12542 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12543 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12544 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12545 {
12546 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12547 if (!plci->internal_command)
12548 next_internal_command (Id, plci);
12549 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012550 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012551}
12552
12553
12554static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12555{
12556
12557 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12558 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12559
12560}
12561
12562
12563static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12564{
12565 word plci_b_write_pos;
12566
12567 plci_b_write_pos = plci->li_plci_b_write_pos;
12568 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12569 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12570 {
12571 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12572 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12573 (char *)(FILE_), __LINE__));
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012574 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012575 }
12576 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12577 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12578 plci->li_plci_b_write_pos = plci_b_write_pos;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012579 return (true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012580}
12581
12582
12583static void mixer_remove (PLCI *plci)
12584{
12585 DIVA_CAPI_ADAPTER *a;
12586 PLCI *notify_plci;
12587 dword plci_b_id;
12588 word i, j;
12589
12590 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12591 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12592 (char *)(FILE_), __LINE__));
12593
12594 a = plci->adapter;
12595 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12596 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12597 {
12598 if ((plci->li_bchannel_id != 0)
12599 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12600 {
12601 i = a->li_base + (plci->li_bchannel_id - 1);
12602 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12603 {
12604 for (j = 0; j < li_total_channels; j++)
12605 {
12606 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12607 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12608 {
12609 notify_plci = li_config_table[j].plci;
12610 if ((notify_plci != NULL)
12611 && (notify_plci != plci)
12612 && (notify_plci->appl != NULL)
12613 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12614 && (notify_plci->State)
12615 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12616 {
12617 mixer_notify_source_removed (notify_plci, plci_b_id);
12618 }
12619 }
12620 }
12621 mixer_clear_config (plci);
12622 mixer_calculate_coefs (a);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012623 mixer_notify_update (plci, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012624 }
12625 li_config_table[i].plci = NULL;
12626 plci->li_bchannel_id = 0;
12627 }
12628 }
12629}
12630
12631
12632/*------------------------------------------------------------------*/
12633/* Echo canceller facilities */
12634/*------------------------------------------------------------------*/
12635
12636
12637static void ec_write_parameters (PLCI *plci)
12638{
12639 word w;
12640 byte parameter_buffer[6];
12641
12642 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12643 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12644 (char *)(FILE_), __LINE__));
12645
12646 parameter_buffer[0] = 5;
12647 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12648 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12649 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12650 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12651 PUT_WORD (&parameter_buffer[4], w);
12652 add_p (plci, FTY, parameter_buffer);
12653 sig_req (plci, TEL_CTRL, 0);
12654 send_req (plci);
12655}
12656
12657
12658static void ec_clear_config (PLCI *plci)
12659{
12660
12661 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12662 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12663 (char *)(FILE_), __LINE__));
12664
12665 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12666 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12667 plci->ec_tail_length = 0;
12668}
12669
12670
12671static void ec_prepare_switch (dword Id, PLCI *plci)
12672{
12673
12674 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12675 UnMapId (Id), (char *)(FILE_), __LINE__));
12676
12677}
12678
12679
12680static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12681{
12682
12683 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12684 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12685
12686 return (GOOD);
12687}
12688
12689
12690static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12691{
12692 word Info;
12693
12694 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12695 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12696
12697 Info = GOOD;
12698 if (plci->B1_facilities & B1_FACILITY_EC)
12699 {
12700 switch (plci->adjust_b_state)
12701 {
12702 case ADJUST_B_RESTORE_EC_1:
12703 plci->internal_command = plci->adjust_b_command;
12704 if (plci->sig_req)
12705 {
12706 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12707 break;
12708 }
12709 ec_write_parameters (plci);
12710 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12711 break;
12712 case ADJUST_B_RESTORE_EC_2:
12713 if ((Rc != OK) && (Rc != OK_FC))
12714 {
12715 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12716 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12717 Info = _WRONG_STATE;
12718 break;
12719 }
12720 break;
12721 }
12722 }
12723 return (Info);
12724}
12725
12726
12727static void ec_command (dword Id, PLCI *plci, byte Rc)
12728{
12729 word internal_command, Info;
12730 byte result[8];
12731
12732 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12733 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12734 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12735
12736 Info = GOOD;
12737 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12738 {
12739 result[0] = 2;
12740 PUT_WORD (&result[1], EC_SUCCESS);
12741 }
12742 else
12743 {
12744 result[0] = 5;
12745 PUT_WORD (&result[1], plci->ec_cmd);
12746 result[3] = 2;
12747 PUT_WORD (&result[4], GOOD);
12748 }
12749 internal_command = plci->internal_command;
12750 plci->internal_command = 0;
12751 switch (plci->ec_cmd)
12752 {
12753 case EC_ENABLE_OPERATION:
12754 case EC_FREEZE_COEFFICIENTS:
12755 case EC_RESUME_COEFFICIENT_UPDATE:
12756 case EC_RESET_COEFFICIENTS:
12757 switch (internal_command)
12758 {
12759 default:
12760 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12761 B1_FACILITY_EC), EC_COMMAND_1);
12762 case EC_COMMAND_1:
12763 if (adjust_b_process (Id, plci, Rc) != GOOD)
12764 {
12765 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12766 UnMapId (Id), (char *)(FILE_), __LINE__));
12767 Info = _FACILITY_NOT_SUPPORTED;
12768 break;
12769 }
12770 if (plci->internal_command)
12771 return;
12772 case EC_COMMAND_2:
12773 if (plci->sig_req)
12774 {
12775 plci->internal_command = EC_COMMAND_2;
12776 return;
12777 }
12778 plci->internal_command = EC_COMMAND_3;
12779 ec_write_parameters (plci);
12780 return;
12781 case EC_COMMAND_3:
12782 if ((Rc != OK) && (Rc != OK_FC))
12783 {
12784 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12785 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12786 Info = _FACILITY_NOT_SUPPORTED;
12787 break;
12788 }
12789 break;
12790 }
12791 break;
12792
12793 case EC_DISABLE_OPERATION:
12794 switch (internal_command)
12795 {
12796 default:
12797 case EC_COMMAND_1:
12798 if (plci->B1_facilities & B1_FACILITY_EC)
12799 {
12800 if (plci->sig_req)
12801 {
12802 plci->internal_command = EC_COMMAND_1;
12803 return;
12804 }
12805 plci->internal_command = EC_COMMAND_2;
12806 ec_write_parameters (plci);
12807 return;
12808 }
12809 Rc = OK;
12810 case EC_COMMAND_2:
12811 if ((Rc != OK) && (Rc != OK_FC))
12812 {
12813 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12814 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12815 Info = _FACILITY_NOT_SUPPORTED;
12816 break;
12817 }
12818 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12819 ~B1_FACILITY_EC), EC_COMMAND_3);
12820 case EC_COMMAND_3:
12821 if (adjust_b_process (Id, plci, Rc) != GOOD)
12822 {
12823 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12824 UnMapId (Id), (char *)(FILE_), __LINE__));
12825 Info = _FACILITY_NOT_SUPPORTED;
12826 break;
12827 }
12828 if (plci->internal_command)
12829 return;
12830 break;
12831 }
12832 break;
12833 }
12834 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12835 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12836 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12837}
12838
12839
12840static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12841{
12842 word Info;
12843 word opt;
12844 API_PARSE ec_parms[3];
12845 byte result[16];
12846
12847 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12848 UnMapId (Id), (char *)(FILE_), __LINE__));
12849
12850 Info = GOOD;
12851 result[0] = 0;
12852 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12853 {
12854 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12855 UnMapId (Id), (char *)(FILE_), __LINE__));
12856 Info = _FACILITY_NOT_SUPPORTED;
12857 }
12858 else
12859 {
12860 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12861 {
12862 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12863 {
12864 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12865 UnMapId (Id), (char *)(FILE_), __LINE__));
12866 Info = _WRONG_MESSAGE_FORMAT;
12867 }
12868 else
12869 {
12870 if (plci == NULL)
12871 {
12872 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12873 UnMapId (Id), (char *)(FILE_), __LINE__));
12874 Info = _WRONG_IDENTIFIER;
12875 }
12876 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12877 {
12878 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12879 UnMapId (Id), (char *)(FILE_), __LINE__));
12880 Info = _WRONG_STATE;
12881 }
12882 else
12883 {
12884 plci->command = 0;
12885 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12886 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12887 result[0] = 2;
12888 PUT_WORD (&result[1], EC_SUCCESS);
12889 if (msg[1].length >= 4)
12890 {
12891 opt = GET_WORD (&ec_parms[0].info[2]);
12892 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12893 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12894 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12895 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12896 if (opt & EC_DETECT_DISABLE_TONE)
12897 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12898 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12899 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12900 if (msg[1].length >= 6)
12901 {
12902 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12903 }
12904 }
12905 switch (plci->ec_cmd)
12906 {
12907 case EC_ENABLE_OPERATION:
12908 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12909 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012910 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012911
12912 case EC_DISABLE_OPERATION:
12913 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12914 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12915 LEC_RESET_COEFFICIENTS;
12916 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012917 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012918
12919 case EC_FREEZE_COEFFICIENTS:
12920 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12921 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012922 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012923
12924 case EC_RESUME_COEFFICIENT_UPDATE:
12925 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12926 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012927 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012928
12929 case EC_RESET_COEFFICIENTS:
12930 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12931 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080012932 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012933
12934 default:
12935 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12936 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12937 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12938 }
12939 }
12940 }
12941 }
12942 else
12943 {
12944 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12945 {
12946 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12947 UnMapId (Id), (char *)(FILE_), __LINE__));
12948 Info = _WRONG_MESSAGE_FORMAT;
12949 }
12950 else
12951 {
12952 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12953 {
12954 result[0] = 11;
12955 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12956 result[3] = 8;
12957 PUT_WORD (&result[4], GOOD);
12958 PUT_WORD (&result[6], 0x0007);
12959 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12960 PUT_WORD (&result[10], 0);
12961 }
12962 else if (plci == NULL)
12963 {
12964 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12965 UnMapId (Id), (char *)(FILE_), __LINE__));
12966 Info = _WRONG_IDENTIFIER;
12967 }
12968 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12969 {
12970 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12971 UnMapId (Id), (char *)(FILE_), __LINE__));
12972 Info = _WRONG_STATE;
12973 }
12974 else
12975 {
12976 plci->command = 0;
12977 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12978 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12979 result[0] = 5;
12980 PUT_WORD (&result[1], plci->ec_cmd);
12981 result[3] = 2;
12982 PUT_WORD (&result[4], GOOD);
12983 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12984 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12985 plci->ec_tail_length = 0;
12986 if (ec_parms[1].length >= 2)
12987 {
12988 opt = GET_WORD (&ec_parms[1].info[1]);
12989 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12990 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12991 if (opt & EC_DETECT_DISABLE_TONE)
12992 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12993 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12994 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12995 if (ec_parms[1].length >= 4)
12996 {
12997 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12998 }
12999 }
13000 switch (plci->ec_cmd)
13001 {
13002 case EC_ENABLE_OPERATION:
13003 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13004 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013005 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013006
13007 case EC_DISABLE_OPERATION:
13008 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13009 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13010 LEC_RESET_COEFFICIENTS;
13011 start_internal_command (Id, plci, ec_command);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013012 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013013
13014 default:
13015 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13016 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13017 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13018 }
13019 }
13020 }
13021 }
13022 }
13023 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13024 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13025 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013026 return (false);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013027}
13028
13029
13030static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13031{
13032 byte result[8];
13033
13034 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13035 UnMapId (Id), (char *)(FILE_), __LINE__));
13036
13037 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13038 {
13039 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13040 {
13041 result[0] = 2;
13042 PUT_WORD (&result[1], 0);
13043 switch (msg[1])
13044 {
13045 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13046 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13047 break;
13048 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13049 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13050 break;
13051 case LEC_DISABLE_RELEASED:
13052 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13053 break;
13054 }
13055 }
13056 else
13057 {
13058 result[0] = 5;
13059 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13060 result[3] = 2;
13061 PUT_WORD (&result[4], 0);
13062 switch (msg[1])
13063 {
13064 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13065 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13066 break;
13067 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13068 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13069 break;
13070 case LEC_DISABLE_RELEASED:
13071 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13072 break;
13073 }
13074 }
13075 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13076 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13077 }
13078}
13079
13080
13081
13082/*------------------------------------------------------------------*/
13083/* Advanced voice */
13084/*------------------------------------------------------------------*/
13085
13086static void adv_voice_write_coefs (PLCI *plci, word write_command)
13087{
13088 DIVA_CAPI_ADAPTER *a;
13089 word i;
13090 byte *p;
13091
13092 word w, n, j, k;
13093 byte ch_map[MIXER_CHANNELS_BRI];
13094
13095 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13096
13097 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13098 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13099 (char *)(FILE_), __LINE__, write_command));
13100
13101 a = plci->adapter;
13102 p = coef_buffer + 1;
13103 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13104 i = 0;
13105 while (i + sizeof(word) <= a->adv_voice_coef_length)
13106 {
13107 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13108 p += 2;
13109 i += 2;
13110 }
13111 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13112 {
13113 PUT_WORD (p, 0x8000);
13114 p += 2;
13115 i += 2;
13116 }
13117
13118 if (!a->li_pri && (plci->li_bchannel_id == 0))
13119 {
13120 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13121 {
13122 plci->li_bchannel_id = 1;
13123 li_config_table[a->li_base].plci = plci;
13124 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13125 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13126 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13127 }
13128 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13129 {
13130 plci->li_bchannel_id = 2;
13131 li_config_table[a->li_base + 1].plci = plci;
13132 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13133 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13134 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13135 }
13136 }
13137 if (!a->li_pri && (plci->li_bchannel_id != 0)
13138 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13139 {
13140 i = a->li_base + (plci->li_bchannel_id - 1);
13141 switch (write_command)
13142 {
13143 case ADV_VOICE_WRITE_ACTIVATION:
13144 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13145 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13146 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13147 {
13148 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13149 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13150 }
13151 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13152 {
13153 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13154 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13155 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13156 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13157 }
13158 mixer_calculate_coefs (a);
13159 li_config_table[i].curchnl = li_config_table[i].channel;
13160 li_config_table[j].curchnl = li_config_table[j].channel;
13161 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13162 li_config_table[k].curchnl = li_config_table[k].channel;
13163 break;
13164
13165 case ADV_VOICE_WRITE_DEACTIVATION:
13166 for (j = 0; j < li_total_channels; j++)
13167 {
13168 li_config_table[i].flag_table[j] = 0;
13169 li_config_table[j].flag_table[i] = 0;
13170 }
13171 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13172 for (j = 0; j < li_total_channels; j++)
13173 {
13174 li_config_table[k].flag_table[j] = 0;
13175 li_config_table[j].flag_table[k] = 0;
13176 }
13177 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13178 {
13179 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13180 for (j = 0; j < li_total_channels; j++)
13181 {
13182 li_config_table[k].flag_table[j] = 0;
13183 li_config_table[j].flag_table[k] = 0;
13184 }
13185 }
13186 mixer_calculate_coefs (a);
13187 break;
13188 }
13189 if (plci->B1_facilities & B1_FACILITY_MIXER)
13190 {
13191 w = 0;
13192 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13193 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13194 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13195 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13196 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13197 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13198 *(p++) = (byte) w;
13199 *(p++) = (byte)(w >> 8);
13200 for (j = 0; j < sizeof(ch_map); j += 2)
13201 {
13202 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13203 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13204 }
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080013205 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013206 {
13207 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13208 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13209 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13210 {
13211 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13212 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13213 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13214 }
13215 else
13216 {
13217 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13218 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13219 }
13220 }
13221 }
13222 else
13223 {
13224 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13225 *(p++) = a->adv_voice_coef_buffer[i];
13226 }
13227 }
13228 else
13229
13230 {
13231 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13232 *(p++) = a->adv_voice_coef_buffer[i];
13233 }
13234 coef_buffer[0] = (p - coef_buffer) - 1;
13235 add_p (plci, FTY, coef_buffer);
13236 sig_req (plci, TEL_CTRL, 0);
13237 send_req (plci);
13238}
13239
13240
13241static void adv_voice_clear_config (PLCI *plci)
13242{
13243 DIVA_CAPI_ADAPTER *a;
13244
13245 word i, j;
13246
13247
13248 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13249 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13250 (char *)(FILE_), __LINE__));
13251
13252 a = plci->adapter;
13253 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13254 {
13255 a->adv_voice_coef_length = 0;
13256
13257 if (!a->li_pri && (plci->li_bchannel_id != 0)
13258 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13259 {
13260 i = a->li_base + (plci->li_bchannel_id - 1);
13261 li_config_table[i].curchnl = 0;
13262 li_config_table[i].channel = 0;
13263 li_config_table[i].chflags = 0;
13264 for (j = 0; j < li_total_channels; j++)
13265 {
13266 li_config_table[i].flag_table[j] = 0;
13267 li_config_table[j].flag_table[i] = 0;
13268 li_config_table[i].coef_table[j] = 0;
13269 li_config_table[j].coef_table[i] = 0;
13270 }
13271 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13272 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13273 li_config_table[i].curchnl = 0;
13274 li_config_table[i].channel = 0;
13275 li_config_table[i].chflags = 0;
13276 for (j = 0; j < li_total_channels; j++)
13277 {
13278 li_config_table[i].flag_table[j] = 0;
13279 li_config_table[j].flag_table[i] = 0;
13280 li_config_table[i].coef_table[j] = 0;
13281 li_config_table[j].coef_table[i] = 0;
13282 }
13283 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13284 {
13285 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13286 li_config_table[i].curchnl = 0;
13287 li_config_table[i].channel = 0;
13288 li_config_table[i].chflags = 0;
13289 for (j = 0; j < li_total_channels; j++)
13290 {
13291 li_config_table[i].flag_table[j] = 0;
13292 li_config_table[j].flag_table[i] = 0;
13293 li_config_table[i].coef_table[j] = 0;
13294 li_config_table[j].coef_table[i] = 0;
13295 }
13296 }
13297 }
13298
13299 }
13300}
13301
13302
13303static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13304{
13305
13306 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13307 UnMapId (Id), (char *)(FILE_), __LINE__));
13308
13309}
13310
13311
13312static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13313{
13314
13315 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13316 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13317
13318 return (GOOD);
13319}
13320
13321
13322static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13323{
13324 DIVA_CAPI_ADAPTER *a;
13325 word Info;
13326
13327 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13328 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13329
13330 Info = GOOD;
13331 a = plci->adapter;
13332 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13333 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13334 {
13335 switch (plci->adjust_b_state)
13336 {
13337 case ADJUST_B_RESTORE_VOICE_1:
13338 plci->internal_command = plci->adjust_b_command;
13339 if (plci->sig_req)
13340 {
13341 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13342 break;
13343 }
13344 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13345 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13346 break;
13347 case ADJUST_B_RESTORE_VOICE_2:
13348 if ((Rc != OK) && (Rc != OK_FC))
13349 {
13350 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13351 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13352 Info = _WRONG_STATE;
13353 break;
13354 }
13355 break;
13356 }
13357 }
13358 return (Info);
13359}
13360
13361
13362
13363
13364/*------------------------------------------------------------------*/
13365/* B1 resource switching */
13366/*------------------------------------------------------------------*/
13367
13368static byte b1_facilities_table[] =
13369{
13370 0x00, /* 0 No bchannel resources */
13371 0x00, /* 1 Codec (automatic law) */
13372 0x00, /* 2 Codec (A-law) */
13373 0x00, /* 3 Codec (y-law) */
13374 0x00, /* 4 HDLC for X.21 */
13375 0x00, /* 5 HDLC */
13376 0x00, /* 6 External Device 0 */
13377 0x00, /* 7 External Device 1 */
13378 0x00, /* 8 HDLC 56k */
13379 0x00, /* 9 Transparent */
13380 0x00, /* 10 Loopback to network */
13381 0x00, /* 11 Test pattern to net */
13382 0x00, /* 12 Rate adaptation sync */
13383 0x00, /* 13 Rate adaptation async */
13384 0x00, /* 14 R-Interface */
13385 0x00, /* 15 HDLC 128k leased line */
13386 0x00, /* 16 FAX */
13387 0x00, /* 17 Modem async */
13388 0x00, /* 18 Modem sync HDLC */
13389 0x00, /* 19 V.110 async HDLC */
13390 0x12, /* 20 Adv voice (Trans,mixer) */
13391 0x00, /* 21 Codec connected to IC */
13392 0x0c, /* 22 Trans,DTMF */
13393 0x1e, /* 23 Trans,DTMF+mixer */
13394 0x1f, /* 24 Trans,DTMF+mixer+local */
13395 0x13, /* 25 Trans,mixer+local */
13396 0x12, /* 26 HDLC,mixer */
13397 0x12, /* 27 HDLC 56k,mixer */
13398 0x2c, /* 28 Trans,LEC+DTMF */
13399 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13400 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13401 0x2c, /* 31 RTP,LEC+DTMF */
13402 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13403 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13404 0x00, /* 34 Signaling task */
13405 0x00, /* 35 PIAFS */
13406 0x0c, /* 36 Trans,DTMF+TONE */
13407 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13408 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13409};
13410
13411
13412static word get_b1_facilities (PLCI * plci, byte b1_resource)
13413{
13414 word b1_facilities;
13415
13416 b1_facilities = b1_facilities_table[b1_resource];
13417 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13418 {
13419
13420 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13421 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13422
13423 {
13424 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13425 b1_facilities |= B1_FACILITY_DTMFX;
13426 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13427 b1_facilities |= B1_FACILITY_DTMFR;
13428 }
13429 }
13430 if ((b1_resource == 17) || (b1_resource == 18))
13431 {
13432 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13433 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13434 }
13435/*
13436 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13437 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13438 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13439*/
13440 return (b1_facilities);
13441}
13442
13443
13444static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13445{
13446 byte b;
13447
13448 switch (b1_resource)
13449 {
13450 case 5:
13451 case 26:
13452 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13453 b = 26;
13454 else
13455 b = 5;
13456 break;
13457
13458 case 8:
13459 case 27:
13460 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13461 b = 27;
13462 else
13463 b = 8;
13464 break;
13465
13466 case 9:
13467 case 20:
13468 case 22:
13469 case 23:
13470 case 24:
13471 case 25:
13472 case 28:
13473 case 29:
13474 case 30:
13475 case 36:
13476 case 37:
13477 case 38:
13478 if (b1_facilities & B1_FACILITY_EC)
13479 {
13480 if (b1_facilities & B1_FACILITY_LOCAL)
13481 b = 30;
13482 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13483 b = 29;
13484 else
13485 b = 28;
13486 }
13487
13488 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13489 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13490 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13491 {
13492 if (b1_facilities & B1_FACILITY_LOCAL)
13493 b = 38;
13494 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13495 b = 37;
13496 else
13497 b = 36;
13498 }
13499
13500 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13501 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13502 || ((b1_facilities & B1_FACILITY_DTMFR)
13503 && ((b1_facilities & B1_FACILITY_MIXER)
13504 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13505 || ((b1_facilities & B1_FACILITY_DTMFX)
13506 && ((b1_facilities & B1_FACILITY_MIXER)
13507 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13508 {
13509 if (b1_facilities & B1_FACILITY_LOCAL)
13510 b = 24;
13511 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13512 b = 23;
13513 else
13514 b = 22;
13515 }
13516 else
13517 {
13518 if (b1_facilities & B1_FACILITY_LOCAL)
13519 b = 25;
13520 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13521 b = 20;
13522 else
13523 b = 9;
13524 }
13525 break;
13526
13527 case 31:
13528 case 32:
13529 case 33:
13530 if (b1_facilities & B1_FACILITY_LOCAL)
13531 b = 33;
13532 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13533 b = 32;
13534 else
13535 b = 31;
13536 break;
13537
13538 default:
13539 b = b1_resource;
13540 }
13541 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13542 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13543 (char *)(FILE_), __LINE__,
13544 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13545 return (b);
13546}
13547
13548
13549static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13550{
13551 word removed_facilities;
13552
13553 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13554 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13555 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13556 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13557
13558 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13559 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13560
13561 if (removed_facilities & B1_FACILITY_EC)
13562 ec_clear_config (plci);
13563
13564
13565 if (removed_facilities & B1_FACILITY_DTMFR)
13566 {
13567 dtmf_rec_clear_config (plci);
13568 dtmf_parameter_clear_config (plci);
13569 }
13570 if (removed_facilities & B1_FACILITY_DTMFX)
13571 dtmf_send_clear_config (plci);
13572
13573
13574 if (removed_facilities & B1_FACILITY_MIXER)
13575 mixer_clear_config (plci);
13576
13577 if (removed_facilities & B1_FACILITY_VOICE)
13578 adv_voice_clear_config (plci);
13579 plci->B1_facilities = new_b1_facilities;
13580}
13581
13582
13583static void adjust_b_clear (PLCI *plci)
13584{
13585
13586 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13587 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13588 (char *)(FILE_), __LINE__));
13589
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013590 plci->adjust_b_restore = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013591}
13592
13593
13594static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13595{
13596 word Info;
13597 byte b1_resource;
13598 NCCI * ncci_ptr;
13599 API_PARSE bp[2];
13600
13601 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13602 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13603
13604 Info = GOOD;
13605 switch (plci->adjust_b_state)
13606 {
13607 case ADJUST_B_START:
13608 if ((plci->adjust_b_parms_msg == NULL)
13609 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13610 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13611 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13612 {
13613 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13614 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13615 if (b1_resource == plci->B1_resource)
13616 {
13617 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13618 break;
13619 }
13620 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13621 {
13622 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13623 UnMapId (Id), (char *)(FILE_), __LINE__,
13624 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13625 Info = _WRONG_STATE;
13626 break;
13627 }
13628 }
13629 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13630 {
13631
13632 mixer_prepare_switch (Id, plci);
13633
13634
13635 dtmf_prepare_switch (Id, plci);
13636 dtmf_parameter_prepare_switch (Id, plci);
13637
13638
13639 ec_prepare_switch (Id, plci);
13640
13641 adv_voice_prepare_switch (Id, plci);
13642 }
13643 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13644 Rc = OK;
13645 case ADJUST_B_SAVE_MIXER_1:
13646 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13647 {
13648
13649 Info = mixer_save_config (Id, plci, Rc);
13650 if ((Info != GOOD) || plci->internal_command)
13651 break;
13652
13653 }
13654 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13655 Rc = OK;
13656 case ADJUST_B_SAVE_DTMF_1:
13657 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13658 {
13659
13660 Info = dtmf_save_config (Id, plci, Rc);
13661 if ((Info != GOOD) || plci->internal_command)
13662 break;
13663
13664 }
13665 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13666 case ADJUST_B_REMOVE_L23_1:
13667 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13668 && plci->NL.Id && !plci->nl_remove_id)
13669 {
13670 plci->internal_command = plci->adjust_b_command;
13671 if (plci->adjust_b_ncci != 0)
13672 {
13673 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13674 while (ncci_ptr->data_pending)
13675 {
13676 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13677 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13678 }
13679 while (ncci_ptr->data_ack_pending)
13680 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13681 }
13682 nl_req_ncci (plci, REMOVE,
13683 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13684 send_req (plci);
13685 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13686 break;
13687 }
13688 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13689 Rc = OK;
13690 case ADJUST_B_REMOVE_L23_2:
13691 if ((Rc != OK) && (Rc != OK_FC))
13692 {
13693 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13694 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13695 Info = _WRONG_STATE;
13696 break;
13697 }
13698 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13699 {
13700 if (plci_nl_busy (plci))
13701 {
13702 plci->internal_command = plci->adjust_b_command;
13703 break;
13704 }
13705 }
13706 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13707 Rc = OK;
13708 case ADJUST_B_SAVE_EC_1:
13709 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13710 {
13711
13712 Info = ec_save_config (Id, plci, Rc);
13713 if ((Info != GOOD) || plci->internal_command)
13714 break;
13715
13716 }
13717 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13718 Rc = OK;
13719 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13720 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13721 {
13722
13723 Info = dtmf_parameter_save_config (Id, plci, Rc);
13724 if ((Info != GOOD) || plci->internal_command)
13725 break;
13726
13727 }
13728 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13729 Rc = OK;
13730 case ADJUST_B_SAVE_VOICE_1:
13731 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13732 {
13733 Info = adv_voice_save_config (Id, plci, Rc);
13734 if ((Info != GOOD) || plci->internal_command)
13735 break;
13736 }
13737 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13738 case ADJUST_B_SWITCH_L1_1:
13739 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13740 {
13741 if (plci->sig_req)
13742 {
13743 plci->internal_command = plci->adjust_b_command;
13744 break;
13745 }
13746 if (plci->adjust_b_parms_msg != NULL)
13747 api_load_msg (plci->adjust_b_parms_msg, bp);
13748 else
13749 api_load_msg (&plci->B_protocol, bp);
13750 Info = add_b1 (plci, bp,
13751 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13752 plci->adjust_b_facilities);
13753 if (Info != GOOD)
13754 {
13755 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13756 UnMapId (Id), (char *)(FILE_), __LINE__,
13757 plci->B1_resource, plci->adjust_b_facilities));
13758 break;
13759 }
13760 plci->internal_command = plci->adjust_b_command;
13761 sig_req (plci, RESOURCES, 0);
13762 send_req (plci);
13763 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13764 break;
13765 }
13766 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13767 Rc = OK;
13768 case ADJUST_B_SWITCH_L1_2:
13769 if ((Rc != OK) && (Rc != OK_FC))
13770 {
13771 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13772 UnMapId (Id), (char *)(FILE_), __LINE__,
13773 Rc, plci->B1_resource, plci->adjust_b_facilities));
13774 Info = _WRONG_STATE;
13775 break;
13776 }
13777 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13778 Rc = OK;
13779 case ADJUST_B_RESTORE_VOICE_1:
13780 case ADJUST_B_RESTORE_VOICE_2:
13781 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13782 {
13783 Info = adv_voice_restore_config (Id, plci, Rc);
13784 if ((Info != GOOD) || plci->internal_command)
13785 break;
13786 }
13787 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13788 Rc = OK;
13789 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13790 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13791 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13792 {
13793
13794 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13795 if ((Info != GOOD) || plci->internal_command)
13796 break;
13797
13798 }
13799 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13800 Rc = OK;
13801 case ADJUST_B_RESTORE_EC_1:
13802 case ADJUST_B_RESTORE_EC_2:
13803 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13804 {
13805
13806 Info = ec_restore_config (Id, plci, Rc);
13807 if ((Info != GOOD) || plci->internal_command)
13808 break;
13809
13810 }
13811 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13812 case ADJUST_B_ASSIGN_L23_1:
13813 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13814 {
13815 if (plci_nl_busy (plci))
13816 {
13817 plci->internal_command = plci->adjust_b_command;
13818 break;
13819 }
13820 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13821 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13822 if (plci->adjust_b_parms_msg != NULL)
13823 api_load_msg (plci->adjust_b_parms_msg, bp);
13824 else
13825 api_load_msg (&plci->B_protocol, bp);
13826 Info = add_b23 (plci, bp);
13827 if (Info != GOOD)
13828 {
13829 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13830 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13831 break;
13832 }
13833 plci->internal_command = plci->adjust_b_command;
13834 nl_req_ncci (plci, ASSIGN, 0);
13835 send_req (plci);
13836 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13837 break;
13838 }
13839 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13840 Rc = ASSIGN_OK;
13841 case ADJUST_B_ASSIGN_L23_2:
13842 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13843 {
13844 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13845 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13846 Info = _WRONG_STATE;
13847 break;
13848 }
13849 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13850 {
13851 if (Rc != ASSIGN_OK)
13852 {
13853 plci->internal_command = plci->adjust_b_command;
13854 break;
13855 }
13856 }
13857 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13858 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080013859 plci->adjust_b_restore = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013860 break;
13861 }
13862 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13863 case ADJUST_B_CONNECT_1:
13864 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865 {
13866 plci->internal_command = plci->adjust_b_command;
13867 if (plci_nl_busy (plci))
13868 break;
13869 nl_req_ncci (plci, N_CONNECT, 0);
13870 send_req (plci);
13871 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13872 break;
13873 }
13874 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13875 Rc = OK;
13876 case ADJUST_B_CONNECT_2:
13877 case ADJUST_B_CONNECT_3:
13878 case ADJUST_B_CONNECT_4:
13879 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13880 {
13881 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13882 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13883 Info = _WRONG_STATE;
13884 break;
13885 }
13886 if (Rc == OK)
13887 {
13888 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13889 {
13890 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13891 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13892 }
13893 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13894 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13895 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13896 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13897 }
13898 else if (Rc == 0)
13899 {
13900 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13901 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13902 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13903 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13904 }
13905 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13906 {
13907 plci->internal_command = plci->adjust_b_command;
13908 break;
13909 }
13910 Rc = OK;
13911 case ADJUST_B_RESTORE_DTMF_1:
13912 case ADJUST_B_RESTORE_DTMF_2:
13913 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13914 {
13915
13916 Info = dtmf_restore_config (Id, plci, Rc);
13917 if ((Info != GOOD) || plci->internal_command)
13918 break;
13919
13920 }
13921 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13922 Rc = OK;
13923 case ADJUST_B_RESTORE_MIXER_1:
13924 case ADJUST_B_RESTORE_MIXER_2:
13925 case ADJUST_B_RESTORE_MIXER_3:
13926 case ADJUST_B_RESTORE_MIXER_4:
13927 case ADJUST_B_RESTORE_MIXER_5:
13928 case ADJUST_B_RESTORE_MIXER_6:
13929 case ADJUST_B_RESTORE_MIXER_7:
13930 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13931 {
13932
13933 Info = mixer_restore_config (Id, plci, Rc);
13934 if ((Info != GOOD) || plci->internal_command)
13935 break;
13936
13937 }
13938 plci->adjust_b_state = ADJUST_B_END;
13939 case ADJUST_B_END:
13940 break;
13941 }
13942 return (Info);
13943}
13944
13945
13946static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13947{
13948
13949 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13950 UnMapId (Id), (char *)(FILE_), __LINE__,
13951 plci->B1_resource, b1_facilities));
13952
13953 plci->adjust_b_parms_msg = bp_msg;
13954 plci->adjust_b_facilities = b1_facilities;
13955 plci->adjust_b_command = internal_command;
13956 plci->adjust_b_ncci = (word)(Id >> 16);
13957 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13958 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13959 else
13960 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13961 plci->adjust_b_state = ADJUST_B_START;
13962 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13963 UnMapId (Id), (char *)(FILE_), __LINE__,
13964 plci->B1_resource, b1_facilities));
13965}
13966
13967
13968static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13969{
13970 word internal_command;
13971
13972 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13973 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13974
13975 internal_command = plci->internal_command;
13976 plci->internal_command = 0;
13977 switch (internal_command)
13978 {
13979 default:
13980 plci->command = 0;
13981 if (plci->req_in != 0)
13982 {
13983 plci->internal_command = ADJUST_B_RESTORE_1;
13984 break;
13985 }
13986 Rc = OK;
13987 case ADJUST_B_RESTORE_1:
13988 if ((Rc != OK) && (Rc != OK_FC))
13989 {
13990 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13991 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13992 }
13993 plci->adjust_b_parms_msg = NULL;
13994 plci->adjust_b_facilities = plci->B1_facilities;
13995 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13996 plci->adjust_b_ncci = (word)(Id >> 16);
13997 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13998 plci->adjust_b_state = ADJUST_B_START;
13999 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
14000 UnMapId (Id), (char *)(FILE_), __LINE__));
14001 case ADJUST_B_RESTORE_2:
14002 if (adjust_b_process (Id, plci, Rc) != GOOD)
14003 {
14004 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14005 UnMapId (Id), (char *)(FILE_), __LINE__));
14006 }
14007 if (plci->internal_command)
14008 break;
14009 break;
14010 }
14011}
14012
14013
14014static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
14015{
14016 word Info;
14017 word internal_command;
14018
14019 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14020 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14021
14022 Info = GOOD;
14023 internal_command = plci->internal_command;
14024 plci->internal_command = 0;
14025 switch (internal_command)
14026 {
14027 default:
14028 plci->command = 0;
14029 plci->adjust_b_parms_msg = NULL;
14030 plci->adjust_b_facilities = plci->B1_facilities;
14031 plci->adjust_b_command = RESET_B3_COMMAND_1;
14032 plci->adjust_b_ncci = (word)(Id >> 16);
14033 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14034 plci->adjust_b_state = ADJUST_B_START;
14035 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14036 UnMapId (Id), (char *)(FILE_), __LINE__));
14037 case RESET_B3_COMMAND_1:
14038 Info = adjust_b_process (Id, plci, Rc);
14039 if (Info != GOOD)
14040 {
14041 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14042 UnMapId (Id), (char *)(FILE_), __LINE__));
14043 break;
14044 }
14045 if (plci->internal_command)
14046 return;
14047 break;
14048 }
14049/* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14050 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14051}
14052
14053
14054static void select_b_command (dword Id, PLCI *plci, byte Rc)
14055{
14056 word Info;
14057 word internal_command;
14058 byte esc_chi[3];
14059
14060 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14061 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14062
14063 Info = GOOD;
14064 internal_command = plci->internal_command;
14065 plci->internal_command = 0;
14066 switch (internal_command)
14067 {
14068 default:
14069 plci->command = 0;
14070 plci->adjust_b_parms_msg = &plci->saved_msg;
14071 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14072 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14073 else
14074 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14075 plci->adjust_b_command = SELECT_B_COMMAND_1;
14076 plci->adjust_b_ncci = (word)(Id >> 16);
14077 if (plci->saved_msg.parms[0].length == 0)
14078 {
14079 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14080 ADJUST_B_MODE_NO_RESOURCE;
14081 }
14082 else
14083 {
14084 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14085 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14086 }
14087 plci->adjust_b_state = ADJUST_B_START;
14088 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14089 UnMapId (Id), (char *)(FILE_), __LINE__));
14090 case SELECT_B_COMMAND_1:
14091 Info = adjust_b_process (Id, plci, Rc);
14092 if (Info != GOOD)
14093 {
14094 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14095 UnMapId (Id), (char *)(FILE_), __LINE__));
14096 break;
14097 }
14098 if (plci->internal_command)
14099 return;
14100 if (plci->tel == ADV_VOICE)
14101 {
14102 esc_chi[0] = 0x02;
14103 esc_chi[1] = 0x18;
14104 esc_chi[2] = plci->b_channel;
14105 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14106 }
14107 break;
14108 }
14109 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14110}
14111
14112
14113static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14114{
14115 word Info;
14116 word internal_command;
14117
14118 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14119 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14120
14121 Info = GOOD;
14122 internal_command = plci->internal_command;
14123 plci->internal_command = 0;
14124 switch (internal_command)
14125 {
14126 default:
14127 plci->command = 0;
14128 case FAX_CONNECT_ACK_COMMAND_1:
14129 if (plci_nl_busy (plci))
14130 {
14131 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14132 return;
14133 }
14134 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14135 plci->NData[0].P = plci->fax_connect_info_buffer;
14136 plci->NData[0].PLength = plci->fax_connect_info_length;
14137 plci->NL.X = plci->NData;
14138 plci->NL.ReqCh = 0;
14139 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14140 plci->adapter->request (&plci->NL);
14141 return;
14142 case FAX_CONNECT_ACK_COMMAND_2:
14143 if ((Rc != OK) && (Rc != OK_FC))
14144 {
14145 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14146 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14147 break;
14148 }
14149 }
14150 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14151 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14152 {
14153 if (plci->B3_prot == 4)
14154 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14155 else
14156 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14157 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14158 }
14159}
14160
14161
14162static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14163{
14164 word Info;
14165 word internal_command;
14166
14167 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14168 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14169
14170 Info = GOOD;
14171 internal_command = plci->internal_command;
14172 plci->internal_command = 0;
14173 switch (internal_command)
14174 {
14175 default:
14176 plci->command = 0;
14177 case FAX_EDATA_ACK_COMMAND_1:
14178 if (plci_nl_busy (plci))
14179 {
14180 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14181 return;
14182 }
14183 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14184 plci->NData[0].P = plci->fax_connect_info_buffer;
14185 plci->NData[0].PLength = plci->fax_edata_ack_length;
14186 plci->NL.X = plci->NData;
14187 plci->NL.ReqCh = 0;
14188 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14189 plci->adapter->request (&plci->NL);
14190 return;
14191 case FAX_EDATA_ACK_COMMAND_2:
14192 if ((Rc != OK) && (Rc != OK_FC))
14193 {
14194 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14195 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14196 break;
14197 }
14198 }
14199}
14200
14201
14202static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14203{
14204 word Info;
14205 word internal_command;
14206
14207 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14208 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14209
14210 Info = GOOD;
14211 internal_command = plci->internal_command;
14212 plci->internal_command = 0;
14213 switch (internal_command)
14214 {
14215 default:
14216 plci->command = 0;
14217 case FAX_CONNECT_INFO_COMMAND_1:
14218 if (plci_nl_busy (plci))
14219 {
14220 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14221 return;
14222 }
14223 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14224 plci->NData[0].P = plci->fax_connect_info_buffer;
14225 plci->NData[0].PLength = plci->fax_connect_info_length;
14226 plci->NL.X = plci->NData;
14227 plci->NL.ReqCh = 0;
14228 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14229 plci->adapter->request (&plci->NL);
14230 return;
14231 case FAX_CONNECT_INFO_COMMAND_2:
14232 if ((Rc != OK) && (Rc != OK_FC))
14233 {
14234 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14235 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14236 Info = _WRONG_STATE;
14237 break;
14238 }
14239 if (plci_nl_busy (plci))
14240 {
14241 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14242 return;
14243 }
14244 plci->command = _CONNECT_B3_R;
14245 nl_req_ncci (plci, N_CONNECT, 0);
14246 send_req (plci);
14247 return;
14248 }
14249 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14250}
14251
14252
14253static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14254{
14255 word Info;
14256 word internal_command;
14257
14258 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14259 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14260
14261 Info = GOOD;
14262 internal_command = plci->internal_command;
14263 plci->internal_command = 0;
14264 switch (internal_command)
14265 {
14266 default:
14267 plci->command = 0;
14268 plci->adjust_b_parms_msg = NULL;
14269 plci->adjust_b_facilities = plci->B1_facilities;
14270 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14271 plci->adjust_b_ncci = (word)(Id >> 16);
14272 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14273 plci->adjust_b_state = ADJUST_B_START;
14274 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14275 UnMapId (Id), (char *)(FILE_), __LINE__));
14276 case FAX_ADJUST_B23_COMMAND_1:
14277 Info = adjust_b_process (Id, plci, Rc);
14278 if (Info != GOOD)
14279 {
14280 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14281 UnMapId (Id), (char *)(FILE_), __LINE__));
14282 break;
14283 }
14284 if (plci->internal_command)
14285 return;
14286 case FAX_ADJUST_B23_COMMAND_2:
14287 if (plci_nl_busy (plci))
14288 {
14289 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14290 return;
14291 }
14292 plci->command = _CONNECT_B3_R;
14293 nl_req_ncci (plci, N_CONNECT, 0);
14294 send_req (plci);
14295 return;
14296 }
14297 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14298}
14299
14300
14301static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14302{
14303 word internal_command;
14304
14305 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14306 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14307
14308 internal_command = plci->internal_command;
14309 plci->internal_command = 0;
14310 switch (internal_command)
14311 {
14312 default:
14313 plci->command = 0;
14314 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14315 return;
14316 case FAX_DISCONNECT_COMMAND_1:
14317 case FAX_DISCONNECT_COMMAND_2:
14318 case FAX_DISCONNECT_COMMAND_3:
14319 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14320 {
14321 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14322 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14323 break;
14324 }
14325 if (Rc == OK)
14326 {
14327 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14328 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14329 {
14330 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14331 }
14332 }
14333 else if (Rc == 0)
14334 {
14335 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14336 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14337 }
14338 return;
14339 }
14340}
14341
14342
14343
14344static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14345{
14346 word Info;
14347 word internal_command;
14348
14349 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14350 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14351
14352 Info = GOOD;
14353 internal_command = plci->internal_command;
14354 plci->internal_command = 0;
14355 switch (internal_command)
14356 {
14357 default:
14358 plci->command = 0;
14359 case RTP_CONNECT_B3_REQ_COMMAND_1:
14360 if (plci_nl_busy (plci))
14361 {
14362 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14363 return;
14364 }
14365 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14366 nl_req_ncci (plci, N_CONNECT, 0);
14367 send_req (plci);
14368 return;
14369 case RTP_CONNECT_B3_REQ_COMMAND_2:
14370 if ((Rc != OK) && (Rc != OK_FC))
14371 {
14372 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14373 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14374 Info = _WRONG_STATE;
14375 break;
14376 }
14377 if (plci_nl_busy (plci))
14378 {
14379 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14380 return;
14381 }
14382 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14383 plci->NData[0].PLength = plci->internal_req_buffer[0];
14384 plci->NData[0].P = plci->internal_req_buffer + 1;
14385 plci->NL.X = plci->NData;
14386 plci->NL.ReqCh = 0;
14387 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14388 plci->adapter->request (&plci->NL);
14389 break;
14390 case RTP_CONNECT_B3_REQ_COMMAND_3:
14391 return;
14392 }
14393 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14394}
14395
14396
14397static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14398{
14399 word Info;
14400 word internal_command;
14401
14402 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14403 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14404
14405 Info = GOOD;
14406 internal_command = plci->internal_command;
14407 plci->internal_command = 0;
14408 switch (internal_command)
14409 {
14410 default:
14411 plci->command = 0;
14412 case RTP_CONNECT_B3_RES_COMMAND_1:
14413 if (plci_nl_busy (plci))
14414 {
14415 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14416 return;
14417 }
14418 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14419 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14420 send_req (plci);
14421 return;
14422 case RTP_CONNECT_B3_RES_COMMAND_2:
14423 if ((Rc != OK) && (Rc != OK_FC))
14424 {
14425 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14426 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14427 Info = _WRONG_STATE;
14428 break;
14429 }
14430 if (plci_nl_busy (plci))
14431 {
14432 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14433 return;
14434 }
14435 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14436 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14437 plci->NData[0].PLength = plci->internal_req_buffer[0];
14438 plci->NData[0].P = plci->internal_req_buffer + 1;
14439 plci->NL.X = plci->NData;
14440 plci->NL.ReqCh = 0;
14441 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14442 plci->adapter->request (&plci->NL);
14443 return;
14444 case RTP_CONNECT_B3_RES_COMMAND_3:
14445 return;
14446 }
14447}
14448
14449
14450
14451static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14452{
14453 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14454 word Info;
14455 word internal_command;
14456
14457 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14458 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14459
14460 Info = GOOD;
14461 internal_command = plci->internal_command;
14462 plci->internal_command = 0;
14463 switch (internal_command)
14464 {
14465 default:
14466 if (!plci->NL.Id)
14467 break;
14468 plci->command = 0;
14469 plci->adjust_b_parms_msg = NULL;
14470 plci->adjust_b_facilities = plci->B1_facilities;
14471 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14472 plci->adjust_b_ncci = (word)(Id >> 16);
14473 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14474 plci->adjust_b_state = ADJUST_B_START;
14475 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14476 UnMapId (Id), (char *)(FILE_), __LINE__));
14477 case HOLD_SAVE_COMMAND_1:
14478 Info = adjust_b_process (Id, plci, Rc);
14479 if (Info != GOOD)
14480 {
14481 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14482 UnMapId (Id), (char *)(FILE_), __LINE__));
14483 break;
14484 }
14485 if (plci->internal_command)
14486 return;
14487 }
14488 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14489}
14490
14491
14492static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14493{
14494 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14495 word Info;
14496 word internal_command;
14497
14498 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14499 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14500
14501 Info = GOOD;
14502 internal_command = plci->internal_command;
14503 plci->internal_command = 0;
14504 switch (internal_command)
14505 {
14506 default:
14507 plci->command = 0;
14508 plci->adjust_b_parms_msg = NULL;
14509 plci->adjust_b_facilities = plci->B1_facilities;
14510 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14511 plci->adjust_b_ncci = (word)(Id >> 16);
14512 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14513 plci->adjust_b_state = ADJUST_B_START;
14514 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14515 UnMapId (Id), (char *)(FILE_), __LINE__));
14516 case RETRIEVE_RESTORE_COMMAND_1:
14517 Info = adjust_b_process (Id, plci, Rc);
14518 if (Info != GOOD)
14519 {
14520 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14521 UnMapId (Id), (char *)(FILE_), __LINE__));
14522 break;
14523 }
14524 if (plci->internal_command)
14525 return;
14526 }
14527 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14528}
14529
14530
14531static void init_b1_config (PLCI *plci)
14532{
14533
14534 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14535 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14536 (char *)(FILE_), __LINE__));
14537
14538 plci->B1_resource = 0;
14539 plci->B1_facilities = 0;
14540
14541 plci->li_bchannel_id = 0;
14542 mixer_clear_config (plci);
14543
14544
14545 ec_clear_config (plci);
14546
14547
14548 dtmf_rec_clear_config (plci);
14549 dtmf_send_clear_config (plci);
14550 dtmf_parameter_clear_config (plci);
14551
14552 adv_voice_clear_config (plci);
14553 adjust_b_clear (plci);
14554}
14555
14556
14557static void clear_b1_config (PLCI *plci)
14558{
14559
14560 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14561 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14562 (char *)(FILE_), __LINE__));
14563
14564 adv_voice_clear_config (plci);
14565 adjust_b_clear (plci);
14566
14567 ec_clear_config (plci);
14568
14569
14570 dtmf_rec_clear_config (plci);
14571 dtmf_send_clear_config (plci);
14572 dtmf_parameter_clear_config (plci);
14573
14574
14575 if ((plci->li_bchannel_id != 0)
14576 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14577 {
14578 mixer_clear_config (plci);
14579 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14580 plci->li_bchannel_id = 0;
14581 }
14582
14583 plci->B1_resource = 0;
14584 plci->B1_facilities = 0;
14585}
14586
14587
14588/* -----------------------------------------------------------------
14589 XON protocol local helpers
14590 ----------------------------------------------------------------- */
14591static void channel_flow_control_remove (PLCI * plci) {
14592 DIVA_CAPI_ADAPTER * a = plci->adapter;
14593 word i;
14594 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14595 if (a->ch_flow_plci[i] == plci->Id) {
14596 a->ch_flow_plci[i] = 0;
14597 a->ch_flow_control[i] = 0;
14598 }
14599 }
14600}
14601
14602static void channel_x_on (PLCI * plci, byte ch) {
14603 DIVA_CAPI_ADAPTER * a = plci->adapter;
14604 if (a->ch_flow_control[ch] & N_XON_SENT) {
14605 a->ch_flow_control[ch] &= ~N_XON_SENT;
14606 }
14607}
14608
14609static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14610 DIVA_CAPI_ADAPTER * a = plci->adapter;
14611 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14612 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14613 a->ch_flow_plci[ch] = plci->Id;
14614 a->ch_flow_control_pending++;
14615 }
14616}
14617
14618static void channel_request_xon (PLCI * plci, byte ch) {
14619 DIVA_CAPI_ADAPTER * a = plci->adapter;
14620
14621 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14622 a->ch_flow_control[ch] |= N_XON_REQ;
14623 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14624 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14625 }
14626}
14627
14628static void channel_xmit_extended_xon (PLCI * plci) {
14629 DIVA_CAPI_ADAPTER * a;
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080014630 int max_ch = ARRAY_SIZE(a->ch_flow_control);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014631 int i, one_requested = 0;
14632
Harvey Harrisondd58c0d2008-04-28 02:14:39 -070014633 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070014634 return;
14635 }
14636
14637 for (i = 0; i < max_ch; i++) {
14638 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14639 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14640 (plci->Id == a->ch_flow_plci[i])) {
14641 channel_request_xon (plci, (byte)i);
14642 one_requested = 1;
14643 }
14644 }
14645
14646 if (one_requested) {
14647 channel_xmit_xon (plci);
14648 }
14649}
14650
14651/*
14652 Try to xmit next X_ON
14653 */
14654static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
Ahmed S. Darwishf85aaeb2007-02-12 00:53:27 -080014655 int max_ch = ARRAY_SIZE(a->ch_flow_control);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014656 int i;
14657
14658 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14659 return (0);
14660 }
14661
14662 if (a->last_flow_control_ch >= max_ch) {
14663 a->last_flow_control_ch = 1;
14664 }
14665 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14666 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14667 (plci->Id == a->ch_flow_plci[i])) {
14668 a->last_flow_control_ch = i+1;
14669 return (i);
14670 }
14671 }
14672
14673 for (i = 1; i < a->last_flow_control_ch; i++) {
14674 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14675 (plci->Id == a->ch_flow_plci[i])) {
14676 a->last_flow_control_ch = i+1;
14677 return (i);
14678 }
14679 }
14680
14681 return (0);
14682}
14683
14684static void channel_xmit_xon (PLCI * plci) {
14685 DIVA_CAPI_ADAPTER * a = plci->adapter;
14686 byte ch;
14687
14688 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14689 return;
14690 }
14691 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14692 return;
14693 }
14694 a->ch_flow_control[ch] &= ~N_XON_REQ;
14695 a->ch_flow_control[ch] |= N_XON_SENT;
14696
14697 plci->NL.Req = plci->nl_req = (byte)N_XON;
14698 plci->NL.ReqCh = ch;
14699 plci->NL.X = plci->NData;
14700 plci->NL.XNum = 1;
14701 plci->NData[0].P = &plci->RBuffer[0];
14702 plci->NData[0].PLength = 0;
14703
14704 plci->adapter->request(&plci->NL);
14705}
14706
14707static int channel_can_xon (PLCI * plci, byte ch) {
14708 APPL * APPLptr;
14709 DIVA_CAPI_ADAPTER * a;
14710 word NCCIcode;
14711 dword count;
14712 word Num;
14713 word i;
14714
14715 APPLptr = plci->appl;
14716 a = plci->adapter;
14717
14718 if (!APPLptr)
14719 return (0);
14720
14721 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14722
14723 /* count all buffers within the Application pool */
14724 /* belonging to the same NCCI. XON if a first is */
14725 /* used. */
14726 count = 0;
14727 Num = 0xffff;
14728 for(i=0; i<APPLptr->MaxBuffer; i++) {
14729 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14730 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14731 }
14732 if ((count > 2) || (Num == 0xffff)) {
14733 return (0);
14734 }
14735 return (1);
14736}
14737
14738
14739/*------------------------------------------------------------------*/
14740
14741static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14742{
14743 return 1;
14744}
14745
14746
14747
14748/**********************************************************************************/
14749/* function groups the listening applications according to the CIP mask and the */
14750/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14751/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14752/* big problems on application level (one call, 30 Connect_Ind, ect). The */
14753/* function must be enabled by setting "a->group_optimization_enabled" from the */
14754/* OS specific part (per adapter). */
14755/**********************************************************************************/
14756static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14757{
14758 word i,j,k,busy,group_found;
14759 dword info_mask_group[MAX_CIP_TYPES];
14760 dword cip_mask_group[MAX_CIP_TYPES];
14761 word appl_number_group_type[MAX_APPL];
14762 PLCI *auxplci;
14763
14764 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14765
14766 if(!a->group_optimization_enabled)
14767 {
14768 dbug(1,dprintf("No group optimization"));
14769 return;
14770 }
14771
14772 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14773
14774 for(i=0;i<MAX_CIP_TYPES;i++)
14775 {
14776 info_mask_group[i] = 0;
14777 cip_mask_group [i] = 0;
14778 }
14779 for(i=0;i<MAX_APPL;i++)
14780 {
14781 appl_number_group_type[i] = 0;
14782 }
14783 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14784 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14785 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14786 {
14787 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14788 return; /* allow good application unfiltered access */
14789 }
14790 }
14791 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14792 {
14793 if(application[i].Id && a->CIP_Mask[i] )
14794 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014795 for(k=0,busy=false; k<a->max_plci; k++)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014796 {
14797 if(a->plci[k].Id)
14798 {
14799 auxplci = &a->plci[k];
14800 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14801 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014802 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014803 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14804 }
14805 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14806 {
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014807 busy = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014808 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14809 }
14810 }
14811 }
14812
14813 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14814 {
14815 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14816 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14817 appl_number_group_type[i] = MAX_CIP_TYPES;
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014818 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014819 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14820 }
14821 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14822 { /* is group already present ? */
14823 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014824 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014825 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]));
14826 }
14827 else if(!info_mask_group[j])
14828 { /* establish a new group */
14829 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14830 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14831 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014832 group_found=true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014833 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]));
14834 }
14835 }
14836 }
14837 }
14838
14839 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14840 {
14841 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14842 {
14843 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14844 {
14845 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14846 }
14847 else
14848 {
14849 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14850 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14851 {
14852 if(appl_number_group_type[i] == appl_number_group_type[j])
14853 {
14854 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14855 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14856 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14857 }
14858 }
14859 }
14860 }
14861 else /* application should not get a call */
14862 {
14863 clear_group_ind_mask_bit (plci, i);
14864 }
14865 }
14866
14867}
14868
14869
14870
14871/* OS notifies the driver about a application Capi_Register */
14872word CapiRegister(word id)
14873{
14874 word i,j,appls_found;
14875
14876 PLCI *plci;
14877 DIVA_CAPI_ADAPTER *a;
14878
14879 for(i=0,appls_found=0; i<max_appl; i++)
14880 {
14881 if( application[i].Id && (application[i].Id!=id) )
14882 {
14883 appls_found++; /* an application has been found */
14884 }
14885 }
14886
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014887 if(appls_found) return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014888 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14889 {
14890 a = &adapter[i];
14891 if(a->request)
14892 {
14893 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14894 {
14895 if(!appls_found) /* first application does a capi register */
14896 {
14897 if((j=get_plci(a))) /* activate L1 of all adapters */
14898 {
14899 plci = &a->plci[j-1];
14900 plci->command = 0;
14901 add_p(plci,OAD,"\x01\xfd");
14902 add_p(plci,CAI,"\x01\x80");
14903 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14904 add_p(plci,SHIFT|6,NULL);
14905 add_p(plci,SIN,"\x02\x00\x00");
14906 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14907 sig_req(plci,ASSIGN,DSIG_ID);
14908 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14909 sig_req(plci,SIG_CTRL,0);
14910 send_req(plci);
14911 }
14912 }
14913 }
14914 }
14915 }
Richard Knutsson986c4bb2007-02-12 00:53:24 -080014916 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014917}
14918
14919/*------------------------------------------------------------------*/
14920
14921/* Functions for virtual Switching e.g. Transfer by join, Conference */
14922
14923static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14924{
14925 word i;
14926 /* Format of vswitch_t:
14927 0 byte length
14928 1 byte VSWITCHIE
14929 2 byte VSWITCH_REQ/VSWITCH_IND
14930 3 byte reserved
14931 4 word VSwitchcommand
14932 6 word returnerror
14933 8... Params
14934 */
14935 if(!plci ||
14936 !plci->appl ||
14937 !plci->State ||
14938 plci->Sig.Ind==NCR_FACILITY
14939 )
14940 return;
14941
14942 for(i=0;i<MAX_MULTI_IE;i++)
14943 {
14944 if(!parms[i][0]) continue;
14945 if(parms[i][0]<7)
14946 {
14947 parms[i][0]=0; /* kill it */
14948 continue;
14949 }
14950 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14951 switch(parms[i][4])
14952 {
14953 case VSJOIN:
14954 if(!plci->relatedPTYPLCI ||
14955 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14956 { /* Error */
14957 break;
14958 }
14959 /* remember all necessary informations */
14960 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14961 {
14962 break;
14963 }
14964 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14965 { /* first indication after ECT-Request on Consultation Call */
14966 plci->vswitchstate=parms[i][9];
14967 parms[i][9]=2; /* State */
14968 /* now ask first Call to join */
14969 }
14970 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14971 { /* Answer of VSWITCH_REQ from first Call */
14972 plci->vswitchstate=parms[i][9];
14973 /* tell consultation call to join
14974 and the protocol capabilities of the first call */
14975 }
14976 else
14977 { /* Error */
14978 break;
14979 }
14980 plci->vsprot=parms[i][10]; /* protocol */
14981 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14982 /* send join request to related PLCI */
14983 parms[i][1]=VSWITCHIE;
14984 parms[i][2]=VSWITCH_REQ;
14985
14986 plci->relatedPTYPLCI->command = 0;
14987 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14988 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14989 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14990 send_req(plci->relatedPTYPLCI);
14991 break;
14992 case VSTRANSPORT:
14993 default:
14994 if(plci->relatedPTYPLCI &&
14995 plci->vswitchstate==3 &&
14996 plci->relatedPTYPLCI->vswitchstate==3)
14997 {
14998 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14999 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15000 send_req(plci->relatedPTYPLCI);
15001 }
15002 break;
15003 }
15004 parms[i][0]=0; /* kill it */
15005 }
15006}
15007
15008
15009/*------------------------------------------------------------------*/
15010
15011static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
15012 ENTITY e;
15013 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15014
15015 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15016 return (-1);
15017 }
15018
15019 pReq->xdi_dma_descriptor_operation.Req = 0;
15020 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15021
15022 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15023 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15024 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15025 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15026
15027 e.user[0] = plci->adapter->Id - 1;
15028 plci->adapter->request((ENTITY*)pReq);
15029
15030 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15031 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15032 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15033 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15034 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15035 plci->adapter->Id,
15036 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15037 *dma_magic));
15038 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15039 } else {
15040 dbug(1,dprintf("dma_alloc failed"));
15041 return (-1);
15042 }
15043}
15044
15045static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15046 ENTITY e;
15047 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15048
15049 if (nr < 0) {
15050 return;
15051 }
15052
15053 pReq->xdi_dma_descriptor_operation.Req = 0;
15054 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15055
15056 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15057 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15058 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15059 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15060
15061 e.user[0] = plci->adapter->Id - 1;
15062 plci->adapter->request((ENTITY*)pReq);
15063
15064 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15065 dbug(1,dprintf("dma_free(%d)", nr));
15066 } else {
15067 dbug(1,dprintf("dma_free failed (%d)", nr));
15068 }
15069}
15070
15071/*------------------------------------------------------------------*/