3 Copyright (c) Eicon Networks, 2002.
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
8 Eicon File Revision : 2.1
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)
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.
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.
40 #define FILE_ "MESSAGE.C"
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter */
55 /* Macrose defined here have only local meaning */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features
= 0;
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
65 CAPI can request to process all return codes self only if:
66 protocol code supports this && xdi supports this
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))
70 /*------------------------------------------------------------------*/
71 /* local function prototypes */
72 /*------------------------------------------------------------------*/
74 static void group_optimization(DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
);
75 static void set_group_ind_mask(PLCI
*plci
);
76 static void clear_group_ind_mask_bit(PLCI
*plci
, word b
);
77 static byte
test_group_ind_mask_bit(PLCI
*plci
, word b
);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER
*);
79 word
CapiRelease(word
);
80 word
CapiRegister(word
);
81 word
api_put(APPL
*, CAPI_MSG
*);
82 static word
api_parse(byte
*, word
, byte
*, API_PARSE
*);
83 static void api_save_msg(API_PARSE
*in
, byte
*format
, API_SAVE
*out
);
84 static void api_load_msg(API_SAVE
*in
, API_PARSE
*out
);
86 word
api_remove_start(void);
87 void api_remove_complete(void);
89 static void plci_remove(PLCI
*);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER
*a
);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER
*, IDI_SYNC_REQ
*);
93 void callback(ENTITY
*);
95 static void control_rc(PLCI
*, byte
, byte
, byte
, byte
, byte
);
96 static void data_rc(PLCI
*, byte
);
97 static void data_ack(PLCI
*, byte
);
98 static void sig_ind(PLCI
*);
99 static void SendInfo(PLCI
*, dword
, byte
**, byte
);
100 static void SendSetupInfo(APPL
*, PLCI
*, dword
, byte
**, byte
);
101 static void SendSSExtInd(APPL
*, PLCI
*plci
, dword Id
, byte
**parms
);
103 static void VSwitchReqInd(PLCI
*plci
, dword Id
, byte
**parms
);
105 static void nl_ind(PLCI
*);
107 static byte
connect_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
108 static byte
connect_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
109 static byte
connect_a_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
110 static byte
disconnect_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
111 static byte
disconnect_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
112 static byte
listen_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
113 static byte
info_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
114 static byte
info_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
115 static byte
alert_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
116 static byte
facility_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
117 static byte
facility_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
118 static byte
connect_b3_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
119 static byte
connect_b3_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
120 static byte
connect_b3_a_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
121 static byte
disconnect_b3_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
122 static byte
disconnect_b3_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
123 static byte
data_b3_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
124 static byte
data_b3_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
125 static byte
reset_b3_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
126 static byte
reset_b3_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
127 static byte
connect_b3_t90_a_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
128 static byte
select_b_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
129 static byte
manufacturer_req(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
130 static byte
manufacturer_res(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
132 static word
get_plci(DIVA_CAPI_ADAPTER
*);
133 static void add_p(PLCI
*, byte
, byte
*);
134 static void add_s(PLCI
*plci
, byte code
, API_PARSE
*p
);
135 static void add_ss(PLCI
*plci
, byte code
, API_PARSE
*p
);
136 static void add_ie(PLCI
*plci
, byte code
, byte
*p
, word p_length
);
137 static void add_d(PLCI
*, word
, byte
*);
138 static void add_ai(PLCI
*, API_PARSE
*);
139 static word
add_b1(PLCI
*, API_PARSE
*, word
, word
);
140 static word
add_b23(PLCI
*, API_PARSE
*);
141 static word
add_modem_b23(PLCI
*plci
, API_PARSE
*bp_parms
);
142 static void sig_req(PLCI
*, byte
, byte
);
143 static void nl_req_ncci(PLCI
*, byte
, byte
);
144 static void send_req(PLCI
*);
145 static void send_data(PLCI
*);
146 static word
plci_remove_check(PLCI
*);
147 static void listen_check(DIVA_CAPI_ADAPTER
*);
148 static byte
AddInfo(byte
**, byte
**, byte
*, byte
*);
149 static byte
getChannel(API_PARSE
*);
150 static void IndParse(PLCI
*, word
*, byte
**, byte
);
151 static byte
ie_compare(byte
*, byte
*);
152 static word
find_cip(DIVA_CAPI_ADAPTER
*, byte
*, byte
*);
153 static word
CPN_filter_ok(byte
*cpn
, DIVA_CAPI_ADAPTER
*, word
);
158 static void channel_flow_control_remove(PLCI
*plci
);
159 static void channel_x_off(PLCI
*plci
, byte ch
, byte flag
);
160 static void channel_x_on(PLCI
*plci
, byte ch
);
161 static void channel_request_xon(PLCI
*plci
, byte ch
);
162 static void channel_xmit_xon(PLCI
*plci
);
163 static int channel_can_xon(PLCI
*plci
, byte ch
);
164 static void channel_xmit_extended_xon(PLCI
*plci
);
166 static byte
SendMultiIE(PLCI
*plci
, dword Id
, byte
**parms
, byte ie_type
, dword info_mask
, byte setupParse
);
167 static word
AdvCodecSupport(DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, byte
);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER
*, PLCI
*);
169 static void SetVoiceChannel(PLCI
*, byte
*, DIVA_CAPI_ADAPTER
*);
170 static void VoiceChannelOff(PLCI
*plci
);
171 static void adv_voice_write_coefs(PLCI
*plci
, word write_command
);
172 static void adv_voice_clear_config(PLCI
*plci
);
174 static word
get_b1_facilities(PLCI
*plci
, byte b1_resource
);
175 static byte
add_b1_facilities(PLCI
*plci
, byte b1_resource
, word b1_facilities
);
176 static void adjust_b1_facilities(PLCI
*plci
, byte new_b1_resource
, word new_b1_facilities
);
177 static word
adjust_b_process(dword Id
, PLCI
*plci
, byte Rc
);
178 static void adjust_b1_resource(dword Id
, PLCI
*plci
, API_SAVE
*bp_msg
, word b1_facilities
, word internal_command
);
179 static void adjust_b_restore(dword Id
, PLCI
*plci
, byte Rc
);
180 static void reset_b3_command(dword Id
, PLCI
*plci
, byte Rc
);
181 static void select_b_command(dword Id
, PLCI
*plci
, byte Rc
);
182 static void fax_connect_ack_command(dword Id
, PLCI
*plci
, byte Rc
);
183 static void fax_edata_ack_command(dword Id
, PLCI
*plci
, byte Rc
);
184 static void fax_connect_info_command(dword Id
, PLCI
*plci
, byte Rc
);
185 static void fax_adjust_b23_command(dword Id
, PLCI
*plci
, byte Rc
);
186 static void fax_disconnect_command(dword Id
, PLCI
*plci
, byte Rc
);
187 static void hold_save_command(dword Id
, PLCI
*plci
, byte Rc
);
188 static void retrieve_restore_command(dword Id
, PLCI
*plci
, byte Rc
);
189 static void init_b1_config(PLCI
*plci
);
190 static void clear_b1_config(PLCI
*plci
);
192 static void dtmf_command(dword Id
, PLCI
*plci
, byte Rc
);
193 static byte
dtmf_request(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
);
194 static void dtmf_confirmation(dword Id
, PLCI
*plci
);
195 static void dtmf_indication(dword Id
, PLCI
*plci
, byte
*msg
, word length
);
196 static void dtmf_parameter_write(PLCI
*plci
);
199 static void mixer_set_bchannel_id_esc(PLCI
*plci
, byte bchannel_id
);
200 static void mixer_set_bchannel_id(PLCI
*plci
, byte
*chi
);
201 static void mixer_clear_config(PLCI
*plci
);
202 static void mixer_notify_update(PLCI
*plci
, byte others
);
203 static void mixer_command(dword Id
, PLCI
*plci
, byte Rc
);
204 static byte
mixer_request(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
);
205 static void mixer_indication_coefs_set(dword Id
, PLCI
*plci
);
206 static void mixer_indication_xconnect_from(dword Id
, PLCI
*plci
, byte
*msg
, word length
);
207 static void mixer_indication_xconnect_to(dword Id
, PLCI
*plci
, byte
*msg
, word length
);
208 static void mixer_remove(PLCI
*plci
);
211 static void ec_command(dword Id
, PLCI
*plci
, byte Rc
);
212 static byte
ec_request(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
);
213 static void ec_indication(dword Id
, PLCI
*plci
, byte
*msg
, word length
);
216 static void rtp_connect_b3_req_command(dword Id
, PLCI
*plci
, byte Rc
);
217 static void rtp_connect_b3_res_command(dword Id
, PLCI
*plci
, byte Rc
);
220 static int diva_get_dma_descriptor(PLCI
*plci
, dword
*dma_magic
);
221 static void diva_free_dma_descriptor(PLCI
*plci
, int nr
);
223 /*------------------------------------------------------------------*/
224 /* external function prototypes */
225 /*------------------------------------------------------------------*/
227 extern byte
MapController(byte
);
228 extern byte
UnMapController(byte
);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
232 void sendf(APPL
*, word
, dword
, word
, byte
*, ...);
233 void *TransmitBufferSet(APPL
*appl
, dword ref
);
234 void *TransmitBufferGet(APPL
*appl
, void *p
);
235 void TransmitBufferFree(APPL
*appl
, void *p
);
236 void *ReceiveBufferGet(APPL
*appl
, int Num
);
238 int fax_head_line_time(char *buffer
);
241 /*------------------------------------------------------------------*/
242 /* Global data definitions */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter
;
245 extern byte max_appl
;
246 extern DIVA_CAPI_ADAPTER
*adapter
;
247 extern APPL
*application
;
255 static byte remove_started
= false;
256 static PLCI dummy_plci
;
259 static struct _ftable
{
262 byte (*function
)(dword
, word
, DIVA_CAPI_ADAPTER
*, PLCI
*, APPL
*, API_PARSE
*);
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
}
292 static byte
*cip_bc
[29][2] = {
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 */
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 */
325 static byte
*cip_hlc
[29] = {
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 */
358 /*------------------------------------------------------------------*/
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)
367 static byte v120_default_header
[] =
370 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
374 static byte v120_break_header
[] =
377 0xc3 | V120_HEADER_BREAK_BIT
/* Ext, BR , res, res, C2 , C1 , B , F */
382 /*------------------------------------------------------------------*/
383 /* API_PUT function */
384 /*------------------------------------------------------------------*/
386 word
api_put(APPL
*appl
, CAPI_MSG
*msg
)
392 DIVA_CAPI_ADAPTER
*a
;
397 API_PARSE msg_parms
[MAX_MSG_PARMS
+ 1];
399 if (msg
->header
.length
< sizeof(msg
->header
) ||
400 msg
->header
.length
> MAX_MSG_SIZE
) {
401 dbug(1, dprintf("bad len"));
405 controller
= (byte
)((msg
->header
.controller
& 0x7f) - 1);
407 /* controller starts with 0 up to (max_adapter - 1) */
408 if (controller
>= max_adapter
)
410 dbug(1, dprintf("invalid ctrl"));
414 a
= &adapter
[controller
];
416 if ((msg
->header
.plci
!= 0) && (msg
->header
.plci
<= a
->max_plci
) && !a
->adapter_disabled
)
418 dbug(1, dprintf("plci=%x", msg
->header
.plci
));
419 plci
= &a
->plci
[msg
->header
.plci
- 1];
420 ncci
= GET_WORD(&msg
->header
.ncci
);
423 || (plci
->State
== INC_CON_PENDING
)
424 || (plci
->State
== INC_CON_ALERT
)
425 || (msg
->header
.command
== (_DISCONNECT_I
| RESPONSE
)))
427 || (msg
->header
.command
== (_DISCONNECT_B3_I
| RESPONSE
))
428 || ((ncci
< MAX_NCCI
+ 1) && (a
->ncci_plci
[ncci
] == plci
->Id
))))
430 i
= plci
->msg_in_read_pos
;
431 j
= plci
->msg_in_write_pos
;
434 if (j
+ msg
->header
.length
+ MSG_IN_OVERHEAD
<= MSG_IN_QUEUE_SIZE
)
435 i
+= MSG_IN_QUEUE_SIZE
- j
;
442 n
= (((CAPI_MSG
*)(plci
->msg_in_queue
))->header
.length
+ MSG_IN_OVERHEAD
+ 3) & 0xfffc;
444 if (i
> MSG_IN_QUEUE_SIZE
- n
)
445 i
= MSG_IN_QUEUE_SIZE
- n
+ 1;
449 if (i
<= ((msg
->header
.length
+ MSG_IN_OVERHEAD
+ 3) & 0xfffc))
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
));
459 if ((((byte
*) msg
) < ((byte
*)(plci
->msg_in_queue
)))
460 || (((byte
*) msg
) >= ((byte
*)(plci
->msg_in_queue
)) + sizeof(plci
->msg_in_queue
)))
462 if (plci
->msg_in_write_pos
!= plci
->msg_in_read_pos
)
465 if (msg
->header
.command
== _DATA_B3_R
)
467 if (msg
->header
.length
< 20)
469 dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg
->header
.length
));
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
)
478 if (k
== plci
->msg_in_wrap_pos
)
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
))
484 if (((CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[k
]))->info
.data_b3_req
.Flags
& 0x0004)
488 k
+= (((CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[k
]))->header
.length
+
489 MSG_IN_OVERHEAD
+ 3) & 0xfffc;
492 if ((n
>= MAX_DATA_B3
) || (l
>= MAX_DATA_ACK
))
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
));
499 if (plci
->req_in
|| plci
->internal_command
)
501 if ((((byte
*) msg
) >= ((byte
*)(plci
->msg_in_queue
)))
502 && (((byte
*) msg
) < ((byte
*)(plci
->msg_in_queue
)) + sizeof(plci
->msg_in_queue
)))
504 dbug(0, dprintf("Q-FULL3(requeue)"));
513 if (plci
->req_in
|| plci
->internal_command
)
517 plci
->command
= msg
->header
.command
;
518 plci
->number
= msg
->header
.number
;
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
));
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
)
535 m
->info
.data_b3_req
.Data
= (dword
)(long)(TransmitBufferSet(appl
, m
->info
.data_b3_req
.Data
));
539 j
= (j
+ 3) & 0xfffc;
541 *((APPL
**)(&((byte
*)(plci
->msg_in_queue
))[j
])) = appl
;
542 plci
->msg_in_write_pos
= j
+ MSG_IN_OVERHEAD
;
551 dbug(1, dprintf("com=%x", msg
->header
.command
));
553 for (j
= 0; j
< MAX_MSG_PARMS
+ 1; j
++) msg_parms
[j
].length
= 0;
554 for (i
= 0, ret
= _BAD_MSG
; i
< ARRAY_SIZE(ftable
); i
++) {
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
)) {
563 for (j
= 0; j
< MAX_MSG_PARMS
+ 1; j
++) msg_parms
[j
].length
= 0;
567 dbug(1, dprintf("BAD_MSG"));
568 if (plci
) plci
->command
= 0;
573 c
= ftable
[i
].function(GET_DWORD(&msg
->header
.controller
),
580 channel_xmit_extended_xon(plci
);
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;
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages */
591 /*------------------------------------------------------------------*/
593 static word
api_parse(byte
*msg
, word length
, byte
*format
, API_PARSE
*parms
)
598 for (i
= 0, p
= 0; format
[i
]; i
++) {
601 parms
[i
].info
= &msg
[p
];
614 if (msg
[p
] == 0xff) {
616 parms
[i
].length
= msg
[p
+ 1] + (msg
[p
+ 2] << 8);
617 p
+= (parms
[i
].length
+ 3);
620 parms
[i
].length
= msg
[p
];
621 p
+= (parms
[i
].length
+ 1);
626 if (p
> length
) return true;
628 if (parms
) parms
[i
].info
= NULL
;
632 static void api_save_msg(API_PARSE
*in
, byte
*format
, API_SAVE
*out
)
638 for (i
= 0; format
[i
] != '\0'; i
++)
640 out
->parms
[i
].info
= p
;
641 out
->parms
[i
].length
= in
[i
].length
;
654 n
= in
[i
].length
+ 1;
657 for (j
= 0; j
< n
; j
++)
658 *(p
++) = in
[i
].info
[j
];
660 out
->parms
[i
].info
= NULL
;
661 out
->parms
[i
].length
= 0;
664 static void api_load_msg(API_SAVE
*in
, API_PARSE
*out
)
671 out
[i
].info
= in
->parms
[i
].info
;
672 out
[i
].length
= in
->parms
[i
].length
;
673 } while (in
->parms
[i
++].info
);
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function */
679 /*------------------------------------------------------------------*/
681 word
api_remove_start(void)
686 if (!remove_started
) {
687 remove_started
= true;
688 for (i
= 0; i
< max_adapter
; i
++) {
689 if (adapter
[i
].request
) {
690 for (j
= 0; j
< adapter
[i
].max_plci
; j
++) {
691 if (adapter
[i
].plci
[j
].Sig
.Id
) plci_remove(&adapter
[i
].plci
[j
]);
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;
706 api_remove_complete();
711 /*------------------------------------------------------------------*/
712 /* internal command queue */
713 /*------------------------------------------------------------------*/
715 static void init_internal_command_queue(PLCI
*plci
)
719 dbug(1, dprintf("%s,%d: init_internal_command_queue",
720 (char *)(FILE_
), __LINE__
));
722 plci
->internal_command
= 0;
723 for (i
= 0; i
< MAX_INTERNAL_COMMAND_LEVELS
; i
++)
724 plci
->internal_command_queue
[i
] = NULL
;
728 static void start_internal_command(dword Id
, PLCI
*plci
, t_std_internal_command command_function
)
732 dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
735 if (plci
->internal_command
== 0)
737 plci
->internal_command_queue
[0] = command_function
;
738 (*command_function
)(Id
, plci
, OK
);
743 while (plci
->internal_command_queue
[i
] != NULL
)
745 plci
->internal_command_queue
[i
] = command_function
;
750 static void next_internal_command(dword Id
, PLCI
*plci
)
754 dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
757 plci
->internal_command
= 0;
758 plci
->internal_command_queue
[0] = NULL
;
759 while (plci
->internal_command_queue
[1] != NULL
)
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)
767 plci
->internal_command_queue
[0] = NULL
;
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function */
774 /*------------------------------------------------------------------*/
776 static dword ncci_mapping_bug
= 0;
778 static word
get_ncci(PLCI
*plci
, byte ch
, word force_ncci
)
780 DIVA_CAPI_ADAPTER
*a
;
784 if (!ch
|| a
->ch_ncci
[ch
])
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
]));
797 if ((ch
< MAX_NCCI
+ 1) && !a
->ncci_ch
[ch
])
802 while ((ncci
< MAX_NCCI
+ 1) && a
->ncci_ch
[ncci
])
804 if (ncci
== MAX_NCCI
+ 1)
811 while ((j
< MAX_NCCI
+ 1) && (a
->ncci_ch
[j
] != i
))
814 if (j
< MAX_NCCI
+ 1)
819 } while ((j
< MAX_NCCI
+ 1) && (a
->ncci_ch
[j
] != i
));
821 } while ((i
< MAX_NL_CHANNEL
+ 1) && (j
< MAX_NCCI
+ 1));
822 if (i
< MAX_NL_CHANNEL
+ 1)
824 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 ncci_mapping_bug
, ch
, force_ncci
, i
, k
, j
));
829 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830 ncci_mapping_bug
, ch
, force_ncci
));
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
;
840 a
->ncci_next
[ncci
] = a
->ncci_next
[plci
->ncci_ring_list
];
841 a
->ncci_next
[plci
->ncci_ring_list
] = (byte
) ncci
;
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
));
852 static void ncci_free_receive_buffers(PLCI
*plci
, word ncci
)
854 DIVA_CAPI_ADAPTER
*a
;
860 Id
= (((dword
) ncci
) << 16) | (((word
)(plci
->Id
)) << 8) | a
->Id
;
863 if (a
->ncci_plci
[ncci
] == plci
->Id
)
868 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869 ncci_mapping_bug
, Id
));
874 ncci_code
= ncci
| (((word
) a
->Id
) << 8);
875 for (i
= 0; i
< appl
->MaxBuffer
; i
++)
877 if ((appl
->DataNCCI
[i
] == ncci_code
)
878 && (((byte
)(appl
->DataFlags
[i
] >> 8)) == plci
->Id
))
880 appl
->DataNCCI
[i
] = 0;
888 for (ncci
= 1; ncci
< MAX_NCCI
+ 1; ncci
++)
890 if (a
->ncci_plci
[ncci
] == plci
->Id
)
895 dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896 ncci_mapping_bug
, Id
));
901 ncci_code
= ncci
| (((word
) a
->Id
) << 8);
902 for (i
= 0; i
< appl
->MaxBuffer
; i
++)
904 if ((appl
->DataNCCI
[i
] == ncci_code
)
905 && (((byte
)(appl
->DataFlags
[i
] >> 8)) == plci
->Id
))
907 appl
->DataNCCI
[i
] = 0;
917 static void cleanup_ncci_data(PLCI
*plci
, word ncci
)
921 if (ncci
&& (plci
->adapter
->ncci_plci
[ncci
] == plci
->Id
))
923 ncci_ptr
= &(plci
->adapter
->ncci
[ncci
]);
926 while (ncci_ptr
->data_pending
!= 0)
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
)--;
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;
944 static void ncci_remove(PLCI
*plci
, word ncci
, byte preserve_ncci
)
946 DIVA_CAPI_ADAPTER
*a
;
951 Id
= (((dword
) ncci
) << 16) | (((word
)(plci
->Id
)) << 8) | a
->Id
;
953 ncci_free_receive_buffers(plci
, ncci
);
956 if (a
->ncci_plci
[ncci
] != plci
->Id
)
959 dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 ncci_mapping_bug
, Id
, preserve_ncci
));
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;
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
))
976 if ((i
!= 0) && (a
->ncci_next
[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
];
984 a
->ncci_next
[ncci
] = 0;
990 for (ncci
= 1; ncci
< MAX_NCCI
+ 1; ncci
++)
992 if (a
->ncci_plci
[ncci
] == plci
->Id
)
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;
1000 a
->ncci_ch
[ncci
] = 0;
1001 a
->ncci_plci
[ncci
] = 0;
1002 a
->ncci_state
[ncci
] = IDLE
;
1003 a
->ncci_next
[ncci
] = 0;
1008 plci
->ncci_ring_list
= 0;
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function */
1015 /*------------------------------------------------------------------*/
1017 static void plci_free_msg_in_queue(PLCI
*plci
)
1023 i
= plci
->msg_in_read_pos
;
1024 while (i
!= plci
->msg_in_write_pos
)
1026 if (i
== plci
->msg_in_wrap_pos
)
1028 if (((CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[i
]))->header
.command
== _DATA_B3_R
)
1031 TransmitBufferFree(plci
->appl
,
1032 (byte
*)(long)(((CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[i
]))->info
.data_b3_req
.Data
));
1036 i
+= (((CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[i
]))->header
.length
+
1037 MSG_IN_OVERHEAD
+ 3) & 0xfffc;
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
;
1047 static void plci_remove(PLCI
*plci
)
1051 dbug(1, dprintf("plci_remove(no plci)"));
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
))
1060 if (plci
->Sig
.Id
== 0xff)
1062 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci
->NL
.Id
));
1063 if (plci
->NL
.Id
&& !plci
->nl_remove_id
)
1065 nl_req_ncci(plci
, REMOVE
, 0);
1071 if (!plci
->sig_remove_id
1073 || (plci
->req_in
!= plci
->req_out
)
1074 || (plci
->nl_req
|| plci
->sig_req
)))
1076 sig_req(plci
, HANGUP
, 0);
1080 ncci_remove(plci
, 0, false);
1081 plci_free_msg_in_queue(plci
);
1085 if ((plci
->State
== INC_CON_PENDING
) || (plci
->State
== INC_CON_ALERT
))
1086 plci
->State
= OUTG_DIS_PENDING
;
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers */
1091 /*------------------------------------------------------------------*/
1093 static void set_group_ind_mask(PLCI
*plci
)
1097 for (i
= 0; i
< C_IND_MASK_DWORDS
; i
++)
1098 plci
->group_optimization_mask_table
[i
] = 0xffffffffL
;
1101 static void clear_group_ind_mask_bit(PLCI
*plci
, word b
)
1103 plci
->group_optimization_mask_table
[b
>> 5] &= ~(1L << (b
& 0x1f));
1106 static byte
test_group_ind_mask_bit(PLCI
*plci
, word b
)
1108 return ((plci
->group_optimization_mask_table
[b
>> 5] & (1L << (b
& 0x1f))) != 0);
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL */
1113 /*------------------------------------------------------------------*/
1115 static void clear_c_ind_mask(PLCI
*plci
)
1119 for (i
= 0; i
< C_IND_MASK_DWORDS
; i
++)
1120 plci
->c_ind_mask_table
[i
] = 0;
1123 static byte
c_ind_mask_empty(PLCI
*plci
)
1128 while ((i
< C_IND_MASK_DWORDS
) && (plci
->c_ind_mask_table
[i
] == 0))
1130 return (i
== C_IND_MASK_DWORDS
);
1133 static void set_c_ind_mask_bit(PLCI
*plci
, word b
)
1135 plci
->c_ind_mask_table
[b
>> 5] |= (1L << (b
& 0x1f));
1138 static void clear_c_ind_mask_bit(PLCI
*plci
, word b
)
1140 plci
->c_ind_mask_table
[b
>> 5] &= ~(1L << (b
& 0x1f));
1143 static byte
test_c_ind_mask_bit(PLCI
*plci
, word b
)
1145 return ((plci
->c_ind_mask_table
[b
>> 5] & (1L << (b
& 0x1f))) != 0);
1148 static void dump_c_ind_mask(PLCI
*plci
)
1155 for (i
= 0; i
< C_IND_MASK_DWORDS
; i
+= 4)
1159 for (j
= 0; j
< 4; j
++)
1161 if (i
+ j
< C_IND_MASK_DWORDS
)
1163 d
= plci
->c_ind_mask_table
[i
+ j
];
1164 for (k
= 0; k
< 8; k
++)
1166 *(--p
) = hex_asc_lo(d
);
1172 for (k
= 0; k
< 8; k
++)
1177 dbug(1, dprintf("c_ind_mask =%s", (char *) p
));
1185 #define dump_plcis(a)
1189 /*------------------------------------------------------------------*/
1190 /* translation function for each message */
1191 /*------------------------------------------------------------------*/
1193 static byte
connect_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1194 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
1202 API_PARSE ai_parms
[5];
1206 static byte esc_chi
[35] = {0x02, 0x18, 0x01};
1207 static byte lli
[2] = {0x01, 0x00};
1212 for (i
= 0; i
< 5; i
++) ai_parms
[i
].length
= 0;
1214 dbug(1, dprintf("connect_req(%d)", parms
->length
));
1215 Info
= _WRONG_IDENTIFIER
;
1218 if (a
->adapter_disabled
)
1220 dbug(1, dprintf("adapter disabled"));
1221 Id
= ((word
)1 << 8) | a
->Id
;
1222 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
, Number
, "w", 0);
1223 sendf(appl
, _DISCONNECT_I
, Id
, 0, "w", _L1_ERROR
);
1226 Info
= _OUT_OF_PLCI
;
1227 if ((i
= get_plci(a
)))
1230 plci
= &a
->plci
[i
- 1];
1232 plci
->call_dir
= CALL_DIR_OUT
| CALL_DIR_ORIGINATE
;
1233 /* check 'external controller' bit for codec support */
1234 if (Id
& EXT_CONTROLLER
)
1236 if (AdvCodecSupport(a
, plci
, appl
, 0))
1239 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
, Number
, "w", _WRONG_IDENTIFIER
);
1246 if (bp
->length
)LinkLayer
= bp
->info
[3];
1251 if (!api_parse(&ai
->info
[1], (word
)ai
->length
, "ssss", ai_parms
))
1254 if (ai_parms
[0].length
)
1256 ch
= GET_WORD(ai_parms
[0].info
+ 1);
1257 if (ch
> 4) ch
= 0; /* safety -> ignore ChannelID */
1258 if (ch
== 4) /* explizit CHI in message */
1260 /* check length of B-CH struct */
1261 if ((ai_parms
[0].info
)[3] >= 1)
1263 if ((ai_parms
[0].info
)[4] == CHI
)
1265 p_chi
= &((ai_parms
[0].info
)[5]);
1269 p_chi
= &((ai_parms
[0].info
)[3]);
1271 if (p_chi
[0] > 35) /* check length of channel ID */
1273 Info
= _WRONG_MESSAGE_FORMAT
;
1276 else Info
= _WRONG_MESSAGE_FORMAT
;
1279 if (ch
== 3 && ai_parms
[0].length
>= 7 && ai_parms
[0].length
<= 36)
1281 dir
= GET_WORD(ai_parms
[0].info
+ 3);
1284 for (i
= 0; i
+ 5 <= ai_parms
[0].length
; i
++)
1286 if (ai_parms
[0].info
[i
+ 5] != 0)
1288 if ((ai_parms
[0].info
[i
+ 5] | m
) != 0xff)
1289 Info
= _WRONG_MESSAGE_FORMAT
;
1300 Info
= _WRONG_MESSAGE_FORMAT
;
1303 if ((ai_parms
[0].length
== 36) || (ch_mask
!= ((dword
)(1L << channel
))))
1305 esc_chi
[0] = (byte
)(ai_parms
[0].length
- 2);
1306 for (i
= 0; i
+ 5 <= ai_parms
[0].length
; i
++)
1307 esc_chi
[i
+ 3] = ai_parms
[0].info
[i
+ 5];
1311 esc_chi
[2] = (byte
)channel
;
1312 plci
->b_channel
= (byte
)channel
; /* not correct for ETSI ch 17..31 */
1313 add_p(plci
, LLI
, lli
);
1314 add_p(plci
, ESC
, esc_chi
);
1315 plci
->State
= LOCAL_CONNECT
;
1316 if (!dir
) plci
->call_dir
|= CALL_DIR_FORCE_OUTG_NL
; /* dir 0=DTE, 1=DCE */
1321 else Info
= _WRONG_MESSAGE_FORMAT
;
1324 dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch
, dir
, channel
));
1325 plci
->command
= _CONNECT_R
;
1326 plci
->number
= Number
;
1327 /* x.31 or D-ch free SAPI in LinkLayer? */
1328 if (ch
== 1 && LinkLayer
!= 3 && LinkLayer
!= 12) noCh
= true;
1329 if ((ch
== 0 || ch
== 2 || noCh
|| ch
== 3 || ch
== 4) && !Info
)
1331 /* B-channel used for B3 connections (ch==0), or no B channel */
1332 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1333 if (noCh
) Info
= add_b1(plci
, &parms
[5], 2, 0); /* no resource */
1334 else Info
= add_b1(plci
, &parms
[5], ch
, 0);
1335 add_s(plci
, OAD
, &parms
[2]);
1336 add_s(plci
, OSA
, &parms
[4]);
1337 add_s(plci
, BC
, &parms
[6]);
1338 add_s(plci
, LLC
, &parms
[7]);
1339 add_s(plci
, HLC
, &parms
[8]);
1340 if (a
->Info_Mask
[appl
->Id
- 1] & 0x200)
1342 /* early B3 connect (CIP mask bit 9) no release after a disc */
1343 add_p(plci
, LLI
, "\x01\x01");
1345 if (GET_WORD(parms
[0].info
) < 29) {
1346 add_p(plci
, BC
, cip_bc
[GET_WORD(parms
[0].info
)][a
->u_law
]);
1347 add_p(plci
, HLC
, cip_hlc
[GET_WORD(parms
[0].info
)]);
1349 add_p(plci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
1350 sig_req(plci
, ASSIGN
, DSIG_ID
);
1354 /* D-Channel used for B3 connections */
1355 plci
->Sig
.Id
= 0xff;
1359 if (!Info
&& ch
!= 2 && !noCh
) {
1360 Info
= add_b23(plci
, &parms
[5]);
1362 if (!(plci
->tel
&& !plci
->adv_nl
))nl_req_ncci(plci
, ASSIGN
, 0);
1368 if (ch
== 0 || ch
== 2 || ch
== 3 || noCh
|| ch
== 4)
1370 if (plci
->spoofed_msg
== SPOOFING_REQUIRED
)
1372 api_save_msg(parms
, "wsssssssss", &plci
->saved_msg
);
1373 plci
->spoofed_msg
= CALL_REQ
;
1374 plci
->internal_command
= BLOCK_PLCI
;
1376 dbug(1, dprintf("Spoof"));
1380 if (ch
== 4)add_p(plci
, CHI
, p_chi
);
1381 add_s(plci
, CPN
, &parms
[1]);
1382 add_s(plci
, DSA
, &parms
[3]);
1383 if (noCh
) add_p(plci
, ESC
, "\x02\x18\xfd"); /* D-channel, no B-L3 */
1384 add_ai(plci
, &parms
[9]);
1385 if (!dir
)sig_req(plci
, CALL_REQ
, 0);
1388 plci
->command
= PERM_LIST_REQ
;
1390 sig_req(plci
, LISTEN_REQ
, 0);
1402 _CONNECT_R
| CONFIRM
,
1409 static byte
connect_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1410 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
1414 static byte cau_t
[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1415 static byte esc_t
[] = {0x03, 0x08, 0x00, 0x00};
1417 API_PARSE ai_parms
[5];
1421 dbug(1, dprintf("connect_res(no plci)"));
1422 return 0; /* no plci, no send */
1425 dbug(1, dprintf("connect_res(State=0x%x)", plci
->State
));
1426 for (i
= 0; i
< 5; i
++) ai_parms
[i
].length
= 0;
1428 dbug(1, dprintf("ai->length=%d", ai
->length
));
1432 if (!api_parse(&ai
->info
[1], (word
)ai
->length
, "ssss", ai_parms
))
1434 dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms
[0].length
, GET_WORD(ai_parms
[0].info
+ 1)));
1436 if (ai_parms
[0].length
)
1438 ch
= GET_WORD(ai_parms
[0].info
+ 1);
1439 dbug(1, dprintf("BCH-I=0x%x", ch
));
1444 if (plci
->State
== INC_CON_CONNECTED_ALERT
)
1446 dbug(1, dprintf("Connected Alert Call_Res"));
1447 if (a
->Info_Mask
[appl
->Id
- 1] & 0x200)
1449 /* early B3 connect (CIP mask bit 9) no release after a disc */
1450 add_p(plci
, LLI
, "\x01\x01");
1452 add_s(plci
, CONN_NR
, &parms
[2]);
1453 add_s(plci
, LLC
, &parms
[4]);
1454 add_ai(plci
, &parms
[5]);
1455 plci
->State
= INC_CON_ACCEPT
;
1456 sig_req(plci
, CALL_RES
, 0);
1459 else if (plci
->State
== INC_CON_PENDING
|| plci
->State
== INC_CON_ALERT
) {
1460 clear_c_ind_mask_bit(plci
, (word
)(appl
->Id
- 1));
1461 dump_c_ind_mask(plci
);
1462 Reject
= GET_WORD(parms
[0].info
);
1463 dbug(1, dprintf("Reject=0x%x", Reject
));
1466 if (c_ind_mask_empty(plci
))
1468 if ((Reject
& 0xff00) == 0x3400)
1470 esc_t
[2] = ((byte
)(Reject
& 0x00ff)) | 0x80;
1471 add_p(plci
, ESC
, esc_t
);
1472 add_ai(plci
, &parms
[5]);
1473 sig_req(plci
, REJECT
, 0);
1475 else if (Reject
== 1 || Reject
>= 9)
1477 add_ai(plci
, &parms
[5]);
1478 sig_req(plci
, HANGUP
, 0);
1482 esc_t
[2] = cau_t
[(Reject
&0x000f)];
1483 add_p(plci
, ESC
, esc_t
);
1484 add_ai(plci
, &parms
[5]);
1485 sig_req(plci
, REJECT
, 0);
1491 sendf(appl
, _DISCONNECT_I
, Id
, 0, "w", _OTHER_APPL_CONNECTED
);
1496 if (Id
& EXT_CONTROLLER
) {
1497 if (AdvCodecSupport(a
, plci
, appl
, 0)) {
1498 dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1499 sig_req(plci
, HANGUP
, 0);
1502 if (plci
->tel
== ADV_VOICE
&& a
->AdvCodecPLCI
)
1504 Info
= add_b23(plci
, &parms
[1]);
1507 dbug(1, dprintf("connect_res(error from add_b23)"));
1508 sig_req(plci
, HANGUP
, 0);
1513 nl_req_ncci(plci
, ASSIGN
, 0);
1522 Info
= add_b23(plci
, &parms
[1]);
1525 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1526 sig_req(plci
, HANGUP
, 0);
1530 nl_req_ncci(plci
, ASSIGN
, 0);
1533 if (plci
->spoofed_msg
== SPOOFING_REQUIRED
)
1535 api_save_msg(parms
, "wsssss", &plci
->saved_msg
);
1536 plci
->spoofed_msg
= CALL_RES
;
1537 plci
->internal_command
= BLOCK_PLCI
;
1539 dbug(1, dprintf("Spoof"));
1543 add_b1(plci
, &parms
[1], ch
, plci
->B1_facilities
);
1544 if (a
->Info_Mask
[appl
->Id
- 1] & 0x200)
1546 /* early B3 connect (CIP mask bit 9) no release after a disc */
1547 add_p(plci
, LLI
, "\x01\x01");
1549 add_s(plci
, CONN_NR
, &parms
[2]);
1550 add_s(plci
, LLC
, &parms
[4]);
1551 add_ai(plci
, &parms
[5]);
1552 plci
->State
= INC_CON_ACCEPT
;
1553 sig_req(plci
, CALL_RES
, 0);
1556 for (i
= 0; i
< max_appl
; i
++) {
1557 if (test_c_ind_mask_bit(plci
, i
)) {
1558 sendf(&application
[i
], _DISCONNECT_I
, Id
, 0, "w", _OTHER_APPL_CONNECTED
);
1566 static byte
connect_a_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1567 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1569 dbug(1, dprintf("connect_a_res"));
1573 static byte
disconnect_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1574 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1579 dbug(1, dprintf("disconnect_req"));
1581 Info
= _WRONG_IDENTIFIER
;
1585 if (plci
->State
== INC_CON_PENDING
|| plci
->State
== INC_CON_ALERT
)
1587 clear_c_ind_mask_bit(plci
, (word
)(appl
->Id
- 1));
1589 for (i
= 0; i
< max_appl
; i
++)
1591 if (test_c_ind_mask_bit(plci
, i
))
1592 sendf(&application
[i
], _DISCONNECT_I
, Id
, 0, "w", 0);
1594 plci
->State
= OUTG_DIS_PENDING
;
1596 if (plci
->Sig
.Id
&& plci
->appl
)
1599 if (plci
->Sig
.Id
!= 0xff)
1601 if (plci
->State
!= INC_DIS_PENDING
)
1603 add_ai(plci
, &msg
[0]);
1604 sig_req(plci
, HANGUP
, 0);
1605 plci
->State
= OUTG_DIS_PENDING
;
1611 if (plci
->NL
.Id
&& !plci
->nl_remove_id
)
1614 nl_req_ncci(plci
, REMOVE
, 0);
1615 sendf(appl
, _DISCONNECT_R
| CONFIRM
, Id
, Number
, "w", 0);
1616 sendf(appl
, _DISCONNECT_I
, Id
, 0, "w", 0);
1617 plci
->State
= INC_DIS_PENDING
;
1624 if (!appl
) return false;
1625 sendf(appl
, _DISCONNECT_R
| CONFIRM
, Id
, Number
, "w", Info
);
1629 static byte
disconnect_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1630 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1632 dbug(1, dprintf("disconnect_res"));
1635 /* clear ind mask bit, just in case of collsion of */
1636 /* DISCONNECT_IND and CONNECT_RES */
1637 clear_c_ind_mask_bit(plci
, (word
)(appl
->Id
- 1));
1638 ncci_free_receive_buffers(plci
, 0);
1639 if (plci_remove_check(plci
))
1643 if (plci
->State
== INC_DIS_PENDING
1644 || plci
->State
== SUSPENDING
) {
1645 if (c_ind_mask_empty(plci
)) {
1646 if (plci
->State
!= SUSPENDING
) plci
->State
= IDLE
;
1647 dbug(1, dprintf("chs=%d", plci
->channels
));
1648 if (!plci
->channels
) {
1657 static byte
listen_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1658 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
1663 dbug(1, dprintf("listen_req(Appl=0x%x)", appl
->Id
));
1665 Info
= _WRONG_IDENTIFIER
;
1668 a
->Info_Mask
[appl
->Id
- 1] = GET_DWORD(parms
[0].info
);
1669 a
->CIP_Mask
[appl
->Id
- 1] = GET_DWORD(parms
[1].info
);
1670 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms
[1].info
)));
1671 if (a
->Info_Mask
[appl
->Id
- 1] & 0x200) { /* early B3 connect provides */
1672 a
->Info_Mask
[appl
->Id
- 1] |= 0x10; /* call progression infos */
1675 /* check if external controller listen and switch listen on or off*/
1676 if (Id
&EXT_CONTROLLER
&& GET_DWORD(parms
[1].info
)) {
1677 if (a
->profile
.Global_Options
& ON_BOARD_CODEC
) {
1678 dummy_plci
.State
= IDLE
;
1679 a
->codec_listen
[appl
->Id
- 1] = &dummy_plci
;
1680 a
->TelOAD
[0] = (byte
)(parms
[3].length
);
1681 for (i
= 1; parms
[3].length
>= i
&& i
< 22; i
++) {
1682 a
->TelOAD
[i
] = parms
[3].info
[i
];
1685 a
->TelOSA
[0] = (byte
)(parms
[4].length
);
1686 for (i
= 1; parms
[4].length
>= i
&& i
< 22; i
++) {
1687 a
->TelOSA
[i
] = parms
[4].info
[i
];
1691 else Info
= 0x2002; /* wrong controller, codec not supported */
1693 else{ /* clear listen */
1694 a
->codec_listen
[appl
->Id
- 1] = (PLCI
*)0;
1698 _LISTEN_R
| CONFIRM
,
1703 if (a
) listen_check(a
);
1707 static byte
info_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1708 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1712 PLCI
*rc_plci
= NULL
;
1713 API_PARSE ai_parms
[5];
1716 dbug(1, dprintf("info_req"));
1717 for (i
= 0; i
< 5; i
++) ai_parms
[i
].length
= 0;
1723 if (api_parse(&ai
->info
[1], (word
)ai
->length
, "ssss", ai_parms
))
1725 dbug(1, dprintf("AddInfo wrong"));
1726 Info
= _WRONG_MESSAGE_FORMAT
;
1729 if (!a
) Info
= _WRONG_STATE
;
1732 { /* no fac, with CPN, or KEY */
1734 if (!ai_parms
[3].length
&& plci
->State
&& (msg
[0].length
|| ai_parms
[1].length
))
1736 /* overlap sending option */
1737 dbug(1, dprintf("OvlSnd"));
1738 add_s(plci
, CPN
, &msg
[0]);
1739 add_s(plci
, KEY
, &ai_parms
[1]);
1740 sig_req(plci
, INFO_REQ
, 0);
1745 if (plci
->State
&& ai_parms
[2].length
)
1747 /* User_Info option */
1748 dbug(1, dprintf("UUI"));
1749 add_s(plci
, UUI
, &ai_parms
[2]);
1750 sig_req(plci
, USER_DATA
, 0);
1752 else if (plci
->State
&& ai_parms
[3].length
)
1754 /* Facility option */
1755 dbug(1, dprintf("FAC"));
1756 add_s(plci
, CPN
, &msg
[0]);
1757 add_ai(plci
, &msg
[1]);
1758 sig_req(plci
, FACILITY_REQ
, 0);
1762 Info
= _WRONG_STATE
;
1765 else if ((ai_parms
[1].length
|| ai_parms
[2].length
|| ai_parms
[3].length
) && !Info
)
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1, dprintf("NCR_FAC"));
1769 if ((i
= get_plci(a
)))
1771 rc_plci
= &a
->plci
[i
- 1];
1772 appl
->NullCREnable
= true;
1773 rc_plci
->internal_command
= C_NCR_FAC_REQ
;
1774 rc_plci
->appl
= appl
;
1775 add_p(rc_plci
, CAI
, "\x01\x80");
1776 add_p(rc_plci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci
, ASSIGN
, DSIG_ID
);
1782 Info
= _OUT_OF_PLCI
;
1787 add_s(rc_plci
, CPN
, &msg
[0]);
1788 add_ai(rc_plci
, &msg
[1]);
1789 sig_req(rc_plci
, NCR_FACILITY
, 0);
1792 /* for application controlled supplementary services */
1798 Info
= _WRONG_MESSAGE_FORMAT
;
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1, dprintf("localInfoCon"));
1817 static byte
info_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1818 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1820 dbug(1, dprintf("info_res"));
1824 static byte
alert_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1825 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1830 dbug(1, dprintf("alert_req"));
1832 Info
= _WRONG_IDENTIFIER
;
1835 Info
= _ALERT_IGNORED
;
1836 if (plci
->State
!= INC_CON_ALERT
) {
1837 Info
= _WRONG_STATE
;
1838 if (plci
->State
== INC_CON_PENDING
) {
1840 plci
->State
= INC_CON_ALERT
;
1841 add_ai(plci
, &msg
[0]);
1842 sig_req(plci
, CALL_ALERT
, 0);
1855 static byte
facility_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
1856 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
1863 long relatedPLCIvalue
;
1864 DIVA_CAPI_ADAPTER
*relatedadapter
;
1866 byte RCparms
[] = "\x05\x00\x00\x02\x00\x00";
1867 byte SSstruct
[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1869 API_PARSE ss_parms
[11];
1875 dbug(1, dprintf("facility_req"));
1876 for (i
= 0; i
< 9; i
++) ss_parms
[i
].length
= 0;
1882 dbug(1, dprintf("wrong Ctrl"));
1883 Info
= _WRONG_IDENTIFIER
;
1886 selector
= GET_WORD(msg
[0].info
);
1892 case SELECTOR_HANDSET
:
1893 Info
= AdvCodecSupport(a
, plci
, appl
, HOOK_SUPPORT
);
1896 case SELECTOR_SU_SERV
:
1899 Info
= _WRONG_MESSAGE_FORMAT
;
1902 SSreq
= GET_WORD(&(msg
[1].info
[1]));
1903 PUT_WORD(&RCparms
[1], SSreq
);
1907 case S_GET_SUPPORTED_SERVICES
:
1908 if ((i
= get_plci(a
)))
1910 rplci
= &a
->plci
[i
- 1];
1912 add_p(rplci
, CAI
, "\x01\x80");
1913 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
1914 sig_req(rplci
, ASSIGN
, DSIG_ID
);
1919 PUT_DWORD(&SSstruct
[6], MASK_TERMINAL_PORTABILITY
);
1920 SSparms
= (byte
*)SSstruct
;
1923 rplci
->internal_command
= GETSERV_REQ_PEND
;
1924 rplci
->number
= Number
;
1926 sig_req(rplci
, S_SUPPORTED
, 0);
1932 if (parms
->length
== 7)
1934 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbd", ss_parms
))
1936 dbug(1, dprintf("format wrong"));
1937 Info
= _WRONG_MESSAGE_FORMAT
;
1943 Info
= _WRONG_MESSAGE_FORMAT
;
1946 a
->Notification_Mask
[appl
->Id
- 1] = GET_DWORD(ss_parms
[2].info
);
1947 if (a
->Notification_Mask
[appl
->Id
- 1] & SMASK_MWI
) /* MWI active? */
1949 if ((i
= get_plci(a
)))
1951 rplci
= &a
->plci
[i
- 1];
1953 add_p(rplci
, CAI
, "\x01\x80");
1954 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
1955 sig_req(rplci
, ASSIGN
, DSIG_ID
);
1962 rplci
->internal_command
= GET_MWI_STATE
;
1963 rplci
->number
= Number
;
1964 sig_req(rplci
, MWI_POLL
, 0);
1970 api_parse(&parms
->info
[1], (word
)parms
->length
, "ws", ss_parms
);
1971 if (plci
&& plci
->State
&& plci
->SuppState
== IDLE
)
1973 plci
->SuppState
= HOLD_REQUEST
;
1974 plci
->command
= C_HOLD_REQ
;
1975 add_s(plci
, CAI
, &ss_parms
[1]);
1976 sig_req(plci
, CALL_HOLD
, 0);
1980 else Info
= 0x3010; /* wrong state */
1983 if (plci
&& plci
->State
&& plci
->SuppState
== CALL_HELD
)
1985 if (Id
& EXT_CONTROLLER
)
1987 if (AdvCodecSupport(a
, plci
, appl
, 0))
1989 Info
= 0x3010; /* wrong state */
1995 plci
->SuppState
= RETRIEVE_REQUEST
;
1996 plci
->command
= C_RETRIEVE_REQ
;
1997 if (plci
->spoofed_msg
== SPOOFING_REQUIRED
)
1999 plci
->spoofed_msg
= CALL_RETRIEVE
;
2000 plci
->internal_command
= BLOCK_PLCI
;
2002 dbug(1, dprintf("Spoof"));
2007 sig_req(plci
, CALL_RETRIEVE
, 0);
2012 else Info
= 0x3010; /* wrong state */
2017 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbs", ss_parms
))
2019 dbug(1, dprintf("format wrong"));
2020 Info
= _WRONG_MESSAGE_FORMAT
;
2024 if (plci
&& plci
->State
)
2026 add_s(plci
, CAI
, &ss_parms
[2]);
2027 plci
->command
= SUSPEND_REQ
;
2028 sig_req(plci
, SUSPEND
, 0);
2029 plci
->State
= SUSPENDING
;
2032 else Info
= 0x3010; /* wrong state */
2036 if (!(i
= get_plci(a
)))
2038 Info
= _OUT_OF_PLCI
;
2041 rplci
= &a
->plci
[i
- 1];
2043 rplci
->number
= Number
;
2045 rplci
->call_dir
= CALL_DIR_OUT
| CALL_DIR_ORIGINATE
;
2046 /* check 'external controller' bit for codec support */
2047 if (Id
& EXT_CONTROLLER
)
2049 if (AdvCodecSupport(a
, rplci
, appl
, 0))
2058 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbs", ss_parms
))
2060 dbug(1, dprintf("format wrong"));
2062 Info
= _WRONG_MESSAGE_FORMAT
;
2067 dummy
.info
= "\x00";
2068 add_b1(rplci
, &dummy
, 0, 0);
2069 if (a
->Info_Mask
[appl
->Id
- 1] & 0x200)
2071 /* early B3 connect (CIP mask bit 9) no release after a disc */
2072 add_p(rplci
, LLI
, "\x01\x01");
2074 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
2075 sig_req(rplci
, ASSIGN
, DSIG_ID
);
2077 add_s(rplci
, CAI
, &ss_parms
[2]);
2078 rplci
->command
= RESUME_REQ
;
2079 sig_req(rplci
, RESUME
, 0);
2080 rplci
->State
= RESUMING
;
2084 case S_CONF_BEGIN
: /* Request */
2086 case S_CONF_ISOLATE
:
2087 case S_CONF_REATTACH
:
2088 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbd", ss_parms
))
2090 dbug(1, dprintf("format wrong"));
2091 Info
= _WRONG_MESSAGE_FORMAT
;
2094 if (plci
&& plci
->State
&& ((plci
->SuppState
== IDLE
) || (plci
->SuppState
== CALL_HELD
)))
2096 d
= GET_DWORD(ss_parms
[2].info
);
2099 dbug(1, dprintf("format wrong"));
2100 Info
= _WRONG_MESSAGE_FORMAT
;
2103 plci
->ptyState
= (byte
)SSreq
;
2109 cai
[1] = CONF_BEGIN
;
2110 plci
->internal_command
= CONF_BEGIN_REQ_PEND
;
2114 plci
->internal_command
= CONF_DROP_REQ_PEND
;
2116 case S_CONF_ISOLATE
:
2117 cai
[1] = CONF_ISOLATE
;
2118 plci
->internal_command
= CONF_ISOLATE_REQ_PEND
;
2120 case S_CONF_REATTACH
:
2121 cai
[1] = CONF_REATTACH
;
2122 plci
->internal_command
= CONF_REATTACH_REQ_PEND
;
2125 cai
[2] = (byte
)d
; /* Conference Size resp. PartyId */
2126 add_p(plci
, CAI
, cai
);
2127 sig_req(plci
, S_SERVICE
, 0);
2131 else Info
= 0x3010; /* wrong state */
2138 if (parms
->length
== 7)
2140 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbd", ss_parms
))
2142 dbug(1, dprintf("format wrong"));
2143 Info
= _WRONG_MESSAGE_FORMAT
;
2147 else if (parms
->length
== 8) /* workaround for the T-View-S */
2149 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbdb", ss_parms
))
2151 dbug(1, dprintf("format wrong"));
2152 Info
= _WRONG_MESSAGE_FORMAT
;
2158 Info
= _WRONG_MESSAGE_FORMAT
;
2163 Info
= _WRONG_MESSAGE_FORMAT
;
2168 Info
= _WRONG_IDENTIFIER
;
2171 relatedPLCIvalue
= GET_DWORD(ss_parms
[2].info
);
2172 relatedPLCIvalue
&= 0x0000FFFF;
2173 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue
));
2174 /* controller starts with 0 up to (max_adapter - 1) */
2175 if (((relatedPLCIvalue
& 0x7f) == 0)
2176 || (MapController((byte
)(relatedPLCIvalue
& 0x7f)) == 0)
2177 || (MapController((byte
)(relatedPLCIvalue
& 0x7f)) > max_adapter
))
2179 if (SSreq
== S_3PTY_END
)
2181 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186 Info
= 0x3010; /* wrong state */
2192 relatedadapter
= &adapter
[MapController((byte
)(relatedPLCIvalue
& 0x7f)) - 1];
2193 relatedPLCIvalue
>>= 8;
2195 for (i
= 0, rplci
= NULL
; i
< relatedadapter
->max_plci
; i
++)
2197 if (relatedadapter
->plci
[i
].Id
== (byte
)relatedPLCIvalue
)
2199 rplci
= &relatedadapter
->plci
[i
];
2202 if (!rplci
|| !relatedPLCIvalue
)
2204 if (SSreq
== S_3PTY_END
)
2206 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211 Info
= 0x3010; /* wrong state */
2217 dbug(1, dprintf("rplci:%x", rplci));
2218 dbug(1, dprintf("plci:%x", plci));
2219 dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2220 dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2221 dbug(1, dprintf("SSreq:%x", SSreq));
2222 dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2223 dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2224 dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2226 /* send PTY/ECT req, cannot check all states because of US stuff */
2227 if (!rplci
->internal_command
&& rplci
->appl
)
2230 rplci
->relatedPTYPLCI
= plci
;
2231 plci
->relatedPTYPLCI
= rplci
;
2232 rplci
->ptyState
= (byte
)SSreq
;
2235 rplci
->internal_command
= ECT_REQ_PEND
;
2236 cai
[1] = ECT_EXECUTE
;
2238 rplci
->vswitchstate
= 0;
2240 rplci
->vsprotdialect
= 0;
2241 plci
->vswitchstate
= 0;
2243 plci
->vsprotdialect
= 0;
2246 else if (SSreq
== S_CONF_ADD
)
2248 rplci
->internal_command
= CONF_ADD_REQ_PEND
;
2253 rplci
->internal_command
= PTY_REQ_PEND
;
2254 cai
[1] = (byte
)(SSreq
- 3);
2256 rplci
->number
= Number
;
2257 if (plci
!= rplci
) /* explicit invocation */
2260 cai
[2] = plci
->Sig
.Id
;
2261 dbug(1, dprintf("explicit invocation"));
2265 dbug(1, dprintf("implicit invocation"));
2268 add_p(rplci
, CAI
, cai
);
2269 sig_req(rplci
, S_SERVICE
, 0);
2275 dbug(0, dprintf("Wrong line"));
2276 Info
= 0x3010; /* wrong state */
2281 case S_CALL_DEFLECTION
:
2282 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbwss", ss_parms
))
2284 dbug(1, dprintf("format wrong"));
2285 Info
= _WRONG_MESSAGE_FORMAT
;
2290 Info
= _WRONG_IDENTIFIER
;
2293 /* reuse unused screening indicator */
2294 ss_parms
[3].info
[3] = (byte
)GET_WORD(&(ss_parms
[2].info
[0]));
2296 plci
->internal_command
= CD_REQ_PEND
;
2297 appl
->CDEnable
= true;
2299 cai
[1] = CALL_DEFLECTION
;
2300 add_p(plci
, CAI
, cai
);
2301 add_p(plci
, CPN
, ss_parms
[3].info
);
2302 sig_req(plci
, S_SERVICE
, 0);
2307 case S_CALL_FORWARDING_START
:
2308 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbdwwsss", ss_parms
))
2310 dbug(1, dprintf("format wrong"));
2311 Info
= _WRONG_MESSAGE_FORMAT
;
2315 if ((i
= get_plci(a
)))
2317 rplci
= &a
->plci
[i
- 1];
2319 add_p(rplci
, CAI
, "\x01\x80");
2320 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
2321 sig_req(rplci
, ASSIGN
, DSIG_ID
);
2326 Info
= _OUT_OF_PLCI
;
2330 /* reuse unused screening indicator */
2331 rplci
->internal_command
= CF_START_PEND
;
2333 rplci
->number
= Number
;
2334 appl
->S_Handle
= GET_DWORD(&(ss_parms
[2].info
[0]));
2336 cai
[1] = 0x70 | (byte
)GET_WORD(&(ss_parms
[3].info
[0])); /* Function */
2337 cai
[2] = (byte
)GET_WORD(&(ss_parms
[4].info
[0])); /* Basic Service */
2338 add_p(rplci
, CAI
, cai
);
2339 add_p(rplci
, OAD
, ss_parms
[5].info
);
2340 add_p(rplci
, CPN
, ss_parms
[6].info
);
2341 sig_req(rplci
, S_SERVICE
, 0);
2346 case S_INTERROGATE_DIVERSION
:
2347 case S_INTERROGATE_NUMBERS
:
2348 case S_CALL_FORWARDING_STOP
:
2349 case S_CCBS_REQUEST
:
2350 case S_CCBS_DEACTIVATE
:
2351 case S_CCBS_INTERROGATE
:
2354 case S_INTERROGATE_NUMBERS
:
2355 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbd", ss_parms
))
2357 dbug(0, dprintf("format wrong"));
2358 Info
= _WRONG_MESSAGE_FORMAT
;
2361 case S_CCBS_REQUEST
:
2362 case S_CCBS_DEACTIVATE
:
2363 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbdw", ss_parms
))
2365 dbug(0, dprintf("format wrong"));
2366 Info
= _WRONG_MESSAGE_FORMAT
;
2369 case S_CCBS_INTERROGATE
:
2370 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbdws", ss_parms
))
2372 dbug(0, dprintf("format wrong"));
2373 Info
= _WRONG_MESSAGE_FORMAT
;
2377 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbdwws", ss_parms
))
2379 dbug(0, dprintf("format wrong"));
2380 Info
= _WRONG_MESSAGE_FORMAT
;
2387 if ((i
= get_plci(a
)))
2389 rplci
= &a
->plci
[i
- 1];
2392 case S_INTERROGATE_DIVERSION
: /* use cai with S_SERVICE below */
2393 cai
[1] = 0x60 | (byte
)GET_WORD(&(ss_parms
[3].info
[0])); /* Function */
2394 rplci
->internal_command
= INTERR_DIVERSION_REQ_PEND
; /* move to rplci if assigned */
2396 case S_INTERROGATE_NUMBERS
: /* use cai with S_SERVICE below */
2397 cai
[1] = DIVERSION_INTERROGATE_NUM
; /* Function */
2398 rplci
->internal_command
= INTERR_NUMBERS_REQ_PEND
; /* move to rplci if assigned */
2400 case S_CALL_FORWARDING_STOP
:
2401 rplci
->internal_command
= CF_STOP_PEND
;
2402 cai
[1] = 0x80 | (byte
)GET_WORD(&(ss_parms
[3].info
[0])); /* Function */
2404 case S_CCBS_REQUEST
:
2405 cai
[1] = CCBS_REQUEST
;
2406 rplci
->internal_command
= CCBS_REQUEST_REQ_PEND
;
2408 case S_CCBS_DEACTIVATE
:
2409 cai
[1] = CCBS_DEACTIVATE
;
2410 rplci
->internal_command
= CCBS_DEACTIVATE_REQ_PEND
;
2412 case S_CCBS_INTERROGATE
:
2413 cai
[1] = CCBS_INTERROGATE
;
2414 rplci
->internal_command
= CCBS_INTERROGATE_REQ_PEND
;
2421 rplci
->number
= Number
;
2422 add_p(rplci
, CAI
, "\x01\x80");
2423 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
2424 sig_req(rplci
, ASSIGN
, DSIG_ID
);
2429 Info
= _OUT_OF_PLCI
;
2433 appl
->S_Handle
= GET_DWORD(&(ss_parms
[2].info
[0]));
2436 case S_INTERROGATE_NUMBERS
:
2438 add_p(rplci
, CAI
, cai
);
2440 case S_CCBS_REQUEST
:
2441 case S_CCBS_DEACTIVATE
:
2443 PUT_WORD(&cai
[2], GET_WORD(&(ss_parms
[3].info
[0])));
2444 add_p(rplci
, CAI
, cai
);
2446 case S_CCBS_INTERROGATE
:
2448 PUT_WORD(&cai
[2], GET_WORD(&(ss_parms
[3].info
[0])));
2449 add_p(rplci
, CAI
, cai
);
2450 add_p(rplci
, OAD
, ss_parms
[4].info
);
2454 cai
[2] = (byte
)GET_WORD(&(ss_parms
[4].info
[0])); /* Basic Service */
2455 add_p(rplci
, CAI
, cai
);
2456 add_p(rplci
, OAD
, ss_parms
[5].info
);
2460 sig_req(rplci
, S_SERVICE
, 0);
2465 case S_MWI_ACTIVATE
:
2466 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbwdwwwssss", ss_parms
))
2468 dbug(1, dprintf("format wrong"));
2469 Info
= _WRONG_MESSAGE_FORMAT
;
2474 if ((i
= get_plci(a
)))
2476 rplci
= &a
->plci
[i
- 1];
2478 rplci
->cr_enquiry
= true;
2479 add_p(rplci
, CAI
, "\x01\x80");
2480 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
2481 sig_req(rplci
, ASSIGN
, DSIG_ID
);
2486 Info
= _OUT_OF_PLCI
;
2493 rplci
->cr_enquiry
= false;
2497 rplci
->internal_command
= MWI_ACTIVATE_REQ_PEND
;
2499 rplci
->number
= Number
;
2502 cai
[1] = ACTIVATION_MWI
; /* Function */
2503 PUT_WORD(&cai
[2], GET_WORD(&(ss_parms
[2].info
[0]))); /* Basic Service */
2504 PUT_DWORD(&cai
[4], GET_DWORD(&(ss_parms
[3].info
[0]))); /* Number of Messages */
2505 PUT_WORD(&cai
[8], GET_WORD(&(ss_parms
[4].info
[0]))); /* Message Status */
2506 PUT_WORD(&cai
[10], GET_WORD(&(ss_parms
[5].info
[0]))); /* Message Reference */
2507 PUT_WORD(&cai
[12], GET_WORD(&(ss_parms
[6].info
[0]))); /* Invocation Mode */
2508 add_p(rplci
, CAI
, cai
);
2509 add_p(rplci
, CPN
, ss_parms
[7].info
); /* Receiving User Number */
2510 add_p(rplci
, OAD
, ss_parms
[8].info
); /* Controlling User Number */
2511 add_p(rplci
, OSA
, ss_parms
[9].info
); /* Controlling User Provided Number */
2512 add_p(rplci
, UID
, ss_parms
[10].info
); /* Time */
2513 sig_req(rplci
, S_SERVICE
, 0);
2517 case S_MWI_DEACTIVATE
:
2518 if (api_parse(&parms
->info
[1], (word
)parms
->length
, "wbwwss", ss_parms
))
2520 dbug(1, dprintf("format wrong"));
2521 Info
= _WRONG_MESSAGE_FORMAT
;
2526 if ((i
= get_plci(a
)))
2528 rplci
= &a
->plci
[i
- 1];
2530 rplci
->cr_enquiry
= true;
2531 add_p(rplci
, CAI
, "\x01\x80");
2532 add_p(rplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
2533 sig_req(rplci
, ASSIGN
, DSIG_ID
);
2538 Info
= _OUT_OF_PLCI
;
2545 rplci
->cr_enquiry
= false;
2549 rplci
->internal_command
= MWI_DEACTIVATE_REQ_PEND
;
2551 rplci
->number
= Number
;
2554 cai
[1] = DEACTIVATION_MWI
; /* Function */
2555 PUT_WORD(&cai
[2], GET_WORD(&(ss_parms
[2].info
[0]))); /* Basic Service */
2556 PUT_WORD(&cai
[4], GET_WORD(&(ss_parms
[3].info
[0]))); /* Invocation Mode */
2557 add_p(rplci
, CAI
, cai
);
2558 add_p(rplci
, CPN
, ss_parms
[4].info
); /* Receiving User Number */
2559 add_p(rplci
, OAD
, ss_parms
[5].info
); /* Controlling User Number */
2560 sig_req(rplci
, S_SERVICE
, 0);
2565 Info
= 0x300E; /* not supported */
2568 break; /* case SELECTOR_SU_SERV: end */
2572 return (dtmf_request(Id
, Number
, a
, plci
, appl
, msg
));
2576 case SELECTOR_LINE_INTERCONNECT
:
2577 return (mixer_request(Id
, Number
, a
, plci
, appl
, msg
));
2581 case PRIV_SELECTOR_ECHO_CANCELLER
:
2582 appl
->appl_flags
|= APPL_FLAG_PRIV_EC_SPEC
;
2583 return (ec_request(Id
, Number
, a
, plci
, appl
, msg
));
2585 case SELECTOR_ECHO_CANCELLER
:
2586 appl
->appl_flags
&= ~APPL_FLAG_PRIV_EC_SPEC
;
2587 return (ec_request(Id
, Number
, a
, plci
, appl
, msg
));
2590 case SELECTOR_V42BIS
:
2592 Info
= _FACILITY_NOT_SUPPORTED
;
2594 } /* end of switch (selector) */
2597 dbug(1, dprintf("SendFacRc"));
2599 _FACILITY_R
| CONFIRM
,
2602 "wws", Info
, selector
, SSparms
);
2606 static byte
facility_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
2607 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
2609 dbug(1, dprintf("facility_res"));
2613 static byte
connect_b3_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
2614 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
2620 word fax_control_bits
, fax_feature_bits
, fax_info_change
;
2624 API_PARSE fax_parms
[9];
2628 dbug(1, dprintf("connect_b3_req"));
2631 if ((plci
->State
== IDLE
) || (plci
->State
== OUTG_DIS_PENDING
)
2632 || (plci
->State
== INC_DIS_PENDING
) || (plci
->SuppState
!= IDLE
))
2634 Info
= _WRONG_STATE
;
2638 /* local reply if assign unsuccessful
2639 or B3 protocol allows only one layer 3 connection
2640 and already connected
2641 or B2 protocol not any LAPD
2642 and connect_b3_req contradicts originate/answer direction */
2644 || (((plci
->B3_prot
!= B3_T90NL
) && (plci
->B3_prot
!= B3_ISO8208
) && (plci
->B3_prot
!= B3_X25_DCE
))
2645 && ((plci
->channels
!= 0)
2646 || (((plci
->B2_prot
!= B2_SDLC
) && (plci
->B2_prot
!= B2_LAPD
) && (plci
->B2_prot
!= B2_LAPD_FREE_SAPI_SEL
))
2647 && ((plci
->call_dir
& CALL_DIR_ANSWER
) && !(plci
->call_dir
& CALL_DIR_FORCE_OUTG_NL
))))))
2649 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2650 plci
->channels
, plci
->NL
.Id
, plci
->call_dir
, plci
->SuppState
));
2651 Info
= _WRONG_STATE
;
2653 _CONNECT_B3_R
| CONFIRM
,
2659 plci
->requested_options_conn
= 0;
2663 if (plci
->B3_prot
== 2 || plci
->B3_prot
== 3)
2665 if (ncpi
->length
> 2)
2668 if (ncpi
->info
[2] || ncpi
->info
[3])
2670 pvc
[0] = ncpi
->info
[3];
2671 pvc
[1] = ncpi
->info
[2];
2672 add_d(plci
, 2, pvc
);
2677 if (ncpi
->info
[1] & 1) req
= N_CONNECT
| N_D_BIT
;
2678 add_d(plci
, (word
)(ncpi
->length
- 3), &ncpi
->info
[4]);
2682 else if (plci
->B3_prot
== 5)
2684 if (plci
->NL
.Id
&& !plci
->nl_remove_id
)
2686 fax_control_bits
= GET_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->control_bits_low
);
2687 fax_feature_bits
= GET_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->feature_bits_low
);
2688 if (!(fax_control_bits
& T30_CONTROL_BIT_MORE_DOCUMENTS
)
2689 || (fax_feature_bits
& T30_FEATURE_BIT_MORE_DOCUMENTS
))
2691 len
= offsetof(T30_INFO
, universal_6
);
2692 fax_info_change
= false;
2693 if (ncpi
->length
>= 4)
2695 w
= GET_WORD(&ncpi
->info
[3]);
2696 if ((w
& 0x0001) != ((word
)(((T30_INFO
*)(plci
->fax_connect_info_buffer
))->resolution
& 0x0001)))
2698 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->resolution
=
2699 (byte
)((((T30_INFO
*)(plci
->fax_connect_info_buffer
))->resolution
& ~T30_RESOLUTION_R8_0770_OR_200
) |
2700 ((w
& 0x0001) ? T30_RESOLUTION_R8_0770_OR_200
: 0));
2701 fax_info_change
= true;
2703 fax_control_bits
&= ~(T30_CONTROL_BIT_REQUEST_POLLING
| T30_CONTROL_BIT_MORE_DOCUMENTS
);
2704 if (w
& 0x0002) /* Fax-polling request */
2705 fax_control_bits
|= T30_CONTROL_BIT_REQUEST_POLLING
;
2706 if ((w
& 0x0004) /* Request to send / poll another document */
2707 && (a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS
))
2709 fax_control_bits
|= T30_CONTROL_BIT_MORE_DOCUMENTS
;
2711 if (ncpi
->length
>= 6)
2713 w
= GET_WORD(&ncpi
->info
[5]);
2714 if (((byte
) w
) != ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->data_format
)
2716 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->data_format
= (byte
) w
;
2717 fax_info_change
= true;
2720 if ((a
->man_profile
.private_options
& (1L << PRIVATE_FAX_SUB_SEP_PWD
))
2721 && (GET_WORD(&ncpi
->info
[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2723 plci
->requested_options_conn
|= (1L << PRIVATE_FAX_SUB_SEP_PWD
);
2725 if ((a
->man_profile
.private_options
& (1L << PRIVATE_FAX_NONSTANDARD
))
2726 && (GET_WORD(&ncpi
->info
[5]) & 0x4000)) /* Private non-standard facilities enable */
2728 plci
->requested_options_conn
|= (1L << PRIVATE_FAX_NONSTANDARD
);
2730 fax_control_bits
&= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS
| T30_CONTROL_BIT_ACCEPT_SEL_POLLING
|
2731 T30_CONTROL_BIT_ACCEPT_PASSWORD
);
2732 if ((plci
->requested_options_conn
| plci
->requested_options
| a
->requested_options_table
[appl
->Id
- 1])
2733 & ((1L << PRIVATE_FAX_SUB_SEP_PWD
) | (1L << PRIVATE_FAX_NONSTANDARD
)))
2735 if (api_parse(&ncpi
->info
[1], ncpi
->length
, "wwwwsss", fax_parms
))
2736 Info
= _WRONG_MESSAGE_FORMAT
;
2739 if ((plci
->requested_options_conn
| plci
->requested_options
| a
->requested_options_table
[appl
->Id
- 1])
2740 & (1L << PRIVATE_FAX_SUB_SEP_PWD
))
2742 fax_control_bits
|= T30_CONTROL_BIT_ACCEPT_SUBADDRESS
| T30_CONTROL_BIT_ACCEPT_PASSWORD
;
2743 if (fax_control_bits
& T30_CONTROL_BIT_ACCEPT_POLLING
)
2744 fax_control_bits
|= T30_CONTROL_BIT_ACCEPT_SEL_POLLING
;
2746 w
= fax_parms
[4].length
;
2749 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->station_id_len
= (byte
) w
;
2750 for (i
= 0; i
< w
; i
++)
2751 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->station_id
[i
] = fax_parms
[4].info
[1 + i
];
2752 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->head_line_len
= 0;
2753 len
= offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
;
2754 w
= fax_parms
[5].length
;
2757 plci
->fax_connect_info_buffer
[len
++] = (byte
) w
;
2758 for (i
= 0; i
< w
; i
++)
2759 plci
->fax_connect_info_buffer
[len
++] = fax_parms
[5].info
[1 + i
];
2760 w
= fax_parms
[6].length
;
2763 plci
->fax_connect_info_buffer
[len
++] = (byte
) w
;
2764 for (i
= 0; i
< w
; i
++)
2765 plci
->fax_connect_info_buffer
[len
++] = fax_parms
[6].info
[1 + i
];
2766 if ((plci
->requested_options_conn
| plci
->requested_options
| a
->requested_options_table
[appl
->Id
- 1])
2767 & (1L << PRIVATE_FAX_NONSTANDARD
))
2769 if (api_parse(&ncpi
->info
[1], ncpi
->length
, "wwwwssss", fax_parms
))
2771 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2772 plci
->fax_connect_info_buffer
[len
++] = 0;
2776 if ((fax_parms
[7].length
>= 3) && (fax_parms
[7].info
[1] >= 2))
2777 plci
->nsf_control_bits
= GET_WORD(&fax_parms
[7].info
[2]);
2778 plci
->fax_connect_info_buffer
[len
++] = (byte
)(fax_parms
[7].length
);
2779 for (i
= 0; i
< fax_parms
[7].length
; i
++)
2780 plci
->fax_connect_info_buffer
[len
++] = fax_parms
[7].info
[1 + i
];
2787 len
= offsetof(T30_INFO
, universal_6
);
2789 fax_info_change
= true;
2792 if (fax_control_bits
!= GET_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->control_bits_low
))
2794 PUT_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->control_bits_low
, fax_control_bits
);
2795 fax_info_change
= true;
2800 plci
->fax_connect_info_length
= len
;
2801 if (fax_info_change
)
2803 if (fax_feature_bits
& T30_FEATURE_BIT_MORE_DOCUMENTS
)
2805 start_internal_command(Id
, plci
, fax_connect_info_command
);
2810 start_internal_command(Id
, plci
, fax_adjust_b23_command
);
2816 else Info
= _WRONG_STATE
;
2818 else Info
= _WRONG_STATE
;
2821 else if (plci
->B3_prot
== B3_RTP
)
2823 plci
->internal_req_buffer
[0] = ncpi
->length
+ 1;
2824 plci
->internal_req_buffer
[1] = UDATA_REQUEST_RTP_RECONFIGURE
;
2825 for (w
= 0; w
< ncpi
->length
; w
++)
2826 plci
->internal_req_buffer
[2 + w
] = ncpi
->info
[1 + w
];
2827 start_internal_command(Id
, plci
, rtp_connect_b3_req_command
);
2833 nl_req_ncci(plci
, req
, 0);
2838 else Info
= _WRONG_IDENTIFIER
;
2841 _CONNECT_B3_R
| CONFIRM
,
2848 static byte
connect_b3_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
2849 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
2858 API_PARSE fax_parms
[9];
2863 dbug(1, dprintf("connect_b3_res"));
2865 ncci
= (word
)(Id
>> 16);
2867 if (a
->ncci_state
[ncci
] == INC_CON_PENDING
) {
2868 if (GET_WORD(&parms
[0].info
[0]) != 0)
2870 a
->ncci_state
[ncci
] = OUTG_REJ_PENDING
;
2871 channel_request_xon(plci
, a
->ncci_ch
[ncci
]);
2872 channel_xmit_xon(plci
);
2873 cleanup_ncci_data(plci
, ncci
);
2874 nl_req_ncci(plci
, N_DISC
, (byte
)ncci
);
2877 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
2879 req
= N_CONNECT_ACK
;
2881 if ((plci
->B3_prot
== 4) || (plci
->B3_prot
== 5) || (plci
->B3_prot
== 7))
2884 if ((plci
->requested_options_conn
| plci
->requested_options
| a
->requested_options_table
[plci
->appl
->Id
- 1])
2885 & (1L << PRIVATE_FAX_NONSTANDARD
))
2887 if (((plci
->B3_prot
== 4) || (plci
->B3_prot
== 5))
2888 && (plci
->nsf_control_bits
& T30_NSF_CONTROL_BIT_ENABLE_NSF
)
2889 && (plci
->nsf_control_bits
& T30_NSF_CONTROL_BIT_NEGOTIATE_RESP
))
2891 len
= offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
;
2892 if (plci
->fax_connect_info_length
< len
)
2894 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->station_id_len
= 0;
2895 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->head_line_len
= 0;
2897 if (api_parse(&ncpi
->info
[1], ncpi
->length
, "wwwwssss", fax_parms
))
2899 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2903 if (plci
->fax_connect_info_length
<= len
)
2904 plci
->fax_connect_info_buffer
[len
] = 0;
2905 len
+= 1 + plci
->fax_connect_info_buffer
[len
];
2906 if (plci
->fax_connect_info_length
<= len
)
2907 plci
->fax_connect_info_buffer
[len
] = 0;
2908 len
+= 1 + plci
->fax_connect_info_buffer
[len
];
2909 if ((fax_parms
[7].length
>= 3) && (fax_parms
[7].info
[1] >= 2))
2910 plci
->nsf_control_bits
= GET_WORD(&fax_parms
[7].info
[2]);
2911 plci
->fax_connect_info_buffer
[len
++] = (byte
)(fax_parms
[7].length
);
2912 for (i
= 0; i
< fax_parms
[7].length
; i
++)
2913 plci
->fax_connect_info_buffer
[len
++] = fax_parms
[7].info
[1 + i
];
2915 plci
->fax_connect_info_length
= len
;
2916 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->code
= 0;
2917 start_internal_command(Id
, plci
, fax_connect_ack_command
);
2922 nl_req_ncci(plci
, req
, (byte
)ncci
);
2923 if ((plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
2924 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
2926 if (plci
->B3_prot
== 4)
2927 sendf(appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
2929 sendf(appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "S", plci
->ncpi_buffer
);
2930 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
2934 else if (plci
->B3_prot
== B3_RTP
)
2936 plci
->internal_req_buffer
[0] = ncpi
->length
+ 1;
2937 plci
->internal_req_buffer
[1] = UDATA_REQUEST_RTP_RECONFIGURE
;
2938 for (w
= 0; w
< ncpi
->length
; w
++)
2939 plci
->internal_req_buffer
[2 + w
] = ncpi
->info
[1+w
];
2940 start_internal_command(Id
, plci
, rtp_connect_b3_res_command
);
2946 if (ncpi
->length
> 2) {
2947 if (ncpi
->info
[1] & 1) req
= N_CONNECT_ACK
| N_D_BIT
;
2948 add_d(plci
, (word
)(ncpi
->length
- 3), &ncpi
->info
[4]);
2950 nl_req_ncci(plci
, req
, (byte
)ncci
);
2951 sendf(appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
2952 if (plci
->adjust_b_restore
)
2954 plci
->adjust_b_restore
= false;
2955 start_internal_command(Id
, plci
, adjust_b_restore
);
2964 static byte
connect_b3_a_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
2965 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
2969 ncci
= (word
)(Id
>> 16);
2970 dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci
));
2972 if (plci
&& ncci
&& (plci
->State
!= IDLE
) && (plci
->State
!= INC_DIS_PENDING
)
2973 && (plci
->State
!= OUTG_DIS_PENDING
))
2975 if (a
->ncci_state
[ncci
] == INC_ACT_PENDING
) {
2976 a
->ncci_state
[ncci
] = CONNECTED
;
2977 if (plci
->State
!= INC_CON_CONNECTED_ALERT
) plci
->State
= CONNECTED
;
2978 channel_request_xon(plci
, a
->ncci_ch
[ncci
]);
2979 channel_xmit_xon(plci
);
2985 static byte
disconnect_b3_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
2986 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
2992 dbug(1, dprintf("disconnect_b3_req"));
2994 Info
= _WRONG_IDENTIFIER
;
2995 ncci
= (word
)(Id
>> 16);
2998 Info
= _WRONG_STATE
;
2999 if ((a
->ncci_state
[ncci
] == CONNECTED
)
3000 || (a
->ncci_state
[ncci
] == OUTG_CON_PENDING
)
3001 || (a
->ncci_state
[ncci
] == INC_CON_PENDING
)
3002 || (a
->ncci_state
[ncci
] == INC_ACT_PENDING
))
3004 a
->ncci_state
[ncci
] = OUTG_DIS_PENDING
;
3005 channel_request_xon(plci
, a
->ncci_ch
[ncci
]);
3006 channel_xmit_xon(plci
);
3008 if (a
->ncci
[ncci
].data_pending
3009 && ((plci
->B3_prot
== B3_TRANSPARENT
)
3010 || (plci
->B3_prot
== B3_T30
)
3011 || (plci
->B3_prot
== B3_T30_WITH_EXTENSIONS
)))
3013 plci
->send_disc
= (byte
)ncci
;
3019 cleanup_ncci_data(plci
, ncci
);
3021 if (plci
->B3_prot
== 2 || plci
->B3_prot
== 3)
3024 if (ncpi
->length
> 3)
3026 add_d(plci
, (word
)(ncpi
->length
- 3), (byte
*)&(ncpi
->info
[4]));
3029 nl_req_ncci(plci
, N_DISC
, (byte
)ncci
);
3035 _DISCONNECT_B3_R
| CONFIRM
,
3042 static byte
disconnect_b3_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3043 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3048 ncci
= (word
)(Id
>> 16);
3049 dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci
));
3051 plci
->requested_options_conn
= 0;
3052 plci
->fax_connect_info_length
= 0;
3053 plci
->ncpi_state
= 0x00;
3054 if (((plci
->B3_prot
!= B3_T90NL
) && (plci
->B3_prot
!= B3_ISO8208
) && (plci
->B3_prot
!= B3_X25_DCE
))
3055 && ((plci
->B2_prot
!= B2_LAPD
) && (plci
->B2_prot
!= B2_LAPD_FREE_SAPI_SEL
)))
3057 plci
->call_dir
|= CALL_DIR_FORCE_OUTG_NL
;
3059 for (i
= 0; i
< MAX_CHANNELS_PER_PLCI
&& plci
->inc_dis_ncci_table
[i
] != (byte
)ncci
; i
++);
3060 if (i
< MAX_CHANNELS_PER_PLCI
) {
3061 if (plci
->channels
)plci
->channels
--;
3062 for (; i
< MAX_CHANNELS_PER_PLCI
- 1; i
++) plci
->inc_dis_ncci_table
[i
] = plci
->inc_dis_ncci_table
[i
+ 1];
3063 plci
->inc_dis_ncci_table
[MAX_CHANNELS_PER_PLCI
- 1] = 0;
3065 ncci_free_receive_buffers(plci
, ncci
);
3067 if ((plci
->State
== IDLE
|| plci
->State
== SUSPENDING
) && !plci
->channels
) {
3068 if (plci
->State
== SUSPENDING
) {
3073 "ws", (word
)3, "\x03\x04\x00\x00");
3074 sendf(plci
->appl
, _DISCONNECT_I
, Id
& 0xffffL
, 0, "w", 0);
3082 if ((a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_PAPER_FORMATS
)
3083 && ((plci
->B3_prot
== 4) || (plci
->B3_prot
== 5))
3084 && (a
->ncci_state
[ncci
] == INC_DIS_PENDING
))
3086 ncci_free_receive_buffers(plci
, ncci
);
3088 nl_req_ncci(plci
, N_EDATA
, (byte
)ncci
);
3090 plci
->adapter
->ncci_state
[ncci
] = IDLE
;
3091 start_internal_command(Id
, plci
, fax_disconnect_command
);
3099 static byte
data_b3_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3100 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3108 dbug(1, dprintf("data_b3_req"));
3110 Info
= _WRONG_IDENTIFIER
;
3111 ncci
= (word
)(Id
>> 16);
3112 dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci
, plci
));
3116 Info
= _WRONG_STATE
;
3117 if ((a
->ncci_state
[ncci
] == CONNECTED
)
3118 || (a
->ncci_state
[ncci
] == INC_ACT_PENDING
))
3121 ncci_ptr
= &(a
->ncci
[ncci
]);
3122 i
= ncci_ptr
->data_out
+ ncci_ptr
->data_pending
;
3123 if (i
>= MAX_DATA_B3
)
3125 data
= &(ncci_ptr
->DBuffer
[i
]);
3126 data
->Number
= Number
;
3127 if ((((byte
*)(parms
[0].info
)) >= ((byte
*)(plci
->msg_in_queue
)))
3128 && (((byte
*)(parms
[0].info
)) < ((byte
*)(plci
->msg_in_queue
)) + sizeof(plci
->msg_in_queue
)))
3131 data
->P
= (byte
*)(long)(*((dword
*)(parms
[0].info
)));
3135 data
->P
= TransmitBufferSet(appl
, *(dword
*)parms
[0].info
);
3136 data
->Length
= GET_WORD(parms
[1].info
);
3137 data
->Handle
= GET_WORD(parms
[2].info
);
3138 data
->Flags
= GET_WORD(parms
[3].info
);
3139 (ncci_ptr
->data_pending
)++;
3141 /* check for delivery confirmation */
3142 if (data
->Flags
& 0x0004)
3144 i
= ncci_ptr
->data_ack_out
+ ncci_ptr
->data_ack_pending
;
3145 if (i
>= MAX_DATA_ACK
)
3147 ncci_ptr
->DataAck
[i
].Number
= data
->Number
;
3148 ncci_ptr
->DataAck
[i
].Handle
= data
->Handle
;
3149 (ncci_ptr
->data_ack_pending
)++;
3160 if ((((byte
*)(parms
[0].info
)) >= ((byte
*)(plci
->msg_in_queue
)))
3161 && (((byte
*)(parms
[0].info
)) < ((byte
*)(plci
->msg_in_queue
)) + sizeof(plci
->msg_in_queue
)))
3164 TransmitBufferFree(appl
, (byte
*)(long)(*((dword
*)(parms
[0].info
))));
3169 _DATA_B3_R
| CONFIRM
,
3172 "ww", GET_WORD(parms
[2].info
), Info
);
3177 static byte
data_b3_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3178 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3184 dbug(1, dprintf("data_b3_res"));
3186 ncci
= (word
)(Id
>> 16);
3188 n
= GET_WORD(parms
[0].info
);
3189 dbug(1, dprintf("free(%d)", n
));
3190 NCCIcode
= ncci
| (((word
) a
->Id
) << 8);
3191 if (n
< appl
->MaxBuffer
&&
3192 appl
->DataNCCI
[n
] == NCCIcode
&&
3193 (byte
)(appl
->DataFlags
[n
] >> 8) == plci
->Id
) {
3194 dbug(1, dprintf("found"));
3195 appl
->DataNCCI
[n
] = 0;
3197 if (channel_can_xon(plci
, a
->ncci_ch
[ncci
])) {
3198 channel_request_xon(plci
, a
->ncci_ch
[ncci
]);
3200 channel_xmit_xon(plci
);
3202 if (appl
->DataFlags
[n
] & 4) {
3203 nl_req_ncci(plci
, N_DATA_ACK
, (byte
)ncci
);
3211 static byte
reset_b3_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3212 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3217 dbug(1, dprintf("reset_b3_req"));
3219 Info
= _WRONG_IDENTIFIER
;
3220 ncci
= (word
)(Id
>> 16);
3223 Info
= _WRONG_STATE
;
3224 switch (plci
->B3_prot
)
3228 if (a
->ncci_state
[ncci
] == CONNECTED
)
3230 nl_req_ncci(plci
, N_RESET
, (byte
)ncci
);
3235 case B3_TRANSPARENT
:
3236 if (a
->ncci_state
[ncci
] == CONNECTED
)
3238 start_internal_command(Id
, plci
, reset_b3_command
);
3244 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3246 _RESET_B3_R
| CONFIRM
,
3253 static byte
reset_b3_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3254 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3258 dbug(1, dprintf("reset_b3_res"));
3260 ncci
= (word
)(Id
>> 16);
3262 switch (plci
->B3_prot
)
3266 if (a
->ncci_state
[ncci
] == INC_RES_PENDING
)
3268 a
->ncci_state
[ncci
] = CONNECTED
;
3269 nl_req_ncci(plci
, N_RESET_ACK
, (byte
)ncci
);
3278 static byte
connect_b3_t90_a_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3279 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3285 dbug(1, dprintf("connect_b3_t90_a_res"));
3287 ncci
= (word
)(Id
>> 16);
3289 if (a
->ncci_state
[ncci
] == INC_ACT_PENDING
) {
3290 a
->ncci_state
[ncci
] = CONNECTED
;
3292 else if (a
->ncci_state
[ncci
] == INC_CON_PENDING
) {
3293 a
->ncci_state
[ncci
] = CONNECTED
;
3295 req
= N_CONNECT_ACK
;
3297 /* parms[0]==0 for CAPI original message definition! */
3298 if (parms
[0].info
) {
3300 if (ncpi
->length
> 2) {
3301 if (ncpi
->info
[1] & 1) req
= N_CONNECT_ACK
| N_D_BIT
;
3302 add_d(plci
, (word
)(ncpi
->length
- 3), &ncpi
->info
[4]);
3305 nl_req_ncci(plci
, req
, (byte
)ncci
);
3313 static byte
select_b_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3314 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
3319 API_PARSE bp_parms
[7];
3323 Info
= _WRONG_IDENTIFIER
;
3327 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3328 msg
->length
, plci
->Id
, plci
->tel
, plci
->NL
.Id
, plci
->appl
, plci
->SuppState
));
3329 dbug(1, dprintf("PlciState=0x%x", plci
->State
));
3330 for (i
= 0; i
< 7; i
++) bp_parms
[i
].length
= 0;
3332 /* check if no channel is open, no B3 connected only */
3333 if ((plci
->State
== IDLE
) || (plci
->State
== OUTG_DIS_PENDING
) || (plci
->State
== INC_DIS_PENDING
)
3334 || (plci
->SuppState
!= IDLE
) || plci
->channels
|| plci
->nl_remove_id
)
3336 Info
= _WRONG_STATE
;
3338 /* check message format and fill bp_parms pointer */
3339 else if (msg
->length
&& api_parse(&msg
->info
[1], (word
)msg
->length
, "wwwsss", bp_parms
))
3341 Info
= _WRONG_MESSAGE_FORMAT
;
3345 if ((plci
->State
== INC_CON_PENDING
) || (plci
->State
== INC_CON_ALERT
)) /* send alert tone inband to the network, */
3346 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3347 if (Id
& EXT_CONTROLLER
)
3349 sendf(appl
, _SELECT_B_REQ
| CONFIRM
, Id
, Number
, "w", 0x2002); /* wrong controller */
3352 plci
->State
= INC_CON_CONNECTED_ALERT
;
3354 clear_c_ind_mask_bit(plci
, (word
)(appl
->Id
- 1));
3355 dump_c_ind_mask(plci
);
3356 for (i
= 0; i
< max_appl
; i
++) /* disconnect the other appls */
3357 { /* its quasi a connect */
3358 if (test_c_ind_mask_bit(plci
, i
))
3359 sendf(&application
[i
], _DISCONNECT_I
, Id
, 0, "w", _OTHER_APPL_CONNECTED
);
3363 api_save_msg(msg
, "s", &plci
->saved_msg
);
3365 if (Id
& EXT_CONTROLLER
)
3367 if (tel
) /* external controller in use by this PLCI */
3369 if (a
->AdvSignalAppl
&& a
->AdvSignalAppl
!= appl
)
3371 dbug(1, dprintf("Ext_Ctrl in use 1"));
3372 Info
= _WRONG_STATE
;
3375 else /* external controller NOT in use by this PLCI ? */
3377 if (a
->AdvSignalPLCI
)
3379 dbug(1, dprintf("Ext_Ctrl in use 2"));
3380 Info
= _WRONG_STATE
;
3382 else /* activate the codec */
3384 dbug(1, dprintf("Ext_Ctrl start"));
3385 if (AdvCodecSupport(a
, plci
, appl
, 0))
3387 dbug(1, dprintf("Error in codec procedures"));
3388 Info
= _WRONG_STATE
;
3390 else if (plci
->spoofed_msg
== SPOOFING_REQUIRED
) /* wait until codec is active */
3392 plci
->spoofed_msg
= AWAITING_SELECT_B
;
3393 plci
->internal_command
= BLOCK_PLCI
; /* lock other commands */
3395 dbug(1, dprintf("continue if codec loaded"));
3401 else /* external controller bit is OFF */
3403 if (tel
) /* external controller in use, need to switch off */
3405 if (a
->AdvSignalAppl
== appl
)
3407 CodecIdCheck(a
, plci
);
3410 dbug(1, dprintf("Ext_Ctrl disable"));
3414 dbug(1, dprintf("Ext_Ctrl not requested"));
3420 if (plci
->call_dir
& CALL_DIR_OUT
)
3421 plci
->call_dir
= CALL_DIR_OUT
| CALL_DIR_ORIGINATE
;
3422 else if (plci
->call_dir
& CALL_DIR_IN
)
3423 plci
->call_dir
= CALL_DIR_IN
| CALL_DIR_ANSWER
;
3424 start_internal_command(Id
, plci
, select_b_command
);
3429 sendf(appl
, _SELECT_B_REQ
| CONFIRM
, Id
, Number
, "w", Info
);
3433 static byte
manufacturer_req(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3434 PLCI
*plci
, APPL
*appl
, API_PARSE
*parms
)
3440 API_PARSE m_parms
[5];
3445 static byte chi
[2] = {0x01, 0x00};
3446 static byte lli
[2] = {0x01, 0x00};
3447 static byte codec_cai
[2] = {0x01, 0x01};
3448 static byte null_msg
= {0};
3449 static API_PARSE null_parms
= { 0, &null_msg
};
3453 dbug(1, dprintf("manufacturer_req"));
3454 for (i
= 0; i
< 5; i
++) m_parms
[i
].length
= 0;
3456 if (GET_DWORD(parms
[0].info
) != _DI_MANU_ID
) {
3457 Info
= _WRONG_MESSAGE_FORMAT
;
3459 command
= GET_WORD(parms
[1].info
);
3464 case _DI_ASSIGN_PLCI
:
3465 if (api_parse(&m
->info
[1], (word
)m
->length
, "wbbs", m_parms
)) {
3466 Info
= _WRONG_MESSAGE_FORMAT
;
3469 codec
= GET_WORD(m_parms
[0].info
);
3470 ch
= m_parms
[1].info
[0];
3471 dir
= m_parms
[2].info
[0];
3472 if ((i
= get_plci(a
))) {
3473 plci
= &a
->plci
[i
- 1];
3475 plci
->command
= _MANUFACTURER_R
;
3476 plci
->m_command
= command
;
3477 plci
->number
= Number
;
3478 plci
->State
= LOCAL_CONNECT
;
3479 Id
= (((word
)plci
->Id
<< 8) | plci
->adapter
->Id
| 0x80);
3480 dbug(1, dprintf("ManCMD,plci=0x%x", Id
));
3482 if ((ch
== 1 || ch
== 2) && (dir
<= 2)) {
3483 chi
[1] = (byte
)(0x80 | ch
);
3485 plci
->call_dir
= CALL_DIR_OUT
| CALL_DIR_ORIGINATE
;
3489 Info
= add_b1(plci
, &m_parms
[3], 0, 0);
3492 add_p(plci
, CAI
, codec_cai
);
3494 /* manual 'swich on' to the codec support without signalling */
3495 /* first 'assign plci' with this function, then use */
3497 if (AdvCodecSupport(a
, plci
, appl
, 0)) {
3498 Info
= _RESOURCE_ERROR
;
3501 Info
= add_b1(plci
, &null_parms
, 0, B1_FACILITY_LOCAL
);
3502 lli
[1] = 0x10; /* local call codec stream */
3507 plci
->State
= LOCAL_CONNECT
;
3508 plci
->manufacturer
= true;
3509 plci
->command
= _MANUFACTURER_R
;
3510 plci
->m_command
= command
;
3511 plci
->number
= Number
;
3515 add_p(plci
, LLI
, lli
);
3516 add_p(plci
, CHI
, chi
);
3517 add_p(plci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
3518 sig_req(plci
, ASSIGN
, DSIG_ID
);
3522 Info
= add_b23(plci
, &m_parms
[3]);
3525 nl_req_ncci(plci
, ASSIGN
, 0);
3531 dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir
, plci
->spoofed_msg
));
3532 if (plci
->spoofed_msg
== SPOOFING_REQUIRED
)
3534 api_save_msg(m_parms
, "wbbs", &plci
->saved_msg
);
3535 plci
->spoofed_msg
= AWAITING_MANUF_CON
;
3536 plci
->internal_command
= BLOCK_PLCI
; /* reject other req meanwhile */
3542 sig_req(plci
, CALL_REQ
, 0);
3545 sig_req(plci
, LISTEN_REQ
, 0);
3552 _MANUFACTURER_R
| CONFIRM
,
3555 "dww", _DI_MANU_ID
, command
, Info
);
3561 else Info
= _OUT_OF_PLCI
;
3567 Info
= _WRONG_IDENTIFIER
;
3570 if (api_parse(&m
->info
[1], (word
)m
->length
, "bs", m_parms
)) {
3571 Info
= _WRONG_MESSAGE_FORMAT
;
3574 req
= m_parms
[0].info
[0];
3575 plci
->command
= _MANUFACTURER_R
;
3576 plci
->m_command
= command
;
3577 plci
->number
= Number
;
3578 if (req
== CALL_REQ
)
3580 plci
->b_channel
= getChannel(&m_parms
[1]);
3581 mixer_set_bchannel_id_esc(plci
, plci
->b_channel
);
3582 if (plci
->spoofed_msg
== SPOOFING_REQUIRED
)
3584 plci
->spoofed_msg
= CALL_REQ
| AWAITING_MANUF_CON
;
3585 plci
->internal_command
= BLOCK_PLCI
; /* reject other req meanwhile */
3590 else if (req
== LAW_REQ
)
3592 plci
->cr_enquiry
= true;
3594 add_ss(plci
, FTY
, &m_parms
[1]);
3595 sig_req(plci
, req
, 0);
3599 if (plci
->NL
.Id
&& !plci
->nl_remove_id
)
3603 for (ncci
= 1; ncci
< MAX_NCCI
+ 1; ncci
++)
3605 if ((a
->ncci_plci
[ncci
] == plci
->Id
) && (a
->ncci_state
[ncci
] == CONNECTED
))
3607 a
->ncci_state
[ncci
] = OUTG_DIS_PENDING
;
3608 cleanup_ncci_data(plci
, ncci
);
3609 nl_req_ncci(plci
, N_DISC
, (byte
)ncci
);
3614 nl_req_ncci(plci
, REMOVE
, 0);
3621 /* signalling control for loop activation B-channel */
3624 Info
= _WRONG_IDENTIFIER
;
3628 plci
->command
= _MANUFACTURER_R
;
3629 plci
->number
= Number
;
3630 add_ss(plci
, FTY
, m
);
3631 sig_req(plci
, SIG_CTRL
, 0);
3634 else Info
= _WRONG_MESSAGE_FORMAT
;
3638 /* activation control for receiver/transmitter B-channel */
3641 Info
= _WRONG_IDENTIFIER
;
3645 plci
->command
= _MANUFACTURER_R
;
3646 plci
->number
= Number
;
3647 add_ss(plci
, FTY
, m
);
3648 sig_req(plci
, DSP_CTRL
, 0);
3651 else Info
= _WRONG_MESSAGE_FORMAT
;
3656 /* TEL_CTRL commands to support non standard adjustments: */
3657 /* Ring on/off, Handset micro volume, external micro vol. */
3658 /* handset+external speaker volume, receiver+transm. gain,*/
3659 /* handsfree on (hookinfo off), set mixer command */
3661 if (command
== _DI_ADV_CODEC
)
3663 if (!a
->AdvCodecPLCI
) {
3664 Info
= _WRONG_STATE
;
3667 v_plci
= a
->AdvCodecPLCI
;
3673 && (m
->info
[1] == 0x1c)
3674 && (m
->info
[2] >= 1))
3676 if (m
->info
[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS
)
3678 if ((plci
->tel
!= ADV_VOICE
) || (plci
!= a
->AdvSignalPLCI
))
3680 Info
= _WRONG_STATE
;
3683 a
->adv_voice_coef_length
= m
->info
[2] - 1;
3684 if (a
->adv_voice_coef_length
> m
->length
- 3)
3685 a
->adv_voice_coef_length
= (byte
)(m
->length
- 3);
3686 if (a
->adv_voice_coef_length
> ADV_VOICE_COEF_BUFFER_SIZE
)
3687 a
->adv_voice_coef_length
= ADV_VOICE_COEF_BUFFER_SIZE
;
3688 for (i
= 0; i
< a
->adv_voice_coef_length
; i
++)
3689 a
->adv_voice_coef_buffer
[i
] = m
->info
[4 + i
];
3690 if (plci
->B1_facilities
& B1_FACILITY_VOICE
)
3691 adv_voice_write_coefs(plci
, ADV_VOICE_WRITE_UPDATE
);
3694 else if (m
->info
[3] == DSP_CTRL_SET_DTMF_PARAMETERS
)
3696 if (!(a
->manufacturer_features
& MANUFACTURER_FEATURE_DTMF_PARAMETERS
))
3698 Info
= _FACILITY_NOT_SUPPORTED
;
3702 plci
->dtmf_parameter_length
= m
->info
[2] - 1;
3703 if (plci
->dtmf_parameter_length
> m
->length
- 3)
3704 plci
->dtmf_parameter_length
= (byte
)(m
->length
- 3);
3705 if (plci
->dtmf_parameter_length
> DTMF_PARAMETER_BUFFER_SIZE
)
3706 plci
->dtmf_parameter_length
= DTMF_PARAMETER_BUFFER_SIZE
;
3707 for (i
= 0; i
< plci
->dtmf_parameter_length
; i
++)
3708 plci
->dtmf_parameter_buffer
[i
] = m
->info
[4 + i
];
3709 if (plci
->B1_facilities
& B1_FACILITY_DTMFR
)
3710 dtmf_parameter_write(plci
);
3720 Info
= _WRONG_IDENTIFIER
;
3724 add_ss(v_plci
, FTY
, m
);
3725 sig_req(v_plci
, TEL_CTRL
, 0);
3728 else Info
= _WRONG_MESSAGE_FORMAT
;
3732 case _DI_OPTIONS_REQUEST
:
3733 if (api_parse(&m
->info
[1], (word
)m
->length
, "d", m_parms
)) {
3734 Info
= _WRONG_MESSAGE_FORMAT
;
3737 if (GET_DWORD(m_parms
[0].info
) & ~a
->man_profile
.private_options
)
3739 Info
= _FACILITY_NOT_SUPPORTED
;
3742 a
->requested_options_table
[appl
->Id
- 1] = GET_DWORD(m_parms
[0].info
);
3748 Info
= _WRONG_MESSAGE_FORMAT
;
3754 _MANUFACTURER_R
| CONFIRM
,
3757 "dww", _DI_MANU_ID
, command
, Info
);
3762 static byte
manufacturer_res(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
,
3763 PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
3767 API_PARSE m_parms
[3];
3769 API_PARSE fax_parms
[9];
3774 dbug(1, dprintf("manufacturer_res"));
3776 if ((msg
[0].length
== 0)
3777 || (msg
[1].length
== 0)
3778 || (GET_DWORD(msg
[0].info
) != _DI_MANU_ID
))
3782 indication
= GET_WORD(msg
[1].info
);
3786 case _DI_NEGOTIATE_B3
:
3789 if (((plci
->B3_prot
!= 4) && (plci
->B3_prot
!= 5))
3790 || !(plci
->ncpi_state
& NCPI_NEGOTIATE_B3_SENT
))
3792 dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795 if (api_parse(&msg
[2].info
[1], msg
[2].length
, "ws", m_parms
))
3797 dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3801 len
= offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
;
3802 if (plci
->fax_connect_info_length
< len
)
3804 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->station_id_len
= 0;
3805 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->head_line_len
= 0;
3807 if (api_parse(&ncpi
->info
[1], ncpi
->length
, "wwwwssss", fax_parms
))
3809 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3813 if (plci
->fax_connect_info_length
<= len
)
3814 plci
->fax_connect_info_buffer
[len
] = 0;
3815 len
+= 1 + plci
->fax_connect_info_buffer
[len
];
3816 if (plci
->fax_connect_info_length
<= len
)
3817 plci
->fax_connect_info_buffer
[len
] = 0;
3818 len
+= 1 + plci
->fax_connect_info_buffer
[len
];
3819 if ((fax_parms
[7].length
>= 3) && (fax_parms
[7].info
[1] >= 2))
3820 plci
->nsf_control_bits
= GET_WORD(&fax_parms
[7].info
[2]);
3821 plci
->fax_connect_info_buffer
[len
++] = (byte
)(fax_parms
[7].length
);
3822 for (i
= 0; i
< fax_parms
[7].length
; i
++)
3823 plci
->fax_connect_info_buffer
[len
++] = fax_parms
[7].info
[1 + i
];
3825 plci
->fax_connect_info_length
= len
;
3826 plci
->fax_edata_ack_length
= plci
->fax_connect_info_length
;
3827 start_internal_command(Id
, plci
, fax_edata_ack_command
);
3834 /*------------------------------------------------------------------*/
3835 /* IDI callback function */
3836 /*------------------------------------------------------------------*/
3838 void callback(ENTITY
*e
)
3840 DIVA_CAPI_ADAPTER
*a
;
3851 dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3852 (e
->user
[0] + 1) & 0x7fff, e
->Id
, e
->Req
, e
->Rc
, e
->Ind
));
3854 a
= &(adapter
[(byte
)e
->user
[0]]);
3855 plci
= &(a
->plci
[e
->user
[1]]);
3856 no_cancel_rc
= DIVA_CAPI_SUPPORTS_NO_CANCEL(a
);
3859 If new protocol code and new XDI is used then CAPI should work
3860 fully in accordance with IDI cpec an look on callback field instead
3861 of Rc field for return codes.
3863 if (((e
->complete
== 0xff) && no_cancel_rc
) ||
3864 (e
->Rc
&& !no_cancel_rc
)) {
3870 if (e
->user
[0] & 0x8000)
3873 If REMOVE request was sent then we have to wait until
3874 return code with Id set to zero arrives.
3875 All other return codes should be ignored.
3881 dbug(1, dprintf("cancel RC in REMOVE state"));
3884 channel_flow_control_remove(plci
);
3885 for (i
= 0; i
< 256; i
++)
3887 if (a
->FlowControlIdTable
[i
] == plci
->nl_remove_id
)
3888 a
->FlowControlIdTable
[i
] = 0;
3890 plci
->nl_remove_id
= 0;
3891 if (plci
->rx_dma_descriptor
> 0) {
3892 diva_free_dma_descriptor(plci
, plci
->rx_dma_descriptor
- 1);
3893 plci
->rx_dma_descriptor
= 0;
3898 a
->FlowControlIdTable
[ch
] = e
->Id
;
3899 a
->FlowControlSkipTable
[ch
] = 0;
3901 a
->ch_flow_control
[ch
] |= N_OK_FC_PENDING
;
3902 a
->ch_flow_plci
[ch
] = plci
->Id
;
3908 Cancel return codes self, if feature was requested
3910 if (no_cancel_rc
&& (a
->FlowControlIdTable
[ch
] == e
->Id
) && e
->Id
) {
3911 a
->FlowControlIdTable
[ch
] = 0;
3912 if ((rc
== OK
) && a
->FlowControlSkipTable
[ch
]) {
3913 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e
->Id
, ch
));
3918 if (a
->ch_flow_control
[ch
] & N_OK_FC_PENDING
)
3920 a
->ch_flow_control
[ch
] &= ~N_OK_FC_PENDING
;
3928 control_rc(plci
, 0, rc
, ch
, 0, true);
3933 channel_x_on(plci
, ch
);
3934 if (plci
->internal_command
)
3935 control_rc(plci
, req
, rc
, ch
, 0, true);
3939 if (plci
->nl_global_req
)
3941 global_req
= plci
->nl_global_req
;
3942 plci
->nl_global_req
= 0;
3943 if (rc
!= ASSIGN_OK
) {
3945 if (plci
->rx_dma_descriptor
> 0) {
3946 diva_free_dma_descriptor(plci
, plci
->rx_dma_descriptor
- 1);
3947 plci
->rx_dma_descriptor
= 0;
3950 channel_xmit_xon(plci
);
3951 control_rc(plci
, 0, rc
, ch
, global_req
, true);
3953 else if (plci
->data_sent
)
3955 channel_xmit_xon(plci
);
3956 plci
->data_sent
= false;
3959 if (plci
->internal_command
)
3960 control_rc(plci
, req
, rc
, ch
, 0, true);
3964 channel_xmit_xon(plci
);
3965 control_rc(plci
, req
, rc
, ch
, 0, true);
3973 If REMOVE request was sent then we have to wait until
3974 return code with Id set to zero arrives.
3975 All other return codes should be ignored.
3981 dbug(1, dprintf("cancel RC in REMOVE state"));
3984 plci
->sig_remove_id
= 0;
3987 if (plci
->sig_global_req
)
3989 global_req
= plci
->sig_global_req
;
3990 plci
->sig_global_req
= 0;
3991 if (rc
!= ASSIGN_OK
)
3993 channel_xmit_xon(plci
);
3994 control_rc(plci
, 0, rc
, ch
, global_req
, false);
3998 channel_xmit_xon(plci
);
3999 control_rc(plci
, req
, rc
, ch
, 0, false);
4003 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4004 same callback. Also if new XDI and protocol code used then jump
4008 channel_xmit_xon(plci
);
4009 goto capi_callback_suffix
;
4013 channel_xmit_xon(plci
);
4016 if (e
->user
[0] & 0x8000) {
4017 byte Ind
= e
->Ind
& 0x0f;
4019 if (((Ind
== N_DISC
) || (Ind
== N_DISC_ACK
)) &&
4020 (a
->ch_flow_plci
[Ch
] == plci
->Id
)) {
4021 if (a
->ch_flow_control
[Ch
] & N_RX_FLOW_CONTROL_MASK
) {
4022 dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch
));
4024 a
->ch_flow_control
[Ch
] &= ~N_RX_FLOW_CONTROL_MASK
;
4027 if ((e
->RNR
!= 1) &&
4028 (a
->ch_flow_plci
[Ch
] == plci
->Id
) &&
4029 (a
->ch_flow_control
[Ch
] & N_RX_FLOW_CONTROL_MASK
)) {
4030 a
->ch_flow_control
[Ch
] &= ~N_RX_FLOW_CONTROL_MASK
;
4031 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch
));
4039 capi_callback_suffix
:
4041 while (!plci
->req_in
4042 && !plci
->internal_command
4043 && (plci
->msg_in_write_pos
!= plci
->msg_in_read_pos
))
4045 j
= (plci
->msg_in_read_pos
== plci
->msg_in_wrap_pos
) ? 0 : plci
->msg_in_read_pos
;
4047 i
= (((CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[j
]))->header
.length
+ 3) & 0xfffc;
4049 m
= (CAPI_MSG
*)(&((byte
*)(plci
->msg_in_queue
))[j
]);
4050 appl
= *((APPL
**)(&((byte
*)(plci
->msg_in_queue
))[j
+ i
]));
4051 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4052 m
->header
.command
, plci
->msg_in_write_pos
, plci
->msg_in_read_pos
, plci
->msg_in_wrap_pos
));
4053 if (plci
->msg_in_read_pos
== plci
->msg_in_wrap_pos
)
4055 plci
->msg_in_wrap_pos
= MSG_IN_QUEUE_SIZE
;
4056 plci
->msg_in_read_pos
= i
+ MSG_IN_OVERHEAD
;
4060 plci
->msg_in_read_pos
= j
+ i
+ MSG_IN_OVERHEAD
;
4062 if (plci
->msg_in_read_pos
== plci
->msg_in_write_pos
)
4064 plci
->msg_in_write_pos
= MSG_IN_QUEUE_SIZE
;
4065 plci
->msg_in_read_pos
= MSG_IN_QUEUE_SIZE
;
4067 else if (plci
->msg_in_read_pos
== plci
->msg_in_wrap_pos
)
4069 plci
->msg_in_read_pos
= MSG_IN_QUEUE_SIZE
;
4070 plci
->msg_in_wrap_pos
= MSG_IN_QUEUE_SIZE
;
4072 i
= api_put(appl
, m
);
4075 if (m
->header
.command
== _DATA_B3_R
)
4077 TransmitBufferFree(appl
, (byte
*)(long)(m
->info
.data_b3_req
.Data
));
4079 dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i
, m
->header
.command
));
4083 if (plci
->li_notify_update
)
4085 plci
->li_notify_update
= false;
4086 mixer_notify_update(plci
, false);
4095 static void control_rc(PLCI
*plci
, byte req
, byte rc
, byte ch
, byte global_req
,
4104 DIVA_CAPI_ADAPTER
*a
;
4107 byte SSparms
[] = "\x05\x00\x00\x02\x00\x00";
4108 byte SSstruct
[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req
, rc
, ch
, global_req
, nl_rc
));
4114 dbug(1, dprintf("req0_in/out=%d/%d", plci
->req_in
, plci
->req_out
));
4115 if (plci
->req_in
!= plci
->req_out
)
4117 if (nl_rc
|| (global_req
!= ASSIGN
) || (rc
== ASSIGN_OK
))
4119 dbug(1, dprintf("req_1return"));
4122 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4124 plci
->req_in
= plci
->req_in_start
= plci
->req_out
= 0;
4125 dbug(1, dprintf("control_rc"));
4129 ncci
= a
->ch_ncci
[ch
];
4132 Id
= (((dword
)(ncci
? ncci
: ch
)) << 16) | ((word
)plci
->Id
<< 8) | a
->Id
;
4133 if (plci
->tel
&& plci
->SuppState
!= CALL_HELD
) Id
|= EXT_CONTROLLER
;
4134 Number
= plci
->number
;
4135 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
));
4136 dbug(1, dprintf("channels=0x%x", plci
->channels
));
4137 if (plci_remove_check(plci
))
4139 if (req
== REMOVE
&& rc
== ASSIGN_OK
)
4141 sig_req(plci
, HANGUP
, 0);
4142 sig_req(plci
, REMOVE
, 0);
4147 switch (plci
->command
)
4150 dbug(1, dprintf("HoldRC=0x%x", rc
));
4151 SSparms
[1] = (byte
)S_HOLD
;
4154 plci
->SuppState
= IDLE
;
4157 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
, Number
, "wws", Info
, 3, SSparms
);
4160 case C_RETRIEVE_REQ
:
4161 dbug(1, dprintf("RetrieveRC=0x%x", rc
));
4162 SSparms
[1] = (byte
)S_RETRIEVE
;
4165 plci
->SuppState
= CALL_HELD
;
4168 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
, Number
, "wws", Info
, 3, SSparms
);
4172 dbug(1, dprintf("InfoRC=0x%x", rc
));
4173 if (rc
!= OK
) Info
= _WRONG_STATE
;
4174 sendf(appl
, _INFO_R
| CONFIRM
, Id
, Number
, "w", Info
);
4178 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req
, rc
, global_req
, nl_rc
));
4179 if (plci
->State
== INC_DIS_PENDING
)
4181 if (plci
->Sig
.Id
!= 0xff)
4183 if (((global_req
== ASSIGN
) && (rc
!= ASSIGN_OK
))
4184 || (!nl_rc
&& (req
== CALL_REQ
) && (rc
!= OK
)))
4186 dbug(1, dprintf("No more IDs/Call_Req failed"));
4187 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
& 0xffL
, Number
, "w", _OUT_OF_PLCI
);
4192 if (plci
->State
!= LOCAL_CONNECT
) plci
->State
= OUTG_CON_PENDING
;
4193 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
, Number
, "w", 0);
4195 else /* D-ch activation */
4197 if (rc
!= ASSIGN_OK
)
4199 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4200 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
& 0xffL
, Number
, "w", _OUT_OF_PLCI
);
4205 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
, Number
, "w", 0);
4206 sendf(plci
->appl
, _CONNECT_ACTIVE_I
, Id
, 0, "sss", "", "", "");
4207 plci
->State
= INC_ACT_PENDING
;
4211 case _CONNECT_I
| RESPONSE
:
4212 if (plci
->State
!= INC_DIS_PENDING
)
4213 plci
->State
= INC_CON_ACCEPT
;
4217 if (plci
->State
== INC_DIS_PENDING
)
4219 if (plci
->Sig
.Id
!= 0xff)
4221 plci
->State
= OUTG_DIS_PENDING
;
4222 sendf(appl
, _DISCONNECT_R
| CONFIRM
, Id
, Number
, "w", 0);
4235 sendf(appl
, _CONNECT_B3_R
| CONFIRM
, Id
, Number
, "w", _WRONG_IDENTIFIER
);
4238 ncci
= get_ncci(plci
, ch
, 0);
4239 Id
= (Id
& 0xffff) | (((dword
) ncci
) << 16);
4243 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
4244 sendf(appl
, _CONNECT_B3_R
| CONFIRM
, Id
, Number
, "w", 0);
4245 sendf(appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
4249 a
->ncci_state
[ncci
] = OUTG_CON_PENDING
;
4250 sendf(appl
, _CONNECT_B3_R
| CONFIRM
, Id
, Number
, "w", 0);
4254 case _CONNECT_B3_I
| RESPONSE
:
4258 /* sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261 case _DISCONNECT_B3_R
:
4262 sendf(appl
, _DISCONNECT_B3_R
| CONFIRM
, Id
, Number
, "w", 0);
4265 case _MANUFACTURER_R
:
4271 Info
= _WRONG_IDENTIFIER
;
4272 sendf(plci
->appl
, _CONNECT_R
| CONFIRM
, Id
, Number
, "w", Info
);
4276 sendf(plci
->appl
, _CONNECT_R
| CONFIRM
, Id
, Number
, "w", Info
);
4284 else if (plci
->internal_command
)
4286 switch (plci
->internal_command
)
4292 if (rc
== OK
) /* command supported, wait for indication */
4299 /* Get Supported Services */
4300 case GETSERV_REQ_PEND
:
4301 if (rc
== OK
) /* command supported, wait for indication */
4305 PUT_DWORD(&SSstruct
[6], MASK_TERMINAL_PORTABILITY
);
4306 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
, Number
, "wws", 0, 3, SSstruct
);
4310 case INTERR_DIVERSION_REQ_PEND
: /* Interrogate Parameters */
4311 case INTERR_NUMBERS_REQ_PEND
:
4312 case CF_START_PEND
: /* Call Forwarding Start pending */
4313 case CF_STOP_PEND
: /* Call Forwarding Stop pending */
4314 case CCBS_REQUEST_REQ_PEND
:
4315 case CCBS_DEACTIVATE_REQ_PEND
:
4316 case CCBS_INTERROGATE_REQ_PEND
:
4317 switch (plci
->internal_command
)
4319 case INTERR_DIVERSION_REQ_PEND
:
4320 SSparms
[1] = S_INTERROGATE_DIVERSION
;
4322 case INTERR_NUMBERS_REQ_PEND
:
4323 SSparms
[1] = S_INTERROGATE_NUMBERS
;
4326 SSparms
[1] = S_CALL_FORWARDING_START
;
4329 SSparms
[1] = S_CALL_FORWARDING_STOP
;
4331 case CCBS_REQUEST_REQ_PEND
:
4332 SSparms
[1] = S_CCBS_REQUEST
;
4334 case CCBS_DEACTIVATE_REQ_PEND
:
4335 SSparms
[1] = S_CCBS_DEACTIVATE
;
4337 case CCBS_INTERROGATE_REQ_PEND
:
4338 SSparms
[1] = S_CCBS_INTERROGATE
;
4341 if (global_req
== ASSIGN
)
4343 dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req
, rc
));
4346 if (!plci
->appl
) break;
4347 if (rc
== ISDN_GUARD_REJ
)
4349 Info
= _CAPI_GUARD_ERROR
;
4353 Info
= _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED
;
4355 sendf(plci
->appl
, _FACILITY_R
| CONFIRM
, Id
& 0x7,
4356 plci
->number
, "wws", Info
, (word
)3, SSparms
);
4357 if (Info
) plci_remove(plci
);
4360 /* 3pty conference pending */
4362 if (!plci
->relatedPTYPLCI
) break;
4363 rplci
= plci
->relatedPTYPLCI
;
4364 SSparms
[1] = plci
->ptyState
;
4365 rId
= ((word
)rplci
->Id
<< 8) | rplci
->adapter
->Id
;
4366 if (rplci
->tel
) rId
|= EXT_CONTROLLER
;
4369 Info
= 0x300E; /* not supported */
4370 plci
->relatedPTYPLCI
= NULL
;
4374 _FACILITY_R
| CONFIRM
,
4377 "wws", Info
, (word
)3, SSparms
);
4380 /* Explicit Call Transfer pending */
4382 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req
, rc
));
4383 if (!plci
->relatedPTYPLCI
) break;
4384 rplci
= plci
->relatedPTYPLCI
;
4386 rId
= ((word
)rplci
->Id
<< 8) | rplci
->adapter
->Id
;
4387 if (rplci
->tel
) rId
|= EXT_CONTROLLER
;
4390 Info
= 0x300E; /* not supported */
4391 plci
->relatedPTYPLCI
= NULL
;
4395 _FACILITY_R
| CONFIRM
,
4398 "wws", Info
, (word
)3, SSparms
);
4401 case _MANUFACTURER_R
:
4402 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req
, rc
));
4403 if ((global_req
== ASSIGN
) && (rc
!= ASSIGN_OK
))
4405 dbug(1, dprintf("No more IDs"));
4406 sendf(appl
, _MANUFACTURER_R
| CONFIRM
, Id
, Number
, "dww", _DI_MANU_ID
, _MANUFACTURER_R
, _OUT_OF_PLCI
);
4407 plci_remove(plci
); /* after codec init, internal codec commands pending */
4412 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req
, rc
));
4413 if ((global_req
== ASSIGN
) && (rc
!= ASSIGN_OK
))
4415 dbug(1, dprintf("No more IDs"));
4416 sendf(appl
, _CONNECT_R
| CONFIRM
, Id
& 0xffL
, Number
, "w", _OUT_OF_PLCI
);
4417 plci_remove(plci
); /* after codec init, internal codec commands pending */
4421 case PERM_COD_HOOK
: /* finished with Hook_Ind */
4425 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc
));
4426 plci
->internal_command
= PERM_COD_CONN_PEND
;
4429 case PERM_COD_ASSIGN
:
4430 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc
));
4431 if (rc
!= ASSIGN_OK
) break;
4432 sig_req(plci
, CALL_REQ
, 0);
4434 plci
->internal_command
= PERM_COD_CALL
;
4437 /* Null Call Reference Request pending */
4439 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req
, rc
));
4440 if (global_req
== ASSIGN
)
4442 if (rc
== ASSIGN_OK
)
4448 sendf(appl
, _INFO_R
| CONFIRM
, Id
& 0xf, Number
, "w", _WRONG_STATE
);
4449 appl
->NullCREnable
= false;
4453 else if (req
== NCR_FACILITY
)
4457 sendf(appl
, _INFO_R
| CONFIRM
, Id
& 0xf, Number
, "w", 0);
4461 sendf(appl
, _INFO_R
| CONFIRM
, Id
& 0xf, Number
, "w", _WRONG_STATE
);
4462 appl
->NullCREnable
= false;
4471 if (a
->ncci_state
[ncci
] == CONNECTED
)
4473 a
->ncci_state
[ncci
] = OUTG_DIS_PENDING
;
4474 cleanup_ncci_data(plci
, ncci
);
4475 nl_req_ncci(plci
, N_DISC
, (byte
)ncci
);
4482 if (plci
->State
== INC_DIS_PENDING
)
4484 sig_req(plci
, CALL_REQ
, 0);
4486 plci
->State
= OUTG_CON_PENDING
;
4490 case MWI_ACTIVATE_REQ_PEND
:
4491 case MWI_DEACTIVATE_REQ_PEND
:
4492 if (global_req
== ASSIGN
&& rc
== ASSIGN_OK
)
4494 dbug(1, dprintf("MWI_REQ assigned"));
4501 Info
= 0x2007; /* Illegal message parameter coding */
4502 dbug(1, dprintf("MWI_REQ invalid parameter"));
4506 Info
= 0x300B; /* not supported */
4507 dbug(1, dprintf("MWI_REQ not supported"));
4509 /* 0x3010: Request not allowed in this state */
4510 PUT_WORD(&SSparms
[4], 0x300E); /* SS not supported */
4513 if (plci
->internal_command
== MWI_ACTIVATE_REQ_PEND
)
4515 PUT_WORD(&SSparms
[1], S_MWI_ACTIVATE
);
4517 else PUT_WORD(&SSparms
[1], S_MWI_DEACTIVATE
);
4519 if (plci
->cr_enquiry
)
4522 _FACILITY_R
| CONFIRM
,
4525 "wws", Info
, (word
)3, SSparms
);
4526 if (rc
!= OK
) plci_remove(plci
);
4531 _FACILITY_R
| CONFIRM
,
4534 "wws", Info
, (word
)3, SSparms
);
4538 case CONF_BEGIN_REQ_PEND
:
4539 case CONF_ADD_REQ_PEND
:
4540 case CONF_SPLIT_REQ_PEND
:
4541 case CONF_DROP_REQ_PEND
:
4542 case CONF_ISOLATE_REQ_PEND
:
4543 case CONF_REATTACH_REQ_PEND
:
4544 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req
, rc
));
4545 if ((plci
->internal_command
== CONF_ADD_REQ_PEND
) && (!plci
->relatedPTYPLCI
)) break;
4548 switch (plci
->internal_command
)
4550 case CONF_BEGIN_REQ_PEND
:
4551 SSparms
[1] = S_CONF_BEGIN
;
4553 case CONF_ADD_REQ_PEND
:
4554 SSparms
[1] = S_CONF_ADD
;
4555 rplci
= plci
->relatedPTYPLCI
;
4556 rId
= ((word
)rplci
->Id
<< 8) | rplci
->adapter
->Id
;
4558 case CONF_SPLIT_REQ_PEND
:
4559 SSparms
[1] = S_CONF_SPLIT
;
4561 case CONF_DROP_REQ_PEND
:
4562 SSparms
[1] = S_CONF_DROP
;
4564 case CONF_ISOLATE_REQ_PEND
:
4565 SSparms
[1] = S_CONF_ISOLATE
;
4567 case CONF_REATTACH_REQ_PEND
:
4568 SSparms
[1] = S_CONF_REATTACH
;
4574 Info
= 0x300E; /* not supported */
4575 plci
->relatedPTYPLCI
= NULL
;
4579 _FACILITY_R
| CONFIRM
,
4582 "wws", Info
, (word
)3, SSparms
);
4585 case VSWITCH_REQ_PEND
:
4588 if (plci
->relatedPTYPLCI
)
4590 plci
->relatedPTYPLCI
->vswitchstate
= 0;
4591 plci
->relatedPTYPLCI
->vsprot
= 0;
4592 plci
->relatedPTYPLCI
->vsprotdialect
= 0;
4594 plci
->vswitchstate
= 0;
4596 plci
->vsprotdialect
= 0;
4600 if (plci
->relatedPTYPLCI
&&
4601 plci
->vswitchstate
== 1 &&
4602 plci
->relatedPTYPLCI
->vswitchstate
== 3) /* join complete */
4603 plci
->vswitchstate
= 3;
4607 /* Call Deflection Request pending (SSCT) */
4609 SSparms
[1] = S_CALL_DEFLECTION
;
4612 Info
= 0x300E; /* not supported */
4613 plci
->appl
->CDEnable
= 0;
4615 sendf(plci
->appl
, _FACILITY_R
| CONFIRM
, Id
,
4616 plci
->number
, "wws", Info
, (word
)3, SSparms
);
4619 case RTP_CONNECT_B3_REQ_COMMAND_2
:
4622 ncci
= get_ncci(plci
, ch
, 0);
4623 Id
= (Id
& 0xffff) | (((dword
) ncci
) << 16);
4625 a
->ncci_state
[ncci
] = OUTG_CON_PENDING
;
4629 if (plci
->internal_command_queue
[0])
4631 (*(plci
->internal_command_queue
[0]))(Id
, plci
, rc
);
4632 if (plci
->internal_command
)
4637 next_internal_command(Id
, plci
);
4642 Id
= ((word
)plci
->Id
<< 8) | plci
->adapter
->Id
;
4643 if (plci
->tel
) Id
|= EXT_CONTROLLER
;
4645 switch (plci
->internal_command
)
4650 case START_L1_SIG_ASSIGN_PEND
:
4651 case REM_L1_SIG_ASSIGN_PEND
:
4652 if (global_req
== ASSIGN
)
4658 dbug(1, dprintf("***L1 Req rem PLCI"));
4659 plci
->internal_command
= 0;
4660 sig_req(plci
, REMOVE
, 0);
4665 /* Call Deflection Request pending, just no appl ptr assigned */
4667 SSparms
[1] = S_CALL_DEFLECTION
;
4670 Info
= 0x300E; /* not supported */
4672 for (i
= 0; i
< max_appl
; i
++)
4674 if (application
[i
].CDEnable
)
4676 if (!application
[i
].Id
) application
[i
].CDEnable
= 0;
4679 sendf(&application
[i
], _FACILITY_R
| CONFIRM
, Id
,
4680 plci
->number
, "wws", Info
, (word
)3, SSparms
);
4681 if (Info
) application
[i
].CDEnable
= 0;
4685 plci
->internal_command
= 0;
4688 case PERM_COD_HOOK
: /* finished with Hook_Ind */
4692 plci
->internal_command
= PERM_COD_CONN_PEND
;
4693 dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc
));
4696 case PERM_COD_ASSIGN
:
4697 dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc
));
4698 plci
->internal_command
= 0;
4699 if (rc
!= ASSIGN_OK
) break;
4700 plci
->internal_command
= PERM_COD_CALL
;
4701 sig_req(plci
, CALL_REQ
, 0);
4705 case LISTEN_SIG_ASSIGN_PEND
:
4706 if (rc
== ASSIGN_OK
)
4708 plci
->internal_command
= 0;
4709 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci
->Sig
.Id
));
4710 add_p(plci
, ESC
, "\x02\x18\x00"); /* support call waiting */
4711 sig_req(plci
, INDICATE_REQ
, 0);
4716 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc
));
4724 if (global_req
== ASSIGN
)
4726 if (rc
== ASSIGN_OK
)
4728 sig_req(plci
, LAW_REQ
, 0);
4730 dbug(1, dprintf("Auto-Law assigned"));
4734 dbug(1, dprintf("Auto-Law assign failed"));
4735 a
->automatic_law
= 3;
4736 plci
->internal_command
= 0;
4737 a
->automatic_lawPLCI
= NULL
;
4741 else if (req
== LAW_REQ
&& rc
== OK
)
4743 dbug(1, dprintf("Auto-Law initiated"));
4744 a
->automatic_law
= 2;
4745 plci
->internal_command
= 0;
4749 dbug(1, dprintf("Auto-Law not supported"));
4750 a
->automatic_law
= 3;
4751 plci
->internal_command
= 0;
4752 sig_req(plci
, REMOVE
, 0);
4754 a
->automatic_lawPLCI
= NULL
;
4758 plci_remove_check(plci
);
4762 static void data_rc(PLCI
*plci
, byte ch
)
4765 DIVA_CAPI_ADAPTER
*a
;
4772 TransmitBufferFree(plci
->appl
, plci
->data_sent_ptr
);
4774 ncci
= a
->ch_ncci
[ch
];
4775 if (ncci
&& (a
->ncci_plci
[ncci
] == plci
->Id
))
4777 ncci_ptr
= &(a
->ncci
[ncci
]);
4778 dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr
->data_out
, ncci_ptr
->data_pending
));
4779 if (ncci_ptr
->data_pending
)
4781 data
= &(ncci_ptr
->DBuffer
[ncci_ptr
->data_out
]);
4782 if (!(data
->Flags
& 4) && a
->ncci_state
[ncci
])
4784 Id
= (((dword
)ncci
) << 16) | ((word
)plci
->Id
<< 8) | a
->Id
;
4785 if (plci
->tel
) Id
|= EXT_CONTROLLER
;
4786 sendf(plci
->appl
, _DATA_B3_R
| CONFIRM
, Id
, data
->Number
,
4787 "ww", data
->Handle
, 0);
4789 (ncci_ptr
->data_out
)++;
4790 if (ncci_ptr
->data_out
== MAX_DATA_B3
)
4791 ncci_ptr
->data_out
= 0;
4792 (ncci_ptr
->data_pending
)--;
4798 static void data_ack(PLCI
*plci
, byte ch
)
4801 DIVA_CAPI_ADAPTER
*a
;
4806 ncci
= a
->ch_ncci
[ch
];
4807 ncci_ptr
= &(a
->ncci
[ncci
]);
4808 if (ncci_ptr
->data_ack_pending
)
4810 if (a
->ncci_state
[ncci
] && (a
->ncci_plci
[ncci
] == plci
->Id
))
4812 Id
= (((dword
)ncci
) << 16) | ((word
)plci
->Id
<< 8) | a
->Id
;
4813 if (plci
->tel
) Id
|= EXT_CONTROLLER
;
4814 sendf(plci
->appl
, _DATA_B3_R
| CONFIRM
, Id
, ncci_ptr
->DataAck
[ncci_ptr
->data_ack_out
].Number
,
4815 "ww", ncci_ptr
->DataAck
[ncci_ptr
->data_ack_out
].Handle
, 0);
4817 (ncci_ptr
->data_ack_out
)++;
4818 if (ncci_ptr
->data_ack_out
== MAX_DATA_ACK
)
4819 ncci_ptr
->data_ack_out
= 0;
4820 (ncci_ptr
->data_ack_pending
)--;
4824 static void sig_ind(PLCI
*plci
)
4833 DIVA_CAPI_ADAPTER
*a
;
4834 API_PARSE saved_parms
[MAX_MSG_PARMS
+ 1];
4835 #define MAXPARMSIDS 31
4836 byte
*parms
[MAXPARMSIDS
];
4838 byte
*multi_fac_parms
[MAX_MULTI_IE
];
4839 byte
*multi_pi_parms
[MAX_MULTI_IE
];
4840 byte
*multi_ssext_parms
[MAX_MULTI_IE
];
4841 byte
*multi_CiPN_parms
[MAX_MULTI_IE
];
4843 byte
*multi_vswitch_parms
[MAX_MULTI_IE
];
4850 byte
*esc_profile
= "";
4854 byte chi
[] = "\x02\x18\x01";
4855 byte voice_cai
[] = "\x06\x14\x00\x00\x00\x00\x08";
4856 byte resume_cau
[] = "\x05\x05\x00\x02\x00\x00";
4857 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4858 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4859 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4860 /* (see Info_Mask Bit 4, first IE. then the message type) */
4862 {MAXPARMSIDS
, CPN
, 0xff, DSA
, OSA
, BC
, LLC
, HLC
, ESC_CAUSE
, DSP
, DT
, CHA
,
4863 UUI
, CONG_RR
, CONG_RNR
, ESC_CHI
, KEY
, CHI
, CAU
, ESC_LAW
,
4864 RDN
, RDX
, CONN_NR
, RIN
, NI
, CAI
, ESC_CR
,
4865 CST
, ESC_PROFILE
, 0xff, ESC_MSGTYPE
, SMSG
};
4866 /* 14 FTY repl by ESC_CHI */
4867 /* 18 PI repl by ESC_LAW */
4868 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4869 word multi_fac_id
[] = {1, FTY
};
4870 word multi_pi_id
[] = {1, PI
};
4871 word multi_CiPN_id
[] = {1, OAD
};
4872 word multi_ssext_id
[] = {1, ESC_SSEXT
};
4874 word multi_vswitch_id
[] = {1, ESC_VSWITCH
};
4878 byte SS_Ind
[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4879 byte CF_Ind
[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4880 byte Interr_Err_Ind
[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4881 byte CONF_Ind
[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4882 byte force_mt_info
= false;
4888 Id
= ((word
)plci
->Id
<< 8) | a
->Id
;
4889 PUT_WORD(&SS_Ind
[4], 0x0000);
4891 if (plci
->sig_remove_id
)
4893 plci
->Sig
.RNR
= 2; /* discard */
4894 dbug(1, dprintf("SIG discard while remove pending"));
4897 if (plci
->tel
&& plci
->SuppState
!= CALL_HELD
) Id
|= EXT_CONTROLLER
;
4898 dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4899 Id
, plci
->Id
, plci
->tel
, plci
->State
, plci
->channels
, plci
->hangup_flow_ctrl_timer
));
4900 if (plci
->Sig
.Ind
== CALL_HOLD_ACK
&& plci
->channels
)
4905 if (plci
->Sig
.Ind
== HANGUP
&& plci
->channels
)
4908 plci
->hangup_flow_ctrl_timer
++;
4909 /* recover the network layer after timeout */
4910 if (plci
->hangup_flow_ctrl_timer
== 100)
4912 dbug(1, dprintf("Exceptional disc"));
4914 plci
->hangup_flow_ctrl_timer
= 0;
4915 for (ncci
= 1; ncci
< MAX_NCCI
+ 1; ncci
++)
4917 if (a
->ncci_plci
[ncci
] == plci
->Id
)
4919 cleanup_ncci_data(plci
, ncci
);
4920 if (plci
->channels
)plci
->channels
--;
4922 sendf(plci
->appl
, _DISCONNECT_B3_I
, (((dword
) ncci
) << 16) | Id
, 0, "ws", 0, "");
4926 sendf(plci
->appl
, _DISCONNECT_I
, Id
, 0, "w", 0);
4933 /* do first parse the info with no OAD in, because OAD will be converted */
4934 /* first the multiple facility IE, then mult. progress ind. */
4935 /* then the parameters for the info_ind + conn_ind */
4936 IndParse(plci
, multi_fac_id
, multi_fac_parms
, MAX_MULTI_IE
);
4937 IndParse(plci
, multi_pi_id
, multi_pi_parms
, MAX_MULTI_IE
);
4938 IndParse(plci
, multi_ssext_id
, multi_ssext_parms
, MAX_MULTI_IE
);
4940 IndParse(plci
, multi_vswitch_id
, multi_vswitch_parms
, MAX_MULTI_IE
);
4942 IndParse(plci
, parms_id
, parms
, 0);
4943 IndParse(plci
, multi_CiPN_id
, multi_CiPN_parms
, MAX_MULTI_IE
);
4944 esc_chi
= parms
[14];
4945 esc_law
= parms
[18];
4946 pty_cai
= parms
[24];
4948 esc_profile
= parms
[27];
4949 if (esc_cr
[0] && plci
)
4951 if (plci
->cr_enquiry
&& plci
->appl
)
4953 plci
->cr_enquiry
= false;
4956 /* b = total length */
4957 /* b = indication type */
4958 /* b = length of all IEs */
4960 /* S = IE1 length + cont. */
4962 /* S = IE2 length + cont. */
4967 "dwbbbbSbS", _DI_MANU_ID
, plci
->m_command
,
4968 2 + 1 + 1 + esc_cr
[0] + 1 + 1 + esc_law
[0], plci
->Sig
.Ind
, 1 + 1 + esc_cr
[0] + 1 + 1 + esc_law
[0], ESC
, esc_cr
, ESC
, esc_law
);
4971 /* create the additional info structure */
4972 add_i
[1] = parms
[15]; /* KEY of additional info */
4973 add_i
[2] = parms
[11]; /* UUI of additional info */
4974 ai_len
= AddInfo(add_i
, multi_fac_parms
, esc_chi
, facility
);
4976 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4977 /* indication returns by the card if requested by the function */
4978 /* AutomaticLaw() after driver init */
4979 if (a
->automatic_law
< 4)
4983 dbug(0, dprintf("u-Law selected"));
4987 dbug(0, dprintf("a-Law selected"));
4990 a
->automatic_law
= 4;
4991 if (plci
== a
->automatic_lawPLCI
) {
4992 plci
->internal_command
= 0;
4993 sig_req(plci
, REMOVE
, 0);
4995 a
->automatic_lawPLCI
= NULL
;
5000 dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5001 UnMapController(a
->Id
), GET_DWORD(&esc_profile
[6]),
5002 GET_DWORD(&esc_profile
[10]), GET_DWORD(&esc_profile
[14]),
5003 GET_DWORD(&esc_profile
[18]), GET_DWORD(&esc_profile
[46])));
5005 a
->profile
.Global_Options
&= 0x000000ffL
;
5006 a
->profile
.B1_Protocols
&= 0x000003ffL
;
5007 a
->profile
.B2_Protocols
&= 0x00001fdfL
;
5008 a
->profile
.B3_Protocols
&= 0x000000b7L
;
5010 a
->profile
.Global_Options
&= GET_DWORD(&esc_profile
[6]) |
5011 GL_BCHANNEL_OPERATION_SUPPORTED
;
5012 a
->profile
.B1_Protocols
&= GET_DWORD(&esc_profile
[10]);
5013 a
->profile
.B2_Protocols
&= GET_DWORD(&esc_profile
[14]);
5014 a
->profile
.B3_Protocols
&= GET_DWORD(&esc_profile
[18]);
5015 a
->manufacturer_features
= GET_DWORD(&esc_profile
[46]);
5016 a
->man_profile
.private_options
= 0;
5018 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_ECHO_CANCELLER
)
5020 a
->man_profile
.private_options
|= 1L << PRIVATE_ECHO_CANCELLER
;
5021 a
->profile
.Global_Options
|= GL_ECHO_CANCELLER_SUPPORTED
;
5025 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_RTP
)
5026 a
->man_profile
.private_options
|= 1L << PRIVATE_RTP
;
5027 a
->man_profile
.rtp_primary_payloads
= GET_DWORD(&esc_profile
[50]);
5028 a
->man_profile
.rtp_additional_payloads
= GET_DWORD(&esc_profile
[54]);
5031 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_T38
)
5032 a
->man_profile
.private_options
|= 1L << PRIVATE_T38
;
5035 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD
)
5036 a
->man_profile
.private_options
|= 1L << PRIVATE_FAX_SUB_SEP_PWD
;
5039 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_V18
)
5040 a
->man_profile
.private_options
|= 1L << PRIVATE_V18
;
5043 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_DTMF_TONE
)
5044 a
->man_profile
.private_options
|= 1L << PRIVATE_DTMF_TONE
;
5047 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_PIAFS
)
5048 a
->man_profile
.private_options
|= 1L << PRIVATE_PIAFS
;
5051 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_PAPER_FORMATS
)
5052 a
->man_profile
.private_options
|= 1L << PRIVATE_FAX_PAPER_FORMATS
;
5055 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_VOWN
)
5056 a
->man_profile
.private_options
|= 1L << PRIVATE_VOWN
;
5059 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_NONSTANDARD
)
5060 a
->man_profile
.private_options
|= 1L << PRIVATE_FAX_NONSTANDARD
;
5065 a
->profile
.Global_Options
&= 0x0000007fL
;
5066 a
->profile
.B1_Protocols
&= 0x000003dfL
;
5067 a
->profile
.B2_Protocols
&= 0x00001adfL
;
5068 a
->profile
.B3_Protocols
&= 0x000000b7L
;
5069 a
->manufacturer_features
&= MANUFACTURER_FEATURE_HARDDTMF
;
5071 if (a
->manufacturer_features
& (MANUFACTURER_FEATURE_HARDDTMF
|
5072 MANUFACTURER_FEATURE_SOFTDTMF_SEND
| MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE
))
5074 a
->profile
.Global_Options
|= GL_DTMF_SUPPORTED
;
5076 a
->manufacturer_features
&= ~MANUFACTURER_FEATURE_OOB_CHANNEL
;
5077 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5078 UnMapController(a
->Id
), a
->profile
.Global_Options
,
5079 a
->profile
.B1_Protocols
, a
->profile
.B2_Protocols
,
5080 a
->profile
.B3_Protocols
, a
->manufacturer_features
));
5082 /* codec plci for the handset/hook state support is just an internal id */
5083 if (plci
!= a
->AdvCodecPLCI
)
5085 force_mt_info
= SendMultiIE(plci
, Id
, multi_fac_parms
, FTY
, 0x20, 0);
5086 force_mt_info
|= SendMultiIE(plci
, Id
, multi_pi_parms
, PI
, 0x210, 0);
5087 SendSSExtInd(NULL
, plci
, Id
, multi_ssext_parms
);
5088 SendInfo(plci
, Id
, parms
, force_mt_info
);
5090 VSwitchReqInd(plci
, Id
, multi_vswitch_parms
);
5094 /* switch the codec to the b-channel */
5095 if (esc_chi
[0] && plci
&& !plci
->SuppState
) {
5096 plci
->b_channel
= esc_chi
[esc_chi
[0]]&0x1f;
5097 mixer_set_bchannel_id_esc(plci
, plci
->b_channel
);
5098 dbug(1, dprintf("storeChannel=0x%x", plci
->b_channel
));
5099 if (plci
->tel
== ADV_VOICE
&& plci
->appl
) {
5100 SetVoiceChannel(a
->AdvCodecPLCI
, esc_chi
, a
);
5104 if (plci
->appl
) plci
->appl
->Number
++;
5106 switch (plci
->Sig
.Ind
) {
5107 /* Response to Get_Supported_Services request */
5109 dbug(1, dprintf("S_Supported"));
5110 if (!plci
->appl
) break;
5111 if (pty_cai
[0] == 4)
5113 PUT_DWORD(&CF_Ind
[6], GET_DWORD(&pty_cai
[1]));
5117 PUT_DWORD(&CF_Ind
[6], MASK_TERMINAL_PORTABILITY
| MASK_HOLD_RETRIEVE
);
5119 PUT_WORD(&CF_Ind
[1], 0);
5120 PUT_WORD(&CF_Ind
[4], 0);
5121 sendf(plci
->appl
, _FACILITY_R
| CONFIRM
, Id
& 0x7, plci
->number
, "wws", 0, 3, CF_Ind
);
5125 /* Supplementary Service rejected */
5127 dbug(1, dprintf("S_Reject=0x%x", pty_cai
[5]));
5128 if (!pty_cai
[0]) break;
5133 case THREE_PTY_BEGIN
:
5134 if (!plci
->relatedPTYPLCI
) break;
5135 tplci
= plci
->relatedPTYPLCI
;
5136 rId
= ((word
)tplci
->Id
<< 8) | tplci
->adapter
->Id
;
5137 if (tplci
->tel
) rId
|= EXT_CONTROLLER
;
5138 if (pty_cai
[5] == ECT_EXECUTE
)
5140 PUT_WORD(&SS_Ind
[1], S_ECT
);
5142 plci
->vswitchstate
= 0;
5143 plci
->relatedPTYPLCI
->vswitchstate
= 0;
5148 PUT_WORD(&SS_Ind
[1], pty_cai
[5] + 3);
5150 if (pty_cai
[2] != 0xff)
5152 PUT_WORD(&SS_Ind
[4], 0x3600 | (word
)pty_cai
[2]);
5156 PUT_WORD(&SS_Ind
[4], 0x300E);
5158 plci
->relatedPTYPLCI
= NULL
;
5160 sendf(tplci
->appl
, _FACILITY_I
, rId
, 0, "ws", 3, SS_Ind
);
5163 case CALL_DEFLECTION
:
5164 if (pty_cai
[2] != 0xff)
5166 PUT_WORD(&SS_Ind
[4], 0x3600 | (word
)pty_cai
[2]);
5170 PUT_WORD(&SS_Ind
[4], 0x300E);
5172 PUT_WORD(&SS_Ind
[1], pty_cai
[5]);
5173 for (i
= 0; i
< max_appl
; i
++)
5175 if (application
[i
].CDEnable
)
5177 if (application
[i
].Id
) sendf(&application
[i
], _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5178 application
[i
].CDEnable
= false;
5183 case DEACTIVATION_DIVERSION
:
5184 case ACTIVATION_DIVERSION
:
5185 case DIVERSION_INTERROGATE_CFU
:
5186 case DIVERSION_INTERROGATE_CFB
:
5187 case DIVERSION_INTERROGATE_CFNR
:
5188 case DIVERSION_INTERROGATE_NUM
:
5190 case CCBS_DEACTIVATE
:
5191 case CCBS_INTERROGATE
:
5192 if (!plci
->appl
) break;
5193 if (pty_cai
[2] != 0xff)
5195 PUT_WORD(&Interr_Err_Ind
[4], 0x3600 | (word
)pty_cai
[2]);
5199 PUT_WORD(&Interr_Err_Ind
[4], 0x300E);
5203 case DEACTIVATION_DIVERSION
:
5204 dbug(1, dprintf("Deact_Div"));
5205 Interr_Err_Ind
[0] = 0x9;
5206 Interr_Err_Ind
[3] = 0x6;
5207 PUT_WORD(&Interr_Err_Ind
[1], S_CALL_FORWARDING_STOP
);
5209 case ACTIVATION_DIVERSION
:
5210 dbug(1, dprintf("Act_Div"));
5211 Interr_Err_Ind
[0] = 0x9;
5212 Interr_Err_Ind
[3] = 0x6;
5213 PUT_WORD(&Interr_Err_Ind
[1], S_CALL_FORWARDING_START
);
5215 case DIVERSION_INTERROGATE_CFU
:
5216 case DIVERSION_INTERROGATE_CFB
:
5217 case DIVERSION_INTERROGATE_CFNR
:
5218 dbug(1, dprintf("Interr_Div"));
5219 Interr_Err_Ind
[0] = 0xa;
5220 Interr_Err_Ind
[3] = 0x7;
5221 PUT_WORD(&Interr_Err_Ind
[1], S_INTERROGATE_DIVERSION
);
5223 case DIVERSION_INTERROGATE_NUM
:
5224 dbug(1, dprintf("Interr_Num"));
5225 Interr_Err_Ind
[0] = 0xa;
5226 Interr_Err_Ind
[3] = 0x7;
5227 PUT_WORD(&Interr_Err_Ind
[1], S_INTERROGATE_NUMBERS
);
5230 dbug(1, dprintf("CCBS Request"));
5231 Interr_Err_Ind
[0] = 0xd;
5232 Interr_Err_Ind
[3] = 0xa;
5233 PUT_WORD(&Interr_Err_Ind
[1], S_CCBS_REQUEST
);
5235 case CCBS_DEACTIVATE
:
5236 dbug(1, dprintf("CCBS Deactivate"));
5237 Interr_Err_Ind
[0] = 0x9;
5238 Interr_Err_Ind
[3] = 0x6;
5239 PUT_WORD(&Interr_Err_Ind
[1], S_CCBS_DEACTIVATE
);
5241 case CCBS_INTERROGATE
:
5242 dbug(1, dprintf("CCBS Interrogate"));
5243 Interr_Err_Ind
[0] = 0xb;
5244 Interr_Err_Ind
[3] = 0x8;
5245 PUT_WORD(&Interr_Err_Ind
[1], S_CCBS_INTERROGATE
);
5248 PUT_DWORD(&Interr_Err_Ind
[6], plci
->appl
->S_Handle
);
5249 sendf(plci
->appl
, _FACILITY_I
, Id
& 0x7, 0, "ws", 3, Interr_Err_Ind
);
5252 case ACTIVATION_MWI
:
5253 case DEACTIVATION_MWI
:
5254 if (pty_cai
[5] == ACTIVATION_MWI
)
5256 PUT_WORD(&SS_Ind
[1], S_MWI_ACTIVATE
);
5258 else PUT_WORD(&SS_Ind
[1], S_MWI_DEACTIVATE
);
5260 if (pty_cai
[2] != 0xff)
5262 PUT_WORD(&SS_Ind
[4], 0x3600 | (word
)pty_cai
[2]);
5266 PUT_WORD(&SS_Ind
[4], 0x300E);
5269 if (plci
->cr_enquiry
)
5271 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xf, 0, "ws", 3, SS_Ind
);
5276 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5279 case CONF_ADD
: /* ERROR */
5289 PUT_WORD(&CONF_Ind
[1], S_CONF_BEGIN
);
5295 PUT_WORD(&CONF_Ind
[1], S_CONF_DROP
);
5296 plci
->ptyState
= CONNECTED
;
5301 PUT_WORD(&CONF_Ind
[1], S_CONF_ISOLATE
);
5302 plci
->ptyState
= CONNECTED
;
5307 PUT_WORD(&CONF_Ind
[1], S_CONF_REATTACH
);
5308 plci
->ptyState
= CONNECTED
;
5311 PUT_WORD(&CONF_Ind
[1], S_CONF_ADD
);
5312 plci
->relatedPTYPLCI
= NULL
;
5313 tplci
= plci
->relatedPTYPLCI
;
5314 if (tplci
) tplci
->ptyState
= CONNECTED
;
5315 plci
->ptyState
= CONNECTED
;
5319 if (pty_cai
[2] != 0xff)
5321 PUT_WORD(&CONF_Ind
[4], 0x3600 | (word
)pty_cai
[2]);
5325 PUT_WORD(&CONF_Ind
[4], 0x3303); /* Time-out: network did not respond
5326 within the required time */
5329 PUT_DWORD(&CONF_Ind
[6], 0x0);
5330 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, CONF_Ind
);
5335 /* Supplementary Service indicates success */
5337 dbug(1, dprintf("Service_Ind"));
5338 PUT_WORD(&CF_Ind
[4], 0);
5342 case THREE_PTY_BEGIN
:
5344 if (!plci
->relatedPTYPLCI
) break;
5345 tplci
= plci
->relatedPTYPLCI
;
5346 rId
= ((word
)tplci
->Id
<< 8) | tplci
->adapter
->Id
;
5347 if (tplci
->tel
) rId
|= EXT_CONTROLLER
;
5348 if (pty_cai
[5] == ECT_EXECUTE
)
5350 PUT_WORD(&SS_Ind
[1], S_ECT
);
5352 if (plci
->vswitchstate
!= 3)
5355 plci
->ptyState
= IDLE
;
5356 plci
->relatedPTYPLCI
= NULL
;
5361 dbug(1, dprintf("ECT OK"));
5362 sendf(tplci
->appl
, _FACILITY_I
, rId
, 0, "ws", 3, SS_Ind
);
5369 switch (plci
->ptyState
)
5372 plci
->ptyState
= CONNECTED
;
5373 dbug(1, dprintf("3PTY ON"));
5377 plci
->ptyState
= IDLE
;
5378 plci
->relatedPTYPLCI
= NULL
;
5380 dbug(1, dprintf("3PTY OFF"));
5383 PUT_WORD(&SS_Ind
[1], pty_cai
[5] + 3);
5384 sendf(tplci
->appl
, _FACILITY_I
, rId
, 0, "ws", 3, SS_Ind
);
5388 case CALL_DEFLECTION
:
5389 PUT_WORD(&SS_Ind
[1], pty_cai
[5]);
5390 for (i
= 0; i
< max_appl
; i
++)
5392 if (application
[i
].CDEnable
)
5394 if (application
[i
].Id
) sendf(&application
[i
], _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5395 application
[i
].CDEnable
= false;
5400 case DEACTIVATION_DIVERSION
:
5401 case ACTIVATION_DIVERSION
:
5402 if (!plci
->appl
) break;
5403 PUT_WORD(&CF_Ind
[1], pty_cai
[5] + 2);
5404 PUT_DWORD(&CF_Ind
[6], plci
->appl
->S_Handle
);
5405 sendf(plci
->appl
, _FACILITY_I
, Id
& 0x7, 0, "ws", 3, CF_Ind
);
5409 case DIVERSION_INTERROGATE_CFU
:
5410 case DIVERSION_INTERROGATE_CFB
:
5411 case DIVERSION_INTERROGATE_CFNR
:
5412 case DIVERSION_INTERROGATE_NUM
:
5414 case CCBS_DEACTIVATE
:
5415 case CCBS_INTERROGATE
:
5416 if (!plci
->appl
) break;
5419 case DIVERSION_INTERROGATE_CFU
:
5420 case DIVERSION_INTERROGATE_CFB
:
5421 case DIVERSION_INTERROGATE_CFNR
:
5422 dbug(1, dprintf("Interr_Div"));
5423 PUT_WORD(&pty_cai
[1], S_INTERROGATE_DIVERSION
);
5424 pty_cai
[3] = pty_cai
[0] - 3; /* Supplementary Service-specific parameter len */
5426 case DIVERSION_INTERROGATE_NUM
:
5427 dbug(1, dprintf("Interr_Num"));
5428 PUT_WORD(&pty_cai
[1], S_INTERROGATE_NUMBERS
);
5429 pty_cai
[3] = pty_cai
[0] - 3; /* Supplementary Service-specific parameter len */
5432 dbug(1, dprintf("CCBS Request"));
5433 PUT_WORD(&pty_cai
[1], S_CCBS_REQUEST
);
5434 pty_cai
[3] = pty_cai
[0] - 3; /* Supplementary Service-specific parameter len */
5436 case CCBS_DEACTIVATE
:
5437 dbug(1, dprintf("CCBS Deactivate"));
5438 PUT_WORD(&pty_cai
[1], S_CCBS_DEACTIVATE
);
5439 pty_cai
[3] = pty_cai
[0] - 3; /* Supplementary Service-specific parameter len */
5441 case CCBS_INTERROGATE
:
5442 dbug(1, dprintf("CCBS Interrogate"));
5443 PUT_WORD(&pty_cai
[1], S_CCBS_INTERROGATE
);
5444 pty_cai
[3] = pty_cai
[0] - 3; /* Supplementary Service-specific parameter len */
5447 PUT_WORD(&pty_cai
[4], 0); /* Supplementary Service Reason */
5448 PUT_DWORD(&pty_cai
[6], plci
->appl
->S_Handle
);
5449 sendf(plci
->appl
, _FACILITY_I
, Id
& 0x7, 0, "wS", 3, pty_cai
);
5453 case ACTIVATION_MWI
:
5454 case DEACTIVATION_MWI
:
5455 if (pty_cai
[5] == ACTIVATION_MWI
)
5457 PUT_WORD(&SS_Ind
[1], S_MWI_ACTIVATE
);
5459 else PUT_WORD(&SS_Ind
[1], S_MWI_DEACTIVATE
);
5460 if (plci
->cr_enquiry
)
5462 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xf, 0, "ws", 3, SS_Ind
);
5467 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5470 case MWI_INDICATION
:
5471 if (pty_cai
[0] >= 0x12)
5473 PUT_WORD(&pty_cai
[3], S_MWI_INDICATE
);
5474 pty_cai
[2] = pty_cai
[0] - 2; /* len Parameter */
5475 pty_cai
[5] = pty_cai
[0] - 5; /* Supplementary Service-specific parameter len */
5476 if (plci
->appl
&& (a
->Notification_Mask
[plci
->appl
->Id
- 1] & SMASK_MWI
))
5478 if (plci
->internal_command
== GET_MWI_STATE
) /* result on Message Waiting Listen */
5480 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xf, 0, "wS", 3, &pty_cai
[2]);
5484 else sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "wS", 3, &pty_cai
[2]);
5489 for (i
= 0; i
< max_appl
; i
++)
5491 if (a
->Notification_Mask
[i
]&SMASK_MWI
)
5493 sendf(&application
[i
], _FACILITY_I
, Id
& 0x7, 0, "wS", 3, &pty_cai
[2]);
5501 facility
[2] = 0; /* returncode */
5503 else facility
[2] = 0xff;
5508 facility
[2] = 0xff; /* returncode */
5511 facility
[1] = MWI_RESPONSE
; /* Function */
5512 add_p(plci
, CAI
, facility
);
5513 add_p(plci
, ESC
, multi_ssext_parms
[0]); /* remembered parameter -> only one possible */
5514 sig_req(plci
, S_SERVICE
, 0);
5517 next_internal_command(Id
, plci
);
5519 case CONF_ADD
: /* OK */
5524 case CONF_PARTYDISC
:
5530 PUT_WORD(&CONF_Ind
[1], S_CONF_BEGIN
);
5531 if (pty_cai
[0] == 6)
5534 PUT_DWORD(&CONF_Ind
[6], d
); /* PartyID */
5538 PUT_DWORD(&CONF_Ind
[6], 0x0);
5542 PUT_WORD(&CONF_Ind
[1], S_CONF_ISOLATE
);
5547 PUT_WORD(&CONF_Ind
[1], S_CONF_REATTACH
);
5552 PUT_WORD(&CONF_Ind
[1], S_CONF_DROP
);
5557 PUT_WORD(&CONF_Ind
[1], S_CONF_ADD
);
5559 PUT_DWORD(&CONF_Ind
[6], d
); /* PartyID */
5560 tplci
= plci
->relatedPTYPLCI
;
5561 if (tplci
) tplci
->ptyState
= CONNECTED
;
5563 case CONF_PARTYDISC
:
5566 PUT_WORD(&CONF_Ind
[1], S_CONF_PARTYDISC
);
5568 PUT_DWORD(&CONF_Ind
[4], d
); /* PartyID */
5571 plci
->ptyState
= CONNECTED
;
5572 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, CONF_Ind
);
5574 case CCBS_INFO_RETAIN
:
5575 case CCBS_ERASECALLLINKAGEID
:
5576 case CCBS_STOP_ALERTING
:
5581 case CCBS_INFO_RETAIN
:
5582 PUT_WORD(&CONF_Ind
[1], S_CCBS_INFO_RETAIN
);
5584 case CCBS_STOP_ALERTING
:
5585 PUT_WORD(&CONF_Ind
[1], S_CCBS_STOP_ALERTING
);
5587 case CCBS_ERASECALLLINKAGEID
:
5588 PUT_WORD(&CONF_Ind
[1], S_CCBS_ERASECALLLINKAGEID
);
5596 PUT_WORD(&CONF_Ind
[4], w
); /* PartyID */
5598 if (plci
->appl
&& (a
->Notification_Mask
[plci
->appl
->Id
- 1] & SMASK_CCBS
))
5600 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, CONF_Ind
);
5604 for (i
= 0; i
< max_appl
; i
++)
5605 if (a
->Notification_Mask
[i
] & SMASK_CCBS
)
5606 sendf(&application
[i
], _FACILITY_I
, Id
& 0x7, 0, "ws", 3, CONF_Ind
);
5615 i
= _L3_CAUSE
| cau
[2];
5616 if (cau
[2] == 0) i
= 0x3603;
5622 PUT_WORD(&SS_Ind
[1], S_HOLD
);
5623 PUT_WORD(&SS_Ind
[4], i
);
5624 if (plci
->SuppState
== HOLD_REQUEST
)
5626 plci
->SuppState
= IDLE
;
5627 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5632 if (plci
->SuppState
== HOLD_REQUEST
)
5634 plci
->SuppState
= CALL_HELD
;
5635 CodecIdCheck(a
, plci
);
5636 start_internal_command(Id
, plci
, hold_save_command
);
5640 case CALL_RETRIEVE_REJ
:
5644 i
= _L3_CAUSE
| cau
[2];
5645 if (cau
[2] == 0) i
= 0x3603;
5651 PUT_WORD(&SS_Ind
[1], S_RETRIEVE
);
5652 PUT_WORD(&SS_Ind
[4], i
);
5653 if (plci
->SuppState
== RETRIEVE_REQUEST
)
5655 plci
->SuppState
= CALL_HELD
;
5656 CodecIdCheck(a
, plci
);
5657 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5661 case CALL_RETRIEVE_ACK
:
5662 PUT_WORD(&SS_Ind
[1], S_RETRIEVE
);
5663 if (plci
->SuppState
== RETRIEVE_REQUEST
)
5665 plci
->SuppState
= IDLE
;
5666 plci
->call_dir
|= CALL_DIR_FORCE_OUTG_NL
;
5667 plci
->b_channel
= esc_chi
[esc_chi
[0]]&0x1f;
5670 mixer_set_bchannel_id_esc(plci
, plci
->b_channel
);
5671 dbug(1, dprintf("RetrChannel=0x%x", plci
->b_channel
));
5672 SetVoiceChannel(a
->AdvCodecPLCI
, esc_chi
, a
);
5673 if (plci
->B2_prot
== B2_TRANSPARENT
&& plci
->B3_prot
== B3_TRANSPARENT
)
5675 dbug(1, dprintf("Get B-ch"));
5676 start_internal_command(Id
, plci
, retrieve_restore_command
);
5679 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", 3, SS_Ind
);
5682 start_internal_command(Id
, plci
, retrieve_restore_command
);
5687 if (plci
->State
!= LISTENING
) {
5688 sig_req(plci
, HANGUP
, 0);
5692 cip
= find_cip(a
, parms
[4], parms
[6]);
5693 cip_mask
= 1L << cip
;
5694 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip
, cip_mask
));
5695 clear_c_ind_mask(plci
);
5696 if (!remove_started
&& !a
->adapter_disabled
)
5698 set_c_ind_mask_bit(plci
, MAX_APPL
);
5699 group_optimization(a
, plci
);
5700 for (i
= 0; i
< max_appl
; i
++) {
5701 if (application
[i
].Id
5702 && (a
->CIP_Mask
[i
] & 1 || a
->CIP_Mask
[i
] & cip_mask
)
5703 && CPN_filter_ok(parms
[0], a
, i
)
5704 && test_group_ind_mask_bit(plci
, i
)) {
5705 dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i
, a
->CIP_Mask
[i
]));
5706 set_c_ind_mask_bit(plci
, i
);
5707 dump_c_ind_mask(plci
);
5708 plci
->State
= INC_CON_PENDING
;
5709 plci
->call_dir
= (plci
->call_dir
& ~(CALL_DIR_OUT
| CALL_DIR_ORIGINATE
)) |
5710 CALL_DIR_IN
| CALL_DIR_ANSWER
;
5712 plci
->b_channel
= esc_chi
[esc_chi
[0]] & 0x1f;
5713 mixer_set_bchannel_id_esc(plci
, plci
->b_channel
);
5715 /* if a listen on the ext controller is done, check if hook states */
5716 /* are supported or if just a on board codec must be activated */
5717 if (a
->codec_listen
[i
] && !a
->AdvSignalPLCI
) {
5718 if (a
->profile
.Global_Options
& HANDSET
)
5719 plci
->tel
= ADV_VOICE
;
5720 else if (a
->profile
.Global_Options
& ON_BOARD_CODEC
)
5722 if (plci
->tel
) Id
|= EXT_CONTROLLER
;
5723 a
->codec_listen
[i
] = plci
;
5726 sendf(&application
[i
], _CONNECT_I
, Id
, 0,
5727 "wSSSSSSSbSSSSS", cip
, /* CIP */
5728 parms
[0], /* CalledPartyNumber */
5729 multi_CiPN_parms
[0], /* CallingPartyNumber */
5730 parms
[2], /* CalledPartySubad */
5731 parms
[3], /* CallingPartySubad */
5732 parms
[4], /* BearerCapability */
5733 parms
[5], /* LowLC */
5734 parms
[6], /* HighLC */
5735 ai_len
, /* nested struct add_i */
5736 add_i
[0], /* B channel info */
5737 add_i
[1], /* keypad facility */
5738 add_i
[2], /* user user data */
5739 add_i
[3], /* nested facility */
5740 multi_CiPN_parms
[1] /* second CiPN(SCR) */
5742 SendSSExtInd(&application
[i
],
5746 SendSetupInfo(&application
[i
],
5750 SendMultiIE(plci
, Id
, multi_pi_parms
, PI
, 0x210, true));
5753 clear_c_ind_mask_bit(plci
, MAX_APPL
);
5754 dump_c_ind_mask(plci
);
5756 if (c_ind_mask_empty(plci
)) {
5757 sig_req(plci
, HANGUP
, 0);
5761 plci
->notifiedcall
= 0;
5766 case CALL_PEND_NOTIFY
:
5767 plci
->notifiedcall
= 1;
5773 if (plci
->State
== ADVANCED_VOICE_SIG
|| plci
->State
== ADVANCED_VOICE_NOSIG
)
5775 if (plci
->internal_command
== PERM_COD_CONN_PEND
)
5777 if (plci
->State
== ADVANCED_VOICE_NOSIG
)
5779 dbug(1, dprintf("***Codec OK"));
5780 if (a
->AdvSignalPLCI
)
5782 tplci
= a
->AdvSignalPLCI
;
5783 if (tplci
->spoofed_msg
)
5785 dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci
->spoofed_msg
));
5787 tplci
->internal_command
= 0;
5788 x_Id
= ((word
)tplci
->Id
<< 8) | tplci
->adapter
->Id
| 0x80;
5789 switch (tplci
->spoofed_msg
)
5792 tplci
->command
= _CONNECT_I
| RESPONSE
;
5793 api_load_msg(&tplci
->saved_msg
, saved_parms
);
5794 add_b1(tplci
, &saved_parms
[1], 0, tplci
->B1_facilities
);
5795 if (tplci
->adapter
->Info_Mask
[tplci
->appl
->Id
- 1] & 0x200)
5797 /* early B3 connect (CIP mask bit 9) no release after a disc */
5798 add_p(tplci
, LLI
, "\x01\x01");
5800 add_s(tplci
, CONN_NR
, &saved_parms
[2]);
5801 add_s(tplci
, LLC
, &saved_parms
[4]);
5802 add_ai(tplci
, &saved_parms
[5]);
5803 tplci
->State
= INC_CON_ACCEPT
;
5804 sig_req(tplci
, CALL_RES
, 0);
5808 case AWAITING_SELECT_B
:
5809 dbug(1, dprintf("Select_B continue"));
5810 start_internal_command(x_Id
, tplci
, select_b_command
);
5813 case AWAITING_MANUF_CON
: /* Get_Plci per Manufacturer_Req to ext controller */
5816 dbug(1, dprintf("No SigID!"));
5817 sendf(tplci
->appl
, _MANUFACTURER_R
| CONFIRM
, x_Id
, tplci
->number
, "dww", _DI_MANU_ID
, _MANUFACTURER_R
, _OUT_OF_PLCI
);
5821 tplci
->command
= _MANUFACTURER_R
;
5822 api_load_msg(&tplci
->saved_msg
, saved_parms
);
5823 dir
= saved_parms
[2].info
[0];
5825 sig_req(tplci
, CALL_REQ
, 0);
5828 sig_req(tplci
, LISTEN_REQ
, 0);
5831 sendf(tplci
->appl
, _MANUFACTURER_R
| CONFIRM
, x_Id
, tplci
->number
, "dww", _DI_MANU_ID
, _MANUFACTURER_R
, 0);
5834 case (CALL_REQ
| AWAITING_MANUF_CON
):
5835 sig_req(tplci
, CALL_REQ
, 0);
5842 dbug(1, dprintf("No SigID!"));
5843 sendf(tplci
->appl
, _CONNECT_R
| CONFIRM
, tplci
->adapter
->Id
, 0, "w", _OUT_OF_PLCI
);
5847 tplci
->command
= _CONNECT_R
;
5848 api_load_msg(&tplci
->saved_msg
, saved_parms
);
5849 add_s(tplci
, CPN
, &saved_parms
[1]);
5850 add_s(tplci
, DSA
, &saved_parms
[3]);
5851 add_ai(tplci
, &saved_parms
[9]);
5852 sig_req(tplci
, CALL_REQ
, 0);
5857 tplci
->command
= C_RETRIEVE_REQ
;
5858 sig_req(tplci
, CALL_RETRIEVE
, 0);
5862 tplci
->spoofed_msg
= 0;
5863 if (tplci
->internal_command
== 0)
5864 next_internal_command(x_Id
, tplci
);
5867 next_internal_command(Id
, plci
);
5870 dbug(1, dprintf("***Codec Hook Init Req"));
5871 plci
->internal_command
= PERM_COD_HOOK
;
5872 add_p(plci
, FTY
, "\x01\x09"); /* Get Hook State*/
5873 sig_req(plci
, TEL_CTRL
, 0);
5877 else if (plci
->command
!= _MANUFACTURER_R
/* old style permanent connect */
5878 && plci
->State
!= INC_ACT_PENDING
)
5880 mixer_set_bchannel_id_esc(plci
, plci
->b_channel
);
5881 if (plci
->tel
== ADV_VOICE
&& plci
->SuppState
== IDLE
) /* with permanent codec switch on immediately */
5883 chi
[2] = plci
->b_channel
;
5884 SetVoiceChannel(a
->AdvCodecPLCI
, chi
, a
);
5886 sendf(plci
->appl
, _CONNECT_ACTIVE_I
, Id
, 0, "Sss", parms
[21], "", "");
5887 plci
->State
= INC_ACT_PENDING
;
5892 ie
= multi_fac_parms
[0]; /* inspect the facility hook indications */
5893 if (plci
->State
== ADVANCED_VOICE_SIG
&& ie
[0]) {
5894 switch (ie
[1] & 0x91) {
5895 case 0x80: /* hook off */
5897 if (plci
->internal_command
== PERM_COD_HOOK
)
5899 dbug(1, dprintf("init:hook_off"));
5900 plci
->hook_state
= ie
[1];
5901 next_internal_command(Id
, plci
);
5904 else /* ignore doubled hook indications */
5906 if (((plci
->hook_state
) & 0xf0) == 0x80)
5908 dbug(1, dprintf("ignore hook"));
5911 plci
->hook_state
= ie
[1]&0x91;
5913 /* check for incoming call pending */
5914 /* and signal '+'.Appl must decide */
5915 /* with connect_res if call must */
5916 /* accepted or not */
5917 for (i
= 0, tplci
= NULL
; i
< max_appl
; i
++) {
5918 if (a
->codec_listen
[i
]
5919 && (a
->codec_listen
[i
]->State
== INC_CON_PENDING
5920 || a
->codec_listen
[i
]->State
== INC_CON_ALERT
)) {
5921 tplci
= a
->codec_listen
[i
];
5922 tplci
->appl
= &application
[i
];
5925 /* no incoming call, do outgoing call */
5926 /* and signal '+' if outg. setup */
5927 if (!a
->AdvSignalPLCI
&& !tplci
) {
5928 if ((i
= get_plci(a
))) {
5929 a
->AdvSignalPLCI
= &a
->plci
[i
- 1];
5930 tplci
= a
->AdvSignalPLCI
;
5931 tplci
->tel
= ADV_VOICE
;
5932 PUT_WORD(&voice_cai
[5], a
->AdvSignalAppl
->MaxDataLength
);
5933 if (a
->Info_Mask
[a
->AdvSignalAppl
->Id
- 1] & 0x200) {
5934 /* early B3 connect (CIP mask bit 9) no release after a disc */
5935 add_p(tplci
, LLI
, "\x01\x01");
5937 add_p(tplci
, CAI
, voice_cai
);
5938 add_p(tplci
, OAD
, a
->TelOAD
);
5939 add_p(tplci
, OSA
, a
->TelOSA
);
5940 add_p(tplci
, SHIFT
| 6, NULL
);
5941 add_p(tplci
, SIN
, "\x02\x01\x00");
5942 add_p(tplci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
5943 sig_req(tplci
, ASSIGN
, DSIG_ID
);
5944 a
->AdvSignalPLCI
->internal_command
= HOOK_OFF_REQ
;
5945 a
->AdvSignalPLCI
->command
= 0;
5946 tplci
->appl
= a
->AdvSignalAppl
;
5947 tplci
->call_dir
= CALL_DIR_OUT
| CALL_DIR_ORIGINATE
;
5954 Id
= ((word
)tplci
->Id
<< 8) | a
->Id
;
5955 Id
|= EXT_CONTROLLER
;
5960 "ws", (word
)0, "\x01+");
5963 case 0x90: /* hook on */
5965 if (plci
->internal_command
== PERM_COD_HOOK
)
5967 dbug(1, dprintf("init:hook_on"));
5968 plci
->hook_state
= ie
[1] & 0x91;
5969 next_internal_command(Id
, plci
);
5972 else /* ignore doubled hook indications */
5974 if (((plci
->hook_state
) & 0xf0) == 0x90) break;
5975 plci
->hook_state
= ie
[1] & 0x91;
5977 /* hangup the adv. voice call and signal '-' to the appl */
5978 if (a
->AdvSignalPLCI
) {
5979 Id
= ((word
)a
->AdvSignalPLCI
->Id
<< 8) | a
->Id
;
5980 if (plci
->tel
) Id
|= EXT_CONTROLLER
;
5981 sendf(a
->AdvSignalAppl
,
5985 "ws", (word
)0, "\x01-");
5986 a
->AdvSignalPLCI
->internal_command
= HOOK_ON_REQ
;
5987 a
->AdvSignalPLCI
->command
= 0;
5988 sig_req(a
->AdvSignalPLCI
, HANGUP
, 0);
5989 send_req(a
->AdvSignalPLCI
);
5997 clear_c_ind_mask_bit(plci
, (word
)(plci
->appl
->Id
- 1));
5998 PUT_WORD(&resume_cau
[4], GOOD
);
5999 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", (word
)3, resume_cau
);
6003 clear_c_ind_mask(plci
);
6005 if (plci
->NL
.Id
&& !plci
->nl_remove_id
) {
6007 nl_req_ncci(plci
, REMOVE
, 0);
6009 if (!plci
->sig_remove_id
) {
6010 plci
->internal_command
= 0;
6011 sig_req(plci
, REMOVE
, 0);
6014 if (!plci
->channels
) {
6015 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", (word
)3, "\x05\x04\x00\x02\x00\x00");
6016 sendf(plci
->appl
, _DISCONNECT_I
, Id
, 0, "w", 0);
6024 plci
->hangup_flow_ctrl_timer
= 0;
6025 if (plci
->manufacturer
&& plci
->State
== LOCAL_CONNECT
) break;
6028 i
= _L3_CAUSE
| cau
[2];
6029 if (cau
[2] == 0) i
= 0;
6030 else if (cau
[2] == 8) i
= _L1_ERROR
;
6031 else if (cau
[2] == 9 || cau
[2] == 10) i
= _L2_ERROR
;
6032 else if (cau
[2] == 5) i
= _CAPI_GUARD_ERROR
;
6038 if (plci
->State
== INC_CON_PENDING
|| plci
->State
== INC_CON_ALERT
)
6040 for (i
= 0; i
< max_appl
; i
++)
6042 if (test_c_ind_mask_bit(plci
, i
))
6043 sendf(&application
[i
], _DISCONNECT_I
, Id
, 0, "w", 0);
6048 clear_c_ind_mask(plci
);
6052 if (plci
->State
== LISTENING
)
6054 plci
->notifiedcall
= 0;
6057 plci
->State
= INC_DIS_PENDING
;
6058 if (c_ind_mask_empty(plci
))
6061 if (plci
->NL
.Id
&& !plci
->nl_remove_id
)
6064 nl_req_ncci(plci
, REMOVE
, 0);
6066 if (!plci
->sig_remove_id
)
6068 plci
->internal_command
= 0;
6069 sig_req(plci
, REMOVE
, 0);
6076 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6077 /* result in a second HANGUP! Don't generate another */
6079 if (plci
->State
!= IDLE
&& plci
->State
!= INC_DIS_PENDING
)
6081 if (plci
->State
== RESUMING
)
6083 PUT_WORD(&resume_cau
[4], i
);
6084 sendf(plci
->appl
, _FACILITY_I
, Id
, 0, "ws", (word
)3, resume_cau
);
6086 plci
->State
= INC_DIS_PENDING
;
6087 sendf(plci
->appl
, _DISCONNECT_I
, Id
, 0, "w", i
);
6093 SendSSExtInd(NULL
, plci
, Id
, multi_ssext_parms
);
6097 VSwitchReqInd(plci
, Id
, multi_vswitch_parms
);
6100 if (plci
->relatedPTYPLCI
&&
6101 plci
->vswitchstate
== 3 &&
6102 plci
->relatedPTYPLCI
->vswitchstate
== 3 &&
6103 parms
[MAXPARMSIDS
- 1][0])
6105 add_p(plci
->relatedPTYPLCI
, SMSG
, parms
[MAXPARMSIDS
- 1]);
6106 sig_req(plci
->relatedPTYPLCI
, VSWITCH_REQ
, 0);
6107 send_req(plci
->relatedPTYPLCI
);
6109 else VSwitchReqInd(plci
, Id
, multi_vswitch_parms
);
6116 static void SendSetupInfo(APPL
*appl
, PLCI
*plci
, dword Id
, byte
**parms
, byte Info_Sent_Flag
)
6124 dbug(1, dprintf("SetupInfo"));
6126 for (i
= 0; i
< MAXPARMSIDS
; i
++) {
6133 dbug(1, dprintf("CPN "));
6134 Info_Number
= 0x0070;
6136 Info_Sent_Flag
= true;
6138 case 8: /* display */
6139 dbug(1, dprintf("display(%d)", i
));
6140 Info_Number
= 0x0028;
6142 Info_Sent_Flag
= true;
6144 case 16: /* Channel Id */
6145 dbug(1, dprintf("CHI"));
6146 Info_Number
= 0x0018;
6148 Info_Sent_Flag
= true;
6149 mixer_set_bchannel_id(plci
, Info_Element
);
6151 case 19: /* Redirected Number */
6152 dbug(1, dprintf("RDN"));
6153 Info_Number
= 0x0074;
6155 Info_Sent_Flag
= true;
6157 case 20: /* Redirected Number extended */
6158 dbug(1, dprintf("RDX"));
6159 Info_Number
= 0x0073;
6161 Info_Sent_Flag
= true;
6163 case 22: /* Redirecing Number */
6164 dbug(1, dprintf("RIN"));
6165 Info_Number
= 0x0076;
6167 Info_Sent_Flag
= true;
6175 if (i
== MAXPARMSIDS
- 2) { /* to indicate the message type "Setup" */
6176 Info_Number
= 0x8000 | 5;
6181 if (Info_Sent_Flag
&& Info_Number
) {
6182 if (plci
->adapter
->Info_Mask
[appl
->Id
- 1] & Info_Mask
) {
6183 sendf(appl
, _INFO_I
, Id
, 0, "wS", Info_Number
, Info_Element
);
6190 static void SendInfo(PLCI
*plci
, dword Id
, byte
**parms
, byte iesent
)
6199 static byte charges
[5] = {4, 0, 0, 0, 0};
6200 static byte cause
[] = {0x02, 0x80, 0x00};
6203 dbug(1, dprintf("InfoParse "));
6208 && plci
->Sig
.Ind
!= NCR_FACILITY
6211 dbug(1, dprintf("NoParse "));
6215 for (i
= 0; i
< MAXPARMSIDS
; i
++) {
6222 dbug(1, dprintf("CPN "));
6223 Info_Number
= 0x0070;
6226 case 7: /* ESC_CAU */
6227 dbug(1, dprintf("cau(0x%x)", ie
[2]));
6228 Info_Number
= 0x0008;
6231 Info_Element
= NULL
;
6233 case 8: /* display */
6234 dbug(1, dprintf("display(%d)", i
));
6235 Info_Number
= 0x0028;
6238 case 9: /* Date display */
6239 dbug(1, dprintf("date(%d)", i
));
6240 Info_Number
= 0x0029;
6243 case 10: /* charges */
6244 for (j
= 0; j
< 4; j
++) charges
[1 + j
] = 0;
6245 for (j
= 0; j
< ie
[0] && !(ie
[1 + j
] & 0x80); j
++);
6246 for (k
= 1, j
++; j
< ie
[0] && k
<= 4; j
++, k
++) charges
[k
] = ie
[1 + j
];
6247 Info_Number
= 0x4000;
6249 Info_Element
= charges
;
6251 case 11: /* user user info */
6252 dbug(1, dprintf("uui"));
6253 Info_Number
= 0x007E;
6256 case 12: /* congestion receiver ready */
6257 dbug(1, dprintf("clRDY"));
6258 Info_Number
= 0x00B0;
6262 case 13: /* congestion receiver not ready */
6263 dbug(1, dprintf("clNRDY"));
6264 Info_Number
= 0x00BF;
6268 case 15: /* Keypad Facility */
6269 dbug(1, dprintf("KEY"));
6270 Info_Number
= 0x002C;
6273 case 16: /* Channel Id */
6274 dbug(1, dprintf("CHI"));
6275 Info_Number
= 0x0018;
6277 mixer_set_bchannel_id(plci
, Info_Element
);
6279 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6280 dbug(1, dprintf("q9cau(0x%x)", ie
[2]));
6281 if (!cause
[2] || cause
[2] < 0x80) break; /* eg. layer 1 error */
6282 Info_Number
= 0x0008;
6284 if (cause
[2] != ie
[2]) Info_Element
= cause
;
6286 case 19: /* Redirected Number */
6287 dbug(1, dprintf("RDN"));
6288 Info_Number
= 0x0074;
6291 case 22: /* Redirecing Number */
6292 dbug(1, dprintf("RIN"));
6293 Info_Number
= 0x0076;
6296 case 23: /* Notification Indicator */
6297 dbug(1, dprintf("NI"));
6298 Info_Number
= (word
)NI
;
6301 case 26: /* Call State */
6302 dbug(1, dprintf("CST"));
6303 Info_Number
= (word
)CST
;
6304 Info_Mask
= 0x01; /* do with cause i.e. for now */
6306 case MAXPARMSIDS
- 2: /* Escape Message Type, must be the last indication */
6307 dbug(1, dprintf("ESC/MT[0x%x]", ie
[3]));
6308 Info_Number
= 0x8000 | ie
[3];
6309 if (iesent
) Info_Mask
= 0xffff;
6310 else Info_Mask
= 0x10;
6321 if (plci
->Sig
.Ind
== NCR_FACILITY
) /* check controller broadcast */
6323 for (j
= 0; j
< max_appl
; j
++)
6325 appl
= &application
[j
];
6328 && plci
->adapter
->Info_Mask
[appl
->Id
- 1] & Info_Mask
)
6330 dbug(1, dprintf("NCR_Ind"));
6332 sendf(&application
[j
], _INFO_I
, Id
& 0x0f, 0, "wS", Info_Number
, Info_Element
);
6336 else if (!plci
->appl
)
6337 { /* overlap receiving broadcast */
6338 if (Info_Number
== CPN
6339 || Info_Number
== KEY
6340 || Info_Number
== NI
6341 || Info_Number
== DSP
6342 || Info_Number
== UUI
)
6344 for (j
= 0; j
< max_appl
; j
++)
6346 if (test_c_ind_mask_bit(plci
, j
))
6348 dbug(1, dprintf("Ovl_Ind"));
6350 sendf(&application
[j
], _INFO_I
, Id
, 0, "wS", Info_Number
, Info_Element
);
6354 } /* all other signalling states */
6355 else if (Info_Number
6356 && plci
->adapter
->Info_Mask
[plci
->appl
->Id
- 1] & Info_Mask
)
6358 dbug(1, dprintf("Std_Ind"));
6360 sendf(plci
->appl
, _INFO_I
, Id
, 0, "wS", Info_Number
, Info_Element
);
6366 static byte
SendMultiIE(PLCI
*plci
, dword Id
, byte
**parms
, byte ie_type
,
6367 dword info_mask
, byte setupParse
)
6381 && plci
->Sig
.Ind
!= NCR_FACILITY
6385 dbug(1, dprintf("NoM-IEParse "));
6388 dbug(1, dprintf("M-IEParse "));
6390 for (i
= 0; i
< MAX_MULTI_IE
; i
++)
6397 dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci
->Sig
.Ind
, ie_type
));
6398 Info_Number
= (word
)ie_type
;
6399 Info_Mask
= (word
)info_mask
;
6402 if (plci
->Sig
.Ind
== NCR_FACILITY
) /* check controller broadcast */
6404 for (j
= 0; j
< max_appl
; j
++)
6406 appl
= &application
[j
];
6409 && plci
->adapter
->Info_Mask
[appl
->Id
- 1] & Info_Mask
)
6412 dbug(1, dprintf("Mlt_NCR_Ind"));
6413 sendf(&application
[j
], _INFO_I
, Id
& 0x0f, 0, "wS", Info_Number
, Info_Element
);
6417 else if (!plci
->appl
&& Info_Number
)
6418 { /* overlap receiving broadcast */
6419 for (j
= 0; j
< max_appl
; j
++)
6421 if (test_c_ind_mask_bit(plci
, j
))
6424 dbug(1, dprintf("Mlt_Ovl_Ind"));
6425 sendf(&application
[j
] , _INFO_I
, Id
, 0, "wS", Info_Number
, Info_Element
);
6428 } /* all other signalling states */
6429 else if (Info_Number
6430 && plci
->adapter
->Info_Mask
[plci
->appl
->Id
- 1] & Info_Mask
)
6433 dbug(1, dprintf("Mlt_Std_Ind"));
6434 sendf(plci
->appl
, _INFO_I
, Id
, 0, "wS", Info_Number
, Info_Element
);
6440 static void SendSSExtInd(APPL
*appl
, PLCI
*plci
, dword Id
, byte
**parms
)
6443 /* Format of multi_ssext_parms[i][]:
6446 2 byte SSEXT_REQ/SSEXT_IND
6454 && plci
->Sig
.Ind
!= NCR_FACILITY
6456 for (i
= 0; i
< MAX_MULTI_IE
; i
++)
6458 if (parms
[i
][0] < 6) continue;
6459 if (parms
[i
][2] == SSEXT_REQ
) continue;
6463 parms
[i
][0] = 0; /* kill it */
6464 sendf(appl
, _MANUFACTURER_I
,
6472 else if (plci
->appl
)
6474 parms
[i
][0] = 0; /* kill it */
6475 sendf(plci
->appl
, _MANUFACTURER_I
,
6486 static void nl_ind(PLCI
*plci
)
6491 DIVA_CAPI_ADAPTER
*a
;
6497 byte len
, ncci_state
;
6500 word fax_feature_bits
;
6501 byte fax_send_edata_ack
;
6502 static byte v120_header_buffer
[2 + 3];
6503 static word fax_info
[] = {
6504 0, /* T30_SUCCESS */
6505 _FAX_NO_CONNECTION
, /* T30_ERR_NO_DIS_RECEIVED */
6506 _FAX_PROTOCOL_ERROR
, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6507 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_RESPONSE */
6508 _FAX_PROTOCOL_ERROR
, /* T30_ERR_TOO_MANY_REPEATS */
6509 _FAX_PROTOCOL_ERROR
, /* T30_ERR_UNEXPECTED_MESSAGE */
6510 _FAX_REMOTE_ABORT
, /* T30_ERR_UNEXPECTED_DCN */
6511 _FAX_LOCAL_ABORT
, /* T30_ERR_DTC_UNSUPPORTED */
6512 _FAX_TRAINING_ERROR
, /* T30_ERR_ALL_RATES_FAILED */
6513 _FAX_TRAINING_ERROR
, /* T30_ERR_TOO_MANY_TRAINS */
6514 _FAX_PARAMETER_ERROR
, /* T30_ERR_RECEIVE_CORRUPTED */
6515 _FAX_REMOTE_ABORT
, /* T30_ERR_UNEXPECTED_DISC */
6516 _FAX_LOCAL_ABORT
, /* T30_ERR_APPLICATION_DISC */
6517 _FAX_REMOTE_REJECT
, /* T30_ERR_INCOMPATIBLE_DIS */
6518 _FAX_LOCAL_ABORT
, /* T30_ERR_INCOMPATIBLE_DCS */
6519 _FAX_PROTOCOL_ERROR
, /* T30_ERR_TIMEOUT_NO_COMMAND */
6520 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_COMMAND */
6521 _FAX_PROTOCOL_ERROR
, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6522 _FAX_PROTOCOL_ERROR
, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6523 _FAX_NO_CONNECTION
, /* T30_ERR_NOT_IDENTIFIED */
6524 _FAX_PROTOCOL_ERROR
, /* T30_ERR_SUPERVISORY_TIMEOUT */
6525 _FAX_PARAMETER_ERROR
, /* T30_ERR_TOO_LONG_SCAN_LINE */
6526 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6527 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6528 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6529 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6530 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6531 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6532 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6533 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_CFR */
6534 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6535 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6536 _FAX_PROTOCOL_ERROR
, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6537 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6538 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6539 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6540 _FAX_PROTOCOL_ERROR
, /* T30_ERR_INVALID_COMMAND_FRAME */
6541 _FAX_PARAMETER_ERROR
, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6542 _FAX_PARAMETER_ERROR
, /* T30_ERR_INVALID_PAGE_CODING */
6543 _FAX_REMOTE_REJECT
, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6544 _FAX_LOCAL_ABORT
, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6545 _FAX_PROTOCOL_ERROR
, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6546 _FAX_PROTOCOL_ERROR
, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6547 _FAX_PROTOCOL_ERROR
, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6548 _FAX_PROTOCOL_ERROR
, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6549 _FAX_LOCAL_ABORT
, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6550 _FAX_LOCAL_ABORT
/* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6553 byte dtmf_code_buffer
[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE
+ 1];
6556 static word rtp_info
[] = {
6557 GOOD
, /* RTP_SUCCESS */
6558 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6561 static dword udata_forwarding_table
[0x100 / sizeof(dword
)] =
6563 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6564 0x00000000, 0x00000000, 0x00000000, 0x00000000
6567 ch
= plci
->NL
.IndCh
;
6569 ncci
= a
->ch_ncci
[ch
];
6570 Id
= (((dword
)(ncci
? ncci
: ch
)) << 16) | (((word
) plci
->Id
) << 8) | a
->Id
;
6571 if (plci
->tel
) Id
|= EXT_CONTROLLER
;
6572 APPLptr
= plci
->appl
;
6573 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",
6574 plci
->NL
.Id
, Id
, plci
->Id
, plci
->tel
, plci
->State
, ch
, plci
->channels
, plci
->NL
.Ind
& 0x0f));
6576 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6578 if (plci
->nl_remove_id
)
6580 plci
->NL
.RNR
= 2; /* discard */
6581 dbug(1, dprintf("NL discard while remove pending"));
6584 if ((plci
->NL
.Ind
& 0x0f) == N_CONNECT
)
6586 if (plci
->State
== INC_DIS_PENDING
6587 || plci
->State
== OUTG_DIS_PENDING
6588 || plci
->State
== IDLE
)
6590 plci
->NL
.RNR
= 2; /* discard */
6591 dbug(1, dprintf("discard n_connect"));
6594 if (plci
->State
< INC_ACT_PENDING
)
6596 plci
->NL
.RNR
= 1; /* flow control */
6597 channel_x_off(plci
, ch
, N_XON_CONNECT_IND
);
6602 if (!APPLptr
) /* no application or invalid data */
6603 { /* while reloading the DSP */
6604 dbug(1, dprintf("discard1"));
6609 if (((plci
->NL
.Ind
& 0x0f) == N_UDATA
)
6610 && (((plci
->B2_prot
!= B2_SDLC
) && ((plci
->B1_resource
== 17) || (plci
->B1_resource
== 18)))
6611 || (plci
->B2_prot
== 7)
6612 || (plci
->B3_prot
== 7)))
6614 plci
->ncpi_buffer
[0] = 0;
6616 ncpi_state
= plci
->ncpi_state
;
6617 if (plci
->NL
.complete
== 1)
6619 byte
*data
= &plci
->NL
.RBuffer
->P
[0];
6621 if ((plci
->NL
.RBuffer
->length
>= 12)
6622 && ((*data
== DSP_UDATA_INDICATION_DCD_ON
)
6623 || (*data
== DSP_UDATA_INDICATION_CTS_ON
)))
6625 word conn_opt
, ncpi_opt
= 0x00;
6626 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6628 if (*data
== DSP_UDATA_INDICATION_DCD_ON
)
6629 plci
->ncpi_state
|= NCPI_MDM_DCD_ON_RECEIVED
;
6630 if (*data
== DSP_UDATA_INDICATION_CTS_ON
)
6631 plci
->ncpi_state
|= NCPI_MDM_CTS_ON_RECEIVED
;
6633 data
++; /* indication code */
6634 data
+= 2; /* timestamp */
6635 if ((*data
== DSP_CONNECTED_NORM_V18
) || (*data
== DSP_CONNECTED_NORM_VOWN
))
6636 ncpi_state
&= ~(NCPI_MDM_DCD_ON_RECEIVED
| NCPI_MDM_CTS_ON_RECEIVED
);
6637 data
++; /* connected norm */
6638 conn_opt
= GET_WORD(data
);
6639 data
+= 2; /* connected options */
6641 PUT_WORD(&(plci
->ncpi_buffer
[1]), (word
)(GET_DWORD(data
) & 0x0000FFFF));
6643 if (conn_opt
& DSP_CONNECTED_OPTION_MASK_V42
)
6645 ncpi_opt
|= MDM_NCPI_ECM_V42
;
6647 else if (conn_opt
& DSP_CONNECTED_OPTION_MASK_MNP
)
6649 ncpi_opt
|= MDM_NCPI_ECM_MNP
;
6653 ncpi_opt
|= MDM_NCPI_TRANSPARENT
;
6655 if (conn_opt
& DSP_CONNECTED_OPTION_MASK_COMPRESSION
)
6657 ncpi_opt
|= MDM_NCPI_COMPRESSED
;
6659 PUT_WORD(&(plci
->ncpi_buffer
[3]), ncpi_opt
);
6660 plci
->ncpi_buffer
[0] = 4;
6662 plci
->ncpi_state
|= NCPI_VALID_CONNECT_B3_IND
| NCPI_VALID_CONNECT_B3_ACT
| NCPI_VALID_DISC_B3_IND
;
6665 if (plci
->B3_prot
== 7)
6667 if (((a
->ncci_state
[ncci
] == INC_ACT_PENDING
) || (a
->ncci_state
[ncci
] == OUTG_CON_PENDING
))
6668 && (plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
6669 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
6671 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
6672 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "S", plci
->ncpi_buffer
);
6673 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
6677 if (!((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1])
6678 & ((1L << PRIVATE_V18
) | (1L << PRIVATE_VOWN
)))
6679 || !(ncpi_state
& NCPI_MDM_DCD_ON_RECEIVED
)
6680 || !(ncpi_state
& NCPI_MDM_CTS_ON_RECEIVED
))
6688 if (plci
->NL
.complete
== 2)
6690 if (((plci
->NL
.Ind
& 0x0f) == N_UDATA
)
6691 && !(udata_forwarding_table
[plci
->RData
[0].P
[0] >> 5] & (1L << (plci
->RData
[0].P
[0] & 0x1f))))
6693 switch (plci
->RData
[0].P
[0])
6696 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE
:
6697 if (plci
->dtmf_rec_active
& DTMF_LISTEN_ACTIVE_FLAG
)
6698 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0, "ws", SELECTOR_DTMF
, "\x01X");
6700 case DTMF_UDATA_INDICATION_ANSWER_TONE
:
6701 if (plci
->dtmf_rec_active
& DTMF_LISTEN_ACTIVE_FLAG
)
6702 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0, "ws", SELECTOR_DTMF
, "\x01Y");
6704 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED
:
6705 dtmf_indication(Id
, plci
, plci
->RData
[0].P
, plci
->RData
[0].PLength
);
6707 case DTMF_UDATA_INDICATION_DIGITS_SENT
:
6708 dtmf_confirmation(Id
, plci
);
6712 case UDATA_INDICATION_MIXER_TAP_DATA
:
6713 capidtmf_recv_process_block(&(plci
->capidtmf_state
), plci
->RData
[0].P
+ 1, (word
)(plci
->RData
[0].PLength
- 1));
6714 i
= capidtmf_indication(&(plci
->capidtmf_state
), dtmf_code_buffer
+ 1);
6717 dtmf_code_buffer
[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED
;
6718 dtmf_indication(Id
, plci
, dtmf_code_buffer
, (word
)(i
+ 1));
6723 case UDATA_INDICATION_MIXER_COEFS_SET
:
6724 mixer_indication_coefs_set(Id
, plci
);
6726 case UDATA_INDICATION_XCONNECT_FROM
:
6727 mixer_indication_xconnect_from(Id
, plci
, plci
->RData
[0].P
, plci
->RData
[0].PLength
);
6729 case UDATA_INDICATION_XCONNECT_TO
:
6730 mixer_indication_xconnect_to(Id
, plci
, plci
->RData
[0].P
, plci
->RData
[0].PLength
);
6734 case LEC_UDATA_INDICATION_DISABLE_DETECT
:
6735 ec_indication(Id
, plci
, plci
->RData
[0].P
, plci
->RData
[0].PLength
);
6746 if ((plci
->RData
[0].PLength
!= 0)
6747 && ((plci
->B2_prot
== B2_V120_ASYNC
)
6748 || (plci
->B2_prot
== B2_V120_ASYNC_V42BIS
)
6749 || (plci
->B2_prot
== B2_V120_BIT_TRANSPARENT
)))
6752 sendf(plci
->appl
, _DATA_B3_I
, Id
, 0,
6755 (plci
->NL
.RNum
< 2) ? 0 : plci
->RData
[1].PLength
,
6763 sendf(plci
->appl
, _DATA_B3_I
, Id
, 0,
6766 plci
->RData
[0].PLength
,
6775 fax_feature_bits
= 0;
6776 if ((plci
->NL
.Ind
& 0x0f) == N_CONNECT
||
6777 (plci
->NL
.Ind
& 0x0f) == N_CONNECT_ACK
||
6778 (plci
->NL
.Ind
& 0x0f) == N_DISC
||
6779 (plci
->NL
.Ind
& 0x0f) == N_EDATA
||
6780 (plci
->NL
.Ind
& 0x0f) == N_DISC_ACK
)
6783 plci
->ncpi_buffer
[0] = 0;
6784 switch (plci
->B3_prot
) {
6787 break; /* no network control protocol info - jfr */
6790 for (i
= 0; i
< plci
->NL
.RLength
; i
++) plci
->ncpi_buffer
[4 + i
] = plci
->NL
.RBuffer
->P
[i
];
6791 plci
->ncpi_buffer
[0] = (byte
)(i
+ 3);
6792 plci
->ncpi_buffer
[1] = (byte
)(plci
->NL
.Ind
& N_D_BIT
? 1 : 0);
6793 plci
->ncpi_buffer
[2] = 0;
6794 plci
->ncpi_buffer
[3] = 0;
6796 case 4: /*T.30 - FAX*/
6797 case 5: /*T.30 - FAX*/
6798 if (plci
->NL
.RLength
>= sizeof(T30_INFO
))
6800 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
));
6802 PUT_WORD(&(plci
->ncpi_buffer
[1]), ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->rate_div_2400
* 2400);
6803 fax_feature_bits
= GET_WORD(&((T30_INFO
*)plci
->NL
.RBuffer
->P
)->feature_bits_low
);
6804 i
= (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->resolution
& T30_RESOLUTION_R8_0770_OR_200
) ? 0x0001 : 0x0000;
6805 if (plci
->B3_prot
== 5)
6807 if (!(fax_feature_bits
& T30_FEATURE_BIT_ECM
))
6808 i
|= 0x8000; /* This is not an ECM connection */
6809 if (fax_feature_bits
& T30_FEATURE_BIT_T6_CODING
)
6810 i
|= 0x4000; /* This is a connection with MMR compression */
6811 if (fax_feature_bits
& T30_FEATURE_BIT_2D_CODING
)
6812 i
|= 0x2000; /* This is a connection with MR compression */
6813 if (fax_feature_bits
& T30_FEATURE_BIT_MORE_DOCUMENTS
)
6814 i
|= 0x0004; /* More documents */
6815 if (fax_feature_bits
& T30_FEATURE_BIT_POLLING
)
6816 i
|= 0x0002; /* Fax-polling indication */
6818 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits
, i
));
6819 PUT_WORD(&(plci
->ncpi_buffer
[3]), i
);
6820 PUT_WORD(&(plci
->ncpi_buffer
[5]), ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->data_format
);
6821 plci
->ncpi_buffer
[7] = ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->pages_low
;
6822 plci
->ncpi_buffer
[8] = ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->pages_high
;
6823 plci
->ncpi_buffer
[len
] = 0;
6824 if (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->station_id_len
)
6826 plci
->ncpi_buffer
[len
] = 20;
6827 for (i
= 0; i
< T30_MAX_STATION_ID_LENGTH
; i
++)
6828 plci
->ncpi_buffer
[++len
] = ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->station_id
[i
];
6830 if (((plci
->NL
.Ind
& 0x0f) == N_DISC
) || ((plci
->NL
.Ind
& 0x0f) == N_DISC_ACK
))
6832 if (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
< ARRAY_SIZE(fax_info
))
6833 info
= fax_info
[((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
];
6835 info
= _FAX_PROTOCOL_ERROR
;
6838 if ((plci
->requested_options_conn
| plci
->requested_options
| a
->requested_options_table
[plci
->appl
->Id
- 1])
6839 & ((1L << PRIVATE_FAX_SUB_SEP_PWD
) | (1L << PRIVATE_FAX_NONSTANDARD
)))
6841 i
= offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->head_line_len
;
6842 while (i
< plci
->NL
.RBuffer
->length
)
6843 plci
->ncpi_buffer
[++len
] = plci
->NL
.RBuffer
->P
[i
++];
6846 plci
->ncpi_buffer
[0] = len
;
6847 fax_feature_bits
= GET_WORD(&((T30_INFO
*)plci
->NL
.RBuffer
->P
)->feature_bits_low
);
6848 PUT_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->feature_bits_low
, fax_feature_bits
);
6850 plci
->ncpi_state
|= NCPI_VALID_CONNECT_B3_IND
;
6851 if (((plci
->NL
.Ind
& 0x0f) == N_CONNECT_ACK
)
6852 || (((plci
->NL
.Ind
& 0x0f) == N_CONNECT
)
6853 && (fax_feature_bits
& T30_FEATURE_BIT_POLLING
))
6854 || (((plci
->NL
.Ind
& 0x0f) == N_EDATA
)
6855 && ((((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
== EDATA_T30_TRAIN_OK
)
6856 || (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
== EDATA_T30_DIS
)
6857 || (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
== EDATA_T30_DTC
))))
6859 plci
->ncpi_state
|= NCPI_VALID_CONNECT_B3_ACT
;
6861 if (((plci
->NL
.Ind
& 0x0f) == N_DISC
)
6862 || ((plci
->NL
.Ind
& 0x0f) == N_DISC_ACK
)
6863 || (((plci
->NL
.Ind
& 0x0f) == N_EDATA
)
6864 && (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
== EDATA_T30_EOP_CAPI
)))
6866 plci
->ncpi_state
|= NCPI_VALID_CONNECT_B3_ACT
| NCPI_VALID_DISC_B3_IND
;
6872 if (((plci
->NL
.Ind
& 0x0f) == N_DISC
) || ((plci
->NL
.Ind
& 0x0f) == N_DISC_ACK
))
6874 if (plci
->NL
.RLength
!= 0)
6876 info
= rtp_info
[plci
->NL
.RBuffer
->P
[0]];
6877 plci
->ncpi_buffer
[0] = plci
->NL
.RLength
- 1;
6878 for (i
= 1; i
< plci
->NL
.RLength
; i
++)
6879 plci
->ncpi_buffer
[i
] = plci
->NL
.RBuffer
->P
[i
];
6887 switch (plci
->NL
.Ind
& 0x0f) {
6889 if ((plci
->B3_prot
== 4) || (plci
->B3_prot
== 5))
6891 dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci
, a
->ncci_state
[ncci
],
6892 ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
));
6893 fax_send_edata_ack
= (((T30_INFO
*)(plci
->fax_connect_info_buffer
))->operating_mode
== T30_OPERATING_MODE_CAPI_NEG
);
6895 if ((plci
->nsf_control_bits
& T30_NSF_CONTROL_BIT_ENABLE_NSF
)
6896 && (plci
->nsf_control_bits
& (T30_NSF_CONTROL_BIT_NEGOTIATE_IND
| T30_NSF_CONTROL_BIT_NEGOTIATE_RESP
))
6897 && (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
== EDATA_T30_DIS
)
6898 && (a
->ncci_state
[ncci
] == OUTG_CON_PENDING
)
6899 && (plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
6900 && !(plci
->ncpi_state
& NCPI_NEGOTIATE_B3_SENT
))
6902 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->code
= ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
;
6903 sendf(plci
->appl
, _MANUFACTURER_I
, Id
, 0, "dwbS", _DI_MANU_ID
, _DI_NEGOTIATE_B3
,
6904 (byte
)(plci
->ncpi_buffer
[0] + 1), plci
->ncpi_buffer
);
6905 plci
->ncpi_state
|= NCPI_NEGOTIATE_B3_SENT
;
6906 if (plci
->nsf_control_bits
& T30_NSF_CONTROL_BIT_NEGOTIATE_RESP
)
6907 fax_send_edata_ack
= false;
6910 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_PAPER_FORMATS
)
6912 switch (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
)
6915 if ((a
->ncci_state
[ncci
] == OUTG_CON_PENDING
)
6916 && !(GET_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->control_bits_low
) & T30_CONTROL_BIT_REQUEST_POLLING
)
6917 && (plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
6918 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
6920 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
6921 if (plci
->B3_prot
== 4)
6922 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
6924 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "S", plci
->ncpi_buffer
);
6925 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
6929 case EDATA_T30_TRAIN_OK
:
6930 if ((a
->ncci_state
[ncci
] == INC_ACT_PENDING
)
6931 && (plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
6932 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
6934 if (plci
->B3_prot
== 4)
6935 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
6937 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "S", plci
->ncpi_buffer
);
6938 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
6942 case EDATA_T30_EOP_CAPI
:
6943 if (a
->ncci_state
[ncci
] == CONNECTED
)
6945 sendf(plci
->appl
, _DISCONNECT_B3_I
, Id
, 0, "wS", GOOD
, plci
->ncpi_buffer
);
6946 a
->ncci_state
[ncci
] = INC_DIS_PENDING
;
6947 plci
->ncpi_state
= 0;
6948 fax_send_edata_ack
= false;
6955 switch (((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
)
6957 case EDATA_T30_TRAIN_OK
:
6958 if ((a
->ncci_state
[ncci
] == INC_ACT_PENDING
)
6959 && (plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
6960 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
6962 if (plci
->B3_prot
== 4)
6963 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
6965 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "S", plci
->ncpi_buffer
);
6966 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
6971 if (fax_send_edata_ack
)
6973 ((T30_INFO
*)(plci
->fax_connect_info_buffer
))->code
= ((T30_INFO
*)plci
->NL
.RBuffer
->P
)->code
;
6974 plci
->fax_edata_ack_length
= 1;
6975 start_internal_command(Id
, plci
, fax_edata_ack_command
);
6980 dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci
, a
->ncci_state
[ncci
]));
6984 if (!a
->ch_ncci
[ch
])
6986 ncci
= get_ncci(plci
, ch
, 0);
6987 Id
= (Id
& 0xffff) | (((dword
) ncci
) << 16);
6989 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6990 ch
, a
->ncci_state
[ncci
], a
->ncci_plci
[ncci
], plci
->Id
, plci
->State
));
6992 msg
= _CONNECT_B3_I
;
6993 if (a
->ncci_state
[ncci
] == IDLE
)
6995 else if (plci
->B3_prot
== 1)
6996 msg
= _CONNECT_B3_T90_ACTIVE_I
;
6998 a
->ncci_state
[ncci
] = INC_CON_PENDING
;
6999 if (plci
->B3_prot
== 4)
7000 sendf(plci
->appl
, msg
, Id
, 0, "s", "");
7002 sendf(plci
->appl
, msg
, Id
, 0, "S", plci
->ncpi_buffer
);
7005 dbug(1, dprintf("N_connect_Ack"));
7006 if (plci
->internal_command_queue
[0]
7007 && ((plci
->adjust_b_state
== ADJUST_B_CONNECT_2
)
7008 || (plci
->adjust_b_state
== ADJUST_B_CONNECT_3
)
7009 || (plci
->adjust_b_state
== ADJUST_B_CONNECT_4
)))
7011 (*(plci
->internal_command_queue
[0]))(Id
, plci
, 0);
7012 if (!plci
->internal_command
)
7013 next_internal_command(Id
, plci
);
7016 msg
= _CONNECT_B3_ACTIVE_I
;
7017 if (plci
->B3_prot
== 1)
7019 if (a
->ncci_state
[ncci
] != OUTG_CON_PENDING
)
7020 msg
= _CONNECT_B3_T90_ACTIVE_I
;
7021 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
7022 sendf(plci
->appl
, msg
, Id
, 0, "S", plci
->ncpi_buffer
);
7024 else if ((plci
->B3_prot
== 4) || (plci
->B3_prot
== 5) || (plci
->B3_prot
== 7))
7026 if ((a
->ncci_state
[ncci
] == OUTG_CON_PENDING
)
7027 && (plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
7028 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
7030 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
7031 if (plci
->B3_prot
== 4)
7032 sendf(plci
->appl
, msg
, Id
, 0, "s", "");
7034 sendf(plci
->appl
, msg
, Id
, 0, "S", plci
->ncpi_buffer
);
7035 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
7040 a
->ncci_state
[ncci
] = INC_ACT_PENDING
;
7041 sendf(plci
->appl
, msg
, Id
, 0, "S", plci
->ncpi_buffer
);
7043 if (plci
->adjust_b_restore
)
7045 plci
->adjust_b_restore
= false;
7046 start_internal_command(Id
, plci
, adjust_b_restore
);
7051 if (plci
->internal_command_queue
[0]
7052 && ((plci
->internal_command
== FAX_DISCONNECT_COMMAND_1
)
7053 || (plci
->internal_command
== FAX_DISCONNECT_COMMAND_2
)
7054 || (plci
->internal_command
== FAX_DISCONNECT_COMMAND_3
)))
7056 (*(plci
->internal_command_queue
[0]))(Id
, plci
, 0);
7057 if (!plci
->internal_command
)
7058 next_internal_command(Id
, plci
);
7060 ncci_state
= a
->ncci_state
[ncci
];
7061 ncci_remove(plci
, ncci
, false);
7063 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7064 /* channel, so we cannot store the state in ncci_state! The */
7065 /* information which channel we received a N_DISC is thus */
7066 /* stored in the inc_dis_ncci_table buffer. */
7067 for (i
= 0; plci
->inc_dis_ncci_table
[i
]; i
++);
7068 plci
->inc_dis_ncci_table
[i
] = (byte
) ncci
;
7070 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7072 && (plci
->B1_resource
== 16)
7073 && (plci
->State
<= CONNECTED
))
7076 i
= ((T30_INFO
*)plci
->fax_connect_info_buffer
)->rate_div_2400
* 2400;
7077 PUT_WORD(&plci
->ncpi_buffer
[1], i
);
7078 PUT_WORD(&plci
->ncpi_buffer
[3], 0);
7079 i
= ((T30_INFO
*)plci
->fax_connect_info_buffer
)->data_format
;
7080 PUT_WORD(&plci
->ncpi_buffer
[5], i
);
7081 PUT_WORD(&plci
->ncpi_buffer
[7], 0);
7082 plci
->ncpi_buffer
[len
] = 0;
7083 plci
->ncpi_buffer
[0] = len
;
7084 if (plci
->B3_prot
== 4)
7085 sendf(plci
->appl
, _CONNECT_B3_I
, Id
, 0, "s", "");
7089 if ((plci
->requested_options_conn
| plci
->requested_options
| a
->requested_options_table
[plci
->appl
->Id
- 1])
7090 & ((1L << PRIVATE_FAX_SUB_SEP_PWD
) | (1L << PRIVATE_FAX_NONSTANDARD
)))
7092 plci
->ncpi_buffer
[++len
] = 0;
7093 plci
->ncpi_buffer
[++len
] = 0;
7094 plci
->ncpi_buffer
[++len
] = 0;
7095 plci
->ncpi_buffer
[0] = len
;
7098 sendf(plci
->appl
, _CONNECT_B3_I
, Id
, 0, "S", plci
->ncpi_buffer
);
7100 sendf(plci
->appl
, _DISCONNECT_B3_I
, Id
, 0, "wS", info
, plci
->ncpi_buffer
);
7101 plci
->ncpi_state
= 0;
7102 sig_req(plci
, HANGUP
, 0);
7104 plci
->State
= OUTG_DIS_PENDING
;
7107 else if ((a
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_PAPER_FORMATS
)
7108 && ((plci
->B3_prot
== 4) || (plci
->B3_prot
== 5))
7109 && ((ncci_state
== INC_DIS_PENDING
) || (ncci_state
== IDLE
)))
7111 if (ncci_state
== IDLE
)
7115 if ((plci
->State
== IDLE
|| plci
->State
== SUSPENDING
) && !plci
->channels
) {
7116 if (plci
->State
== SUSPENDING
) {
7121 "ws", (word
)3, "\x03\x04\x00\x00");
7122 sendf(plci
->appl
, _DISCONNECT_I
, Id
& 0xffffL
, 0, "w", 0);
7129 else if (plci
->channels
)
7131 sendf(plci
->appl
, _DISCONNECT_B3_I
, Id
, 0, "wS", info
, plci
->ncpi_buffer
);
7132 plci
->ncpi_state
= 0;
7133 if ((ncci_state
== OUTG_REJ_PENDING
)
7134 && ((plci
->B3_prot
!= B3_T90NL
) && (plci
->B3_prot
!= B3_ISO8208
) && (plci
->B3_prot
!= B3_X25_DCE
)))
7136 sig_req(plci
, HANGUP
, 0);
7138 plci
->State
= OUTG_DIS_PENDING
;
7143 a
->ncci_state
[ncci
] = INC_RES_PENDING
;
7144 sendf(plci
->appl
, _RESET_B3_I
, Id
, 0, "S", plci
->ncpi_buffer
);
7147 a
->ncci_state
[ncci
] = CONNECTED
;
7148 sendf(plci
->appl
, _RESET_B3_I
, Id
, 0, "S", plci
->ncpi_buffer
);
7152 if (!(udata_forwarding_table
[plci
->NL
.RBuffer
->P
[0] >> 5] & (1L << (plci
->NL
.RBuffer
->P
[0] & 0x1f))))
7154 plci
->RData
[0].P
= plci
->internal_ind_buffer
+ (-((int)(long)(plci
->internal_ind_buffer
)) & 3);
7155 plci
->RData
[0].PLength
= INTERNAL_IND_BUFFER_SIZE
;
7156 plci
->NL
.R
= plci
->RData
;
7162 if (((a
->ncci_state
[ncci
] != CONNECTED
) && (plci
->B2_prot
== 1)) /* transparent */
7163 || (a
->ncci_state
[ncci
] == IDLE
)
7164 || (a
->ncci_state
[ncci
] == INC_DIS_PENDING
))
7169 if ((a
->ncci_state
[ncci
] != CONNECTED
)
7170 && (a
->ncci_state
[ncci
] != OUTG_DIS_PENDING
)
7171 && (a
->ncci_state
[ncci
] != OUTG_REJ_PENDING
))
7173 dbug(1, dprintf("flow control"));
7174 plci
->NL
.RNR
= 1; /* flow control */
7175 channel_x_off(plci
, ch
, 0);
7179 NCCIcode
= ncci
| (((word
)a
->Id
) << 8);
7181 /* count all buffers within the Application pool */
7182 /* belonging to the same NCCI. If this is below the */
7183 /* number of buffers available per NCCI we accept */
7184 /* this packet, otherwise we reject it */
7187 for (i
= 0; i
< APPLptr
->MaxBuffer
; i
++) {
7188 if (NCCIcode
== APPLptr
->DataNCCI
[i
]) count
++;
7189 if (!APPLptr
->DataNCCI
[i
] && Num
== 0xffff) Num
= i
;
7192 if (count
>= APPLptr
->MaxNCCIData
|| Num
== 0xffff)
7194 dbug(3, dprintf("Flow-Control"));
7196 if (++(APPLptr
->NCCIDataFlowCtrlTimer
) >=
7197 (word
)((a
->manufacturer_features
& MANUFACTURER_FEATURE_OOB_CHANNEL
) ? 40 : 2000))
7200 dbug(3, dprintf("DiscardData"));
7202 channel_x_off(plci
, ch
, 0);
7208 APPLptr
->NCCIDataFlowCtrlTimer
= 0;
7211 plci
->RData
[0].P
= ReceiveBufferGet(APPLptr
, Num
);
7212 if (!plci
->RData
[0].P
) {
7214 channel_x_off(plci
, ch
, 0);
7218 APPLptr
->DataNCCI
[Num
] = NCCIcode
;
7219 APPLptr
->DataFlags
[Num
] = (plci
->Id
<< 8) | (plci
->NL
.Ind
>> 4);
7220 dbug(3, dprintf("Buffer(%d), Max = %d", Num
, APPLptr
->MaxBuffer
));
7223 plci
->RFlags
= plci
->NL
.Ind
>> 4;
7224 plci
->RData
[0].PLength
= APPLptr
->MaxDataLength
;
7225 plci
->NL
.R
= plci
->RData
;
7226 if ((plci
->NL
.RLength
!= 0)
7227 && ((plci
->B2_prot
== B2_V120_ASYNC
)
7228 || (plci
->B2_prot
== B2_V120_ASYNC_V42BIS
)
7229 || (plci
->B2_prot
== B2_V120_BIT_TRANSPARENT
)))
7231 plci
->RData
[1].P
= plci
->RData
[0].P
;
7232 plci
->RData
[1].PLength
= plci
->RData
[0].PLength
;
7233 plci
->RData
[0].P
= v120_header_buffer
+ (-((unsigned long)v120_header_buffer
) & 3);
7234 if ((plci
->NL
.RBuffer
->P
[0] & V120_HEADER_EXTEND_BIT
) || (plci
->NL
.RLength
== 1))
7235 plci
->RData
[0].PLength
= 1;
7237 plci
->RData
[0].PLength
= 2;
7238 if (plci
->NL
.RBuffer
->P
[0] & V120_HEADER_BREAK_BIT
)
7239 plci
->RFlags
|= 0x0010;
7240 if (plci
->NL
.RBuffer
->P
[0] & (V120_HEADER_C1_BIT
| V120_HEADER_C2_BIT
))
7241 plci
->RFlags
|= 0x8000;
7246 if ((plci
->NL
.Ind
& 0x0f) == N_UDATA
)
7247 plci
->RFlags
|= 0x0010;
7249 else if ((plci
->B3_prot
== B3_RTP
) && ((plci
->NL
.Ind
& 0x0f) == N_BDATA
))
7250 plci
->RFlags
|= 0x0001;
7264 /*------------------------------------------------------------------*/
7265 /* find a free PLCI */
7266 /*------------------------------------------------------------------*/
7268 static word
get_plci(DIVA_CAPI_ADAPTER
*a
)
7274 for (i
= 0; i
< a
->max_plci
&& a
->plci
[i
].Id
; i
++);
7275 if (i
== a
->max_plci
) {
7276 dbug(1, dprintf("get_plci: out of PLCIs"));
7280 plci
->Id
= (byte
)(i
+ 1);
7288 plci
->relatedPTYPLCI
= NULL
;
7290 plci
->SuppState
= IDLE
;
7293 plci
->B1_resource
= 0;
7298 plci
->m_command
= 0;
7299 init_internal_command_queue(plci
);
7301 plci
->req_in_start
= 0;
7304 plci
->msg_in_write_pos
= MSG_IN_QUEUE_SIZE
;
7305 plci
->msg_in_read_pos
= MSG_IN_QUEUE_SIZE
;
7306 plci
->msg_in_wrap_pos
= MSG_IN_QUEUE_SIZE
;
7308 plci
->data_sent
= false;
7309 plci
->send_disc
= 0;
7310 plci
->sig_global_req
= 0;
7311 plci
->sig_remove_id
= 0;
7312 plci
->nl_global_req
= 0;
7313 plci
->nl_remove_id
= 0;
7315 plci
->manufacturer
= false;
7316 plci
->call_dir
= CALL_DIR_OUT
| CALL_DIR_ORIGINATE
;
7317 plci
->spoofed_msg
= 0;
7319 plci
->cr_enquiry
= false;
7320 plci
->hangup_flow_ctrl_timer
= 0;
7322 plci
->ncci_ring_list
= 0;
7323 for (j
= 0; j
< MAX_CHANNELS_PER_PLCI
; j
++) plci
->inc_dis_ncci_table
[j
] = 0;
7324 clear_c_ind_mask(plci
);
7325 set_group_ind_mask(plci
);
7326 plci
->fax_connect_info_length
= 0;
7327 plci
->nsf_control_bits
= 0;
7328 plci
->ncpi_state
= 0x00;
7329 plci
->ncpi_buffer
[0] = 0;
7331 plci
->requested_options_conn
= 0;
7332 plci
->requested_options
= 0;
7333 plci
->notifiedcall
= 0;
7334 plci
->vswitchstate
= 0;
7336 plci
->vsprotdialect
= 0;
7337 init_b1_config(plci
);
7338 dbug(1, dprintf("get_plci(%x)", plci
->Id
));
7342 /*------------------------------------------------------------------*/
7343 /* put a parameter in the parameter buffer */
7344 /*------------------------------------------------------------------*/
7346 static void add_p(PLCI
*plci
, byte code
, byte
*p
)
7351 if (p
) p_length
= p
[0];
7352 add_ie(plci
, code
, p
, p_length
);
7355 /*------------------------------------------------------------------*/
7356 /* put a structure in the parameter buffer */
7357 /*------------------------------------------------------------------*/
7358 static void add_s(PLCI
*plci
, byte code
, API_PARSE
*p
)
7360 if (p
) add_ie(plci
, code
, p
->info
, (word
)p
->length
);
7363 /*------------------------------------------------------------------*/
7364 /* put multiple structures in the parameter buffer */
7365 /*------------------------------------------------------------------*/
7366 static void add_ss(PLCI
*plci
, byte code
, API_PARSE
*p
)
7371 dbug(1, dprintf("add_ss(%x,len=%d)", code
, p
->length
));
7372 for (i
= 2; i
< (byte
)p
->length
; i
+= p
->info
[i
] + 2) {
7373 dbug(1, dprintf("add_ss_ie(%x,len=%d)", p
->info
[i
- 1], p
->info
[i
]));
7374 add_ie(plci
, p
->info
[i
- 1], (byte
*)&(p
->info
[i
]), (word
)p
->info
[i
]);
7379 /*------------------------------------------------------------------*/
7380 /* return the channel number sent by the application in a esc_chi */
7381 /*------------------------------------------------------------------*/
7382 static byte
getChannel(API_PARSE
*p
)
7387 for (i
= 2; i
< (byte
)p
->length
; i
+= p
->info
[i
] + 2) {
7388 if (p
->info
[i
] == 2) {
7389 if (p
->info
[i
- 1] == ESC
&& p
->info
[i
+ 1] == CHI
) return (p
->info
[i
+ 2]);
7397 /*------------------------------------------------------------------*/
7398 /* put an information element in the parameter buffer */
7399 /*------------------------------------------------------------------*/
7401 static void add_ie(PLCI
*plci
, byte code
, byte
*p
, word p_length
)
7405 if (!(code
& 0x80) && !p_length
) return;
7407 if (plci
->req_in
== plci
->req_in_start
) {
7413 plci
->RBuffer
[plci
->req_in
++] = code
;
7416 plci
->RBuffer
[plci
->req_in
++] = (byte
)p_length
;
7417 for (i
= 0; i
< p_length
; i
++) plci
->RBuffer
[plci
->req_in
++] = p
[1 + i
];
7420 plci
->RBuffer
[plci
->req_in
++] = 0;
7423 /*------------------------------------------------------------------*/
7424 /* put a unstructured data into the buffer */
7425 /*------------------------------------------------------------------*/
7427 static void add_d(PLCI
*plci
, word length
, byte
*p
)
7431 if (plci
->req_in
== plci
->req_in_start
) {
7437 for (i
= 0; i
< length
; i
++) plci
->RBuffer
[plci
->req_in
++] = p
[i
];
7440 /*------------------------------------------------------------------*/
7441 /* put parameters from the Additional Info parameter in the */
7442 /* parameter buffer */
7443 /*------------------------------------------------------------------*/
7445 static void add_ai(PLCI
*plci
, API_PARSE
*ai
)
7448 API_PARSE ai_parms
[5];
7450 for (i
= 0; i
< 5; i
++) ai_parms
[i
].length
= 0;
7454 if (api_parse(&ai
->info
[1], (word
)ai
->length
, "ssss", ai_parms
))
7457 add_s(plci
, KEY
, &ai_parms
[1]);
7458 add_s(plci
, UUI
, &ai_parms
[2]);
7459 add_ss(plci
, FTY
, &ai_parms
[3]);
7462 /*------------------------------------------------------------------*/
7463 /* put parameter for b1 protocol in the parameter buffer */
7464 /*------------------------------------------------------------------*/
7466 static word
add_b1(PLCI
*plci
, API_PARSE
*bp
, word b_channel_info
,
7469 API_PARSE bp_parms
[8];
7470 API_PARSE mdm_cfg
[9];
7471 API_PARSE global_config
[2];
7473 byte resource
[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7474 byte voice_cai
[] = "\x06\x14\x00\x00\x00\x00\x08";
7477 API_PARSE mdm_cfg_v18
[4];
7482 for (i
= 0; i
< 8; i
++) bp_parms
[i
].length
= 0;
7483 for (i
= 0; i
< 2; i
++) global_config
[i
].length
= 0;
7485 dbug(1, dprintf("add_b1"));
7486 api_save_msg(bp
, "s", &plci
->B_protocol
);
7488 if (b_channel_info
== 2) {
7489 plci
->B1_resource
= 0;
7490 adjust_b1_facilities(plci
, plci
->B1_resource
, b1_facilities
);
7491 add_p(plci
, CAI
, "\x01\x00");
7492 dbug(1, dprintf("Cai=1,0 (no resource)"));
7496 if (plci
->tel
== CODEC_PERMANENT
) return 0;
7497 else if (plci
->tel
== CODEC
) {
7498 plci
->B1_resource
= 1;
7499 adjust_b1_facilities(plci
, plci
->B1_resource
, b1_facilities
);
7500 add_p(plci
, CAI
, "\x01\x01");
7501 dbug(1, dprintf("Cai=1,1 (Codec)"));
7504 else if (plci
->tel
== ADV_VOICE
) {
7505 plci
->B1_resource
= add_b1_facilities(plci
, 9, (word
)(b1_facilities
| B1_FACILITY_VOICE
));
7506 adjust_b1_facilities(plci
, plci
->B1_resource
, (word
)(b1_facilities
| B1_FACILITY_VOICE
));
7507 voice_cai
[1] = plci
->B1_resource
;
7508 PUT_WORD(&voice_cai
[5], plci
->appl
->MaxDataLength
);
7509 add_p(plci
, CAI
, voice_cai
);
7510 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai
[1]));
7513 plci
->call_dir
&= ~(CALL_DIR_ORIGINATE
| CALL_DIR_ANSWER
);
7514 if (plci
->call_dir
& CALL_DIR_OUT
)
7515 plci
->call_dir
|= CALL_DIR_ORIGINATE
;
7516 else if (plci
->call_dir
& CALL_DIR_IN
)
7517 plci
->call_dir
|= CALL_DIR_ANSWER
;
7520 plci
->B1_resource
= 0x5;
7521 adjust_b1_facilities(plci
, plci
->B1_resource
, b1_facilities
);
7522 add_p(plci
, CAI
, "\x01\x05");
7526 dbug(1, dprintf("b_prot_len=%d", (word
)bp
->length
));
7527 if (bp
->length
> 256) return _WRONG_MESSAGE_FORMAT
;
7528 if (api_parse(&bp
->info
[1], (word
)bp
->length
, "wwwsssb", bp_parms
))
7530 bp_parms
[6].length
= 0;
7531 if (api_parse(&bp
->info
[1], (word
)bp
->length
, "wwwsss", bp_parms
))
7533 dbug(1, dprintf("b-form.!"));
7534 return _WRONG_MESSAGE_FORMAT
;
7537 else if (api_parse(&bp
->info
[1], (word
)bp
->length
, "wwwssss", bp_parms
))
7539 dbug(1, dprintf("b-form.!"));
7540 return _WRONG_MESSAGE_FORMAT
;
7543 if (bp_parms
[6].length
)
7545 if (api_parse(&bp_parms
[6].info
[1], (word
)bp_parms
[6].length
, "w", global_config
))
7547 return _WRONG_MESSAGE_FORMAT
;
7549 switch (GET_WORD(global_config
[0].info
))
7552 plci
->call_dir
= (plci
->call_dir
& ~CALL_DIR_ANSWER
) | CALL_DIR_ORIGINATE
;
7555 plci
->call_dir
= (plci
->call_dir
& ~CALL_DIR_ORIGINATE
) | CALL_DIR_ANSWER
;
7559 dbug(1, dprintf("call_dir=%04x", plci
->call_dir
));
7562 if ((GET_WORD(bp_parms
[0].info
) == B1_RTP
)
7563 && (plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_RTP
)))
7565 plci
->B1_resource
= add_b1_facilities(plci
, 31, (word
)(b1_facilities
& ~B1_FACILITY_VOICE
));
7566 adjust_b1_facilities(plci
, plci
->B1_resource
, (word
)(b1_facilities
& ~B1_FACILITY_VOICE
));
7567 cai
[1] = plci
->B1_resource
;
7571 PUT_WORD(&cai
[5], plci
->appl
->MaxDataLength
);
7572 for (i
= 0; i
< bp_parms
[3].length
; i
++)
7573 cai
[7 + i
] = bp_parms
[3].info
[1 + i
];
7574 cai
[0] = 6 + bp_parms
[3].length
;
7575 add_p(plci
, CAI
, cai
);
7580 if ((GET_WORD(bp_parms
[0].info
) == B1_PIAFS
)
7581 && (plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_PIAFS
)))
7583 plci
->B1_resource
= add_b1_facilities(plci
, 35/* PIAFS HARDWARE FACILITY */, (word
)(b1_facilities
& ~B1_FACILITY_VOICE
));
7584 adjust_b1_facilities(plci
, plci
->B1_resource
, (word
)(b1_facilities
& ~B1_FACILITY_VOICE
));
7585 cai
[1] = plci
->B1_resource
;
7589 PUT_WORD(&cai
[5], plci
->appl
->MaxDataLength
);
7591 add_p(plci
, CAI
, cai
);
7596 if ((GET_WORD(bp_parms
[0].info
) >= 32)
7597 || (!((1L << GET_WORD(bp_parms
[0].info
)) & plci
->adapter
->profile
.B1_Protocols
)
7598 && ((GET_WORD(bp_parms
[0].info
) != 3)
7599 || !((1L << B1_HDLC
) & plci
->adapter
->profile
.B1_Protocols
)
7600 || ((bp_parms
[3].length
!= 0) && (GET_WORD(&bp_parms
[3].info
[1]) != 0) && (GET_WORD(&bp_parms
[3].info
[1]) != 56000)))))
7602 return _B1_NOT_SUPPORTED
;
7604 plci
->B1_resource
= add_b1_facilities(plci
, resource
[GET_WORD(bp_parms
[0].info
)],
7605 (word
)(b1_facilities
& ~B1_FACILITY_VOICE
));
7606 adjust_b1_facilities(plci
, plci
->B1_resource
, (word
)(b1_facilities
& ~B1_FACILITY_VOICE
));
7608 cai
[1] = plci
->B1_resource
;
7609 for (i
= 2; i
< sizeof(cai
); i
++) cai
[i
] = 0;
7611 if ((GET_WORD(bp_parms
[0].info
) == B1_MODEM_ALL_NEGOTIATE
)
7612 || (GET_WORD(bp_parms
[0].info
) == B1_MODEM_ASYNC
)
7613 || (GET_WORD(bp_parms
[0].info
) == B1_MODEM_SYNC_HDLC
))
7615 for (i
= 0; i
< 7; i
++) mdm_cfg
[i
].length
= 0;
7617 if (bp_parms
[3].length
)
7619 if (api_parse(&bp_parms
[3].info
[1], (word
)bp_parms
[3].length
, "wwwwww", mdm_cfg
))
7621 return (_WRONG_MESSAGE_FORMAT
);
7624 cai
[2] = 0; /* Bit rate for adaptation */
7626 dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg
[0].info
)));
7628 PUT_WORD(&cai
[13], 0); /* Min Tx speed */
7629 PUT_WORD(&cai
[15], GET_WORD(mdm_cfg
[0].info
)); /* Max Tx speed */
7630 PUT_WORD(&cai
[17], 0); /* Min Rx speed */
7631 PUT_WORD(&cai
[19], GET_WORD(mdm_cfg
[0].info
)); /* Max Rx speed */
7633 cai
[3] = 0; /* Async framing parameters */
7634 switch (GET_WORD(mdm_cfg
[2].info
))
7636 case 1: /* odd parity */
7637 cai
[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE
| DSP_CAI_ASYNC_PARITY_ODD
);
7638 dbug(1, dprintf("MDM: odd parity"));
7641 case 2: /* even parity */
7642 cai
[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE
| DSP_CAI_ASYNC_PARITY_EVEN
);
7643 dbug(1, dprintf("MDM: even parity"));
7647 dbug(1, dprintf("MDM: no parity"));
7651 switch (GET_WORD(mdm_cfg
[3].info
))
7653 case 1: /* 2 stop bits */
7654 cai
[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS
;
7655 dbug(1, dprintf("MDM: 2 stop bits"));
7659 dbug(1, dprintf("MDM: 1 stop bit"));
7663 switch (GET_WORD(mdm_cfg
[1].info
))
7666 cai
[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5
;
7667 dbug(1, dprintf("MDM: 5 bits"));
7671 cai
[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6
;
7672 dbug(1, dprintf("MDM: 6 bits"));
7676 cai
[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7
;
7677 dbug(1, dprintf("MDM: 7 bits"));
7681 dbug(1, dprintf("MDM: 8 bits"));
7685 cai
[7] = 0; /* Line taking options */
7686 cai
[8] = 0; /* Modulation negotiation options */
7687 cai
[9] = 0; /* Modulation options */
7689 if (((plci
->call_dir
& CALL_DIR_ORIGINATE
) != 0) ^ ((plci
->call_dir
& CALL_DIR_OUT
) != 0))
7691 cai
[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION
;
7692 dbug(1, dprintf("MDM: Reverse direction"));
7695 if (GET_WORD(mdm_cfg
[4].info
) & MDM_CAPI_DISABLE_RETRAIN
)
7697 cai
[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN
;
7698 dbug(1, dprintf("MDM: Disable retrain"));
7701 if (GET_WORD(mdm_cfg
[4].info
) & MDM_CAPI_DISABLE_RING_TONE
)
7703 cai
[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE
| DSP_CAI_MODEM_DISABLE_ANSWER_TONE
;
7704 dbug(1, dprintf("MDM: Disable ring tone"));
7707 if (GET_WORD(mdm_cfg
[4].info
) & MDM_CAPI_GUARD_1800
)
7709 cai
[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ
;
7710 dbug(1, dprintf("MDM: 1800 guard tone"));
7712 else if (GET_WORD(mdm_cfg
[4].info
) & MDM_CAPI_GUARD_550
)
7714 cai
[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ
;
7715 dbug(1, dprintf("MDM: 550 guard tone"));
7718 if ((GET_WORD(mdm_cfg
[5].info
) & 0x00ff) == MDM_CAPI_NEG_V100
)
7720 cai
[8] |= DSP_CAI_MODEM_NEGOTIATE_V100
;
7721 dbug(1, dprintf("MDM: V100"));
7723 else if ((GET_WORD(mdm_cfg
[5].info
) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS
)
7725 cai
[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS
;
7726 dbug(1, dprintf("MDM: IN CLASS"));
7728 else if ((GET_WORD(mdm_cfg
[5].info
) & 0x00ff) == MDM_CAPI_NEG_DISABLED
)
7730 cai
[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED
;
7731 dbug(1, dprintf("MDM: DISABLED"));
7735 if ((plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_V18
))
7736 && (GET_WORD(mdm_cfg
[5].info
) & 0x8000)) /* Private V.18 enable */
7738 plci
->requested_options
|= 1L << PRIVATE_V18
;
7740 if (GET_WORD(mdm_cfg
[5].info
) & 0x4000) /* Private VOWN enable */
7741 plci
->requested_options
|= 1L << PRIVATE_VOWN
;
7743 if ((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1])
7744 & ((1L << PRIVATE_V18
) | (1L << PRIVATE_VOWN
)))
7746 if (!api_parse(&bp_parms
[3].info
[1], (word
)bp_parms
[3].length
, "wwwwwws", mdm_cfg
))
7749 if (mdm_cfg
[6].length
>= 4)
7751 d
= GET_DWORD(&mdm_cfg
[6].info
[1]);
7752 cai
[7] |= (byte
) d
; /* line taking options */
7753 cai
[9] |= (byte
)(d
>> 8); /* modulation options */
7754 cai
[++i
] = (byte
)(d
>> 16); /* vown modulation options */
7755 cai
[++i
] = (byte
)(d
>> 24);
7756 if (mdm_cfg
[6].length
>= 8)
7758 d
= GET_DWORD(&mdm_cfg
[6].info
[5]);
7759 cai
[10] |= (byte
) d
; /* disabled modulations mask */
7760 cai
[11] |= (byte
)(d
>> 8);
7761 if (mdm_cfg
[6].length
>= 12)
7763 d
= GET_DWORD(&mdm_cfg
[6].info
[9]);
7764 cai
[12] = (byte
) d
; /* enabled modulations mask */
7765 cai
[++i
] = (byte
)(d
>> 8); /* vown enabled modulations */
7766 cai
[++i
] = (byte
)(d
>> 16);
7767 cai
[++i
] = (byte
)(d
>> 24);
7769 if (mdm_cfg
[6].length
>= 14)
7771 w
= GET_WORD(&mdm_cfg
[6].info
[13]);
7773 PUT_WORD(&cai
[13], w
); /* min tx speed */
7774 if (mdm_cfg
[6].length
>= 16)
7776 w
= GET_WORD(&mdm_cfg
[6].info
[15]);
7778 PUT_WORD(&cai
[15], w
); /* max tx speed */
7779 if (mdm_cfg
[6].length
>= 18)
7781 w
= GET_WORD(&mdm_cfg
[6].info
[17]);
7783 PUT_WORD(&cai
[17], w
); /* min rx speed */
7784 if (mdm_cfg
[6].length
>= 20)
7786 w
= GET_WORD(&mdm_cfg
[6].info
[19]);
7788 PUT_WORD(&cai
[19], w
); /* max rx speed */
7789 if (mdm_cfg
[6].length
>= 22)
7791 w
= GET_WORD(&mdm_cfg
[6].info
[21]);
7792 cai
[23] = (byte
)(-((short) w
)); /* transmit level */
7793 if (mdm_cfg
[6].length
>= 24)
7795 w
= GET_WORD(&mdm_cfg
[6].info
[23]);
7796 cai
[22] |= (byte
) w
; /* info options mask */
7797 cai
[21] |= (byte
)(w
>> 8); /* disabled symbol rates */
7809 if (!api_parse(&bp_parms
[3].info
[1], (word
)bp_parms
[3].length
, "wwwwwwss", mdm_cfg
))
7811 if (!api_parse(&mdm_cfg
[7].info
[1], (word
)mdm_cfg
[7].length
, "sss", mdm_cfg_v18
))
7813 for (n
= 0; n
< 3; n
++)
7815 cai
[i
] = (byte
)(mdm_cfg_v18
[n
].length
);
7816 for (j
= 1; j
< ((word
)(cai
[i
] + 1)); j
++)
7817 cai
[i
+ j
] = mdm_cfg_v18
[n
].info
[j
];
7822 cai
[0] = (byte
)(i
- 1);
7828 if (GET_WORD(bp_parms
[0].info
) == 2 || /* V.110 async */
7829 GET_WORD(bp_parms
[0].info
) == 3) /* V.110 sync */
7831 if (bp_parms
[3].length
) {
7832 dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms
[3].info
[1])));
7833 switch (GET_WORD(&bp_parms
[3].info
[1])) { /* Rate */
7836 if (GET_WORD(bp_parms
[0].info
) == 3) { /* V.110 sync 56k */
7837 dbug(1, dprintf("56k sync HSCX"));
7842 else if (GET_WORD(bp_parms
[0].info
) == 2) {
7843 dbug(1, dprintf("56k async DSP"));
7847 case 50: cai
[2] = 1; break;
7848 case 75: cai
[2] = 1; break;
7849 case 110: cai
[2] = 1; break;
7850 case 150: cai
[2] = 1; break;
7851 case 200: cai
[2] = 1; break;
7852 case 300: cai
[2] = 1; break;
7853 case 600: cai
[2] = 1; break;
7854 case 1200: cai
[2] = 2; break;
7855 case 2400: cai
[2] = 3; break;
7856 case 4800: cai
[2] = 4; break;
7857 case 7200: cai
[2] = 10; break;
7858 case 9600: cai
[2] = 5; break;
7859 case 12000: cai
[2] = 13; break;
7860 case 24000: cai
[2] = 0; break;
7861 case 14400: cai
[2] = 11; break;
7862 case 19200: cai
[2] = 6; break;
7863 case 28800: cai
[2] = 12; break;
7864 case 38400: cai
[2] = 7; break;
7865 case 48000: cai
[2] = 8; break;
7866 case 76: cai
[2] = 15; break; /* 75/1200 */
7867 case 1201: cai
[2] = 14; break; /* 1200/75 */
7868 case 56001: cai
[2] = 9; break; /* V.110 56000 */
7871 return _B1_PARM_NOT_SUPPORTED
;
7874 if (cai
[1] == 13) /* v.110 async */
7876 if (bp_parms
[3].length
>= 8)
7878 switch (GET_WORD(&bp_parms
[3].info
[3]))
7881 cai
[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5
;
7884 cai
[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6
;
7887 cai
[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7
;
7890 switch (GET_WORD(&bp_parms
[3].info
[5]))
7892 case 1: /* odd parity */
7893 cai
[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE
| DSP_CAI_ASYNC_PARITY_ODD
);
7895 case 2: /* even parity */
7896 cai
[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE
| DSP_CAI_ASYNC_PARITY_EVEN
);
7899 switch (GET_WORD(&bp_parms
[3].info
[7]))
7901 case 1: /* 2 stop bits */
7902 cai
[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS
;
7908 else if (cai
[1] == 8 || GET_WORD(bp_parms
[0].info
) == 3) {
7909 dbug(1, dprintf("V.110 default 56k sync"));
7915 dbug(1, dprintf("V.110 default 9600 async"));
7919 PUT_WORD(&cai
[5], plci
->appl
->MaxDataLength
);
7920 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]));
7921 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7923 add_p(plci
, CAI
, cai
);
7927 /*------------------------------------------------------------------*/
7928 /* put parameter for b2 and B3 protocol in the parameter buffer */
7929 /*------------------------------------------------------------------*/
7931 static word
add_b23(PLCI
*plci
, API_PARSE
*bp
)
7933 word i
, fax_control_bits
;
7935 byte SAPI
= 0x40; /* default SAPI 16 for x.31 */
7936 API_PARSE bp_parms
[8];
7937 API_PARSE
*b1_config
;
7938 API_PARSE
*b2_config
;
7939 API_PARSE b2_config_parms
[8];
7940 API_PARSE
*b3_config
;
7941 API_PARSE b3_config_parms
[6];
7942 API_PARSE global_config
[2];
7944 static byte llc
[3] = {2,0,0};
7945 static byte dlc
[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7946 static byte nlc
[256];
7947 static byte lli
[12] = {1,1};
7949 const byte llc2_out
[] = {1,2,4,6,2,0,0,0, X75_V42BIS
,V120_L2
,V120_V42BIS
,V120_L2
,6};
7950 const byte llc2_in
[] = {1,3,4,6,3,0,0,0, X75_V42BIS
,V120_L2
,V120_V42BIS
,V120_L2
,6};
7952 const byte llc3
[] = {4,3,2,2,6,6,0};
7953 const byte header
[] = {0,2,3,3,0,0,0};
7955 for (i
= 0; i
< 8; i
++) bp_parms
[i
].length
= 0;
7956 for (i
= 0; i
< 6; i
++) b2_config_parms
[i
].length
= 0;
7957 for (i
= 0; i
< 5; i
++) b3_config_parms
[i
].length
= 0;
7961 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL
)
7963 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_OOB_CHANNEL
)
7966 if ((lli
[1] & 0x02) && (diva_xdi_extended_features
& DIVA_CAPI_USE_CMA
)) {
7968 if (plci
->rx_dma_descriptor
<= 0) {
7969 plci
->rx_dma_descriptor
= diva_get_dma_descriptor(plci
, &plci
->rx_dma_magic
);
7970 if (plci
->rx_dma_descriptor
>= 0)
7971 plci
->rx_dma_descriptor
++;
7973 if (plci
->rx_dma_descriptor
> 0) {
7976 lli
[2] = (byte
)(plci
->rx_dma_descriptor
- 1);
7977 lli
[3] = (byte
)plci
->rx_dma_magic
;
7978 lli
[4] = (byte
)(plci
->rx_dma_magic
>> 8);
7979 lli
[5] = (byte
)(plci
->rx_dma_magic
>> 16);
7980 lli
[6] = (byte
)(plci
->rx_dma_magic
>> 24);
7984 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci
->adapter
)) {
7988 dbug(1, dprintf("add_b23"));
7989 api_save_msg(bp
, "s", &plci
->B_protocol
);
7991 if (!bp
->length
&& plci
->tel
)
7993 plci
->adv_nl
= true;
7994 dbug(1, dprintf("Default adv.Nl"));
7995 add_p(plci
, LLI
, lli
);
7996 plci
->B2_prot
= 1 /*XPARENT*/;
7997 plci
->B3_prot
= 0 /*XPARENT*/;
8000 add_p(plci
, LLC
, llc
);
8002 PUT_WORD(&dlc
[1], plci
->appl
->MaxDataLength
);
8003 add_p(plci
, DLC
, dlc
);
8007 if (!bp
->length
) /*default*/
8009 dbug(1, dprintf("ret default"));
8010 add_p(plci
, LLI
, lli
);
8011 plci
->B2_prot
= 0 /*X.75 */;
8012 plci
->B3_prot
= 0 /*XPARENT*/;
8015 add_p(plci
, LLC
, llc
);
8017 PUT_WORD(&dlc
[1], plci
->appl
->MaxDataLength
);
8018 add_p(plci
, DLC
, dlc
);
8021 dbug(1, dprintf("b_prot_len=%d", (word
)bp
->length
));
8022 if ((word
)bp
->length
> 256) return _WRONG_MESSAGE_FORMAT
;
8024 if (api_parse(&bp
->info
[1], (word
)bp
->length
, "wwwsssb", bp_parms
))
8026 bp_parms
[6].length
= 0;
8027 if (api_parse(&bp
->info
[1], (word
)bp
->length
, "wwwsss", bp_parms
))
8029 dbug(1, dprintf("b-form.!"));
8030 return _WRONG_MESSAGE_FORMAT
;
8033 else if (api_parse(&bp
->info
[1], (word
)bp
->length
, "wwwssss", bp_parms
))
8035 dbug(1, dprintf("b-form.!"));
8036 return _WRONG_MESSAGE_FORMAT
;
8039 if (plci
->tel
== ADV_VOICE
) /* transparent B on advanced voice */
8041 if (GET_WORD(bp_parms
[1].info
) != 1
8042 || GET_WORD(bp_parms
[2].info
) != 0) return _B2_NOT_SUPPORTED
;
8043 plci
->adv_nl
= true;
8045 else if (plci
->tel
) return _B2_NOT_SUPPORTED
;
8048 if ((GET_WORD(bp_parms
[1].info
) == B2_RTP
)
8049 && (GET_WORD(bp_parms
[2].info
) == B3_RTP
)
8050 && (plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_RTP
)))
8052 add_p(plci
, LLI
, lli
);
8053 plci
->B2_prot
= (byte
) GET_WORD(bp_parms
[1].info
);
8054 plci
->B3_prot
= (byte
) GET_WORD(bp_parms
[2].info
);
8055 llc
[1] = (plci
->call_dir
& (CALL_DIR_ORIGINATE
| CALL_DIR_FORCE_OUTG_NL
)) ? 14 : 13;
8057 add_p(plci
, LLC
, llc
);
8059 PUT_WORD(&dlc
[1], plci
->appl
->MaxDataLength
);
8060 dlc
[3] = 3; /* Addr A */
8061 dlc
[4] = 1; /* Addr B */
8062 dlc
[5] = 7; /* modulo mode */
8063 dlc
[6] = 7; /* window size */
8064 dlc
[7] = 0; /* XID len Lo */
8065 dlc
[8] = 0; /* XID len Hi */
8066 for (i
= 0; i
< bp_parms
[4].length
; i
++)
8067 dlc
[9 + i
] = bp_parms
[4].info
[1 + i
];
8068 dlc
[0] = (byte
)(8 + bp_parms
[4].length
);
8069 add_p(plci
, DLC
, dlc
);
8070 for (i
= 0; i
< bp_parms
[5].length
; i
++)
8071 nlc
[1 + i
] = bp_parms
[5].info
[1 + i
];
8072 nlc
[0] = (byte
)(bp_parms
[5].length
);
8073 add_p(plci
, NLC
, nlc
);
8079 if ((GET_WORD(bp_parms
[1].info
) >= 32)
8080 || (!((1L << GET_WORD(bp_parms
[1].info
)) & plci
->adapter
->profile
.B2_Protocols
)
8081 && ((GET_WORD(bp_parms
[1].info
) != B2_PIAFS
)
8082 || !(plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_PIAFS
)))))
8085 return _B2_NOT_SUPPORTED
;
8087 if ((GET_WORD(bp_parms
[2].info
) >= 32)
8088 || !((1L << GET_WORD(bp_parms
[2].info
)) & plci
->adapter
->profile
.B3_Protocols
))
8090 return _B3_NOT_SUPPORTED
;
8092 if ((GET_WORD(bp_parms
[1].info
) != B2_SDLC
)
8093 && ((GET_WORD(bp_parms
[0].info
) == B1_MODEM_ALL_NEGOTIATE
)
8094 || (GET_WORD(bp_parms
[0].info
) == B1_MODEM_ASYNC
)
8095 || (GET_WORD(bp_parms
[0].info
) == B1_MODEM_SYNC_HDLC
)))
8097 return (add_modem_b23(plci
, bp_parms
));
8100 add_p(plci
, LLI
, lli
);
8102 plci
->B2_prot
= (byte
)GET_WORD(bp_parms
[1].info
);
8103 plci
->B3_prot
= (byte
)GET_WORD(bp_parms
[2].info
);
8104 if (plci
->B2_prot
== 12) SAPI
= 0; /* default SAPI D-channel */
8106 if (bp_parms
[6].length
)
8108 if (api_parse(&bp_parms
[6].info
[1], (word
)bp_parms
[6].length
, "w", global_config
))
8110 return _WRONG_MESSAGE_FORMAT
;
8112 switch (GET_WORD(global_config
[0].info
))
8115 plci
->call_dir
= (plci
->call_dir
& ~CALL_DIR_ANSWER
) | CALL_DIR_ORIGINATE
;
8118 plci
->call_dir
= (plci
->call_dir
& ~CALL_DIR_ORIGINATE
) | CALL_DIR_ANSWER
;
8122 dbug(1, dprintf("call_dir=%04x", plci
->call_dir
));
8125 if (plci
->B2_prot
== B2_PIAFS
)
8128 /* IMPLEMENT_PIAFS */
8130 llc
[1] = (plci
->call_dir
& (CALL_DIR_ORIGINATE
| CALL_DIR_FORCE_OUTG_NL
)) ?
8131 llc2_out
[GET_WORD(bp_parms
[1].info
)] : llc2_in
[GET_WORD(bp_parms
[1].info
)];
8133 llc
[2] = llc3
[GET_WORD(bp_parms
[2].info
)];
8135 add_p(plci
, LLC
, llc
);
8138 PUT_WORD(&dlc
[1], plci
->appl
->MaxDataLength
+
8139 header
[GET_WORD(bp_parms
[2].info
)]);
8141 b1_config
= &bp_parms
[3];
8143 if (plci
->B3_prot
== 4
8144 || plci
->B3_prot
== 5)
8146 for (i
= 0; i
< sizeof(T30_INFO
); i
++) nlc
[i
] = 0;
8147 nlc
[0] = sizeof(T30_INFO
);
8148 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_PAPER_FORMATS
)
8149 ((T30_INFO
*)&nlc
[1])->operating_mode
= T30_OPERATING_MODE_CAPI
;
8150 ((T30_INFO
*)&nlc
[1])->rate_div_2400
= 0xff;
8151 if (b1_config
->length
>= 2)
8153 ((T30_INFO
*)&nlc
[1])->rate_div_2400
= (byte
)(GET_WORD(&b1_config
->info
[1]) / 2400);
8156 b2_config
= &bp_parms
[4];
8159 if (llc
[1] == PIAFS_CRC
)
8161 if (plci
->B3_prot
!= B3_TRANSPARENT
)
8163 return _B_STACK_NOT_SUPPORTED
;
8165 if (b2_config
->length
&& api_parse(&b2_config
->info
[1], (word
)b2_config
->length
, "bwww", b2_config_parms
)) {
8166 return _WRONG_MESSAGE_FORMAT
;
8168 PUT_WORD(&dlc
[1], plci
->appl
->MaxDataLength
);
8169 dlc
[3] = 0; /* Addr A */
8170 dlc
[4] = 0; /* Addr B */
8171 dlc
[5] = 0; /* modulo mode */
8172 dlc
[6] = 0; /* window size */
8173 if (b2_config
->length
>= 7) {
8176 dlc
[9] = b2_config_parms
[0].info
[0]; /* PIAFS protocol Speed configuration */
8177 dlc
[10] = b2_config_parms
[1].info
[0]; /* V.42bis P0 */
8178 dlc
[11] = b2_config_parms
[1].info
[1]; /* V.42bis P0 */
8179 dlc
[12] = b2_config_parms
[2].info
[0]; /* V.42bis P1 */
8180 dlc
[13] = b2_config_parms
[2].info
[1]; /* V.42bis P1 */
8181 dlc
[14] = b2_config_parms
[3].info
[0]; /* V.42bis P2 */
8182 dlc
[15] = b2_config_parms
[3].info
[1]; /* V.42bis P2 */
8184 if (b2_config
->length
>= 8) { /* PIAFS control abilities */
8186 dlc
[16] = 2; /* Length of PIAFS extension */
8187 dlc
[17] = PIAFS_UDATA_ABILITIES
; /* control (UDATA) ability */
8188 dlc
[18] = b2_config_parms
[4].info
[0]; /* value */
8192 else /* default values, 64K, variable, no compression */
8196 dlc
[9] = 0x03; /* PIAFS protocol Speed configuration */
8197 dlc
[10] = 0x03; /* V.42bis P0 */
8198 dlc
[11] = 0; /* V.42bis P0 */
8199 dlc
[12] = 0; /* V.42bis P1 */
8200 dlc
[13] = 0; /* V.42bis P1 */
8201 dlc
[14] = 0; /* V.42bis P2 */
8202 dlc
[15] = 0; /* V.42bis P2 */
8205 add_p(plci
, DLC
, dlc
);
8209 if ((llc
[1] == V120_L2
) || (llc
[1] == V120_V42BIS
))
8211 if (plci
->B3_prot
!= B3_TRANSPARENT
)
8212 return _B_STACK_NOT_SUPPORTED
;
8215 PUT_WORD(&dlc
[1], GET_WORD(&dlc
[1]) + 2);
8220 if (b2_config
->length
!= 0)
8222 if ((llc
[1] == V120_V42BIS
) && api_parse(&b2_config
->info
[1], (word
)b2_config
->length
, "bbbbwww", b2_config_parms
)) {
8223 return _WRONG_MESSAGE_FORMAT
;
8225 dlc
[3] = (byte
)((b2_config
->info
[2] << 3) | ((b2_config
->info
[1] >> 5) & 0x04));
8226 dlc
[4] = (byte
)((b2_config
->info
[1] << 1) | 0x01);
8227 if (b2_config
->info
[3] != 128)
8229 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc
[0], dlc
[1], dlc
[2], dlc
[3], dlc
[4]));
8230 return _B2_PARM_NOT_SUPPORTED
;
8232 dlc
[5] = (byte
)(b2_config
->info
[3] - 1);
8233 dlc
[6] = b2_config
->info
[4];
8234 if (llc
[1] == V120_V42BIS
) {
8235 if (b2_config
->length
>= 10) {
8238 dlc
[9] = b2_config_parms
[4].info
[0];
8239 dlc
[10] = b2_config_parms
[4].info
[1];
8240 dlc
[11] = b2_config_parms
[5].info
[0];
8241 dlc
[12] = b2_config_parms
[5].info
[1];
8242 dlc
[13] = b2_config_parms
[6].info
[0];
8243 dlc
[14] = b2_config_parms
[6].info
[1];
8245 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms
[4].info
[0], b2_config_parms
[4].info
[1]));
8246 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms
[5].info
[0], b2_config_parms
[5].info
[1]));
8247 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms
[6].info
[0], b2_config_parms
[6].info
[1]));
8257 if (b2_config
->length
)
8259 dbug(1, dprintf("B2-Config"));
8260 if (llc
[1] == X75_V42BIS
) {
8261 if (api_parse(&b2_config
->info
[1], (word
)b2_config
->length
, "bbbbwww", b2_config_parms
))
8263 return _WRONG_MESSAGE_FORMAT
;
8267 if (api_parse(&b2_config
->info
[1], (word
)b2_config
->length
, "bbbbs", b2_config_parms
))
8269 return _WRONG_MESSAGE_FORMAT
;
8272 /* if B2 Protocol is LAPD, b2_config structure is different */
8276 if (b2_config
->length
>= 1) dlc
[2] = b2_config
->info
[1]; /* TEI */
8278 if ((b2_config
->length
>= 2) && (plci
->B2_prot
== 12))
8280 SAPI
= b2_config
->info
[2]; /* SAPI */
8283 if ((b2_config
->length
>= 3) && (b2_config
->info
[3] == 128))
8285 dlc
[3] = 127; /* Mode */
8289 dlc
[3] = 7; /* Mode */
8292 if (b2_config
->length
>= 4) dlc
[4] = b2_config
->info
[4]; /* Window */
8294 dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc
[0], dlc
[1], dlc
[2], dlc
[3], dlc
[4]));
8295 if (b2_config
->length
> 5) return _B2_PARM_NOT_SUPPORTED
;
8299 dlc
[0] = (byte
)(b2_config_parms
[4].length
+ 6);
8300 dlc
[3] = b2_config
->info
[1];
8301 dlc
[4] = b2_config
->info
[2];
8302 if (b2_config
->info
[3] != 8 && b2_config
->info
[3] != 128) {
8303 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc
[0], dlc
[1], dlc
[2], dlc
[3], dlc
[4]));
8304 return _B2_PARM_NOT_SUPPORTED
;
8307 dlc
[5] = (byte
)(b2_config
->info
[3] - 1);
8308 dlc
[6] = b2_config
->info
[4];
8309 if (dlc
[6] > dlc
[5]) {
8310 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]));
8311 return _B2_PARM_NOT_SUPPORTED
;
8314 if (llc
[1] == X75_V42BIS
) {
8315 if (b2_config
->length
>= 10) {
8318 dlc
[9] = b2_config_parms
[4].info
[0];
8319 dlc
[10] = b2_config_parms
[4].info
[1];
8320 dlc
[11] = b2_config_parms
[5].info
[0];
8321 dlc
[12] = b2_config_parms
[5].info
[1];
8322 dlc
[13] = b2_config_parms
[6].info
[0];
8323 dlc
[14] = b2_config_parms
[6].info
[1];
8325 dbug(1, dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms
[4].info
[0], b2_config_parms
[4].info
[1]));
8326 dbug(1, dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms
[5].info
[0], b2_config_parms
[5].info
[1]));
8327 dbug(1, dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms
[6].info
[0], b2_config_parms
[6].info
[1]));
8335 PUT_WORD(&dlc
[7], (word
)b2_config_parms
[4].length
);
8336 for (i
= 0; i
< b2_config_parms
[4].length
; i
++)
8337 dlc
[11 + i
] = b2_config_parms
[4].info
[1 + i
];
8342 add_p(plci
, DLC
, dlc
);
8344 b3_config
= &bp_parms
[5];
8345 if (b3_config
->length
)
8347 if (plci
->B3_prot
== 4
8348 || plci
->B3_prot
== 5)
8350 if (api_parse(&b3_config
->info
[1], (word
)b3_config
->length
, "wwss", b3_config_parms
))
8352 return _WRONG_MESSAGE_FORMAT
;
8354 i
= GET_WORD((byte
*)(b3_config_parms
[0].info
));
8355 ((T30_INFO
*)&nlc
[1])->resolution
= (byte
)(((i
& 0x0001) ||
8356 ((plci
->B3_prot
== 4) && (((byte
)(GET_WORD((byte
*)b3_config_parms
[1].info
))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200
: 0);
8357 ((T30_INFO
*)&nlc
[1])->data_format
= (byte
)(GET_WORD((byte
*)b3_config_parms
[1].info
));
8358 fax_control_bits
= T30_CONTROL_BIT_ALL_FEATURES
;
8359 if ((((T30_INFO
*)&nlc
[1])->rate_div_2400
!= 0) && (((T30_INFO
*)&nlc
[1])->rate_div_2400
<= 6))
8360 fax_control_bits
&= ~T30_CONTROL_BIT_ENABLE_V34FAX
;
8361 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_FAX_PAPER_FORMATS
)
8364 if ((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1])
8365 & (1L << PRIVATE_FAX_PAPER_FORMATS
))
8367 ((T30_INFO
*)&nlc
[1])->resolution
|= T30_RESOLUTION_R8_1540
|
8368 T30_RESOLUTION_R16_1540_OR_400
| T30_RESOLUTION_300_300
|
8369 T30_RESOLUTION_INCH_BASED
| T30_RESOLUTION_METRIC_BASED
;
8372 ((T30_INFO
*)&nlc
[1])->recording_properties
=
8373 T30_RECORDING_WIDTH_ISO_A3
|
8374 (T30_RECORDING_LENGTH_UNLIMITED
<< 2) |
8375 (T30_MIN_SCANLINE_TIME_00_00_00
<< 4);
8377 if (plci
->B3_prot
== 5)
8379 if (i
& 0x0002) /* Accept incoming fax-polling requests */
8380 fax_control_bits
|= T30_CONTROL_BIT_ACCEPT_POLLING
;
8381 if (i
& 0x2000) /* Do not use MR compression */
8382 fax_control_bits
&= ~T30_CONTROL_BIT_ENABLE_2D_CODING
;
8383 if (i
& 0x4000) /* Do not use MMR compression */
8384 fax_control_bits
&= ~T30_CONTROL_BIT_ENABLE_T6_CODING
;
8385 if (i
& 0x8000) /* Do not use ECM */
8386 fax_control_bits
&= ~T30_CONTROL_BIT_ENABLE_ECM
;
8387 if (plci
->fax_connect_info_length
!= 0)
8389 ((T30_INFO
*)&nlc
[1])->resolution
= ((T30_INFO
*)plci
->fax_connect_info_buffer
)->resolution
;
8390 ((T30_INFO
*)&nlc
[1])->data_format
= ((T30_INFO
*)plci
->fax_connect_info_buffer
)->data_format
;
8391 ((T30_INFO
*)&nlc
[1])->recording_properties
= ((T30_INFO
*)plci
->fax_connect_info_buffer
)->recording_properties
;
8392 fax_control_bits
|= GET_WORD(&((T30_INFO
*)plci
->fax_connect_info_buffer
)->control_bits_low
) &
8393 (T30_CONTROL_BIT_REQUEST_POLLING
| T30_CONTROL_BIT_MORE_DOCUMENTS
);
8396 /* copy station id to NLC */
8397 for (i
= 0; i
< T30_MAX_STATION_ID_LENGTH
; i
++)
8399 if (i
< b3_config_parms
[2].length
)
8401 ((T30_INFO
*)&nlc
[1])->station_id
[i
] = ((byte
*)b3_config_parms
[2].info
)[1 + i
];
8405 ((T30_INFO
*)&nlc
[1])->station_id
[i
] = ' ';
8408 ((T30_INFO
*)&nlc
[1])->station_id_len
= T30_MAX_STATION_ID_LENGTH
;
8409 /* copy head line to NLC */
8410 if (b3_config_parms
[3].length
)
8413 pos
= (byte
)(fax_head_line_time(&(((T30_INFO
*)&nlc
[1])->station_id
[T30_MAX_STATION_ID_LENGTH
])));
8416 if (CAPI_MAX_DATE_TIME_LENGTH
+ 2 + b3_config_parms
[3].length
> CAPI_MAX_HEAD_LINE_SPACE
)
8420 nlc
[1 + offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ pos
++] = ' ';
8421 nlc
[1 + offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ pos
++] = ' ';
8422 len
= (byte
)b3_config_parms
[2].length
;
8425 if (CAPI_MAX_DATE_TIME_LENGTH
+ 2 + len
+ 2 + b3_config_parms
[3].length
<= CAPI_MAX_HEAD_LINE_SPACE
)
8427 for (i
= 0; i
< len
; i
++)
8428 nlc
[1 + offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ pos
++] = ((byte
*)b3_config_parms
[2].info
)[1 + i
];
8429 nlc
[1 + offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ pos
++] = ' ';
8430 nlc
[1 + offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ pos
++] = ' ';
8435 len
= (byte
)b3_config_parms
[3].length
;
8436 if (len
> CAPI_MAX_HEAD_LINE_SPACE
- pos
)
8437 len
= (byte
)(CAPI_MAX_HEAD_LINE_SPACE
- pos
);
8438 ((T30_INFO
*)&nlc
[1])->head_line_len
= (byte
)(pos
+ len
);
8439 nlc
[0] += (byte
)(pos
+ len
);
8440 for (i
= 0; i
< len
; i
++)
8441 nlc
[1 + offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
+ pos
++] = ((byte
*)b3_config_parms
[3].info
)[1 + i
];
8443 ((T30_INFO
*)&nlc
[1])->head_line_len
= 0;
8445 plci
->nsf_control_bits
= 0;
8446 if (plci
->B3_prot
== 5)
8448 if ((plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_FAX_SUB_SEP_PWD
))
8449 && (GET_WORD((byte
*)b3_config_parms
[1].info
) & 0x8000)) /* Private SUB/SEP/PWD enable */
8451 plci
->requested_options
|= 1L << PRIVATE_FAX_SUB_SEP_PWD
;
8453 if ((plci
->adapter
->man_profile
.private_options
& (1L << PRIVATE_FAX_NONSTANDARD
))
8454 && (GET_WORD((byte
*)b3_config_parms
[1].info
) & 0x4000)) /* Private non-standard facilities enable */
8456 plci
->requested_options
|= 1L << PRIVATE_FAX_NONSTANDARD
;
8458 if ((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1])
8459 & ((1L << PRIVATE_FAX_SUB_SEP_PWD
) | (1L << PRIVATE_FAX_NONSTANDARD
)))
8461 if ((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1])
8462 & (1L << PRIVATE_FAX_SUB_SEP_PWD
))
8464 fax_control_bits
|= T30_CONTROL_BIT_ACCEPT_SUBADDRESS
| T30_CONTROL_BIT_ACCEPT_PASSWORD
;
8465 if (fax_control_bits
& T30_CONTROL_BIT_ACCEPT_POLLING
)
8466 fax_control_bits
|= T30_CONTROL_BIT_ACCEPT_SEL_POLLING
;
8469 pos
= offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
;
8470 if (pos
< plci
->fax_connect_info_length
)
8472 for (i
= 1 + plci
->fax_connect_info_buffer
[pos
]; i
!= 0; i
--)
8473 nlc
[++len
] = plci
->fax_connect_info_buffer
[pos
++];
8477 if (pos
< plci
->fax_connect_info_length
)
8479 for (i
= 1 + plci
->fax_connect_info_buffer
[pos
]; i
!= 0; i
--)
8480 nlc
[++len
] = plci
->fax_connect_info_buffer
[pos
++];
8484 if ((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1])
8485 & (1L << PRIVATE_FAX_NONSTANDARD
))
8487 if ((pos
< plci
->fax_connect_info_length
) && (plci
->fax_connect_info_buffer
[pos
] != 0))
8489 if ((plci
->fax_connect_info_buffer
[pos
] >= 3) && (plci
->fax_connect_info_buffer
[pos
+ 1] >= 2))
8490 plci
->nsf_control_bits
= GET_WORD(&plci
->fax_connect_info_buffer
[pos
+ 2]);
8491 for (i
= 1 + plci
->fax_connect_info_buffer
[pos
]; i
!= 0; i
--)
8492 nlc
[++len
] = plci
->fax_connect_info_buffer
[pos
++];
8496 if (api_parse(&b3_config
->info
[1], (word
)b3_config
->length
, "wwsss", b3_config_parms
))
8498 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8503 if ((b3_config_parms
[4].length
>= 3) && (b3_config_parms
[4].info
[1] >= 2))
8504 plci
->nsf_control_bits
= GET_WORD(&b3_config_parms
[4].info
[2]);
8505 nlc
[++len
] = (byte
)(b3_config_parms
[4].length
);
8506 for (i
= 0; i
< b3_config_parms
[4].length
; i
++)
8507 nlc
[++len
] = b3_config_parms
[4].info
[1 + i
];
8512 if ((plci
->nsf_control_bits
& T30_NSF_CONTROL_BIT_ENABLE_NSF
)
8513 && (plci
->nsf_control_bits
& T30_NSF_CONTROL_BIT_NEGOTIATE_RESP
))
8515 ((T30_INFO
*)&nlc
[1])->operating_mode
= T30_OPERATING_MODE_CAPI_NEG
;
8520 PUT_WORD(&(((T30_INFO
*)&nlc
[1])->control_bits_low
), fax_control_bits
);
8521 len
= offsetof(T30_INFO
, station_id
) + T30_MAX_STATION_ID_LENGTH
;
8522 for (i
= 0; i
< len
; i
++)
8523 plci
->fax_connect_info_buffer
[i
] = nlc
[1 + i
];
8524 ((T30_INFO
*) plci
->fax_connect_info_buffer
)->head_line_len
= 0;
8525 i
+= ((T30_INFO
*)&nlc
[1])->head_line_len
;
8527 plci
->fax_connect_info_buffer
[len
++] = nlc
[++i
];
8528 plci
->fax_connect_info_length
= len
;
8533 if (b3_config
->length
!= 16)
8534 return _B3_PARM_NOT_SUPPORTED
;
8535 for (i
= 0; i
< 12; i
++) nlc
[1 + i
] = b3_config
->info
[1 + i
];
8536 if (GET_WORD(&b3_config
->info
[13]) != 8 && GET_WORD(&b3_config
->info
[13]) != 128)
8537 return _B3_PARM_NOT_SUPPORTED
;
8538 nlc
[13] = b3_config
->info
[13];
8539 if (GET_WORD(&b3_config
->info
[15]) >= nlc
[13])
8540 return _B3_PARM_NOT_SUPPORTED
;
8541 nlc
[14] = b3_config
->info
[15];
8546 if (plci
->B3_prot
== 4
8547 || plci
->B3_prot
== 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED
;
8549 add_p(plci
, NLC
, nlc
);
8553 /*----------------------------------------------------------------*/
8554 /* make the same as add_b23, but only for the modem related */
8555 /* L2 and L3 B-Chan protocol. */
8557 /* Enabled L2 and L3 Configurations: */
8558 /* If L1 == Modem all negotiation */
8559 /* only L2 == Modem with full negotiation is allowed */
8560 /* If L1 == Modem async or sync */
8561 /* only L2 == Transparent is allowed */
8562 /* L3 == Modem or L3 == Transparent are allowed */
8563 /* B2 Configuration for modem: */
8564 /* word : enable/disable compression, bitoptions */
8565 /* B3 Configuration for modem: */
8567 /*----------------------------------------------------------------*/
8568 static word
add_modem_b23(PLCI
*plci
, API_PARSE
*bp_parms
)
8570 static byte lli
[12] = {1,1};
8571 static byte llc
[3] = {2,0,0};
8572 static byte dlc
[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8573 API_PARSE mdm_config
[2];
8577 for (i
= 0; i
< 2; i
++) mdm_config
[i
].length
= 0;
8578 for (i
= 0; i
< sizeof(dlc
); i
++) dlc
[i
] = 0;
8580 if (((GET_WORD(bp_parms
[0].info
) == B1_MODEM_ALL_NEGOTIATE
)
8581 && (GET_WORD(bp_parms
[1].info
) != B2_MODEM_EC_COMPRESSION
))
8582 || ((GET_WORD(bp_parms
[0].info
) != B1_MODEM_ALL_NEGOTIATE
)
8583 && (GET_WORD(bp_parms
[1].info
) != B2_TRANSPARENT
)))
8585 return (_B_STACK_NOT_SUPPORTED
);
8587 if ((GET_WORD(bp_parms
[2].info
) != B3_MODEM
)
8588 && (GET_WORD(bp_parms
[2].info
) != B3_TRANSPARENT
))
8590 return (_B_STACK_NOT_SUPPORTED
);
8593 plci
->B2_prot
= (byte
) GET_WORD(bp_parms
[1].info
);
8594 plci
->B3_prot
= (byte
) GET_WORD(bp_parms
[2].info
);
8596 if ((GET_WORD(bp_parms
[1].info
) == B2_MODEM_EC_COMPRESSION
) && bp_parms
[4].length
)
8598 if (api_parse(&bp_parms
[4].info
[1],
8599 (word
)bp_parms
[4].length
, "w",
8602 return (_WRONG_MESSAGE_FORMAT
);
8604 b2_config
= GET_WORD(mdm_config
[0].info
);
8607 /* OK, L2 is modem */
8611 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL
)
8613 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_OOB_CHANNEL
)
8616 if ((lli
[1] & 0x02) && (diva_xdi_extended_features
& DIVA_CAPI_USE_CMA
)) {
8618 if (plci
->rx_dma_descriptor
<= 0) {
8619 plci
->rx_dma_descriptor
= diva_get_dma_descriptor(plci
, &plci
->rx_dma_magic
);
8620 if (plci
->rx_dma_descriptor
>= 0)
8621 plci
->rx_dma_descriptor
++;
8623 if (plci
->rx_dma_descriptor
> 0) {
8626 lli
[2] = (byte
)(plci
->rx_dma_descriptor
- 1);
8627 lli
[3] = (byte
)plci
->rx_dma_magic
;
8628 lli
[4] = (byte
)(plci
->rx_dma_magic
>> 8);
8629 lli
[5] = (byte
)(plci
->rx_dma_magic
>> 16);
8630 lli
[6] = (byte
)(plci
->rx_dma_magic
>> 24);
8634 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci
->adapter
)) {
8638 llc
[1] = (plci
->call_dir
& (CALL_DIR_ORIGINATE
| CALL_DIR_FORCE_OUTG_NL
)) ?
8639 /*V42*/ 10 : /*V42_IN*/ 9;
8640 llc
[2] = 4; /* pass L3 always transparent */
8641 add_p(plci
, LLI
, lli
);
8642 add_p(plci
, LLC
, llc
);
8644 PUT_WORD(&dlc
[i
], plci
->appl
->MaxDataLength
);
8646 if (GET_WORD(bp_parms
[1].info
) == B2_MODEM_EC_COMPRESSION
)
8648 if (bp_parms
[4].length
)
8650 dbug(1, dprintf("MDM b2_config=%02x", b2_config
));
8651 dlc
[i
++] = 3; /* Addr A */
8652 dlc
[i
++] = 1; /* Addr B */
8653 dlc
[i
++] = 7; /* modulo mode */
8654 dlc
[i
++] = 7; /* window size */
8655 dlc
[i
++] = 0; /* XID len Lo */
8656 dlc
[i
++] = 0; /* XID len Hi */
8658 if (b2_config
& MDM_B2_DISABLE_V42bis
)
8660 dlc
[i
] |= DLC_MODEMPROT_DISABLE_V42_V42BIS
;
8662 if (b2_config
& MDM_B2_DISABLE_MNP
)
8664 dlc
[i
] |= DLC_MODEMPROT_DISABLE_MNP_MNP5
;
8666 if (b2_config
& MDM_B2_DISABLE_TRANS
)
8668 dlc
[i
] |= DLC_MODEMPROT_REQUIRE_PROTOCOL
;
8670 if (b2_config
& MDM_B2_DISABLE_V42
)
8672 dlc
[i
] |= DLC_MODEMPROT_DISABLE_V42_DETECT
;
8674 if (b2_config
& MDM_B2_DISABLE_COMP
)
8676 dlc
[i
] |= DLC_MODEMPROT_DISABLE_COMPRESSION
;
8683 dlc
[i
++] = 3; /* Addr A */
8684 dlc
[i
++] = 1; /* Addr B */
8685 dlc
[i
++] = 7; /* modulo mode */
8686 dlc
[i
++] = 7; /* window size */
8687 dlc
[i
++] = 0; /* XID len Lo */
8688 dlc
[i
++] = 0; /* XID len Hi */
8689 dlc
[i
++] = DLC_MODEMPROT_DISABLE_V42_V42BIS
|
8690 DLC_MODEMPROT_DISABLE_MNP_MNP5
|
8691 DLC_MODEMPROT_DISABLE_V42_DETECT
|
8692 DLC_MODEMPROT_DISABLE_COMPRESSION
;
8694 dlc
[0] = (byte
)(i
- 1);
8695 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8696 add_p(plci
, DLC
, dlc
);
8701 /*------------------------------------------------------------------*/
8702 /* send a request for the signaling entity */
8703 /*------------------------------------------------------------------*/
8705 static void sig_req(PLCI
*plci
, byte req
, byte Id
)
8708 if (plci
->adapter
->adapter_disabled
) return;
8709 dbug(1, dprintf("sig_req(%x)", req
));
8711 plci
->sig_remove_id
= plci
->Sig
.Id
;
8712 if (plci
->req_in
== plci
->req_in_start
) {
8714 plci
->RBuffer
[plci
->req_in
++] = 0;
8716 PUT_WORD(&plci
->RBuffer
[plci
->req_in_start
], plci
->req_in
-plci
->req_in_start
- 2);
8717 plci
->RBuffer
[plci
->req_in
++] = Id
; /* sig/nl flag */
8718 plci
->RBuffer
[plci
->req_in
++] = req
; /* request */
8719 plci
->RBuffer
[plci
->req_in
++] = 0; /* channel */
8720 plci
->req_in_start
= plci
->req_in
;
8723 /*------------------------------------------------------------------*/
8724 /* send a request for the network layer entity */
8725 /*------------------------------------------------------------------*/
8727 static void nl_req_ncci(PLCI
*plci
, byte req
, byte ncci
)
8730 if (plci
->adapter
->adapter_disabled
) return;
8731 dbug(1, dprintf("nl_req %02x %02x %02x", plci
->Id
, req
, ncci
));
8734 plci
->nl_remove_id
= plci
->NL
.Id
;
8735 ncci_remove(plci
, 0, (byte
)(ncci
!= 0));
8738 if (plci
->req_in
== plci
->req_in_start
) {
8740 plci
->RBuffer
[plci
->req_in
++] = 0;
8742 PUT_WORD(&plci
->RBuffer
[plci
->req_in_start
], plci
->req_in
-plci
->req_in_start
- 2);
8743 plci
->RBuffer
[plci
->req_in
++] = 1; /* sig/nl flag */
8744 plci
->RBuffer
[plci
->req_in
++] = req
; /* request */
8745 plci
->RBuffer
[plci
->req_in
++] = plci
->adapter
->ncci_ch
[ncci
]; /* channel */
8746 plci
->req_in_start
= plci
->req_in
;
8749 static void send_req(PLCI
*plci
)
8756 if (plci
->adapter
->adapter_disabled
) return;
8757 channel_xmit_xon(plci
);
8759 /* if nothing to do, return */
8760 if (plci
->req_in
== plci
->req_out
) return;
8761 dbug(1, dprintf("send_req(in=%d,out=%d)", plci
->req_in
, plci
->req_out
));
8763 if (plci
->nl_req
|| plci
->sig_req
) return;
8765 l
= GET_WORD(&plci
->RBuffer
[plci
->req_out
]);
8767 plci
->XData
[0].P
= &plci
->RBuffer
[plci
->req_out
];
8769 if (plci
->RBuffer
[plci
->req_out
] == 1)
8773 e
->Req
= plci
->nl_req
= plci
->RBuffer
[plci
->req_out
++];
8774 e
->ReqCh
= plci
->RBuffer
[plci
->req_out
++];
8775 if (!(e
->Id
& 0x1f))
8778 plci
->RBuffer
[plci
->req_out
- 4] = CAI
;
8779 plci
->RBuffer
[plci
->req_out
- 3] = 1;
8780 plci
->RBuffer
[plci
->req_out
- 2] = (plci
->Sig
.Id
== 0xff) ? 0 : plci
->Sig
.Id
;
8781 plci
->RBuffer
[plci
->req_out
- 1] = 0;
8783 plci
->nl_global_req
= plci
->nl_req
;
8785 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci
->adapter
->Id
, e
->Id
, e
->Req
, e
->ReqCh
));
8790 if (plci
->RBuffer
[plci
->req_out
])
8791 e
->Id
= plci
->RBuffer
[plci
->req_out
];
8793 e
->Req
= plci
->sig_req
= plci
->RBuffer
[plci
->req_out
++];
8794 e
->ReqCh
= plci
->RBuffer
[plci
->req_out
++];
8795 if (!(e
->Id
& 0x1f))
8796 plci
->sig_global_req
= plci
->sig_req
;
8797 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci
->adapter
->Id
, e
->Id
, e
->Req
, e
->ReqCh
));
8799 plci
->XData
[0].PLength
= l
;
8801 plci
->adapter
->request(e
);
8802 dbug(1, dprintf("send_ok"));
8805 static void send_data(PLCI
*plci
)
8807 DIVA_CAPI_ADAPTER
*a
;
8812 if (!plci
->nl_req
&& plci
->ncci_ring_list
)
8815 ncci
= plci
->ncci_ring_list
;
8818 ncci
= a
->ncci_next
[ncci
];
8819 ncci_ptr
= &(a
->ncci
[ncci
]);
8820 if (!(a
->ncci_ch
[ncci
]
8821 && (a
->ch_flow_control
[a
->ncci_ch
[ncci
]] & N_OK_FC_PENDING
)))
8823 if (ncci_ptr
->data_pending
)
8825 if ((a
->ncci_state
[ncci
] == CONNECTED
)
8826 || (a
->ncci_state
[ncci
] == INC_ACT_PENDING
)
8827 || (plci
->send_disc
== ncci
))
8829 data
= &(ncci_ptr
->DBuffer
[ncci_ptr
->data_out
]);
8830 if ((plci
->B2_prot
== B2_V120_ASYNC
)
8831 || (plci
->B2_prot
== B2_V120_ASYNC_V42BIS
)
8832 || (plci
->B2_prot
== B2_V120_BIT_TRANSPARENT
))
8834 plci
->NData
[1].P
= TransmitBufferGet(plci
->appl
, data
->P
);
8835 plci
->NData
[1].PLength
= data
->Length
;
8836 if (data
->Flags
& 0x10)
8837 plci
->NData
[0].P
= v120_break_header
;
8839 plci
->NData
[0].P
= v120_default_header
;
8840 plci
->NData
[0].PLength
= 1;
8842 plci
->NL
.Req
= plci
->nl_req
= (byte
)((data
->Flags
& 0x07) << 4 | N_DATA
);
8846 plci
->NData
[0].P
= TransmitBufferGet(plci
->appl
, data
->P
);
8847 plci
->NData
[0].PLength
= data
->Length
;
8848 if (data
->Flags
& 0x10)
8849 plci
->NL
.Req
= plci
->nl_req
= (byte
)N_UDATA
;
8851 else if ((plci
->B3_prot
== B3_RTP
) && (data
->Flags
& 0x01))
8852 plci
->NL
.Req
= plci
->nl_req
= (byte
)N_BDATA
;
8855 plci
->NL
.Req
= plci
->nl_req
= (byte
)((data
->Flags
& 0x07) << 4 | N_DATA
);
8857 plci
->NL
.X
= plci
->NData
;
8858 plci
->NL
.ReqCh
= a
->ncci_ch
[ncci
];
8859 dbug(1, dprintf("%x:DREQ(%x:%x)", a
->Id
, plci
->NL
.Id
, plci
->NL
.Req
));
8860 plci
->data_sent
= true;
8861 plci
->data_sent_ptr
= data
->P
;
8862 a
->request(&plci
->NL
);
8865 cleanup_ncci_data(plci
, ncci
);
8868 else if (plci
->send_disc
== ncci
)
8870 /* dprintf("N_DISC"); */
8871 plci
->NData
[0].PLength
= 0;
8872 plci
->NL
.ReqCh
= a
->ncci_ch
[ncci
];
8873 plci
->NL
.Req
= plci
->nl_req
= N_DISC
;
8874 a
->request(&plci
->NL
);
8875 plci
->command
= _DISCONNECT_B3_R
;
8876 plci
->send_disc
= 0;
8879 } while (!plci
->nl_req
&& (ncci
!= plci
->ncci_ring_list
));
8880 plci
->ncci_ring_list
= ncci
;
8884 static void listen_check(DIVA_CAPI_ADAPTER
*a
)
8888 byte activnotifiedcalls
= 0;
8890 dbug(1, dprintf("listen_check(%d,%d)", a
->listen_active
, a
->max_listen
));
8891 if (!remove_started
&& !a
->adapter_disabled
)
8893 for (i
= 0; i
< a
->max_plci
; i
++)
8895 plci
= &(a
->plci
[i
]);
8896 if (plci
->notifiedcall
) activnotifiedcalls
++;
8898 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls
));
8900 for (i
= a
->listen_active
; i
< ((word
)(a
->max_listen
+ activnotifiedcalls
)); i
++) {
8901 if ((j
= get_plci(a
))) {
8903 plci
= &a
->plci
[j
- 1];
8904 plci
->State
= LISTENING
;
8906 add_p(plci
, OAD
, "\x01\xfd");
8908 add_p(plci
, KEY
, "\x04\x43\x41\x32\x30");
8910 add_p(plci
, CAI
, "\x01\xc0");
8911 add_p(plci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
8912 add_p(plci
, LLI
, "\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8913 add_p(plci
, SHIFT
| 6, NULL
);
8914 add_p(plci
, SIN
, "\x02\x00\x00");
8915 plci
->internal_command
= LISTEN_SIG_ASSIGN_PEND
; /* do indicate_req if OK */
8916 sig_req(plci
, ASSIGN
, DSIG_ID
);
8923 /*------------------------------------------------------------------*/
8924 /* functions for all parameters sent in INDs */
8925 /*------------------------------------------------------------------*/
8927 static void IndParse(PLCI
*plci
, word
*parms_id
, byte
**parms
, byte multiIEsize
)
8929 word ploc
; /* points to current location within packet */
8941 in
= plci
->Sig
.RBuffer
->P
;
8942 for (i
= 0; i
< parms_id
[0]; i
++) /* multiIE parms_id contains just the 1st */
8943 { /* element but parms array is larger */
8944 parms
[i
] = (byte
*)"";
8946 for (i
= 0; i
< multiIEsize
; i
++)
8948 parms
[i
] = (byte
*)"";
8951 while (ploc
< plci
->Sig
.RBuffer
->length
- 1) {
8953 /* read information element id and length */
8957 /* w &=0xf0; removed, cannot detect congestion levels */
8958 /* upper 4 bit masked with w==SHIFT now */
8962 wlen
= (byte
)(in
[ploc
+ 1] + 1);
8964 /* check if length valid (not exceeding end of packet) */
8965 if ((ploc
+ wlen
) > 270) return;
8966 if (lock
& 0x80) lock
&= 0x7f;
8967 else codeset
= lock
;
8969 if ((w
& 0xf0) == SHIFT
) {
8971 if (!(codeset
& 0x08)) lock
= (byte
)(codeset
& 7);
8976 if (w
== ESC
&& wlen
>= 3) code
= in
[ploc
+ 2] | 0x800;
8978 code
|= (codeset
<< 8);
8980 for (i
= 1; i
< parms_id
[0] + 1 && parms_id
[i
] != code
; i
++);
8982 if (i
< parms_id
[0] + 1) {
8983 if (!multiIEsize
) { /* with multiIEs use next field index, */
8984 mIEindex
= i
- 1; /* with normal IEs use same index like parms_id */
8987 parms
[mIEindex
] = &in
[ploc
+ 1];
8988 dbug(1, dprintf("mIE[%d]=0x%x", *parms
[mIEindex
], in
[ploc
]));
8989 if (parms_id
[i
] == OAD
8990 || parms_id
[i
] == CONN_NR
8991 || parms_id
[i
] == CAD
) {
8992 if (in
[ploc
+ 2] & 0x80) {
8993 in
[ploc
+ 0] = (byte
)(in
[ploc
+ 1] + 1);
8994 in
[ploc
+ 1] = (byte
)(in
[ploc
+ 2] & 0x7f);
8995 in
[ploc
+ 2] = 0x80;
8996 parms
[mIEindex
] = &in
[ploc
];
8999 mIEindex
++; /* effects multiIEs only */
9008 /*------------------------------------------------------------------*/
9009 /* try to match a cip from received BC and HLC */
9010 /*------------------------------------------------------------------*/
9012 static byte
ie_compare(byte
*ie1
, byte
*ie2
)
9015 if (!ie1
|| !ie2
) return false;
9016 if (!ie1
[0]) return false;
9017 for (i
= 0; i
< (word
)(ie1
[0] + 1); i
++) if (ie1
[i
] != ie2
[i
]) return false;
9021 static word
find_cip(DIVA_CAPI_ADAPTER
*a
, byte
*bc
, byte
*hlc
)
9026 for (i
= 9; i
&& !ie_compare(bc
, cip_bc
[i
][a
->u_law
]); i
--);
9028 for (j
= 16; j
< 29 &&
9029 (!ie_compare(bc
, cip_bc
[j
][a
->u_law
]) || !ie_compare(hlc
, cip_hlc
[j
])); j
++);
9030 if (j
== 29) return i
;
9035 static byte
AddInfo(byte
**add_i
,
9045 /* facility is a nested structure */
9046 /* FTY can be more than once */
9048 if (esc_chi
[0] && !(esc_chi
[esc_chi
[0]] & 0x7f))
9050 add_i
[0] = (byte
*)"\x02\x02\x00"; /* use neither b nor d channel */
9055 add_i
[0] = (byte
*)"";
9059 add_i
[3] = (byte
*)"";
9062 { /* facility array found */
9063 for (i
= 0, j
= 1; i
< MAX_MULTI_IE
&& fty_i
[i
][0]; i
++)
9065 dbug(1, dprintf("AddIFac[%d]", fty_i
[i
][0]));
9069 facility
[j
++] = 0x1c; /* copy fac IE */
9070 for (k
= 0; k
<= flen
; k
++, j
++)
9072 facility
[j
] = fty_i
[i
][k
];
9073 /* dbug(1, dprintf("%x ",facility[j])); */
9077 add_i
[3] = facility
;
9079 /* dbug(1, dprintf("FacArrLen=%d ",len)); */
9080 len
= add_i
[0][0] + add_i
[1][0] + add_i
[2][0] + add_i
[3][0];
9081 len
+= 4; /* calculate length of all */
9085 /*------------------------------------------------------------------*/
9086 /* voice and codec features */
9087 /*------------------------------------------------------------------*/
9089 static void SetVoiceChannel(PLCI
*plci
, byte
*chi
, DIVA_CAPI_ADAPTER
*a
)
9091 byte voice_chi
[] = "\x02\x18\x01";
9094 channel
= chi
[chi
[0]] & 0x3;
9095 dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel
));
9096 voice_chi
[2] = (channel
) ? channel
: 1;
9097 add_p(plci
, FTY
, "\x02\x01\x07"); /* B On, default on 1 */
9098 add_p(plci
, ESC
, voice_chi
); /* Channel */
9099 sig_req(plci
, TEL_CTRL
, 0);
9101 if (a
->AdvSignalPLCI
)
9103 adv_voice_write_coefs(a
->AdvSignalPLCI
, ADV_VOICE_WRITE_ACTIVATION
);
9107 static void VoiceChannelOff(PLCI
*plci
)
9109 dbug(1, dprintf("ExtDevOFF"));
9110 add_p(plci
, FTY
, "\x02\x01\x08"); /* B Off */
9111 sig_req(plci
, TEL_CTRL
, 0);
9113 if (plci
->adapter
->AdvSignalPLCI
)
9115 adv_voice_clear_config(plci
->adapter
->AdvSignalPLCI
);
9120 static word
AdvCodecSupport(DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
,
9126 /* check if hardware supports handset with hook states (adv.codec) */
9127 /* or if just a on board codec is supported */
9128 /* the advanced codec plci is just for internal use */
9130 /* diva Pro with on-board codec: */
9131 if (a
->profile
.Global_Options
& HANDSET
)
9133 /* new call, but hook states are already signalled */
9134 if (a
->AdvCodecFLAG
)
9136 if (a
->AdvSignalAppl
!= appl
|| a
->AdvSignalPLCI
)
9138 dbug(1, dprintf("AdvSigPlci=0x%x", a
->AdvSignalPLCI
));
9139 return 0x2001; /* codec in use by another application */
9143 a
->AdvSignalPLCI
= plci
;
9144 plci
->tel
= ADV_VOICE
;
9146 return 0; /* adv codec still used */
9148 if ((j
= get_plci(a
)))
9150 splci
= &a
->plci
[j
- 1];
9151 splci
->tel
= CODEC_PERMANENT
;
9152 /* hook_listen indicates if a facility_req with handset/hook support */
9153 /* was sent. Otherwise if just a call on an external device was made */
9154 /* the codec will be used but the hook info will be discarded (just */
9155 /* the external controller is in use */
9156 if (hook_listen
) splci
->State
= ADVANCED_VOICE_SIG
;
9159 splci
->State
= ADVANCED_VOICE_NOSIG
;
9162 plci
->spoofed_msg
= SPOOFING_REQUIRED
;
9164 /* indicate D-ch connect if */
9165 } /* codec is connected OK */
9168 a
->AdvSignalPLCI
= plci
;
9169 plci
->tel
= ADV_VOICE
;
9171 a
->AdvSignalAppl
= appl
;
9172 a
->AdvCodecFLAG
= true;
9173 a
->AdvCodecPLCI
= splci
;
9174 add_p(splci
, CAI
, "\x01\x15");
9175 add_p(splci
, LLI
, "\x01\x00");
9176 add_p(splci
, ESC
, "\x02\x18\x00");
9177 add_p(splci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
9178 splci
->internal_command
= PERM_COD_ASSIGN
;
9179 dbug(1, dprintf("Codec Assign"));
9180 sig_req(splci
, ASSIGN
, DSIG_ID
);
9185 return 0x2001; /* wrong state, no more plcis */
9188 else if (a
->profile
.Global_Options
& ON_BOARD_CODEC
)
9190 if (hook_listen
) return 0x300B; /* Facility not supported */
9191 /* no hook with SCOM */
9192 if (plci
!= NULL
) plci
->tel
= CODEC
;
9193 dbug(1, dprintf("S/SCOM codec"));
9194 /* first time we use the scom-s codec we must shut down the internal */
9195 /* handset application of the card. This can be done by an assign with */
9196 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9197 if (!a
->scom_appl_disable
) {
9198 if ((j
= get_plci(a
))) {
9199 splci
= &a
->plci
[j
- 1];
9200 add_p(splci
, CAI
, "\x01\x80");
9201 add_p(splci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
9202 sig_req(splci
, ASSIGN
, 0xC0); /* 0xc0 is the TEL_ID */
9204 a
->scom_appl_disable
= true;
9207 return 0x2001; /* wrong state, no more plcis */
9211 else return 0x300B; /* Facility not supported */
9217 static void CodecIdCheck(DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
)
9220 dbug(1, dprintf("CodecIdCheck"));
9222 if (a
->AdvSignalPLCI
== plci
)
9224 dbug(1, dprintf("PLCI owns codec"));
9225 VoiceChannelOff(a
->AdvCodecPLCI
);
9226 if (a
->AdvCodecPLCI
->State
== ADVANCED_VOICE_NOSIG
)
9228 dbug(1, dprintf("remove temp codec PLCI"));
9229 plci_remove(a
->AdvCodecPLCI
);
9230 a
->AdvCodecFLAG
= 0;
9231 a
->AdvCodecPLCI
= NULL
;
9232 a
->AdvSignalAppl
= NULL
;
9234 a
->AdvSignalPLCI
= NULL
;
9238 /* -------------------------------------------------------------------
9239 Ask for physical address of card on PCI bus
9240 ------------------------------------------------------------------- */
9241 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER
*a
,
9242 IDI_SYNC_REQ
*preq
) {
9244 if (diva_xdi_extended_features
& DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR
) {
9245 ENTITY
*e
= (ENTITY
*)preq
;
9247 e
->user
[0] = a
->Id
- 1;
9248 preq
->xdi_sdram_bar
.info
.bar
= 0;
9249 preq
->xdi_sdram_bar
.Req
= 0;
9250 preq
->xdi_sdram_bar
.Rc
= IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR
;
9254 a
->sdram_bar
= preq
->xdi_sdram_bar
.info
.bar
;
9255 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a
->Id
, a
->sdram_bar
));
9259 /* -------------------------------------------------------------------
9260 Ask XDI about extended features
9261 ------------------------------------------------------------------- */
9262 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER
*a
) {
9264 char buffer
[((sizeof(preq
->xdi_extended_features
) + 4) > sizeof(ENTITY
)) ? (sizeof(preq
->xdi_extended_features
) + 4) : sizeof(ENTITY
)];
9267 preq
= (IDI_SYNC_REQ
*)&buffer
[0];
9269 if (!diva_xdi_extended_features
) {
9270 ENTITY
*e
= (ENTITY
*)preq
;
9271 diva_xdi_extended_features
|= 0x80000000;
9273 e
->user
[0] = a
->Id
- 1;
9274 preq
->xdi_extended_features
.Req
= 0;
9275 preq
->xdi_extended_features
.Rc
= IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES
;
9276 preq
->xdi_extended_features
.info
.buffer_length_in_bytes
= sizeof(features
);
9277 preq
->xdi_extended_features
.info
.features
= &features
[0];
9281 if (features
[0] & DIVA_XDI_EXTENDED_FEATURES_VALID
) {
9283 Check features located in the byte '0'
9285 if (features
[0] & DIVA_XDI_EXTENDED_FEATURE_CMA
) {
9286 diva_xdi_extended_features
|= DIVA_CAPI_USE_CMA
;
9288 if (features
[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA
) {
9289 diva_xdi_extended_features
|= DIVA_CAPI_XDI_PROVIDES_RX_DMA
;
9290 dbug(1, dprintf("XDI provides RxDMA"));
9292 if (features
[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR
) {
9293 diva_xdi_extended_features
|= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR
;
9295 if (features
[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC
) {
9296 diva_xdi_extended_features
|= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL
;
9297 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9303 diva_ask_for_xdi_sdram_bar(a
, preq
);
9306 /*------------------------------------------------------------------*/
9308 /*------------------------------------------------------------------*/
9309 /* called from OS specific part after init time to get the Law */
9310 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9311 void AutomaticLaw(DIVA_CAPI_ADAPTER
*a
)
9316 if (a
->automatic_law
) {
9319 if ((j
= get_plci(a
))) {
9320 diva_get_extended_adapter_features(a
);
9321 splci
= &a
->plci
[j
- 1];
9322 a
->automatic_lawPLCI
= splci
;
9323 a
->automatic_law
= 1;
9324 add_p(splci
, CAI
, "\x01\x80");
9325 add_p(splci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
9326 splci
->internal_command
= USELAW_REQ
;
9329 sig_req(splci
, ASSIGN
, DSIG_ID
);
9334 /* called from OS specific part if an application sends an Capi20Release */
9335 word
CapiRelease(word Id
)
9337 word i
, j
, appls_found
;
9340 DIVA_CAPI_ADAPTER
*a
;
9344 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9345 return (_WRONG_APPL_ID
);
9348 this = &application
[Id
- 1]; /* get application pointer */
9350 for (i
= 0, appls_found
= 0; i
< max_appl
; i
++)
9352 if (application
[i
].Id
) /* an application has been found */
9358 for (i
= 0; i
< max_adapter
; i
++) /* scan all adapters... */
9363 a
->Info_Mask
[Id
- 1] = 0;
9364 a
->CIP_Mask
[Id
- 1] = 0;
9365 a
->Notification_Mask
[Id
- 1] = 0;
9366 a
->codec_listen
[Id
- 1] = NULL
;
9367 a
->requested_options_table
[Id
- 1] = 0;
9368 for (j
= 0; j
< a
->max_plci
; j
++) /* and all PLCIs connected */
9369 { /* with this application */
9371 if (plci
->Id
) /* if plci owns no application */
9372 { /* it may be not jet connected */
9373 if (plci
->State
== INC_CON_PENDING
9374 || plci
->State
== INC_CON_ALERT
)
9376 if (test_c_ind_mask_bit(plci
, (word
)(Id
- 1)))
9378 clear_c_ind_mask_bit(plci
, (word
)(Id
- 1));
9379 if (c_ind_mask_empty(plci
))
9381 sig_req(plci
, HANGUP
, 0);
9383 plci
->State
= OUTG_DIS_PENDING
;
9387 if (test_c_ind_mask_bit(plci
, (word
)(Id
- 1)))
9389 clear_c_ind_mask_bit(plci
, (word
)(Id
- 1));
9390 if (c_ind_mask_empty(plci
))
9399 if (plci
->appl
== this)
9409 if (a
->flag_dynamic_l1_down
)
9411 if (appls_found
== 1) /* last application does a capi release */
9413 if ((j
= get_plci(a
)))
9415 plci
= &a
->plci
[j
- 1];
9417 add_p(plci
, OAD
, "\x01\xfd");
9418 add_p(plci
, CAI
, "\x01\x80");
9419 add_p(plci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
9420 add_p(plci
, SHIFT
| 6, NULL
);
9421 add_p(plci
, SIN
, "\x02\x00\x00");
9422 plci
->internal_command
= REM_L1_SIG_ASSIGN_PEND
;
9423 sig_req(plci
, ASSIGN
, DSIG_ID
);
9424 add_p(plci
, FTY
, "\x02\xff\x06"); /* l1 down */
9425 sig_req(plci
, SIG_CTRL
, 0);
9430 if (a
->AdvSignalAppl
== this)
9432 this->NullCREnable
= false;
9433 if (a
->AdvCodecPLCI
)
9435 plci_remove(a
->AdvCodecPLCI
);
9436 a
->AdvCodecPLCI
->tel
= 0;
9437 a
->AdvCodecPLCI
->adv_nl
= 0;
9439 a
->AdvSignalAppl
= NULL
;
9440 a
->AdvSignalPLCI
= NULL
;
9441 a
->AdvCodecFLAG
= 0;
9442 a
->AdvCodecPLCI
= NULL
;
9452 static word
plci_remove_check(PLCI
*plci
)
9454 if (!plci
) return true;
9455 if (!plci
->NL
.Id
&& c_ind_mask_empty(plci
))
9457 if (plci
->Sig
.Id
== 0xff)
9461 dbug(1, dprintf("plci_remove_complete(%x)", plci
->Id
));
9462 dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci
->tel
, plci
->Sig
.Id
));
9465 CodecIdCheck(plci
->adapter
, plci
);
9466 clear_b1_config(plci
);
9467 ncci_remove(plci
, 0, false);
9468 plci_free_msg_in_queue(plci
);
9469 channel_flow_control_remove(plci
);
9474 plci
->notifiedcall
= 0;
9476 listen_check(plci
->adapter
);
9484 /*------------------------------------------------------------------*/
9486 static byte
plci_nl_busy(PLCI
*plci
)
9488 /* only applicable for non-multiplexed protocols */
9489 return (plci
->nl_req
9490 || (plci
->ncci_ring_list
9491 && plci
->adapter
->ncci_ch
[plci
->ncci_ring_list
]
9492 && (plci
->adapter
->ch_flow_control
[plci
->adapter
->ncci_ch
[plci
->ncci_ring_list
]] & N_OK_FC_PENDING
)));
9496 /*------------------------------------------------------------------*/
9497 /* DTMF facilities */
9498 /*------------------------------------------------------------------*/
9507 } dtmf_digit_map
[] =
9509 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK
},
9510 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR
},
9511 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0
},
9512 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1
},
9513 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2
},
9514 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3
},
9515 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4
},
9516 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5
},
9517 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6
},
9518 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7
},
9519 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8
},
9520 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9
},
9521 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A
},
9522 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B
},
9523 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C
},
9524 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D
},
9525 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A
},
9526 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B
},
9527 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C
},
9528 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D
},
9530 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE
},
9531 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE
},
9532 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE
},
9533 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE
},
9534 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE
},
9535 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE
},
9536 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE
},
9537 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE
},
9538 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE
},
9539 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE
},
9540 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE
},
9541 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE
},
9542 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE
},
9543 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE
},
9544 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE
},
9545 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE
},
9546 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE
},
9547 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE
},
9548 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE
},
9549 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE
},
9550 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE
},
9551 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE
},
9552 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE
},
9553 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL
},
9554 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE
},
9555 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE
},
9556 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE
},
9557 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE
},
9558 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE
},
9559 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE
},
9560 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE
},
9561 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE
},
9562 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE
},
9563 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS
},
9564 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID
},
9565 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH
},
9566 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390
},
9567 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1
},
9568 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2
},
9569 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3
},
9570 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4
},
9571 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5
},
9572 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6
},
9573 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7
},
9574 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8
},
9575 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9
},
9576 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0
},
9577 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1
},
9578 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2
},
9579 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP
},
9580 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1
},
9581 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST
},
9585 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588 static void dtmf_enable_receiver(PLCI
*plci
, byte enable_mask
)
9590 word min_digit_duration
, min_gap_duration
;
9592 dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9593 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
9594 (char *)(FILE_
), __LINE__
, enable_mask
));
9596 if (enable_mask
!= 0)
9598 min_digit_duration
= (plci
->dtmf_rec_pulse_ms
== 0) ? 40 : plci
->dtmf_rec_pulse_ms
;
9599 min_gap_duration
= (plci
->dtmf_rec_pause_ms
== 0) ? 40 : plci
->dtmf_rec_pause_ms
;
9600 plci
->internal_req_buffer
[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER
;
9601 PUT_WORD(&plci
->internal_req_buffer
[1], min_digit_duration
);
9602 PUT_WORD(&plci
->internal_req_buffer
[3], min_gap_duration
);
9603 plci
->NData
[0].PLength
= 5;
9605 PUT_WORD(&plci
->internal_req_buffer
[5], INTERNAL_IND_BUFFER_SIZE
);
9606 plci
->NData
[0].PLength
+= 2;
9607 capidtmf_recv_enable(&(plci
->capidtmf_state
), min_digit_duration
, min_gap_duration
);
9612 plci
->internal_req_buffer
[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER
;
9613 plci
->NData
[0].PLength
= 1;
9615 capidtmf_recv_disable(&(plci
->capidtmf_state
));
9618 plci
->NData
[0].P
= plci
->internal_req_buffer
;
9619 plci
->NL
.X
= plci
->NData
;
9621 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_UDATA
;
9622 plci
->adapter
->request(&plci
->NL
);
9626 static void dtmf_send_digits(PLCI
*plci
, byte
*digit_buffer
, word digit_count
)
9630 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9631 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
9632 (char *)(FILE_
), __LINE__
, digit_count
));
9634 plci
->internal_req_buffer
[0] = DTMF_UDATA_REQUEST_SEND_DIGITS
;
9635 w
= (plci
->dtmf_send_pulse_ms
== 0) ? 40 : plci
->dtmf_send_pulse_ms
;
9636 PUT_WORD(&plci
->internal_req_buffer
[1], w
);
9637 w
= (plci
->dtmf_send_pause_ms
== 0) ? 40 : plci
->dtmf_send_pause_ms
;
9638 PUT_WORD(&plci
->internal_req_buffer
[3], w
);
9639 for (i
= 0; i
< digit_count
; i
++)
9642 while ((w
< DTMF_DIGIT_MAP_ENTRIES
)
9643 && (digit_buffer
[i
] != dtmf_digit_map
[w
].character
))
9647 plci
->internal_req_buffer
[5 + i
] = (w
< DTMF_DIGIT_MAP_ENTRIES
) ?
9648 dtmf_digit_map
[w
].code
: DTMF_DIGIT_TONE_CODE_STAR
;
9650 plci
->NData
[0].PLength
= 5 + digit_count
;
9651 plci
->NData
[0].P
= plci
->internal_req_buffer
;
9652 plci
->NL
.X
= plci
->NData
;
9654 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_UDATA
;
9655 plci
->adapter
->request(&plci
->NL
);
9659 static void dtmf_rec_clear_config(PLCI
*plci
)
9662 dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9663 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
9664 (char *)(FILE_
), __LINE__
));
9666 plci
->dtmf_rec_active
= 0;
9667 plci
->dtmf_rec_pulse_ms
= 0;
9668 plci
->dtmf_rec_pause_ms
= 0;
9670 capidtmf_init(&(plci
->capidtmf_state
), plci
->adapter
->u_law
);
9675 static void dtmf_send_clear_config(PLCI
*plci
)
9678 dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9679 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
9680 (char *)(FILE_
), __LINE__
));
9682 plci
->dtmf_send_requests
= 0;
9683 plci
->dtmf_send_pulse_ms
= 0;
9684 plci
->dtmf_send_pause_ms
= 0;
9688 static void dtmf_prepare_switch(dword Id
, PLCI
*plci
)
9691 dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9692 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9694 while (plci
->dtmf_send_requests
!= 0)
9695 dtmf_confirmation(Id
, plci
);
9699 static word
dtmf_save_config(dword Id
, PLCI
*plci
, byte Rc
)
9702 dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9703 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
9709 static word
dtmf_restore_config(dword Id
, PLCI
*plci
, byte Rc
)
9713 dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9714 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
9717 if (plci
->B1_facilities
& B1_FACILITY_DTMFR
)
9719 switch (plci
->adjust_b_state
)
9721 case ADJUST_B_RESTORE_DTMF_1
:
9722 plci
->internal_command
= plci
->adjust_b_command
;
9723 if (plci_nl_busy(plci
))
9725 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_1
;
9728 dtmf_enable_receiver(plci
, plci
->dtmf_rec_active
);
9729 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_2
;
9731 case ADJUST_B_RESTORE_DTMF_2
:
9732 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
9734 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9735 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
9736 Info
= _WRONG_STATE
;
9746 static void dtmf_command(dword Id
, PLCI
*plci
, byte Rc
)
9748 word internal_command
, Info
;
9752 dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9753 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
,
9754 plci
->dtmf_cmd
, plci
->dtmf_rec_pulse_ms
, plci
->dtmf_rec_pause_ms
,
9755 plci
->dtmf_send_pulse_ms
, plci
->dtmf_send_pause_ms
));
9759 PUT_WORD(&result
[1], DTMF_SUCCESS
);
9760 internal_command
= plci
->internal_command
;
9761 plci
->internal_command
= 0;
9763 switch (plci
->dtmf_cmd
)
9766 case DTMF_LISTEN_TONE_START
:
9768 case DTMF_LISTEN_MF_START
:
9771 case DTMF_LISTEN_START
:
9772 switch (internal_command
)
9775 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
|
9776 B1_FACILITY_DTMFR
), DTMF_COMMAND_1
);
9777 case DTMF_COMMAND_1
:
9778 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
9780 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9781 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9782 Info
= _FACILITY_NOT_SUPPORTED
;
9785 if (plci
->internal_command
)
9787 case DTMF_COMMAND_2
:
9788 if (plci_nl_busy(plci
))
9790 plci
->internal_command
= DTMF_COMMAND_2
;
9793 plci
->internal_command
= DTMF_COMMAND_3
;
9794 dtmf_enable_receiver(plci
, (byte
)(plci
->dtmf_rec_active
| mask
));
9796 case DTMF_COMMAND_3
:
9797 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
9799 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9800 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
9801 Info
= _FACILITY_NOT_SUPPORTED
;
9805 plci
->tone_last_indication_code
= DTMF_SIGNAL_NO_TONE
;
9807 plci
->dtmf_rec_active
|= mask
;
9813 case DTMF_LISTEN_TONE_STOP
:
9815 case DTMF_LISTEN_MF_STOP
:
9818 case DTMF_LISTEN_STOP
:
9819 switch (internal_command
)
9822 plci
->dtmf_rec_active
&= ~mask
;
9823 if (plci
->dtmf_rec_active
)
9826 case DTMF_COMMAND_1:
9827 if (plci->dtmf_rec_active)
9829 if (plci_nl_busy (plci))
9831 plci->internal_command = DTMF_COMMAND_1;
9834 plci->dtmf_rec_active &= ~mask;
9835 plci->internal_command = DTMF_COMMAND_2;
9836 dtmf_enable_receiver (plci, false);
9840 case DTMF_COMMAND_2:
9841 if ((Rc != OK) && (Rc != OK_FC))
9843 dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9844 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9845 Info = _FACILITY_NOT_SUPPORTED;
9849 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
&
9850 ~(B1_FACILITY_DTMFX
| B1_FACILITY_DTMFR
)), DTMF_COMMAND_3
);
9851 case DTMF_COMMAND_3
:
9852 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
9854 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9855 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9856 Info
= _FACILITY_NOT_SUPPORTED
;
9859 if (plci
->internal_command
)
9866 case DTMF_SEND_TONE
:
9871 case DTMF_DIGITS_SEND
:
9872 switch (internal_command
)
9875 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
|
9876 ((plci
->dtmf_parameter_length
!= 0) ? B1_FACILITY_DTMFX
| B1_FACILITY_DTMFR
: B1_FACILITY_DTMFX
)),
9878 case DTMF_COMMAND_1
:
9879 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
9881 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9882 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9883 Info
= _FACILITY_NOT_SUPPORTED
;
9886 if (plci
->internal_command
)
9888 case DTMF_COMMAND_2
:
9889 if (plci_nl_busy(plci
))
9891 plci
->internal_command
= DTMF_COMMAND_2
;
9894 plci
->dtmf_msg_number_queue
[(plci
->dtmf_send_requests
)++] = plci
->number
;
9895 plci
->internal_command
= DTMF_COMMAND_3
;
9896 dtmf_send_digits(plci
, &plci
->saved_msg
.parms
[3].info
[1], plci
->saved_msg
.parms
[3].length
);
9898 case DTMF_COMMAND_3
:
9899 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
9901 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9902 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
9903 if (plci
->dtmf_send_requests
!= 0)
9904 (plci
->dtmf_send_requests
)--;
9905 Info
= _FACILITY_NOT_SUPPORTED
;
9912 sendf(plci
->appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, plci
->number
,
9913 "wws", Info
, SELECTOR_DTMF
, result
);
9917 static byte
dtmf_request(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
9922 API_PARSE dtmf_parms
[5];
9925 dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9926 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9930 PUT_WORD(&result
[1], DTMF_SUCCESS
);
9931 if (!(a
->profile
.Global_Options
& GL_DTMF_SUPPORTED
))
9933 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9934 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9935 Info
= _FACILITY_NOT_SUPPORTED
;
9937 else if (api_parse(&msg
[1].info
[1], msg
[1].length
, "w", dtmf_parms
))
9939 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9940 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9941 Info
= _WRONG_MESSAGE_FORMAT
;
9944 else if ((GET_WORD(dtmf_parms
[0].info
) == DTMF_GET_SUPPORTED_DETECT_CODES
)
9945 || (GET_WORD(dtmf_parms
[0].info
) == DTMF_GET_SUPPORTED_SEND_CODES
))
9947 if (!((a
->requested_options_table
[appl
->Id
- 1])
9948 & (1L << PRIVATE_DTMF_TONE
)))
9950 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9951 UnMapId(Id
), (char *)(FILE_
), __LINE__
, GET_WORD(dtmf_parms
[0].info
)));
9952 PUT_WORD(&result
[1], DTMF_UNKNOWN_REQUEST
);
9956 for (i
= 0; i
< 32; i
++)
9958 if (GET_WORD(dtmf_parms
[0].info
) == DTMF_GET_SUPPORTED_DETECT_CODES
)
9960 for (i
= 0; i
< DTMF_DIGIT_MAP_ENTRIES
; i
++)
9962 if (dtmf_digit_map
[i
].listen_mask
!= 0)
9963 result
[4 + (dtmf_digit_map
[i
].character
>> 3)] |= (1 << (dtmf_digit_map
[i
].character
& 0x7));
9968 for (i
= 0; i
< DTMF_DIGIT_MAP_ENTRIES
; i
++)
9970 if (dtmf_digit_map
[i
].send_mask
!= 0)
9971 result
[4 + (dtmf_digit_map
[i
].character
>> 3)] |= (1 << (dtmf_digit_map
[i
].character
& 0x7));
9979 else if (plci
== NULL
)
9981 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9982 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9983 Info
= _WRONG_IDENTIFIER
;
9988 || !plci
->NL
.Id
|| plci
->nl_remove_id
)
9990 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9991 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
9992 Info
= _WRONG_STATE
;
9997 plci
->dtmf_cmd
= GET_WORD(dtmf_parms
[0].info
);
9999 switch (plci
->dtmf_cmd
)
10002 case DTMF_LISTEN_TONE_START
:
10003 case DTMF_LISTEN_TONE_STOP
:
10005 case DTMF_LISTEN_MF_START
:
10006 case DTMF_LISTEN_MF_STOP
:
10008 if (!((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[appl
->Id
- 1])
10009 & (1L << PRIVATE_DTMF_TONE
)))
10011 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10012 UnMapId(Id
), (char *)(FILE_
), __LINE__
, GET_WORD(dtmf_parms
[0].info
)));
10013 PUT_WORD(&result
[1], DTMF_UNKNOWN_REQUEST
);
10017 case DTMF_LISTEN_START
:
10018 case DTMF_LISTEN_STOP
:
10019 if (!(a
->manufacturer_features
& MANUFACTURER_FEATURE_HARDDTMF
)
10020 && !(a
->manufacturer_features
& MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE
))
10022 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10023 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10024 Info
= _FACILITY_NOT_SUPPORTED
;
10027 if (mask
& DTMF_LISTEN_ACTIVE_FLAG
)
10029 if (api_parse(&msg
[1].info
[1], msg
[1].length
, "wwws", dtmf_parms
))
10031 plci
->dtmf_rec_pulse_ms
= 0;
10032 plci
->dtmf_rec_pause_ms
= 0;
10036 plci
->dtmf_rec_pulse_ms
= GET_WORD(dtmf_parms
[1].info
);
10037 plci
->dtmf_rec_pause_ms
= GET_WORD(dtmf_parms
[2].info
);
10040 start_internal_command(Id
, plci
, dtmf_command
);
10044 case DTMF_SEND_TONE
:
10048 if (!((plci
->requested_options_conn
| plci
->requested_options
| plci
->adapter
->requested_options_table
[appl
->Id
- 1])
10049 & (1L << PRIVATE_DTMF_TONE
)))
10051 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10052 UnMapId(Id
), (char *)(FILE_
), __LINE__
, GET_WORD(dtmf_parms
[0].info
)));
10053 PUT_WORD(&result
[1], DTMF_UNKNOWN_REQUEST
);
10057 case DTMF_DIGITS_SEND
:
10058 if (api_parse(&msg
[1].info
[1], msg
[1].length
, "wwws", dtmf_parms
))
10060 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10061 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10062 Info
= _WRONG_MESSAGE_FORMAT
;
10065 if (mask
& DTMF_LISTEN_ACTIVE_FLAG
)
10067 plci
->dtmf_send_pulse_ms
= GET_WORD(dtmf_parms
[1].info
);
10068 plci
->dtmf_send_pause_ms
= GET_WORD(dtmf_parms
[2].info
);
10072 while ((i
< dtmf_parms
[3].length
) && (j
< DTMF_DIGIT_MAP_ENTRIES
))
10075 while ((j
< DTMF_DIGIT_MAP_ENTRIES
)
10076 && ((dtmf_parms
[3].info
[i
+ 1] != dtmf_digit_map
[j
].character
)
10077 || ((dtmf_digit_map
[j
].send_mask
& mask
) == 0)))
10083 if (j
== DTMF_DIGIT_MAP_ENTRIES
)
10085 dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10086 UnMapId(Id
), (char *)(FILE_
), __LINE__
, dtmf_parms
[3].info
[i
]));
10087 PUT_WORD(&result
[1], DTMF_INCORRECT_DIGIT
);
10090 if (plci
->dtmf_send_requests
>= ARRAY_SIZE(plci
->dtmf_msg_number_queue
))
10092 dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10093 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10094 Info
= _WRONG_STATE
;
10097 api_save_msg(dtmf_parms
, "wwws", &plci
->saved_msg
);
10098 start_internal_command(Id
, plci
, dtmf_command
);
10102 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10103 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci
->dtmf_cmd
));
10104 PUT_WORD(&result
[1], DTMF_UNKNOWN_REQUEST
);
10108 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, Number
,
10109 "wws", Info
, SELECTOR_DTMF
, result
);
10114 static void dtmf_confirmation(dword Id
, PLCI
*plci
)
10119 dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10120 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10123 PUT_WORD(&result
[1], DTMF_SUCCESS
);
10124 if (plci
->dtmf_send_requests
!= 0)
10126 sendf(plci
->appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, plci
->dtmf_msg_number_queue
[0],
10127 "wws", GOOD
, SELECTOR_DTMF
, result
);
10128 (plci
->dtmf_send_requests
)--;
10129 for (i
= 0; i
< plci
->dtmf_send_requests
; i
++)
10130 plci
->dtmf_msg_number_queue
[i
] = plci
->dtmf_msg_number_queue
[i
+ 1];
10135 static void dtmf_indication(dword Id
, PLCI
*plci
, byte
*msg
, word length
)
10139 dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10140 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10143 for (i
= 1; i
< length
; i
++)
10146 while ((j
< DTMF_DIGIT_MAP_ENTRIES
)
10147 && ((msg
[i
] != dtmf_digit_map
[j
].code
)
10148 || ((dtmf_digit_map
[j
].listen_mask
& plci
->dtmf_rec_active
) == 0)))
10152 if (j
< DTMF_DIGIT_MAP_ENTRIES
)
10155 if ((dtmf_digit_map
[j
].listen_mask
& DTMF_TONE_LISTEN_ACTIVE_FLAG
)
10156 && (plci
->tone_last_indication_code
== DTMF_SIGNAL_NO_TONE
)
10157 && (dtmf_digit_map
[j
].character
!= DTMF_SIGNAL_UNIDENTIFIED_TONE
))
10161 for (i
= length
; i
> n
+ 1; i
--)
10162 msg
[i
] = msg
[i
- 1];
10166 msg
[++n
] = DTMF_SIGNAL_UNIDENTIFIED_TONE
;
10168 plci
->tone_last_indication_code
= dtmf_digit_map
[j
].character
;
10170 msg
[++n
] = dtmf_digit_map
[j
].character
;
10176 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0, "wS", SELECTOR_DTMF
, msg
);
10181 /*------------------------------------------------------------------*/
10182 /* DTMF parameters */
10183 /*------------------------------------------------------------------*/
10185 static void dtmf_parameter_write(PLCI
*plci
)
10188 byte parameter_buffer
[DTMF_PARAMETER_BUFFER_SIZE
+ 2];
10190 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10191 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10192 (char *)(FILE_
), __LINE__
));
10194 parameter_buffer
[0] = plci
->dtmf_parameter_length
+ 1;
10195 parameter_buffer
[1] = DSP_CTRL_SET_DTMF_PARAMETERS
;
10196 for (i
= 0; i
< plci
->dtmf_parameter_length
; i
++)
10197 parameter_buffer
[2 + i
] = plci
->dtmf_parameter_buffer
[i
];
10198 add_p(plci
, FTY
, parameter_buffer
);
10199 sig_req(plci
, TEL_CTRL
, 0);
10204 static void dtmf_parameter_clear_config(PLCI
*plci
)
10207 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10208 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10209 (char *)(FILE_
), __LINE__
));
10211 plci
->dtmf_parameter_length
= 0;
10215 static void dtmf_parameter_prepare_switch(dword Id
, PLCI
*plci
)
10218 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10219 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10224 static word
dtmf_parameter_save_config(dword Id
, PLCI
*plci
, byte Rc
)
10227 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10228 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
10234 static word
dtmf_parameter_restore_config(dword Id
, PLCI
*plci
, byte Rc
)
10238 dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10239 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
10242 if ((plci
->B1_facilities
& B1_FACILITY_DTMFR
)
10243 && (plci
->dtmf_parameter_length
!= 0))
10245 switch (plci
->adjust_b_state
)
10247 case ADJUST_B_RESTORE_DTMF_PARAMETER_1
:
10248 plci
->internal_command
= plci
->adjust_b_command
;
10251 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_PARAMETER_1
;
10254 dtmf_parameter_write(plci
);
10255 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_PARAMETER_2
;
10257 case ADJUST_B_RESTORE_DTMF_PARAMETER_2
:
10258 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
10260 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10261 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
10262 Info
= _WRONG_STATE
;
10272 /*------------------------------------------------------------------*/
10273 /* Line interconnect facilities */
10274 /*------------------------------------------------------------------*/
10277 LI_CONFIG
*li_config_table
;
10278 word li_total_channels
;
10281 /*------------------------------------------------------------------*/
10282 /* translate a CHI information element to a channel number */
10283 /* returns 0xff - any channel */
10284 /* 0xfe - chi wrong coding */
10285 /* 0xfd - D-channel */
10286 /* 0x00 - no channel */
10287 /* else channel number / PRI: timeslot */
10288 /* if channels is provided we accept more than one channel. */
10289 /*------------------------------------------------------------------*/
10291 static byte
chi_to_channel(byte
*chi
, dword
*pchannelmap
)
10300 if (pchannelmap
) *pchannelmap
= 0;
10301 if (!chi
[0]) return 0xff;
10304 if (chi
[1] & 0x20) {
10305 if (chi
[0] == 1 && chi
[1] == 0xac) return 0xfd; /* exclusive d-channel */
10306 for (i
= 1; i
< chi
[0] && !(chi
[i
] & 0x80); i
++);
10307 if (i
== chi
[0] || !(chi
[i
] & 0x80)) return 0xfe;
10308 if ((chi
[1] | 0xc8) != 0xe9) return 0xfe;
10309 if (chi
[1] & 0x08) excl
= 0x40;
10311 /* int. id present */
10312 if (chi
[1] & 0x40) {
10314 for (i
= p
; i
< chi
[0] && !(chi
[i
] & 0x80); i
++);
10315 if (i
== chi
[0] || !(chi
[i
] & 0x80)) return 0xfe;
10318 /* coding standard, Number/Map, Channel Type */
10320 for (i
= p
; i
< chi
[0] && !(chi
[i
] & 0x80); i
++);
10321 if (i
== chi
[0] || !(chi
[i
] & 0x80)) return 0xfe;
10322 if ((chi
[p
] | 0xd0) != 0xd3) return 0xfe;
10325 if (chi
[p
] & 0x10) {
10328 if ((chi
[0] - p
) == 4) ofs
= 0;
10329 else if ((chi
[0] - p
) == 3) ofs
= 1;
10333 for (i
= 0; i
< 4 && p
< chi
[0]; i
++) {
10338 for (ch
= 0; !(chi
[p
] & (1 << ch
)); ch
++);
10349 ch
= chi
[p
] & 0x3f;
10351 if ((byte
)(chi
[0] - p
) > 30) return 0xfe;
10353 for (i
= p
; i
<= chi
[0]; i
++) {
10354 if ((chi
[i
] & 0x7f) > 31) return 0xfe;
10355 map
|= (1L << (chi
[i
] & 0x7f));
10359 if (p
!= chi
[0]) return 0xfe;
10360 if (ch
> 31) return 0xfe;
10363 if (chi
[p
] & 0x40) return 0xfe;
10365 if (pchannelmap
) *pchannelmap
= map
;
10366 else if (map
!= ((dword
)(1L << ch
))) return 0xfe;
10367 return (byte
)(excl
| ch
);
10369 else { /* not PRI */
10370 for (i
= 1; i
< chi
[0] && !(chi
[i
] & 0x80); i
++);
10371 if (i
!= chi
[0] || !(chi
[i
] & 0x80)) return 0xfe;
10372 if (chi
[1] & 0x08) excl
= 0x40;
10374 switch (chi
[1] | 0x98) {
10375 case 0x98: return 0;
10377 if (pchannelmap
) *pchannelmap
= 2;
10380 if (pchannelmap
) *pchannelmap
= 4;
10382 case 0x9b: return 0xff;
10383 case 0x9c: return 0xfd; /* d-ch */
10384 default: return 0xfe;
10390 static void mixer_set_bchannel_id_esc(PLCI
*plci
, byte bchannel_id
)
10392 DIVA_CAPI_ADAPTER
*a
;
10397 old_id
= plci
->li_bchannel_id
;
10400 if ((old_id
!= 0) && (li_config_table
[a
->li_base
+ (old_id
- 1)].plci
== plci
))
10401 li_config_table
[a
->li_base
+ (old_id
- 1)].plci
= NULL
;
10402 plci
->li_bchannel_id
= (bchannel_id
& 0x1f) + 1;
10403 if (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== NULL
)
10404 li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
= plci
;
10408 if (((bchannel_id
& 0x03) == 1) || ((bchannel_id
& 0x03) == 2))
10410 if ((old_id
!= 0) && (li_config_table
[a
->li_base
+ (old_id
- 1)].plci
== plci
))
10411 li_config_table
[a
->li_base
+ (old_id
- 1)].plci
= NULL
;
10412 plci
->li_bchannel_id
= bchannel_id
& 0x03;
10413 if ((a
->AdvSignalPLCI
!= NULL
) && (a
->AdvSignalPLCI
!= plci
) && (a
->AdvSignalPLCI
->tel
== ADV_VOICE
))
10415 splci
= a
->AdvSignalPLCI
;
10416 if (li_config_table
[a
->li_base
+ (2 - plci
->li_bchannel_id
)].plci
== NULL
)
10418 if ((splci
->li_bchannel_id
!= 0)
10419 && (li_config_table
[a
->li_base
+ (splci
->li_bchannel_id
- 1)].plci
== splci
))
10421 li_config_table
[a
->li_base
+ (splci
->li_bchannel_id
- 1)].plci
= NULL
;
10423 splci
->li_bchannel_id
= 3 - plci
->li_bchannel_id
;
10424 li_config_table
[a
->li_base
+ (2 - plci
->li_bchannel_id
)].plci
= splci
;
10425 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10426 (dword
)((splci
->Id
<< 8) | UnMapController(splci
->adapter
->Id
)),
10427 (char *)(FILE_
), __LINE__
, splci
->li_bchannel_id
));
10430 if (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== NULL
)
10431 li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
= plci
;
10434 if ((old_id
== 0) && (plci
->li_bchannel_id
!= 0)
10435 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
10437 mixer_clear_config(plci
);
10439 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10440 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10441 (char *)(FILE_
), __LINE__
, bchannel_id
, plci
->li_bchannel_id
));
10445 static void mixer_set_bchannel_id(PLCI
*plci
, byte
*chi
)
10447 DIVA_CAPI_ADAPTER
*a
;
10452 old_id
= plci
->li_bchannel_id
;
10453 ch
= chi_to_channel(chi
, NULL
);
10458 if ((old_id
!= 0) && (li_config_table
[a
->li_base
+ (old_id
- 1)].plci
== plci
))
10459 li_config_table
[a
->li_base
+ (old_id
- 1)].plci
= NULL
;
10460 plci
->li_bchannel_id
= (ch
& 0x1f) + 1;
10461 if (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== NULL
)
10462 li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
= plci
;
10466 if (((ch
& 0x1f) == 1) || ((ch
& 0x1f) == 2))
10468 if ((old_id
!= 0) && (li_config_table
[a
->li_base
+ (old_id
- 1)].plci
== plci
))
10469 li_config_table
[a
->li_base
+ (old_id
- 1)].plci
= NULL
;
10470 plci
->li_bchannel_id
= ch
& 0x1f;
10471 if ((a
->AdvSignalPLCI
!= NULL
) && (a
->AdvSignalPLCI
!= plci
) && (a
->AdvSignalPLCI
->tel
== ADV_VOICE
))
10473 splci
= a
->AdvSignalPLCI
;
10474 if (li_config_table
[a
->li_base
+ (2 - plci
->li_bchannel_id
)].plci
== NULL
)
10476 if ((splci
->li_bchannel_id
!= 0)
10477 && (li_config_table
[a
->li_base
+ (splci
->li_bchannel_id
- 1)].plci
== splci
))
10479 li_config_table
[a
->li_base
+ (splci
->li_bchannel_id
- 1)].plci
= NULL
;
10481 splci
->li_bchannel_id
= 3 - plci
->li_bchannel_id
;
10482 li_config_table
[a
->li_base
+ (2 - plci
->li_bchannel_id
)].plci
= splci
;
10483 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10484 (dword
)((splci
->Id
<< 8) | UnMapController(splci
->adapter
->Id
)),
10485 (char *)(FILE_
), __LINE__
, splci
->li_bchannel_id
));
10488 if (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== NULL
)
10489 li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
= plci
;
10493 if ((old_id
== 0) && (plci
->li_bchannel_id
!= 0)
10494 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
10496 mixer_clear_config(plci
);
10498 dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10499 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10500 (char *)(FILE_
), __LINE__
, ch
, plci
->li_bchannel_id
));
10504 #define MIXER_MAX_DUMP_CHANNELS 34
10506 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER
*a
)
10510 char hex_line
[2 * MIXER_MAX_DUMP_CHANNELS
+ MIXER_MAX_DUMP_CHANNELS
/ 8 + 4];
10512 dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10513 (dword
)(UnMapController(a
->Id
)), (char *)(FILE_
), __LINE__
));
10515 for (i
= 0; i
< li_total_channels
; i
++)
10517 li_config_table
[i
].channel
&= LI_CHANNEL_ADDRESSES_SET
;
10518 if (li_config_table
[i
].chflags
!= 0)
10519 li_config_table
[i
].channel
|= LI_CHANNEL_INVOLVED
;
10522 for (j
= 0; j
< li_total_channels
; j
++)
10524 if (((li_config_table
[i
].flag_table
[j
]) != 0)
10525 || ((li_config_table
[j
].flag_table
[i
]) != 0))
10527 li_config_table
[i
].channel
|= LI_CHANNEL_INVOLVED
;
10529 if (((li_config_table
[i
].flag_table
[j
] & LI_FLAG_CONFERENCE
) != 0)
10530 || ((li_config_table
[j
].flag_table
[i
] & LI_FLAG_CONFERENCE
) != 0))
10532 li_config_table
[i
].channel
|= LI_CHANNEL_CONFERENCE
;
10537 for (i
= 0; i
< li_total_channels
; i
++)
10539 for (j
= 0; j
< li_total_channels
; j
++)
10541 li_config_table
[i
].coef_table
[j
] &= ~(LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
);
10542 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_CONFERENCE
)
10543 li_config_table
[i
].coef_table
[j
] |= LI_COEF_CH_CH
;
10546 for (n
= 0; n
< li_total_channels
; n
++)
10548 if (li_config_table
[n
].channel
& LI_CHANNEL_CONFERENCE
)
10550 for (i
= 0; i
< li_total_channels
; i
++)
10552 if (li_config_table
[i
].channel
& LI_CHANNEL_CONFERENCE
)
10554 for (j
= 0; j
< li_total_channels
; j
++)
10556 li_config_table
[i
].coef_table
[j
] |=
10557 li_config_table
[i
].coef_table
[n
] & li_config_table
[n
].coef_table
[j
];
10563 for (i
= 0; i
< li_total_channels
; i
++)
10565 if (li_config_table
[i
].channel
& LI_CHANNEL_INVOLVED
)
10567 li_config_table
[i
].coef_table
[i
] &= ~LI_COEF_CH_CH
;
10568 for (j
= 0; j
< li_total_channels
; j
++)
10570 if (li_config_table
[i
].coef_table
[j
] & LI_COEF_CH_CH
)
10571 li_config_table
[i
].flag_table
[j
] |= LI_FLAG_CONFERENCE
;
10573 if (li_config_table
[i
].flag_table
[i
] & LI_FLAG_CONFERENCE
)
10574 li_config_table
[i
].coef_table
[i
] |= LI_COEF_CH_CH
;
10577 for (i
= 0; i
< li_total_channels
; i
++)
10579 if (li_config_table
[i
].channel
& LI_CHANNEL_INVOLVED
)
10581 for (j
= 0; j
< li_total_channels
; j
++)
10583 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_INTERCONNECT
)
10584 li_config_table
[i
].coef_table
[j
] |= LI_COEF_CH_CH
;
10585 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_MONITOR
)
10586 li_config_table
[i
].coef_table
[j
] |= LI_COEF_CH_PC
;
10587 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_MIX
)
10588 li_config_table
[i
].coef_table
[j
] |= LI_COEF_PC_CH
;
10589 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_PCCONNECT
)
10590 li_config_table
[i
].coef_table
[j
] |= LI_COEF_PC_PC
;
10592 if (li_config_table
[i
].chflags
& LI_CHFLAG_MONITOR
)
10594 for (j
= 0; j
< li_total_channels
; j
++)
10596 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_INTERCONNECT
)
10598 li_config_table
[i
].coef_table
[j
] |= LI_COEF_CH_PC
;
10599 if (li_config_table
[j
].chflags
& LI_CHFLAG_MIX
)
10600 li_config_table
[i
].coef_table
[j
] |= LI_COEF_PC_CH
| LI_COEF_PC_PC
;
10604 if (li_config_table
[i
].chflags
& LI_CHFLAG_MIX
)
10606 for (j
= 0; j
< li_total_channels
; j
++)
10608 if (li_config_table
[j
].flag_table
[i
] & LI_FLAG_INTERCONNECT
)
10609 li_config_table
[j
].coef_table
[i
] |= LI_COEF_PC_CH
;
10612 if (li_config_table
[i
].chflags
& LI_CHFLAG_LOOP
)
10614 for (j
= 0; j
< li_total_channels
; j
++)
10616 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_INTERCONNECT
)
10618 for (n
= 0; n
< li_total_channels
; n
++)
10620 if (li_config_table
[n
].flag_table
[i
] & LI_FLAG_INTERCONNECT
)
10622 li_config_table
[n
].coef_table
[j
] |= LI_COEF_CH_CH
;
10623 if (li_config_table
[j
].chflags
& LI_CHFLAG_MIX
)
10625 li_config_table
[n
].coef_table
[j
] |= LI_COEF_PC_CH
;
10626 if (li_config_table
[n
].chflags
& LI_CHFLAG_MONITOR
)
10627 li_config_table
[n
].coef_table
[j
] |= LI_COEF_CH_PC
| LI_COEF_PC_PC
;
10629 else if (li_config_table
[n
].chflags
& LI_CHFLAG_MONITOR
)
10630 li_config_table
[n
].coef_table
[j
] |= LI_COEF_CH_PC
;
10638 for (i
= 0; i
< li_total_channels
; i
++)
10640 if (li_config_table
[i
].channel
& LI_CHANNEL_INVOLVED
)
10642 if (li_config_table
[i
].chflags
& (LI_CHFLAG_MONITOR
| LI_CHFLAG_MIX
| LI_CHFLAG_LOOP
))
10643 li_config_table
[i
].channel
|= LI_CHANNEL_ACTIVE
;
10644 if (li_config_table
[i
].chflags
& LI_CHFLAG_MONITOR
)
10645 li_config_table
[i
].channel
|= LI_CHANNEL_RX_DATA
;
10646 if (li_config_table
[i
].chflags
& LI_CHFLAG_MIX
)
10647 li_config_table
[i
].channel
|= LI_CHANNEL_TX_DATA
;
10648 for (j
= 0; j
< li_total_channels
; j
++)
10650 if ((li_config_table
[i
].flag_table
[j
] &
10651 (LI_FLAG_INTERCONNECT
| LI_FLAG_PCCONNECT
| LI_FLAG_CONFERENCE
| LI_FLAG_MONITOR
))
10652 || (li_config_table
[j
].flag_table
[i
] &
10653 (LI_FLAG_INTERCONNECT
| LI_FLAG_PCCONNECT
| LI_FLAG_CONFERENCE
| LI_FLAG_ANNOUNCEMENT
| LI_FLAG_MIX
)))
10655 li_config_table
[i
].channel
|= LI_CHANNEL_ACTIVE
;
10657 if (li_config_table
[i
].flag_table
[j
] & (LI_FLAG_PCCONNECT
| LI_FLAG_MONITOR
))
10658 li_config_table
[i
].channel
|= LI_CHANNEL_RX_DATA
;
10659 if (li_config_table
[j
].flag_table
[i
] & (LI_FLAG_PCCONNECT
| LI_FLAG_ANNOUNCEMENT
| LI_FLAG_MIX
))
10660 li_config_table
[i
].channel
|= LI_CHANNEL_TX_DATA
;
10662 if (!(li_config_table
[i
].channel
& LI_CHANNEL_ACTIVE
))
10664 li_config_table
[i
].coef_table
[i
] |= LI_COEF_PC_CH
| LI_COEF_CH_PC
;
10665 li_config_table
[i
].channel
|= LI_CHANNEL_TX_DATA
| LI_CHANNEL_RX_DATA
;
10669 for (i
= 0; i
< li_total_channels
; i
++)
10671 if (li_config_table
[i
].channel
& LI_CHANNEL_INVOLVED
)
10674 while ((j
< li_total_channels
) && !(li_config_table
[i
].flag_table
[j
] & LI_FLAG_ANNOUNCEMENT
))
10676 if (j
< li_total_channels
)
10678 for (j
= 0; j
< li_total_channels
; j
++)
10680 li_config_table
[i
].coef_table
[j
] &= ~(LI_COEF_CH_CH
| LI_COEF_PC_CH
);
10681 if (li_config_table
[i
].flag_table
[j
] & LI_FLAG_ANNOUNCEMENT
)
10682 li_config_table
[i
].coef_table
[j
] |= LI_COEF_PC_CH
;
10687 n
= li_total_channels
;
10688 if (n
> MIXER_MAX_DUMP_CHANNELS
)
10689 n
= MIXER_MAX_DUMP_CHANNELS
;
10692 for (j
= 0; j
< n
; j
++)
10694 if ((j
& 0x7) == 0)
10696 p
= hex_byte_pack(p
, li_config_table
[j
].curchnl
);
10699 dbug(1, dprintf("[%06lx] CURRENT %s",
10700 (dword
)(UnMapController(a
->Id
)), (char *)hex_line
));
10702 for (j
= 0; j
< n
; j
++)
10704 if ((j
& 0x7) == 0)
10706 p
= hex_byte_pack(p
, li_config_table
[j
].channel
);
10709 dbug(1, dprintf("[%06lx] CHANNEL %s",
10710 (dword
)(UnMapController(a
->Id
)), (char *)hex_line
));
10712 for (j
= 0; j
< n
; j
++)
10714 if ((j
& 0x7) == 0)
10716 p
= hex_byte_pack(p
, li_config_table
[j
].chflags
);
10719 dbug(1, dprintf("[%06lx] CHFLAG %s",
10720 (dword
)(UnMapController(a
->Id
)), (char *)hex_line
));
10721 for (i
= 0; i
< n
; i
++)
10724 for (j
= 0; j
< n
; j
++)
10726 if ((j
& 0x7) == 0)
10728 p
= hex_byte_pack(p
, li_config_table
[i
].flag_table
[j
]);
10731 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10732 (dword
)(UnMapController(a
->Id
)), i
, (char *)hex_line
));
10734 for (i
= 0; i
< n
; i
++)
10737 for (j
= 0; j
< n
; j
++)
10739 if ((j
& 0x7) == 0)
10741 p
= hex_byte_pack(p
, li_config_table
[i
].coef_table
[j
]);
10744 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10745 (dword
)(UnMapController(a
->Id
)), i
, (char *)hex_line
));
10754 } mixer_write_prog_pri
[] =
10756 { LI_COEF_CH_CH
, 0 },
10757 { LI_COEF_CH_PC
, MIXER_COEF_LINE_TO_PC_FLAG
},
10758 { LI_COEF_PC_CH
, MIXER_COEF_LINE_FROM_PC_FLAG
},
10759 { LI_COEF_PC_PC
, MIXER_COEF_LINE_TO_PC_FLAG
| MIXER_COEF_LINE_FROM_PC_FLAG
}
10767 byte xconnect_override
;
10768 } mixer_write_prog_bri
[] =
10770 { 0, 0, LI_COEF_CH_CH
, 0x01 }, /* B to B */
10771 { 1, 0, LI_COEF_CH_CH
, 0x01 }, /* Alt B to B */
10772 { 0, 0, LI_COEF_PC_CH
, 0x80 }, /* PC to B */
10773 { 1, 0, LI_COEF_PC_CH
, 0x01 }, /* Alt PC to B */
10774 { 2, 0, LI_COEF_CH_CH
, 0x00 }, /* IC to B */
10775 { 3, 0, LI_COEF_CH_CH
, 0x00 }, /* Alt IC to B */
10776 { 0, 0, LI_COEF_CH_PC
, 0x80 }, /* B to PC */
10777 { 1, 0, LI_COEF_CH_PC
, 0x01 }, /* Alt B to PC */
10778 { 0, 0, LI_COEF_PC_PC
, 0x01 }, /* PC to PC */
10779 { 1, 0, LI_COEF_PC_PC
, 0x01 }, /* Alt PC to PC */
10780 { 2, 0, LI_COEF_CH_PC
, 0x00 }, /* IC to PC */
10781 { 3, 0, LI_COEF_CH_PC
, 0x00 }, /* Alt IC to PC */
10782 { 0, 2, LI_COEF_CH_CH
, 0x00 }, /* B to IC */
10783 { 1, 2, LI_COEF_CH_CH
, 0x00 }, /* Alt B to IC */
10784 { 0, 2, LI_COEF_PC_CH
, 0x00 }, /* PC to IC */
10785 { 1, 2, LI_COEF_PC_CH
, 0x00 }, /* Alt PC to IC */
10786 { 2, 2, LI_COEF_CH_CH
, 0x00 }, /* IC to IC */
10787 { 3, 2, LI_COEF_CH_CH
, 0x00 }, /* Alt IC to IC */
10788 { 1, 1, LI_COEF_CH_CH
, 0x01 }, /* Alt B to Alt B */
10789 { 0, 1, LI_COEF_CH_CH
, 0x01 }, /* B to Alt B */
10790 { 1, 1, LI_COEF_PC_CH
, 0x80 }, /* Alt PC to Alt B */
10791 { 0, 1, LI_COEF_PC_CH
, 0x01 }, /* PC to Alt B */
10792 { 3, 1, LI_COEF_CH_CH
, 0x00 }, /* Alt IC to Alt B */
10793 { 2, 1, LI_COEF_CH_CH
, 0x00 }, /* IC to Alt B */
10794 { 1, 1, LI_COEF_CH_PC
, 0x80 }, /* Alt B to Alt PC */
10795 { 0, 1, LI_COEF_CH_PC
, 0x01 }, /* B to Alt PC */
10796 { 1, 1, LI_COEF_PC_PC
, 0x01 }, /* Alt PC to Alt PC */
10797 { 0, 1, LI_COEF_PC_PC
, 0x01 }, /* PC to Alt PC */
10798 { 3, 1, LI_COEF_CH_PC
, 0x00 }, /* Alt IC to Alt PC */
10799 { 2, 1, LI_COEF_CH_PC
, 0x00 }, /* IC to Alt PC */
10800 { 1, 3, LI_COEF_CH_CH
, 0x00 }, /* Alt B to Alt IC */
10801 { 0, 3, LI_COEF_CH_CH
, 0x00 }, /* B to Alt IC */
10802 { 1, 3, LI_COEF_PC_CH
, 0x00 }, /* Alt PC to Alt IC */
10803 { 0, 3, LI_COEF_PC_CH
, 0x00 }, /* PC to Alt IC */
10804 { 3, 3, LI_COEF_CH_CH
, 0x00 }, /* Alt IC to Alt IC */
10805 { 2, 3, LI_COEF_CH_CH
, 0x00 } /* IC to Alt IC */
10808 static byte mixer_swapped_index_bri
[] =
10811 19, /* Alt B to B */
10813 21, /* Alt PC to B */
10815 23, /* Alt IC to B */
10817 25, /* Alt B to PC */
10819 27, /* Alt PC to PC */
10821 29, /* Alt IC to PC */
10823 31, /* Alt B to IC */
10825 33, /* Alt PC to IC */
10827 35, /* Alt IC to IC */
10828 0, /* Alt B to Alt B */
10829 1, /* B to Alt B */
10830 2, /* Alt PC to Alt B */
10831 3, /* PC to Alt B */
10832 4, /* Alt IC to Alt B */
10833 5, /* IC to Alt B */
10834 6, /* Alt B to Alt PC */
10835 7, /* B to Alt PC */
10836 8, /* Alt PC to Alt PC */
10837 9, /* PC to Alt PC */
10838 10, /* Alt IC to Alt PC */
10839 11, /* IC to Alt PC */
10840 12, /* Alt B to Alt IC */
10841 13, /* B to Alt IC */
10842 14, /* Alt PC to Alt IC */
10843 15, /* PC to Alt IC */
10844 16, /* Alt IC to Alt IC */
10845 17 /* IC to Alt IC */
10853 } xconnect_write_prog
[] =
10855 { LI_COEF_CH_CH
, false, false },
10856 { LI_COEF_CH_PC
, false, true },
10857 { LI_COEF_PC_CH
, true, false },
10858 { LI_COEF_PC_PC
, true, true }
10862 static void xconnect_query_addresses(PLCI
*plci
)
10864 DIVA_CAPI_ADAPTER
*a
;
10868 dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10869 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10870 (char *)(FILE_
), __LINE__
));
10873 if (a
->li_pri
&& ((plci
->li_bchannel_id
== 0)
10874 || (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
!= plci
)))
10876 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10877 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10878 (char *)(FILE_
), __LINE__
));
10881 p
= plci
->internal_req_buffer
;
10882 ch
= (a
->li_pri
) ? plci
->li_bchannel_id
- 1 : 0;
10883 *(p
++) = UDATA_REQUEST_XCONNECT_FROM
;
10886 *(p
++) = (byte
)(w
>> 8);
10887 w
= ch
| XCONNECT_CHANNEL_PORT_PC
;
10889 *(p
++) = (byte
)(w
>> 8);
10890 plci
->NData
[0].P
= plci
->internal_req_buffer
;
10891 plci
->NData
[0].PLength
= p
- plci
->internal_req_buffer
;
10892 plci
->NL
.X
= plci
->NData
;
10893 plci
->NL
.ReqCh
= 0;
10894 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_UDATA
;
10895 plci
->adapter
->request(&plci
->NL
);
10899 static void xconnect_write_coefs(PLCI
*plci
, word internal_command
)
10902 dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10903 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
10904 (char *)(FILE_
), __LINE__
, internal_command
));
10906 plci
->li_write_command
= internal_command
;
10907 plci
->li_write_channel
= 0;
10911 static byte
xconnect_write_coefs_process(dword Id
, PLCI
*plci
, byte Rc
)
10913 DIVA_CAPI_ADAPTER
*a
;
10914 word w
, n
, i
, j
, r
, s
, to_ch
;
10917 struct xconnect_transfer_address_s
*transfer_address
;
10918 byte ch_map
[MIXER_CHANNELS_BRI
];
10920 dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10921 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->li_write_channel
));
10924 if ((plci
->li_bchannel_id
== 0)
10925 || (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
!= plci
))
10927 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10928 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
10931 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
10932 j
= plci
->li_write_channel
;
10933 p
= plci
->internal_req_buffer
;
10936 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
10938 dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10939 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
10943 if (li_config_table
[i
].adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
10947 if (j
< li_total_channels
)
10949 if (li_config_table
[i
].channel
& LI_CHANNEL_ADDRESSES_SET
)
10951 s
= ((li_config_table
[i
].send_b
.card_address
.low
| li_config_table
[i
].send_b
.card_address
.high
) ?
10952 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_CH_PC
| LI_COEF_PC_PC
)) &
10953 ((li_config_table
[i
].send_pc
.card_address
.low
| li_config_table
[i
].send_pc
.card_address
.high
) ?
10954 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_CH_CH
| LI_COEF_PC_CH
));
10956 r
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
10957 while ((j
< li_total_channels
)
10959 || (!(li_config_table
[j
].channel
& LI_CHANNEL_ADDRESSES_SET
))
10960 || (!li_config_table
[j
].adapter
->li_pri
10961 && (j
>= li_config_table
[j
].adapter
->li_base
+ MIXER_BCHANNELS_BRI
))
10962 || (((li_config_table
[j
].send_b
.card_address
.low
!= li_config_table
[i
].send_b
.card_address
.low
)
10963 || (li_config_table
[j
].send_b
.card_address
.high
!= li_config_table
[i
].send_b
.card_address
.high
))
10964 && (!(a
->manufacturer_features
& MANUFACTURER_FEATURE_DMACONNECT
)
10965 || !(li_config_table
[j
].adapter
->manufacturer_features
& MANUFACTURER_FEATURE_DMACONNECT
)))
10966 || ((li_config_table
[j
].adapter
->li_base
!= a
->li_base
)
10968 ((li_config_table
[j
].send_b
.card_address
.low
| li_config_table
[j
].send_b
.card_address
.high
) ?
10969 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_PC_CH
| LI_COEF_PC_PC
)) &
10970 ((li_config_table
[j
].send_pc
.card_address
.low
| li_config_table
[j
].send_pc
.card_address
.high
) ?
10971 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_CH_CH
| LI_COEF_CH_PC
))))))
10974 if (j
< li_total_channels
)
10975 r
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
10978 if (j
< li_total_channels
)
10980 plci
->internal_command
= plci
->li_write_command
;
10981 if (plci_nl_busy(plci
))
10983 to_ch
= (a
->li_pri
) ? plci
->li_bchannel_id
- 1 : 0;
10984 *(p
++) = UDATA_REQUEST_XCONNECT_TO
;
10987 if (li_config_table
[j
].adapter
->li_base
!= a
->li_base
)
10990 ((li_config_table
[j
].send_b
.card_address
.low
| li_config_table
[j
].send_b
.card_address
.high
) ?
10991 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_PC_CH
| LI_COEF_PC_PC
)) &
10992 ((li_config_table
[j
].send_pc
.card_address
.low
| li_config_table
[j
].send_pc
.card_address
.high
) ?
10993 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_CH_CH
| LI_COEF_CH_PC
));
10998 if (r
& xconnect_write_prog
[n
].mask
)
11000 if (xconnect_write_prog
[n
].from_pc
)
11001 transfer_address
= &(li_config_table
[j
].send_pc
);
11003 transfer_address
= &(li_config_table
[j
].send_b
);
11004 d
= transfer_address
->card_address
.low
;
11006 *(p
++) = (byte
)(d
>> 8);
11007 *(p
++) = (byte
)(d
>> 16);
11008 *(p
++) = (byte
)(d
>> 24);
11009 d
= transfer_address
->card_address
.high
;
11011 *(p
++) = (byte
)(d
>> 8);
11012 *(p
++) = (byte
)(d
>> 16);
11013 *(p
++) = (byte
)(d
>> 24);
11014 d
= transfer_address
->offset
;
11016 *(p
++) = (byte
)(d
>> 8);
11017 *(p
++) = (byte
)(d
>> 16);
11018 *(p
++) = (byte
)(d
>> 24);
11019 w
= xconnect_write_prog
[n
].to_pc
? to_ch
| XCONNECT_CHANNEL_PORT_PC
: to_ch
;
11021 *(p
++) = (byte
)(w
>> 8);
11022 w
= ((li_config_table
[i
].coef_table
[j
] & xconnect_write_prog
[n
].mask
) == 0) ? 0x01 :
11023 (li_config_table
[i
].adapter
->u_law
?
11024 (li_config_table
[j
].adapter
->u_law
? 0x80 : 0x86) :
11025 (li_config_table
[j
].adapter
->u_law
? 0x7a : 0x80));
11028 li_config_table
[i
].coef_table
[j
] ^= xconnect_write_prog
[n
].mask
<< 4;
11031 } while ((n
< ARRAY_SIZE(xconnect_write_prog
))
11032 && ((p
- plci
->internal_req_buffer
) + 16 < INTERNAL_REQ_BUFFER_SIZE
));
11033 if (n
== ARRAY_SIZE(xconnect_write_prog
))
11038 if (j
< li_total_channels
)
11039 r
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
11040 } while ((j
< li_total_channels
)
11042 || (!(li_config_table
[j
].channel
& LI_CHANNEL_ADDRESSES_SET
))
11043 || (!li_config_table
[j
].adapter
->li_pri
11044 && (j
>= li_config_table
[j
].adapter
->li_base
+ MIXER_BCHANNELS_BRI
))
11045 || (((li_config_table
[j
].send_b
.card_address
.low
!= li_config_table
[i
].send_b
.card_address
.low
)
11046 || (li_config_table
[j
].send_b
.card_address
.high
!= li_config_table
[i
].send_b
.card_address
.high
))
11047 && (!(a
->manufacturer_features
& MANUFACTURER_FEATURE_DMACONNECT
)
11048 || !(li_config_table
[j
].adapter
->manufacturer_features
& MANUFACTURER_FEATURE_DMACONNECT
)))
11049 || ((li_config_table
[j
].adapter
->li_base
!= a
->li_base
)
11051 ((li_config_table
[j
].send_b
.card_address
.low
| li_config_table
[j
].send_b
.card_address
.high
) ?
11052 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_PC_CH
| LI_COEF_PC_PC
)) &
11053 ((li_config_table
[j
].send_pc
.card_address
.low
| li_config_table
[j
].send_pc
.card_address
.high
) ?
11054 (LI_COEF_CH_CH
| LI_COEF_CH_PC
| LI_COEF_PC_CH
| LI_COEF_PC_PC
) : (LI_COEF_CH_CH
| LI_COEF_CH_PC
))))));
11056 } while ((j
< li_total_channels
)
11057 && ((p
- plci
->internal_req_buffer
) + 16 < INTERNAL_REQ_BUFFER_SIZE
));
11059 else if (j
== li_total_channels
)
11061 plci
->internal_command
= plci
->li_write_command
;
11062 if (plci_nl_busy(plci
))
11066 *(p
++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC
;
11068 if (li_config_table
[i
].channel
& LI_CHANNEL_TX_DATA
)
11069 w
|= MIXER_FEATURE_ENABLE_TX_DATA
;
11070 if (li_config_table
[i
].channel
& LI_CHANNEL_RX_DATA
)
11071 w
|= MIXER_FEATURE_ENABLE_RX_DATA
;
11073 *(p
++) = (byte
)(w
>> 8);
11077 *(p
++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI
;
11079 if ((plci
->tel
== ADV_VOICE
) && (plci
== a
->AdvSignalPLCI
)
11080 && (ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) <= a
->adv_voice_coef_length
))
11082 w
= GET_WORD(a
->adv_voice_coef_buffer
+ ADV_VOICE_NEW_COEF_BASE
);
11084 if (li_config_table
[i
].channel
& LI_CHANNEL_TX_DATA
)
11085 w
|= MIXER_FEATURE_ENABLE_TX_DATA
;
11086 if (li_config_table
[i
].channel
& LI_CHANNEL_RX_DATA
)
11087 w
|= MIXER_FEATURE_ENABLE_RX_DATA
;
11089 *(p
++) = (byte
)(w
>> 8);
11090 for (j
= 0; j
< sizeof(ch_map
); j
+= 2)
11092 if (plci
->li_bchannel_id
== 2)
11094 ch_map
[j
] = (byte
)(j
+ 1);
11095 ch_map
[j
+ 1] = (byte
) j
;
11099 ch_map
[j
] = (byte
) j
;
11100 ch_map
[j
+ 1] = (byte
)(j
+ 1);
11103 for (n
= 0; n
< ARRAY_SIZE(mixer_write_prog_bri
); n
++)
11105 i
= a
->li_base
+ ch_map
[mixer_write_prog_bri
[n
].to_ch
];
11106 j
= a
->li_base
+ ch_map
[mixer_write_prog_bri
[n
].from_ch
];
11107 if (li_config_table
[i
].channel
& li_config_table
[j
].channel
& LI_CHANNEL_INVOLVED
)
11109 *p
= (mixer_write_prog_bri
[n
].xconnect_override
!= 0) ?
11110 mixer_write_prog_bri
[n
].xconnect_override
:
11111 ((li_config_table
[i
].coef_table
[j
] & mixer_write_prog_bri
[n
].mask
) ? 0x80 : 0x01);
11112 if ((i
>= a
->li_base
+ MIXER_BCHANNELS_BRI
) || (j
>= a
->li_base
+ MIXER_BCHANNELS_BRI
))
11114 w
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
11115 li_config_table
[i
].coef_table
[j
] ^= (w
& mixer_write_prog_bri
[n
].mask
) << 4;
11121 if ((a
->AdvSignalPLCI
!= NULL
) && (a
->AdvSignalPLCI
->tel
== ADV_VOICE
))
11123 w
= (plci
== a
->AdvSignalPLCI
) ? n
: mixer_swapped_index_bri
[n
];
11124 if (ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) + w
< a
->adv_voice_coef_length
)
11125 *p
= a
->adv_voice_coef_buffer
[ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) + w
];
11131 j
= li_total_channels
+ 1;
11136 if (j
<= li_total_channels
)
11138 plci
->internal_command
= plci
->li_write_command
;
11139 if (plci_nl_busy(plci
))
11141 if (j
< a
->li_base
)
11145 *(p
++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC
;
11147 if (li_config_table
[i
].channel
& LI_CHANNEL_TX_DATA
)
11148 w
|= MIXER_FEATURE_ENABLE_TX_DATA
;
11149 if (li_config_table
[i
].channel
& LI_CHANNEL_RX_DATA
)
11150 w
|= MIXER_FEATURE_ENABLE_RX_DATA
;
11152 *(p
++) = (byte
)(w
>> 8);
11153 for (n
= 0; n
< ARRAY_SIZE(mixer_write_prog_pri
); n
++)
11155 *(p
++) = (byte
)((plci
->li_bchannel_id
- 1) | mixer_write_prog_pri
[n
].line_flags
);
11156 for (j
= a
->li_base
; j
< a
->li_base
+ MIXER_CHANNELS_PRI
; j
++)
11158 w
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
11159 if (w
& mixer_write_prog_pri
[n
].mask
)
11161 *(p
++) = (li_config_table
[i
].coef_table
[j
] & mixer_write_prog_pri
[n
].mask
) ? 0x80 : 0x01;
11162 li_config_table
[i
].coef_table
[j
] ^= mixer_write_prog_pri
[n
].mask
<< 4;
11167 *(p
++) = (byte
)((plci
->li_bchannel_id
- 1) | MIXER_COEF_LINE_ROW_FLAG
| mixer_write_prog_pri
[n
].line_flags
);
11168 for (j
= a
->li_base
; j
< a
->li_base
+ MIXER_CHANNELS_PRI
; j
++)
11170 w
= ((li_config_table
[j
].coef_table
[i
] & 0xf) ^ (li_config_table
[j
].coef_table
[i
] >> 4));
11171 if (w
& mixer_write_prog_pri
[n
].mask
)
11173 *(p
++) = (li_config_table
[j
].coef_table
[i
] & mixer_write_prog_pri
[n
].mask
) ? 0x80 : 0x01;
11174 li_config_table
[j
].coef_table
[i
] ^= mixer_write_prog_pri
[n
].mask
<< 4;
11183 *(p
++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI
;
11185 if ((plci
->tel
== ADV_VOICE
) && (plci
== a
->AdvSignalPLCI
)
11186 && (ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) <= a
->adv_voice_coef_length
))
11188 w
= GET_WORD(a
->adv_voice_coef_buffer
+ ADV_VOICE_NEW_COEF_BASE
);
11190 if (li_config_table
[i
].channel
& LI_CHANNEL_TX_DATA
)
11191 w
|= MIXER_FEATURE_ENABLE_TX_DATA
;
11192 if (li_config_table
[i
].channel
& LI_CHANNEL_RX_DATA
)
11193 w
|= MIXER_FEATURE_ENABLE_RX_DATA
;
11195 *(p
++) = (byte
)(w
>> 8);
11196 for (j
= 0; j
< sizeof(ch_map
); j
+= 2)
11198 if (plci
->li_bchannel_id
== 2)
11200 ch_map
[j
] = (byte
)(j
+ 1);
11201 ch_map
[j
+ 1] = (byte
) j
;
11205 ch_map
[j
] = (byte
) j
;
11206 ch_map
[j
+ 1] = (byte
)(j
+ 1);
11209 for (n
= 0; n
< ARRAY_SIZE(mixer_write_prog_bri
); n
++)
11211 i
= a
->li_base
+ ch_map
[mixer_write_prog_bri
[n
].to_ch
];
11212 j
= a
->li_base
+ ch_map
[mixer_write_prog_bri
[n
].from_ch
];
11213 if (li_config_table
[i
].channel
& li_config_table
[j
].channel
& LI_CHANNEL_INVOLVED
)
11215 *p
= ((li_config_table
[i
].coef_table
[j
] & mixer_write_prog_bri
[n
].mask
) ? 0x80 : 0x01);
11216 w
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
11217 li_config_table
[i
].coef_table
[j
] ^= (w
& mixer_write_prog_bri
[n
].mask
) << 4;
11222 if ((a
->AdvSignalPLCI
!= NULL
) && (a
->AdvSignalPLCI
->tel
== ADV_VOICE
))
11224 w
= (plci
== a
->AdvSignalPLCI
) ? n
: mixer_swapped_index_bri
[n
];
11225 if (ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) + w
< a
->adv_voice_coef_length
)
11226 *p
= a
->adv_voice_coef_buffer
[ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) + w
];
11232 j
= li_total_channels
+ 1;
11235 plci
->li_write_channel
= j
;
11236 if (p
!= plci
->internal_req_buffer
)
11238 plci
->NData
[0].P
= plci
->internal_req_buffer
;
11239 plci
->NData
[0].PLength
= p
- plci
->internal_req_buffer
;
11240 plci
->NL
.X
= plci
->NData
;
11241 plci
->NL
.ReqCh
= 0;
11242 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_UDATA
;
11243 plci
->adapter
->request(&plci
->NL
);
11249 static void mixer_notify_update(PLCI
*plci
, byte others
)
11251 DIVA_CAPI_ADAPTER
*a
;
11254 byte msg
[sizeof(CAPI_MSG_HEADER
) + 6];
11256 dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11257 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
11258 (char *)(FILE_
), __LINE__
, others
));
11261 if (a
->profile
.Global_Options
& GL_LINE_INTERCONNECT_SUPPORTED
)
11264 plci
->li_notify_update
= true;
11268 notify_plci
= NULL
;
11271 while ((i
< li_total_channels
) && (li_config_table
[i
].plci
== NULL
))
11273 if (i
< li_total_channels
)
11274 notify_plci
= li_config_table
[i
++].plci
;
11278 if ((plci
->li_bchannel_id
!= 0)
11279 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
11281 notify_plci
= plci
;
11284 if ((notify_plci
!= NULL
)
11285 && !notify_plci
->li_notify_update
11286 && (notify_plci
->appl
!= NULL
)
11287 && (notify_plci
->State
)
11288 && notify_plci
->NL
.Id
&& !notify_plci
->nl_remove_id
)
11290 notify_plci
->li_notify_update
= true;
11291 ((CAPI_MSG
*) msg
)->header
.length
= 18;
11292 ((CAPI_MSG
*) msg
)->header
.appl_id
= notify_plci
->appl
->Id
;
11293 ((CAPI_MSG
*) msg
)->header
.command
= _FACILITY_R
;
11294 ((CAPI_MSG
*) msg
)->header
.number
= 0;
11295 ((CAPI_MSG
*) msg
)->header
.controller
= notify_plci
->adapter
->Id
;
11296 ((CAPI_MSG
*) msg
)->header
.plci
= notify_plci
->Id
;
11297 ((CAPI_MSG
*) msg
)->header
.ncci
= 0;
11298 ((CAPI_MSG
*) msg
)->info
.facility_req
.Selector
= SELECTOR_LINE_INTERCONNECT
;
11299 ((CAPI_MSG
*) msg
)->info
.facility_req
.structs
[0] = 3;
11300 PUT_WORD(&(((CAPI_MSG
*) msg
)->info
.facility_req
.structs
[1]), LI_REQ_SILENT_UPDATE
);
11301 ((CAPI_MSG
*) msg
)->info
.facility_req
.structs
[3] = 0;
11302 w
= api_put(notify_plci
->appl
, (CAPI_MSG
*) msg
);
11303 if (w
!= _QUEUE_FULL
)
11307 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11308 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
11309 (char *)(FILE_
), __LINE__
,
11310 (dword
)((notify_plci
->Id
<< 8) | UnMapController(notify_plci
->adapter
->Id
)), w
));
11312 notify_plci
->li_notify_update
= false;
11315 } while (others
&& (notify_plci
!= NULL
));
11317 plci
->li_notify_update
= false;
11322 static void mixer_clear_config(PLCI
*plci
)
11324 DIVA_CAPI_ADAPTER
*a
;
11327 dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11328 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
11329 (char *)(FILE_
), __LINE__
));
11331 plci
->li_notify_update
= false;
11332 plci
->li_plci_b_write_pos
= 0;
11333 plci
->li_plci_b_read_pos
= 0;
11334 plci
->li_plci_b_req_pos
= 0;
11336 if ((plci
->li_bchannel_id
!= 0)
11337 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
11339 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
11340 li_config_table
[i
].curchnl
= 0;
11341 li_config_table
[i
].channel
= 0;
11342 li_config_table
[i
].chflags
= 0;
11343 for (j
= 0; j
< li_total_channels
; j
++)
11345 li_config_table
[j
].flag_table
[i
] = 0;
11346 li_config_table
[i
].flag_table
[j
] = 0;
11347 li_config_table
[i
].coef_table
[j
] = 0;
11348 li_config_table
[j
].coef_table
[i
] = 0;
11352 li_config_table
[i
].coef_table
[i
] |= LI_COEF_CH_PC_SET
| LI_COEF_PC_CH_SET
;
11353 if ((plci
->tel
== ADV_VOICE
) && (plci
== a
->AdvSignalPLCI
))
11355 i
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (plci
->li_bchannel_id
- 1);
11356 li_config_table
[i
].curchnl
= 0;
11357 li_config_table
[i
].channel
= 0;
11358 li_config_table
[i
].chflags
= 0;
11359 for (j
= 0; j
< li_total_channels
; j
++)
11361 li_config_table
[i
].flag_table
[j
] = 0;
11362 li_config_table
[j
].flag_table
[i
] = 0;
11363 li_config_table
[i
].coef_table
[j
] = 0;
11364 li_config_table
[j
].coef_table
[i
] = 0;
11366 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
)
11368 i
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
);
11369 li_config_table
[i
].curchnl
= 0;
11370 li_config_table
[i
].channel
= 0;
11371 li_config_table
[i
].chflags
= 0;
11372 for (j
= 0; j
< li_total_channels
; j
++)
11374 li_config_table
[i
].flag_table
[j
] = 0;
11375 li_config_table
[j
].flag_table
[i
] = 0;
11376 li_config_table
[i
].coef_table
[j
] = 0;
11377 li_config_table
[j
].coef_table
[i
] = 0;
11386 static void mixer_prepare_switch(dword Id
, PLCI
*plci
)
11389 dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11390 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11394 mixer_indication_coefs_set(Id
, plci
);
11395 } while (plci
->li_plci_b_read_pos
!= plci
->li_plci_b_req_pos
);
11399 static word
mixer_save_config(dword Id
, PLCI
*plci
, byte Rc
)
11401 DIVA_CAPI_ADAPTER
*a
;
11404 dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11405 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
11408 if ((plci
->li_bchannel_id
!= 0)
11409 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
11411 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
11412 for (j
= 0; j
< li_total_channels
; j
++)
11414 li_config_table
[i
].coef_table
[j
] &= 0xf;
11415 li_config_table
[j
].coef_table
[i
] &= 0xf;
11418 li_config_table
[i
].coef_table
[i
] |= LI_COEF_CH_PC_SET
| LI_COEF_PC_CH_SET
;
11424 static word
mixer_restore_config(dword Id
, PLCI
*plci
, byte Rc
)
11426 DIVA_CAPI_ADAPTER
*a
;
11429 dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11430 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
11434 if ((plci
->B1_facilities
& B1_FACILITY_MIXER
)
11435 && (plci
->li_bchannel_id
!= 0)
11436 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
11438 switch (plci
->adjust_b_state
)
11440 case ADJUST_B_RESTORE_MIXER_1
:
11441 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
11443 plci
->internal_command
= plci
->adjust_b_command
;
11444 if (plci_nl_busy(plci
))
11446 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_1
;
11449 xconnect_query_addresses(plci
);
11450 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_2
;
11453 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_5
;
11455 case ADJUST_B_RESTORE_MIXER_2
:
11456 case ADJUST_B_RESTORE_MIXER_3
:
11457 case ADJUST_B_RESTORE_MIXER_4
:
11458 if ((Rc
!= OK
) && (Rc
!= OK_FC
) && (Rc
!= 0))
11460 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11461 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
11462 Info
= _WRONG_STATE
;
11467 if (plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_2
)
11468 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_3
;
11469 else if (plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_4
)
11470 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_5
;
11474 if (plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_2
)
11475 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_4
;
11476 else if (plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_3
)
11477 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_5
;
11479 if (plci
->adjust_b_state
!= ADJUST_B_RESTORE_MIXER_5
)
11481 plci
->internal_command
= plci
->adjust_b_command
;
11484 case ADJUST_B_RESTORE_MIXER_5
:
11485 xconnect_write_coefs(plci
, plci
->adjust_b_command
);
11486 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_6
;
11488 case ADJUST_B_RESTORE_MIXER_6
:
11489 if (!xconnect_write_coefs_process(Id
, plci
, Rc
))
11491 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11492 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11493 Info
= _FACILITY_NOT_SUPPORTED
;
11496 if (plci
->internal_command
)
11498 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_7
;
11499 case ADJUST_B_RESTORE_MIXER_7
:
11507 static void mixer_command(dword Id
, PLCI
*plci
, byte Rc
)
11509 DIVA_CAPI_ADAPTER
*a
;
11510 word i
, internal_command
;
11512 dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11513 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
,
11517 internal_command
= plci
->internal_command
;
11518 plci
->internal_command
= 0;
11519 switch (plci
->li_cmd
)
11521 case LI_REQ_CONNECT
:
11522 case LI_REQ_DISCONNECT
:
11523 case LI_REQ_SILENT_UPDATE
:
11524 switch (internal_command
)
11527 if (plci
->li_channel_bits
& LI_CHANNEL_INVOLVED
)
11529 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
|
11530 B1_FACILITY_MIXER
), MIXER_COMMAND_1
);
11532 case MIXER_COMMAND_1
:
11533 if (plci
->li_channel_bits
& LI_CHANNEL_INVOLVED
)
11535 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
11537 dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11538 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11541 if (plci
->internal_command
)
11544 plci
->li_plci_b_req_pos
= plci
->li_plci_b_write_pos
;
11545 if ((plci
->li_channel_bits
& LI_CHANNEL_INVOLVED
)
11546 || ((get_b1_facilities(plci
, plci
->B1_resource
) & B1_FACILITY_MIXER
)
11547 && (add_b1_facilities(plci
, plci
->B1_resource
, (word
)(plci
->B1_facilities
&
11548 ~B1_FACILITY_MIXER
)) == plci
->B1_resource
)))
11550 xconnect_write_coefs(plci
, MIXER_COMMAND_2
);
11556 mixer_indication_coefs_set(Id
, plci
);
11557 } while (plci
->li_plci_b_read_pos
!= plci
->li_plci_b_req_pos
);
11559 case MIXER_COMMAND_2
:
11560 if ((plci
->li_channel_bits
& LI_CHANNEL_INVOLVED
)
11561 || ((get_b1_facilities(plci
, plci
->B1_resource
) & B1_FACILITY_MIXER
)
11562 && (add_b1_facilities(plci
, plci
->B1_resource
, (word
)(plci
->B1_facilities
&
11563 ~B1_FACILITY_MIXER
)) == plci
->B1_resource
)))
11565 if (!xconnect_write_coefs_process(Id
, plci
, Rc
))
11567 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11568 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11569 if (plci
->li_plci_b_write_pos
!= plci
->li_plci_b_req_pos
)
11573 plci
->li_plci_b_write_pos
= (plci
->li_plci_b_write_pos
== 0) ?
11574 LI_PLCI_B_QUEUE_ENTRIES
- 1 : plci
->li_plci_b_write_pos
- 1;
11575 i
= (plci
->li_plci_b_write_pos
== 0) ?
11576 LI_PLCI_B_QUEUE_ENTRIES
- 1 : plci
->li_plci_b_write_pos
- 1;
11577 } while ((plci
->li_plci_b_write_pos
!= plci
->li_plci_b_req_pos
)
11578 && !(plci
->li_plci_b_queue
[i
] & LI_PLCI_B_LAST_FLAG
));
11582 if (plci
->internal_command
)
11585 if (!(plci
->li_channel_bits
& LI_CHANNEL_INVOLVED
))
11587 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
&
11588 ~B1_FACILITY_MIXER
), MIXER_COMMAND_3
);
11590 case MIXER_COMMAND_3
:
11591 if (!(plci
->li_channel_bits
& LI_CHANNEL_INVOLVED
))
11593 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
11595 dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11596 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11599 if (plci
->internal_command
)
11606 if ((plci
->li_bchannel_id
== 0)
11607 || (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
!= plci
))
11609 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11610 UnMapId(Id
), (char *)(FILE_
), __LINE__
, (int)(plci
->li_bchannel_id
)));
11614 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
11615 li_config_table
[i
].curchnl
= plci
->li_channel_bits
;
11616 if (!a
->li_pri
&& (plci
->tel
== ADV_VOICE
) && (plci
== a
->AdvSignalPLCI
))
11618 i
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (plci
->li_bchannel_id
- 1);
11619 li_config_table
[i
].curchnl
= plci
->li_channel_bits
;
11620 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
)
11622 i
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
);
11623 li_config_table
[i
].curchnl
= plci
->li_channel_bits
;
11630 static void li_update_connect(dword Id
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
,
11631 dword plci_b_id
, byte connect
, dword li_flags
)
11633 word i
, ch_a
, ch_a_v
, ch_a_s
, ch_b
, ch_b_v
, ch_b_s
;
11635 DIVA_CAPI_ADAPTER
*a_b
;
11637 a_b
= &(adapter
[MapController((byte
)(plci_b_id
& 0x7f)) - 1]);
11638 plci_b
= &(a_b
->plci
[((plci_b_id
>> 8) & 0xff) - 1]);
11639 ch_a
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
11640 if (!a
->li_pri
&& (plci
->tel
== ADV_VOICE
)
11641 && (plci
== a
->AdvSignalPLCI
) && (Id
& EXT_CONTROLLER
))
11643 ch_a_v
= ch_a
+ MIXER_IC_CHANNEL_BASE
;
11644 ch_a_s
= (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
) ?
11645 a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
) : ch_a_v
;
11652 ch_b
= a_b
->li_base
+ (plci_b
->li_bchannel_id
- 1);
11653 if (!a_b
->li_pri
&& (plci_b
->tel
== ADV_VOICE
)
11654 && (plci_b
== a_b
->AdvSignalPLCI
) && (plci_b_id
& EXT_CONTROLLER
))
11656 ch_b_v
= ch_b
+ MIXER_IC_CHANNEL_BASE
;
11657 ch_b_s
= (a_b
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
) ?
11658 a_b
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci_b
->li_bchannel_id
) : ch_b_v
;
11667 li_config_table
[ch_a
].flag_table
[ch_a_v
] &= ~LI_FLAG_MONITOR
;
11668 li_config_table
[ch_a
].flag_table
[ch_a_s
] &= ~LI_FLAG_MONITOR
;
11669 li_config_table
[ch_a_v
].flag_table
[ch_a
] &= ~(LI_FLAG_ANNOUNCEMENT
| LI_FLAG_MIX
);
11670 li_config_table
[ch_a_s
].flag_table
[ch_a
] &= ~(LI_FLAG_ANNOUNCEMENT
| LI_FLAG_MIX
);
11672 li_config_table
[ch_a
].flag_table
[ch_b_v
] &= ~LI_FLAG_MONITOR
;
11673 li_config_table
[ch_a
].flag_table
[ch_b_s
] &= ~LI_FLAG_MONITOR
;
11674 li_config_table
[ch_b_v
].flag_table
[ch_a
] &= ~(LI_FLAG_ANNOUNCEMENT
| LI_FLAG_MIX
);
11675 li_config_table
[ch_b_s
].flag_table
[ch_a
] &= ~(LI_FLAG_ANNOUNCEMENT
| LI_FLAG_MIX
);
11676 if (ch_a_v
== ch_b_v
)
11678 li_config_table
[ch_a_v
].flag_table
[ch_b_v
] &= ~LI_FLAG_CONFERENCE
;
11679 li_config_table
[ch_a_s
].flag_table
[ch_b_s
] &= ~LI_FLAG_CONFERENCE
;
11683 if (li_config_table
[ch_a_v
].flag_table
[ch_b_v
] & LI_FLAG_CONFERENCE
)
11685 for (i
= 0; i
< li_total_channels
; i
++)
11688 li_config_table
[ch_a_v
].flag_table
[i
] &= ~LI_FLAG_CONFERENCE
;
11691 if (li_config_table
[ch_a_s
].flag_table
[ch_b_v
] & LI_FLAG_CONFERENCE
)
11693 for (i
= 0; i
< li_total_channels
; i
++)
11696 li_config_table
[ch_a_s
].flag_table
[i
] &= ~LI_FLAG_CONFERENCE
;
11699 if (li_config_table
[ch_b_v
].flag_table
[ch_a_v
] & LI_FLAG_CONFERENCE
)
11701 for (i
= 0; i
< li_total_channels
; i
++)
11704 li_config_table
[i
].flag_table
[ch_a_v
] &= ~LI_FLAG_CONFERENCE
;
11707 if (li_config_table
[ch_b_v
].flag_table
[ch_a_s
] & LI_FLAG_CONFERENCE
)
11709 for (i
= 0; i
< li_total_channels
; i
++)
11712 li_config_table
[i
].flag_table
[ch_a_s
] &= ~LI_FLAG_CONFERENCE
;
11716 if (li_flags
& LI_FLAG_CONFERENCE_A_B
)
11718 li_config_table
[ch_b_v
].flag_table
[ch_a_v
] |= LI_FLAG_CONFERENCE
;
11719 li_config_table
[ch_b_s
].flag_table
[ch_a_v
] |= LI_FLAG_CONFERENCE
;
11720 li_config_table
[ch_b_v
].flag_table
[ch_a_s
] |= LI_FLAG_CONFERENCE
;
11721 li_config_table
[ch_b_s
].flag_table
[ch_a_s
] |= LI_FLAG_CONFERENCE
;
11723 if (li_flags
& LI_FLAG_CONFERENCE_B_A
)
11725 li_config_table
[ch_a_v
].flag_table
[ch_b_v
] |= LI_FLAG_CONFERENCE
;
11726 li_config_table
[ch_a_v
].flag_table
[ch_b_s
] |= LI_FLAG_CONFERENCE
;
11727 li_config_table
[ch_a_s
].flag_table
[ch_b_v
] |= LI_FLAG_CONFERENCE
;
11728 li_config_table
[ch_a_s
].flag_table
[ch_b_s
] |= LI_FLAG_CONFERENCE
;
11730 if (li_flags
& LI_FLAG_MONITOR_A
)
11732 li_config_table
[ch_a
].flag_table
[ch_a_v
] |= LI_FLAG_MONITOR
;
11733 li_config_table
[ch_a
].flag_table
[ch_a_s
] |= LI_FLAG_MONITOR
;
11735 if (li_flags
& LI_FLAG_MONITOR_B
)
11737 li_config_table
[ch_a
].flag_table
[ch_b_v
] |= LI_FLAG_MONITOR
;
11738 li_config_table
[ch_a
].flag_table
[ch_b_s
] |= LI_FLAG_MONITOR
;
11740 if (li_flags
& LI_FLAG_ANNOUNCEMENT_A
)
11742 li_config_table
[ch_a_v
].flag_table
[ch_a
] |= LI_FLAG_ANNOUNCEMENT
;
11743 li_config_table
[ch_a_s
].flag_table
[ch_a
] |= LI_FLAG_ANNOUNCEMENT
;
11745 if (li_flags
& LI_FLAG_ANNOUNCEMENT_B
)
11747 li_config_table
[ch_b_v
].flag_table
[ch_a
] |= LI_FLAG_ANNOUNCEMENT
;
11748 li_config_table
[ch_b_s
].flag_table
[ch_a
] |= LI_FLAG_ANNOUNCEMENT
;
11750 if (li_flags
& LI_FLAG_MIX_A
)
11752 li_config_table
[ch_a_v
].flag_table
[ch_a
] |= LI_FLAG_MIX
;
11753 li_config_table
[ch_a_s
].flag_table
[ch_a
] |= LI_FLAG_MIX
;
11755 if (li_flags
& LI_FLAG_MIX_B
)
11757 li_config_table
[ch_b_v
].flag_table
[ch_a
] |= LI_FLAG_MIX
;
11758 li_config_table
[ch_b_s
].flag_table
[ch_a
] |= LI_FLAG_MIX
;
11760 if (ch_a_v
!= ch_a_s
)
11762 li_config_table
[ch_a_v
].flag_table
[ch_a_s
] |= LI_FLAG_CONFERENCE
;
11763 li_config_table
[ch_a_s
].flag_table
[ch_a_v
] |= LI_FLAG_CONFERENCE
;
11765 if (ch_b_v
!= ch_b_s
)
11767 li_config_table
[ch_b_v
].flag_table
[ch_b_s
] |= LI_FLAG_CONFERENCE
;
11768 li_config_table
[ch_b_s
].flag_table
[ch_b_v
] |= LI_FLAG_CONFERENCE
;
11773 static void li2_update_connect(dword Id
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
,
11774 dword plci_b_id
, byte connect
, dword li_flags
)
11776 word ch_a
, ch_a_v
, ch_a_s
, ch_b
, ch_b_v
, ch_b_s
;
11778 DIVA_CAPI_ADAPTER
*a_b
;
11780 a_b
= &(adapter
[MapController((byte
)(plci_b_id
& 0x7f)) - 1]);
11781 plci_b
= &(a_b
->plci
[((plci_b_id
>> 8) & 0xff) - 1]);
11782 ch_a
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
11783 if (!a
->li_pri
&& (plci
->tel
== ADV_VOICE
)
11784 && (plci
== a
->AdvSignalPLCI
) && (Id
& EXT_CONTROLLER
))
11786 ch_a_v
= ch_a
+ MIXER_IC_CHANNEL_BASE
;
11787 ch_a_s
= (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
) ?
11788 a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
) : ch_a_v
;
11795 ch_b
= a_b
->li_base
+ (plci_b
->li_bchannel_id
- 1);
11796 if (!a_b
->li_pri
&& (plci_b
->tel
== ADV_VOICE
)
11797 && (plci_b
== a_b
->AdvSignalPLCI
) && (plci_b_id
& EXT_CONTROLLER
))
11799 ch_b_v
= ch_b
+ MIXER_IC_CHANNEL_BASE
;
11800 ch_b_s
= (a_b
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
) ?
11801 a_b
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci_b
->li_bchannel_id
) : ch_b_v
;
11810 li_config_table
[ch_b
].flag_table
[ch_b_v
] &= ~LI_FLAG_MONITOR
;
11811 li_config_table
[ch_b
].flag_table
[ch_b_s
] &= ~LI_FLAG_MONITOR
;
11812 li_config_table
[ch_b_v
].flag_table
[ch_b
] &= ~LI_FLAG_MIX
;
11813 li_config_table
[ch_b_s
].flag_table
[ch_b
] &= ~LI_FLAG_MIX
;
11814 li_config_table
[ch_b
].flag_table
[ch_b
] &= ~LI_FLAG_PCCONNECT
;
11815 li_config_table
[ch_b
].chflags
&= ~(LI_CHFLAG_MONITOR
| LI_CHFLAG_MIX
| LI_CHFLAG_LOOP
);
11817 li_config_table
[ch_b_v
].flag_table
[ch_a_v
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11818 li_config_table
[ch_b_s
].flag_table
[ch_a_v
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11819 li_config_table
[ch_b_v
].flag_table
[ch_a_s
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11820 li_config_table
[ch_b_s
].flag_table
[ch_a_s
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11821 li_config_table
[ch_a_v
].flag_table
[ch_b_v
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11822 li_config_table
[ch_a_v
].flag_table
[ch_b_s
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11823 li_config_table
[ch_a_s
].flag_table
[ch_b_v
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11824 li_config_table
[ch_a_s
].flag_table
[ch_b_s
] &= ~(LI_FLAG_INTERCONNECT
| LI_FLAG_CONFERENCE
);
11825 if (li_flags
& LI2_FLAG_INTERCONNECT_A_B
)
11827 li_config_table
[ch_b_v
].flag_table
[ch_a_v
] |= LI_FLAG_INTERCONNECT
;
11828 li_config_table
[ch_b_s
].flag_table
[ch_a_v
] |= LI_FLAG_INTERCONNECT
;
11829 li_config_table
[ch_b_v
].flag_table
[ch_a_s
] |= LI_FLAG_INTERCONNECT
;
11830 li_config_table
[ch_b_s
].flag_table
[ch_a_s
] |= LI_FLAG_INTERCONNECT
;
11832 if (li_flags
& LI2_FLAG_INTERCONNECT_B_A
)
11834 li_config_table
[ch_a_v
].flag_table
[ch_b_v
] |= LI_FLAG_INTERCONNECT
;
11835 li_config_table
[ch_a_v
].flag_table
[ch_b_s
] |= LI_FLAG_INTERCONNECT
;
11836 li_config_table
[ch_a_s
].flag_table
[ch_b_v
] |= LI_FLAG_INTERCONNECT
;
11837 li_config_table
[ch_a_s
].flag_table
[ch_b_s
] |= LI_FLAG_INTERCONNECT
;
11839 if (li_flags
& LI2_FLAG_MONITOR_B
)
11841 li_config_table
[ch_b
].flag_table
[ch_b_v
] |= LI_FLAG_MONITOR
;
11842 li_config_table
[ch_b
].flag_table
[ch_b_s
] |= LI_FLAG_MONITOR
;
11844 if (li_flags
& LI2_FLAG_MIX_B
)
11846 li_config_table
[ch_b_v
].flag_table
[ch_b
] |= LI_FLAG_MIX
;
11847 li_config_table
[ch_b_s
].flag_table
[ch_b
] |= LI_FLAG_MIX
;
11849 if (li_flags
& LI2_FLAG_MONITOR_X
)
11850 li_config_table
[ch_b
].chflags
|= LI_CHFLAG_MONITOR
;
11851 if (li_flags
& LI2_FLAG_MIX_X
)
11852 li_config_table
[ch_b
].chflags
|= LI_CHFLAG_MIX
;
11853 if (li_flags
& LI2_FLAG_LOOP_B
)
11855 li_config_table
[ch_b_v
].flag_table
[ch_b_v
] |= LI_FLAG_INTERCONNECT
;
11856 li_config_table
[ch_b_s
].flag_table
[ch_b_v
] |= LI_FLAG_INTERCONNECT
;
11857 li_config_table
[ch_b_v
].flag_table
[ch_b_s
] |= LI_FLAG_INTERCONNECT
;
11858 li_config_table
[ch_b_s
].flag_table
[ch_b_s
] |= LI_FLAG_INTERCONNECT
;
11860 if (li_flags
& LI2_FLAG_LOOP_PC
)
11861 li_config_table
[ch_b
].flag_table
[ch_b
] |= LI_FLAG_PCCONNECT
;
11862 if (li_flags
& LI2_FLAG_LOOP_X
)
11863 li_config_table
[ch_b
].chflags
|= LI_CHFLAG_LOOP
;
11864 if (li_flags
& LI2_FLAG_PCCONNECT_A_B
)
11865 li_config_table
[ch_b_s
].flag_table
[ch_a_s
] |= LI_FLAG_PCCONNECT
;
11866 if (li_flags
& LI2_FLAG_PCCONNECT_B_A
)
11867 li_config_table
[ch_a_s
].flag_table
[ch_b_s
] |= LI_FLAG_PCCONNECT
;
11868 if (ch_a_v
!= ch_a_s
)
11870 li_config_table
[ch_a_v
].flag_table
[ch_a_s
] |= LI_FLAG_CONFERENCE
;
11871 li_config_table
[ch_a_s
].flag_table
[ch_a_v
] |= LI_FLAG_CONFERENCE
;
11873 if (ch_b_v
!= ch_b_s
)
11875 li_config_table
[ch_b_v
].flag_table
[ch_b_s
] |= LI_FLAG_CONFERENCE
;
11876 li_config_table
[ch_b_s
].flag_table
[ch_b_v
] |= LI_FLAG_CONFERENCE
;
11881 static word
li_check_main_plci(dword Id
, PLCI
*plci
)
11885 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11886 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11887 return (_WRONG_IDENTIFIER
);
11890 || !plci
->NL
.Id
|| plci
->nl_remove_id
11891 || (plci
->li_bchannel_id
== 0))
11893 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11894 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11895 return (_WRONG_STATE
);
11897 li_config_table
[plci
->adapter
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
= plci
;
11902 static PLCI
*li_check_plci_b(dword Id
, PLCI
*plci
,
11903 dword plci_b_id
, word plci_b_write_pos
, byte
*p_result
)
11908 if (((plci
->li_plci_b_read_pos
> plci_b_write_pos
) ? plci
->li_plci_b_read_pos
:
11909 LI_PLCI_B_QUEUE_ENTRIES
+ plci
->li_plci_b_read_pos
) - plci_b_write_pos
- 1 < 2)
11911 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11912 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11913 PUT_WORD(p_result
, _REQUEST_NOT_ALLOWED_IN_THIS_STATE
);
11917 if ((plci_b_id
& 0x7f) != 0)
11919 ctlr_b
= MapController((byte
)(plci_b_id
& 0x7f));
11920 if ((ctlr_b
> max_adapter
) || ((ctlr_b
!= 0) && (adapter
[ctlr_b
- 1].request
== NULL
)))
11924 || (((plci_b_id
>> 8) & 0xff) == 0)
11925 || (((plci_b_id
>> 8) & 0xff) > adapter
[ctlr_b
- 1].max_plci
))
11927 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11928 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b_id
));
11929 PUT_WORD(p_result
, _WRONG_IDENTIFIER
);
11932 plci_b
= &(adapter
[ctlr_b
- 1].plci
[((plci_b_id
>> 8) & 0xff) - 1]);
11934 || !plci_b
->NL
.Id
|| plci_b
->nl_remove_id
11935 || (plci_b
->li_bchannel_id
== 0))
11937 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11938 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b_id
));
11939 PUT_WORD(p_result
, _REQUEST_NOT_ALLOWED_IN_THIS_STATE
);
11942 li_config_table
[plci_b
->adapter
->li_base
+ (plci_b
->li_bchannel_id
- 1)].plci
= plci_b
;
11943 if (((byte
)(plci_b_id
& ~EXT_CONTROLLER
)) !=
11944 ((byte
)(UnMapController(plci
->adapter
->Id
) & ~EXT_CONTROLLER
))
11945 && (!(plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
11946 || !(plci_b
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)))
11948 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11949 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b_id
));
11950 PUT_WORD(p_result
, _WRONG_IDENTIFIER
);
11953 if (!(get_b1_facilities(plci_b
, add_b1_facilities(plci_b
, plci_b
->B1_resource
,
11954 (word
)(plci_b
->B1_facilities
| B1_FACILITY_MIXER
))) & B1_FACILITY_MIXER
))
11956 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11957 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b
->B1_resource
));
11958 PUT_WORD(p_result
, _REQUEST_NOT_ALLOWED_IN_THIS_STATE
);
11965 static PLCI
*li2_check_plci_b(dword Id
, PLCI
*plci
,
11966 dword plci_b_id
, word plci_b_write_pos
, byte
*p_result
)
11971 if (((plci
->li_plci_b_read_pos
> plci_b_write_pos
) ? plci
->li_plci_b_read_pos
:
11972 LI_PLCI_B_QUEUE_ENTRIES
+ plci
->li_plci_b_read_pos
) - plci_b_write_pos
- 1 < 2)
11974 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11975 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
11976 PUT_WORD(p_result
, _WRONG_STATE
);
11980 if ((plci_b_id
& 0x7f) != 0)
11982 ctlr_b
= MapController((byte
)(plci_b_id
& 0x7f));
11983 if ((ctlr_b
> max_adapter
) || ((ctlr_b
!= 0) && (adapter
[ctlr_b
- 1].request
== NULL
)))
11987 || (((plci_b_id
>> 8) & 0xff) == 0)
11988 || (((plci_b_id
>> 8) & 0xff) > adapter
[ctlr_b
- 1].max_plci
))
11990 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11991 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b_id
));
11992 PUT_WORD(p_result
, _WRONG_IDENTIFIER
);
11995 plci_b
= &(adapter
[ctlr_b
- 1].plci
[((plci_b_id
>> 8) & 0xff) - 1]);
11997 || !plci_b
->NL
.Id
|| plci_b
->nl_remove_id
11998 || (plci_b
->li_bchannel_id
== 0)
11999 || (li_config_table
[plci_b
->adapter
->li_base
+ (plci_b
->li_bchannel_id
- 1)].plci
!= plci_b
))
12001 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12002 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b_id
));
12003 PUT_WORD(p_result
, _WRONG_STATE
);
12006 if (((byte
)(plci_b_id
& ~EXT_CONTROLLER
)) !=
12007 ((byte
)(UnMapController(plci
->adapter
->Id
) & ~EXT_CONTROLLER
))
12008 && (!(plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12009 || !(plci_b
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)))
12011 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12012 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b_id
));
12013 PUT_WORD(p_result
, _WRONG_IDENTIFIER
);
12016 if (!(get_b1_facilities(plci_b
, add_b1_facilities(plci_b
, plci_b
->B1_resource
,
12017 (word
)(plci_b
->B1_facilities
| B1_FACILITY_MIXER
))) & B1_FACILITY_MIXER
))
12019 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12020 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci_b
->B1_resource
));
12021 PUT_WORD(p_result
, _WRONG_STATE
);
12028 static byte
mixer_request(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
12032 dword d
, li_flags
, plci_b_id
;
12034 API_PARSE li_parms
[3];
12035 API_PARSE li_req_parms
[3];
12036 API_PARSE li_participant_struct
[2];
12037 API_PARSE li_participant_parms
[3];
12038 word participant_parms_pos
;
12039 byte result_buffer
[32];
12042 word plci_b_write_pos
;
12044 dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12045 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12048 result
= result_buffer
;
12049 result_buffer
[0] = 0;
12050 if (!(a
->profile
.Global_Options
& GL_LINE_INTERCONNECT_SUPPORTED
))
12052 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12053 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12054 Info
= _FACILITY_NOT_SUPPORTED
;
12056 else if (api_parse(&msg
[1].info
[1], msg
[1].length
, "ws", li_parms
))
12058 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12059 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12060 Info
= _WRONG_MESSAGE_FORMAT
;
12064 result_buffer
[0] = 3;
12065 PUT_WORD(&result_buffer
[1], GET_WORD(li_parms
[0].info
));
12066 result_buffer
[3] = 0;
12067 switch (GET_WORD(li_parms
[0].info
))
12069 case LI_GET_SUPPORTED_SERVICES
:
12070 if (appl
->appl_flags
& APPL_FLAG_OLD_LI_SPEC
)
12072 result_buffer
[0] = 17;
12073 result_buffer
[3] = 14;
12074 PUT_WORD(&result_buffer
[4], GOOD
);
12076 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_MIXER_CH_CH
)
12077 d
|= LI_CONFERENCING_SUPPORTED
;
12078 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_MIXER_CH_PC
)
12079 d
|= LI_MONITORING_SUPPORTED
;
12080 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_MIXER_PC_CH
)
12081 d
|= LI_ANNOUNCEMENTS_SUPPORTED
| LI_MIXING_SUPPORTED
;
12082 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12083 d
|= LI_CROSS_CONTROLLER_SUPPORTED
;
12084 PUT_DWORD(&result_buffer
[6], d
);
12085 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12088 for (i
= 0; i
< li_total_channels
; i
++)
12090 if ((li_config_table
[i
].adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12091 && (li_config_table
[i
].adapter
->li_pri
12092 || (i
< li_config_table
[i
].adapter
->li_base
+ MIXER_BCHANNELS_BRI
)))
12100 d
= a
->li_pri
? a
->li_channels
: MIXER_BCHANNELS_BRI
;
12102 PUT_DWORD(&result_buffer
[10], d
/ 2);
12103 PUT_DWORD(&result_buffer
[14], d
);
12107 result_buffer
[0] = 25;
12108 result_buffer
[3] = 22;
12109 PUT_WORD(&result_buffer
[4], GOOD
);
12110 d
= LI2_ASYMMETRIC_SUPPORTED
| LI2_B_LOOPING_SUPPORTED
| LI2_X_LOOPING_SUPPORTED
;
12111 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_MIXER_CH_PC
)
12112 d
|= LI2_MONITORING_SUPPORTED
| LI2_REMOTE_MONITORING_SUPPORTED
;
12113 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_MIXER_PC_CH
)
12114 d
|= LI2_MIXING_SUPPORTED
| LI2_REMOTE_MIXING_SUPPORTED
;
12115 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_MIXER_PC_PC
)
12116 d
|= LI2_PC_LOOPING_SUPPORTED
;
12117 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12118 d
|= LI2_CROSS_CONTROLLER_SUPPORTED
;
12119 PUT_DWORD(&result_buffer
[6], d
);
12120 d
= a
->li_pri
? a
->li_channels
: MIXER_BCHANNELS_BRI
;
12121 PUT_DWORD(&result_buffer
[10], d
/ 2);
12122 PUT_DWORD(&result_buffer
[14], d
- 1);
12123 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12126 for (i
= 0; i
< li_total_channels
; i
++)
12128 if ((li_config_table
[i
].adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XCONNECT
)
12129 && (li_config_table
[i
].adapter
->li_pri
12130 || (i
< li_config_table
[i
].adapter
->li_base
+ MIXER_BCHANNELS_BRI
)))
12136 PUT_DWORD(&result_buffer
[18], d
/ 2);
12137 PUT_DWORD(&result_buffer
[22], d
- 1);
12141 case LI_REQ_CONNECT
:
12142 if (li_parms
[1].length
== 8)
12144 appl
->appl_flags
|= APPL_FLAG_OLD_LI_SPEC
;
12145 if (api_parse(&li_parms
[1].info
[1], li_parms
[1].length
, "dd", li_req_parms
))
12147 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12148 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12149 Info
= _WRONG_MESSAGE_FORMAT
;
12152 plci_b_id
= GET_DWORD(li_req_parms
[0].info
) & 0xffff;
12153 li_flags
= GET_DWORD(li_req_parms
[1].info
);
12154 Info
= li_check_main_plci(Id
, plci
);
12155 result_buffer
[0] = 9;
12156 result_buffer
[3] = 6;
12157 PUT_DWORD(&result_buffer
[4], plci_b_id
);
12158 PUT_WORD(&result_buffer
[8], GOOD
);
12161 result
= plci
->saved_msg
.info
;
12162 for (i
= 0; i
<= result_buffer
[0]; i
++)
12163 result
[i
] = result_buffer
[i
];
12164 plci_b_write_pos
= plci
->li_plci_b_write_pos
;
12165 plci_b
= li_check_plci_b(Id
, plci
, plci_b_id
, plci_b_write_pos
, &result
[8]);
12166 if (plci_b
== NULL
)
12168 li_update_connect(Id
, a
, plci
, plci_b_id
, true, li_flags
);
12169 plci
->li_plci_b_queue
[plci_b_write_pos
] = plci_b_id
| LI_PLCI_B_LAST_FLAG
;
12170 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12171 plci
->li_plci_b_write_pos
= plci_b_write_pos
;
12175 appl
->appl_flags
&= ~APPL_FLAG_OLD_LI_SPEC
;
12176 if (api_parse(&li_parms
[1].info
[1], li_parms
[1].length
, "ds", li_req_parms
))
12178 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12179 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12180 Info
= _WRONG_MESSAGE_FORMAT
;
12183 li_flags
= GET_DWORD(li_req_parms
[0].info
) & ~(LI2_FLAG_INTERCONNECT_A_B
| LI2_FLAG_INTERCONNECT_B_A
);
12184 Info
= li_check_main_plci(Id
, plci
);
12185 result_buffer
[0] = 7;
12186 result_buffer
[3] = 4;
12187 PUT_WORD(&result_buffer
[4], Info
);
12188 result_buffer
[6] = 0;
12191 result
= plci
->saved_msg
.info
;
12192 for (i
= 0; i
<= result_buffer
[0]; i
++)
12193 result
[i
] = result_buffer
[i
];
12194 plci_b_write_pos
= plci
->li_plci_b_write_pos
;
12195 participant_parms_pos
= 0;
12197 li2_update_connect(Id
, a
, plci
, UnMapId(Id
), true, li_flags
);
12198 while (participant_parms_pos
< li_req_parms
[1].length
)
12200 result
[result_pos
] = 6;
12202 PUT_DWORD(&result
[result_pos
- 6], 0);
12203 PUT_WORD(&result
[result_pos
- 2], GOOD
);
12204 if (api_parse(&li_req_parms
[1].info
[1 + participant_parms_pos
],
12205 (word
)(li_parms
[1].length
- participant_parms_pos
), "s", li_participant_struct
))
12207 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12209 PUT_WORD(&result
[result_pos
- 2], _WRONG_MESSAGE_FORMAT
);
12212 if (api_parse(&li_participant_struct
[0].info
[1],
12213 li_participant_struct
[0].length
, "dd", li_participant_parms
))
12215 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12217 PUT_WORD(&result
[result_pos
- 2], _WRONG_MESSAGE_FORMAT
);
12220 plci_b_id
= GET_DWORD(li_participant_parms
[0].info
) & 0xffff;
12221 li_flags
= GET_DWORD(li_participant_parms
[1].info
);
12222 PUT_DWORD(&result
[result_pos
- 6], plci_b_id
);
12223 if (sizeof(result
) - result_pos
< 7)
12225 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12226 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12227 PUT_WORD(&result
[result_pos
- 2], _WRONG_STATE
);
12230 plci_b
= li2_check_plci_b(Id
, plci
, plci_b_id
, plci_b_write_pos
, &result
[result_pos
- 2]);
12231 if (plci_b
!= NULL
)
12233 li2_update_connect(Id
, a
, plci
, plci_b_id
, true, li_flags
);
12234 plci
->li_plci_b_queue
[plci_b_write_pos
] = plci_b_id
|
12235 ((li_flags
& (LI2_FLAG_INTERCONNECT_A_B
| LI2_FLAG_INTERCONNECT_B_A
|
12236 LI2_FLAG_PCCONNECT_A_B
| LI2_FLAG_PCCONNECT_B_A
)) ? 0 : LI_PLCI_B_DISC_FLAG
);
12237 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12239 participant_parms_pos
= (word
)((&li_participant_struct
[0].info
[1 + li_participant_struct
[0].length
]) -
12240 (&li_req_parms
[1].info
[1]));
12242 result
[0] = (byte
)(result_pos
- 1);
12243 result
[3] = (byte
)(result_pos
- 4);
12244 result
[6] = (byte
)(result_pos
- 7);
12245 i
= (plci_b_write_pos
== 0) ? LI_PLCI_B_QUEUE_ENTRIES
- 1 : plci_b_write_pos
- 1;
12246 if ((plci_b_write_pos
== plci
->li_plci_b_read_pos
)
12247 || (plci
->li_plci_b_queue
[i
] & LI_PLCI_B_LAST_FLAG
))
12249 plci
->li_plci_b_queue
[plci_b_write_pos
] = LI_PLCI_B_SKIP_FLAG
| LI_PLCI_B_LAST_FLAG
;
12250 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12253 plci
->li_plci_b_queue
[i
] |= LI_PLCI_B_LAST_FLAG
;
12254 plci
->li_plci_b_write_pos
= plci_b_write_pos
;
12256 mixer_calculate_coefs(a
);
12257 plci
->li_channel_bits
= li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].channel
;
12258 mixer_notify_update(plci
, true);
12259 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, Number
,
12260 "wwS", Info
, SELECTOR_LINE_INTERCONNECT
, result
);
12262 plci
->li_cmd
= GET_WORD(li_parms
[0].info
);
12263 start_internal_command(Id
, plci
, mixer_command
);
12266 case LI_REQ_DISCONNECT
:
12267 if (li_parms
[1].length
== 4)
12269 appl
->appl_flags
|= APPL_FLAG_OLD_LI_SPEC
;
12270 if (api_parse(&li_parms
[1].info
[1], li_parms
[1].length
, "d", li_req_parms
))
12272 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12273 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12274 Info
= _WRONG_MESSAGE_FORMAT
;
12277 plci_b_id
= GET_DWORD(li_req_parms
[0].info
) & 0xffff;
12278 Info
= li_check_main_plci(Id
, plci
);
12279 result_buffer
[0] = 9;
12280 result_buffer
[3] = 6;
12281 PUT_DWORD(&result_buffer
[4], GET_DWORD(li_req_parms
[0].info
));
12282 PUT_WORD(&result_buffer
[8], GOOD
);
12285 result
= plci
->saved_msg
.info
;
12286 for (i
= 0; i
<= result_buffer
[0]; i
++)
12287 result
[i
] = result_buffer
[i
];
12288 plci_b_write_pos
= plci
->li_plci_b_write_pos
;
12289 plci_b
= li_check_plci_b(Id
, plci
, plci_b_id
, plci_b_write_pos
, &result
[8]);
12290 if (plci_b
== NULL
)
12292 li_update_connect(Id
, a
, plci
, plci_b_id
, false, 0);
12293 plci
->li_plci_b_queue
[plci_b_write_pos
] = plci_b_id
| LI_PLCI_B_DISC_FLAG
| LI_PLCI_B_LAST_FLAG
;
12294 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12295 plci
->li_plci_b_write_pos
= plci_b_write_pos
;
12299 appl
->appl_flags
&= ~APPL_FLAG_OLD_LI_SPEC
;
12300 if (api_parse(&li_parms
[1].info
[1], li_parms
[1].length
, "s", li_req_parms
))
12302 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12303 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12304 Info
= _WRONG_MESSAGE_FORMAT
;
12307 Info
= li_check_main_plci(Id
, plci
);
12308 result_buffer
[0] = 7;
12309 result_buffer
[3] = 4;
12310 PUT_WORD(&result_buffer
[4], Info
);
12311 result_buffer
[6] = 0;
12314 result
= plci
->saved_msg
.info
;
12315 for (i
= 0; i
<= result_buffer
[0]; i
++)
12316 result
[i
] = result_buffer
[i
];
12317 plci_b_write_pos
= plci
->li_plci_b_write_pos
;
12318 participant_parms_pos
= 0;
12320 while (participant_parms_pos
< li_req_parms
[0].length
)
12322 result
[result_pos
] = 6;
12324 PUT_DWORD(&result
[result_pos
- 6], 0);
12325 PUT_WORD(&result
[result_pos
- 2], GOOD
);
12326 if (api_parse(&li_req_parms
[0].info
[1 + participant_parms_pos
],
12327 (word
)(li_parms
[1].length
- participant_parms_pos
), "s", li_participant_struct
))
12329 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12330 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12331 PUT_WORD(&result
[result_pos
- 2], _WRONG_MESSAGE_FORMAT
);
12334 if (api_parse(&li_participant_struct
[0].info
[1],
12335 li_participant_struct
[0].length
, "d", li_participant_parms
))
12337 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12338 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12339 PUT_WORD(&result
[result_pos
- 2], _WRONG_MESSAGE_FORMAT
);
12342 plci_b_id
= GET_DWORD(li_participant_parms
[0].info
) & 0xffff;
12343 PUT_DWORD(&result
[result_pos
- 6], plci_b_id
);
12344 if (sizeof(result
) - result_pos
< 7)
12346 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12347 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12348 PUT_WORD(&result
[result_pos
- 2], _WRONG_STATE
);
12351 plci_b
= li2_check_plci_b(Id
, plci
, plci_b_id
, plci_b_write_pos
, &result
[result_pos
- 2]);
12352 if (plci_b
!= NULL
)
12354 li2_update_connect(Id
, a
, plci
, plci_b_id
, false, 0);
12355 plci
->li_plci_b_queue
[plci_b_write_pos
] = plci_b_id
| LI_PLCI_B_DISC_FLAG
;
12356 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12358 participant_parms_pos
= (word
)((&li_participant_struct
[0].info
[1 + li_participant_struct
[0].length
]) -
12359 (&li_req_parms
[0].info
[1]));
12361 result
[0] = (byte
)(result_pos
- 1);
12362 result
[3] = (byte
)(result_pos
- 4);
12363 result
[6] = (byte
)(result_pos
- 7);
12364 i
= (plci_b_write_pos
== 0) ? LI_PLCI_B_QUEUE_ENTRIES
- 1 : plci_b_write_pos
- 1;
12365 if ((plci_b_write_pos
== plci
->li_plci_b_read_pos
)
12366 || (plci
->li_plci_b_queue
[i
] & LI_PLCI_B_LAST_FLAG
))
12368 plci
->li_plci_b_queue
[plci_b_write_pos
] = LI_PLCI_B_SKIP_FLAG
| LI_PLCI_B_LAST_FLAG
;
12369 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12372 plci
->li_plci_b_queue
[i
] |= LI_PLCI_B_LAST_FLAG
;
12373 plci
->li_plci_b_write_pos
= plci_b_write_pos
;
12375 mixer_calculate_coefs(a
);
12376 plci
->li_channel_bits
= li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].channel
;
12377 mixer_notify_update(plci
, true);
12378 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, Number
,
12379 "wwS", Info
, SELECTOR_LINE_INTERCONNECT
, result
);
12381 plci
->li_cmd
= GET_WORD(li_parms
[0].info
);
12382 start_internal_command(Id
, plci
, mixer_command
);
12385 case LI_REQ_SILENT_UPDATE
:
12386 if (!plci
|| !plci
->State
12387 || !plci
->NL
.Id
|| plci
->nl_remove_id
12388 || (plci
->li_bchannel_id
== 0)
12389 || (li_config_table
[plci
->adapter
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
!= plci
))
12391 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12392 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12395 plci_b_write_pos
= plci
->li_plci_b_write_pos
;
12396 if (((plci
->li_plci_b_read_pos
> plci_b_write_pos
) ? plci
->li_plci_b_read_pos
:
12397 LI_PLCI_B_QUEUE_ENTRIES
+ plci
->li_plci_b_read_pos
) - plci_b_write_pos
- 1 < 2)
12399 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12400 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12403 i
= (plci_b_write_pos
== 0) ? LI_PLCI_B_QUEUE_ENTRIES
- 1 : plci_b_write_pos
- 1;
12404 if ((plci_b_write_pos
== plci
->li_plci_b_read_pos
)
12405 || (plci
->li_plci_b_queue
[i
] & LI_PLCI_B_LAST_FLAG
))
12407 plci
->li_plci_b_queue
[plci_b_write_pos
] = LI_PLCI_B_SKIP_FLAG
| LI_PLCI_B_LAST_FLAG
;
12408 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12411 plci
->li_plci_b_queue
[i
] |= LI_PLCI_B_LAST_FLAG
;
12412 plci
->li_plci_b_write_pos
= plci_b_write_pos
;
12413 plci
->li_channel_bits
= li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].channel
;
12415 plci
->li_cmd
= GET_WORD(li_parms
[0].info
);
12416 start_internal_command(Id
, plci
, mixer_command
);
12420 dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12421 UnMapId(Id
), (char *)(FILE_
), __LINE__
, GET_WORD(li_parms
[0].info
)));
12422 Info
= _FACILITY_NOT_SUPPORTED
;
12425 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, Number
,
12426 "wwS", Info
, SELECTOR_LINE_INTERCONNECT
, result
);
12431 static void mixer_indication_coefs_set(dword Id
, PLCI
*plci
)
12436 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12437 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12439 if (plci
->li_plci_b_read_pos
!= plci
->li_plci_b_req_pos
)
12443 d
= plci
->li_plci_b_queue
[plci
->li_plci_b_read_pos
];
12444 if (!(d
& LI_PLCI_B_SKIP_FLAG
))
12446 if (plci
->appl
->appl_flags
& APPL_FLAG_OLD_LI_SPEC
)
12448 if (d
& LI_PLCI_B_DISC_FLAG
)
12451 PUT_WORD(&result
[1], LI_IND_DISCONNECT
);
12453 PUT_WORD(&result
[4], _LI_USER_INITIATED
);
12458 PUT_WORD(&result
[1], LI_IND_CONNECT_ACTIVE
);
12460 PUT_DWORD(&result
[4], d
& ~LI_PLCI_B_FLAG_MASK
);
12465 if (d
& LI_PLCI_B_DISC_FLAG
)
12468 PUT_WORD(&result
[1], LI_IND_DISCONNECT
);
12470 PUT_DWORD(&result
[4], d
& ~LI_PLCI_B_FLAG_MASK
);
12471 PUT_WORD(&result
[8], _LI_USER_INITIATED
);
12476 PUT_WORD(&result
[1], LI_IND_CONNECT_ACTIVE
);
12478 PUT_DWORD(&result
[4], d
& ~LI_PLCI_B_FLAG_MASK
);
12481 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0,
12482 "ws", SELECTOR_LINE_INTERCONNECT
, result
);
12484 plci
->li_plci_b_read_pos
= (plci
->li_plci_b_read_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ?
12485 0 : plci
->li_plci_b_read_pos
+ 1;
12486 } while (!(d
& LI_PLCI_B_LAST_FLAG
) && (plci
->li_plci_b_read_pos
!= plci
->li_plci_b_req_pos
));
12491 static void mixer_indication_xconnect_from(dword Id
, PLCI
*plci
, byte
*msg
, word length
)
12494 struct xconnect_transfer_address_s s
, *p
;
12495 DIVA_CAPI_ADAPTER
*a
;
12497 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12498 UnMapId(Id
), (char *)(FILE_
), __LINE__
, (int)length
));
12502 for (i
= 1; i
< length
; i
+= 16)
12504 s
.card_address
.low
= msg
[i
] | (msg
[i
+ 1] << 8) | (((dword
)(msg
[i
+ 2])) << 16) | (((dword
)(msg
[i
+ 3])) << 24);
12505 s
.card_address
.high
= msg
[i
+ 4] | (msg
[i
+ 5] << 8) | (((dword
)(msg
[i
+ 6])) << 16) | (((dword
)(msg
[i
+ 7])) << 24);
12506 s
.offset
= msg
[i
+ 8] | (msg
[i
+ 9] << 8) | (((dword
)(msg
[i
+ 10])) << 16) | (((dword
)(msg
[i
+ 11])) << 24);
12507 ch
= msg
[i
+ 12] | (msg
[i
+ 13] << 8);
12508 j
= ch
& XCONNECT_CHANNEL_NUMBER_MASK
;
12509 if (!a
->li_pri
&& (plci
->li_bchannel_id
== 2))
12512 if (ch
& XCONNECT_CHANNEL_PORT_PC
)
12513 p
= &(li_config_table
[j
].send_pc
);
12515 p
= &(li_config_table
[j
].send_b
);
12516 p
->card_address
.low
= s
.card_address
.low
;
12517 p
->card_address
.high
= s
.card_address
.high
;
12518 p
->offset
= s
.offset
;
12519 li_config_table
[j
].channel
|= LI_CHANNEL_ADDRESSES_SET
;
12521 if (plci
->internal_command_queue
[0]
12522 && ((plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_2
)
12523 || (plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_3
)
12524 || (plci
->adjust_b_state
== ADJUST_B_RESTORE_MIXER_4
)))
12526 (*(plci
->internal_command_queue
[0]))(Id
, plci
, 0);
12527 if (!plci
->internal_command
)
12528 next_internal_command(Id
, plci
);
12530 mixer_notify_update(plci
, true);
12534 static void mixer_indication_xconnect_to(dword Id
, PLCI
*plci
, byte
*msg
, word length
)
12537 dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12538 UnMapId(Id
), (char *)(FILE_
), __LINE__
, (int) length
));
12543 static byte
mixer_notify_source_removed(PLCI
*plci
, dword plci_b_id
)
12545 word plci_b_write_pos
;
12547 plci_b_write_pos
= plci
->li_plci_b_write_pos
;
12548 if (((plci
->li_plci_b_read_pos
> plci_b_write_pos
) ? plci
->li_plci_b_read_pos
:
12549 LI_PLCI_B_QUEUE_ENTRIES
+ plci
->li_plci_b_read_pos
) - plci_b_write_pos
- 1 < 1)
12551 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12552 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
12553 (char *)(FILE_
), __LINE__
));
12556 plci
->li_plci_b_queue
[plci_b_write_pos
] = plci_b_id
| LI_PLCI_B_DISC_FLAG
;
12557 plci_b_write_pos
= (plci_b_write_pos
== LI_PLCI_B_QUEUE_ENTRIES
- 1) ? 0 : plci_b_write_pos
+ 1;
12558 plci
->li_plci_b_write_pos
= plci_b_write_pos
;
12563 static void mixer_remove(PLCI
*plci
)
12565 DIVA_CAPI_ADAPTER
*a
;
12570 dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12571 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
12572 (char *)(FILE_
), __LINE__
));
12575 plci_b_id
= (plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
);
12576 if (a
->profile
.Global_Options
& GL_LINE_INTERCONNECT_SUPPORTED
)
12578 if ((plci
->li_bchannel_id
!= 0)
12579 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
12581 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
12582 if ((li_config_table
[i
].curchnl
| li_config_table
[i
].channel
) & LI_CHANNEL_INVOLVED
)
12584 for (j
= 0; j
< li_total_channels
; j
++)
12586 if ((li_config_table
[i
].flag_table
[j
] & LI_FLAG_INTERCONNECT
)
12587 || (li_config_table
[j
].flag_table
[i
] & LI_FLAG_INTERCONNECT
))
12589 notify_plci
= li_config_table
[j
].plci
;
12590 if ((notify_plci
!= NULL
)
12591 && (notify_plci
!= plci
)
12592 && (notify_plci
->appl
!= NULL
)
12593 && !(notify_plci
->appl
->appl_flags
& APPL_FLAG_OLD_LI_SPEC
)
12594 && (notify_plci
->State
)
12595 && notify_plci
->NL
.Id
&& !notify_plci
->nl_remove_id
)
12597 mixer_notify_source_removed(notify_plci
, plci_b_id
);
12601 mixer_clear_config(plci
);
12602 mixer_calculate_coefs(a
);
12603 mixer_notify_update(plci
, true);
12605 li_config_table
[i
].plci
= NULL
;
12606 plci
->li_bchannel_id
= 0;
12612 /*------------------------------------------------------------------*/
12613 /* Echo canceller facilities */
12614 /*------------------------------------------------------------------*/
12617 static void ec_write_parameters(PLCI
*plci
)
12620 byte parameter_buffer
[6];
12622 dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12623 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
12624 (char *)(FILE_
), __LINE__
));
12626 parameter_buffer
[0] = 5;
12627 parameter_buffer
[1] = DSP_CTRL_SET_LEC_PARAMETERS
;
12628 PUT_WORD(¶meter_buffer
[2], plci
->ec_idi_options
);
12629 plci
->ec_idi_options
&= ~LEC_RESET_COEFFICIENTS
;
12630 w
= (plci
->ec_tail_length
== 0) ? 128 : plci
->ec_tail_length
;
12631 PUT_WORD(¶meter_buffer
[4], w
);
12632 add_p(plci
, FTY
, parameter_buffer
);
12633 sig_req(plci
, TEL_CTRL
, 0);
12638 static void ec_clear_config(PLCI
*plci
)
12641 dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12642 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
12643 (char *)(FILE_
), __LINE__
));
12645 plci
->ec_idi_options
= LEC_ENABLE_ECHO_CANCELLER
|
12646 LEC_MANUAL_DISABLE
| LEC_ENABLE_NONLINEAR_PROCESSING
;
12647 plci
->ec_tail_length
= 0;
12651 static void ec_prepare_switch(dword Id
, PLCI
*plci
)
12654 dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12655 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12660 static word
ec_save_config(dword Id
, PLCI
*plci
, byte Rc
)
12663 dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12664 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
12670 static word
ec_restore_config(dword Id
, PLCI
*plci
, byte Rc
)
12674 dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12675 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
12678 if (plci
->B1_facilities
& B1_FACILITY_EC
)
12680 switch (plci
->adjust_b_state
)
12682 case ADJUST_B_RESTORE_EC_1
:
12683 plci
->internal_command
= plci
->adjust_b_command
;
12686 plci
->adjust_b_state
= ADJUST_B_RESTORE_EC_1
;
12689 ec_write_parameters(plci
);
12690 plci
->adjust_b_state
= ADJUST_B_RESTORE_EC_2
;
12692 case ADJUST_B_RESTORE_EC_2
:
12693 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
12695 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12696 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
12697 Info
= _WRONG_STATE
;
12707 static void ec_command(dword Id
, PLCI
*plci
, byte Rc
)
12709 word internal_command
, Info
;
12712 dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12713 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
,
12714 plci
->ec_cmd
, plci
->ec_idi_options
, plci
->ec_tail_length
));
12717 if (plci
->appl
->appl_flags
& APPL_FLAG_PRIV_EC_SPEC
)
12720 PUT_WORD(&result
[1], EC_SUCCESS
);
12725 PUT_WORD(&result
[1], plci
->ec_cmd
);
12727 PUT_WORD(&result
[4], GOOD
);
12729 internal_command
= plci
->internal_command
;
12730 plci
->internal_command
= 0;
12731 switch (plci
->ec_cmd
)
12733 case EC_ENABLE_OPERATION
:
12734 case EC_FREEZE_COEFFICIENTS
:
12735 case EC_RESUME_COEFFICIENT_UPDATE
:
12736 case EC_RESET_COEFFICIENTS
:
12737 switch (internal_command
)
12740 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
|
12741 B1_FACILITY_EC
), EC_COMMAND_1
);
12743 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
12745 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12746 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12747 Info
= _FACILITY_NOT_SUPPORTED
;
12750 if (plci
->internal_command
)
12755 plci
->internal_command
= EC_COMMAND_2
;
12758 plci
->internal_command
= EC_COMMAND_3
;
12759 ec_write_parameters(plci
);
12762 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
12764 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12765 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
12766 Info
= _FACILITY_NOT_SUPPORTED
;
12773 case EC_DISABLE_OPERATION
:
12774 switch (internal_command
)
12778 if (plci
->B1_facilities
& B1_FACILITY_EC
)
12782 plci
->internal_command
= EC_COMMAND_1
;
12785 plci
->internal_command
= EC_COMMAND_2
;
12786 ec_write_parameters(plci
);
12791 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
12793 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12794 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
12795 Info
= _FACILITY_NOT_SUPPORTED
;
12798 adjust_b1_resource(Id
, plci
, NULL
, (word
)(plci
->B1_facilities
&
12799 ~B1_FACILITY_EC
), EC_COMMAND_3
);
12801 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
12803 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12804 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12805 Info
= _FACILITY_NOT_SUPPORTED
;
12808 if (plci
->internal_command
)
12814 sendf(plci
->appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, plci
->number
,
12815 "wws", Info
, (plci
->appl
->appl_flags
& APPL_FLAG_PRIV_EC_SPEC
) ?
12816 PRIV_SELECTOR_ECHO_CANCELLER
: SELECTOR_ECHO_CANCELLER
, result
);
12820 static byte
ec_request(dword Id
, word Number
, DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
, APPL
*appl
, API_PARSE
*msg
)
12824 API_PARSE ec_parms
[3];
12827 dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12828 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12832 if (!(a
->man_profile
.private_options
& (1L << PRIVATE_ECHO_CANCELLER
)))
12834 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12835 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12836 Info
= _FACILITY_NOT_SUPPORTED
;
12840 if (appl
->appl_flags
& APPL_FLAG_PRIV_EC_SPEC
)
12842 if (api_parse(&msg
[1].info
[1], msg
[1].length
, "w", ec_parms
))
12844 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12845 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12846 Info
= _WRONG_MESSAGE_FORMAT
;
12852 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12853 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12854 Info
= _WRONG_IDENTIFIER
;
12856 else if (!plci
->State
|| !plci
->NL
.Id
|| plci
->nl_remove_id
)
12858 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12859 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12860 Info
= _WRONG_STATE
;
12865 plci
->ec_cmd
= GET_WORD(ec_parms
[0].info
);
12866 plci
->ec_idi_options
&= ~(LEC_MANUAL_DISABLE
| LEC_RESET_COEFFICIENTS
);
12868 PUT_WORD(&result
[1], EC_SUCCESS
);
12869 if (msg
[1].length
>= 4)
12871 opt
= GET_WORD(&ec_parms
[0].info
[2]);
12872 plci
->ec_idi_options
&= ~(LEC_ENABLE_NONLINEAR_PROCESSING
|
12873 LEC_ENABLE_2100HZ_DETECTOR
| LEC_REQUIRE_2100HZ_REVERSALS
);
12874 if (!(opt
& EC_DISABLE_NON_LINEAR_PROCESSING
))
12875 plci
->ec_idi_options
|= LEC_ENABLE_NONLINEAR_PROCESSING
;
12876 if (opt
& EC_DETECT_DISABLE_TONE
)
12877 plci
->ec_idi_options
|= LEC_ENABLE_2100HZ_DETECTOR
;
12878 if (!(opt
& EC_DO_NOT_REQUIRE_REVERSALS
))
12879 plci
->ec_idi_options
|= LEC_REQUIRE_2100HZ_REVERSALS
;
12880 if (msg
[1].length
>= 6)
12882 plci
->ec_tail_length
= GET_WORD(&ec_parms
[0].info
[4]);
12885 switch (plci
->ec_cmd
)
12887 case EC_ENABLE_OPERATION
:
12888 plci
->ec_idi_options
&= ~LEC_FREEZE_COEFFICIENTS
;
12889 start_internal_command(Id
, plci
, ec_command
);
12892 case EC_DISABLE_OPERATION
:
12893 plci
->ec_idi_options
= LEC_ENABLE_ECHO_CANCELLER
|
12894 LEC_MANUAL_DISABLE
| LEC_ENABLE_NONLINEAR_PROCESSING
|
12895 LEC_RESET_COEFFICIENTS
;
12896 start_internal_command(Id
, plci
, ec_command
);
12899 case EC_FREEZE_COEFFICIENTS
:
12900 plci
->ec_idi_options
|= LEC_FREEZE_COEFFICIENTS
;
12901 start_internal_command(Id
, plci
, ec_command
);
12904 case EC_RESUME_COEFFICIENT_UPDATE
:
12905 plci
->ec_idi_options
&= ~LEC_FREEZE_COEFFICIENTS
;
12906 start_internal_command(Id
, plci
, ec_command
);
12909 case EC_RESET_COEFFICIENTS
:
12910 plci
->ec_idi_options
|= LEC_RESET_COEFFICIENTS
;
12911 start_internal_command(Id
, plci
, ec_command
);
12915 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12916 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci
->ec_cmd
));
12917 PUT_WORD(&result
[1], EC_UNSUPPORTED_OPERATION
);
12924 if (api_parse(&msg
[1].info
[1], msg
[1].length
, "ws", ec_parms
))
12926 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12927 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12928 Info
= _WRONG_MESSAGE_FORMAT
;
12932 if (GET_WORD(ec_parms
[0].info
) == EC_GET_SUPPORTED_SERVICES
)
12935 PUT_WORD(&result
[1], EC_GET_SUPPORTED_SERVICES
);
12937 PUT_WORD(&result
[4], GOOD
);
12938 PUT_WORD(&result
[6], 0x0007);
12939 PUT_WORD(&result
[8], LEC_MAX_SUPPORTED_TAIL_LENGTH
);
12940 PUT_WORD(&result
[10], 0);
12942 else if (plci
== NULL
)
12944 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12945 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12946 Info
= _WRONG_IDENTIFIER
;
12948 else if (!plci
->State
|| !plci
->NL
.Id
|| plci
->nl_remove_id
)
12950 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12951 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
12952 Info
= _WRONG_STATE
;
12957 plci
->ec_cmd
= GET_WORD(ec_parms
[0].info
);
12958 plci
->ec_idi_options
&= ~(LEC_MANUAL_DISABLE
| LEC_RESET_COEFFICIENTS
);
12960 PUT_WORD(&result
[1], plci
->ec_cmd
);
12962 PUT_WORD(&result
[4], GOOD
);
12963 plci
->ec_idi_options
&= ~(LEC_ENABLE_NONLINEAR_PROCESSING
|
12964 LEC_ENABLE_2100HZ_DETECTOR
| LEC_REQUIRE_2100HZ_REVERSALS
);
12965 plci
->ec_tail_length
= 0;
12966 if (ec_parms
[1].length
>= 2)
12968 opt
= GET_WORD(&ec_parms
[1].info
[1]);
12969 if (opt
& EC_ENABLE_NON_LINEAR_PROCESSING
)
12970 plci
->ec_idi_options
|= LEC_ENABLE_NONLINEAR_PROCESSING
;
12971 if (opt
& EC_DETECT_DISABLE_TONE
)
12972 plci
->ec_idi_options
|= LEC_ENABLE_2100HZ_DETECTOR
;
12973 if (!(opt
& EC_DO_NOT_REQUIRE_REVERSALS
))
12974 plci
->ec_idi_options
|= LEC_REQUIRE_2100HZ_REVERSALS
;
12975 if (ec_parms
[1].length
>= 4)
12977 plci
->ec_tail_length
= GET_WORD(&ec_parms
[1].info
[3]);
12980 switch (plci
->ec_cmd
)
12982 case EC_ENABLE_OPERATION
:
12983 plci
->ec_idi_options
&= ~LEC_FREEZE_COEFFICIENTS
;
12984 start_internal_command(Id
, plci
, ec_command
);
12987 case EC_DISABLE_OPERATION
:
12988 plci
->ec_idi_options
= LEC_ENABLE_ECHO_CANCELLER
|
12989 LEC_MANUAL_DISABLE
| LEC_ENABLE_NONLINEAR_PROCESSING
|
12990 LEC_RESET_COEFFICIENTS
;
12991 start_internal_command(Id
, plci
, ec_command
);
12995 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12996 UnMapId(Id
), (char *)(FILE_
), __LINE__
, plci
->ec_cmd
));
12997 PUT_WORD(&result
[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP
);
13003 sendf(appl
, _FACILITY_R
| CONFIRM
, Id
& 0xffffL
, Number
,
13004 "wws", Info
, (appl
->appl_flags
& APPL_FLAG_PRIV_EC_SPEC
) ?
13005 PRIV_SELECTOR_ECHO_CANCELLER
: SELECTOR_ECHO_CANCELLER
, result
);
13010 static void ec_indication(dword Id
, PLCI
*plci
, byte
*msg
, word length
)
13014 dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13015 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
13017 if (!(plci
->ec_idi_options
& LEC_MANUAL_DISABLE
))
13019 if (plci
->appl
->appl_flags
& APPL_FLAG_PRIV_EC_SPEC
)
13022 PUT_WORD(&result
[1], 0);
13025 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ
:
13026 PUT_WORD(&result
[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ
);
13028 case LEC_DISABLE_TYPE_REVERSED_2100HZ
:
13029 PUT_WORD(&result
[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ
);
13031 case LEC_DISABLE_RELEASED
:
13032 PUT_WORD(&result
[1], EC_BYPASS_RELEASED
);
13039 PUT_WORD(&result
[1], EC_BYPASS_INDICATION
);
13041 PUT_WORD(&result
[4], 0);
13044 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ
:
13045 PUT_WORD(&result
[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ
);
13047 case LEC_DISABLE_TYPE_REVERSED_2100HZ
:
13048 PUT_WORD(&result
[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ
);
13050 case LEC_DISABLE_RELEASED
:
13051 PUT_WORD(&result
[4], EC_BYPASS_RELEASED
);
13055 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0, "ws", (plci
->appl
->appl_flags
& APPL_FLAG_PRIV_EC_SPEC
) ?
13056 PRIV_SELECTOR_ECHO_CANCELLER
: SELECTOR_ECHO_CANCELLER
, result
);
13062 /*------------------------------------------------------------------*/
13063 /* Advanced voice */
13064 /*------------------------------------------------------------------*/
13066 static void adv_voice_write_coefs(PLCI
*plci
, word write_command
)
13068 DIVA_CAPI_ADAPTER
*a
;
13073 byte ch_map
[MIXER_CHANNELS_BRI
];
13075 byte coef_buffer
[ADV_VOICE_COEF_BUFFER_SIZE
+ 2];
13077 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13078 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13079 (char *)(FILE_
), __LINE__
, write_command
));
13082 p
= coef_buffer
+ 1;
13083 *(p
++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS
;
13085 while (i
+ sizeof(word
) <= a
->adv_voice_coef_length
)
13087 PUT_WORD(p
, GET_WORD(a
->adv_voice_coef_buffer
+ i
));
13091 while (i
< ADV_VOICE_OLD_COEF_COUNT
* sizeof(word
))
13093 PUT_WORD(p
, 0x8000);
13098 if (!a
->li_pri
&& (plci
->li_bchannel_id
== 0))
13100 if ((li_config_table
[a
->li_base
].plci
== NULL
) && (li_config_table
[a
->li_base
+ 1].plci
!= NULL
))
13102 plci
->li_bchannel_id
= 1;
13103 li_config_table
[a
->li_base
].plci
= plci
;
13104 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13105 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13106 (char *)(FILE_
), __LINE__
, plci
->li_bchannel_id
));
13108 else if ((li_config_table
[a
->li_base
].plci
!= NULL
) && (li_config_table
[a
->li_base
+ 1].plci
== NULL
))
13110 plci
->li_bchannel_id
= 2;
13111 li_config_table
[a
->li_base
+ 1].plci
= plci
;
13112 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13114 (char *)(FILE_
), __LINE__
, plci
->li_bchannel_id
));
13117 if (!a
->li_pri
&& (plci
->li_bchannel_id
!= 0)
13118 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
13120 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
13121 switch (write_command
)
13123 case ADV_VOICE_WRITE_ACTIVATION
:
13124 j
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (plci
->li_bchannel_id
- 1);
13125 k
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
);
13126 if (!(plci
->B1_facilities
& B1_FACILITY_MIXER
))
13128 li_config_table
[j
].flag_table
[i
] |= LI_FLAG_CONFERENCE
| LI_FLAG_MIX
;
13129 li_config_table
[i
].flag_table
[j
] |= LI_FLAG_CONFERENCE
| LI_FLAG_MONITOR
;
13131 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
)
13133 li_config_table
[k
].flag_table
[i
] |= LI_FLAG_CONFERENCE
| LI_FLAG_MIX
;
13134 li_config_table
[i
].flag_table
[k
] |= LI_FLAG_CONFERENCE
| LI_FLAG_MONITOR
;
13135 li_config_table
[k
].flag_table
[j
] |= LI_FLAG_CONFERENCE
;
13136 li_config_table
[j
].flag_table
[k
] |= LI_FLAG_CONFERENCE
;
13138 mixer_calculate_coefs(a
);
13139 li_config_table
[i
].curchnl
= li_config_table
[i
].channel
;
13140 li_config_table
[j
].curchnl
= li_config_table
[j
].channel
;
13141 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
)
13142 li_config_table
[k
].curchnl
= li_config_table
[k
].channel
;
13145 case ADV_VOICE_WRITE_DEACTIVATION
:
13146 for (j
= 0; j
< li_total_channels
; j
++)
13148 li_config_table
[i
].flag_table
[j
] = 0;
13149 li_config_table
[j
].flag_table
[i
] = 0;
13151 k
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (plci
->li_bchannel_id
- 1);
13152 for (j
= 0; j
< li_total_channels
; j
++)
13154 li_config_table
[k
].flag_table
[j
] = 0;
13155 li_config_table
[j
].flag_table
[k
] = 0;
13157 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
)
13159 k
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
);
13160 for (j
= 0; j
< li_total_channels
; j
++)
13162 li_config_table
[k
].flag_table
[j
] = 0;
13163 li_config_table
[j
].flag_table
[k
] = 0;
13166 mixer_calculate_coefs(a
);
13169 if (plci
->B1_facilities
& B1_FACILITY_MIXER
)
13172 if (ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) <= a
->adv_voice_coef_length
)
13173 w
= GET_WORD(a
->adv_voice_coef_buffer
+ ADV_VOICE_NEW_COEF_BASE
);
13174 if (li_config_table
[i
].channel
& LI_CHANNEL_TX_DATA
)
13175 w
|= MIXER_FEATURE_ENABLE_TX_DATA
;
13176 if (li_config_table
[i
].channel
& LI_CHANNEL_RX_DATA
)
13177 w
|= MIXER_FEATURE_ENABLE_RX_DATA
;
13179 *(p
++) = (byte
)(w
>> 8);
13180 for (j
= 0; j
< sizeof(ch_map
); j
+= 2)
13182 ch_map
[j
] = (byte
)(j
+ (plci
->li_bchannel_id
- 1));
13183 ch_map
[j
+ 1] = (byte
)(j
+ (2 - plci
->li_bchannel_id
));
13185 for (n
= 0; n
< ARRAY_SIZE(mixer_write_prog_bri
); n
++)
13187 i
= a
->li_base
+ ch_map
[mixer_write_prog_bri
[n
].to_ch
];
13188 j
= a
->li_base
+ ch_map
[mixer_write_prog_bri
[n
].from_ch
];
13189 if (li_config_table
[i
].channel
& li_config_table
[j
].channel
& LI_CHANNEL_INVOLVED
)
13191 *(p
++) = ((li_config_table
[i
].coef_table
[j
] & mixer_write_prog_bri
[n
].mask
) ? 0x80 : 0x01);
13192 w
= ((li_config_table
[i
].coef_table
[j
] & 0xf) ^ (li_config_table
[i
].coef_table
[j
] >> 4));
13193 li_config_table
[i
].coef_table
[j
] ^= (w
& mixer_write_prog_bri
[n
].mask
) << 4;
13197 *(p
++) = (ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) + n
< a
->adv_voice_coef_length
) ?
13198 a
->adv_voice_coef_buffer
[ADV_VOICE_NEW_COEF_BASE
+ sizeof(word
) + n
] : 0x00;
13204 for (i
= ADV_VOICE_NEW_COEF_BASE
; i
< a
->adv_voice_coef_length
; i
++)
13205 *(p
++) = a
->adv_voice_coef_buffer
[i
];
13211 for (i
= ADV_VOICE_NEW_COEF_BASE
; i
< a
->adv_voice_coef_length
; i
++)
13212 *(p
++) = a
->adv_voice_coef_buffer
[i
];
13214 coef_buffer
[0] = (p
- coef_buffer
) - 1;
13215 add_p(plci
, FTY
, coef_buffer
);
13216 sig_req(plci
, TEL_CTRL
, 0);
13221 static void adv_voice_clear_config(PLCI
*plci
)
13223 DIVA_CAPI_ADAPTER
*a
;
13228 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13229 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13230 (char *)(FILE_
), __LINE__
));
13233 if ((plci
->tel
== ADV_VOICE
) && (plci
== a
->AdvSignalPLCI
))
13235 a
->adv_voice_coef_length
= 0;
13237 if (!a
->li_pri
&& (plci
->li_bchannel_id
!= 0)
13238 && (li_config_table
[a
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
13240 i
= a
->li_base
+ (plci
->li_bchannel_id
- 1);
13241 li_config_table
[i
].curchnl
= 0;
13242 li_config_table
[i
].channel
= 0;
13243 li_config_table
[i
].chflags
= 0;
13244 for (j
= 0; j
< li_total_channels
; j
++)
13246 li_config_table
[i
].flag_table
[j
] = 0;
13247 li_config_table
[j
].flag_table
[i
] = 0;
13248 li_config_table
[i
].coef_table
[j
] = 0;
13249 li_config_table
[j
].coef_table
[i
] = 0;
13251 li_config_table
[i
].coef_table
[i
] |= LI_COEF_CH_PC_SET
| LI_COEF_PC_CH_SET
;
13252 i
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (plci
->li_bchannel_id
- 1);
13253 li_config_table
[i
].curchnl
= 0;
13254 li_config_table
[i
].channel
= 0;
13255 li_config_table
[i
].chflags
= 0;
13256 for (j
= 0; j
< li_total_channels
; j
++)
13258 li_config_table
[i
].flag_table
[j
] = 0;
13259 li_config_table
[j
].flag_table
[i
] = 0;
13260 li_config_table
[i
].coef_table
[j
] = 0;
13261 li_config_table
[j
].coef_table
[i
] = 0;
13263 if (a
->manufacturer_features
& MANUFACTURER_FEATURE_SLAVE_CODEC
)
13265 i
= a
->li_base
+ MIXER_IC_CHANNEL_BASE
+ (2 - plci
->li_bchannel_id
);
13266 li_config_table
[i
].curchnl
= 0;
13267 li_config_table
[i
].channel
= 0;
13268 li_config_table
[i
].chflags
= 0;
13269 for (j
= 0; j
< li_total_channels
; j
++)
13271 li_config_table
[i
].flag_table
[j
] = 0;
13272 li_config_table
[j
].flag_table
[i
] = 0;
13273 li_config_table
[i
].coef_table
[j
] = 0;
13274 li_config_table
[j
].coef_table
[i
] = 0;
13283 static void adv_voice_prepare_switch(dword Id
, PLCI
*plci
)
13286 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13287 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
13292 static word
adv_voice_save_config(dword Id
, PLCI
*plci
, byte Rc
)
13295 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13296 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
13302 static word
adv_voice_restore_config(dword Id
, PLCI
*plci
, byte Rc
)
13304 DIVA_CAPI_ADAPTER
*a
;
13307 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13308 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
13312 if ((plci
->B1_facilities
& B1_FACILITY_VOICE
)
13313 && (plci
->tel
== ADV_VOICE
) && (plci
== a
->AdvSignalPLCI
))
13315 switch (plci
->adjust_b_state
)
13317 case ADJUST_B_RESTORE_VOICE_1
:
13318 plci
->internal_command
= plci
->adjust_b_command
;
13321 plci
->adjust_b_state
= ADJUST_B_RESTORE_VOICE_1
;
13324 adv_voice_write_coefs(plci
, ADV_VOICE_WRITE_UPDATE
);
13325 plci
->adjust_b_state
= ADJUST_B_RESTORE_VOICE_2
;
13327 case ADJUST_B_RESTORE_VOICE_2
:
13328 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
13330 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13331 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
13332 Info
= _WRONG_STATE
;
13344 /*------------------------------------------------------------------*/
13345 /* B1 resource switching */
13346 /*------------------------------------------------------------------*/
13348 static byte b1_facilities_table
[] =
13350 0x00, /* 0 No bchannel resources */
13351 0x00, /* 1 Codec (automatic law) */
13352 0x00, /* 2 Codec (A-law) */
13353 0x00, /* 3 Codec (y-law) */
13354 0x00, /* 4 HDLC for X.21 */
13356 0x00, /* 6 External Device 0 */
13357 0x00, /* 7 External Device 1 */
13358 0x00, /* 8 HDLC 56k */
13359 0x00, /* 9 Transparent */
13360 0x00, /* 10 Loopback to network */
13361 0x00, /* 11 Test pattern to net */
13362 0x00, /* 12 Rate adaptation sync */
13363 0x00, /* 13 Rate adaptation async */
13364 0x00, /* 14 R-Interface */
13365 0x00, /* 15 HDLC 128k leased line */
13367 0x00, /* 17 Modem async */
13368 0x00, /* 18 Modem sync HDLC */
13369 0x00, /* 19 V.110 async HDLC */
13370 0x12, /* 20 Adv voice (Trans,mixer) */
13371 0x00, /* 21 Codec connected to IC */
13372 0x0c, /* 22 Trans,DTMF */
13373 0x1e, /* 23 Trans,DTMF+mixer */
13374 0x1f, /* 24 Trans,DTMF+mixer+local */
13375 0x13, /* 25 Trans,mixer+local */
13376 0x12, /* 26 HDLC,mixer */
13377 0x12, /* 27 HDLC 56k,mixer */
13378 0x2c, /* 28 Trans,LEC+DTMF */
13379 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13380 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13381 0x2c, /* 31 RTP,LEC+DTMF */
13382 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13383 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13384 0x00, /* 34 Signaling task */
13385 0x00, /* 35 PIAFS */
13386 0x0c, /* 36 Trans,DTMF+TONE */
13387 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13388 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13392 static word
get_b1_facilities(PLCI
*plci
, byte b1_resource
)
13394 word b1_facilities
;
13396 b1_facilities
= b1_facilities_table
[b1_resource
];
13397 if ((b1_resource
== 9) || (b1_resource
== 20) || (b1_resource
== 25))
13400 if (!(((plci
->requested_options_conn
| plci
->requested_options
) & (1L << PRIVATE_DTMF_TONE
))
13401 || (plci
->appl
&& (plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1] & (1L << PRIVATE_DTMF_TONE
)))))
13404 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_SOFTDTMF_SEND
)
13405 b1_facilities
|= B1_FACILITY_DTMFX
;
13406 if (plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE
)
13407 b1_facilities
|= B1_FACILITY_DTMFR
;
13410 if ((b1_resource
== 17) || (b1_resource
== 18))
13412 if (plci
->adapter
->manufacturer_features
& (MANUFACTURER_FEATURE_V18
| MANUFACTURER_FEATURE_VOWN
))
13413 b1_facilities
|= B1_FACILITY_DTMFX
| B1_FACILITY_DTMFR
;
13416 dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13417 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13418 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13420 return (b1_facilities
);
13424 static byte
add_b1_facilities(PLCI
*plci
, byte b1_resource
, word b1_facilities
)
13428 switch (b1_resource
)
13432 if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13440 if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13458 if (b1_facilities
& B1_FACILITY_EC
)
13460 if (b1_facilities
& B1_FACILITY_LOCAL
)
13462 else if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13468 else if ((b1_facilities
& (B1_FACILITY_DTMFX
| B1_FACILITY_DTMFR
| B1_FACILITY_MIXER
))
13469 && (((plci
->requested_options_conn
| plci
->requested_options
) & (1L << PRIVATE_DTMF_TONE
))
13470 || (plci
->appl
&& (plci
->adapter
->requested_options_table
[plci
->appl
->Id
- 1] & (1L << PRIVATE_DTMF_TONE
)))))
13472 if (b1_facilities
& B1_FACILITY_LOCAL
)
13474 else if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13480 else if (((plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_HARDDTMF
)
13481 && !(plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE
))
13482 || ((b1_facilities
& B1_FACILITY_DTMFR
)
13483 && ((b1_facilities
& B1_FACILITY_MIXER
)
13484 || !(plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE
)))
13485 || ((b1_facilities
& B1_FACILITY_DTMFX
)
13486 && ((b1_facilities
& B1_FACILITY_MIXER
)
13487 || !(plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_SOFTDTMF_SEND
))))
13489 if (b1_facilities
& B1_FACILITY_LOCAL
)
13491 else if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13498 if (b1_facilities
& B1_FACILITY_LOCAL
)
13500 else if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13510 if (b1_facilities
& B1_FACILITY_LOCAL
)
13512 else if (b1_facilities
& (B1_FACILITY_MIXER
| B1_FACILITY_VOICE
))
13521 dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13522 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13523 (char *)(FILE_
), __LINE__
,
13524 b1_resource
, b1_facilities
, b
, get_b1_facilities(plci
, b
)));
13529 static void adjust_b1_facilities(PLCI
*plci
, byte new_b1_resource
, word new_b1_facilities
)
13531 word removed_facilities
;
13533 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13534 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13535 (char *)(FILE_
), __LINE__
, new_b1_resource
, new_b1_facilities
,
13536 new_b1_facilities
& get_b1_facilities(plci
, new_b1_resource
)));
13538 new_b1_facilities
&= get_b1_facilities(plci
, new_b1_resource
);
13539 removed_facilities
= plci
->B1_facilities
& ~new_b1_facilities
;
13541 if (removed_facilities
& B1_FACILITY_EC
)
13542 ec_clear_config(plci
);
13545 if (removed_facilities
& B1_FACILITY_DTMFR
)
13547 dtmf_rec_clear_config(plci
);
13548 dtmf_parameter_clear_config(plci
);
13550 if (removed_facilities
& B1_FACILITY_DTMFX
)
13551 dtmf_send_clear_config(plci
);
13554 if (removed_facilities
& B1_FACILITY_MIXER
)
13555 mixer_clear_config(plci
);
13557 if (removed_facilities
& B1_FACILITY_VOICE
)
13558 adv_voice_clear_config(plci
);
13559 plci
->B1_facilities
= new_b1_facilities
;
13563 static void adjust_b_clear(PLCI
*plci
)
13566 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13567 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
13568 (char *)(FILE_
), __LINE__
));
13570 plci
->adjust_b_restore
= false;
13574 static word
adjust_b_process(dword Id
, PLCI
*plci
, byte Rc
)
13581 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13582 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->adjust_b_state
));
13585 switch (plci
->adjust_b_state
)
13587 case ADJUST_B_START
:
13588 if ((plci
->adjust_b_parms_msg
== NULL
)
13589 && (plci
->adjust_b_mode
& ADJUST_B_MODE_SWITCH_L1
)
13590 && ((plci
->adjust_b_mode
& ~(ADJUST_B_MODE_SAVE
| ADJUST_B_MODE_SWITCH_L1
|
13591 ADJUST_B_MODE_NO_RESOURCE
| ADJUST_B_MODE_RESTORE
)) == 0))
13593 b1_resource
= (plci
->adjust_b_mode
== ADJUST_B_MODE_NO_RESOURCE
) ?
13594 0 : add_b1_facilities(plci
, plci
->B1_resource
, plci
->adjust_b_facilities
);
13595 if (b1_resource
== plci
->B1_resource
)
13597 adjust_b1_facilities(plci
, b1_resource
, plci
->adjust_b_facilities
);
13600 if (plci
->adjust_b_facilities
& ~get_b1_facilities(plci
, b1_resource
))
13602 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13603 UnMapId(Id
), (char *)(FILE_
), __LINE__
,
13604 plci
->B1_resource
, b1_resource
, plci
->adjust_b_facilities
));
13605 Info
= _WRONG_STATE
;
13609 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SAVE
)
13612 mixer_prepare_switch(Id
, plci
);
13615 dtmf_prepare_switch(Id
, plci
);
13616 dtmf_parameter_prepare_switch(Id
, plci
);
13619 ec_prepare_switch(Id
, plci
);
13621 adv_voice_prepare_switch(Id
, plci
);
13623 plci
->adjust_b_state
= ADJUST_B_SAVE_MIXER_1
;
13625 case ADJUST_B_SAVE_MIXER_1
:
13626 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SAVE
)
13629 Info
= mixer_save_config(Id
, plci
, Rc
);
13630 if ((Info
!= GOOD
) || plci
->internal_command
)
13634 plci
->adjust_b_state
= ADJUST_B_SAVE_DTMF_1
;
13636 case ADJUST_B_SAVE_DTMF_1
:
13637 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SAVE
)
13640 Info
= dtmf_save_config(Id
, plci
, Rc
);
13641 if ((Info
!= GOOD
) || plci
->internal_command
)
13645 plci
->adjust_b_state
= ADJUST_B_REMOVE_L23_1
;
13646 case ADJUST_B_REMOVE_L23_1
:
13647 if ((plci
->adjust_b_mode
& ADJUST_B_MODE_REMOVE_L23
)
13648 && plci
->NL
.Id
&& !plci
->nl_remove_id
)
13650 plci
->internal_command
= plci
->adjust_b_command
;
13651 if (plci
->adjust_b_ncci
!= 0)
13653 ncci_ptr
= &(plci
->adapter
->ncci
[plci
->adjust_b_ncci
]);
13654 while (ncci_ptr
->data_pending
)
13656 plci
->data_sent_ptr
= ncci_ptr
->DBuffer
[ncci_ptr
->data_out
].P
;
13657 data_rc(plci
, plci
->adapter
->ncci_ch
[plci
->adjust_b_ncci
]);
13659 while (ncci_ptr
->data_ack_pending
)
13660 data_ack(plci
, plci
->adapter
->ncci_ch
[plci
->adjust_b_ncci
]);
13662 nl_req_ncci(plci
, REMOVE
,
13663 (byte
)((plci
->adjust_b_mode
& ADJUST_B_MODE_CONNECT
) ? plci
->adjust_b_ncci
: 0));
13665 plci
->adjust_b_state
= ADJUST_B_REMOVE_L23_2
;
13668 plci
->adjust_b_state
= ADJUST_B_REMOVE_L23_2
;
13670 case ADJUST_B_REMOVE_L23_2
:
13671 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
13673 dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13674 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
13675 Info
= _WRONG_STATE
;
13678 if (plci
->adjust_b_mode
& ADJUST_B_MODE_REMOVE_L23
)
13680 if (plci_nl_busy(plci
))
13682 plci
->internal_command
= plci
->adjust_b_command
;
13686 plci
->adjust_b_state
= ADJUST_B_SAVE_EC_1
;
13688 case ADJUST_B_SAVE_EC_1
:
13689 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SAVE
)
13692 Info
= ec_save_config(Id
, plci
, Rc
);
13693 if ((Info
!= GOOD
) || plci
->internal_command
)
13697 plci
->adjust_b_state
= ADJUST_B_SAVE_DTMF_PARAMETER_1
;
13699 case ADJUST_B_SAVE_DTMF_PARAMETER_1
:
13700 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SAVE
)
13703 Info
= dtmf_parameter_save_config(Id
, plci
, Rc
);
13704 if ((Info
!= GOOD
) || plci
->internal_command
)
13708 plci
->adjust_b_state
= ADJUST_B_SAVE_VOICE_1
;
13710 case ADJUST_B_SAVE_VOICE_1
:
13711 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SAVE
)
13713 Info
= adv_voice_save_config(Id
, plci
, Rc
);
13714 if ((Info
!= GOOD
) || plci
->internal_command
)
13717 plci
->adjust_b_state
= ADJUST_B_SWITCH_L1_1
;
13718 case ADJUST_B_SWITCH_L1_1
:
13719 if (plci
->adjust_b_mode
& ADJUST_B_MODE_SWITCH_L1
)
13723 plci
->internal_command
= plci
->adjust_b_command
;
13726 if (plci
->adjust_b_parms_msg
!= NULL
)
13727 api_load_msg(plci
->adjust_b_parms_msg
, bp
);
13729 api_load_msg(&plci
->B_protocol
, bp
);
13730 Info
= add_b1(plci
, bp
,
13731 (word
)((plci
->adjust_b_mode
& ADJUST_B_MODE_NO_RESOURCE
) ? 2 : 0),
13732 plci
->adjust_b_facilities
);
13735 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13736 UnMapId(Id
), (char *)(FILE_
), __LINE__
,
13737 plci
->B1_resource
, plci
->adjust_b_facilities
));
13740 plci
->internal_command
= plci
->adjust_b_command
;
13741 sig_req(plci
, RESOURCES
, 0);
13743 plci
->adjust_b_state
= ADJUST_B_SWITCH_L1_2
;
13746 plci
->adjust_b_state
= ADJUST_B_SWITCH_L1_2
;
13748 case ADJUST_B_SWITCH_L1_2
:
13749 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
13751 dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13752 UnMapId(Id
), (char *)(FILE_
), __LINE__
,
13753 Rc
, plci
->B1_resource
, plci
->adjust_b_facilities
));
13754 Info
= _WRONG_STATE
;
13757 plci
->adjust_b_state
= ADJUST_B_RESTORE_VOICE_1
;
13759 case ADJUST_B_RESTORE_VOICE_1
:
13760 case ADJUST_B_RESTORE_VOICE_2
:
13761 if (plci
->adjust_b_mode
& ADJUST_B_MODE_RESTORE
)
13763 Info
= adv_voice_restore_config(Id
, plci
, Rc
);
13764 if ((Info
!= GOOD
) || plci
->internal_command
)
13767 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_PARAMETER_1
;
13769 case ADJUST_B_RESTORE_DTMF_PARAMETER_1
:
13770 case ADJUST_B_RESTORE_DTMF_PARAMETER_2
:
13771 if (plci
->adjust_b_mode
& ADJUST_B_MODE_RESTORE
)
13774 Info
= dtmf_parameter_restore_config(Id
, plci
, Rc
);
13775 if ((Info
!= GOOD
) || plci
->internal_command
)
13779 plci
->adjust_b_state
= ADJUST_B_RESTORE_EC_1
;
13781 case ADJUST_B_RESTORE_EC_1
:
13782 case ADJUST_B_RESTORE_EC_2
:
13783 if (plci
->adjust_b_mode
& ADJUST_B_MODE_RESTORE
)
13786 Info
= ec_restore_config(Id
, plci
, Rc
);
13787 if ((Info
!= GOOD
) || plci
->internal_command
)
13791 plci
->adjust_b_state
= ADJUST_B_ASSIGN_L23_1
;
13792 case ADJUST_B_ASSIGN_L23_1
:
13793 if (plci
->adjust_b_mode
& ADJUST_B_MODE_ASSIGN_L23
)
13795 if (plci_nl_busy(plci
))
13797 plci
->internal_command
= plci
->adjust_b_command
;
13800 if (plci
->adjust_b_mode
& ADJUST_B_MODE_CONNECT
)
13801 plci
->call_dir
|= CALL_DIR_FORCE_OUTG_NL
;
13802 if (plci
->adjust_b_parms_msg
!= NULL
)
13803 api_load_msg(plci
->adjust_b_parms_msg
, bp
);
13805 api_load_msg(&plci
->B_protocol
, bp
);
13806 Info
= add_b23(plci
, bp
);
13809 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13810 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Info
));
13813 plci
->internal_command
= plci
->adjust_b_command
;
13814 nl_req_ncci(plci
, ASSIGN
, 0);
13816 plci
->adjust_b_state
= ADJUST_B_ASSIGN_L23_2
;
13819 plci
->adjust_b_state
= ADJUST_B_ASSIGN_L23_2
;
13821 case ADJUST_B_ASSIGN_L23_2
:
13822 if ((Rc
!= OK
) && (Rc
!= OK_FC
) && (Rc
!= ASSIGN_OK
))
13824 dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13825 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
13826 Info
= _WRONG_STATE
;
13829 if (plci
->adjust_b_mode
& ADJUST_B_MODE_ASSIGN_L23
)
13831 if (Rc
!= ASSIGN_OK
)
13833 plci
->internal_command
= plci
->adjust_b_command
;
13837 if (plci
->adjust_b_mode
& ADJUST_B_MODE_USER_CONNECT
)
13839 plci
->adjust_b_restore
= true;
13842 plci
->adjust_b_state
= ADJUST_B_CONNECT_1
;
13843 case ADJUST_B_CONNECT_1
:
13844 if (plci
->adjust_b_mode
& ADJUST_B_MODE_CONNECT
)
13846 plci
->internal_command
= plci
->adjust_b_command
;
13847 if (plci_nl_busy(plci
))
13849 nl_req_ncci(plci
, N_CONNECT
, 0);
13851 plci
->adjust_b_state
= ADJUST_B_CONNECT_2
;
13854 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_1
;
13856 case ADJUST_B_CONNECT_2
:
13857 case ADJUST_B_CONNECT_3
:
13858 case ADJUST_B_CONNECT_4
:
13859 if ((Rc
!= OK
) && (Rc
!= OK_FC
) && (Rc
!= 0))
13861 dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13862 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
13863 Info
= _WRONG_STATE
;
13868 if (plci
->adjust_b_mode
& ADJUST_B_MODE_CONNECT
)
13870 get_ncci(plci
, (byte
)(Id
>> 16), plci
->adjust_b_ncci
);
13871 Id
= (Id
& 0xffff) | (((dword
)(plci
->adjust_b_ncci
)) << 16);
13873 if (plci
->adjust_b_state
== ADJUST_B_CONNECT_2
)
13874 plci
->adjust_b_state
= ADJUST_B_CONNECT_3
;
13875 else if (plci
->adjust_b_state
== ADJUST_B_CONNECT_4
)
13876 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_1
;
13880 if (plci
->adjust_b_state
== ADJUST_B_CONNECT_2
)
13881 plci
->adjust_b_state
= ADJUST_B_CONNECT_4
;
13882 else if (plci
->adjust_b_state
== ADJUST_B_CONNECT_3
)
13883 plci
->adjust_b_state
= ADJUST_B_RESTORE_DTMF_1
;
13885 if (plci
->adjust_b_state
!= ADJUST_B_RESTORE_DTMF_1
)
13887 plci
->internal_command
= plci
->adjust_b_command
;
13891 case ADJUST_B_RESTORE_DTMF_1
:
13892 case ADJUST_B_RESTORE_DTMF_2
:
13893 if (plci
->adjust_b_mode
& ADJUST_B_MODE_RESTORE
)
13896 Info
= dtmf_restore_config(Id
, plci
, Rc
);
13897 if ((Info
!= GOOD
) || plci
->internal_command
)
13901 plci
->adjust_b_state
= ADJUST_B_RESTORE_MIXER_1
;
13903 case ADJUST_B_RESTORE_MIXER_1
:
13904 case ADJUST_B_RESTORE_MIXER_2
:
13905 case ADJUST_B_RESTORE_MIXER_3
:
13906 case ADJUST_B_RESTORE_MIXER_4
:
13907 case ADJUST_B_RESTORE_MIXER_5
:
13908 case ADJUST_B_RESTORE_MIXER_6
:
13909 case ADJUST_B_RESTORE_MIXER_7
:
13910 if (plci
->adjust_b_mode
& ADJUST_B_MODE_RESTORE
)
13913 Info
= mixer_restore_config(Id
, plci
, Rc
);
13914 if ((Info
!= GOOD
) || plci
->internal_command
)
13918 plci
->adjust_b_state
= ADJUST_B_END
;
13926 static void adjust_b1_resource(dword Id
, PLCI
*plci
, API_SAVE
*bp_msg
, word b1_facilities
, word internal_command
)
13929 dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13930 UnMapId(Id
), (char *)(FILE_
), __LINE__
,
13931 plci
->B1_resource
, b1_facilities
));
13933 plci
->adjust_b_parms_msg
= bp_msg
;
13934 plci
->adjust_b_facilities
= b1_facilities
;
13935 plci
->adjust_b_command
= internal_command
;
13936 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
13937 if ((bp_msg
== NULL
) && (plci
->B1_resource
== 0))
13938 plci
->adjust_b_mode
= ADJUST_B_MODE_SAVE
| ADJUST_B_MODE_NO_RESOURCE
| ADJUST_B_MODE_SWITCH_L1
;
13940 plci
->adjust_b_mode
= ADJUST_B_MODE_SAVE
| ADJUST_B_MODE_SWITCH_L1
| ADJUST_B_MODE_RESTORE
;
13941 plci
->adjust_b_state
= ADJUST_B_START
;
13942 dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13943 UnMapId(Id
), (char *)(FILE_
), __LINE__
,
13944 plci
->B1_resource
, b1_facilities
));
13948 static void adjust_b_restore(dword Id
, PLCI
*plci
, byte Rc
)
13950 word internal_command
;
13952 dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13953 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
13955 internal_command
= plci
->internal_command
;
13956 plci
->internal_command
= 0;
13957 switch (internal_command
)
13961 if (plci
->req_in
!= 0)
13963 plci
->internal_command
= ADJUST_B_RESTORE_1
;
13967 case ADJUST_B_RESTORE_1
:
13968 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
13970 dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13971 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
13973 plci
->adjust_b_parms_msg
= NULL
;
13974 plci
->adjust_b_facilities
= plci
->B1_facilities
;
13975 plci
->adjust_b_command
= ADJUST_B_RESTORE_2
;
13976 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
13977 plci
->adjust_b_mode
= ADJUST_B_MODE_RESTORE
;
13978 plci
->adjust_b_state
= ADJUST_B_START
;
13979 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13980 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
13981 case ADJUST_B_RESTORE_2
:
13982 if (adjust_b_process(Id
, plci
, Rc
) != GOOD
)
13984 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13985 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
13987 if (plci
->internal_command
)
13994 static void reset_b3_command(dword Id
, PLCI
*plci
, byte Rc
)
13997 word internal_command
;
13999 dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14000 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14003 internal_command
= plci
->internal_command
;
14004 plci
->internal_command
= 0;
14005 switch (internal_command
)
14009 plci
->adjust_b_parms_msg
= NULL
;
14010 plci
->adjust_b_facilities
= plci
->B1_facilities
;
14011 plci
->adjust_b_command
= RESET_B3_COMMAND_1
;
14012 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
14013 plci
->adjust_b_mode
= ADJUST_B_MODE_REMOVE_L23
| ADJUST_B_MODE_ASSIGN_L23
| ADJUST_B_MODE_CONNECT
;
14014 plci
->adjust_b_state
= ADJUST_B_START
;
14015 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14016 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14017 case RESET_B3_COMMAND_1
:
14018 Info
= adjust_b_process(Id
, plci
, Rc
);
14021 dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14022 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14025 if (plci
->internal_command
)
14029 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14030 sendf(plci
->appl
, _RESET_B3_I
, Id
, 0, "s", "");
14034 static void select_b_command(dword Id
, PLCI
*plci
, byte Rc
)
14037 word internal_command
;
14040 dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14041 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14044 internal_command
= plci
->internal_command
;
14045 plci
->internal_command
= 0;
14046 switch (internal_command
)
14050 plci
->adjust_b_parms_msg
= &plci
->saved_msg
;
14051 if ((plci
->tel
== ADV_VOICE
) && (plci
== plci
->adapter
->AdvSignalPLCI
))
14052 plci
->adjust_b_facilities
= plci
->B1_facilities
| B1_FACILITY_VOICE
;
14054 plci
->adjust_b_facilities
= plci
->B1_facilities
& ~B1_FACILITY_VOICE
;
14055 plci
->adjust_b_command
= SELECT_B_COMMAND_1
;
14056 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
14057 if (plci
->saved_msg
.parms
[0].length
== 0)
14059 plci
->adjust_b_mode
= ADJUST_B_MODE_SAVE
| ADJUST_B_MODE_REMOVE_L23
| ADJUST_B_MODE_SWITCH_L1
|
14060 ADJUST_B_MODE_NO_RESOURCE
;
14064 plci
->adjust_b_mode
= ADJUST_B_MODE_SAVE
| ADJUST_B_MODE_REMOVE_L23
| ADJUST_B_MODE_SWITCH_L1
|
14065 ADJUST_B_MODE_ASSIGN_L23
| ADJUST_B_MODE_USER_CONNECT
| ADJUST_B_MODE_RESTORE
;
14067 plci
->adjust_b_state
= ADJUST_B_START
;
14068 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14069 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14070 case SELECT_B_COMMAND_1
:
14071 Info
= adjust_b_process(Id
, plci
, Rc
);
14074 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14075 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14078 if (plci
->internal_command
)
14080 if (plci
->tel
== ADV_VOICE
)
14084 esc_chi
[2] = plci
->b_channel
;
14085 SetVoiceChannel(plci
->adapter
->AdvCodecPLCI
, esc_chi
, plci
->adapter
);
14089 sendf(plci
->appl
, _SELECT_B_REQ
| CONFIRM
, Id
, plci
->number
, "w", Info
);
14093 static void fax_connect_ack_command(dword Id
, PLCI
*plci
, byte Rc
)
14095 word internal_command
;
14097 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14098 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14100 internal_command
= plci
->internal_command
;
14101 plci
->internal_command
= 0;
14102 switch (internal_command
)
14106 case FAX_CONNECT_ACK_COMMAND_1
:
14107 if (plci_nl_busy(plci
))
14109 plci
->internal_command
= FAX_CONNECT_ACK_COMMAND_1
;
14112 plci
->internal_command
= FAX_CONNECT_ACK_COMMAND_2
;
14113 plci
->NData
[0].P
= plci
->fax_connect_info_buffer
;
14114 plci
->NData
[0].PLength
= plci
->fax_connect_info_length
;
14115 plci
->NL
.X
= plci
->NData
;
14116 plci
->NL
.ReqCh
= 0;
14117 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_CONNECT_ACK
;
14118 plci
->adapter
->request(&plci
->NL
);
14120 case FAX_CONNECT_ACK_COMMAND_2
:
14121 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
14123 dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14124 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
14128 if ((plci
->ncpi_state
& NCPI_VALID_CONNECT_B3_ACT
)
14129 && !(plci
->ncpi_state
& NCPI_CONNECT_B3_ACT_SENT
))
14131 if (plci
->B3_prot
== 4)
14132 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
14134 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "S", plci
->ncpi_buffer
);
14135 plci
->ncpi_state
|= NCPI_CONNECT_B3_ACT_SENT
;
14140 static void fax_edata_ack_command(dword Id
, PLCI
*plci
, byte Rc
)
14142 word internal_command
;
14144 dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14145 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14147 internal_command
= plci
->internal_command
;
14148 plci
->internal_command
= 0;
14149 switch (internal_command
)
14153 case FAX_EDATA_ACK_COMMAND_1
:
14154 if (plci_nl_busy(plci
))
14156 plci
->internal_command
= FAX_EDATA_ACK_COMMAND_1
;
14159 plci
->internal_command
= FAX_EDATA_ACK_COMMAND_2
;
14160 plci
->NData
[0].P
= plci
->fax_connect_info_buffer
;
14161 plci
->NData
[0].PLength
= plci
->fax_edata_ack_length
;
14162 plci
->NL
.X
= plci
->NData
;
14163 plci
->NL
.ReqCh
= 0;
14164 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_EDATA
;
14165 plci
->adapter
->request(&plci
->NL
);
14167 case FAX_EDATA_ACK_COMMAND_2
:
14168 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
14170 dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14171 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
14178 static void fax_connect_info_command(dword Id
, PLCI
*plci
, byte Rc
)
14181 word internal_command
;
14183 dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14184 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14187 internal_command
= plci
->internal_command
;
14188 plci
->internal_command
= 0;
14189 switch (internal_command
)
14193 case FAX_CONNECT_INFO_COMMAND_1
:
14194 if (plci_nl_busy(plci
))
14196 plci
->internal_command
= FAX_CONNECT_INFO_COMMAND_1
;
14199 plci
->internal_command
= FAX_CONNECT_INFO_COMMAND_2
;
14200 plci
->NData
[0].P
= plci
->fax_connect_info_buffer
;
14201 plci
->NData
[0].PLength
= plci
->fax_connect_info_length
;
14202 plci
->NL
.X
= plci
->NData
;
14203 plci
->NL
.ReqCh
= 0;
14204 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_EDATA
;
14205 plci
->adapter
->request(&plci
->NL
);
14207 case FAX_CONNECT_INFO_COMMAND_2
:
14208 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
14210 dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14211 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
14212 Info
= _WRONG_STATE
;
14215 if (plci_nl_busy(plci
))
14217 plci
->internal_command
= FAX_CONNECT_INFO_COMMAND_2
;
14220 plci
->command
= _CONNECT_B3_R
;
14221 nl_req_ncci(plci
, N_CONNECT
, 0);
14225 sendf(plci
->appl
, _CONNECT_B3_R
| CONFIRM
, Id
, plci
->number
, "w", Info
);
14229 static void fax_adjust_b23_command(dword Id
, PLCI
*plci
, byte Rc
)
14232 word internal_command
;
14234 dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14235 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14238 internal_command
= plci
->internal_command
;
14239 plci
->internal_command
= 0;
14240 switch (internal_command
)
14244 plci
->adjust_b_parms_msg
= NULL
;
14245 plci
->adjust_b_facilities
= plci
->B1_facilities
;
14246 plci
->adjust_b_command
= FAX_ADJUST_B23_COMMAND_1
;
14247 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
14248 plci
->adjust_b_mode
= ADJUST_B_MODE_REMOVE_L23
| ADJUST_B_MODE_ASSIGN_L23
;
14249 plci
->adjust_b_state
= ADJUST_B_START
;
14250 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14251 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14252 case FAX_ADJUST_B23_COMMAND_1
:
14253 Info
= adjust_b_process(Id
, plci
, Rc
);
14256 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14257 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14260 if (plci
->internal_command
)
14262 case FAX_ADJUST_B23_COMMAND_2
:
14263 if (plci_nl_busy(plci
))
14265 plci
->internal_command
= FAX_ADJUST_B23_COMMAND_2
;
14268 plci
->command
= _CONNECT_B3_R
;
14269 nl_req_ncci(plci
, N_CONNECT
, 0);
14273 sendf(plci
->appl
, _CONNECT_B3_R
| CONFIRM
, Id
, plci
->number
, "w", Info
);
14277 static void fax_disconnect_command(dword Id
, PLCI
*plci
, byte Rc
)
14279 word internal_command
;
14281 dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14282 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14284 internal_command
= plci
->internal_command
;
14285 plci
->internal_command
= 0;
14286 switch (internal_command
)
14290 plci
->internal_command
= FAX_DISCONNECT_COMMAND_1
;
14292 case FAX_DISCONNECT_COMMAND_1
:
14293 case FAX_DISCONNECT_COMMAND_2
:
14294 case FAX_DISCONNECT_COMMAND_3
:
14295 if ((Rc
!= OK
) && (Rc
!= OK_FC
) && (Rc
!= 0))
14297 dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14298 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
14303 if ((internal_command
== FAX_DISCONNECT_COMMAND_1
)
14304 || (internal_command
== FAX_DISCONNECT_COMMAND_2
))
14306 plci
->internal_command
= FAX_DISCONNECT_COMMAND_2
;
14311 if (internal_command
== FAX_DISCONNECT_COMMAND_1
)
14312 plci
->internal_command
= FAX_DISCONNECT_COMMAND_3
;
14320 static void rtp_connect_b3_req_command(dword Id
, PLCI
*plci
, byte Rc
)
14323 word internal_command
;
14325 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14326 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14329 internal_command
= plci
->internal_command
;
14330 plci
->internal_command
= 0;
14331 switch (internal_command
)
14335 case RTP_CONNECT_B3_REQ_COMMAND_1
:
14336 if (plci_nl_busy(plci
))
14338 plci
->internal_command
= RTP_CONNECT_B3_REQ_COMMAND_1
;
14341 plci
->internal_command
= RTP_CONNECT_B3_REQ_COMMAND_2
;
14342 nl_req_ncci(plci
, N_CONNECT
, 0);
14345 case RTP_CONNECT_B3_REQ_COMMAND_2
:
14346 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
14348 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14349 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
14350 Info
= _WRONG_STATE
;
14353 if (plci_nl_busy(plci
))
14355 plci
->internal_command
= RTP_CONNECT_B3_REQ_COMMAND_2
;
14358 plci
->internal_command
= RTP_CONNECT_B3_REQ_COMMAND_3
;
14359 plci
->NData
[0].PLength
= plci
->internal_req_buffer
[0];
14360 plci
->NData
[0].P
= plci
->internal_req_buffer
+ 1;
14361 plci
->NL
.X
= plci
->NData
;
14362 plci
->NL
.ReqCh
= 0;
14363 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_UDATA
;
14364 plci
->adapter
->request(&plci
->NL
);
14366 case RTP_CONNECT_B3_REQ_COMMAND_3
:
14369 sendf(plci
->appl
, _CONNECT_B3_R
| CONFIRM
, Id
, plci
->number
, "w", Info
);
14373 static void rtp_connect_b3_res_command(dword Id
, PLCI
*plci
, byte Rc
)
14375 word internal_command
;
14377 dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14378 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14380 internal_command
= plci
->internal_command
;
14381 plci
->internal_command
= 0;
14382 switch (internal_command
)
14386 case RTP_CONNECT_B3_RES_COMMAND_1
:
14387 if (plci_nl_busy(plci
))
14389 plci
->internal_command
= RTP_CONNECT_B3_RES_COMMAND_1
;
14392 plci
->internal_command
= RTP_CONNECT_B3_RES_COMMAND_2
;
14393 nl_req_ncci(plci
, N_CONNECT_ACK
, (byte
)(Id
>> 16));
14396 case RTP_CONNECT_B3_RES_COMMAND_2
:
14397 if ((Rc
!= OK
) && (Rc
!= OK_FC
))
14399 dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14400 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
));
14403 if (plci_nl_busy(plci
))
14405 plci
->internal_command
= RTP_CONNECT_B3_RES_COMMAND_2
;
14408 sendf(plci
->appl
, _CONNECT_B3_ACTIVE_I
, Id
, 0, "s", "");
14409 plci
->internal_command
= RTP_CONNECT_B3_RES_COMMAND_3
;
14410 plci
->NData
[0].PLength
= plci
->internal_req_buffer
[0];
14411 plci
->NData
[0].P
= plci
->internal_req_buffer
+ 1;
14412 plci
->NL
.X
= plci
->NData
;
14413 plci
->NL
.ReqCh
= 0;
14414 plci
->NL
.Req
= plci
->nl_req
= (byte
) N_UDATA
;
14415 plci
->adapter
->request(&plci
->NL
);
14417 case RTP_CONNECT_B3_RES_COMMAND_3
:
14424 static void hold_save_command(dword Id
, PLCI
*plci
, byte Rc
)
14426 byte SS_Ind
[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14428 word internal_command
;
14430 dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14431 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14434 internal_command
= plci
->internal_command
;
14435 plci
->internal_command
= 0;
14436 switch (internal_command
)
14442 plci
->adjust_b_parms_msg
= NULL
;
14443 plci
->adjust_b_facilities
= plci
->B1_facilities
;
14444 plci
->adjust_b_command
= HOLD_SAVE_COMMAND_1
;
14445 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
14446 plci
->adjust_b_mode
= ADJUST_B_MODE_SAVE
| ADJUST_B_MODE_REMOVE_L23
;
14447 plci
->adjust_b_state
= ADJUST_B_START
;
14448 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14449 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14450 case HOLD_SAVE_COMMAND_1
:
14451 Info
= adjust_b_process(Id
, plci
, Rc
);
14454 dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14455 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14458 if (plci
->internal_command
)
14461 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0, "ws", 3, SS_Ind
);
14465 static void retrieve_restore_command(dword Id
, PLCI
*plci
, byte Rc
)
14467 byte SS_Ind
[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14469 word internal_command
;
14471 dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14472 UnMapId(Id
), (char *)(FILE_
), __LINE__
, Rc
, plci
->internal_command
));
14475 internal_command
= plci
->internal_command
;
14476 plci
->internal_command
= 0;
14477 switch (internal_command
)
14481 plci
->adjust_b_parms_msg
= NULL
;
14482 plci
->adjust_b_facilities
= plci
->B1_facilities
;
14483 plci
->adjust_b_command
= RETRIEVE_RESTORE_COMMAND_1
;
14484 plci
->adjust_b_ncci
= (word
)(Id
>> 16);
14485 plci
->adjust_b_mode
= ADJUST_B_MODE_ASSIGN_L23
| ADJUST_B_MODE_USER_CONNECT
| ADJUST_B_MODE_RESTORE
;
14486 plci
->adjust_b_state
= ADJUST_B_START
;
14487 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14488 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14489 case RETRIEVE_RESTORE_COMMAND_1
:
14490 Info
= adjust_b_process(Id
, plci
, Rc
);
14493 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14494 UnMapId(Id
), (char *)(FILE_
), __LINE__
));
14497 if (plci
->internal_command
)
14500 sendf(plci
->appl
, _FACILITY_I
, Id
& 0xffffL
, 0, "ws", 3, SS_Ind
);
14504 static void init_b1_config(PLCI
*plci
)
14507 dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14508 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
14509 (char *)(FILE_
), __LINE__
));
14511 plci
->B1_resource
= 0;
14512 plci
->B1_facilities
= 0;
14514 plci
->li_bchannel_id
= 0;
14515 mixer_clear_config(plci
);
14518 ec_clear_config(plci
);
14521 dtmf_rec_clear_config(plci
);
14522 dtmf_send_clear_config(plci
);
14523 dtmf_parameter_clear_config(plci
);
14525 adv_voice_clear_config(plci
);
14526 adjust_b_clear(plci
);
14530 static void clear_b1_config(PLCI
*plci
)
14533 dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14534 (dword
)((plci
->Id
<< 8) | UnMapController(plci
->adapter
->Id
)),
14535 (char *)(FILE_
), __LINE__
));
14537 adv_voice_clear_config(plci
);
14538 adjust_b_clear(plci
);
14540 ec_clear_config(plci
);
14543 dtmf_rec_clear_config(plci
);
14544 dtmf_send_clear_config(plci
);
14545 dtmf_parameter_clear_config(plci
);
14548 if ((plci
->li_bchannel_id
!= 0)
14549 && (li_config_table
[plci
->adapter
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
== plci
))
14551 mixer_clear_config(plci
);
14552 li_config_table
[plci
->adapter
->li_base
+ (plci
->li_bchannel_id
- 1)].plci
= NULL
;
14553 plci
->li_bchannel_id
= 0;
14556 plci
->B1_resource
= 0;
14557 plci
->B1_facilities
= 0;
14561 /* -----------------------------------------------------------------
14562 XON protocol local helpers
14563 ----------------------------------------------------------------- */
14564 static void channel_flow_control_remove(PLCI
*plci
) {
14565 DIVA_CAPI_ADAPTER
*a
= plci
->adapter
;
14567 for (i
= 1; i
< MAX_NL_CHANNEL
+ 1; i
++) {
14568 if (a
->ch_flow_plci
[i
] == plci
->Id
) {
14569 a
->ch_flow_plci
[i
] = 0;
14570 a
->ch_flow_control
[i
] = 0;
14575 static void channel_x_on(PLCI
*plci
, byte ch
) {
14576 DIVA_CAPI_ADAPTER
*a
= plci
->adapter
;
14577 if (a
->ch_flow_control
[ch
] & N_XON_SENT
) {
14578 a
->ch_flow_control
[ch
] &= ~N_XON_SENT
;
14582 static void channel_x_off(PLCI
*plci
, byte ch
, byte flag
) {
14583 DIVA_CAPI_ADAPTER
*a
= plci
->adapter
;
14584 if ((a
->ch_flow_control
[ch
] & N_RX_FLOW_CONTROL_MASK
) == 0) {
14585 a
->ch_flow_control
[ch
] |= (N_CH_XOFF
| flag
);
14586 a
->ch_flow_plci
[ch
] = plci
->Id
;
14587 a
->ch_flow_control_pending
++;
14591 static void channel_request_xon(PLCI
*plci
, byte ch
) {
14592 DIVA_CAPI_ADAPTER
*a
= plci
->adapter
;
14594 if (a
->ch_flow_control
[ch
] & N_CH_XOFF
) {
14595 a
->ch_flow_control
[ch
] |= N_XON_REQ
;
14596 a
->ch_flow_control
[ch
] &= ~N_CH_XOFF
;
14597 a
->ch_flow_control
[ch
] &= ~N_XON_CONNECT_IND
;
14601 static void channel_xmit_extended_xon(PLCI
*plci
) {
14602 DIVA_CAPI_ADAPTER
*a
;
14603 int max_ch
= ARRAY_SIZE(a
->ch_flow_control
);
14604 int i
, one_requested
= 0;
14606 if ((!plci
) || (!plci
->Id
) || ((a
= plci
->adapter
) == NULL
)) {
14610 for (i
= 0; i
< max_ch
; i
++) {
14611 if ((a
->ch_flow_control
[i
] & N_CH_XOFF
) &&
14612 (a
->ch_flow_control
[i
] & N_XON_CONNECT_IND
) &&
14613 (plci
->Id
== a
->ch_flow_plci
[i
])) {
14614 channel_request_xon(plci
, (byte
)i
);
14619 if (one_requested
) {
14620 channel_xmit_xon(plci
);
14625 Try to xmit next X_ON
14627 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
) {
14628 int max_ch
= ARRAY_SIZE(a
->ch_flow_control
);
14631 if (!(plci
->adapter
->manufacturer_features
& MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL
)) {
14635 if (a
->last_flow_control_ch
>= max_ch
) {
14636 a
->last_flow_control_ch
= 1;
14638 for (i
= a
->last_flow_control_ch
; i
< max_ch
; i
++) {
14639 if ((a
->ch_flow_control
[i
] & N_XON_REQ
) &&
14640 (plci
->Id
== a
->ch_flow_plci
[i
])) {
14641 a
->last_flow_control_ch
= i
+ 1;
14646 for (i
= 1; i
< a
->last_flow_control_ch
; i
++) {
14647 if ((a
->ch_flow_control
[i
] & N_XON_REQ
) &&
14648 (plci
->Id
== a
->ch_flow_plci
[i
])) {
14649 a
->last_flow_control_ch
= i
+ 1;
14657 static void channel_xmit_xon(PLCI
*plci
) {
14658 DIVA_CAPI_ADAPTER
*a
= plci
->adapter
;
14661 if (plci
->nl_req
|| !plci
->NL
.Id
|| plci
->nl_remove_id
) {
14664 if ((ch
= (byte
)find_channel_with_pending_x_on(a
, plci
)) == 0) {
14667 a
->ch_flow_control
[ch
] &= ~N_XON_REQ
;
14668 a
->ch_flow_control
[ch
] |= N_XON_SENT
;
14670 plci
->NL
.Req
= plci
->nl_req
= (byte
)N_XON
;
14671 plci
->NL
.ReqCh
= ch
;
14672 plci
->NL
.X
= plci
->NData
;
14674 plci
->NData
[0].P
= &plci
->RBuffer
[0];
14675 plci
->NData
[0].PLength
= 0;
14677 plci
->adapter
->request(&plci
->NL
);
14680 static int channel_can_xon(PLCI
*plci
, byte ch
) {
14682 DIVA_CAPI_ADAPTER
*a
;
14688 APPLptr
= plci
->appl
;
14694 NCCIcode
= a
->ch_ncci
[ch
] | (((word
) a
->Id
) << 8);
14696 /* count all buffers within the Application pool */
14697 /* belonging to the same NCCI. XON if a first is */
14701 for (i
= 0; i
< APPLptr
->MaxBuffer
; i
++) {
14702 if (NCCIcode
== APPLptr
->DataNCCI
[i
]) count
++;
14703 if (!APPLptr
->DataNCCI
[i
] && Num
== 0xffff) Num
= i
;
14705 if ((count
> 2) || (Num
== 0xffff)) {
14712 /*------------------------------------------------------------------*/
14714 static word
CPN_filter_ok(byte
*cpn
, DIVA_CAPI_ADAPTER
*a
, word offset
)
14721 /**********************************************************************************/
14722 /* function groups the listening applications according to the CIP mask and the */
14723 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14724 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14725 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14726 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14727 /* OS specific part (per adapter). */
14728 /**********************************************************************************/
14729 static void group_optimization(DIVA_CAPI_ADAPTER
*a
, PLCI
*plci
)
14731 word i
, j
, k
, busy
, group_found
;
14732 dword info_mask_group
[MAX_CIP_TYPES
];
14733 dword cip_mask_group
[MAX_CIP_TYPES
];
14734 word appl_number_group_type
[MAX_APPL
];
14737 set_group_ind_mask(plci
); /* all APPLs within this inc. call are allowed to dial in */
14739 if (!a
->group_optimization_enabled
)
14741 dbug(1, dprintf("No group optimization"));
14745 dbug(1, dprintf("Group optimization = 0x%x...", a
->group_optimization_enabled
));
14747 for (i
= 0; i
< MAX_CIP_TYPES
; i
++)
14749 info_mask_group
[i
] = 0;
14750 cip_mask_group
[i
] = 0;
14752 for (i
= 0; i
< MAX_APPL
; i
++)
14754 appl_number_group_type
[i
] = 0;
14756 for (i
= 0; i
< max_appl
; i
++) /* check if any multi instance capable application is present */
14757 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14758 if (application
[i
].Id
&& (application
[i
].MaxNCCI
) > 1 && (a
->CIP_Mask
[i
]) && (a
->group_optimization_enabled
== 1))
14760 dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14761 return; /* allow good application unfiltered access */
14764 for (i
= 0; i
< max_appl
; i
++) /* Build CIP Groups */
14766 if (application
[i
].Id
&& a
->CIP_Mask
[i
])
14768 for (k
= 0, busy
= false; k
< a
->max_plci
; k
++)
14772 auxplci
= &a
->plci
[k
];
14773 if (auxplci
->appl
== &application
[i
]) /* application has a busy PLCI */
14776 dbug(1, dprintf("Appl 0x%x is busy", i
+ 1));
14778 else if (test_c_ind_mask_bit(auxplci
, i
)) /* application has an incoming call pending */
14781 dbug(1, dprintf("Appl 0x%x has inc. call pending", i
+ 1));
14786 for (j
= 0, group_found
= 0; j
<= (MAX_CIP_TYPES
) && !busy
&& !group_found
; j
++) /* build groups with free applications only */
14788 if (j
== MAX_CIP_TYPES
) /* all groups are in use but group still not found */
14789 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14790 appl_number_group_type
[i
] = MAX_CIP_TYPES
;
14791 group_found
= true;
14792 dbug(1, dprintf("Field overflow appl 0x%x", i
+ 1));
14794 else if ((info_mask_group
[j
] == a
->CIP_Mask
[i
]) && (cip_mask_group
[j
] == a
->Info_Mask
[i
]))
14795 { /* is group already present ? */
14796 appl_number_group_type
[i
] = j
| 0x80; /* store the group number for each application */
14797 group_found
= true;
14798 dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type
[i
], i
+ 1, info_mask_group
[j
]));
14800 else if (!info_mask_group
[j
])
14801 { /* establish a new group */
14802 appl_number_group_type
[i
] = j
| 0x80; /* store the group number for each application */
14803 info_mask_group
[j
] = a
->CIP_Mask
[i
]; /* store the new CIP mask for the new group */
14804 cip_mask_group
[j
] = a
->Info_Mask
[i
]; /* store the new Info_Mask for this new group */
14805 group_found
= true;
14806 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
]));
14812 for (i
= 0; i
< max_appl
; i
++) /* Build group_optimization_mask_table */
14814 if (appl_number_group_type
[i
]) /* application is free, has listens and is member of a group */
14816 if (appl_number_group_type
[i
] == MAX_CIP_TYPES
)
14818 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type
[i
], i
+ 1));
14822 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type
[i
], i
+ 1));
14823 for (j
= i
+ 1; j
< max_appl
; j
++) /* search other group members and mark them as busy */
14825 if (appl_number_group_type
[i
] == appl_number_group_type
[j
])
14827 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j
+ 1, appl_number_group_type
[j
]));
14828 clear_group_ind_mask_bit(plci
, j
); /* disable call on other group members */
14829 appl_number_group_type
[j
] = 0; /* remove disabled group member from group list */
14834 else /* application should not get a call */
14836 clear_group_ind_mask_bit(plci
, i
);
14844 /* OS notifies the driver about a application Capi_Register */
14845 word
CapiRegister(word id
)
14847 word i
, j
, appls_found
;
14850 DIVA_CAPI_ADAPTER
*a
;
14852 for (i
= 0, appls_found
= 0; i
< max_appl
; i
++)
14854 if (application
[i
].Id
&& (application
[i
].Id
!= id
))
14856 appls_found
++; /* an application has been found */
14860 if (appls_found
) return true;
14861 for (i
= 0; i
< max_adapter
; i
++) /* scan all adapters... */
14866 if (a
->flag_dynamic_l1_down
) /* remove adapter from L1 tristate (Huntgroup) */
14868 if (!appls_found
) /* first application does a capi register */
14870 if ((j
= get_plci(a
))) /* activate L1 of all adapters */
14872 plci
= &a
->plci
[j
- 1];
14874 add_p(plci
, OAD
, "\x01\xfd");
14875 add_p(plci
, CAI
, "\x01\x80");
14876 add_p(plci
, UID
, "\x06\x43\x61\x70\x69\x32\x30");
14877 add_p(plci
, SHIFT
| 6, NULL
);
14878 add_p(plci
, SIN
, "\x02\x00\x00");
14879 plci
->internal_command
= START_L1_SIG_ASSIGN_PEND
;
14880 sig_req(plci
, ASSIGN
, DSIG_ID
);
14881 add_p(plci
, FTY
, "\x02\xff\x07"); /* l1 start */
14882 sig_req(plci
, SIG_CTRL
, 0);
14892 /*------------------------------------------------------------------*/
14894 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14896 static void VSwitchReqInd(PLCI
*plci
, dword Id
, byte
**parms
)
14899 /* Format of vswitch_t:
14902 2 byte VSWITCH_REQ/VSWITCH_IND
14904 4 word VSwitchcommand
14911 plci
->Sig
.Ind
== NCR_FACILITY
14915 for (i
= 0; i
< MAX_MULTI_IE
; i
++)
14917 if (!parms
[i
][0]) continue;
14918 if (parms
[i
][0] < 7)
14920 parms
[i
][0] = 0; /* kill it */
14923 dbug(1, dprintf("VSwitchReqInd(%d)", parms
[i
][4]));
14924 switch (parms
[i
][4])
14927 if (!plci
->relatedPTYPLCI
||
14928 (plci
->ptyState
!= S_ECT
&& plci
->relatedPTYPLCI
->ptyState
!= S_ECT
))
14932 /* remember all necessary informations */
14933 if (parms
[i
][0] != 11 || parms
[i
][8] != 3) /* Length Test */
14937 if (parms
[i
][2] == VSWITCH_IND
&& parms
[i
][9] == 1)
14938 { /* first indication after ECT-Request on Consultation Call */
14939 plci
->vswitchstate
= parms
[i
][9];
14940 parms
[i
][9] = 2; /* State */
14941 /* now ask first Call to join */
14943 else if (parms
[i
][2] == VSWITCH_REQ
&& parms
[i
][9] == 3)
14944 { /* Answer of VSWITCH_REQ from first Call */
14945 plci
->vswitchstate
= parms
[i
][9];
14946 /* tell consultation call to join
14947 and the protocol capabilities of the first call */
14953 plci
->vsprot
= parms
[i
][10]; /* protocol */
14954 plci
->vsprotdialect
= parms
[i
][11]; /* protocoldialect */
14955 /* send join request to related PLCI */
14956 parms
[i
][1] = VSWITCHIE
;
14957 parms
[i
][2] = VSWITCH_REQ
;
14959 plci
->relatedPTYPLCI
->command
= 0;
14960 plci
->relatedPTYPLCI
->internal_command
= VSWITCH_REQ_PEND
;
14961 add_p(plci
->relatedPTYPLCI
, ESC
, &parms
[i
][0]);
14962 sig_req(plci
->relatedPTYPLCI
, VSWITCH_REQ
, 0);
14963 send_req(plci
->relatedPTYPLCI
);
14967 if (plci
->relatedPTYPLCI
&&
14968 plci
->vswitchstate
== 3 &&
14969 plci
->relatedPTYPLCI
->vswitchstate
== 3)
14971 add_p(plci
->relatedPTYPLCI
, ESC
, &parms
[i
][0]);
14972 sig_req(plci
->relatedPTYPLCI
, VSWITCH_REQ
, 0);
14973 send_req(plci
->relatedPTYPLCI
);
14977 parms
[i
][0] = 0; /* kill it */
14982 /*------------------------------------------------------------------*/
14984 static int diva_get_dma_descriptor(PLCI
*plci
, dword
*dma_magic
) {
14986 IDI_SYNC_REQ
*pReq
= (IDI_SYNC_REQ
*)&e
;
14988 if (!(diva_xdi_extended_features
& DIVA_CAPI_XDI_PROVIDES_RX_DMA
)) {
14992 pReq
->xdi_dma_descriptor_operation
.Req
= 0;
14993 pReq
->xdi_dma_descriptor_operation
.Rc
= IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION
;
14995 pReq
->xdi_dma_descriptor_operation
.info
.operation
= IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC
;
14996 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_number
= -1;
14997 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_address
= NULL
;
14998 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_magic
= 0;
15000 e
.user
[0] = plci
->adapter
->Id
- 1;
15001 plci
->adapter
->request((ENTITY
*)pReq
);
15003 if (!pReq
->xdi_dma_descriptor_operation
.info
.operation
&&
15004 (pReq
->xdi_dma_descriptor_operation
.info
.descriptor_number
>= 0) &&
15005 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_magic
) {
15006 *dma_magic
= pReq
->xdi_dma_descriptor_operation
.info
.descriptor_magic
;
15007 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15009 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_number
,
15011 return (pReq
->xdi_dma_descriptor_operation
.info
.descriptor_number
);
15013 dbug(1, dprintf("dma_alloc failed"));
15018 static void diva_free_dma_descriptor(PLCI
*plci
, int nr
) {
15020 IDI_SYNC_REQ
*pReq
= (IDI_SYNC_REQ
*)&e
;
15026 pReq
->xdi_dma_descriptor_operation
.Req
= 0;
15027 pReq
->xdi_dma_descriptor_operation
.Rc
= IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION
;
15029 pReq
->xdi_dma_descriptor_operation
.info
.operation
= IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE
;
15030 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_number
= nr
;
15031 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_address
= NULL
;
15032 pReq
->xdi_dma_descriptor_operation
.info
.descriptor_magic
= 0;
15034 e
.user
[0] = plci
->adapter
->Id
- 1;
15035 plci
->adapter
->request((ENTITY
*)pReq
);
15037 if (!pReq
->xdi_dma_descriptor_operation
.info
.operation
) {
15038 dbug(1, dprintf("dma_free(%d)", nr
));
15040 dbug(1, dprintf("dma_free failed (%d)", nr
));
15044 /*------------------------------------------------------------------*/