diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hardware/eicon/message.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hardware/eicon/message.c')
-rw-r--r-- | drivers/isdn/hardware/eicon/message.c | 15047 |
1 files changed, 15047 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c new file mode 100644 index 000000000000..f9b00f19afd2 --- /dev/null +++ b/drivers/isdn/hardware/eicon/message.c | |||
@@ -0,0 +1,15047 @@ | |||
1 | |||
2 | /* | ||
3 | * | ||
4 | Copyright (c) Eicon Networks, 2002. | ||
5 | * | ||
6 | This source file is supplied for the use with | ||
7 | Eicon Networks range of DIVA Server Adapters. | ||
8 | * | ||
9 | Eicon File Revision : 2.1 | ||
10 | * | ||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2, or (at your option) | ||
14 | any later version. | ||
15 | * | ||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY | ||
18 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
19 | See the GNU General Public License for more details. | ||
20 | * | ||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | |||
28 | |||
29 | |||
30 | |||
31 | #include "platform.h" | ||
32 | #include "di_defs.h" | ||
33 | #include "pc.h" | ||
34 | #include "capi20.h" | ||
35 | #include "divacapi.h" | ||
36 | #include "mdm_msg.h" | ||
37 | #include "divasync.h" | ||
38 | |||
39 | |||
40 | |||
41 | #define FILE_ "MESSAGE.C" | ||
42 | #define dprintf | ||
43 | |||
44 | |||
45 | |||
46 | |||
47 | |||
48 | |||
49 | |||
50 | |||
51 | |||
52 | /*------------------------------------------------------------------*/ | ||
53 | /* This is options supported for all adapters that are server by */ | ||
54 | /* XDI driver. Allo it is not necessary to ask it from every adapter*/ | ||
55 | /* and it is not necessary to save it separate for every adapter */ | ||
56 | /* Macrose defined here have only local meaning */ | ||
57 | /*------------------------------------------------------------------*/ | ||
58 | static dword diva_xdi_extended_features = 0; | ||
59 | |||
60 | #define DIVA_CAPI_USE_CMA 0x00000001 | ||
61 | #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002 | ||
62 | #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004 | ||
63 | #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008 | ||
64 | |||
65 | /* | ||
66 | CAPI can request to process all return codes self only if: | ||
67 | protocol code supports this && xdi supports this | ||
68 | */ | ||
69 | #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&& ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL)) | ||
70 | |||
71 | /*------------------------------------------------------------------*/ | ||
72 | /* local function prototypes */ | ||
73 | /*------------------------------------------------------------------*/ | ||
74 | |||
75 | static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci); | ||
76 | static void set_group_ind_mask (PLCI *plci); | ||
77 | static void clear_group_ind_mask_bit (PLCI *plci, word b); | ||
78 | static byte test_group_ind_mask_bit (PLCI *plci, word b); | ||
79 | void AutomaticLaw(DIVA_CAPI_ADAPTER *); | ||
80 | word CapiRelease(word); | ||
81 | word CapiRegister(word); | ||
82 | word api_put(APPL *, CAPI_MSG *); | ||
83 | static word api_parse(byte *, word, byte *, API_PARSE *); | ||
84 | static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out); | ||
85 | static void api_load_msg(API_SAVE *in, API_PARSE *out); | ||
86 | |||
87 | word api_remove_start(void); | ||
88 | void api_remove_complete(void); | ||
89 | |||
90 | static void plci_remove(PLCI *); | ||
91 | static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a); | ||
92 | static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *); | ||
93 | |||
94 | void callback(ENTITY *); | ||
95 | |||
96 | static void control_rc(PLCI *, byte, byte, byte, byte, byte); | ||
97 | static void data_rc(PLCI *, byte); | ||
98 | static void data_ack(PLCI *, byte); | ||
99 | static void sig_ind(PLCI *); | ||
100 | static void SendInfo(PLCI *, dword, byte * *, byte); | ||
101 | static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte); | ||
102 | static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms); | ||
103 | |||
104 | static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms); | ||
105 | |||
106 | static void nl_ind(PLCI *); | ||
107 | |||
108 | static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
109 | static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
110 | static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
111 | static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
112 | static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
113 | static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
114 | static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
115 | static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
116 | static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
117 | static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
118 | static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
119 | static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
120 | static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
121 | static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
122 | static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
123 | static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
124 | static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
125 | static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
126 | static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
127 | static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
128 | static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
129 | static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
130 | static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
131 | static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
132 | |||
133 | static word get_plci(DIVA_CAPI_ADAPTER *); | ||
134 | static void add_p(PLCI *, byte, byte *); | ||
135 | static void add_s(PLCI * plci, byte code, API_PARSE * p); | ||
136 | static void add_ss(PLCI * plci, byte code, API_PARSE * p); | ||
137 | static void add_ie(PLCI * plci, byte code, byte * p, word p_length); | ||
138 | static void add_d(PLCI *, word, byte *); | ||
139 | static void add_ai(PLCI *, API_PARSE *); | ||
140 | static word add_b1(PLCI *, API_PARSE *, word, word); | ||
141 | static word add_b23(PLCI *, API_PARSE *); | ||
142 | static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms); | ||
143 | static void sig_req(PLCI *, byte, byte); | ||
144 | static void nl_req_ncci(PLCI *, byte, byte); | ||
145 | static void send_req(PLCI *); | ||
146 | static void send_data(PLCI *); | ||
147 | static word plci_remove_check(PLCI *); | ||
148 | static void listen_check(DIVA_CAPI_ADAPTER *); | ||
149 | static byte AddInfo(byte **, byte **, byte *, byte *); | ||
150 | static byte getChannel(API_PARSE *); | ||
151 | static void IndParse(PLCI *, word *, byte **, byte); | ||
152 | static byte ie_compare(byte *, byte *); | ||
153 | static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *); | ||
154 | static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word); | ||
155 | |||
156 | /* | ||
157 | XON protocol helpers | ||
158 | */ | ||
159 | static void channel_flow_control_remove (PLCI * plci); | ||
160 | static void channel_x_off (PLCI * plci, byte ch, byte flag); | ||
161 | static void channel_x_on (PLCI * plci, byte ch); | ||
162 | static void channel_request_xon (PLCI * plci, byte ch); | ||
163 | static void channel_xmit_xon (PLCI * plci); | ||
164 | static int channel_can_xon (PLCI * plci, byte ch); | ||
165 | static void channel_xmit_extended_xon (PLCI * plci); | ||
166 | |||
167 | static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse); | ||
168 | static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte); | ||
169 | static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *); | ||
170 | static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * ); | ||
171 | static void VoiceChannelOff(PLCI *plci); | ||
172 | static void adv_voice_write_coefs (PLCI *plci, word write_command); | ||
173 | static void adv_voice_clear_config (PLCI *plci); | ||
174 | |||
175 | static word get_b1_facilities (PLCI * plci, byte b1_resource); | ||
176 | static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities); | ||
177 | static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities); | ||
178 | static word adjust_b_process (dword Id, PLCI *plci, byte Rc); | ||
179 | static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command); | ||
180 | static void adjust_b_restore (dword Id, PLCI *plci, byte Rc); | ||
181 | static void reset_b3_command (dword Id, PLCI *plci, byte Rc); | ||
182 | static void select_b_command (dword Id, PLCI *plci, byte Rc); | ||
183 | static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc); | ||
184 | static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc); | ||
185 | static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc); | ||
186 | static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc); | ||
187 | static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc); | ||
188 | static void hold_save_command (dword Id, PLCI *plci, byte Rc); | ||
189 | static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc); | ||
190 | static void init_b1_config (PLCI *plci); | ||
191 | static void clear_b1_config (PLCI *plci); | ||
192 | |||
193 | static void dtmf_command (dword Id, PLCI *plci, byte Rc); | ||
194 | static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg); | ||
195 | static void dtmf_confirmation (dword Id, PLCI *plci); | ||
196 | static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length); | ||
197 | static void dtmf_parameter_write (PLCI *plci); | ||
198 | |||
199 | |||
200 | static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id); | ||
201 | static void mixer_set_bchannel_id (PLCI *plci, byte *chi); | ||
202 | static void mixer_clear_config (PLCI *plci); | ||
203 | static void mixer_notify_update (PLCI *plci, byte others); | ||
204 | static void mixer_command (dword Id, PLCI *plci, byte Rc); | ||
205 | static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg); | ||
206 | static void mixer_indication_coefs_set (dword Id, PLCI *plci); | ||
207 | static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length); | ||
208 | static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length); | ||
209 | static void mixer_remove (PLCI *plci); | ||
210 | |||
211 | |||
212 | static void ec_command (dword Id, PLCI *plci, byte Rc); | ||
213 | static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg); | ||
214 | static void ec_indication (dword Id, PLCI *plci, byte *msg, word length); | ||
215 | |||
216 | |||
217 | static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc); | ||
218 | static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc); | ||
219 | |||
220 | |||
221 | static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic); | ||
222 | static void diva_free_dma_descriptor (PLCI *plci, int nr); | ||
223 | |||
224 | /*------------------------------------------------------------------*/ | ||
225 | /* external function prototypes */ | ||
226 | /*------------------------------------------------------------------*/ | ||
227 | |||
228 | extern byte MapController (byte); | ||
229 | extern byte UnMapController (byte); | ||
230 | #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id))) | ||
231 | #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id))) | ||
232 | |||
233 | void sendf(APPL *, word, dword, word, byte *, ...); | ||
234 | void * TransmitBufferSet(APPL * appl, dword ref); | ||
235 | void * TransmitBufferGet(APPL * appl, void * p); | ||
236 | void TransmitBufferFree(APPL * appl, void * p); | ||
237 | void * ReceiveBufferGet(APPL * appl, int Num); | ||
238 | |||
239 | int fax_head_line_time (char *buffer); | ||
240 | |||
241 | |||
242 | /*------------------------------------------------------------------*/ | ||
243 | /* Global data definitions */ | ||
244 | /*------------------------------------------------------------------*/ | ||
245 | extern byte max_adapter; | ||
246 | extern byte max_appl; | ||
247 | extern DIVA_CAPI_ADAPTER * adapter; | ||
248 | extern APPL * application; | ||
249 | |||
250 | |||
251 | |||
252 | |||
253 | |||
254 | |||
255 | |||
256 | static byte remove_started = FALSE; | ||
257 | static PLCI dummy_plci; | ||
258 | |||
259 | |||
260 | static struct _ftable { | ||
261 | word command; | ||
262 | byte * format; | ||
263 | byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *); | ||
264 | } ftable[] = { | ||
265 | {_DATA_B3_R, "dwww", data_b3_req}, | ||
266 | {_DATA_B3_I|RESPONSE, "w", data_b3_res}, | ||
267 | {_INFO_R, "ss", info_req}, | ||
268 | {_INFO_I|RESPONSE, "", info_res}, | ||
269 | {_CONNECT_R, "wsssssssss", connect_req}, | ||
270 | {_CONNECT_I|RESPONSE, "wsssss", connect_res}, | ||
271 | {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res}, | ||
272 | {_DISCONNECT_R, "s", disconnect_req}, | ||
273 | {_DISCONNECT_I|RESPONSE, "", disconnect_res}, | ||
274 | {_LISTEN_R, "dddss", listen_req}, | ||
275 | {_ALERT_R, "s", alert_req}, | ||
276 | {_FACILITY_R, "ws", facility_req}, | ||
277 | {_FACILITY_I|RESPONSE, "ws", facility_res}, | ||
278 | {_CONNECT_B3_R, "s", connect_b3_req}, | ||
279 | {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res}, | ||
280 | {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res}, | ||
281 | {_DISCONNECT_B3_R, "s", disconnect_b3_req}, | ||
282 | {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res}, | ||
283 | {_RESET_B3_R, "s", reset_b3_req}, | ||
284 | {_RESET_B3_I|RESPONSE, "", reset_b3_res}, | ||
285 | {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res}, | ||
286 | {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res}, | ||
287 | {_SELECT_B_REQ, "s", select_b_req}, | ||
288 | {_MANUFACTURER_R, "dws", manufacturer_req}, | ||
289 | {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res}, | ||
290 | {_MANUFACTURER_I|RESPONSE, "", manufacturer_res} | ||
291 | }; | ||
292 | |||
293 | static byte * cip_bc[29][2] = { | ||
294 | { "", "" }, /* 0 */ | ||
295 | { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */ | ||
296 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */ | ||
297 | { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */ | ||
298 | { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */ | ||
299 | { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */ | ||
300 | { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */ | ||
301 | { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */ | ||
302 | { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */ | ||
303 | { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */ | ||
304 | { "", "" }, /* 10 */ | ||
305 | { "", "" }, /* 11 */ | ||
306 | { "", "" }, /* 12 */ | ||
307 | { "", "" }, /* 13 */ | ||
308 | { "", "" }, /* 14 */ | ||
309 | { "", "" }, /* 15 */ | ||
310 | |||
311 | { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */ | ||
312 | { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */ | ||
313 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */ | ||
314 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */ | ||
315 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */ | ||
316 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */ | ||
317 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */ | ||
318 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */ | ||
319 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */ | ||
320 | { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */ | ||
321 | { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */ | ||
322 | { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */ | ||
323 | { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */ | ||
324 | }; | ||
325 | |||
326 | static byte * cip_hlc[29] = { | ||
327 | "", /* 0 */ | ||
328 | "", /* 1 */ | ||
329 | "", /* 2 */ | ||
330 | "", /* 3 */ | ||
331 | "", /* 4 */ | ||
332 | "", /* 5 */ | ||
333 | "", /* 6 */ | ||
334 | "", /* 7 */ | ||
335 | "", /* 8 */ | ||
336 | "", /* 9 */ | ||
337 | "", /* 10 */ | ||
338 | "", /* 11 */ | ||
339 | "", /* 12 */ | ||
340 | "", /* 13 */ | ||
341 | "", /* 14 */ | ||
342 | "", /* 15 */ | ||
343 | |||
344 | "\x02\x91\x81", /* 16 */ | ||
345 | "\x02\x91\x84", /* 17 */ | ||
346 | "\x02\x91\xa1", /* 18 */ | ||
347 | "\x02\x91\xa4", /* 19 */ | ||
348 | "\x02\x91\xa8", /* 20 */ | ||
349 | "\x02\x91\xb1", /* 21 */ | ||
350 | "\x02\x91\xb2", /* 22 */ | ||
351 | "\x02\x91\xb5", /* 23 */ | ||
352 | "\x02\x91\xb8", /* 24 */ | ||
353 | "\x02\x91\xc1", /* 25 */ | ||
354 | "\x02\x91\x81", /* 26 */ | ||
355 | "\x03\x91\xe0\x01", /* 27 */ | ||
356 | "\x03\x91\xe0\x02" /* 28 */ | ||
357 | }; | ||
358 | |||
359 | /*------------------------------------------------------------------*/ | ||
360 | |||
361 | #define V120_HEADER_LENGTH 1 | ||
362 | #define V120_HEADER_EXTEND_BIT 0x80 | ||
363 | #define V120_HEADER_BREAK_BIT 0x40 | ||
364 | #define V120_HEADER_C1_BIT 0x04 | ||
365 | #define V120_HEADER_C2_BIT 0x08 | ||
366 | #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT) | ||
367 | |||
368 | static byte v120_default_header[] = | ||
369 | { | ||
370 | |||
371 | 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */ | ||
372 | |||
373 | }; | ||
374 | |||
375 | static byte v120_break_header[] = | ||
376 | { | ||
377 | |||
378 | 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */ | ||
379 | |||
380 | }; | ||
381 | |||
382 | |||
383 | /*------------------------------------------------------------------*/ | ||
384 | /* API_PUT function */ | ||
385 | /*------------------------------------------------------------------*/ | ||
386 | |||
387 | word api_put(APPL * appl, CAPI_MSG * msg) | ||
388 | { | ||
389 | word i, j, k, l, n; | ||
390 | word ret; | ||
391 | byte c; | ||
392 | byte controller; | ||
393 | DIVA_CAPI_ADAPTER * a; | ||
394 | PLCI * plci; | ||
395 | NCCI * ncci_ptr; | ||
396 | word ncci; | ||
397 | CAPI_MSG *m; | ||
398 | API_PARSE msg_parms[MAX_MSG_PARMS+1]; | ||
399 | |||
400 | if (msg->header.length < sizeof (msg->header) || | ||
401 | msg->header.length > MAX_MSG_SIZE) { | ||
402 | dbug(1,dprintf("bad len")); | ||
403 | return _BAD_MSG; | ||
404 | } | ||
405 | |||
406 | controller = (byte)((msg->header.controller &0x7f)-1); | ||
407 | |||
408 | /* controller starts with 0 up to (max_adapter - 1) */ | ||
409 | if ( controller >= max_adapter ) | ||
410 | { | ||
411 | dbug(1,dprintf("invalid ctrl")); | ||
412 | return _BAD_MSG; | ||
413 | } | ||
414 | |||
415 | a = &adapter[controller]; | ||
416 | plci = NULL; | ||
417 | if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled) | ||
418 | { | ||
419 | dbug(1,dprintf("plci=%x",msg->header.plci)); | ||
420 | plci = &a->plci[msg->header.plci-1]; | ||
421 | ncci = GET_WORD(&msg->header.ncci); | ||
422 | if (plci->Id | ||
423 | && (plci->appl | ||
424 | || (plci->State == INC_CON_PENDING) | ||
425 | || (plci->State == INC_CON_ALERT) | ||
426 | || (msg->header.command == (_DISCONNECT_I|RESPONSE))) | ||
427 | && ((ncci == 0) | ||
428 | || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE)) | ||
429 | || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id)))) | ||
430 | { | ||
431 | i = plci->msg_in_read_pos; | ||
432 | j = plci->msg_in_write_pos; | ||
433 | if (j >= i) | ||
434 | { | ||
435 | if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE) | ||
436 | i += MSG_IN_QUEUE_SIZE - j; | ||
437 | else | ||
438 | j = 0; | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | |||
443 | n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc; | ||
444 | |||
445 | if (i > MSG_IN_QUEUE_SIZE - n) | ||
446 | i = MSG_IN_QUEUE_SIZE - n + 1; | ||
447 | i -= j; | ||
448 | } | ||
449 | |||
450 | if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc)) | ||
451 | |||
452 | { | ||
453 | dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d", | ||
454 | msg->header.length, plci->msg_in_write_pos, | ||
455 | plci->msg_in_read_pos, plci->msg_in_wrap_pos, i)); | ||
456 | |||
457 | return _QUEUE_FULL; | ||
458 | } | ||
459 | c = FALSE; | ||
460 | if ((((byte *) msg) < ((byte *)(plci->msg_in_queue))) | ||
461 | || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | ||
462 | { | ||
463 | if (plci->msg_in_write_pos != plci->msg_in_read_pos) | ||
464 | c = TRUE; | ||
465 | } | ||
466 | if (msg->header.command == _DATA_B3_R) | ||
467 | { | ||
468 | if (msg->header.length < 20) | ||
469 | { | ||
470 | dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length)); | ||
471 | return _BAD_MSG; | ||
472 | } | ||
473 | ncci_ptr = &(a->ncci[ncci]); | ||
474 | n = ncci_ptr->data_pending; | ||
475 | l = ncci_ptr->data_ack_pending; | ||
476 | k = plci->msg_in_read_pos; | ||
477 | while (k != plci->msg_in_write_pos) | ||
478 | { | ||
479 | if (k == plci->msg_in_wrap_pos) | ||
480 | k = 0; | ||
481 | if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R) | ||
482 | && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci)) | ||
483 | { | ||
484 | n++; | ||
485 | if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004) | ||
486 | l++; | ||
487 | } | ||
488 | |||
489 | k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length + | ||
490 | MSG_IN_OVERHEAD + 3) & 0xfffc; | ||
491 | |||
492 | } | ||
493 | if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK)) | ||
494 | { | ||
495 | dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d", | ||
496 | ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l)); | ||
497 | |||
498 | return _QUEUE_FULL; | ||
499 | } | ||
500 | if (plci->req_in || plci->internal_command) | ||
501 | { | ||
502 | if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue))) | ||
503 | && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | ||
504 | { | ||
505 | dbug(0,dprintf("Q-FULL3(requeue)")); | ||
506 | |||
507 | return _QUEUE_FULL; | ||
508 | } | ||
509 | c = TRUE; | ||
510 | } | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | if (plci->req_in || plci->internal_command) | ||
515 | c = TRUE; | ||
516 | else | ||
517 | { | ||
518 | plci->command = msg->header.command; | ||
519 | plci->number = msg->header.number; | ||
520 | } | ||
521 | } | ||
522 | if (c) | ||
523 | { | ||
524 | dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d", | ||
525 | msg->header.command, plci->req_in, plci->internal_command, | ||
526 | msg->header.length, plci->msg_in_write_pos, | ||
527 | plci->msg_in_read_pos, plci->msg_in_wrap_pos, i)); | ||
528 | if (j == 0) | ||
529 | plci->msg_in_wrap_pos = plci->msg_in_write_pos; | ||
530 | m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]); | ||
531 | for (i = 0; i < msg->header.length; i++) | ||
532 | ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i]; | ||
533 | if (m->header.command == _DATA_B3_R) | ||
534 | { | ||
535 | |||
536 | m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data)); | ||
537 | |||
538 | } | ||
539 | |||
540 | j = (j + 3) & 0xfffc; | ||
541 | |||
542 | *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl; | ||
543 | plci->msg_in_write_pos = j + MSG_IN_OVERHEAD; | ||
544 | return 0; | ||
545 | } | ||
546 | } | ||
547 | else | ||
548 | { | ||
549 | plci = NULL; | ||
550 | } | ||
551 | } | ||
552 | dbug(1,dprintf("com=%x",msg->header.command)); | ||
553 | |||
554 | for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0; | ||
555 | for(i=0, ret = _BAD_MSG; | ||
556 | i<(sizeof(ftable)/sizeof(struct _ftable)); | ||
557 | i++) { | ||
558 | |||
559 | if(ftable[i].command==msg->header.command) { | ||
560 | /* break loop if the message is correct, otherwise continue scan */ | ||
561 | /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */ | ||
562 | if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) { | ||
563 | ret = 0; | ||
564 | break; | ||
565 | } | ||
566 | for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0; | ||
567 | } | ||
568 | } | ||
569 | if(ret) { | ||
570 | dbug(1,dprintf("BAD_MSG")); | ||
571 | if(plci) plci->command = 0; | ||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | |||
576 | c = ftable[i].function(GET_DWORD(&msg->header.controller), | ||
577 | msg->header.number, | ||
578 | a, | ||
579 | plci, | ||
580 | appl, | ||
581 | msg_parms); | ||
582 | |||
583 | channel_xmit_extended_xon (plci); | ||
584 | |||
585 | if(c==1) send_req(plci); | ||
586 | if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0; | ||
587 | if(plci && !plci->req_in) plci->command = 0; | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | |||
592 | /*------------------------------------------------------------------*/ | ||
593 | /* api_parse function, check the format of api messages */ | ||
594 | /*------------------------------------------------------------------*/ | ||
595 | |||
596 | word api_parse(byte * msg, word length, byte * format, API_PARSE * parms) | ||
597 | { | ||
598 | word i; | ||
599 | word p; | ||
600 | |||
601 | for(i=0,p=0; format[i]; i++) { | ||
602 | if(parms) | ||
603 | { | ||
604 | parms[i].info = &msg[p]; | ||
605 | } | ||
606 | switch(format[i]) { | ||
607 | case 'b': | ||
608 | p +=1; | ||
609 | break; | ||
610 | case 'w': | ||
611 | p +=2; | ||
612 | break; | ||
613 | case 'd': | ||
614 | p +=4; | ||
615 | break; | ||
616 | case 's': | ||
617 | if(msg[p]==0xff) { | ||
618 | parms[i].info +=2; | ||
619 | parms[i].length = msg[p+1] + (msg[p+2]<<8); | ||
620 | p +=(parms[i].length +3); | ||
621 | } | ||
622 | else { | ||
623 | parms[i].length = msg[p]; | ||
624 | p +=(parms[i].length +1); | ||
625 | } | ||
626 | break; | ||
627 | } | ||
628 | |||
629 | if(p>length) return TRUE; | ||
630 | } | ||
631 | if(parms) parms[i].info = NULL; | ||
632 | return FALSE; | ||
633 | } | ||
634 | |||
635 | void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out) | ||
636 | { | ||
637 | word i, j, n = 0; | ||
638 | byte *p; | ||
639 | |||
640 | p = out->info; | ||
641 | for (i = 0; format[i] != '\0'; i++) | ||
642 | { | ||
643 | out->parms[i].info = p; | ||
644 | out->parms[i].length = in[i].length; | ||
645 | switch (format[i]) | ||
646 | { | ||
647 | case 'b': | ||
648 | n = 1; | ||
649 | break; | ||
650 | case 'w': | ||
651 | n = 2; | ||
652 | break; | ||
653 | case 'd': | ||
654 | n = 4; | ||
655 | break; | ||
656 | case 's': | ||
657 | n = in[i].length + 1; | ||
658 | break; | ||
659 | } | ||
660 | for (j = 0; j < n; j++) | ||
661 | *(p++) = in[i].info[j]; | ||
662 | } | ||
663 | out->parms[i].info = NULL; | ||
664 | out->parms[i].length = 0; | ||
665 | } | ||
666 | |||
667 | void api_load_msg(API_SAVE *in, API_PARSE *out) | ||
668 | { | ||
669 | word i; | ||
670 | |||
671 | i = 0; | ||
672 | do | ||
673 | { | ||
674 | out[i].info = in->parms[i].info; | ||
675 | out[i].length = in->parms[i].length; | ||
676 | } while (in->parms[i++].info); | ||
677 | } | ||
678 | |||
679 | |||
680 | /*------------------------------------------------------------------*/ | ||
681 | /* CAPI remove function */ | ||
682 | /*------------------------------------------------------------------*/ | ||
683 | |||
684 | word api_remove_start(void) | ||
685 | { | ||
686 | word i; | ||
687 | word j; | ||
688 | |||
689 | if(!remove_started) { | ||
690 | remove_started = TRUE; | ||
691 | for(i=0;i<max_adapter;i++) { | ||
692 | if(adapter[i].request) { | ||
693 | for(j=0;j<adapter[i].max_plci;j++) { | ||
694 | if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]); | ||
695 | } | ||
696 | } | ||
697 | } | ||
698 | return 1; | ||
699 | } | ||
700 | else { | ||
701 | for(i=0;i<max_adapter;i++) { | ||
702 | if(adapter[i].request) { | ||
703 | for(j=0;j<adapter[i].max_plci;j++) { | ||
704 | if(adapter[i].plci[j].Sig.Id) return 1; | ||
705 | } | ||
706 | } | ||
707 | } | ||
708 | } | ||
709 | api_remove_complete(); | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | |||
714 | /*------------------------------------------------------------------*/ | ||
715 | /* internal command queue */ | ||
716 | /*------------------------------------------------------------------*/ | ||
717 | |||
718 | static void init_internal_command_queue (PLCI *plci) | ||
719 | { | ||
720 | word i; | ||
721 | |||
722 | dbug (1, dprintf ("%s,%d: init_internal_command_queue", | ||
723 | (char *)(FILE_), __LINE__)); | ||
724 | |||
725 | plci->internal_command = 0; | ||
726 | for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++) | ||
727 | plci->internal_command_queue[i] = NULL; | ||
728 | } | ||
729 | |||
730 | |||
731 | static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function) | ||
732 | { | ||
733 | word i; | ||
734 | |||
735 | dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command", | ||
736 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
737 | |||
738 | if (plci->internal_command == 0) | ||
739 | { | ||
740 | plci->internal_command_queue[0] = command_function; | ||
741 | (* command_function)(Id, plci, OK); | ||
742 | } | ||
743 | else | ||
744 | { | ||
745 | i = 1; | ||
746 | while (plci->internal_command_queue[i] != 0) | ||
747 | i++; | ||
748 | plci->internal_command_queue[i] = command_function; | ||
749 | } | ||
750 | } | ||
751 | |||
752 | |||
753 | static void next_internal_command (dword Id, PLCI *plci) | ||
754 | { | ||
755 | word i; | ||
756 | |||
757 | dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command", | ||
758 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
759 | |||
760 | plci->internal_command = 0; | ||
761 | plci->internal_command_queue[0] = NULL; | ||
762 | while (plci->internal_command_queue[1] != 0) | ||
763 | { | ||
764 | for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++) | ||
765 | plci->internal_command_queue[i] = plci->internal_command_queue[i+1]; | ||
766 | plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL; | ||
767 | (*(plci->internal_command_queue[0]))(Id, plci, OK); | ||
768 | if (plci->internal_command != 0) | ||
769 | return; | ||
770 | plci->internal_command_queue[0] = NULL; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | |||
775 | /*------------------------------------------------------------------*/ | ||
776 | /* NCCI allocate/remove function */ | ||
777 | /*------------------------------------------------------------------*/ | ||
778 | |||
779 | static dword ncci_mapping_bug = 0; | ||
780 | |||
781 | static word get_ncci (PLCI *plci, byte ch, word force_ncci) | ||
782 | { | ||
783 | DIVA_CAPI_ADAPTER *a; | ||
784 | word ncci, i, j, k; | ||
785 | |||
786 | a = plci->adapter; | ||
787 | if (!ch || a->ch_ncci[ch]) | ||
788 | { | ||
789 | ncci_mapping_bug++; | ||
790 | dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x", | ||
791 | ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch])); | ||
792 | ncci = ch; | ||
793 | } | ||
794 | else | ||
795 | { | ||
796 | if (force_ncci) | ||
797 | ncci = force_ncci; | ||
798 | else | ||
799 | { | ||
800 | if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch]) | ||
801 | ncci = ch; | ||
802 | else | ||
803 | { | ||
804 | ncci = 1; | ||
805 | while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci]) | ||
806 | ncci++; | ||
807 | if (ncci == MAX_NCCI+1) | ||
808 | { | ||
809 | ncci_mapping_bug++; | ||
810 | i = 1; | ||
811 | do | ||
812 | { | ||
813 | j = 1; | ||
814 | while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i)) | ||
815 | j++; | ||
816 | k = j; | ||
817 | if (j < MAX_NCCI+1) | ||
818 | { | ||
819 | do | ||
820 | { | ||
821 | j++; | ||
822 | } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i)); | ||
823 | } | ||
824 | } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1)); | ||
825 | if (i < MAX_NL_CHANNEL+1) | ||
826 | { | ||
827 | dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x", | ||
828 | ncci_mapping_bug, ch, force_ncci, i, k, j)); | ||
829 | } | ||
830 | else | ||
831 | { | ||
832 | dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x", | ||
833 | ncci_mapping_bug, ch, force_ncci)); | ||
834 | } | ||
835 | ncci = ch; | ||
836 | } | ||
837 | } | ||
838 | a->ncci_plci[ncci] = plci->Id; | ||
839 | a->ncci_state[ncci] = IDLE; | ||
840 | if (!plci->ncci_ring_list) | ||
841 | plci->ncci_ring_list = ncci; | ||
842 | else | ||
843 | a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list]; | ||
844 | a->ncci_next[plci->ncci_ring_list] = (byte) ncci; | ||
845 | } | ||
846 | a->ncci_ch[ncci] = ch; | ||
847 | a->ch_ncci[ch] = (byte) ncci; | ||
848 | dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x", | ||
849 | ncci_mapping_bug, ch, force_ncci, ch, ncci)); | ||
850 | } | ||
851 | return (ncci); | ||
852 | } | ||
853 | |||
854 | |||
855 | static void ncci_free_receive_buffers (PLCI *plci, word ncci) | ||
856 | { | ||
857 | DIVA_CAPI_ADAPTER *a; | ||
858 | APPL *appl; | ||
859 | word i, ncci_code; | ||
860 | dword Id; | ||
861 | |||
862 | a = plci->adapter; | ||
863 | Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id; | ||
864 | if (ncci) | ||
865 | { | ||
866 | if (a->ncci_plci[ncci] == plci->Id) | ||
867 | { | ||
868 | if (!plci->appl) | ||
869 | { | ||
870 | ncci_mapping_bug++; | ||
871 | dbug(1,dprintf("NCCI mapping appl expected %ld %08lx", | ||
872 | ncci_mapping_bug, Id)); | ||
873 | } | ||
874 | else | ||
875 | { | ||
876 | appl = plci->appl; | ||
877 | ncci_code = ncci | (((word) a->Id) << 8); | ||
878 | for (i = 0; i < appl->MaxBuffer; i++) | ||
879 | { | ||
880 | if ((appl->DataNCCI[i] == ncci_code) | ||
881 | && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id)) | ||
882 | { | ||
883 | appl->DataNCCI[i] = 0; | ||
884 | } | ||
885 | } | ||
886 | } | ||
887 | } | ||
888 | } | ||
889 | else | ||
890 | { | ||
891 | for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | ||
892 | { | ||
893 | if (a->ncci_plci[ncci] == plci->Id) | ||
894 | { | ||
895 | if (!plci->appl) | ||
896 | { | ||
897 | ncci_mapping_bug++; | ||
898 | dbug(1,dprintf("NCCI mapping no appl %ld %08lx", | ||
899 | ncci_mapping_bug, Id)); | ||
900 | } | ||
901 | else | ||
902 | { | ||
903 | appl = plci->appl; | ||
904 | ncci_code = ncci | (((word) a->Id) << 8); | ||
905 | for (i = 0; i < appl->MaxBuffer; i++) | ||
906 | { | ||
907 | if ((appl->DataNCCI[i] == ncci_code) | ||
908 | && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id)) | ||
909 | { | ||
910 | appl->DataNCCI[i] = 0; | ||
911 | } | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | } | ||
916 | } | ||
917 | } | ||
918 | |||
919 | |||
920 | static void cleanup_ncci_data (PLCI *plci, word ncci) | ||
921 | { | ||
922 | NCCI *ncci_ptr; | ||
923 | |||
924 | if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id)) | ||
925 | { | ||
926 | ncci_ptr = &(plci->adapter->ncci[ncci]); | ||
927 | if (plci->appl) | ||
928 | { | ||
929 | while (ncci_ptr->data_pending != 0) | ||
930 | { | ||
931 | if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr)) | ||
932 | TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P); | ||
933 | (ncci_ptr->data_out)++; | ||
934 | if (ncci_ptr->data_out == MAX_DATA_B3) | ||
935 | ncci_ptr->data_out = 0; | ||
936 | (ncci_ptr->data_pending)--; | ||
937 | } | ||
938 | } | ||
939 | ncci_ptr->data_out = 0; | ||
940 | ncci_ptr->data_pending = 0; | ||
941 | ncci_ptr->data_ack_out = 0; | ||
942 | ncci_ptr->data_ack_pending = 0; | ||
943 | } | ||
944 | } | ||
945 | |||
946 | |||
947 | static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci) | ||
948 | { | ||
949 | DIVA_CAPI_ADAPTER *a; | ||
950 | dword Id; | ||
951 | word i; | ||
952 | |||
953 | a = plci->adapter; | ||
954 | Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id; | ||
955 | if (!preserve_ncci) | ||
956 | ncci_free_receive_buffers (plci, ncci); | ||
957 | if (ncci) | ||
958 | { | ||
959 | if (a->ncci_plci[ncci] != plci->Id) | ||
960 | { | ||
961 | ncci_mapping_bug++; | ||
962 | dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x", | ||
963 | ncci_mapping_bug, Id, preserve_ncci)); | ||
964 | } | ||
965 | else | ||
966 | { | ||
967 | cleanup_ncci_data (plci, ncci); | ||
968 | dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x", | ||
969 | ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci)); | ||
970 | a->ch_ncci[a->ncci_ch[ncci]] = 0; | ||
971 | if (!preserve_ncci) | ||
972 | { | ||
973 | a->ncci_ch[ncci] = 0; | ||
974 | a->ncci_plci[ncci] = 0; | ||
975 | a->ncci_state[ncci] = IDLE; | ||
976 | i = plci->ncci_ring_list; | ||
977 | while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci)) | ||
978 | i = a->ncci_next[i]; | ||
979 | if ((i != 0) && (a->ncci_next[i] == ncci)) | ||
980 | { | ||
981 | if (i == ncci) | ||
982 | plci->ncci_ring_list = 0; | ||
983 | else if (plci->ncci_ring_list == ncci) | ||
984 | plci->ncci_ring_list = i; | ||
985 | a->ncci_next[i] = a->ncci_next[ncci]; | ||
986 | } | ||
987 | a->ncci_next[ncci] = 0; | ||
988 | } | ||
989 | } | ||
990 | } | ||
991 | else | ||
992 | { | ||
993 | for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | ||
994 | { | ||
995 | if (a->ncci_plci[ncci] == plci->Id) | ||
996 | { | ||
997 | cleanup_ncci_data (plci, ncci); | ||
998 | dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x", | ||
999 | ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci)); | ||
1000 | a->ch_ncci[a->ncci_ch[ncci]] = 0; | ||
1001 | if (!preserve_ncci) | ||
1002 | { | ||
1003 | a->ncci_ch[ncci] = 0; | ||
1004 | a->ncci_plci[ncci] = 0; | ||
1005 | a->ncci_state[ncci] = IDLE; | ||
1006 | a->ncci_next[ncci] = 0; | ||
1007 | } | ||
1008 | } | ||
1009 | } | ||
1010 | if (!preserve_ncci) | ||
1011 | plci->ncci_ring_list = 0; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | /*------------------------------------------------------------------*/ | ||
1017 | /* PLCI remove function */ | ||
1018 | /*------------------------------------------------------------------*/ | ||
1019 | |||
1020 | static void plci_free_msg_in_queue (PLCI *plci) | ||
1021 | { | ||
1022 | word i; | ||
1023 | |||
1024 | if (plci->appl) | ||
1025 | { | ||
1026 | i = plci->msg_in_read_pos; | ||
1027 | while (i != plci->msg_in_write_pos) | ||
1028 | { | ||
1029 | if (i == plci->msg_in_wrap_pos) | ||
1030 | i = 0; | ||
1031 | if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R) | ||
1032 | { | ||
1033 | |||
1034 | TransmitBufferFree (plci->appl, | ||
1035 | (byte *)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data)); | ||
1036 | |||
1037 | } | ||
1038 | |||
1039 | i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length + | ||
1040 | MSG_IN_OVERHEAD + 3) & 0xfffc; | ||
1041 | |||
1042 | } | ||
1043 | } | ||
1044 | plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE; | ||
1045 | plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | ||
1046 | plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | static void plci_remove(PLCI * plci) | ||
1051 | { | ||
1052 | |||
1053 | if(!plci) { | ||
1054 | dbug(1,dprintf("plci_remove(no plci)")); | ||
1055 | return; | ||
1056 | } | ||
1057 | init_internal_command_queue (plci); | ||
1058 | dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel)); | ||
1059 | if(plci_remove_check(plci)) | ||
1060 | { | ||
1061 | return; | ||
1062 | } | ||
1063 | if (plci->Sig.Id == 0xff) | ||
1064 | { | ||
1065 | dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id)); | ||
1066 | if (plci->NL.Id && !plci->nl_remove_id) | ||
1067 | { | ||
1068 | nl_req_ncci(plci,REMOVE,0); | ||
1069 | send_req(plci); | ||
1070 | } | ||
1071 | } | ||
1072 | else | ||
1073 | { | ||
1074 | if (!plci->sig_remove_id | ||
1075 | && (plci->Sig.Id | ||
1076 | || (plci->req_in!=plci->req_out) | ||
1077 | || (plci->nl_req || plci->sig_req))) | ||
1078 | { | ||
1079 | sig_req(plci,HANGUP,0); | ||
1080 | send_req(plci); | ||
1081 | } | ||
1082 | } | ||
1083 | ncci_remove (plci, 0, FALSE); | ||
1084 | plci_free_msg_in_queue (plci); | ||
1085 | |||
1086 | plci->channels = 0; | ||
1087 | plci->appl = NULL; | ||
1088 | if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) | ||
1089 | plci->State = OUTG_DIS_PENDING; | ||
1090 | } | ||
1091 | |||
1092 | /*------------------------------------------------------------------*/ | ||
1093 | /* Application Group function helpers */ | ||
1094 | /*------------------------------------------------------------------*/ | ||
1095 | |||
1096 | static void set_group_ind_mask (PLCI *plci) | ||
1097 | { | ||
1098 | word i; | ||
1099 | |||
1100 | for (i = 0; i < C_IND_MASK_DWORDS; i++) | ||
1101 | plci->group_optimization_mask_table[i] = 0xffffffffL; | ||
1102 | } | ||
1103 | |||
1104 | static void clear_group_ind_mask_bit (PLCI *plci, word b) | ||
1105 | { | ||
1106 | plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f)); | ||
1107 | } | ||
1108 | |||
1109 | static byte test_group_ind_mask_bit (PLCI *plci, word b) | ||
1110 | { | ||
1111 | return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0); | ||
1112 | } | ||
1113 | |||
1114 | /*------------------------------------------------------------------*/ | ||
1115 | /* c_ind_mask operations for arbitrary MAX_APPL */ | ||
1116 | /*------------------------------------------------------------------*/ | ||
1117 | |||
1118 | static void clear_c_ind_mask (PLCI *plci) | ||
1119 | { | ||
1120 | word i; | ||
1121 | |||
1122 | for (i = 0; i < C_IND_MASK_DWORDS; i++) | ||
1123 | plci->c_ind_mask_table[i] = 0; | ||
1124 | } | ||
1125 | |||
1126 | static byte c_ind_mask_empty (PLCI *plci) | ||
1127 | { | ||
1128 | word i; | ||
1129 | |||
1130 | i = 0; | ||
1131 | while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0)) | ||
1132 | i++; | ||
1133 | return (i == C_IND_MASK_DWORDS); | ||
1134 | } | ||
1135 | |||
1136 | static void set_c_ind_mask_bit (PLCI *plci, word b) | ||
1137 | { | ||
1138 | plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f)); | ||
1139 | } | ||
1140 | |||
1141 | static void clear_c_ind_mask_bit (PLCI *plci, word b) | ||
1142 | { | ||
1143 | plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f)); | ||
1144 | } | ||
1145 | |||
1146 | static byte test_c_ind_mask_bit (PLCI *plci, word b) | ||
1147 | { | ||
1148 | return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0); | ||
1149 | } | ||
1150 | |||
1151 | static void dump_c_ind_mask (PLCI *plci) | ||
1152 | { | ||
1153 | static char hex_digit_table[0x10] = | ||
1154 | {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; | ||
1155 | word i, j, k; | ||
1156 | dword d; | ||
1157 | char *p; | ||
1158 | char buf[40]; | ||
1159 | |||
1160 | for (i = 0; i < C_IND_MASK_DWORDS; i += 4) | ||
1161 | { | ||
1162 | p = buf + 36; | ||
1163 | *p = '\0'; | ||
1164 | for (j = 0; j < 4; j++) | ||
1165 | { | ||
1166 | if (i+j < C_IND_MASK_DWORDS) | ||
1167 | { | ||
1168 | d = plci->c_ind_mask_table[i+j]; | ||
1169 | for (k = 0; k < 8; k++) | ||
1170 | { | ||
1171 | *(--p) = hex_digit_table[d & 0xf]; | ||
1172 | d >>= 4; | ||
1173 | } | ||
1174 | } | ||
1175 | else if (i != 0) | ||
1176 | { | ||
1177 | for (k = 0; k < 8; k++) | ||
1178 | *(--p) = ' '; | ||
1179 | } | ||
1180 | *(--p) = ' '; | ||
1181 | } | ||
1182 | dbug(1,dprintf ("c_ind_mask =%s", (char *) p)); | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1186 | |||
1187 | |||
1188 | |||
1189 | |||
1190 | #define dump_plcis(a) | ||
1191 | |||
1192 | |||
1193 | |||
1194 | /*------------------------------------------------------------------*/ | ||
1195 | /* translation function for each message */ | ||
1196 | /*------------------------------------------------------------------*/ | ||
1197 | |||
1198 | byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
1199 | { | ||
1200 | word ch; | ||
1201 | word i; | ||
1202 | word Info; | ||
1203 | word CIP; | ||
1204 | byte LinkLayer; | ||
1205 | API_PARSE * ai; | ||
1206 | API_PARSE * bp; | ||
1207 | API_PARSE ai_parms[5]; | ||
1208 | word channel = 0; | ||
1209 | dword ch_mask; | ||
1210 | byte m; | ||
1211 | static byte esc_chi[35] = {0x02,0x18,0x01}; | ||
1212 | static byte lli[2] = {0x01,0x00}; | ||
1213 | byte noCh = 0; | ||
1214 | word dir = 0; | ||
1215 | byte *p_chi = ""; | ||
1216 | |||
1217 | for(i=0;i<5;i++) ai_parms[i].length = 0; | ||
1218 | |||
1219 | dbug(1,dprintf("connect_req(%d)",parms->length)); | ||
1220 | Info = _WRONG_IDENTIFIER; | ||
1221 | if(a) | ||
1222 | { | ||
1223 | if(a->adapter_disabled) | ||
1224 | { | ||
1225 | dbug(1,dprintf("adapter disabled")); | ||
1226 | Id = ((word)1<<8)|a->Id; | ||
1227 | sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0); | ||
1228 | sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR); | ||
1229 | return FALSE; | ||
1230 | } | ||
1231 | Info = _OUT_OF_PLCI; | ||
1232 | if((i=get_plci(a))) | ||
1233 | { | ||
1234 | Info = 0; | ||
1235 | plci = &a->plci[i-1]; | ||
1236 | plci->appl = appl; | ||
1237 | plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | ||
1238 | /* check 'external controller' bit for codec support */ | ||
1239 | if(Id & EXT_CONTROLLER) | ||
1240 | { | ||
1241 | if(AdvCodecSupport(a, plci, appl, 0) ) | ||
1242 | { | ||
1243 | plci->Id = 0; | ||
1244 | sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER); | ||
1245 | return 2; | ||
1246 | } | ||
1247 | } | ||
1248 | ai = &parms[9]; | ||
1249 | bp = &parms[5]; | ||
1250 | ch = 0; | ||
1251 | if(bp->length)LinkLayer = bp->info[3]; | ||
1252 | else LinkLayer = 0; | ||
1253 | if(ai->length) | ||
1254 | { | ||
1255 | ch=0xffff; | ||
1256 | if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) | ||
1257 | { | ||
1258 | ch = 0; | ||
1259 | if(ai_parms[0].length) | ||
1260 | { | ||
1261 | ch = GET_WORD(ai_parms[0].info+1); | ||
1262 | if(ch>4) ch=0; /* safety -> ignore ChannelID */ | ||
1263 | if(ch==4) /* explizit CHI in message */ | ||
1264 | { | ||
1265 | /* check length of B-CH struct */ | ||
1266 | if((ai_parms[0].info)[3]>=1) | ||
1267 | { | ||
1268 | if((ai_parms[0].info)[4]==CHI) | ||
1269 | { | ||
1270 | p_chi = &((ai_parms[0].info)[5]); | ||
1271 | } | ||
1272 | else | ||
1273 | { | ||
1274 | p_chi = &((ai_parms[0].info)[3]); | ||
1275 | } | ||
1276 | if(p_chi[0]>35) /* check length of channel ID */ | ||
1277 | { | ||
1278 | Info = _WRONG_MESSAGE_FORMAT; | ||
1279 | } | ||
1280 | } | ||
1281 | else Info = _WRONG_MESSAGE_FORMAT; | ||
1282 | } | ||
1283 | |||
1284 | if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36) | ||
1285 | { | ||
1286 | dir = GET_WORD(ai_parms[0].info+3); | ||
1287 | ch_mask = 0; | ||
1288 | m = 0x3f; | ||
1289 | for(i=0; i+5<=ai_parms[0].length; i++) | ||
1290 | { | ||
1291 | if(ai_parms[0].info[i+5]!=0) | ||
1292 | { | ||
1293 | if((ai_parms[0].info[i+5] | m) != 0xff) | ||
1294 | Info = _WRONG_MESSAGE_FORMAT; | ||
1295 | else | ||
1296 | { | ||
1297 | if (ch_mask == 0) | ||
1298 | channel = i; | ||
1299 | ch_mask |= 1L << i; | ||
1300 | } | ||
1301 | } | ||
1302 | m = 0; | ||
1303 | } | ||
1304 | if (ch_mask == 0) | ||
1305 | Info = _WRONG_MESSAGE_FORMAT; | ||
1306 | if (!Info) | ||
1307 | { | ||
1308 | if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel)))) | ||
1309 | { | ||
1310 | esc_chi[0] = (byte)(ai_parms[0].length - 2); | ||
1311 | for(i=0; i+5<=ai_parms[0].length; i++) | ||
1312 | esc_chi[i+3] = ai_parms[0].info[i+5]; | ||
1313 | } | ||
1314 | else | ||
1315 | esc_chi[0] = 2; | ||
1316 | esc_chi[2] = (byte)channel; | ||
1317 | plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */ | ||
1318 | add_p(plci,LLI,lli); | ||
1319 | add_p(plci,ESC,esc_chi); | ||
1320 | plci->State = LOCAL_CONNECT; | ||
1321 | if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */ | ||
1322 | } | ||
1323 | } | ||
1324 | } | ||
1325 | } | ||
1326 | else Info = _WRONG_MESSAGE_FORMAT; | ||
1327 | } | ||
1328 | |||
1329 | dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel)); | ||
1330 | plci->command = _CONNECT_R; | ||
1331 | plci->number = Number; | ||
1332 | /* x.31 or D-ch free SAPI in LinkLayer? */ | ||
1333 | if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE; | ||
1334 | if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info) | ||
1335 | { | ||
1336 | /* B-channel used for B3 connections (ch==0), or no B channel */ | ||
1337 | /* is used (ch==2) or perm. connection (3) is used do a CALL */ | ||
1338 | if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */ | ||
1339 | else Info = add_b1(plci,&parms[5],ch,0); | ||
1340 | add_s(plci,OAD,&parms[2]); | ||
1341 | add_s(plci,OSA,&parms[4]); | ||
1342 | add_s(plci,BC,&parms[6]); | ||
1343 | add_s(plci,LLC,&parms[7]); | ||
1344 | add_s(plci,HLC,&parms[8]); | ||
1345 | CIP = GET_WORD(parms[0].info); | ||
1346 | if (a->Info_Mask[appl->Id-1] & 0x200) | ||
1347 | { | ||
1348 | /* early B3 connect (CIP mask bit 9) no release after a disc */ | ||
1349 | add_p(plci,LLI,"\x01\x01"); | ||
1350 | } | ||
1351 | if(GET_WORD(parms[0].info)<29) { | ||
1352 | add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]); | ||
1353 | add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]); | ||
1354 | } | ||
1355 | add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
1356 | sig_req(plci,ASSIGN,DSIG_ID); | ||
1357 | } | ||
1358 | else if(ch==1) { | ||
1359 | |||
1360 | /* D-Channel used for B3 connections */ | ||
1361 | plci->Sig.Id = 0xff; | ||
1362 | Info = 0; | ||
1363 | } | ||
1364 | |||
1365 | if(!Info && ch!=2 && !noCh ) { | ||
1366 | Info = add_b23(plci,&parms[5]); | ||
1367 | if(!Info) { | ||
1368 | if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0); | ||
1369 | } | ||
1370 | } | ||
1371 | |||
1372 | if(!Info) | ||
1373 | { | ||
1374 | if(ch==0 || ch==2 || ch==3 || noCh || ch==4) | ||
1375 | { | ||
1376 | if(plci->spoofed_msg==SPOOFING_REQUIRED) | ||
1377 | { | ||
1378 | api_save_msg(parms, "wsssssssss", &plci->saved_msg); | ||
1379 | plci->spoofed_msg = CALL_REQ; | ||
1380 | plci->internal_command = BLOCK_PLCI; | ||
1381 | plci->command = 0; | ||
1382 | dbug(1,dprintf("Spoof")); | ||
1383 | send_req(plci); | ||
1384 | return FALSE; | ||
1385 | } | ||
1386 | if(ch==4)add_p(plci,CHI,p_chi); | ||
1387 | add_s(plci,CPN,&parms[1]); | ||
1388 | add_s(plci,DSA,&parms[3]); | ||
1389 | if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */ | ||
1390 | add_ai(plci,&parms[9]); | ||
1391 | if(!dir)sig_req(plci,CALL_REQ,0); | ||
1392 | else | ||
1393 | { | ||
1394 | plci->command = PERM_LIST_REQ; | ||
1395 | plci->appl = appl; | ||
1396 | sig_req(plci,LISTEN_REQ,0); | ||
1397 | send_req(plci); | ||
1398 | return FALSE; | ||
1399 | } | ||
1400 | } | ||
1401 | send_req(plci); | ||
1402 | return FALSE; | ||
1403 | } | ||
1404 | plci->Id = 0; | ||
1405 | } | ||
1406 | } | ||
1407 | sendf(appl, | ||
1408 | _CONNECT_R|CONFIRM, | ||
1409 | Id, | ||
1410 | Number, | ||
1411 | "w",Info); | ||
1412 | return 2; | ||
1413 | } | ||
1414 | |||
1415 | byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
1416 | { | ||
1417 | word i, Info; | ||
1418 | word Reject; | ||
1419 | static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b}; | ||
1420 | static byte esc_t[] = {0x03,0x08,0x00,0x00}; | ||
1421 | API_PARSE * ai; | ||
1422 | API_PARSE ai_parms[5]; | ||
1423 | word ch=0; | ||
1424 | |||
1425 | if(!plci) { | ||
1426 | dbug(1,dprintf("connect_res(no plci)")); | ||
1427 | return 0; /* no plci, no send */ | ||
1428 | } | ||
1429 | |||
1430 | dbug(1,dprintf("connect_res(State=0x%x)",plci->State)); | ||
1431 | for(i=0;i<5;i++) ai_parms[i].length = 0; | ||
1432 | ai = &parms[5]; | ||
1433 | dbug(1,dprintf("ai->length=%d",ai->length)); | ||
1434 | |||
1435 | if(ai->length) | ||
1436 | { | ||
1437 | if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) | ||
1438 | { | ||
1439 | dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1))); | ||
1440 | ch = 0; | ||
1441 | if(ai_parms[0].length) | ||
1442 | { | ||
1443 | ch = GET_WORD(ai_parms[0].info+1); | ||
1444 | dbug(1,dprintf("BCH-I=0x%x",ch)); | ||
1445 | } | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1449 | if(plci->State==INC_CON_CONNECTED_ALERT) | ||
1450 | { | ||
1451 | dbug(1,dprintf("Connected Alert Call_Res")); | ||
1452 | if (a->Info_Mask[appl->Id-1] & 0x200) | ||
1453 | { | ||
1454 | /* early B3 connect (CIP mask bit 9) no release after a disc */ | ||
1455 | add_p(plci,LLI,"\x01\x01"); | ||
1456 | } | ||
1457 | add_s(plci, CONN_NR, &parms[2]); | ||
1458 | add_s(plci, LLC, &parms[4]); | ||
1459 | add_ai(plci, &parms[5]); | ||
1460 | plci->State = INC_CON_ACCEPT; | ||
1461 | sig_req(plci, CALL_RES,0); | ||
1462 | return 1; | ||
1463 | } | ||
1464 | else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) { | ||
1465 | clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | ||
1466 | dump_c_ind_mask (plci); | ||
1467 | Reject = GET_WORD(parms[0].info); | ||
1468 | dbug(1,dprintf("Reject=0x%x",Reject)); | ||
1469 | if(Reject) | ||
1470 | { | ||
1471 | if(c_ind_mask_empty (plci)) | ||
1472 | { | ||
1473 | if((Reject&0xff00)==0x3400) | ||
1474 | { | ||
1475 | esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80; | ||
1476 | add_p(plci,ESC,esc_t); | ||
1477 | add_ai(plci, &parms[5]); | ||
1478 | sig_req(plci,REJECT,0); | ||
1479 | } | ||
1480 | else if(Reject==1 || Reject>9) | ||
1481 | { | ||
1482 | add_ai(plci, &parms[5]); | ||
1483 | sig_req(plci,HANGUP,0); | ||
1484 | } | ||
1485 | else | ||
1486 | { | ||
1487 | esc_t[2] = cau_t[(Reject&0x000f)]; | ||
1488 | add_p(plci,ESC,esc_t); | ||
1489 | add_ai(plci, &parms[5]); | ||
1490 | sig_req(plci,REJECT,0); | ||
1491 | } | ||
1492 | plci->appl = appl; | ||
1493 | } | ||
1494 | else | ||
1495 | { | ||
1496 | sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED); | ||
1497 | } | ||
1498 | } | ||
1499 | else { | ||
1500 | plci->appl = appl; | ||
1501 | if(Id & EXT_CONTROLLER){ | ||
1502 | if(AdvCodecSupport(a, plci, appl, 0)){ | ||
1503 | dbug(1,dprintf("connect_res(error from AdvCodecSupport)")); | ||
1504 | sig_req(plci,HANGUP,0); | ||
1505 | return 1; | ||
1506 | } | ||
1507 | if(plci->tel == ADV_VOICE && a->AdvCodecPLCI) | ||
1508 | { | ||
1509 | Info = add_b23(plci, &parms[1]); | ||
1510 | if (Info) | ||
1511 | { | ||
1512 | dbug(1,dprintf("connect_res(error from add_b23)")); | ||
1513 | sig_req(plci,HANGUP,0); | ||
1514 | return 1; | ||
1515 | } | ||
1516 | if(plci->adv_nl) | ||
1517 | { | ||
1518 | nl_req_ncci(plci, ASSIGN, 0); | ||
1519 | } | ||
1520 | } | ||
1521 | } | ||
1522 | else | ||
1523 | { | ||
1524 | plci->tel = 0; | ||
1525 | if(ch!=2) | ||
1526 | { | ||
1527 | Info = add_b23(plci, &parms[1]); | ||
1528 | if (Info) | ||
1529 | { | ||
1530 | dbug(1,dprintf("connect_res(error from add_b23 2)")); | ||
1531 | sig_req(plci,HANGUP,0); | ||
1532 | return 1; | ||
1533 | } | ||
1534 | } | ||
1535 | nl_req_ncci(plci, ASSIGN, 0); | ||
1536 | } | ||
1537 | |||
1538 | if(plci->spoofed_msg==SPOOFING_REQUIRED) | ||
1539 | { | ||
1540 | api_save_msg(parms, "wsssss", &plci->saved_msg); | ||
1541 | plci->spoofed_msg = CALL_RES; | ||
1542 | plci->internal_command = BLOCK_PLCI; | ||
1543 | plci->command = 0; | ||
1544 | dbug(1,dprintf("Spoof")); | ||
1545 | } | ||
1546 | else | ||
1547 | { | ||
1548 | add_b1 (plci, &parms[1], ch, plci->B1_facilities); | ||
1549 | if (a->Info_Mask[appl->Id-1] & 0x200) | ||
1550 | { | ||
1551 | /* early B3 connect (CIP mask bit 9) no release after a disc */ | ||
1552 | add_p(plci,LLI,"\x01\x01"); | ||
1553 | } | ||
1554 | add_s(plci, CONN_NR, &parms[2]); | ||
1555 | add_s(plci, LLC, &parms[4]); | ||
1556 | add_ai(plci, &parms[5]); | ||
1557 | plci->State = INC_CON_ACCEPT; | ||
1558 | sig_req(plci, CALL_RES,0); | ||
1559 | } | ||
1560 | |||
1561 | for(i=0; i<max_appl; i++) { | ||
1562 | if(test_c_ind_mask_bit (plci, i)) { | ||
1563 | sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED); | ||
1564 | } | ||
1565 | } | ||
1566 | } | ||
1567 | } | ||
1568 | return 1; | ||
1569 | } | ||
1570 | |||
1571 | byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1572 | { | ||
1573 | dbug(1,dprintf("connect_a_res")); | ||
1574 | return FALSE; | ||
1575 | } | ||
1576 | |||
1577 | byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1578 | { | ||
1579 | word Info; | ||
1580 | word i; | ||
1581 | |||
1582 | dbug(1,dprintf("disconnect_req")); | ||
1583 | |||
1584 | Info = _WRONG_IDENTIFIER; | ||
1585 | |||
1586 | if(plci) | ||
1587 | { | ||
1588 | if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) | ||
1589 | { | ||
1590 | clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | ||
1591 | plci->appl = appl; | ||
1592 | for(i=0; i<max_appl; i++) | ||
1593 | { | ||
1594 | if(test_c_ind_mask_bit (plci, i)) | ||
1595 | sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0); | ||
1596 | } | ||
1597 | plci->State = OUTG_DIS_PENDING; | ||
1598 | } | ||
1599 | if(plci->Sig.Id && plci->appl) | ||
1600 | { | ||
1601 | Info = 0; | ||
1602 | if(plci->Sig.Id!=0xff) | ||
1603 | { | ||
1604 | if(plci->State!=INC_DIS_PENDING) | ||
1605 | { | ||
1606 | add_ai(plci, &msg[0]); | ||
1607 | sig_req(plci,HANGUP,0); | ||
1608 | plci->State = OUTG_DIS_PENDING; | ||
1609 | return 1; | ||
1610 | } | ||
1611 | } | ||
1612 | else | ||
1613 | { | ||
1614 | if (plci->NL.Id && !plci->nl_remove_id) | ||
1615 | { | ||
1616 | mixer_remove (plci); | ||
1617 | nl_req_ncci(plci,REMOVE,0); | ||
1618 | sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0); | ||
1619 | sendf(appl, _DISCONNECT_I, Id, 0, "w", 0); | ||
1620 | plci->State = INC_DIS_PENDING; | ||
1621 | } | ||
1622 | return 1; | ||
1623 | } | ||
1624 | } | ||
1625 | } | ||
1626 | |||
1627 | if(!appl) return FALSE; | ||
1628 | sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info); | ||
1629 | return FALSE; | ||
1630 | } | ||
1631 | |||
1632 | byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1633 | { | ||
1634 | dbug(1,dprintf("disconnect_res")); | ||
1635 | if(plci) | ||
1636 | { | ||
1637 | /* clear ind mask bit, just in case of collsion of */ | ||
1638 | /* DISCONNECT_IND and CONNECT_RES */ | ||
1639 | clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | ||
1640 | ncci_free_receive_buffers (plci, 0); | ||
1641 | if(plci_remove_check(plci)) | ||
1642 | { | ||
1643 | return 0; | ||
1644 | } | ||
1645 | if(plci->State==INC_DIS_PENDING | ||
1646 | || plci->State==SUSPENDING) { | ||
1647 | if(c_ind_mask_empty (plci)) { | ||
1648 | if(plci->State!=SUSPENDING)plci->State = IDLE; | ||
1649 | dbug(1,dprintf("chs=%d",plci->channels)); | ||
1650 | if(!plci->channels) { | ||
1651 | plci_remove(plci); | ||
1652 | } | ||
1653 | } | ||
1654 | } | ||
1655 | } | ||
1656 | return 0; | ||
1657 | } | ||
1658 | |||
1659 | byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
1660 | { | ||
1661 | word Info; | ||
1662 | byte i; | ||
1663 | |||
1664 | dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id)); | ||
1665 | |||
1666 | Info = _WRONG_IDENTIFIER; | ||
1667 | if(a) { | ||
1668 | Info = 0; | ||
1669 | a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info); | ||
1670 | a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info); | ||
1671 | dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info))); | ||
1672 | if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */ | ||
1673 | a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */ | ||
1674 | } | ||
1675 | |||
1676 | /* check if external controller listen and switch listen on or off*/ | ||
1677 | if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){ | ||
1678 | if(a->profile.Global_Options & ON_BOARD_CODEC) { | ||
1679 | dummy_plci.State = IDLE; | ||
1680 | a->codec_listen[appl->Id-1] = &dummy_plci; | ||
1681 | a->TelOAD[0] = (byte)(parms[3].length); | ||
1682 | for(i=1;parms[3].length>=i && i<22;i++) { | ||
1683 | a->TelOAD[i] = parms[3].info[i]; | ||
1684 | } | ||
1685 | a->TelOAD[i] = 0; | ||
1686 | a->TelOSA[0] = (byte)(parms[4].length); | ||
1687 | for(i=1;parms[4].length>=i && i<22;i++) { | ||
1688 | a->TelOSA[i] = parms[4].info[i]; | ||
1689 | } | ||
1690 | a->TelOSA[i] = 0; | ||
1691 | } | ||
1692 | else Info = 0x2002; /* wrong controller, codec not supported */ | ||
1693 | } | ||
1694 | else{ /* clear listen */ | ||
1695 | a->codec_listen[appl->Id-1] = (PLCI *)0; | ||
1696 | } | ||
1697 | } | ||
1698 | sendf(appl, | ||
1699 | _LISTEN_R|CONFIRM, | ||
1700 | Id, | ||
1701 | Number, | ||
1702 | "w",Info); | ||
1703 | |||
1704 | if (a) listen_check(a); | ||
1705 | return FALSE; | ||
1706 | } | ||
1707 | |||
1708 | byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1709 | { | ||
1710 | word i; | ||
1711 | API_PARSE * ai; | ||
1712 | PLCI * rc_plci = NULL; | ||
1713 | API_PARSE ai_parms[5]; | ||
1714 | word Info = 0; | ||
1715 | |||
1716 | dbug(1,dprintf("info_req")); | ||
1717 | for(i=0;i<5;i++) ai_parms[i].length = 0; | ||
1718 | |||
1719 | ai = &msg[1]; | ||
1720 | |||
1721 | if(ai->length) | ||
1722 | { | ||
1723 | if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) | ||
1724 | { | ||
1725 | dbug(1,dprintf("AddInfo wrong")); | ||
1726 | Info = _WRONG_MESSAGE_FORMAT; | ||
1727 | } | ||
1728 | } | ||
1729 | if(!a) Info = _WRONG_STATE; | ||
1730 | |||
1731 | if(!Info && plci) | ||
1732 | { /* no fac, with CPN, or KEY */ | ||
1733 | rc_plci = plci; | ||
1734 | if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) ) | ||
1735 | { | ||
1736 | /* overlap sending option */ | ||
1737 | dbug(1,dprintf("OvlSnd")); | ||
1738 | add_s(plci,CPN,&msg[0]); | ||
1739 | add_s(plci,KEY,&ai_parms[1]); | ||
1740 | sig_req(plci,INFO_REQ,0); | ||
1741 | send_req(plci); | ||
1742 | return FALSE; | ||
1743 | } | ||
1744 | |||
1745 | if(plci->State && ai_parms[2].length) | ||
1746 | { | ||
1747 | /* User_Info option */ | ||
1748 | dbug(1,dprintf("UUI")); | ||
1749 | add_s(plci,UUI,&ai_parms[2]); | ||
1750 | sig_req(plci,USER_DATA,0); | ||
1751 | } | ||
1752 | else if(plci->State && ai_parms[3].length) | ||
1753 | { | ||
1754 | /* Facility option */ | ||
1755 | dbug(1,dprintf("FAC")); | ||
1756 | add_s(plci,CPN,&msg[0]); | ||
1757 | add_ai(plci, &msg[1]); | ||
1758 | sig_req(plci,FACILITY_REQ,0); | ||
1759 | } | ||
1760 | else | ||
1761 | { | ||
1762 | Info = _WRONG_STATE; | ||
1763 | } | ||
1764 | } | ||
1765 | else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info) | ||
1766 | { | ||
1767 | /* NCR_Facility option -> send UUI and Keypad too */ | ||
1768 | dbug(1,dprintf("NCR_FAC")); | ||
1769 | if((i=get_plci(a))) | ||
1770 | { | ||
1771 | rc_plci = &a->plci[i-1]; | ||
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); | ||
1778 | send_req(rc_plci); | ||
1779 | } | ||
1780 | else | ||
1781 | { | ||
1782 | Info = _OUT_OF_PLCI; | ||
1783 | } | ||
1784 | |||
1785 | if(!Info) | ||
1786 | { | ||
1787 | add_s(rc_plci,CPN,&msg[0]); | ||
1788 | add_ai(rc_plci, &msg[1]); | ||
1789 | sig_req(rc_plci,NCR_FACILITY,0); | ||
1790 | send_req(rc_plci); | ||
1791 | return FALSE; | ||
1792 | /* for application controlled supplementary services */ | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | if (!rc_plci) | ||
1797 | { | ||
1798 | Info = _WRONG_MESSAGE_FORMAT; | ||
1799 | } | ||
1800 | |||
1801 | if(!Info) | ||
1802 | { | ||
1803 | send_req(rc_plci); | ||
1804 | } | ||
1805 | else | ||
1806 | { /* appl is not assigned to a PLCI or error condition */ | ||
1807 | dbug(1,dprintf("localInfoCon")); | ||
1808 | sendf(appl, | ||
1809 | _INFO_R|CONFIRM, | ||
1810 | Id, | ||
1811 | Number, | ||
1812 | "w",Info); | ||
1813 | } | ||
1814 | return FALSE; | ||
1815 | } | ||
1816 | |||
1817 | byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1818 | { | ||
1819 | dbug(1,dprintf("info_res")); | ||
1820 | return FALSE; | ||
1821 | } | ||
1822 | |||
1823 | byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1824 | { | ||
1825 | word Info; | ||
1826 | byte ret; | ||
1827 | |||
1828 | dbug(1,dprintf("alert_req")); | ||
1829 | |||
1830 | Info = _WRONG_IDENTIFIER; | ||
1831 | ret = FALSE; | ||
1832 | if(plci) { | ||
1833 | Info = _ALERT_IGNORED; | ||
1834 | if(plci->State!=INC_CON_ALERT) { | ||
1835 | Info = _WRONG_STATE; | ||
1836 | if(plci->State==INC_CON_PENDING) { | ||
1837 | Info = 0; | ||
1838 | plci->State=INC_CON_ALERT; | ||
1839 | add_ai(plci, &msg[0]); | ||
1840 | sig_req(plci,CALL_ALERT,0); | ||
1841 | ret = 1; | ||
1842 | } | ||
1843 | } | ||
1844 | } | ||
1845 | sendf(appl, | ||
1846 | _ALERT_R|CONFIRM, | ||
1847 | Id, | ||
1848 | Number, | ||
1849 | "w",Info); | ||
1850 | return ret; | ||
1851 | } | ||
1852 | |||
1853 | byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
1854 | { | ||
1855 | word Info = 0; | ||
1856 | word i = 0; | ||
1857 | |||
1858 | word selector; | ||
1859 | word SSreq; | ||
1860 | long relatedPLCIvalue; | ||
1861 | DIVA_CAPI_ADAPTER * relatedadapter; | ||
1862 | byte * SSparms = ""; | ||
1863 | byte RCparms[] = "\x05\x00\x00\x02\x00\x00"; | ||
1864 | byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00"; | ||
1865 | API_PARSE * parms; | ||
1866 | API_PARSE ss_parms[11]; | ||
1867 | PLCI *rplci; | ||
1868 | byte cai[15]; | ||
1869 | dword d; | ||
1870 | API_PARSE dummy; | ||
1871 | |||
1872 | dbug(1,dprintf("facility_req")); | ||
1873 | for(i=0;i<9;i++) ss_parms[i].length = 0; | ||
1874 | |||
1875 | parms = &msg[1]; | ||
1876 | |||
1877 | if(!a) | ||
1878 | { | ||
1879 | dbug(1,dprintf("wrong Ctrl")); | ||
1880 | Info = _WRONG_IDENTIFIER; | ||
1881 | } | ||
1882 | |||
1883 | selector = GET_WORD(msg[0].info); | ||
1884 | |||
1885 | if(!Info) | ||
1886 | { | ||
1887 | switch(selector) | ||
1888 | { | ||
1889 | case SELECTOR_HANDSET: | ||
1890 | Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT); | ||
1891 | break; | ||
1892 | |||
1893 | case SELECTOR_SU_SERV: | ||
1894 | if(!msg[1].length) | ||
1895 | { | ||
1896 | Info = _WRONG_MESSAGE_FORMAT; | ||
1897 | break; | ||
1898 | } | ||
1899 | SSreq = GET_WORD(&(msg[1].info[1])); | ||
1900 | PUT_WORD(&RCparms[1],SSreq); | ||
1901 | SSparms = RCparms; | ||
1902 | switch(SSreq) | ||
1903 | { | ||
1904 | case S_GET_SUPPORTED_SERVICES: | ||
1905 | if((i=get_plci(a))) | ||
1906 | { | ||
1907 | rplci = &a->plci[i-1]; | ||
1908 | rplci->appl = appl; | ||
1909 | add_p(rplci,CAI,"\x01\x80"); | ||
1910 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
1911 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
1912 | send_req(rplci); | ||
1913 | } | ||
1914 | else | ||
1915 | { | ||
1916 | PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); | ||
1917 | SSparms = (byte *)SSstruct; | ||
1918 | break; | ||
1919 | } | ||
1920 | rplci->internal_command = GETSERV_REQ_PEND; | ||
1921 | rplci->number = Number; | ||
1922 | rplci->appl = appl; | ||
1923 | sig_req(rplci,S_SUPPORTED,0); | ||
1924 | send_req(rplci); | ||
1925 | return FALSE; | ||
1926 | break; | ||
1927 | |||
1928 | case S_LISTEN: | ||
1929 | if(parms->length==7) | ||
1930 | { | ||
1931 | if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | ||
1932 | { | ||
1933 | dbug(1,dprintf("format wrong")); | ||
1934 | Info = _WRONG_MESSAGE_FORMAT; | ||
1935 | break; | ||
1936 | } | ||
1937 | } | ||
1938 | else | ||
1939 | { | ||
1940 | Info = _WRONG_MESSAGE_FORMAT; | ||
1941 | break; | ||
1942 | } | ||
1943 | a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info); | ||
1944 | if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */ | ||
1945 | { | ||
1946 | if((i=get_plci(a))) | ||
1947 | { | ||
1948 | rplci = &a->plci[i-1]; | ||
1949 | rplci->appl = appl; | ||
1950 | add_p(rplci,CAI,"\x01\x80"); | ||
1951 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
1952 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
1953 | send_req(rplci); | ||
1954 | } | ||
1955 | else | ||
1956 | { | ||
1957 | break; | ||
1958 | } | ||
1959 | rplci->internal_command = GET_MWI_STATE; | ||
1960 | rplci->number = Number; | ||
1961 | sig_req(rplci,MWI_POLL,0); | ||
1962 | send_req(rplci); | ||
1963 | } | ||
1964 | break; | ||
1965 | |||
1966 | case S_HOLD: | ||
1967 | api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms); | ||
1968 | if(plci && plci->State && plci->SuppState==IDLE) | ||
1969 | { | ||
1970 | plci->SuppState = HOLD_REQUEST; | ||
1971 | plci->command = C_HOLD_REQ; | ||
1972 | add_s(plci,CAI,&ss_parms[1]); | ||
1973 | sig_req(plci,CALL_HOLD,0); | ||
1974 | send_req(plci); | ||
1975 | return FALSE; | ||
1976 | } | ||
1977 | else Info = 0x3010; /* wrong state */ | ||
1978 | break; | ||
1979 | case S_RETRIEVE: | ||
1980 | if(plci && plci->State && plci->SuppState==CALL_HELD) | ||
1981 | { | ||
1982 | if(Id & EXT_CONTROLLER) | ||
1983 | { | ||
1984 | if(AdvCodecSupport(a, plci, appl, 0)) | ||
1985 | { | ||
1986 | Info = 0x3010; /* wrong state */ | ||
1987 | break; | ||
1988 | } | ||
1989 | } | ||
1990 | else plci->tel = 0; | ||
1991 | |||
1992 | plci->SuppState = RETRIEVE_REQUEST; | ||
1993 | plci->command = C_RETRIEVE_REQ; | ||
1994 | if(plci->spoofed_msg==SPOOFING_REQUIRED) | ||
1995 | { | ||
1996 | plci->spoofed_msg = CALL_RETRIEVE; | ||
1997 | plci->internal_command = BLOCK_PLCI; | ||
1998 | plci->command = 0; | ||
1999 | dbug(1,dprintf("Spoof")); | ||
2000 | return FALSE; | ||
2001 | } | ||
2002 | else | ||
2003 | { | ||
2004 | sig_req(plci,CALL_RETRIEVE,0); | ||
2005 | send_req(plci); | ||
2006 | return FALSE; | ||
2007 | } | ||
2008 | } | ||
2009 | else Info = 0x3010; /* wrong state */ | ||
2010 | break; | ||
2011 | case S_SUSPEND: | ||
2012 | if(parms->length) | ||
2013 | { | ||
2014 | if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms)) | ||
2015 | { | ||
2016 | dbug(1,dprintf("format wrong")); | ||
2017 | Info = _WRONG_MESSAGE_FORMAT; | ||
2018 | break; | ||
2019 | } | ||
2020 | } | ||
2021 | if(plci && plci->State) | ||
2022 | { | ||
2023 | add_s(plci,CAI,&ss_parms[2]); | ||
2024 | plci->command = SUSPEND_REQ; | ||
2025 | sig_req(plci,SUSPEND,0); | ||
2026 | plci->State = SUSPENDING; | ||
2027 | send_req(plci); | ||
2028 | } | ||
2029 | else Info = 0x3010; /* wrong state */ | ||
2030 | break; | ||
2031 | |||
2032 | case S_RESUME: | ||
2033 | if(!(i=get_plci(a)) ) | ||
2034 | { | ||
2035 | Info = _OUT_OF_PLCI; | ||
2036 | break; | ||
2037 | } | ||
2038 | rplci = &a->plci[i-1]; | ||
2039 | rplci->appl = appl; | ||
2040 | rplci->number = Number; | ||
2041 | rplci->tel = 0; | ||
2042 | rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | ||
2043 | /* check 'external controller' bit for codec support */ | ||
2044 | if(Id & EXT_CONTROLLER) | ||
2045 | { | ||
2046 | if(AdvCodecSupport(a, rplci, appl, 0) ) | ||
2047 | { | ||
2048 | rplci->Id = 0; | ||
2049 | Info = 0x300A; | ||
2050 | break; | ||
2051 | } | ||
2052 | } | ||
2053 | if(parms->length) | ||
2054 | { | ||
2055 | if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms)) | ||
2056 | { | ||
2057 | dbug(1,dprintf("format wrong")); | ||
2058 | rplci->Id = 0; | ||
2059 | Info = _WRONG_MESSAGE_FORMAT; | ||
2060 | break; | ||
2061 | } | ||
2062 | } | ||
2063 | dummy.length = 0; | ||
2064 | dummy.info = "\x00"; | ||
2065 | add_b1(rplci, &dummy, 0, 0); | ||
2066 | if (a->Info_Mask[appl->Id-1] & 0x200) | ||
2067 | { | ||
2068 | /* early B3 connect (CIP mask bit 9) no release after a disc */ | ||
2069 | add_p(rplci,LLI,"\x01\x01"); | ||
2070 | } | ||
2071 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
2072 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
2073 | send_req(rplci); | ||
2074 | add_s(rplci,CAI,&ss_parms[2]); | ||
2075 | rplci->command = RESUME_REQ; | ||
2076 | sig_req(rplci,RESUME,0); | ||
2077 | rplci->State = RESUMING; | ||
2078 | send_req(rplci); | ||
2079 | break; | ||
2080 | |||
2081 | case S_CONF_BEGIN: /* Request */ | ||
2082 | case S_CONF_DROP: | ||
2083 | case S_CONF_ISOLATE: | ||
2084 | case S_CONF_REATTACH: | ||
2085 | if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | ||
2086 | { | ||
2087 | dbug(1,dprintf("format wrong")); | ||
2088 | Info = _WRONG_MESSAGE_FORMAT; | ||
2089 | break; | ||
2090 | } | ||
2091 | if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD))) | ||
2092 | { | ||
2093 | d = GET_DWORD(ss_parms[2].info); | ||
2094 | if(d>=0x80) | ||
2095 | { | ||
2096 | dbug(1,dprintf("format wrong")); | ||
2097 | Info = _WRONG_MESSAGE_FORMAT; | ||
2098 | break; | ||
2099 | } | ||
2100 | plci->ptyState = (byte)SSreq; | ||
2101 | plci->command = 0; | ||
2102 | cai[0] = 2; | ||
2103 | switch(SSreq) | ||
2104 | { | ||
2105 | case S_CONF_BEGIN: | ||
2106 | cai[1] = CONF_BEGIN; | ||
2107 | plci->internal_command = CONF_BEGIN_REQ_PEND; | ||
2108 | break; | ||
2109 | case S_CONF_DROP: | ||
2110 | cai[1] = CONF_DROP; | ||
2111 | plci->internal_command = CONF_DROP_REQ_PEND; | ||
2112 | break; | ||
2113 | case S_CONF_ISOLATE: | ||
2114 | cai[1] = CONF_ISOLATE; | ||
2115 | plci->internal_command = CONF_ISOLATE_REQ_PEND; | ||
2116 | break; | ||
2117 | case S_CONF_REATTACH: | ||
2118 | cai[1] = CONF_REATTACH; | ||
2119 | plci->internal_command = CONF_REATTACH_REQ_PEND; | ||
2120 | break; | ||
2121 | } | ||
2122 | cai[2] = (byte)d; /* Conference Size resp. PartyId */ | ||
2123 | add_p(plci,CAI,cai); | ||
2124 | sig_req(plci,S_SERVICE,0); | ||
2125 | send_req(plci); | ||
2126 | return FALSE; | ||
2127 | } | ||
2128 | else Info = 0x3010; /* wrong state */ | ||
2129 | break; | ||
2130 | |||
2131 | case S_ECT: | ||
2132 | case S_3PTY_BEGIN: | ||
2133 | case S_3PTY_END: | ||
2134 | case S_CONF_ADD: | ||
2135 | if(parms->length==7) | ||
2136 | { | ||
2137 | if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | ||
2138 | { | ||
2139 | dbug(1,dprintf("format wrong")); | ||
2140 | Info = _WRONG_MESSAGE_FORMAT; | ||
2141 | break; | ||
2142 | } | ||
2143 | } | ||
2144 | else if(parms->length==8) /* workaround for the T-View-S */ | ||
2145 | { | ||
2146 | if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms)) | ||
2147 | { | ||
2148 | dbug(1,dprintf("format wrong")); | ||
2149 | Info = _WRONG_MESSAGE_FORMAT; | ||
2150 | break; | ||
2151 | } | ||
2152 | } | ||
2153 | else | ||
2154 | { | ||
2155 | Info = _WRONG_MESSAGE_FORMAT; | ||
2156 | break; | ||
2157 | } | ||
2158 | if(!msg[1].length) | ||
2159 | { | ||
2160 | Info = _WRONG_MESSAGE_FORMAT; | ||
2161 | break; | ||
2162 | } | ||
2163 | if (!plci) | ||
2164 | { | ||
2165 | Info = _WRONG_IDENTIFIER; | ||
2166 | break; | ||
2167 | } | ||
2168 | relatedPLCIvalue = GET_DWORD(ss_parms[2].info); | ||
2169 | relatedPLCIvalue &= 0x0000FFFF; | ||
2170 | dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue)); | ||
2171 | /* controller starts with 0 up to (max_adapter - 1) */ | ||
2172 | if (((relatedPLCIvalue & 0x7f) == 0) | ||
2173 | || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0) | ||
2174 | || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter)) | ||
2175 | { | ||
2176 | if(SSreq==S_3PTY_END) | ||
2177 | { | ||
2178 | dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI")); | ||
2179 | rplci = plci; | ||
2180 | } | ||
2181 | else | ||
2182 | { | ||
2183 | Info = 0x3010; /* wrong state */ | ||
2184 | break; | ||
2185 | } | ||
2186 | } | ||
2187 | else | ||
2188 | { | ||
2189 | relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1]; | ||
2190 | relatedPLCIvalue >>=8; | ||
2191 | /* find PLCI PTR*/ | ||
2192 | for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++) | ||
2193 | { | ||
2194 | if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue) | ||
2195 | { | ||
2196 | rplci = &relatedadapter->plci[i]; | ||
2197 | } | ||
2198 | } | ||
2199 | if(!rplci || !relatedPLCIvalue) | ||
2200 | { | ||
2201 | if(SSreq==S_3PTY_END) | ||
2202 | { | ||
2203 | dbug(1, dprintf("use 2nd PLCI=PLCI")); | ||
2204 | rplci = plci; | ||
2205 | } | ||
2206 | else | ||
2207 | { | ||
2208 | Info = 0x3010; /* wrong state */ | ||
2209 | break; | ||
2210 | } | ||
2211 | } | ||
2212 | } | ||
2213 | /* | ||
2214 | dbug(1,dprintf("rplci:%x",rplci)); | ||
2215 | dbug(1,dprintf("plci:%x",plci)); | ||
2216 | dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState)); | ||
2217 | dbug(1,dprintf("plci->ptyState:%x",plci->ptyState)); | ||
2218 | dbug(1,dprintf("SSreq:%x",SSreq)); | ||
2219 | dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command)); | ||
2220 | dbug(1,dprintf("rplci->appl:%x",rplci->appl)); | ||
2221 | dbug(1,dprintf("rplci->Id:%x",rplci->Id)); | ||
2222 | */ | ||
2223 | /* send PTY/ECT req, cannot check all states because of US stuff */ | ||
2224 | if( !rplci->internal_command && rplci->appl ) | ||
2225 | { | ||
2226 | plci->command = 0; | ||
2227 | rplci->relatedPTYPLCI = plci; | ||
2228 | plci->relatedPTYPLCI = rplci; | ||
2229 | rplci->ptyState = (byte)SSreq; | ||
2230 | if(SSreq==S_ECT) | ||
2231 | { | ||
2232 | rplci->internal_command = ECT_REQ_PEND; | ||
2233 | cai[1] = ECT_EXECUTE; | ||
2234 | |||
2235 | rplci->vswitchstate=0; | ||
2236 | rplci->vsprot=0; | ||
2237 | rplci->vsprotdialect=0; | ||
2238 | plci->vswitchstate=0; | ||
2239 | plci->vsprot=0; | ||
2240 | plci->vsprotdialect=0; | ||
2241 | |||
2242 | } | ||
2243 | else if(SSreq==S_CONF_ADD) | ||
2244 | { | ||
2245 | rplci->internal_command = CONF_ADD_REQ_PEND; | ||
2246 | cai[1] = CONF_ADD; | ||
2247 | } | ||
2248 | else | ||
2249 | { | ||
2250 | rplci->internal_command = PTY_REQ_PEND; | ||
2251 | cai[1] = (byte)(SSreq-3); | ||
2252 | } | ||
2253 | rplci->number = Number; | ||
2254 | if(plci!=rplci) /* explicit invocation */ | ||
2255 | { | ||
2256 | cai[0] = 2; | ||
2257 | cai[2] = plci->Sig.Id; | ||
2258 | dbug(1,dprintf("explicit invocation")); | ||
2259 | } | ||
2260 | else | ||
2261 | { | ||
2262 | dbug(1,dprintf("implicit invocation")); | ||
2263 | cai[0] = 1; | ||
2264 | } | ||
2265 | add_p(rplci,CAI,cai); | ||
2266 | sig_req(rplci,S_SERVICE,0); | ||
2267 | send_req(rplci); | ||
2268 | return FALSE; | ||
2269 | } | ||
2270 | else | ||
2271 | { | ||
2272 | dbug(0,dprintf("Wrong line")); | ||
2273 | Info = 0x3010; /* wrong state */ | ||
2274 | break; | ||
2275 | } | ||
2276 | break; | ||
2277 | |||
2278 | case S_CALL_DEFLECTION: | ||
2279 | if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms)) | ||
2280 | { | ||
2281 | dbug(1,dprintf("format wrong")); | ||
2282 | Info = _WRONG_MESSAGE_FORMAT; | ||
2283 | break; | ||
2284 | } | ||
2285 | if (!plci) | ||
2286 | { | ||
2287 | Info = _WRONG_IDENTIFIER; | ||
2288 | break; | ||
2289 | } | ||
2290 | /* reuse unused screening indicator */ | ||
2291 | ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0])); | ||
2292 | plci->command = 0; | ||
2293 | plci->internal_command = CD_REQ_PEND; | ||
2294 | appl->CDEnable = TRUE; | ||
2295 | cai[0] = 1; | ||
2296 | cai[1] = CALL_DEFLECTION; | ||
2297 | add_p(plci,CAI,cai); | ||
2298 | add_p(plci,CPN,ss_parms[3].info); | ||
2299 | sig_req(plci,S_SERVICE,0); | ||
2300 | send_req(plci); | ||
2301 | return FALSE; | ||
2302 | break; | ||
2303 | |||
2304 | case S_CALL_FORWARDING_START: | ||
2305 | if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms)) | ||
2306 | { | ||
2307 | dbug(1,dprintf("format wrong")); | ||
2308 | Info = _WRONG_MESSAGE_FORMAT; | ||
2309 | break; | ||
2310 | } | ||
2311 | |||
2312 | if((i=get_plci(a))) | ||
2313 | { | ||
2314 | rplci = &a->plci[i-1]; | ||
2315 | rplci->appl = appl; | ||
2316 | add_p(rplci,CAI,"\x01\x80"); | ||
2317 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
2318 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
2319 | send_req(rplci); | ||
2320 | } | ||
2321 | else | ||
2322 | { | ||
2323 | Info = _OUT_OF_PLCI; | ||
2324 | break; | ||
2325 | } | ||
2326 | |||
2327 | /* reuse unused screening indicator */ | ||
2328 | rplci->internal_command = CF_START_PEND; | ||
2329 | rplci->appl = appl; | ||
2330 | rplci->number = Number; | ||
2331 | appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0])); | ||
2332 | cai[0] = 2; | ||
2333 | cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ | ||
2334 | cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */ | ||
2335 | add_p(rplci,CAI,cai); | ||
2336 | add_p(rplci,OAD,ss_parms[5].info); | ||
2337 | add_p(rplci,CPN,ss_parms[6].info); | ||
2338 | sig_req(rplci,S_SERVICE,0); | ||
2339 | send_req(rplci); | ||
2340 | return FALSE; | ||
2341 | break; | ||
2342 | |||
2343 | case S_INTERROGATE_DIVERSION: | ||
2344 | case S_INTERROGATE_NUMBERS: | ||
2345 | case S_CALL_FORWARDING_STOP: | ||
2346 | case S_CCBS_REQUEST: | ||
2347 | case S_CCBS_DEACTIVATE: | ||
2348 | case S_CCBS_INTERROGATE: | ||
2349 | switch(SSreq) | ||
2350 | { | ||
2351 | case S_INTERROGATE_NUMBERS: | ||
2352 | if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms)) | ||
2353 | { | ||
2354 | dbug(0,dprintf("format wrong")); | ||
2355 | Info = _WRONG_MESSAGE_FORMAT; | ||
2356 | } | ||
2357 | break; | ||
2358 | case S_CCBS_REQUEST: | ||
2359 | case S_CCBS_DEACTIVATE: | ||
2360 | if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms)) | ||
2361 | { | ||
2362 | dbug(0,dprintf("format wrong")); | ||
2363 | Info = _WRONG_MESSAGE_FORMAT; | ||
2364 | } | ||
2365 | break; | ||
2366 | case S_CCBS_INTERROGATE: | ||
2367 | if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms)) | ||
2368 | { | ||
2369 | dbug(0,dprintf("format wrong")); | ||
2370 | Info = _WRONG_MESSAGE_FORMAT; | ||
2371 | } | ||
2372 | break; | ||
2373 | default: | ||
2374 | if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms)) | ||
2375 | { | ||
2376 | dbug(0,dprintf("format wrong")); | ||
2377 | Info = _WRONG_MESSAGE_FORMAT; | ||
2378 | break; | ||
2379 | } | ||
2380 | break; | ||
2381 | } | ||
2382 | |||
2383 | if(Info) break; | ||
2384 | if((i=get_plci(a))) | ||
2385 | { | ||
2386 | rplci = &a->plci[i-1]; | ||
2387 | switch(SSreq) | ||
2388 | { | ||
2389 | case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */ | ||
2390 | cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ | ||
2391 | rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */ | ||
2392 | break; | ||
2393 | case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */ | ||
2394 | cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */ | ||
2395 | rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */ | ||
2396 | break; | ||
2397 | case S_CALL_FORWARDING_STOP: | ||
2398 | rplci->internal_command = CF_STOP_PEND; | ||
2399 | cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ | ||
2400 | break; | ||
2401 | case S_CCBS_REQUEST: | ||
2402 | cai[1] = CCBS_REQUEST; | ||
2403 | rplci->internal_command = CCBS_REQUEST_REQ_PEND; | ||
2404 | break; | ||
2405 | case S_CCBS_DEACTIVATE: | ||
2406 | cai[1] = CCBS_DEACTIVATE; | ||
2407 | rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND; | ||
2408 | break; | ||
2409 | case S_CCBS_INTERROGATE: | ||
2410 | cai[1] = CCBS_INTERROGATE; | ||
2411 | rplci->internal_command = CCBS_INTERROGATE_REQ_PEND; | ||
2412 | break; | ||
2413 | default: | ||
2414 | cai[1] = 0; | ||
2415 | break; | ||
2416 | } | ||
2417 | rplci->appl = appl; | ||
2418 | rplci->number = Number; | ||
2419 | add_p(rplci,CAI,"\x01\x80"); | ||
2420 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
2421 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
2422 | send_req(rplci); | ||
2423 | } | ||
2424 | else | ||
2425 | { | ||
2426 | Info = _OUT_OF_PLCI; | ||
2427 | break; | ||
2428 | } | ||
2429 | |||
2430 | appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0])); | ||
2431 | switch(SSreq) | ||
2432 | { | ||
2433 | case S_INTERROGATE_NUMBERS: | ||
2434 | cai[0] = 1; | ||
2435 | add_p(rplci,CAI,cai); | ||
2436 | break; | ||
2437 | case S_CCBS_REQUEST: | ||
2438 | case S_CCBS_DEACTIVATE: | ||
2439 | cai[0] = 3; | ||
2440 | PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0]))); | ||
2441 | add_p(rplci,CAI,cai); | ||
2442 | break; | ||
2443 | case S_CCBS_INTERROGATE: | ||
2444 | cai[0] = 3; | ||
2445 | PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0]))); | ||
2446 | add_p(rplci,CAI,cai); | ||
2447 | add_p(rplci,OAD,ss_parms[4].info); | ||
2448 | break; | ||
2449 | default: | ||
2450 | cai[0] = 2; | ||
2451 | cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */ | ||
2452 | add_p(rplci,CAI,cai); | ||
2453 | add_p(rplci,OAD,ss_parms[5].info); | ||
2454 | break; | ||
2455 | } | ||
2456 | |||
2457 | sig_req(rplci,S_SERVICE,0); | ||
2458 | send_req(rplci); | ||
2459 | return FALSE; | ||
2460 | break; | ||
2461 | |||
2462 | case S_MWI_ACTIVATE: | ||
2463 | if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms)) | ||
2464 | { | ||
2465 | dbug(1,dprintf("format wrong")); | ||
2466 | Info = _WRONG_MESSAGE_FORMAT; | ||
2467 | break; | ||
2468 | } | ||
2469 | if(!plci) | ||
2470 | { | ||
2471 | if((i=get_plci(a))) | ||
2472 | { | ||
2473 | rplci = &a->plci[i-1]; | ||
2474 | rplci->appl = appl; | ||
2475 | rplci->cr_enquiry=TRUE; | ||
2476 | add_p(rplci,CAI,"\x01\x80"); | ||
2477 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
2478 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
2479 | send_req(rplci); | ||
2480 | } | ||
2481 | else | ||
2482 | { | ||
2483 | Info = _OUT_OF_PLCI; | ||
2484 | break; | ||
2485 | } | ||
2486 | } | ||
2487 | else | ||
2488 | { | ||
2489 | rplci = plci; | ||
2490 | rplci->cr_enquiry=FALSE; | ||
2491 | } | ||
2492 | |||
2493 | rplci->command = 0; | ||
2494 | rplci->internal_command = MWI_ACTIVATE_REQ_PEND; | ||
2495 | rplci->appl = appl; | ||
2496 | rplci->number = Number; | ||
2497 | |||
2498 | cai[0] = 13; | ||
2499 | cai[1] = ACTIVATION_MWI; /* Function */ | ||
2500 | PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ | ||
2501 | PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */ | ||
2502 | PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */ | ||
2503 | PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */ | ||
2504 | PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */ | ||
2505 | add_p(rplci,CAI,cai); | ||
2506 | add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */ | ||
2507 | add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */ | ||
2508 | add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */ | ||
2509 | add_p(rplci,UID,ss_parms[10].info); /* Time */ | ||
2510 | sig_req(rplci,S_SERVICE,0); | ||
2511 | send_req(rplci); | ||
2512 | return FALSE; | ||
2513 | |||
2514 | case S_MWI_DEACTIVATE: | ||
2515 | if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms)) | ||
2516 | { | ||
2517 | dbug(1,dprintf("format wrong")); | ||
2518 | Info = _WRONG_MESSAGE_FORMAT; | ||
2519 | break; | ||
2520 | } | ||
2521 | if(!plci) | ||
2522 | { | ||
2523 | if((i=get_plci(a))) | ||
2524 | { | ||
2525 | rplci = &a->plci[i-1]; | ||
2526 | rplci->appl = appl; | ||
2527 | rplci->cr_enquiry=TRUE; | ||
2528 | add_p(rplci,CAI,"\x01\x80"); | ||
2529 | add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
2530 | sig_req(rplci,ASSIGN,DSIG_ID); | ||
2531 | send_req(rplci); | ||
2532 | } | ||
2533 | else | ||
2534 | { | ||
2535 | Info = _OUT_OF_PLCI; | ||
2536 | break; | ||
2537 | } | ||
2538 | } | ||
2539 | else | ||
2540 | { | ||
2541 | rplci = plci; | ||
2542 | rplci->cr_enquiry=FALSE; | ||
2543 | } | ||
2544 | |||
2545 | rplci->command = 0; | ||
2546 | rplci->internal_command = MWI_DEACTIVATE_REQ_PEND; | ||
2547 | rplci->appl = appl; | ||
2548 | rplci->number = Number; | ||
2549 | |||
2550 | cai[0] = 5; | ||
2551 | cai[1] = DEACTIVATION_MWI; /* Function */ | ||
2552 | PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ | ||
2553 | PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */ | ||
2554 | add_p(rplci,CAI,cai); | ||
2555 | add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */ | ||
2556 | add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */ | ||
2557 | sig_req(rplci,S_SERVICE,0); | ||
2558 | send_req(rplci); | ||
2559 | return FALSE; | ||
2560 | |||
2561 | default: | ||
2562 | Info = 0x300E; /* not supported */ | ||
2563 | break; | ||
2564 | } | ||
2565 | break; /* case SELECTOR_SU_SERV: end */ | ||
2566 | |||
2567 | |||
2568 | case SELECTOR_DTMF: | ||
2569 | return (dtmf_request (Id, Number, a, plci, appl, msg)); | ||
2570 | |||
2571 | |||
2572 | |||
2573 | case SELECTOR_LINE_INTERCONNECT: | ||
2574 | return (mixer_request (Id, Number, a, plci, appl, msg)); | ||
2575 | |||
2576 | |||
2577 | |||
2578 | case PRIV_SELECTOR_ECHO_CANCELLER: | ||
2579 | appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC; | ||
2580 | return (ec_request (Id, Number, a, plci, appl, msg)); | ||
2581 | |||
2582 | case SELECTOR_ECHO_CANCELLER: | ||
2583 | appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC; | ||
2584 | return (ec_request (Id, Number, a, plci, appl, msg)); | ||
2585 | |||
2586 | |||
2587 | case SELECTOR_V42BIS: | ||
2588 | default: | ||
2589 | Info = _FACILITY_NOT_SUPPORTED; | ||
2590 | break; | ||
2591 | } /* end of switch(selector) */ | ||
2592 | } | ||
2593 | |||
2594 | dbug(1,dprintf("SendFacRc")); | ||
2595 | sendf(appl, | ||
2596 | _FACILITY_R|CONFIRM, | ||
2597 | Id, | ||
2598 | Number, | ||
2599 | "wws",Info,selector,SSparms); | ||
2600 | return FALSE; | ||
2601 | } | ||
2602 | |||
2603 | byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
2604 | { | ||
2605 | dbug(1,dprintf("facility_res")); | ||
2606 | return FALSE; | ||
2607 | } | ||
2608 | |||
2609 | byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
2610 | { | ||
2611 | word Info = 0; | ||
2612 | byte req; | ||
2613 | byte len; | ||
2614 | word w; | ||
2615 | word fax_control_bits, fax_feature_bits, fax_info_change; | ||
2616 | API_PARSE * ncpi; | ||
2617 | byte pvc[2]; | ||
2618 | |||
2619 | API_PARSE fax_parms[9]; | ||
2620 | word i; | ||
2621 | |||
2622 | |||
2623 | dbug(1,dprintf("connect_b3_req")); | ||
2624 | if(plci) | ||
2625 | { | ||
2626 | if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) | ||
2627 | || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE)) | ||
2628 | { | ||
2629 | Info = _WRONG_STATE; | ||
2630 | } | ||
2631 | else | ||
2632 | { | ||
2633 | /* local reply if assign unsuccessfull | ||
2634 | or B3 protocol allows only one layer 3 connection | ||
2635 | and already connected | ||
2636 | or B2 protocol not any LAPD | ||
2637 | and connect_b3_req contradicts originate/answer direction */ | ||
2638 | if (!plci->NL.Id | ||
2639 | || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)) | ||
2640 | && ((plci->channels != 0) | ||
2641 | || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)) | ||
2642 | && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL)))))) | ||
2643 | { | ||
2644 | dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x", | ||
2645 | plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState)); | ||
2646 | Info = _WRONG_STATE; | ||
2647 | sendf(appl, | ||
2648 | _CONNECT_B3_R|CONFIRM, | ||
2649 | Id, | ||
2650 | Number, | ||
2651 | "w",Info); | ||
2652 | return FALSE; | ||
2653 | } | ||
2654 | plci->requested_options_conn = 0; | ||
2655 | |||
2656 | req = N_CONNECT; | ||
2657 | ncpi = &parms[0]; | ||
2658 | if(plci->B3_prot==2 || plci->B3_prot==3) | ||
2659 | { | ||
2660 | if(ncpi->length>2) | ||
2661 | { | ||
2662 | /* check for PVC */ | ||
2663 | if(ncpi->info[2] || ncpi->info[3]) | ||
2664 | { | ||
2665 | pvc[0] = ncpi->info[3]; | ||
2666 | pvc[1] = ncpi->info[2]; | ||
2667 | add_d(plci,2,pvc); | ||
2668 | req = N_RESET; | ||
2669 | } | ||
2670 | else | ||
2671 | { | ||
2672 | if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT; | ||
2673 | add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]); | ||
2674 | } | ||
2675 | } | ||
2676 | } | ||
2677 | else if(plci->B3_prot==5) | ||
2678 | { | ||
2679 | if (plci->NL.Id && !plci->nl_remove_id) | ||
2680 | { | ||
2681 | fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low); | ||
2682 | fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low); | ||
2683 | if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS) | ||
2684 | || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)) | ||
2685 | { | ||
2686 | len = (byte)(&(((T30_INFO *) 0)->universal_6)); | ||
2687 | fax_info_change = FALSE; | ||
2688 | if (ncpi->length >= 4) | ||
2689 | { | ||
2690 | w = GET_WORD(&ncpi->info[3]); | ||
2691 | if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001))) | ||
2692 | { | ||
2693 | ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution = | ||
2694 | (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) | | ||
2695 | ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0)); | ||
2696 | fax_info_change = TRUE; | ||
2697 | } | ||
2698 | fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS); | ||
2699 | if (w & 0x0002) /* Fax-polling request */ | ||
2700 | fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING; | ||
2701 | if ((w & 0x0004) /* Request to send / poll another document */ | ||
2702 | && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS)) | ||
2703 | { | ||
2704 | fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS; | ||
2705 | } | ||
2706 | if (ncpi->length >= 6) | ||
2707 | { | ||
2708 | w = GET_WORD(&ncpi->info[5]); | ||
2709 | if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format) | ||
2710 | { | ||
2711 | ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w; | ||
2712 | fax_info_change = TRUE; | ||
2713 | } | ||
2714 | |||
2715 | if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | ||
2716 | && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */ | ||
2717 | { | ||
2718 | plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD); | ||
2719 | } | ||
2720 | if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD)) | ||
2721 | && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */ | ||
2722 | { | ||
2723 | plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD); | ||
2724 | } | ||
2725 | fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING | | ||
2726 | T30_CONTROL_BIT_ACCEPT_PASSWORD); | ||
2727 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1]) | ||
2728 | & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | ||
2729 | { | ||
2730 | if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms)) | ||
2731 | Info = _WRONG_MESSAGE_FORMAT; | ||
2732 | else | ||
2733 | { | ||
2734 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1]) | ||
2735 | & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | ||
2736 | { | ||
2737 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD; | ||
2738 | if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING) | ||
2739 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; | ||
2740 | } | ||
2741 | w = fax_parms[4].length; | ||
2742 | if (w > 20) | ||
2743 | w = 20; | ||
2744 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w; | ||
2745 | for (i = 0; i < w; i++) | ||
2746 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i]; | ||
2747 | ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; | ||
2748 | len = (byte)(((T30_INFO *) 0)->station_id + 20); | ||
2749 | w = fax_parms[5].length; | ||
2750 | if (w > 20) | ||
2751 | w = 20; | ||
2752 | plci->fax_connect_info_buffer[len++] = (byte) w; | ||
2753 | for (i = 0; i < w; i++) | ||
2754 | plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i]; | ||
2755 | w = fax_parms[6].length; | ||
2756 | if (w > 20) | ||
2757 | w = 20; | ||
2758 | plci->fax_connect_info_buffer[len++] = (byte) w; | ||
2759 | for (i = 0; i < w; i++) | ||
2760 | plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i]; | ||
2761 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1]) | ||
2762 | & (1L << PRIVATE_FAX_NONSTANDARD)) | ||
2763 | { | ||
2764 | if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms)) | ||
2765 | { | ||
2766 | dbug(1,dprintf("non-standard facilities info missing or wrong format")); | ||
2767 | plci->fax_connect_info_buffer[len++] = 0; | ||
2768 | } | ||
2769 | else | ||
2770 | { | ||
2771 | if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) | ||
2772 | plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); | ||
2773 | plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); | ||
2774 | for (i = 0; i < fax_parms[7].length; i++) | ||
2775 | plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; | ||
2776 | } | ||
2777 | } | ||
2778 | } | ||
2779 | } | ||
2780 | else | ||
2781 | { | ||
2782 | len = (byte)(&(((T30_INFO *) 0)->universal_6)); | ||
2783 | } | ||
2784 | fax_info_change = TRUE; | ||
2785 | |||
2786 | } | ||
2787 | if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low)) | ||
2788 | { | ||
2789 | PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits); | ||
2790 | fax_info_change = TRUE; | ||
2791 | } | ||
2792 | } | ||
2793 | if (Info == GOOD) | ||
2794 | { | ||
2795 | plci->fax_connect_info_length = len; | ||
2796 | if (fax_info_change) | ||
2797 | { | ||
2798 | if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS) | ||
2799 | { | ||
2800 | start_internal_command (Id, plci, fax_connect_info_command); | ||
2801 | return FALSE; | ||
2802 | } | ||
2803 | else | ||
2804 | { | ||
2805 | start_internal_command (Id, plci, fax_adjust_b23_command); | ||
2806 | return FALSE; | ||
2807 | } | ||
2808 | } | ||
2809 | } | ||
2810 | } | ||
2811 | else Info = _WRONG_STATE; | ||
2812 | } | ||
2813 | else Info = _WRONG_STATE; | ||
2814 | } | ||
2815 | |||
2816 | else if (plci->B3_prot == B3_RTP) | ||
2817 | { | ||
2818 | plci->internal_req_buffer[0] = ncpi->length + 1; | ||
2819 | plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE; | ||
2820 | for (w = 0; w < ncpi->length; w++) | ||
2821 | plci->internal_req_buffer[2+w] = ncpi->info[1+w]; | ||
2822 | start_internal_command (Id, plci, rtp_connect_b3_req_command); | ||
2823 | return FALSE; | ||
2824 | } | ||
2825 | |||
2826 | if(!Info) | ||
2827 | { | ||
2828 | nl_req_ncci(plci,req,0); | ||
2829 | return 1; | ||
2830 | } | ||
2831 | } | ||
2832 | } | ||
2833 | else Info = _WRONG_IDENTIFIER; | ||
2834 | |||
2835 | sendf(appl, | ||
2836 | _CONNECT_B3_R|CONFIRM, | ||
2837 | Id, | ||
2838 | Number, | ||
2839 | "w",Info); | ||
2840 | return FALSE; | ||
2841 | } | ||
2842 | |||
2843 | byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
2844 | { | ||
2845 | word ncci; | ||
2846 | API_PARSE * ncpi; | ||
2847 | byte req; | ||
2848 | |||
2849 | word w; | ||
2850 | |||
2851 | |||
2852 | API_PARSE fax_parms[9]; | ||
2853 | word i; | ||
2854 | byte len; | ||
2855 | |||
2856 | |||
2857 | dbug(1,dprintf("connect_b3_res")); | ||
2858 | |||
2859 | ncci = (word)(Id>>16); | ||
2860 | if(plci && ncci) { | ||
2861 | if(a->ncci_state[ncci]==INC_CON_PENDING) { | ||
2862 | if (GET_WORD (&parms[0].info[0]) != 0) | ||
2863 | { | ||
2864 | a->ncci_state[ncci] = OUTG_REJ_PENDING; | ||
2865 | channel_request_xon (plci, a->ncci_ch[ncci]); | ||
2866 | channel_xmit_xon (plci); | ||
2867 | cleanup_ncci_data (plci, ncci); | ||
2868 | nl_req_ncci(plci,N_DISC,(byte)ncci); | ||
2869 | return 1; | ||
2870 | } | ||
2871 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
2872 | |||
2873 | req = N_CONNECT_ACK; | ||
2874 | ncpi = &parms[1]; | ||
2875 | if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7)) | ||
2876 | { | ||
2877 | |||
2878 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | ||
2879 | & (1L << PRIVATE_FAX_NONSTANDARD)) | ||
2880 | { | ||
2881 | if (((plci->B3_prot == 4) || (plci->B3_prot == 5)) | ||
2882 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | ||
2883 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | ||
2884 | { | ||
2885 | len = ((byte)(((T30_INFO *) 0)->station_id + 20)); | ||
2886 | if (plci->fax_connect_info_length < len) | ||
2887 | { | ||
2888 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; | ||
2889 | ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; | ||
2890 | } | ||
2891 | if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms)) | ||
2892 | { | ||
2893 | dbug(1,dprintf("non-standard facilities info missing or wrong format")); | ||
2894 | } | ||
2895 | else | ||
2896 | { | ||
2897 | if (plci->fax_connect_info_length <= len) | ||
2898 | plci->fax_connect_info_buffer[len] = 0; | ||
2899 | len += 1 + plci->fax_connect_info_buffer[len]; | ||
2900 | if (plci->fax_connect_info_length <= len) | ||
2901 | plci->fax_connect_info_buffer[len] = 0; | ||
2902 | len += 1 + plci->fax_connect_info_buffer[len]; | ||
2903 | if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) | ||
2904 | plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); | ||
2905 | plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); | ||
2906 | for (i = 0; i < fax_parms[7].length; i++) | ||
2907 | plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; | ||
2908 | } | ||
2909 | plci->fax_connect_info_length = len; | ||
2910 | ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0; | ||
2911 | start_internal_command (Id, plci, fax_connect_ack_command); | ||
2912 | return FALSE; | ||
2913 | } | ||
2914 | } | ||
2915 | |||
2916 | nl_req_ncci(plci,req,(byte)ncci); | ||
2917 | if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
2918 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
2919 | { | ||
2920 | if (plci->B3_prot == 4) | ||
2921 | sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
2922 | else | ||
2923 | sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | ||
2924 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
2925 | } | ||
2926 | } | ||
2927 | |||
2928 | else if (plci->B3_prot == B3_RTP) | ||
2929 | { | ||
2930 | plci->internal_req_buffer[0] = ncpi->length + 1; | ||
2931 | plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE; | ||
2932 | for (w = 0; w < ncpi->length; w++) | ||
2933 | plci->internal_req_buffer[2+w] = ncpi->info[1+w]; | ||
2934 | start_internal_command (Id, plci, rtp_connect_b3_res_command); | ||
2935 | return FALSE; | ||
2936 | } | ||
2937 | |||
2938 | else | ||
2939 | { | ||
2940 | if(ncpi->length>2) { | ||
2941 | if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT; | ||
2942 | add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]); | ||
2943 | } | ||
2944 | nl_req_ncci(plci,req,(byte)ncci); | ||
2945 | sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
2946 | if (plci->adjust_b_restore) | ||
2947 | { | ||
2948 | plci->adjust_b_restore = FALSE; | ||
2949 | start_internal_command (Id, plci, adjust_b_restore); | ||
2950 | } | ||
2951 | } | ||
2952 | return 1; | ||
2953 | } | ||
2954 | } | ||
2955 | return FALSE; | ||
2956 | } | ||
2957 | |||
2958 | byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
2959 | { | ||
2960 | word ncci; | ||
2961 | |||
2962 | ncci = (word)(Id>>16); | ||
2963 | dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci)); | ||
2964 | |||
2965 | if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING) | ||
2966 | && (plci->State != OUTG_DIS_PENDING)) | ||
2967 | { | ||
2968 | if(a->ncci_state[ncci]==INC_ACT_PENDING) { | ||
2969 | a->ncci_state[ncci] = CONNECTED; | ||
2970 | if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED; | ||
2971 | channel_request_xon (plci, a->ncci_ch[ncci]); | ||
2972 | channel_xmit_xon (plci); | ||
2973 | } | ||
2974 | } | ||
2975 | return FALSE; | ||
2976 | } | ||
2977 | |||
2978 | byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
2979 | { | ||
2980 | word Info; | ||
2981 | word ncci; | ||
2982 | API_PARSE * ncpi; | ||
2983 | |||
2984 | dbug(1,dprintf("disconnect_b3_req")); | ||
2985 | |||
2986 | Info = _WRONG_IDENTIFIER; | ||
2987 | ncci = (word)(Id>>16); | ||
2988 | if (plci && ncci) | ||
2989 | { | ||
2990 | Info = _WRONG_STATE; | ||
2991 | if ((a->ncci_state[ncci] == CONNECTED) | ||
2992 | || (a->ncci_state[ncci] == OUTG_CON_PENDING) | ||
2993 | || (a->ncci_state[ncci] == INC_CON_PENDING) | ||
2994 | || (a->ncci_state[ncci] == INC_ACT_PENDING)) | ||
2995 | { | ||
2996 | a->ncci_state[ncci] = OUTG_DIS_PENDING; | ||
2997 | channel_request_xon (plci, a->ncci_ch[ncci]); | ||
2998 | channel_xmit_xon (plci); | ||
2999 | |||
3000 | if (a->ncci[ncci].data_pending | ||
3001 | && ((plci->B3_prot == B3_TRANSPARENT) | ||
3002 | || (plci->B3_prot == B3_T30) | ||
3003 | || (plci->B3_prot == B3_T30_WITH_EXTENSIONS))) | ||
3004 | { | ||
3005 | plci->send_disc = (byte)ncci; | ||
3006 | plci->command = 0; | ||
3007 | return FALSE; | ||
3008 | } | ||
3009 | else | ||
3010 | { | ||
3011 | cleanup_ncci_data (plci, ncci); | ||
3012 | |||
3013 | if(plci->B3_prot==2 || plci->B3_prot==3) | ||
3014 | { | ||
3015 | ncpi = &parms[0]; | ||
3016 | if(ncpi->length>3) | ||
3017 | { | ||
3018 | add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4])); | ||
3019 | } | ||
3020 | } | ||
3021 | nl_req_ncci(plci,N_DISC,(byte)ncci); | ||
3022 | } | ||
3023 | return 1; | ||
3024 | } | ||
3025 | } | ||
3026 | sendf(appl, | ||
3027 | _DISCONNECT_B3_R|CONFIRM, | ||
3028 | Id, | ||
3029 | Number, | ||
3030 | "w",Info); | ||
3031 | return FALSE; | ||
3032 | } | ||
3033 | |||
3034 | byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3035 | { | ||
3036 | word ncci; | ||
3037 | word i; | ||
3038 | |||
3039 | ncci = (word)(Id>>16); | ||
3040 | dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci)); | ||
3041 | if(plci && ncci) { | ||
3042 | plci->requested_options_conn = 0; | ||
3043 | plci->fax_connect_info_length = 0; | ||
3044 | plci->ncpi_state = 0x00; | ||
3045 | if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)) | ||
3046 | && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))) | ||
3047 | { | ||
3048 | plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; | ||
3049 | } | ||
3050 | for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++); | ||
3051 | if(i<MAX_CHANNELS_PER_PLCI) { | ||
3052 | if(plci->channels)plci->channels--; | ||
3053 | for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1]; | ||
3054 | plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0; | ||
3055 | |||
3056 | ncci_free_receive_buffers (plci, ncci); | ||
3057 | |||
3058 | if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){ | ||
3059 | if(plci->State == SUSPENDING){ | ||
3060 | sendf(plci->appl, | ||
3061 | _FACILITY_I, | ||
3062 | Id & 0xffffL, | ||
3063 | 0, | ||
3064 | "ws", (word)3, "\x03\x04\x00\x00"); | ||
3065 | sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0); | ||
3066 | } | ||
3067 | plci_remove(plci); | ||
3068 | plci->State=IDLE; | ||
3069 | } | ||
3070 | } | ||
3071 | else | ||
3072 | { | ||
3073 | if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | ||
3074 | && ((plci->B3_prot == 4) || (plci->B3_prot == 5)) | ||
3075 | && (a->ncci_state[ncci] == INC_DIS_PENDING)) | ||
3076 | { | ||
3077 | ncci_free_receive_buffers (plci, ncci); | ||
3078 | |||
3079 | nl_req_ncci(plci,N_EDATA,(byte)ncci); | ||
3080 | |||
3081 | plci->adapter->ncci_state[ncci] = IDLE; | ||
3082 | start_internal_command (Id, plci, fax_disconnect_command); | ||
3083 | return 1; | ||
3084 | } | ||
3085 | } | ||
3086 | } | ||
3087 | return FALSE; | ||
3088 | } | ||
3089 | |||
3090 | byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3091 | { | ||
3092 | NCCI *ncci_ptr; | ||
3093 | DATA_B3_DESC *data; | ||
3094 | word Info; | ||
3095 | word ncci; | ||
3096 | word i; | ||
3097 | |||
3098 | dbug(1,dprintf("data_b3_req")); | ||
3099 | |||
3100 | Info = _WRONG_IDENTIFIER; | ||
3101 | ncci = (word)(Id>>16); | ||
3102 | dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci)); | ||
3103 | |||
3104 | if (plci && ncci) | ||
3105 | { | ||
3106 | Info = _WRONG_STATE; | ||
3107 | if ((a->ncci_state[ncci] == CONNECTED) | ||
3108 | || (a->ncci_state[ncci] == INC_ACT_PENDING)) | ||
3109 | { | ||
3110 | /* queue data */ | ||
3111 | ncci_ptr = &(a->ncci[ncci]); | ||
3112 | i = ncci_ptr->data_out + ncci_ptr->data_pending; | ||
3113 | if (i >= MAX_DATA_B3) | ||
3114 | i -= MAX_DATA_B3; | ||
3115 | data = &(ncci_ptr->DBuffer[i]); | ||
3116 | data->Number = Number; | ||
3117 | if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue))) | ||
3118 | && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | ||
3119 | { | ||
3120 | |||
3121 | data->P = (byte *)(*((dword *)(parms[0].info))); | ||
3122 | |||
3123 | } | ||
3124 | else | ||
3125 | data->P = TransmitBufferSet(appl,*(dword *)parms[0].info); | ||
3126 | data->Length = GET_WORD(parms[1].info); | ||
3127 | data->Handle = GET_WORD(parms[2].info); | ||
3128 | data->Flags = GET_WORD(parms[3].info); | ||
3129 | (ncci_ptr->data_pending)++; | ||
3130 | |||
3131 | /* check for delivery confirmation */ | ||
3132 | if (data->Flags & 0x0004) | ||
3133 | { | ||
3134 | i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending; | ||
3135 | if (i >= MAX_DATA_ACK) | ||
3136 | i -= MAX_DATA_ACK; | ||
3137 | ncci_ptr->DataAck[i].Number = data->Number; | ||
3138 | ncci_ptr->DataAck[i].Handle = data->Handle; | ||
3139 | (ncci_ptr->data_ack_pending)++; | ||
3140 | } | ||
3141 | |||
3142 | send_data(plci); | ||
3143 | return FALSE; | ||
3144 | } | ||
3145 | } | ||
3146 | if (appl) | ||
3147 | { | ||
3148 | if (plci) | ||
3149 | { | ||
3150 | if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue))) | ||
3151 | && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue))) | ||
3152 | { | ||
3153 | |||
3154 | TransmitBufferFree (appl, (byte *)(*((dword *)(parms[0].info)))); | ||
3155 | |||
3156 | } | ||
3157 | } | ||
3158 | sendf(appl, | ||
3159 | _DATA_B3_R|CONFIRM, | ||
3160 | Id, | ||
3161 | Number, | ||
3162 | "ww",GET_WORD(parms[2].info),Info); | ||
3163 | } | ||
3164 | return FALSE; | ||
3165 | } | ||
3166 | |||
3167 | byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3168 | { | ||
3169 | word n; | ||
3170 | word ncci; | ||
3171 | word NCCIcode; | ||
3172 | |||
3173 | dbug(1,dprintf("data_b3_res")); | ||
3174 | |||
3175 | ncci = (word)(Id>>16); | ||
3176 | if(plci && ncci) { | ||
3177 | n = GET_WORD(parms[0].info); | ||
3178 | dbug(1,dprintf("free(%d)",n)); | ||
3179 | NCCIcode = ncci | (((word) a->Id) << 8); | ||
3180 | if(n<appl->MaxBuffer && | ||
3181 | appl->DataNCCI[n]==NCCIcode && | ||
3182 | (byte)(appl->DataFlags[n]>>8)==plci->Id) { | ||
3183 | dbug(1,dprintf("found")); | ||
3184 | appl->DataNCCI[n] = 0; | ||
3185 | |||
3186 | if (channel_can_xon (plci, a->ncci_ch[ncci])) { | ||
3187 | channel_request_xon (plci, a->ncci_ch[ncci]); | ||
3188 | } | ||
3189 | channel_xmit_xon (plci); | ||
3190 | |||
3191 | if(appl->DataFlags[n] &4) { | ||
3192 | nl_req_ncci(plci,N_DATA_ACK,(byte)ncci); | ||
3193 | return 1; | ||
3194 | } | ||
3195 | } | ||
3196 | } | ||
3197 | return FALSE; | ||
3198 | } | ||
3199 | |||
3200 | byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3201 | { | ||
3202 | word Info; | ||
3203 | word ncci; | ||
3204 | |||
3205 | dbug(1,dprintf("reset_b3_req")); | ||
3206 | |||
3207 | Info = _WRONG_IDENTIFIER; | ||
3208 | ncci = (word)(Id>>16); | ||
3209 | if(plci && ncci) | ||
3210 | { | ||
3211 | Info = _WRONG_STATE; | ||
3212 | switch (plci->B3_prot) | ||
3213 | { | ||
3214 | case B3_ISO8208: | ||
3215 | case B3_X25_DCE: | ||
3216 | if(a->ncci_state[ncci]==CONNECTED) | ||
3217 | { | ||
3218 | nl_req_ncci(plci,N_RESET,(byte)ncci); | ||
3219 | send_req(plci); | ||
3220 | Info = GOOD; | ||
3221 | } | ||
3222 | break; | ||
3223 | case B3_TRANSPARENT: | ||
3224 | if(a->ncci_state[ncci]==CONNECTED) | ||
3225 | { | ||
3226 | start_internal_command (Id, plci, reset_b3_command); | ||
3227 | Info = GOOD; | ||
3228 | } | ||
3229 | break; | ||
3230 | } | ||
3231 | } | ||
3232 | /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */ | ||
3233 | sendf(appl, | ||
3234 | _RESET_B3_R|CONFIRM, | ||
3235 | Id, | ||
3236 | Number, | ||
3237 | "w",Info); | ||
3238 | return FALSE; | ||
3239 | } | ||
3240 | |||
3241 | byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3242 | { | ||
3243 | word ncci; | ||
3244 | |||
3245 | dbug(1,dprintf("reset_b3_res")); | ||
3246 | |||
3247 | ncci = (word)(Id>>16); | ||
3248 | if(plci && ncci) { | ||
3249 | switch (plci->B3_prot) | ||
3250 | { | ||
3251 | case B3_ISO8208: | ||
3252 | case B3_X25_DCE: | ||
3253 | if(a->ncci_state[ncci]==INC_RES_PENDING) | ||
3254 | { | ||
3255 | a->ncci_state[ncci] = CONNECTED; | ||
3256 | nl_req_ncci(plci,N_RESET_ACK,(byte)ncci); | ||
3257 | return TRUE; | ||
3258 | } | ||
3259 | break; | ||
3260 | } | ||
3261 | } | ||
3262 | return FALSE; | ||
3263 | } | ||
3264 | |||
3265 | byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3266 | { | ||
3267 | word ncci; | ||
3268 | API_PARSE * ncpi; | ||
3269 | byte req; | ||
3270 | |||
3271 | dbug(1,dprintf("connect_b3_t90_a_res")); | ||
3272 | |||
3273 | ncci = (word)(Id>>16); | ||
3274 | if(plci && ncci) { | ||
3275 | if(a->ncci_state[ncci]==INC_ACT_PENDING) { | ||
3276 | a->ncci_state[ncci] = CONNECTED; | ||
3277 | } | ||
3278 | else if(a->ncci_state[ncci]==INC_CON_PENDING) { | ||
3279 | a->ncci_state[ncci] = CONNECTED; | ||
3280 | |||
3281 | req = N_CONNECT_ACK; | ||
3282 | |||
3283 | /* parms[0]==0 for CAPI original message definition! */ | ||
3284 | if(parms[0].info) { | ||
3285 | ncpi = &parms[1]; | ||
3286 | if(ncpi->length>2) { | ||
3287 | if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT; | ||
3288 | add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]); | ||
3289 | } | ||
3290 | } | ||
3291 | nl_req_ncci(plci,req,(byte)ncci); | ||
3292 | return 1; | ||
3293 | } | ||
3294 | } | ||
3295 | return FALSE; | ||
3296 | } | ||
3297 | |||
3298 | |||
3299 | byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
3300 | { | ||
3301 | word Info=0; | ||
3302 | word i; | ||
3303 | byte tel; | ||
3304 | API_PARSE bp_parms[7]; | ||
3305 | |||
3306 | if(!plci || !msg) | ||
3307 | { | ||
3308 | Info = _WRONG_IDENTIFIER; | ||
3309 | } | ||
3310 | else | ||
3311 | { | ||
3312 | dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x", | ||
3313 | msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState)); | ||
3314 | dbug(1,dprintf("PlciState=0x%x",plci->State)); | ||
3315 | for(i=0;i<7;i++) bp_parms[i].length = 0; | ||
3316 | |||
3317 | /* check if no channel is open, no B3 connected only */ | ||
3318 | if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING) | ||
3319 | || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id) | ||
3320 | { | ||
3321 | Info = _WRONG_STATE; | ||
3322 | } | ||
3323 | /* check message format and fill bp_parms pointer */ | ||
3324 | else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms)) | ||
3325 | { | ||
3326 | Info = _WRONG_MESSAGE_FORMAT; | ||
3327 | } | ||
3328 | else | ||
3329 | { | ||
3330 | if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */ | ||
3331 | { /* e.g. Qsig or RBS or Cornet-N or xess PRI */ | ||
3332 | if(Id & EXT_CONTROLLER) | ||
3333 | { | ||
3334 | sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */ | ||
3335 | return 0; | ||
3336 | } | ||
3337 | plci->State=INC_CON_CONNECTED_ALERT; | ||
3338 | plci->appl = appl; | ||
3339 | clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); | ||
3340 | dump_c_ind_mask (plci); | ||
3341 | for(i=0; i<max_appl; i++) /* disconnect the other appls */ | ||
3342 | { /* its quasi a connect */ | ||
3343 | if(test_c_ind_mask_bit (plci, i)) | ||
3344 | sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED); | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3348 | api_save_msg(msg, "s", &plci->saved_msg); | ||
3349 | tel = plci->tel; | ||
3350 | if(Id & EXT_CONTROLLER) | ||
3351 | { | ||
3352 | if(tel) /* external controller in use by this PLCI */ | ||
3353 | { | ||
3354 | if(a->AdvSignalAppl && a->AdvSignalAppl!=appl) | ||
3355 | { | ||
3356 | dbug(1,dprintf("Ext_Ctrl in use 1")); | ||
3357 | Info = _WRONG_STATE; | ||
3358 | } | ||
3359 | } | ||
3360 | else /* external controller NOT in use by this PLCI ? */ | ||
3361 | { | ||
3362 | if(a->AdvSignalPLCI) | ||
3363 | { | ||
3364 | dbug(1,dprintf("Ext_Ctrl in use 2")); | ||
3365 | Info = _WRONG_STATE; | ||
3366 | } | ||
3367 | else /* activate the codec */ | ||
3368 | { | ||
3369 | dbug(1,dprintf("Ext_Ctrl start")); | ||
3370 | if(AdvCodecSupport(a, plci, appl, 0) ) | ||
3371 | { | ||
3372 | dbug(1,dprintf("Error in codec procedures")); | ||
3373 | Info = _WRONG_STATE; | ||
3374 | } | ||
3375 | else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */ | ||
3376 | { | ||
3377 | plci->spoofed_msg = AWAITING_SELECT_B; | ||
3378 | plci->internal_command = BLOCK_PLCI; /* lock other commands */ | ||
3379 | plci->command = 0; | ||
3380 | dbug(1,dprintf("continue if codec loaded")); | ||
3381 | return FALSE; | ||
3382 | } | ||
3383 | } | ||
3384 | } | ||
3385 | } | ||
3386 | else /* external controller bit is OFF */ | ||
3387 | { | ||
3388 | if(tel) /* external controller in use, need to switch off */ | ||
3389 | { | ||
3390 | if(a->AdvSignalAppl==appl) | ||
3391 | { | ||
3392 | CodecIdCheck(a, plci); | ||
3393 | plci->tel = 0; | ||
3394 | plci->adv_nl = 0; | ||
3395 | dbug(1,dprintf("Ext_Ctrl disable")); | ||
3396 | } | ||
3397 | else | ||
3398 | { | ||
3399 | dbug(1,dprintf("Ext_Ctrl not requested")); | ||
3400 | } | ||
3401 | } | ||
3402 | } | ||
3403 | if (!Info) | ||
3404 | { | ||
3405 | if (plci->call_dir & CALL_DIR_OUT) | ||
3406 | plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | ||
3407 | else if (plci->call_dir & CALL_DIR_IN) | ||
3408 | plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER; | ||
3409 | start_internal_command (Id, plci, select_b_command); | ||
3410 | return FALSE; | ||
3411 | } | ||
3412 | } | ||
3413 | } | ||
3414 | sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info); | ||
3415 | return FALSE; | ||
3416 | } | ||
3417 | |||
3418 | byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms) | ||
3419 | { | ||
3420 | word command; | ||
3421 | word i; | ||
3422 | word ncci; | ||
3423 | API_PARSE * m; | ||
3424 | API_PARSE m_parms[5]; | ||
3425 | word codec; | ||
3426 | byte req; | ||
3427 | byte ch; | ||
3428 | byte dir; | ||
3429 | static byte chi[2] = {0x01,0x00}; | ||
3430 | static byte lli[2] = {0x01,0x00}; | ||
3431 | static byte codec_cai[2] = {0x01,0x01}; | ||
3432 | static byte null_msg = {0}; | ||
3433 | static API_PARSE null_parms = { 0, &null_msg }; | ||
3434 | PLCI * v_plci; | ||
3435 | word Info=0; | ||
3436 | |||
3437 | dbug(1,dprintf("manufacturer_req")); | ||
3438 | for(i=0;i<5;i++) m_parms[i].length = 0; | ||
3439 | |||
3440 | if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) { | ||
3441 | Info = _WRONG_MESSAGE_FORMAT; | ||
3442 | } | ||
3443 | command = GET_WORD(parms[1].info); | ||
3444 | m = &parms[2]; | ||
3445 | if (!Info) | ||
3446 | { | ||
3447 | switch(command) { | ||
3448 | case _DI_ASSIGN_PLCI: | ||
3449 | if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) { | ||
3450 | Info = _WRONG_MESSAGE_FORMAT; | ||
3451 | break; | ||
3452 | } | ||
3453 | codec = GET_WORD(m_parms[0].info); | ||
3454 | ch = m_parms[1].info[0]; | ||
3455 | dir = m_parms[2].info[0]; | ||
3456 | if((i=get_plci(a))) { | ||
3457 | plci = &a->plci[i-1]; | ||
3458 | plci->appl = appl; | ||
3459 | plci->command = _MANUFACTURER_R; | ||
3460 | plci->m_command = command; | ||
3461 | plci->number = Number; | ||
3462 | plci->State = LOCAL_CONNECT; | ||
3463 | Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80); | ||
3464 | dbug(1,dprintf("ManCMD,plci=0x%x",Id)); | ||
3465 | |||
3466 | if((ch==1 || ch==2) && (dir<=2)) { | ||
3467 | chi[1] = (byte)(0x80|ch); | ||
3468 | lli[1] = 0; | ||
3469 | plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | ||
3470 | switch(codec) | ||
3471 | { | ||
3472 | case 0: | ||
3473 | Info = add_b1(plci,&m_parms[3],0,0); | ||
3474 | break; | ||
3475 | case 1: | ||
3476 | add_p(plci,CAI,codec_cai); | ||
3477 | break; | ||
3478 | /* manual 'swich on' to the codec support without signalling */ | ||
3479 | /* first 'assign plci' with this function, then use */ | ||
3480 | case 2: | ||
3481 | if(AdvCodecSupport(a, plci, appl, 0) ) { | ||
3482 | Info = _RESOURCE_ERROR; | ||
3483 | } | ||
3484 | else { | ||
3485 | Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL); | ||
3486 | lli[1] = 0x10; /* local call codec stream */ | ||
3487 | } | ||
3488 | break; | ||
3489 | } | ||
3490 | |||
3491 | plci->State = LOCAL_CONNECT; | ||
3492 | plci->manufacturer = TRUE; | ||
3493 | plci->command = _MANUFACTURER_R; | ||
3494 | plci->m_command = command; | ||
3495 | plci->number = Number; | ||
3496 | |||
3497 | if(!Info) | ||
3498 | { | ||
3499 | add_p(plci,LLI,lli); | ||
3500 | add_p(plci,CHI,chi); | ||
3501 | add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
3502 | sig_req(plci,ASSIGN,DSIG_ID); | ||
3503 | |||
3504 | if(!codec) | ||
3505 | { | ||
3506 | Info = add_b23(plci,&m_parms[3]); | ||
3507 | if(!Info) | ||
3508 | { | ||
3509 | nl_req_ncci(plci,ASSIGN,0); | ||
3510 | send_req(plci); | ||
3511 | } | ||
3512 | } | ||
3513 | if(!Info) | ||
3514 | { | ||
3515 | dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg)); | ||
3516 | if (plci->spoofed_msg==SPOOFING_REQUIRED) | ||
3517 | { | ||
3518 | api_save_msg (m_parms, "wbbs", &plci->saved_msg); | ||
3519 | plci->spoofed_msg = AWAITING_MANUF_CON; | ||
3520 | plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */ | ||
3521 | plci->command = 0; | ||
3522 | send_req(plci); | ||
3523 | return FALSE; | ||
3524 | } | ||
3525 | if(dir==1) { | ||
3526 | sig_req(plci,CALL_REQ,0); | ||
3527 | } | ||
3528 | else if(!dir){ | ||
3529 | sig_req(plci,LISTEN_REQ,0); | ||
3530 | } | ||
3531 | send_req(plci); | ||
3532 | } | ||
3533 | else | ||
3534 | { | ||
3535 | sendf(appl, | ||
3536 | _MANUFACTURER_R|CONFIRM, | ||
3537 | Id, | ||
3538 | Number, | ||
3539 | "dww",_DI_MANU_ID,command,Info); | ||
3540 | return 2; | ||
3541 | } | ||
3542 | } | ||
3543 | } | ||
3544 | } | ||
3545 | else Info = _OUT_OF_PLCI; | ||
3546 | break; | ||
3547 | |||
3548 | case _DI_IDI_CTRL: | ||
3549 | if(!plci) | ||
3550 | { | ||
3551 | Info = _WRONG_IDENTIFIER; | ||
3552 | break; | ||
3553 | } | ||
3554 | if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) { | ||
3555 | Info = _WRONG_MESSAGE_FORMAT; | ||
3556 | break; | ||
3557 | } | ||
3558 | req = m_parms[0].info[0]; | ||
3559 | plci->command = _MANUFACTURER_R; | ||
3560 | plci->m_command = command; | ||
3561 | plci->number = Number; | ||
3562 | if(req==CALL_REQ) | ||
3563 | { | ||
3564 | plci->b_channel = getChannel(&m_parms[1]); | ||
3565 | mixer_set_bchannel_id_esc (plci, plci->b_channel); | ||
3566 | if(plci->spoofed_msg==SPOOFING_REQUIRED) | ||
3567 | { | ||
3568 | plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON; | ||
3569 | plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */ | ||
3570 | plci->command = 0; | ||
3571 | break; | ||
3572 | } | ||
3573 | } | ||
3574 | else if(req==LAW_REQ) | ||
3575 | { | ||
3576 | plci->cr_enquiry = TRUE; | ||
3577 | } | ||
3578 | add_ss(plci,FTY,&m_parms[1]); | ||
3579 | sig_req(plci,req,0); | ||
3580 | send_req(plci); | ||
3581 | if(req==HANGUP) | ||
3582 | { | ||
3583 | if (plci->NL.Id && !plci->nl_remove_id) | ||
3584 | { | ||
3585 | if (plci->channels) | ||
3586 | { | ||
3587 | for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | ||
3588 | { | ||
3589 | if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED)) | ||
3590 | { | ||
3591 | a->ncci_state[ncci] = OUTG_DIS_PENDING; | ||
3592 | cleanup_ncci_data (plci, ncci); | ||
3593 | nl_req_ncci(plci,N_DISC,(byte)ncci); | ||
3594 | } | ||
3595 | } | ||
3596 | } | ||
3597 | mixer_remove (plci); | ||
3598 | nl_req_ncci(plci,REMOVE,0); | ||
3599 | send_req(plci); | ||
3600 | } | ||
3601 | } | ||
3602 | break; | ||
3603 | |||
3604 | case _DI_SIG_CTRL: | ||
3605 | /* signalling control for loop activation B-channel */ | ||
3606 | if(!plci) | ||
3607 | { | ||
3608 | Info = _WRONG_IDENTIFIER; | ||
3609 | break; | ||
3610 | } | ||
3611 | if(m->length){ | ||
3612 | plci->command = _MANUFACTURER_R; | ||
3613 | plci->number = Number; | ||
3614 | add_ss(plci,FTY,m); | ||
3615 | sig_req(plci,SIG_CTRL,0); | ||
3616 | send_req(plci); | ||
3617 | } | ||
3618 | else Info = _WRONG_MESSAGE_FORMAT; | ||
3619 | break; | ||
3620 | |||
3621 | case _DI_RXT_CTRL: | ||
3622 | /* activation control for receiver/transmitter B-channel */ | ||
3623 | if(!plci) | ||
3624 | { | ||
3625 | Info = _WRONG_IDENTIFIER; | ||
3626 | break; | ||
3627 | } | ||
3628 | if(m->length){ | ||
3629 | plci->command = _MANUFACTURER_R; | ||
3630 | plci->number = Number; | ||
3631 | add_ss(plci,FTY,m); | ||
3632 | sig_req(plci,DSP_CTRL,0); | ||
3633 | send_req(plci); | ||
3634 | } | ||
3635 | else Info = _WRONG_MESSAGE_FORMAT; | ||
3636 | break; | ||
3637 | |||
3638 | case _DI_ADV_CODEC: | ||
3639 | case _DI_DSP_CTRL: | ||
3640 | /* TEL_CTRL commands to support non standard adjustments: */ | ||
3641 | /* Ring on/off, Handset micro volume, external micro vol. */ | ||
3642 | /* handset+external speaker volume, receiver+transm. gain,*/ | ||
3643 | /* handsfree on (hookinfo off), set mixer command */ | ||
3644 | |||
3645 | if(command == _DI_ADV_CODEC) | ||
3646 | { | ||
3647 | if(!a->AdvCodecPLCI) { | ||
3648 | Info = _WRONG_STATE; | ||
3649 | break; | ||
3650 | } | ||
3651 | v_plci = a->AdvCodecPLCI; | ||
3652 | } | ||
3653 | else | ||
3654 | { | ||
3655 | if (plci | ||
3656 | && (m->length >= 3) | ||
3657 | && (m->info[1] == 0x1c) | ||
3658 | && (m->info[2] >= 1)) | ||
3659 | { | ||
3660 | if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS) | ||
3661 | { | ||
3662 | if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI)) | ||
3663 | { | ||
3664 | Info = _WRONG_STATE; | ||
3665 | break; | ||
3666 | } | ||
3667 | a->adv_voice_coef_length = m->info[2] - 1; | ||
3668 | if (a->adv_voice_coef_length > m->length - 3) | ||
3669 | a->adv_voice_coef_length = (byte)(m->length - 3); | ||
3670 | if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE) | ||
3671 | a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE; | ||
3672 | for (i = 0; i < a->adv_voice_coef_length; i++) | ||
3673 | a->adv_voice_coef_buffer[i] = m->info[4 + i]; | ||
3674 | if (plci->B1_facilities & B1_FACILITY_VOICE) | ||
3675 | adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE); | ||
3676 | break; | ||
3677 | } | ||
3678 | else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS) | ||
3679 | { | ||
3680 | if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS)) | ||
3681 | { | ||
3682 | Info = _FACILITY_NOT_SUPPORTED; | ||
3683 | break; | ||
3684 | } | ||
3685 | |||
3686 | plci->dtmf_parameter_length = m->info[2] - 1; | ||
3687 | if (plci->dtmf_parameter_length > m->length - 3) | ||
3688 | plci->dtmf_parameter_length = (byte)(m->length - 3); | ||
3689 | if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE) | ||
3690 | plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE; | ||
3691 | for (i = 0; i < plci->dtmf_parameter_length; i++) | ||
3692 | plci->dtmf_parameter_buffer[i] = m->info[4+i]; | ||
3693 | if (plci->B1_facilities & B1_FACILITY_DTMFR) | ||
3694 | dtmf_parameter_write (plci); | ||
3695 | break; | ||
3696 | |||
3697 | } | ||
3698 | } | ||
3699 | v_plci = plci; | ||
3700 | } | ||
3701 | |||
3702 | if(!v_plci) | ||
3703 | { | ||
3704 | Info = _WRONG_IDENTIFIER; | ||
3705 | break; | ||
3706 | } | ||
3707 | if(m->length){ | ||
3708 | add_ss(v_plci,FTY,m); | ||
3709 | sig_req(v_plci,TEL_CTRL,0); | ||
3710 | send_req(v_plci); | ||
3711 | } | ||
3712 | else Info = _WRONG_MESSAGE_FORMAT; | ||
3713 | |||
3714 | break; | ||
3715 | |||
3716 | case _DI_OPTIONS_REQUEST: | ||
3717 | if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) { | ||
3718 | Info = _WRONG_MESSAGE_FORMAT; | ||
3719 | break; | ||
3720 | } | ||
3721 | if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options) | ||
3722 | { | ||
3723 | Info = _FACILITY_NOT_SUPPORTED; | ||
3724 | break; | ||
3725 | } | ||
3726 | a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info); | ||
3727 | break; | ||
3728 | |||
3729 | |||
3730 | |||
3731 | default: | ||
3732 | Info = _WRONG_MESSAGE_FORMAT; | ||
3733 | break; | ||
3734 | } | ||
3735 | } | ||
3736 | |||
3737 | sendf(appl, | ||
3738 | _MANUFACTURER_R|CONFIRM, | ||
3739 | Id, | ||
3740 | Number, | ||
3741 | "dww",_DI_MANU_ID,command,Info); | ||
3742 | return FALSE; | ||
3743 | } | ||
3744 | |||
3745 | |||
3746 | byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg) | ||
3747 | { | ||
3748 | word indication; | ||
3749 | |||
3750 | API_PARSE m_parms[3]; | ||
3751 | API_PARSE *ncpi; | ||
3752 | API_PARSE fax_parms[9]; | ||
3753 | word i; | ||
3754 | byte len; | ||
3755 | |||
3756 | |||
3757 | dbug(1,dprintf("manufacturer_res")); | ||
3758 | |||
3759 | if ((msg[0].length == 0) | ||
3760 | || (msg[1].length == 0) | ||
3761 | || (GET_DWORD(msg[0].info)!=_DI_MANU_ID)) | ||
3762 | { | ||
3763 | return FALSE; | ||
3764 | } | ||
3765 | indication = GET_WORD(msg[1].info); | ||
3766 | switch (indication) | ||
3767 | { | ||
3768 | |||
3769 | case _DI_NEGOTIATE_B3: | ||
3770 | if(!plci) | ||
3771 | break; | ||
3772 | if (((plci->B3_prot != 4) && (plci->B3_prot != 5)) | ||
3773 | || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT)) | ||
3774 | { | ||
3775 | dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters")); | ||
3776 | break; | ||
3777 | } | ||
3778 | if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms)) | ||
3779 | { | ||
3780 | dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters")); | ||
3781 | break; | ||
3782 | } | ||
3783 | ncpi = &m_parms[1]; | ||
3784 | len = ((byte)(((T30_INFO *) 0)->station_id + 20)); | ||
3785 | if (plci->fax_connect_info_length < len) | ||
3786 | { | ||
3787 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; | ||
3788 | ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; | ||
3789 | } | ||
3790 | if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms)) | ||
3791 | { | ||
3792 | dbug(1,dprintf("non-standard facilities info missing or wrong format")); | ||
3793 | } | ||
3794 | else | ||
3795 | { | ||
3796 | if (plci->fax_connect_info_length <= len) | ||
3797 | plci->fax_connect_info_buffer[len] = 0; | ||
3798 | len += 1 + plci->fax_connect_info_buffer[len]; | ||
3799 | if (plci->fax_connect_info_length <= len) | ||
3800 | plci->fax_connect_info_buffer[len] = 0; | ||
3801 | len += 1 + plci->fax_connect_info_buffer[len]; | ||
3802 | if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) | ||
3803 | plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); | ||
3804 | plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); | ||
3805 | for (i = 0; i < fax_parms[7].length; i++) | ||
3806 | plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; | ||
3807 | } | ||
3808 | plci->fax_connect_info_length = len; | ||
3809 | plci->fax_edata_ack_length = plci->fax_connect_info_length; | ||
3810 | start_internal_command (Id, plci, fax_edata_ack_command); | ||
3811 | break; | ||
3812 | |||
3813 | } | ||
3814 | return FALSE; | ||
3815 | } | ||
3816 | |||
3817 | /*------------------------------------------------------------------*/ | ||
3818 | /* IDI callback function */ | ||
3819 | /*------------------------------------------------------------------*/ | ||
3820 | |||
3821 | void callback(ENTITY * e) | ||
3822 | { | ||
3823 | DIVA_CAPI_ADAPTER * a; | ||
3824 | APPL * appl; | ||
3825 | PLCI * plci; | ||
3826 | CAPI_MSG *m; | ||
3827 | word i, j; | ||
3828 | byte rc; | ||
3829 | byte ch; | ||
3830 | byte req; | ||
3831 | byte global_req; | ||
3832 | int no_cancel_rc; | ||
3833 | |||
3834 | dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)", | ||
3835 | (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind)); | ||
3836 | |||
3837 | a = &(adapter[(byte)e->user[0]]); | ||
3838 | plci = &(a->plci[e->user[1]]); | ||
3839 | no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a); | ||
3840 | |||
3841 | /* | ||
3842 | If new protocol code and new XDI is used then CAPI should work | ||
3843 | fully in accordance with IDI cpec an look on callback field instead | ||
3844 | of Rc field for return codes. | ||
3845 | */ | ||
3846 | if (((e->complete == 0xff) && no_cancel_rc) || | ||
3847 | (e->Rc && !no_cancel_rc)) { | ||
3848 | rc = e->Rc; | ||
3849 | ch = e->RcCh; | ||
3850 | req = e->Req; | ||
3851 | e->Rc = 0; | ||
3852 | |||
3853 | if (e->user[0] & 0x8000) | ||
3854 | { | ||
3855 | /* | ||
3856 | If REMOVE request was sent then we have to wait until | ||
3857 | return code with Id set to zero arrives. | ||
3858 | All other return codes should be ignored. | ||
3859 | */ | ||
3860 | if (req == REMOVE) | ||
3861 | { | ||
3862 | if (e->Id) | ||
3863 | { | ||
3864 | dbug(1,dprintf("cancel RC in REMOVE state")); | ||
3865 | return; | ||
3866 | } | ||
3867 | channel_flow_control_remove (plci); | ||
3868 | for (i = 0; i < 256; i++) | ||
3869 | { | ||
3870 | if (a->FlowControlIdTable[i] == plci->nl_remove_id) | ||
3871 | a->FlowControlIdTable[i] = 0; | ||
3872 | } | ||
3873 | plci->nl_remove_id = 0; | ||
3874 | if (plci->rx_dma_descriptor > 0) { | ||
3875 | diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1); | ||
3876 | plci->rx_dma_descriptor = 0; | ||
3877 | } | ||
3878 | } | ||
3879 | if (rc == OK_FC) | ||
3880 | { | ||
3881 | a->FlowControlIdTable[ch] = e->Id; | ||
3882 | a->FlowControlSkipTable[ch] = 0; | ||
3883 | |||
3884 | a->ch_flow_control[ch] |= N_OK_FC_PENDING; | ||
3885 | a->ch_flow_plci[ch] = plci->Id; | ||
3886 | plci->nl_req = 0; | ||
3887 | } | ||
3888 | else | ||
3889 | { | ||
3890 | /* | ||
3891 | Cancel return codes self, if feature was requested | ||
3892 | */ | ||
3893 | if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) { | ||
3894 | a->FlowControlIdTable[ch] = 0; | ||
3895 | if ((rc == OK) && a->FlowControlSkipTable[ch]) { | ||
3896 | dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch)); | ||
3897 | return; | ||
3898 | } | ||
3899 | } | ||
3900 | |||
3901 | if (a->ch_flow_control[ch] & N_OK_FC_PENDING) | ||
3902 | { | ||
3903 | a->ch_flow_control[ch] &= ~N_OK_FC_PENDING; | ||
3904 | if (ch == e->ReqCh) | ||
3905 | plci->nl_req = 0; | ||
3906 | } | ||
3907 | else | ||
3908 | plci->nl_req = 0; | ||
3909 | } | ||
3910 | if (plci->nl_req) | ||
3911 | control_rc (plci, 0, rc, ch, 0, TRUE); | ||
3912 | else | ||
3913 | { | ||
3914 | if (req == N_XON) | ||
3915 | { | ||
3916 | channel_x_on (plci, ch); | ||
3917 | if (plci->internal_command) | ||
3918 | control_rc (plci, req, rc, ch, 0, TRUE); | ||
3919 | } | ||
3920 | else | ||
3921 | { | ||
3922 | if (plci->nl_global_req) | ||
3923 | { | ||
3924 | global_req = plci->nl_global_req; | ||
3925 | plci->nl_global_req = 0; | ||
3926 | if (rc != ASSIGN_OK) { | ||
3927 | e->Id = 0; | ||
3928 | if (plci->rx_dma_descriptor > 0) { | ||
3929 | diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1); | ||
3930 | plci->rx_dma_descriptor = 0; | ||
3931 | } | ||
3932 | } | ||
3933 | channel_xmit_xon (plci); | ||
3934 | control_rc (plci, 0, rc, ch, global_req, TRUE); | ||
3935 | } | ||
3936 | else if (plci->data_sent) | ||
3937 | { | ||
3938 | channel_xmit_xon (plci); | ||
3939 | plci->data_sent = FALSE; | ||
3940 | plci->NL.XNum = 1; | ||
3941 | data_rc (plci, ch); | ||
3942 | if (plci->internal_command) | ||
3943 | control_rc (plci, req, rc, ch, 0, TRUE); | ||
3944 | } | ||
3945 | else | ||
3946 | { | ||
3947 | channel_xmit_xon (plci); | ||
3948 | control_rc (plci, req, rc, ch, 0, TRUE); | ||
3949 | } | ||
3950 | } | ||
3951 | } | ||
3952 | } | ||
3953 | else | ||
3954 | { | ||
3955 | /* | ||
3956 | If REMOVE request was sent then we have to wait until | ||
3957 | return code with Id set to zero arrives. | ||
3958 | All other return codes should be ignored. | ||
3959 | */ | ||
3960 | if (req == REMOVE) | ||
3961 | { | ||
3962 | if (e->Id) | ||
3963 | { | ||
3964 | dbug(1,dprintf("cancel RC in REMOVE state")); | ||
3965 | return; | ||
3966 | } | ||
3967 | plci->sig_remove_id = 0; | ||
3968 | } | ||
3969 | plci->sig_req = 0; | ||
3970 | if (plci->sig_global_req) | ||
3971 | { | ||
3972 | global_req = plci->sig_global_req; | ||
3973 | plci->sig_global_req = 0; | ||
3974 | if (rc != ASSIGN_OK) | ||
3975 | e->Id = 0; | ||
3976 | channel_xmit_xon (plci); | ||
3977 | control_rc (plci, 0, rc, ch, global_req, FALSE); | ||
3978 | } | ||
3979 | else | ||
3980 | { | ||
3981 | channel_xmit_xon (plci); | ||
3982 | control_rc (plci, req, rc, ch, 0, FALSE); | ||
3983 | } | ||
3984 | } | ||
3985 | /* | ||
3986 | Again: in accordance with IDI spec Rc and Ind can't be delivered in the | ||
3987 | same callback. Also if new XDI and protocol code used then jump | ||
3988 | direct to finish. | ||
3989 | */ | ||
3990 | if (no_cancel_rc) { | ||
3991 | channel_xmit_xon(plci); | ||
3992 | goto capi_callback_suffix; | ||
3993 | } | ||
3994 | } | ||
3995 | |||
3996 | channel_xmit_xon(plci); | ||
3997 | |||
3998 | if (e->Ind) { | ||
3999 | if (e->user[0] &0x8000) { | ||
4000 | byte Ind = e->Ind & 0x0f; | ||
4001 | byte Ch = e->IndCh; | ||
4002 | if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) && | ||
4003 | (a->ch_flow_plci[Ch] == plci->Id)) { | ||
4004 | if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) { | ||
4005 | dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch)); | ||
4006 | } | ||
4007 | a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK; | ||
4008 | } | ||
4009 | nl_ind(plci); | ||
4010 | if ((e->RNR != 1) && | ||
4011 | (a->ch_flow_plci[Ch] == plci->Id) && | ||
4012 | (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) { | ||
4013 | a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK; | ||
4014 | dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch)); | ||
4015 | } | ||
4016 | } else { | ||
4017 | sig_ind(plci); | ||
4018 | } | ||
4019 | e->Ind = 0; | ||
4020 | } | ||
4021 | |||
4022 | capi_callback_suffix: | ||
4023 | |||
4024 | while (!plci->req_in | ||
4025 | && !plci->internal_command | ||
4026 | && (plci->msg_in_write_pos != plci->msg_in_read_pos)) | ||
4027 | { | ||
4028 | j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos; | ||
4029 | |||
4030 | i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc; | ||
4031 | |||
4032 | m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]); | ||
4033 | appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i])); | ||
4034 | dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d", | ||
4035 | m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos)); | ||
4036 | if (plci->msg_in_read_pos == plci->msg_in_wrap_pos) | ||
4037 | { | ||
4038 | plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | ||
4039 | plci->msg_in_read_pos = i + MSG_IN_OVERHEAD; | ||
4040 | } | ||
4041 | else | ||
4042 | { | ||
4043 | plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD; | ||
4044 | } | ||
4045 | if (plci->msg_in_read_pos == plci->msg_in_write_pos) | ||
4046 | { | ||
4047 | plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE; | ||
4048 | plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | ||
4049 | } | ||
4050 | else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos) | ||
4051 | { | ||
4052 | plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | ||
4053 | plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | ||
4054 | } | ||
4055 | i = api_put (appl, m); | ||
4056 | if (i != 0) | ||
4057 | { | ||
4058 | if (m->header.command == _DATA_B3_R) | ||
4059 | |||
4060 | TransmitBufferFree (appl, (byte *)(m->info.data_b3_req.Data)); | ||
4061 | |||
4062 | dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command)); | ||
4063 | break; | ||
4064 | } | ||
4065 | |||
4066 | if (plci->li_notify_update) | ||
4067 | { | ||
4068 | plci->li_notify_update = FALSE; | ||
4069 | mixer_notify_update (plci, FALSE); | ||
4070 | } | ||
4071 | |||
4072 | } | ||
4073 | send_data(plci); | ||
4074 | send_req(plci); | ||
4075 | } | ||
4076 | |||
4077 | |||
4078 | void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc) | ||
4079 | { | ||
4080 | dword Id; | ||
4081 | dword rId; | ||
4082 | word Number; | ||
4083 | word Info=0; | ||
4084 | word i; | ||
4085 | word ncci; | ||
4086 | DIVA_CAPI_ADAPTER * a; | ||
4087 | APPL * appl; | ||
4088 | PLCI * rplci; | ||
4089 | byte SSparms[] = "\x05\x00\x00\x02\x00\x00"; | ||
4090 | byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00"; | ||
4091 | |||
4092 | if (!plci) { | ||
4093 | dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc)); | ||
4094 | return; | ||
4095 | } | ||
4096 | dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out)); | ||
4097 | if(plci->req_in!=plci->req_out) | ||
4098 | { | ||
4099 | if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK)) | ||
4100 | { | ||
4101 | dbug(1,dprintf("req_1return")); | ||
4102 | return; | ||
4103 | } | ||
4104 | /* cancel outstanding request on the PLCI after SIG ASSIGN failure */ | ||
4105 | } | ||
4106 | plci->req_in = plci->req_in_start = plci->req_out = 0; | ||
4107 | dbug(1,dprintf("control_rc")); | ||
4108 | |||
4109 | appl = plci->appl; | ||
4110 | a = plci->adapter; | ||
4111 | ncci = a->ch_ncci[ch]; | ||
4112 | if(appl) | ||
4113 | { | ||
4114 | Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id; | ||
4115 | if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER; | ||
4116 | Number = plci->number; | ||
4117 | dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command)); | ||
4118 | dbug(1,dprintf("channels=0x%x",plci->channels)); | ||
4119 | if (plci_remove_check(plci)) | ||
4120 | return; | ||
4121 | if(req==REMOVE && rc==ASSIGN_OK) | ||
4122 | { | ||
4123 | sig_req(plci,HANGUP,0); | ||
4124 | sig_req(plci,REMOVE,0); | ||
4125 | send_req(plci); | ||
4126 | } | ||
4127 | if(plci->command) | ||
4128 | { | ||
4129 | switch(plci->command) | ||
4130 | { | ||
4131 | case C_HOLD_REQ: | ||
4132 | dbug(1,dprintf("HoldRC=0x%x",rc)); | ||
4133 | SSparms[1] = (byte)S_HOLD; | ||
4134 | if(rc!=OK) | ||
4135 | { | ||
4136 | plci->SuppState = IDLE; | ||
4137 | Info = 0x2001; | ||
4138 | } | ||
4139 | sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms); | ||
4140 | break; | ||
4141 | |||
4142 | case C_RETRIEVE_REQ: | ||
4143 | dbug(1,dprintf("RetrieveRC=0x%x",rc)); | ||
4144 | SSparms[1] = (byte)S_RETRIEVE; | ||
4145 | if(rc!=OK) | ||
4146 | { | ||
4147 | plci->SuppState = CALL_HELD; | ||
4148 | Info = 0x2001; | ||
4149 | } | ||
4150 | sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms); | ||
4151 | break; | ||
4152 | |||
4153 | case _INFO_R: | ||
4154 | dbug(1,dprintf("InfoRC=0x%x",rc)); | ||
4155 | if(rc!=OK) Info=_WRONG_STATE; | ||
4156 | sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info); | ||
4157 | break; | ||
4158 | |||
4159 | case _CONNECT_R: | ||
4160 | dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc)); | ||
4161 | if (plci->State == INC_DIS_PENDING) | ||
4162 | break; | ||
4163 | if(plci->Sig.Id!=0xff) | ||
4164 | { | ||
4165 | if (((global_req == ASSIGN) && (rc != ASSIGN_OK)) | ||
4166 | || (!nl_rc && (req == CALL_REQ) && (rc != OK))) | ||
4167 | { | ||
4168 | dbug(1,dprintf("No more IDs/Call_Req failed")); | ||
4169 | sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI); | ||
4170 | plci_remove(plci); | ||
4171 | plci->State = IDLE; | ||
4172 | break; | ||
4173 | } | ||
4174 | if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING; | ||
4175 | sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0); | ||
4176 | } | ||
4177 | else /* D-ch activation */ | ||
4178 | { | ||
4179 | if (rc != ASSIGN_OK) | ||
4180 | { | ||
4181 | dbug(1,dprintf("No more IDs/X.25 Call_Req failed")); | ||
4182 | sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI); | ||
4183 | plci_remove(plci); | ||
4184 | plci->State = IDLE; | ||
4185 | break; | ||
4186 | } | ||
4187 | sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0); | ||
4188 | sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","",""); | ||
4189 | plci->State = INC_ACT_PENDING; | ||
4190 | } | ||
4191 | break; | ||
4192 | |||
4193 | case _CONNECT_I|RESPONSE: | ||
4194 | if (plci->State != INC_DIS_PENDING) | ||
4195 | plci->State = INC_CON_ACCEPT; | ||
4196 | break; | ||
4197 | |||
4198 | case _DISCONNECT_R: | ||
4199 | if (plci->State == INC_DIS_PENDING) | ||
4200 | break; | ||
4201 | if(plci->Sig.Id!=0xff) | ||
4202 | { | ||
4203 | plci->State = OUTG_DIS_PENDING; | ||
4204 | sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0); | ||
4205 | } | ||
4206 | break; | ||
4207 | |||
4208 | case SUSPEND_REQ: | ||
4209 | break; | ||
4210 | |||
4211 | case RESUME_REQ: | ||
4212 | break; | ||
4213 | |||
4214 | case _CONNECT_B3_R: | ||
4215 | if(rc!=OK) | ||
4216 | { | ||
4217 | sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER); | ||
4218 | break; | ||
4219 | } | ||
4220 | ncci = get_ncci (plci, ch, 0); | ||
4221 | Id = (Id & 0xffff) | (((dword) ncci) << 16); | ||
4222 | plci->channels++; | ||
4223 | if(req==N_RESET) | ||
4224 | { | ||
4225 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
4226 | sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0); | ||
4227 | sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
4228 | } | ||
4229 | else | ||
4230 | { | ||
4231 | a->ncci_state[ncci] = OUTG_CON_PENDING; | ||
4232 | sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0); | ||
4233 | } | ||
4234 | break; | ||
4235 | |||
4236 | case _CONNECT_B3_I|RESPONSE: | ||
4237 | break; | ||
4238 | |||
4239 | case _RESET_B3_R: | ||
4240 | /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/ | ||
4241 | break; | ||
4242 | |||
4243 | case _DISCONNECT_B3_R: | ||
4244 | sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0); | ||
4245 | break; | ||
4246 | |||
4247 | case _MANUFACTURER_R: | ||
4248 | break; | ||
4249 | |||
4250 | case PERM_LIST_REQ: | ||
4251 | if(rc!=OK) | ||
4252 | { | ||
4253 | Info = _WRONG_IDENTIFIER; | ||
4254 | sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info); | ||
4255 | plci_remove(plci); | ||
4256 | } | ||
4257 | else | ||
4258 | sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info); | ||
4259 | break; | ||
4260 | |||
4261 | default: | ||
4262 | break; | ||
4263 | } | ||
4264 | plci->command = 0; | ||
4265 | } | ||
4266 | else if (plci->internal_command) | ||
4267 | { | ||
4268 | switch(plci->internal_command) | ||
4269 | { | ||
4270 | case BLOCK_PLCI: | ||
4271 | return; | ||
4272 | |||
4273 | case GET_MWI_STATE: | ||
4274 | if(rc==OK) /* command supported, wait for indication */ | ||
4275 | { | ||
4276 | return; | ||
4277 | } | ||
4278 | plci_remove(plci); | ||
4279 | break; | ||
4280 | |||
4281 | /* Get Supported Services */ | ||
4282 | case GETSERV_REQ_PEND: | ||
4283 | if(rc==OK) /* command supported, wait for indication */ | ||
4284 | { | ||
4285 | break; | ||
4286 | } | ||
4287 | PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); | ||
4288 | sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct); | ||
4289 | plci_remove(plci); | ||
4290 | break; | ||
4291 | |||
4292 | case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */ | ||
4293 | case INTERR_NUMBERS_REQ_PEND: | ||
4294 | case CF_START_PEND: /* Call Forwarding Start pending */ | ||
4295 | case CF_STOP_PEND: /* Call Forwarding Stop pending */ | ||
4296 | case CCBS_REQUEST_REQ_PEND: | ||
4297 | case CCBS_DEACTIVATE_REQ_PEND: | ||
4298 | case CCBS_INTERROGATE_REQ_PEND: | ||
4299 | switch(plci->internal_command) | ||
4300 | { | ||
4301 | case INTERR_DIVERSION_REQ_PEND: | ||
4302 | SSparms[1] = S_INTERROGATE_DIVERSION; | ||
4303 | break; | ||
4304 | case INTERR_NUMBERS_REQ_PEND: | ||
4305 | SSparms[1] = S_INTERROGATE_NUMBERS; | ||
4306 | break; | ||
4307 | case CF_START_PEND: | ||
4308 | SSparms[1] = S_CALL_FORWARDING_START; | ||
4309 | break; | ||
4310 | case CF_STOP_PEND: | ||
4311 | SSparms[1] = S_CALL_FORWARDING_STOP; | ||
4312 | break; | ||
4313 | case CCBS_REQUEST_REQ_PEND: | ||
4314 | SSparms[1] = S_CCBS_REQUEST; | ||
4315 | break; | ||
4316 | case CCBS_DEACTIVATE_REQ_PEND: | ||
4317 | SSparms[1] = S_CCBS_DEACTIVATE; | ||
4318 | break; | ||
4319 | case CCBS_INTERROGATE_REQ_PEND: | ||
4320 | SSparms[1] = S_CCBS_INTERROGATE; | ||
4321 | break; | ||
4322 | } | ||
4323 | if(global_req==ASSIGN) | ||
4324 | { | ||
4325 | dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc)); | ||
4326 | return; | ||
4327 | } | ||
4328 | if(!plci->appl) break; | ||
4329 | if(rc==ISDN_GUARD_REJ) | ||
4330 | { | ||
4331 | Info = _CAPI_GUARD_ERROR; | ||
4332 | } | ||
4333 | else if(rc!=OK) | ||
4334 | { | ||
4335 | Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED; | ||
4336 | } | ||
4337 | sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7, | ||
4338 | plci->number,"wws",Info,(word)3,SSparms); | ||
4339 | if(Info) plci_remove(plci); | ||
4340 | break; | ||
4341 | |||
4342 | /* 3pty conference pending */ | ||
4343 | case PTY_REQ_PEND: | ||
4344 | if(!plci->relatedPTYPLCI) break; | ||
4345 | rplci = plci->relatedPTYPLCI; | ||
4346 | SSparms[1] = plci->ptyState; | ||
4347 | rId = ((word)rplci->Id<<8)|rplci->adapter->Id; | ||
4348 | if(rplci->tel) rId|=EXT_CONTROLLER; | ||
4349 | if(rc!=OK) | ||
4350 | { | ||
4351 | Info = 0x300E; /* not supported */ | ||
4352 | plci->relatedPTYPLCI = NULL; | ||
4353 | plci->ptyState = 0; | ||
4354 | } | ||
4355 | sendf(rplci->appl, | ||
4356 | _FACILITY_R|CONFIRM, | ||
4357 | rId, | ||
4358 | plci->number, | ||
4359 | "wws",Info,(word)3,SSparms); | ||
4360 | break; | ||
4361 | |||
4362 | /* Explicit Call Transfer pending */ | ||
4363 | case ECT_REQ_PEND: | ||
4364 | dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc)); | ||
4365 | if(!plci->relatedPTYPLCI) break; | ||
4366 | rplci = plci->relatedPTYPLCI; | ||
4367 | SSparms[1] = S_ECT; | ||
4368 | rId = ((word)rplci->Id<<8)|rplci->adapter->Id; | ||
4369 | if(rplci->tel) rId|=EXT_CONTROLLER; | ||
4370 | if(rc!=OK) | ||
4371 | { | ||
4372 | Info = 0x300E; /* not supported */ | ||
4373 | plci->relatedPTYPLCI = NULL; | ||
4374 | plci->ptyState = 0; | ||
4375 | } | ||
4376 | sendf(rplci->appl, | ||
4377 | _FACILITY_R|CONFIRM, | ||
4378 | rId, | ||
4379 | plci->number, | ||
4380 | "wws",Info,(word)3,SSparms); | ||
4381 | break; | ||
4382 | |||
4383 | case _MANUFACTURER_R: | ||
4384 | dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc)); | ||
4385 | if ((global_req == ASSIGN) && (rc != ASSIGN_OK)) | ||
4386 | { | ||
4387 | dbug(1,dprintf("No more IDs")); | ||
4388 | sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI); | ||
4389 | plci_remove(plci); /* after codec init, internal codec commands pending */ | ||
4390 | } | ||
4391 | break; | ||
4392 | |||
4393 | case _CONNECT_R: | ||
4394 | dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc)); | ||
4395 | if ((global_req == ASSIGN) && (rc != ASSIGN_OK)) | ||
4396 | { | ||
4397 | dbug(1,dprintf("No more IDs")); | ||
4398 | sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI); | ||
4399 | plci_remove(plci); /* after codec init, internal codec commands pending */ | ||
4400 | } | ||
4401 | break; | ||
4402 | |||
4403 | case PERM_COD_HOOK: /* finished with Hook_Ind */ | ||
4404 | return; | ||
4405 | |||
4406 | case PERM_COD_CALL: | ||
4407 | dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc)); | ||
4408 | plci->internal_command = PERM_COD_CONN_PEND; | ||
4409 | return; | ||
4410 | |||
4411 | case PERM_COD_ASSIGN: | ||
4412 | dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc)); | ||
4413 | if(rc!=ASSIGN_OK) break; | ||
4414 | sig_req(plci,CALL_REQ,0); | ||
4415 | send_req(plci); | ||
4416 | plci->internal_command = PERM_COD_CALL; | ||
4417 | return; | ||
4418 | |||
4419 | /* Null Call Reference Request pending */ | ||
4420 | case C_NCR_FAC_REQ: | ||
4421 | dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc)); | ||
4422 | if(global_req==ASSIGN) | ||
4423 | { | ||
4424 | if(rc==ASSIGN_OK) | ||
4425 | { | ||
4426 | return; | ||
4427 | } | ||
4428 | else | ||
4429 | { | ||
4430 | sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE); | ||
4431 | appl->NullCREnable = FALSE; | ||
4432 | plci_remove(plci); | ||
4433 | } | ||
4434 | } | ||
4435 | else if(req==NCR_FACILITY) | ||
4436 | { | ||
4437 | if(rc==OK) | ||
4438 | { | ||
4439 | sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0); | ||
4440 | } | ||
4441 | else | ||
4442 | { | ||
4443 | sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE); | ||
4444 | appl->NullCREnable = FALSE; | ||
4445 | } | ||
4446 | plci_remove(plci); | ||
4447 | } | ||
4448 | break; | ||
4449 | |||
4450 | case HOOK_ON_REQ: | ||
4451 | if(plci->channels) | ||
4452 | { | ||
4453 | if(a->ncci_state[ncci]==CONNECTED) | ||
4454 | { | ||
4455 | a->ncci_state[ncci] = OUTG_DIS_PENDING; | ||
4456 | cleanup_ncci_data (plci, ncci); | ||
4457 | nl_req_ncci(plci,N_DISC,(byte)ncci); | ||
4458 | } | ||
4459 | break; | ||
4460 | } | ||
4461 | break; | ||
4462 | |||
4463 | case HOOK_OFF_REQ: | ||
4464 | if (plci->State == INC_DIS_PENDING) | ||
4465 | break; | ||
4466 | sig_req(plci,CALL_REQ,0); | ||
4467 | send_req(plci); | ||
4468 | plci->State=OUTG_CON_PENDING; | ||
4469 | break; | ||
4470 | |||
4471 | |||
4472 | case MWI_ACTIVATE_REQ_PEND: | ||
4473 | case MWI_DEACTIVATE_REQ_PEND: | ||
4474 | if(global_req == ASSIGN && rc==ASSIGN_OK) | ||
4475 | { | ||
4476 | dbug(1,dprintf("MWI_REQ assigned")); | ||
4477 | return; | ||
4478 | } | ||
4479 | else if(rc!=OK) | ||
4480 | { | ||
4481 | if(rc==WRONG_IE) | ||
4482 | { | ||
4483 | Info = 0x2007; /* Illegal message parameter coding */ | ||
4484 | dbug(1,dprintf("MWI_REQ invalid parameter")); | ||
4485 | } | ||
4486 | else | ||
4487 | { | ||
4488 | Info = 0x300B; /* not supported */ | ||
4489 | dbug(1,dprintf("MWI_REQ not supported")); | ||
4490 | } | ||
4491 | /* 0x3010: Request not allowed in this state */ | ||
4492 | PUT_WORD(&SSparms[4],0x300E); /* SS not supported */ | ||
4493 | |||
4494 | } | ||
4495 | if(plci->internal_command==MWI_ACTIVATE_REQ_PEND) | ||
4496 | { | ||
4497 | PUT_WORD(&SSparms[1],S_MWI_ACTIVATE); | ||
4498 | } | ||
4499 | else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE); | ||
4500 | |||
4501 | if(plci->cr_enquiry) | ||
4502 | { | ||
4503 | sendf(plci->appl, | ||
4504 | _FACILITY_R|CONFIRM, | ||
4505 | Id&0xf, | ||
4506 | plci->number, | ||
4507 | "wws",Info,(word)3,SSparms); | ||
4508 | if(rc!=OK) plci_remove(plci); | ||
4509 | } | ||
4510 | else | ||
4511 | { | ||
4512 | sendf(plci->appl, | ||
4513 | _FACILITY_R|CONFIRM, | ||
4514 | Id, | ||
4515 | plci->number, | ||
4516 | "wws",Info,(word)3,SSparms); | ||
4517 | } | ||
4518 | break; | ||
4519 | |||
4520 | case CONF_BEGIN_REQ_PEND: | ||
4521 | case CONF_ADD_REQ_PEND: | ||
4522 | case CONF_SPLIT_REQ_PEND: | ||
4523 | case CONF_DROP_REQ_PEND: | ||
4524 | case CONF_ISOLATE_REQ_PEND: | ||
4525 | case CONF_REATTACH_REQ_PEND: | ||
4526 | dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc)); | ||
4527 | if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break; | ||
4528 | rplci = plci; | ||
4529 | rId = Id; | ||
4530 | switch(plci->internal_command) | ||
4531 | { | ||
4532 | case CONF_BEGIN_REQ_PEND: | ||
4533 | SSparms[1] = S_CONF_BEGIN; | ||
4534 | break; | ||
4535 | case CONF_ADD_REQ_PEND: | ||
4536 | SSparms[1] = S_CONF_ADD; | ||
4537 | rplci = plci->relatedPTYPLCI; | ||
4538 | rId = ((word)rplci->Id<<8)|rplci->adapter->Id; | ||
4539 | break; | ||
4540 | case CONF_SPLIT_REQ_PEND: | ||
4541 | SSparms[1] = S_CONF_SPLIT; | ||
4542 | break; | ||
4543 | case CONF_DROP_REQ_PEND: | ||
4544 | SSparms[1] = S_CONF_DROP; | ||
4545 | break; | ||
4546 | case CONF_ISOLATE_REQ_PEND: | ||
4547 | SSparms[1] = S_CONF_ISOLATE; | ||
4548 | break; | ||
4549 | case CONF_REATTACH_REQ_PEND: | ||
4550 | SSparms[1] = S_CONF_REATTACH; | ||
4551 | break; | ||
4552 | } | ||
4553 | |||
4554 | if(rc!=OK) | ||
4555 | { | ||
4556 | Info = 0x300E; /* not supported */ | ||
4557 | plci->relatedPTYPLCI = NULL; | ||
4558 | plci->ptyState = 0; | ||
4559 | } | ||
4560 | sendf(rplci->appl, | ||
4561 | _FACILITY_R|CONFIRM, | ||
4562 | rId, | ||
4563 | plci->number, | ||
4564 | "wws",Info,(word)3,SSparms); | ||
4565 | break; | ||
4566 | |||
4567 | case VSWITCH_REQ_PEND: | ||
4568 | if(rc!=OK) | ||
4569 | { | ||
4570 | if(plci->relatedPTYPLCI) | ||
4571 | { | ||
4572 | plci->relatedPTYPLCI->vswitchstate=0; | ||
4573 | plci->relatedPTYPLCI->vsprot=0; | ||
4574 | plci->relatedPTYPLCI->vsprotdialect=0; | ||
4575 | } | ||
4576 | plci->vswitchstate=0; | ||
4577 | plci->vsprot=0; | ||
4578 | plci->vsprotdialect=0; | ||
4579 | } | ||
4580 | else | ||
4581 | { | ||
4582 | if(plci->relatedPTYPLCI && | ||
4583 | plci->vswitchstate==1 && | ||
4584 | plci->relatedPTYPLCI->vswitchstate==3) /* join complete */ | ||
4585 | plci->vswitchstate=3; | ||
4586 | } | ||
4587 | break; | ||
4588 | |||
4589 | /* Call Deflection Request pending (SSCT) */ | ||
4590 | case CD_REQ_PEND: | ||
4591 | SSparms[1] = S_CALL_DEFLECTION; | ||
4592 | if(rc!=OK) | ||
4593 | { | ||
4594 | Info = 0x300E; /* not supported */ | ||
4595 | plci->appl->CDEnable = 0; | ||
4596 | } | ||
4597 | sendf(plci->appl,_FACILITY_R|CONFIRM,Id, | ||
4598 | plci->number,"wws",Info,(word)3,SSparms); | ||
4599 | break; | ||
4600 | |||
4601 | case RTP_CONNECT_B3_REQ_COMMAND_2: | ||
4602 | if (rc == OK) | ||
4603 | { | ||
4604 | ncci = get_ncci (plci, ch, 0); | ||
4605 | Id = (Id & 0xffff) | (((dword) ncci) << 16); | ||
4606 | plci->channels++; | ||
4607 | a->ncci_state[ncci] = OUTG_CON_PENDING; | ||
4608 | } | ||
4609 | |||
4610 | default: | ||
4611 | if (plci->internal_command_queue[0]) | ||
4612 | { | ||
4613 | (*(plci->internal_command_queue[0]))(Id, plci, rc); | ||
4614 | if (plci->internal_command) | ||
4615 | return; | ||
4616 | } | ||
4617 | break; | ||
4618 | } | ||
4619 | next_internal_command (Id, plci); | ||
4620 | } | ||
4621 | } | ||
4622 | else /* appl==0 */ | ||
4623 | { | ||
4624 | Id = ((word)plci->Id<<8)|plci->adapter->Id; | ||
4625 | if(plci->tel) Id|=EXT_CONTROLLER; | ||
4626 | |||
4627 | switch(plci->internal_command) | ||
4628 | { | ||
4629 | case BLOCK_PLCI: | ||
4630 | return; | ||
4631 | |||
4632 | case START_L1_SIG_ASSIGN_PEND: | ||
4633 | case REM_L1_SIG_ASSIGN_PEND: | ||
4634 | if(global_req == ASSIGN) | ||
4635 | { | ||
4636 | break; | ||
4637 | } | ||
4638 | else | ||
4639 | { | ||
4640 | dbug(1,dprintf("***L1 Req rem PLCI")); | ||
4641 | plci->internal_command = 0; | ||
4642 | sig_req(plci,REMOVE,0); | ||
4643 | send_req(plci); | ||
4644 | } | ||
4645 | break; | ||
4646 | |||
4647 | /* Call Deflection Request pending, just no appl ptr assigned */ | ||
4648 | case CD_REQ_PEND: | ||
4649 | SSparms[1] = S_CALL_DEFLECTION; | ||
4650 | if(rc!=OK) | ||
4651 | { | ||
4652 | Info = 0x300E; /* not supported */ | ||
4653 | } | ||
4654 | for(i=0; i<max_appl; i++) | ||
4655 | { | ||
4656 | if(application[i].CDEnable) | ||
4657 | { | ||
4658 | if(!application[i].Id) application[i].CDEnable = 0; | ||
4659 | else | ||
4660 | { | ||
4661 | sendf(&application[i],_FACILITY_R|CONFIRM,Id, | ||
4662 | plci->number,"wws",Info,(word)3,SSparms); | ||
4663 | if(Info) application[i].CDEnable = 0; | ||
4664 | } | ||
4665 | } | ||
4666 | } | ||
4667 | plci->internal_command = 0; | ||
4668 | break; | ||
4669 | |||
4670 | case PERM_COD_HOOK: /* finished with Hook_Ind */ | ||
4671 | return; | ||
4672 | |||
4673 | case PERM_COD_CALL: | ||
4674 | plci->internal_command = PERM_COD_CONN_PEND; | ||
4675 | dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc)); | ||
4676 | return; | ||
4677 | |||
4678 | case PERM_COD_ASSIGN: | ||
4679 | dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc)); | ||
4680 | plci->internal_command = 0; | ||
4681 | if(rc!=ASSIGN_OK) break; | ||
4682 | plci->internal_command = PERM_COD_CALL; | ||
4683 | sig_req(plci,CALL_REQ,0); | ||
4684 | send_req(plci); | ||
4685 | return; | ||
4686 | |||
4687 | case LISTEN_SIG_ASSIGN_PEND: | ||
4688 | if(rc == ASSIGN_OK) | ||
4689 | { | ||
4690 | plci->internal_command = 0; | ||
4691 | dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id)); | ||
4692 | add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */ | ||
4693 | sig_req(plci,INDICATE_REQ,0); | ||
4694 | send_req(plci); | ||
4695 | } | ||
4696 | else | ||
4697 | { | ||
4698 | dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc)); | ||
4699 | a->listen_active--; | ||
4700 | plci_remove(plci); | ||
4701 | plci->State = IDLE; | ||
4702 | } | ||
4703 | break; | ||
4704 | |||
4705 | case USELAW_REQ: | ||
4706 | if(global_req == ASSIGN) | ||
4707 | { | ||
4708 | if (rc==ASSIGN_OK) | ||
4709 | { | ||
4710 | sig_req(plci,LAW_REQ,0); | ||
4711 | send_req(plci); | ||
4712 | dbug(1,dprintf("Auto-Law assigned")); | ||
4713 | } | ||
4714 | else | ||
4715 | { | ||
4716 | dbug(1,dprintf("Auto-Law assign failed")); | ||
4717 | a->automatic_law = 3; | ||
4718 | plci->internal_command = 0; | ||
4719 | a->automatic_lawPLCI = NULL; | ||
4720 | } | ||
4721 | break; | ||
4722 | } | ||
4723 | else if(req == LAW_REQ && rc==OK) | ||
4724 | { | ||
4725 | dbug(1,dprintf("Auto-Law initiated")); | ||
4726 | a->automatic_law = 2; | ||
4727 | plci->internal_command = 0; | ||
4728 | } | ||
4729 | else | ||
4730 | { | ||
4731 | dbug(1,dprintf("Auto-Law not supported")); | ||
4732 | a->automatic_law = 3; | ||
4733 | plci->internal_command = 0; | ||
4734 | sig_req(plci,REMOVE,0); | ||
4735 | send_req(plci); | ||
4736 | a->automatic_lawPLCI = NULL; | ||
4737 | } | ||
4738 | break; | ||
4739 | } | ||
4740 | plci_remove_check(plci); | ||
4741 | } | ||
4742 | } | ||
4743 | |||
4744 | void data_rc(PLCI * plci, byte ch) | ||
4745 | { | ||
4746 | dword Id; | ||
4747 | DIVA_CAPI_ADAPTER * a; | ||
4748 | NCCI *ncci_ptr; | ||
4749 | DATA_B3_DESC *data; | ||
4750 | word ncci; | ||
4751 | |||
4752 | if (plci->appl) | ||
4753 | { | ||
4754 | TransmitBufferFree (plci->appl, plci->data_sent_ptr); | ||
4755 | a = plci->adapter; | ||
4756 | ncci = a->ch_ncci[ch]; | ||
4757 | if (ncci && (a->ncci_plci[ncci] == plci->Id)) | ||
4758 | { | ||
4759 | ncci_ptr = &(a->ncci[ncci]); | ||
4760 | dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending)); | ||
4761 | if (ncci_ptr->data_pending) | ||
4762 | { | ||
4763 | data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]); | ||
4764 | if (!(data->Flags &4) && a->ncci_state[ncci]) | ||
4765 | { | ||
4766 | Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id; | ||
4767 | if(plci->tel) Id|=EXT_CONTROLLER; | ||
4768 | sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number, | ||
4769 | "ww",data->Handle,0); | ||
4770 | } | ||
4771 | (ncci_ptr->data_out)++; | ||
4772 | if (ncci_ptr->data_out == MAX_DATA_B3) | ||
4773 | ncci_ptr->data_out = 0; | ||
4774 | (ncci_ptr->data_pending)--; | ||
4775 | } | ||
4776 | } | ||
4777 | } | ||
4778 | } | ||
4779 | |||
4780 | void data_ack(PLCI * plci, byte ch) | ||
4781 | { | ||
4782 | dword Id; | ||
4783 | DIVA_CAPI_ADAPTER * a; | ||
4784 | NCCI *ncci_ptr; | ||
4785 | word ncci; | ||
4786 | |||
4787 | a = plci->adapter; | ||
4788 | ncci = a->ch_ncci[ch]; | ||
4789 | ncci_ptr = &(a->ncci[ncci]); | ||
4790 | if (ncci_ptr->data_ack_pending) | ||
4791 | { | ||
4792 | if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id)) | ||
4793 | { | ||
4794 | Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id; | ||
4795 | if(plci->tel) Id|=EXT_CONTROLLER; | ||
4796 | sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number, | ||
4797 | "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0); | ||
4798 | } | ||
4799 | (ncci_ptr->data_ack_out)++; | ||
4800 | if (ncci_ptr->data_ack_out == MAX_DATA_ACK) | ||
4801 | ncci_ptr->data_ack_out = 0; | ||
4802 | (ncci_ptr->data_ack_pending)--; | ||
4803 | } | ||
4804 | } | ||
4805 | |||
4806 | void sig_ind(PLCI * plci) | ||
4807 | { | ||
4808 | dword x_Id; | ||
4809 | dword Id; | ||
4810 | dword rId; | ||
4811 | word Number = 0; | ||
4812 | word i; | ||
4813 | word cip; | ||
4814 | dword cip_mask; | ||
4815 | byte *ie; | ||
4816 | DIVA_CAPI_ADAPTER * a; | ||
4817 | API_PARSE saved_parms[MAX_MSG_PARMS+1]; | ||
4818 | #define MAXPARMSIDS 31 | ||
4819 | byte * parms[MAXPARMSIDS]; | ||
4820 | byte * add_i[4]; | ||
4821 | byte * multi_fac_parms[MAX_MULTI_IE]; | ||
4822 | byte * multi_pi_parms [MAX_MULTI_IE]; | ||
4823 | byte * multi_ssext_parms [MAX_MULTI_IE]; | ||
4824 | byte * multi_CiPN_parms [MAX_MULTI_IE]; | ||
4825 | |||
4826 | byte * multi_vswitch_parms [MAX_MULTI_IE]; | ||
4827 | |||
4828 | byte ai_len; | ||
4829 | byte *esc_chi = ""; | ||
4830 | byte *esc_law = ""; | ||
4831 | byte *pty_cai = ""; | ||
4832 | byte *esc_cr = ""; | ||
4833 | byte *esc_profile = ""; | ||
4834 | |||
4835 | byte facility[256]; | ||
4836 | PLCI * tplci = NULL; | ||
4837 | byte chi[] = "\x02\x18\x01"; | ||
4838 | byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08"; | ||
4839 | byte resume_cau[] = "\x05\x05\x00\x02\x00\x00"; | ||
4840 | /* ESC_MSGTYPE must be the last but one message, a new IE has to be */ | ||
4841 | /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */ | ||
4842 | /* SMSG is situated at the end because its 0 (for compatibility reasons */ | ||
4843 | /* (see Info_Mask Bit 4, first IE. then the message type) */ | ||
4844 | word parms_id[] = | ||
4845 | {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA, | ||
4846 | UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW, | ||
4847 | RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR, | ||
4848 | CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG}; | ||
4849 | /* 14 FTY repl by ESC_CHI */ | ||
4850 | /* 18 PI repl by ESC_LAW */ | ||
4851 | /* removed OAD changed to 0xff for future use, OAD is multiIE now */ | ||
4852 | word multi_fac_id[] = {1, FTY}; | ||
4853 | word multi_pi_id[] = {1, PI}; | ||
4854 | word multi_CiPN_id[] = {1, OAD}; | ||
4855 | word multi_ssext_id[] = {1, ESC_SSEXT}; | ||
4856 | |||
4857 | word multi_vswitch_id[] = {1, ESC_VSWITCH}; | ||
4858 | |||
4859 | byte * cau; | ||
4860 | word ncci; | ||
4861 | byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/ | ||
4862 | byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00"; | ||
4863 | byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; | ||
4864 | byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00"; | ||
4865 | byte force_mt_info = FALSE; | ||
4866 | byte dir; | ||
4867 | dword d; | ||
4868 | word w; | ||
4869 | |||
4870 | a = plci->adapter; | ||
4871 | Id = ((word)plci->Id<<8)|a->Id; | ||
4872 | PUT_WORD(&SS_Ind[4],0x0000); | ||
4873 | |||
4874 | if (plci->sig_remove_id) | ||
4875 | { | ||
4876 | plci->Sig.RNR = 2; /* discard */ | ||
4877 | dbug(1,dprintf("SIG discard while remove pending")); | ||
4878 | return; | ||
4879 | } | ||
4880 | if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER; | ||
4881 | dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d", | ||
4882 | Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer)); | ||
4883 | if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels) | ||
4884 | { | ||
4885 | plci->Sig.RNR = 1; | ||
4886 | return; | ||
4887 | } | ||
4888 | if(plci->Sig.Ind==HANGUP && plci->channels) | ||
4889 | { | ||
4890 | plci->Sig.RNR = 1; | ||
4891 | plci->hangup_flow_ctrl_timer++; | ||
4892 | /* recover the network layer after timeout */ | ||
4893 | if(plci->hangup_flow_ctrl_timer==100) | ||
4894 | { | ||
4895 | dbug(1,dprintf("Exceptional disc")); | ||
4896 | plci->Sig.RNR = 0; | ||
4897 | plci->hangup_flow_ctrl_timer = 0; | ||
4898 | for (ncci = 1; ncci < MAX_NCCI+1; ncci++) | ||
4899 | { | ||
4900 | if (a->ncci_plci[ncci] == plci->Id) | ||
4901 | { | ||
4902 | cleanup_ncci_data (plci, ncci); | ||
4903 | if(plci->channels)plci->channels--; | ||
4904 | if (plci->appl) | ||
4905 | sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,""); | ||
4906 | } | ||
4907 | } | ||
4908 | if (plci->appl) | ||
4909 | sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0); | ||
4910 | plci_remove(plci); | ||
4911 | plci->State=IDLE; | ||
4912 | } | ||
4913 | return; | ||
4914 | } | ||
4915 | |||
4916 | /* do first parse the info with no OAD in, because OAD will be converted */ | ||
4917 | /* first the multiple facility IE, then mult. progress ind. */ | ||
4918 | /* then the parameters for the info_ind + conn_ind */ | ||
4919 | IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE); | ||
4920 | IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE); | ||
4921 | IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE); | ||
4922 | |||
4923 | IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE); | ||
4924 | |||
4925 | IndParse(plci,parms_id,parms,0); | ||
4926 | IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE); | ||
4927 | esc_chi = parms[14]; | ||
4928 | esc_law = parms[18]; | ||
4929 | pty_cai = parms[24]; | ||
4930 | esc_cr = parms[25]; | ||
4931 | esc_profile = parms[27]; | ||
4932 | if(esc_cr[0] && plci) | ||
4933 | { | ||
4934 | if(plci->cr_enquiry && plci->appl) | ||
4935 | { | ||
4936 | plci->cr_enquiry = FALSE; | ||
4937 | /* d = MANU_ID */ | ||
4938 | /* w = m_command */ | ||
4939 | /* b = total length */ | ||
4940 | /* b = indication type */ | ||
4941 | /* b = length of all IEs */ | ||
4942 | /* b = IE1 */ | ||
4943 | /* S = IE1 length + cont. */ | ||
4944 | /* b = IE2 */ | ||
4945 | /* S = IE2 lenght + cont. */ | ||
4946 | sendf(plci->appl, | ||
4947 | _MANUFACTURER_I, | ||
4948 | Id, | ||
4949 | 0, | ||
4950 | "dwbbbbSbS",_DI_MANU_ID,plci->m_command, | ||
4951 | 2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law); | ||
4952 | } | ||
4953 | } | ||
4954 | /* create the additional info structure */ | ||
4955 | add_i[1] = parms[15]; /* KEY of additional info */ | ||
4956 | add_i[2] = parms[11]; /* UUI of additional info */ | ||
4957 | ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility); | ||
4958 | |||
4959 | /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */ | ||
4960 | /* indication returns by the card if requested by the function */ | ||
4961 | /* AutomaticLaw() after driver init */ | ||
4962 | if (a->automatic_law<4) | ||
4963 | { | ||
4964 | if(esc_law[0]){ | ||
4965 | if(esc_law[2]){ | ||
4966 | dbug(0,dprintf("u-Law selected")); | ||
4967 | a->u_law = 1; | ||
4968 | } | ||
4969 | else { | ||
4970 | dbug(0,dprintf("a-Law selected")); | ||
4971 | a->u_law = 0; | ||
4972 | } | ||
4973 | a->automatic_law = 4; | ||
4974 | if(plci==a->automatic_lawPLCI) { | ||
4975 | plci->internal_command = 0; | ||
4976 | sig_req(plci,REMOVE,0); | ||
4977 | send_req(plci); | ||
4978 | a->automatic_lawPLCI = NULL; | ||
4979 | } | ||
4980 | } | ||
4981 | if (esc_profile[0]) | ||
4982 | { | ||
4983 | dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx", | ||
4984 | UnMapController (a->Id), GET_DWORD (&esc_profile[6]), | ||
4985 | GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]), | ||
4986 | GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46]))); | ||
4987 | |||
4988 | a->profile.Global_Options &= 0x000000ffL; | ||
4989 | a->profile.B1_Protocols &= 0x000003ffL; | ||
4990 | a->profile.B2_Protocols &= 0x00001fdfL; | ||
4991 | a->profile.B3_Protocols &= 0x000000b7L; | ||
4992 | |||
4993 | a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) | | ||
4994 | GL_BCHANNEL_OPERATION_SUPPORTED; | ||
4995 | a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]); | ||
4996 | a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]); | ||
4997 | a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]); | ||
4998 | a->manufacturer_features = GET_DWORD (&esc_profile[46]); | ||
4999 | a->man_profile.private_options = 0; | ||
5000 | |||
5001 | if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER) | ||
5002 | { | ||
5003 | a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER; | ||
5004 | a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED; | ||
5005 | } | ||
5006 | |||
5007 | |||
5008 | if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP) | ||
5009 | a->man_profile.private_options |= 1L << PRIVATE_RTP; | ||
5010 | a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]); | ||
5011 | a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]); | ||
5012 | |||
5013 | |||
5014 | if (a->manufacturer_features & MANUFACTURER_FEATURE_T38) | ||
5015 | a->man_profile.private_options |= 1L << PRIVATE_T38; | ||
5016 | |||
5017 | |||
5018 | if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD) | ||
5019 | a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD; | ||
5020 | |||
5021 | |||
5022 | if (a->manufacturer_features & MANUFACTURER_FEATURE_V18) | ||
5023 | a->man_profile.private_options |= 1L << PRIVATE_V18; | ||
5024 | |||
5025 | |||
5026 | if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE) | ||
5027 | a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE; | ||
5028 | |||
5029 | |||
5030 | if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS) | ||
5031 | a->man_profile.private_options |= 1L << PRIVATE_PIAFS; | ||
5032 | |||
5033 | |||
5034 | if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | ||
5035 | a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS; | ||
5036 | |||
5037 | |||
5038 | if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN) | ||
5039 | a->man_profile.private_options |= 1L << PRIVATE_VOWN; | ||
5040 | |||
5041 | |||
5042 | if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD) | ||
5043 | a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD; | ||
5044 | |||
5045 | } | ||
5046 | else | ||
5047 | { | ||
5048 | a->profile.Global_Options &= 0x0000007fL; | ||
5049 | a->profile.B1_Protocols &= 0x000003dfL; | ||
5050 | a->profile.B2_Protocols &= 0x00001adfL; | ||
5051 | a->profile.B3_Protocols &= 0x000000b7L; | ||
5052 | a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF; | ||
5053 | } | ||
5054 | if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF | | ||
5055 | MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)) | ||
5056 | { | ||
5057 | a->profile.Global_Options |= GL_DTMF_SUPPORTED; | ||
5058 | } | ||
5059 | a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL; | ||
5060 | dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx", | ||
5061 | UnMapController (a->Id), a->profile.Global_Options, | ||
5062 | a->profile.B1_Protocols, a->profile.B2_Protocols, | ||
5063 | a->profile.B3_Protocols, a->manufacturer_features)); | ||
5064 | } | ||
5065 | /* codec plci for the handset/hook state support is just an internal id */ | ||
5066 | if(plci!=a->AdvCodecPLCI) | ||
5067 | { | ||
5068 | force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0); | ||
5069 | force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0); | ||
5070 | SendSSExtInd(NULL,plci,Id,multi_ssext_parms); | ||
5071 | SendInfo(plci,Id, parms, force_mt_info); | ||
5072 | |||
5073 | VSwitchReqInd(plci,Id,multi_vswitch_parms); | ||
5074 | |||
5075 | } | ||
5076 | |||
5077 | /* switch the codec to the b-channel */ | ||
5078 | if(esc_chi[0] && plci && !plci->SuppState){ | ||
5079 | plci->b_channel = esc_chi[esc_chi[0]]&0x1f; | ||
5080 | mixer_set_bchannel_id_esc (plci, plci->b_channel); | ||
5081 | dbug(1,dprintf("storeChannel=0x%x",plci->b_channel)); | ||
5082 | if(plci->tel==ADV_VOICE && plci->appl) { | ||
5083 | SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a); | ||
5084 | } | ||
5085 | } | ||
5086 | |||
5087 | if(plci->appl) Number = plci->appl->Number++; | ||
5088 | |||
5089 | switch(plci->Sig.Ind) { | ||
5090 | /* Response to Get_Supported_Services request */ | ||
5091 | case S_SUPPORTED: | ||
5092 | dbug(1,dprintf("S_Supported")); | ||
5093 | if(!plci->appl) break; | ||
5094 | if(pty_cai[0]==4) | ||
5095 | { | ||
5096 | PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) ); | ||
5097 | } | ||
5098 | else | ||
5099 | { | ||
5100 | PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE); | ||
5101 | } | ||
5102 | PUT_WORD (&CF_Ind[1], 0); | ||
5103 | PUT_WORD (&CF_Ind[4], 0); | ||
5104 | sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind); | ||
5105 | plci_remove(plci); | ||
5106 | break; | ||
5107 | |||
5108 | /* Supplementary Service rejected */ | ||
5109 | case S_SERVICE_REJ: | ||
5110 | dbug(1,dprintf("S_Reject=0x%x",pty_cai[5])); | ||
5111 | if(!pty_cai[0]) break; | ||
5112 | switch (pty_cai[5]) | ||
5113 | { | ||
5114 | case ECT_EXECUTE: | ||
5115 | case THREE_PTY_END: | ||
5116 | case THREE_PTY_BEGIN: | ||
5117 | if(!plci->relatedPTYPLCI) break; | ||
5118 | tplci = plci->relatedPTYPLCI; | ||
5119 | rId = ( (word)tplci->Id<<8)|tplci->adapter->Id; | ||
5120 | if(tplci->tel) rId|=EXT_CONTROLLER; | ||
5121 | if(pty_cai[5]==ECT_EXECUTE) | ||
5122 | { | ||
5123 | PUT_WORD(&SS_Ind[1],S_ECT); | ||
5124 | |||
5125 | plci->vswitchstate=0; | ||
5126 | plci->relatedPTYPLCI->vswitchstate=0; | ||
5127 | |||
5128 | } | ||
5129 | else | ||
5130 | { | ||
5131 | PUT_WORD(&SS_Ind[1],pty_cai[5]+3); | ||
5132 | } | ||
5133 | if(pty_cai[2]!=0xff) | ||
5134 | { | ||
5135 | PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); | ||
5136 | } | ||
5137 | else | ||
5138 | { | ||
5139 | PUT_WORD(&SS_Ind[4],0x300E); | ||
5140 | } | ||
5141 | plci->relatedPTYPLCI = NULL; | ||
5142 | plci->ptyState = 0; | ||
5143 | sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); | ||
5144 | break; | ||
5145 | |||
5146 | case CALL_DEFLECTION: | ||
5147 | if(pty_cai[2]!=0xff) | ||
5148 | { | ||
5149 | PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); | ||
5150 | } | ||
5151 | else | ||
5152 | { | ||
5153 | PUT_WORD(&SS_Ind[4],0x300E); | ||
5154 | } | ||
5155 | PUT_WORD(&SS_Ind[1],pty_cai[5]); | ||
5156 | for(i=0; i<max_appl; i++) | ||
5157 | { | ||
5158 | if(application[i].CDEnable) | ||
5159 | { | ||
5160 | if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5161 | application[i].CDEnable = FALSE; | ||
5162 | } | ||
5163 | } | ||
5164 | break; | ||
5165 | |||
5166 | case DEACTIVATION_DIVERSION: | ||
5167 | case ACTIVATION_DIVERSION: | ||
5168 | case DIVERSION_INTERROGATE_CFU: | ||
5169 | case DIVERSION_INTERROGATE_CFB: | ||
5170 | case DIVERSION_INTERROGATE_CFNR: | ||
5171 | case DIVERSION_INTERROGATE_NUM: | ||
5172 | case CCBS_REQUEST: | ||
5173 | case CCBS_DEACTIVATE: | ||
5174 | case CCBS_INTERROGATE: | ||
5175 | if(!plci->appl) break; | ||
5176 | if(pty_cai[2]!=0xff) | ||
5177 | { | ||
5178 | PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]); | ||
5179 | } | ||
5180 | else | ||
5181 | { | ||
5182 | PUT_WORD(&Interr_Err_Ind[4],0x300E); | ||
5183 | } | ||
5184 | switch (pty_cai[5]) | ||
5185 | { | ||
5186 | case DEACTIVATION_DIVERSION: | ||
5187 | dbug(1,dprintf("Deact_Div")); | ||
5188 | Interr_Err_Ind[0]=0x9; | ||
5189 | Interr_Err_Ind[3]=0x6; | ||
5190 | PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP); | ||
5191 | break; | ||
5192 | case ACTIVATION_DIVERSION: | ||
5193 | dbug(1,dprintf("Act_Div")); | ||
5194 | Interr_Err_Ind[0]=0x9; | ||
5195 | Interr_Err_Ind[3]=0x6; | ||
5196 | PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START); | ||
5197 | break; | ||
5198 | case DIVERSION_INTERROGATE_CFU: | ||
5199 | case DIVERSION_INTERROGATE_CFB: | ||
5200 | case DIVERSION_INTERROGATE_CFNR: | ||
5201 | dbug(1,dprintf("Interr_Div")); | ||
5202 | Interr_Err_Ind[0]=0xa; | ||
5203 | Interr_Err_Ind[3]=0x7; | ||
5204 | PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION); | ||
5205 | break; | ||
5206 | case DIVERSION_INTERROGATE_NUM: | ||
5207 | dbug(1,dprintf("Interr_Num")); | ||
5208 | Interr_Err_Ind[0]=0xa; | ||
5209 | Interr_Err_Ind[3]=0x7; | ||
5210 | PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS); | ||
5211 | break; | ||
5212 | case CCBS_REQUEST: | ||
5213 | dbug(1,dprintf("CCBS Request")); | ||
5214 | Interr_Err_Ind[0]=0xd; | ||
5215 | Interr_Err_Ind[3]=0xa; | ||
5216 | PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST); | ||
5217 | break; | ||
5218 | case CCBS_DEACTIVATE: | ||
5219 | dbug(1,dprintf("CCBS Deactivate")); | ||
5220 | Interr_Err_Ind[0]=0x9; | ||
5221 | Interr_Err_Ind[3]=0x6; | ||
5222 | PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE); | ||
5223 | break; | ||
5224 | case CCBS_INTERROGATE: | ||
5225 | dbug(1,dprintf("CCBS Interrogate")); | ||
5226 | Interr_Err_Ind[0]=0xb; | ||
5227 | Interr_Err_Ind[3]=0x8; | ||
5228 | PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE); | ||
5229 | break; | ||
5230 | } | ||
5231 | PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle); | ||
5232 | sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind); | ||
5233 | plci_remove(plci); | ||
5234 | break; | ||
5235 | case ACTIVATION_MWI: | ||
5236 | case DEACTIVATION_MWI: | ||
5237 | if(pty_cai[5]==ACTIVATION_MWI) | ||
5238 | { | ||
5239 | PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE); | ||
5240 | } | ||
5241 | else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); | ||
5242 | |||
5243 | if(pty_cai[2]!=0xff) | ||
5244 | { | ||
5245 | PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); | ||
5246 | } | ||
5247 | else | ||
5248 | { | ||
5249 | PUT_WORD(&SS_Ind[4],0x300E); | ||
5250 | } | ||
5251 | |||
5252 | if(plci->cr_enquiry) | ||
5253 | { | ||
5254 | sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind); | ||
5255 | plci_remove(plci); | ||
5256 | } | ||
5257 | else | ||
5258 | { | ||
5259 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5260 | } | ||
5261 | break; | ||
5262 | case CONF_ADD: /* ERROR */ | ||
5263 | case CONF_BEGIN: | ||
5264 | case CONF_DROP: | ||
5265 | case CONF_ISOLATE: | ||
5266 | case CONF_REATTACH: | ||
5267 | CONF_Ind[0]=9; | ||
5268 | CONF_Ind[3]=6; | ||
5269 | switch(pty_cai[5]) | ||
5270 | { | ||
5271 | case CONF_BEGIN: | ||
5272 | PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN); | ||
5273 | plci->ptyState = 0; | ||
5274 | break; | ||
5275 | case CONF_DROP: | ||
5276 | CONF_Ind[0]=5; | ||
5277 | CONF_Ind[3]=2; | ||
5278 | PUT_WORD(&CONF_Ind[1],S_CONF_DROP); | ||
5279 | plci->ptyState = CONNECTED; | ||
5280 | break; | ||
5281 | case CONF_ISOLATE: | ||
5282 | CONF_Ind[0]=5; | ||
5283 | CONF_Ind[3]=2; | ||
5284 | PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE); | ||
5285 | plci->ptyState = CONNECTED; | ||
5286 | break; | ||
5287 | case CONF_REATTACH: | ||
5288 | CONF_Ind[0]=5; | ||
5289 | CONF_Ind[3]=2; | ||
5290 | PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH); | ||
5291 | plci->ptyState = CONNECTED; | ||
5292 | break; | ||
5293 | case CONF_ADD: | ||
5294 | PUT_WORD(&CONF_Ind[1],S_CONF_ADD); | ||
5295 | plci->relatedPTYPLCI = NULL; | ||
5296 | tplci=plci->relatedPTYPLCI; | ||
5297 | if(tplci) tplci->ptyState = CONNECTED; | ||
5298 | plci->ptyState = CONNECTED; | ||
5299 | break; | ||
5300 | } | ||
5301 | |||
5302 | if(pty_cai[2]!=0xff) | ||
5303 | { | ||
5304 | PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]); | ||
5305 | } | ||
5306 | else | ||
5307 | { | ||
5308 | PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond | ||
5309 | within the required time */ | ||
5310 | } | ||
5311 | |||
5312 | PUT_DWORD(&CONF_Ind[6],0x0); | ||
5313 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); | ||
5314 | break; | ||
5315 | } | ||
5316 | break; | ||
5317 | |||
5318 | /* Supplementary Service indicates success */ | ||
5319 | case S_SERVICE: | ||
5320 | dbug(1,dprintf("Service_Ind")); | ||
5321 | PUT_WORD (&CF_Ind[4], 0); | ||
5322 | switch (pty_cai[5]) | ||
5323 | { | ||
5324 | case THREE_PTY_END: | ||
5325 | case THREE_PTY_BEGIN: | ||
5326 | case ECT_EXECUTE: | ||
5327 | if(!plci->relatedPTYPLCI) break; | ||
5328 | tplci = plci->relatedPTYPLCI; | ||
5329 | rId = ( (word)tplci->Id<<8)|tplci->adapter->Id; | ||
5330 | if(tplci->tel) rId|=EXT_CONTROLLER; | ||
5331 | if(pty_cai[5]==ECT_EXECUTE) | ||
5332 | { | ||
5333 | PUT_WORD(&SS_Ind[1],S_ECT); | ||
5334 | |||
5335 | if(plci->vswitchstate!=3) | ||
5336 | { | ||
5337 | |||
5338 | plci->ptyState = IDLE; | ||
5339 | plci->relatedPTYPLCI = NULL; | ||
5340 | plci->ptyState = 0; | ||
5341 | |||
5342 | } | ||
5343 | |||
5344 | dbug(1,dprintf("ECT OK")); | ||
5345 | sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); | ||
5346 | |||
5347 | |||
5348 | |||
5349 | } | ||
5350 | else | ||
5351 | { | ||
5352 | switch (plci->ptyState) | ||
5353 | { | ||
5354 | case S_3PTY_BEGIN: | ||
5355 | plci->ptyState = CONNECTED; | ||
5356 | dbug(1,dprintf("3PTY ON")); | ||
5357 | break; | ||
5358 | |||
5359 | case S_3PTY_END: | ||
5360 | plci->ptyState = IDLE; | ||
5361 | plci->relatedPTYPLCI = NULL; | ||
5362 | plci->ptyState = 0; | ||
5363 | dbug(1,dprintf("3PTY OFF")); | ||
5364 | break; | ||
5365 | } | ||
5366 | PUT_WORD(&SS_Ind[1],pty_cai[5]+3); | ||
5367 | sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); | ||
5368 | } | ||
5369 | break; | ||
5370 | |||
5371 | case CALL_DEFLECTION: | ||
5372 | PUT_WORD(&SS_Ind[1],pty_cai[5]); | ||
5373 | for(i=0; i<max_appl; i++) | ||
5374 | { | ||
5375 | if(application[i].CDEnable) | ||
5376 | { | ||
5377 | if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5378 | application[i].CDEnable = FALSE; | ||
5379 | } | ||
5380 | } | ||
5381 | break; | ||
5382 | |||
5383 | case DEACTIVATION_DIVERSION: | ||
5384 | case ACTIVATION_DIVERSION: | ||
5385 | if(!plci->appl) break; | ||
5386 | PUT_WORD(&CF_Ind[1],pty_cai[5]+2); | ||
5387 | PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle); | ||
5388 | sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind); | ||
5389 | plci_remove(plci); | ||
5390 | break; | ||
5391 | |||
5392 | case DIVERSION_INTERROGATE_CFU: | ||
5393 | case DIVERSION_INTERROGATE_CFB: | ||
5394 | case DIVERSION_INTERROGATE_CFNR: | ||
5395 | case DIVERSION_INTERROGATE_NUM: | ||
5396 | case CCBS_REQUEST: | ||
5397 | case CCBS_DEACTIVATE: | ||
5398 | case CCBS_INTERROGATE: | ||
5399 | if(!plci->appl) break; | ||
5400 | switch (pty_cai[5]) | ||
5401 | { | ||
5402 | case DIVERSION_INTERROGATE_CFU: | ||
5403 | case DIVERSION_INTERROGATE_CFB: | ||
5404 | case DIVERSION_INTERROGATE_CFNR: | ||
5405 | dbug(1,dprintf("Interr_Div")); | ||
5406 | PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION); | ||
5407 | pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | ||
5408 | break; | ||
5409 | case DIVERSION_INTERROGATE_NUM: | ||
5410 | dbug(1,dprintf("Interr_Num")); | ||
5411 | PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS); | ||
5412 | pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | ||
5413 | break; | ||
5414 | case CCBS_REQUEST: | ||
5415 | dbug(1,dprintf("CCBS Request")); | ||
5416 | PUT_WORD(&pty_cai[1],S_CCBS_REQUEST); | ||
5417 | pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | ||
5418 | break; | ||
5419 | case CCBS_DEACTIVATE: | ||
5420 | dbug(1,dprintf("CCBS Deactivate")); | ||
5421 | PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE); | ||
5422 | pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | ||
5423 | break; | ||
5424 | case CCBS_INTERROGATE: | ||
5425 | dbug(1,dprintf("CCBS Interrogate")); | ||
5426 | PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE); | ||
5427 | pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ | ||
5428 | break; | ||
5429 | } | ||
5430 | PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */ | ||
5431 | PUT_DWORD(&pty_cai[6],plci->appl->S_Handle); | ||
5432 | sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai); | ||
5433 | plci_remove(plci); | ||
5434 | break; | ||
5435 | |||
5436 | case ACTIVATION_MWI: | ||
5437 | case DEACTIVATION_MWI: | ||
5438 | if(pty_cai[5]==ACTIVATION_MWI) | ||
5439 | { | ||
5440 | PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE); | ||
5441 | } | ||
5442 | else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); | ||
5443 | if(plci->cr_enquiry) | ||
5444 | { | ||
5445 | sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind); | ||
5446 | plci_remove(plci); | ||
5447 | } | ||
5448 | else | ||
5449 | { | ||
5450 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5451 | } | ||
5452 | break; | ||
5453 | case MWI_INDICATION: | ||
5454 | if(pty_cai[0]>=0x12) | ||
5455 | { | ||
5456 | PUT_WORD(&pty_cai[3],S_MWI_INDICATE); | ||
5457 | pty_cai[2]=pty_cai[0]-2; /* len Parameter */ | ||
5458 | pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */ | ||
5459 | if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI)) | ||
5460 | { | ||
5461 | if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */ | ||
5462 | { | ||
5463 | sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]); | ||
5464 | plci_remove(plci); | ||
5465 | return; | ||
5466 | } | ||
5467 | else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]); | ||
5468 | pty_cai[0]=0; | ||
5469 | } | ||
5470 | else | ||
5471 | { | ||
5472 | for(i=0; i<max_appl; i++) | ||
5473 | { | ||
5474 | if(a->Notification_Mask[i]&SMASK_MWI) | ||
5475 | { | ||
5476 | sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]); | ||
5477 | pty_cai[0]=0; | ||
5478 | } | ||
5479 | } | ||
5480 | } | ||
5481 | |||
5482 | if(!pty_cai[0]) | ||
5483 | { /* acknowledge */ | ||
5484 | facility[2]= 0; /* returncode */ | ||
5485 | } | ||
5486 | else facility[2]= 0xff; | ||
5487 | } | ||
5488 | else | ||
5489 | { | ||
5490 | /* reject */ | ||
5491 | facility[2]= 0xff; /* returncode */ | ||
5492 | } | ||
5493 | facility[0]= 2; | ||
5494 | facility[1]= MWI_RESPONSE; /* Function */ | ||
5495 | add_p(plci,CAI,facility); | ||
5496 | add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */ | ||
5497 | sig_req(plci,S_SERVICE,0); | ||
5498 | send_req(plci); | ||
5499 | plci->command = 0; | ||
5500 | next_internal_command (Id, plci); | ||
5501 | break; | ||
5502 | case CONF_ADD: /* OK */ | ||
5503 | case CONF_BEGIN: | ||
5504 | case CONF_DROP: | ||
5505 | case CONF_ISOLATE: | ||
5506 | case CONF_REATTACH: | ||
5507 | case CONF_PARTYDISC: | ||
5508 | CONF_Ind[0]=9; | ||
5509 | CONF_Ind[3]=6; | ||
5510 | switch(pty_cai[5]) | ||
5511 | { | ||
5512 | case CONF_BEGIN: | ||
5513 | PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN); | ||
5514 | if(pty_cai[0]==6) | ||
5515 | { | ||
5516 | d=pty_cai[6]; | ||
5517 | PUT_DWORD(&CONF_Ind[6],d); /* PartyID */ | ||
5518 | } | ||
5519 | else | ||
5520 | { | ||
5521 | PUT_DWORD(&CONF_Ind[6],0x0); | ||
5522 | } | ||
5523 | break; | ||
5524 | case CONF_ISOLATE: | ||
5525 | PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE); | ||
5526 | CONF_Ind[0]=5; | ||
5527 | CONF_Ind[3]=2; | ||
5528 | break; | ||
5529 | case CONF_REATTACH: | ||
5530 | PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH); | ||
5531 | CONF_Ind[0]=5; | ||
5532 | CONF_Ind[3]=2; | ||
5533 | break; | ||
5534 | case CONF_DROP: | ||
5535 | PUT_WORD(&CONF_Ind[1],S_CONF_DROP); | ||
5536 | CONF_Ind[0]=5; | ||
5537 | CONF_Ind[3]=2; | ||
5538 | break; | ||
5539 | case CONF_ADD: | ||
5540 | PUT_WORD(&CONF_Ind[1],S_CONF_ADD); | ||
5541 | d=pty_cai[6]; | ||
5542 | PUT_DWORD(&CONF_Ind[6],d); /* PartyID */ | ||
5543 | tplci=plci->relatedPTYPLCI; | ||
5544 | if(tplci) tplci->ptyState = CONNECTED; | ||
5545 | break; | ||
5546 | case CONF_PARTYDISC: | ||
5547 | CONF_Ind[0]=7; | ||
5548 | CONF_Ind[3]=4; | ||
5549 | PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC); | ||
5550 | d=pty_cai[6]; | ||
5551 | PUT_DWORD(&CONF_Ind[4],d); /* PartyID */ | ||
5552 | break; | ||
5553 | } | ||
5554 | plci->ptyState = CONNECTED; | ||
5555 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); | ||
5556 | break; | ||
5557 | case CCBS_INFO_RETAIN: | ||
5558 | case CCBS_ERASECALLLINKAGEID: | ||
5559 | case CCBS_STOP_ALERTING: | ||
5560 | CONF_Ind[0]=5; | ||
5561 | CONF_Ind[3]=2; | ||
5562 | switch(pty_cai[5]) | ||
5563 | { | ||
5564 | case CCBS_INFO_RETAIN: | ||
5565 | PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN); | ||
5566 | break; | ||
5567 | case CCBS_STOP_ALERTING: | ||
5568 | PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING); | ||
5569 | break; | ||
5570 | case CCBS_ERASECALLLINKAGEID: | ||
5571 | PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID); | ||
5572 | CONF_Ind[0]=7; | ||
5573 | CONF_Ind[3]=4; | ||
5574 | CONF_Ind[6]=0; | ||
5575 | CONF_Ind[7]=0; | ||
5576 | break; | ||
5577 | } | ||
5578 | w=pty_cai[6]; | ||
5579 | PUT_WORD(&CONF_Ind[4],w); /* PartyID */ | ||
5580 | |||
5581 | if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS)) | ||
5582 | { | ||
5583 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); | ||
5584 | } | ||
5585 | else | ||
5586 | { | ||
5587 | for(i=0; i<max_appl; i++) | ||
5588 | if(a->Notification_Mask[i]&SMASK_CCBS) | ||
5589 | sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind); | ||
5590 | } | ||
5591 | break; | ||
5592 | } | ||
5593 | break; | ||
5594 | case CALL_HOLD_REJ: | ||
5595 | cau = parms[7]; | ||
5596 | if(cau) | ||
5597 | { | ||
5598 | i = _L3_CAUSE | cau[2]; | ||
5599 | if(cau[2]==0) i = 0x3603; | ||
5600 | } | ||
5601 | else | ||
5602 | { | ||
5603 | i = 0x3603; | ||
5604 | } | ||
5605 | PUT_WORD(&SS_Ind[1],S_HOLD); | ||
5606 | PUT_WORD(&SS_Ind[4],i); | ||
5607 | if(plci->SuppState == HOLD_REQUEST) | ||
5608 | { | ||
5609 | plci->SuppState = IDLE; | ||
5610 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5611 | } | ||
5612 | break; | ||
5613 | |||
5614 | case CALL_HOLD_ACK: | ||
5615 | if(plci->SuppState == HOLD_REQUEST) | ||
5616 | { | ||
5617 | plci->SuppState = CALL_HELD; | ||
5618 | CodecIdCheck(a, plci); | ||
5619 | start_internal_command (Id, plci, hold_save_command); | ||
5620 | } | ||
5621 | break; | ||
5622 | |||
5623 | case CALL_RETRIEVE_REJ: | ||
5624 | cau = parms[7]; | ||
5625 | if(cau) | ||
5626 | { | ||
5627 | i = _L3_CAUSE | cau[2]; | ||
5628 | if(cau[2]==0) i = 0x3603; | ||
5629 | } | ||
5630 | else | ||
5631 | { | ||
5632 | i = 0x3603; | ||
5633 | } | ||
5634 | PUT_WORD(&SS_Ind[1],S_RETRIEVE); | ||
5635 | PUT_WORD(&SS_Ind[4],i); | ||
5636 | if(plci->SuppState == RETRIEVE_REQUEST) | ||
5637 | { | ||
5638 | plci->SuppState = CALL_HELD; | ||
5639 | CodecIdCheck(a, plci); | ||
5640 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5641 | } | ||
5642 | break; | ||
5643 | |||
5644 | case CALL_RETRIEVE_ACK: | ||
5645 | PUT_WORD(&SS_Ind[1],S_RETRIEVE); | ||
5646 | if(plci->SuppState == RETRIEVE_REQUEST) | ||
5647 | { | ||
5648 | plci->SuppState = IDLE; | ||
5649 | plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; | ||
5650 | plci->b_channel = esc_chi[esc_chi[0]]&0x1f; | ||
5651 | if(plci->tel) | ||
5652 | { | ||
5653 | mixer_set_bchannel_id_esc (plci, plci->b_channel); | ||
5654 | dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel)); | ||
5655 | SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a); | ||
5656 | if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT) | ||
5657 | { | ||
5658 | dbug(1,dprintf("Get B-ch")); | ||
5659 | start_internal_command (Id, plci, retrieve_restore_command); | ||
5660 | } | ||
5661 | else | ||
5662 | sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind); | ||
5663 | } | ||
5664 | else | ||
5665 | start_internal_command (Id, plci, retrieve_restore_command); | ||
5666 | } | ||
5667 | break; | ||
5668 | |||
5669 | case INDICATE_IND: | ||
5670 | if(plci->State != LISTENING) { | ||
5671 | sig_req(plci,HANGUP,0); | ||
5672 | send_req(plci); | ||
5673 | break; | ||
5674 | } | ||
5675 | cip = find_cip(a,parms[4],parms[6]); | ||
5676 | cip_mask = 1L<<cip; | ||
5677 | dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask)); | ||
5678 | clear_c_ind_mask (plci); | ||
5679 | if (!remove_started && !a->adapter_disabled) | ||
5680 | { | ||
5681 | set_c_ind_mask_bit (plci, MAX_APPL); | ||
5682 | group_optimization(a, plci); | ||
5683 | for(i=0; i<max_appl; i++) { | ||
5684 | if(application[i].Id | ||
5685 | && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask) | ||
5686 | && CPN_filter_ok(parms[0],a,i) | ||
5687 | && test_group_ind_mask_bit (plci, i) ) { | ||
5688 | dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] )); | ||
5689 | set_c_ind_mask_bit (plci, i); | ||
5690 | dump_c_ind_mask (plci); | ||
5691 | plci->State = INC_CON_PENDING; | ||
5692 | plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) | | ||
5693 | CALL_DIR_IN | CALL_DIR_ANSWER; | ||
5694 | if(esc_chi[0]) { | ||
5695 | plci->b_channel = esc_chi[esc_chi[0]]&0x1f; | ||
5696 | mixer_set_bchannel_id_esc (plci, plci->b_channel); | ||
5697 | } | ||
5698 | /* if a listen on the ext controller is done, check if hook states */ | ||
5699 | /* are supported or if just a on board codec must be activated */ | ||
5700 | if(a->codec_listen[i] && !a->AdvSignalPLCI) { | ||
5701 | if(a->profile.Global_Options & HANDSET) | ||
5702 | plci->tel = ADV_VOICE; | ||
5703 | else if(a->profile.Global_Options & ON_BOARD_CODEC) | ||
5704 | plci->tel = CODEC; | ||
5705 | if(plci->tel) Id|=EXT_CONTROLLER; | ||
5706 | a->codec_listen[i] = plci; | ||
5707 | } | ||
5708 | |||
5709 | sendf(&application[i],_CONNECT_I,Id,0, | ||
5710 | "wSSSSSSSbSSSSS", cip, /* CIP */ | ||
5711 | parms[0], /* CalledPartyNumber */ | ||
5712 | multi_CiPN_parms[0], /* CallingPartyNumber */ | ||
5713 | parms[2], /* CalledPartySubad */ | ||
5714 | parms[3], /* CallingPartySubad */ | ||
5715 | parms[4], /* BearerCapability */ | ||
5716 | parms[5], /* LowLC */ | ||
5717 | parms[6], /* HighLC */ | ||
5718 | ai_len, /* nested struct add_i */ | ||
5719 | add_i[0], /* B channel info */ | ||
5720 | add_i[1], /* keypad facility */ | ||
5721 | add_i[2], /* user user data */ | ||
5722 | add_i[3], /* nested facility */ | ||
5723 | multi_CiPN_parms[1] /* second CiPN(SCR) */ | ||
5724 | ); | ||
5725 | SendSSExtInd(&application[i], | ||
5726 | plci, | ||
5727 | Id, | ||
5728 | multi_ssext_parms); | ||
5729 | SendSetupInfo(&application[i], | ||
5730 | plci, | ||
5731 | Id, | ||
5732 | parms, | ||
5733 | SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE)); | ||
5734 | } | ||
5735 | } | ||
5736 | clear_c_ind_mask_bit (plci, MAX_APPL); | ||
5737 | dump_c_ind_mask (plci); | ||
5738 | } | ||
5739 | if(c_ind_mask_empty (plci)) { | ||
5740 | sig_req(plci,HANGUP,0); | ||
5741 | send_req(plci); | ||
5742 | plci->State = IDLE; | ||
5743 | } | ||
5744 | plci->notifiedcall = 0; | ||
5745 | a->listen_active--; | ||
5746 | listen_check(a); | ||
5747 | break; | ||
5748 | |||
5749 | case CALL_PEND_NOTIFY: | ||
5750 | plci->notifiedcall = 1; | ||
5751 | listen_check(a); | ||
5752 | break; | ||
5753 | |||
5754 | case CALL_IND: | ||
5755 | case CALL_CON: | ||
5756 | if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG) | ||
5757 | { | ||
5758 | if(plci->internal_command==PERM_COD_CONN_PEND) | ||
5759 | { | ||
5760 | if(plci->State==ADVANCED_VOICE_NOSIG) | ||
5761 | { | ||
5762 | dbug(1,dprintf("***Codec OK")); | ||
5763 | if(a->AdvSignalPLCI) | ||
5764 | { | ||
5765 | tplci = a->AdvSignalPLCI; | ||
5766 | if(tplci->spoofed_msg) | ||
5767 | { | ||
5768 | dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg)); | ||
5769 | tplci->command = 0; | ||
5770 | tplci->internal_command = 0; | ||
5771 | x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80; | ||
5772 | switch (tplci->spoofed_msg) | ||
5773 | { | ||
5774 | case CALL_RES: | ||
5775 | tplci->command = _CONNECT_I|RESPONSE; | ||
5776 | api_load_msg (&tplci->saved_msg, saved_parms); | ||
5777 | add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities); | ||
5778 | if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200) | ||
5779 | { | ||
5780 | /* early B3 connect (CIP mask bit 9) no release after a disc */ | ||
5781 | add_p(tplci,LLI,"\x01\x01"); | ||
5782 | } | ||
5783 | add_s(tplci, CONN_NR, &saved_parms[2]); | ||
5784 | add_s(tplci, LLC, &saved_parms[4]); | ||
5785 | add_ai(tplci, &saved_parms[5]); | ||
5786 | tplci->State = INC_CON_ACCEPT; | ||
5787 | sig_req(tplci, CALL_RES,0); | ||
5788 | send_req(tplci); | ||
5789 | break; | ||
5790 | |||
5791 | case AWAITING_SELECT_B: | ||
5792 | dbug(1,dprintf("Select_B continue")); | ||
5793 | start_internal_command (x_Id, tplci, select_b_command); | ||
5794 | break; | ||
5795 | |||
5796 | case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */ | ||
5797 | if(!tplci->Sig.Id) | ||
5798 | { | ||
5799 | dbug(1,dprintf("No SigID!")); | ||
5800 | sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI); | ||
5801 | plci_remove(tplci); | ||
5802 | break; | ||
5803 | } | ||
5804 | tplci->command = _MANUFACTURER_R; | ||
5805 | api_load_msg (&tplci->saved_msg, saved_parms); | ||
5806 | dir = saved_parms[2].info[0]; | ||
5807 | if(dir==1) { | ||
5808 | sig_req(tplci,CALL_REQ,0); | ||
5809 | } | ||
5810 | else if(!dir){ | ||
5811 | sig_req(tplci,LISTEN_REQ,0); | ||
5812 | } | ||
5813 | send_req(tplci); | ||
5814 | sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0); | ||
5815 | break; | ||
5816 | |||
5817 | case (CALL_REQ|AWAITING_MANUF_CON): | ||
5818 | sig_req(tplci,CALL_REQ,0); | ||
5819 | send_req(tplci); | ||
5820 | break; | ||
5821 | |||
5822 | case CALL_REQ: | ||
5823 | if(!tplci->Sig.Id) | ||
5824 | { | ||
5825 | dbug(1,dprintf("No SigID!")); | ||
5826 | sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI); | ||
5827 | plci_remove(tplci); | ||
5828 | break; | ||
5829 | } | ||
5830 | tplci->command = _CONNECT_R; | ||
5831 | api_load_msg (&tplci->saved_msg, saved_parms); | ||
5832 | add_s(tplci,CPN,&saved_parms[1]); | ||
5833 | add_s(tplci,DSA,&saved_parms[3]); | ||
5834 | add_ai(tplci,&saved_parms[9]); | ||
5835 | sig_req(tplci,CALL_REQ,0); | ||
5836 | send_req(tplci); | ||
5837 | break; | ||
5838 | |||
5839 | case CALL_RETRIEVE: | ||
5840 | tplci->command = C_RETRIEVE_REQ; | ||
5841 | sig_req(tplci,CALL_RETRIEVE,0); | ||
5842 | send_req(tplci); | ||
5843 | break; | ||
5844 | } | ||
5845 | tplci->spoofed_msg = 0; | ||
5846 | if (tplci->internal_command == 0) | ||
5847 | next_internal_command (x_Id, tplci); | ||
5848 | } | ||
5849 | } | ||
5850 | next_internal_command (Id, plci); | ||
5851 | break; | ||
5852 | } | ||
5853 | dbug(1,dprintf("***Codec Hook Init Req")); | ||
5854 | plci->internal_command = PERM_COD_HOOK; | ||
5855 | add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/ | ||
5856 | sig_req(plci,TEL_CTRL,0); | ||
5857 | send_req(plci); | ||
5858 | } | ||
5859 | } | ||
5860 | else if(plci->command != _MANUFACTURER_R /* old style permanent connect */ | ||
5861 | && plci->State!=INC_ACT_PENDING) | ||
5862 | { | ||
5863 | mixer_set_bchannel_id_esc (plci, plci->b_channel); | ||
5864 | if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */ | ||
5865 | { | ||
5866 | chi[2] = plci->b_channel; | ||
5867 | SetVoiceChannel(a->AdvCodecPLCI, chi, a); | ||
5868 | } | ||
5869 | sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"",""); | ||
5870 | plci->State = INC_ACT_PENDING; | ||
5871 | } | ||
5872 | break; | ||
5873 | |||
5874 | case TEL_CTRL: | ||
5875 | Number = 0; | ||
5876 | ie = multi_fac_parms[0]; /* inspect the facility hook indications */ | ||
5877 | if(plci->State==ADVANCED_VOICE_SIG && ie[0]){ | ||
5878 | switch (ie[1]&0x91) { | ||
5879 | case 0x80: /* hook off */ | ||
5880 | case 0x81: | ||
5881 | if(plci->internal_command==PERM_COD_HOOK) | ||
5882 | { | ||
5883 | dbug(1,dprintf("init:hook_off")); | ||
5884 | plci->hook_state = ie[1]; | ||
5885 | next_internal_command (Id, plci); | ||
5886 | break; | ||
5887 | } | ||
5888 | else /* ignore doubled hook indications */ | ||
5889 | { | ||
5890 | if( ((plci->hook_state)&0xf0)==0x80) | ||
5891 | { | ||
5892 | dbug(1,dprintf("ignore hook")); | ||
5893 | break; | ||
5894 | } | ||
5895 | plci->hook_state = ie[1]&0x91; | ||
5896 | } | ||
5897 | /* check for incoming call pending */ | ||
5898 | /* and signal '+'.Appl must decide */ | ||
5899 | /* with connect_res if call must */ | ||
5900 | /* accepted or not */ | ||
5901 | for(i=0, tplci=NULL;i<max_appl;i++){ | ||
5902 | if(a->codec_listen[i] | ||
5903 | && (a->codec_listen[i]->State==INC_CON_PENDING | ||
5904 | ||a->codec_listen[i]->State==INC_CON_ALERT) ){ | ||
5905 | tplci = a->codec_listen[i]; | ||
5906 | tplci->appl = &application[i]; | ||
5907 | } | ||
5908 | } | ||
5909 | /* no incoming call, do outgoing call */ | ||
5910 | /* and signal '+' if outg. setup */ | ||
5911 | if(!a->AdvSignalPLCI && !tplci){ | ||
5912 | if((i=get_plci(a))) { | ||
5913 | a->AdvSignalPLCI = &a->plci[i-1]; | ||
5914 | tplci = a->AdvSignalPLCI; | ||
5915 | tplci->tel = ADV_VOICE; | ||
5916 | PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength); | ||
5917 | if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){ | ||
5918 | /* early B3 connect (CIP mask bit 9) no release after a disc */ | ||
5919 | add_p(tplci,LLI,"\x01\x01"); | ||
5920 | } | ||
5921 | add_p(tplci, CAI, voice_cai); | ||
5922 | add_p(tplci, OAD, a->TelOAD); | ||
5923 | add_p(tplci, OSA, a->TelOSA); | ||
5924 | add_p(tplci,SHIFT|6,NULL); | ||
5925 | add_p(tplci,SIN,"\x02\x01\x00"); | ||
5926 | add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
5927 | sig_req(tplci,ASSIGN,DSIG_ID); | ||
5928 | a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ; | ||
5929 | a->AdvSignalPLCI->command = 0; | ||
5930 | tplci->appl = a->AdvSignalAppl; | ||
5931 | tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | ||
5932 | send_req(tplci); | ||
5933 | } | ||
5934 | |||
5935 | } | ||
5936 | |||
5937 | if(!tplci) break; | ||
5938 | Id = ((word)tplci->Id<<8)|a->Id; | ||
5939 | Id|=EXT_CONTROLLER; | ||
5940 | sendf(tplci->appl, | ||
5941 | _FACILITY_I, | ||
5942 | Id, | ||
5943 | 0, | ||
5944 | "ws", (word)0, "\x01+"); | ||
5945 | break; | ||
5946 | |||
5947 | case 0x90: /* hook on */ | ||
5948 | case 0x91: | ||
5949 | if(plci->internal_command==PERM_COD_HOOK) | ||
5950 | { | ||
5951 | dbug(1,dprintf("init:hook_on")); | ||
5952 | plci->hook_state = ie[1]&0x91; | ||
5953 | next_internal_command (Id, plci); | ||
5954 | break; | ||
5955 | } | ||
5956 | else /* ignore doubled hook indications */ | ||
5957 | { | ||
5958 | if( ((plci->hook_state)&0xf0)==0x90) break; | ||
5959 | plci->hook_state = ie[1]&0x91; | ||
5960 | } | ||
5961 | /* hangup the adv. voice call and signal '-' to the appl */ | ||
5962 | if(a->AdvSignalPLCI) { | ||
5963 | Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id; | ||
5964 | if(plci->tel) Id|=EXT_CONTROLLER; | ||
5965 | sendf(a->AdvSignalAppl, | ||
5966 | _FACILITY_I, | ||
5967 | Id, | ||
5968 | 0, | ||
5969 | "ws", (word)0, "\x01-"); | ||
5970 | a->AdvSignalPLCI->internal_command = HOOK_ON_REQ; | ||
5971 | a->AdvSignalPLCI->command = 0; | ||
5972 | sig_req(a->AdvSignalPLCI,HANGUP,0); | ||
5973 | send_req(a->AdvSignalPLCI); | ||
5974 | } | ||
5975 | break; | ||
5976 | } | ||
5977 | } | ||
5978 | break; | ||
5979 | |||
5980 | case RESUME: | ||
5981 | clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1)); | ||
5982 | PUT_WORD(&resume_cau[4],GOOD); | ||
5983 | sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau); | ||
5984 | break; | ||
5985 | |||
5986 | case SUSPEND: | ||
5987 | clear_c_ind_mask (plci); | ||
5988 | |||
5989 | if (plci->NL.Id && !plci->nl_remove_id) { | ||
5990 | mixer_remove (plci); | ||
5991 | nl_req_ncci(plci,REMOVE,0); | ||
5992 | } | ||
5993 | if (!plci->sig_remove_id) { | ||
5994 | plci->internal_command = 0; | ||
5995 | sig_req(plci,REMOVE,0); | ||
5996 | } | ||
5997 | send_req(plci); | ||
5998 | if(!plci->channels) { | ||
5999 | sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00"); | ||
6000 | sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0); | ||
6001 | } | ||
6002 | break; | ||
6003 | |||
6004 | case SUSPEND_REJ: | ||
6005 | break; | ||
6006 | |||
6007 | case HANGUP: | ||
6008 | plci->hangup_flow_ctrl_timer=0; | ||
6009 | if(plci->manufacturer && plci->State==LOCAL_CONNECT) break; | ||
6010 | cau = parms[7]; | ||
6011 | if(cau) { | ||
6012 | i = _L3_CAUSE | cau[2]; | ||
6013 | if(cau[2]==0) i = 0; | ||
6014 | else if(cau[2]==8) i = _L1_ERROR; | ||
6015 | else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR; | ||
6016 | else if(cau[2]==5) i = _CAPI_GUARD_ERROR; | ||
6017 | } | ||
6018 | else { | ||
6019 | i = _L3_ERROR; | ||
6020 | } | ||
6021 | |||
6022 | if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) | ||
6023 | { | ||
6024 | for(i=0; i<max_appl; i++) | ||
6025 | { | ||
6026 | if(test_c_ind_mask_bit (plci, i)) | ||
6027 | sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0); | ||
6028 | } | ||
6029 | } | ||
6030 | else | ||
6031 | { | ||
6032 | clear_c_ind_mask (plci); | ||
6033 | } | ||
6034 | if(!plci->appl) | ||
6035 | { | ||
6036 | if (plci->State == LISTENING) | ||
6037 | { | ||
6038 | plci->notifiedcall=0; | ||
6039 | a->listen_active--; | ||
6040 | } | ||
6041 | plci->State = INC_DIS_PENDING; | ||
6042 | if(c_ind_mask_empty (plci)) | ||
6043 | { | ||
6044 | plci->State = IDLE; | ||
6045 | if (plci->NL.Id && !plci->nl_remove_id) | ||
6046 | { | ||
6047 | mixer_remove (plci); | ||
6048 | nl_req_ncci(plci,REMOVE,0); | ||
6049 | } | ||
6050 | if (!plci->sig_remove_id) | ||
6051 | { | ||
6052 | plci->internal_command = 0; | ||
6053 | sig_req(plci,REMOVE,0); | ||
6054 | } | ||
6055 | send_req(plci); | ||
6056 | } | ||
6057 | } | ||
6058 | else | ||
6059 | { | ||
6060 | /* collision of DISCONNECT or CONNECT_RES with HANGUP can */ | ||
6061 | /* result in a second HANGUP! Don't generate another */ | ||
6062 | /* DISCONNECT */ | ||
6063 | if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING) | ||
6064 | { | ||
6065 | if(plci->State==RESUMING) | ||
6066 | { | ||
6067 | PUT_WORD(&resume_cau[4],i); | ||
6068 | sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau); | ||
6069 | } | ||
6070 | plci->State = INC_DIS_PENDING; | ||
6071 | sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i); | ||
6072 | } | ||
6073 | } | ||
6074 | break; | ||
6075 | |||
6076 | case SSEXT_IND: | ||
6077 | SendSSExtInd(NULL,plci,Id,multi_ssext_parms); | ||
6078 | break; | ||
6079 | |||
6080 | case VSWITCH_REQ: | ||
6081 | VSwitchReqInd(plci,Id,multi_vswitch_parms); | ||
6082 | break; | ||
6083 | case VSWITCH_IND: | ||
6084 | if(plci->relatedPTYPLCI && | ||
6085 | plci->vswitchstate==3 && | ||
6086 | plci->relatedPTYPLCI->vswitchstate==3 && | ||
6087 | parms[MAXPARMSIDS-1][0]) | ||
6088 | { | ||
6089 | add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]); | ||
6090 | sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0); | ||
6091 | send_req(plci->relatedPTYPLCI); | ||
6092 | } | ||
6093 | else VSwitchReqInd(plci,Id,multi_vswitch_parms); | ||
6094 | break; | ||
6095 | |||
6096 | } | ||
6097 | } | ||
6098 | |||
6099 | |||
6100 | static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag) | ||
6101 | { | ||
6102 | word i; | ||
6103 | byte * ie; | ||
6104 | word Info_Number; | ||
6105 | byte * Info_Element; | ||
6106 | word Info_Mask = 0; | ||
6107 | |||
6108 | dbug(1,dprintf("SetupInfo")); | ||
6109 | |||
6110 | for(i=0; i<MAXPARMSIDS; i++) { | ||
6111 | ie = parms[i]; | ||
6112 | Info_Number = 0; | ||
6113 | Info_Element = ie; | ||
6114 | if(ie[0]) { | ||
6115 | switch(i) { | ||
6116 | case 0: | ||
6117 | dbug(1,dprintf("CPN ")); | ||
6118 | Info_Number = 0x0070; | ||
6119 | Info_Mask = 0x80; | ||
6120 | Info_Sent_Flag = TRUE; | ||
6121 | break; | ||
6122 | case 8: /* display */ | ||
6123 | dbug(1,dprintf("display(%d)",i)); | ||
6124 | Info_Number = 0x0028; | ||
6125 | Info_Mask = 0x04; | ||
6126 | Info_Sent_Flag = TRUE; | ||
6127 | break; | ||
6128 | case 16: /* Channel Id */ | ||
6129 | dbug(1,dprintf("CHI")); | ||
6130 | Info_Number = 0x0018; | ||
6131 | Info_Mask = 0x100; | ||
6132 | Info_Sent_Flag = TRUE; | ||
6133 | mixer_set_bchannel_id (plci, Info_Element); | ||
6134 | break; | ||
6135 | case 19: /* Redirected Number */ | ||
6136 | dbug(1,dprintf("RDN")); | ||
6137 | Info_Number = 0x0074; | ||
6138 | Info_Mask = 0x400; | ||
6139 | Info_Sent_Flag = TRUE; | ||
6140 | break; | ||
6141 | case 20: /* Redirected Number extended */ | ||
6142 | dbug(1,dprintf("RDX")); | ||
6143 | Info_Number = 0x0073; | ||
6144 | Info_Mask = 0x400; | ||
6145 | Info_Sent_Flag = TRUE; | ||
6146 | break; | ||
6147 | case 22: /* Redirecing Number */ | ||
6148 | dbug(1,dprintf("RIN")); | ||
6149 | Info_Number = 0x0076; | ||
6150 | Info_Mask = 0x400; | ||
6151 | Info_Sent_Flag = TRUE; | ||
6152 | break; | ||
6153 | default: | ||
6154 | Info_Number = 0; | ||
6155 | break; | ||
6156 | } | ||
6157 | } | ||
6158 | |||
6159 | if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */ | ||
6160 | Info_Number = 0x8000 |5; | ||
6161 | Info_Mask = 0x10; | ||
6162 | Info_Element = ""; | ||
6163 | } | ||
6164 | |||
6165 | if(Info_Sent_Flag && Info_Number){ | ||
6166 | if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) { | ||
6167 | sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element); | ||
6168 | } | ||
6169 | } | ||
6170 | } | ||
6171 | } | ||
6172 | |||
6173 | |||
6174 | void SendInfo(PLCI * plci, dword Id, byte * * parms, byte iesent) | ||
6175 | { | ||
6176 | word i; | ||
6177 | word j; | ||
6178 | word k; | ||
6179 | byte * ie; | ||
6180 | word Info_Number; | ||
6181 | byte * Info_Element; | ||
6182 | word Info_Mask = 0; | ||
6183 | static byte charges[5] = {4,0,0,0,0}; | ||
6184 | static byte cause[] = {0x02,0x80,0x00}; | ||
6185 | APPL *appl; | ||
6186 | |||
6187 | dbug(1,dprintf("InfoParse ")); | ||
6188 | |||
6189 | if( | ||
6190 | !plci->appl | ||
6191 | && !plci->State | ||
6192 | && plci->Sig.Ind!=NCR_FACILITY | ||
6193 | ) | ||
6194 | { | ||
6195 | dbug(1,dprintf("NoParse ")); | ||
6196 | return; | ||
6197 | } | ||
6198 | cause[2] = 0; | ||
6199 | for(i=0; i<MAXPARMSIDS; i++) { | ||
6200 | ie = parms[i]; | ||
6201 | Info_Number = 0; | ||
6202 | Info_Element = ie; | ||
6203 | if(ie[0]) { | ||
6204 | switch(i) { | ||
6205 | case 0: | ||
6206 | dbug(1,dprintf("CPN ")); | ||
6207 | Info_Number = 0x0070; | ||
6208 | Info_Mask = 0x80; | ||
6209 | break; | ||
6210 | case 7: /* ESC_CAU */ | ||
6211 | dbug(1,dprintf("cau(0x%x)",ie[2])); | ||
6212 | Info_Number = 0x0008; | ||
6213 | Info_Mask = 0x00; | ||
6214 | cause[2] = ie[2]; | ||
6215 | Info_Element = NULL; | ||
6216 | break; | ||
6217 | case 8: /* display */ | ||
6218 | dbug(1,dprintf("display(%d)",i)); | ||
6219 | Info_Number = 0x0028; | ||
6220 | Info_Mask = 0x04; | ||
6221 | break; | ||
6222 | case 9: /* Date display */ | ||
6223 | dbug(1,dprintf("date(%d)",i)); | ||
6224 | Info_Number = 0x0029; | ||
6225 | Info_Mask = 0x02; | ||
6226 | break; | ||
6227 | case 10: /* charges */ | ||
6228 | for(j=0;j<4;j++) charges[1+j] = 0; | ||
6229 | for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++); | ||
6230 | for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j]; | ||
6231 | Info_Number = 0x4000; | ||
6232 | Info_Mask = 0x40; | ||
6233 | Info_Element = charges; | ||
6234 | break; | ||
6235 | case 11: /* user user info */ | ||
6236 | dbug(1,dprintf("uui")); | ||
6237 | Info_Number = 0x007E; | ||
6238 | Info_Mask = 0x08; | ||
6239 | break; | ||
6240 | case 12: /* congestion receiver ready */ | ||
6241 | dbug(1,dprintf("clRDY")); | ||
6242 | Info_Number = 0x00B0; | ||
6243 | Info_Mask = 0x08; | ||
6244 | Info_Element = ""; | ||
6245 | break; | ||
6246 | case 13: /* congestion receiver not ready */ | ||
6247 | dbug(1,dprintf("clNRDY")); | ||
6248 | Info_Number = 0x00BF; | ||
6249 | Info_Mask = 0x08; | ||
6250 | Info_Element = ""; | ||
6251 | break; | ||
6252 | case 15: /* Keypad Facility */ | ||
6253 | dbug(1,dprintf("KEY")); | ||
6254 | Info_Number = 0x002C; | ||
6255 | Info_Mask = 0x20; | ||
6256 | break; | ||
6257 | case 16: /* Channel Id */ | ||
6258 | dbug(1,dprintf("CHI")); | ||
6259 | Info_Number = 0x0018; | ||
6260 | Info_Mask = 0x100; | ||
6261 | mixer_set_bchannel_id (plci, Info_Element); | ||
6262 | break; | ||
6263 | case 17: /* if no 1tr6 cause, send full cause, else esc_cause */ | ||
6264 | dbug(1,dprintf("q9cau(0x%x)",ie[2])); | ||
6265 | if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */ | ||
6266 | Info_Number = 0x0008; | ||
6267 | Info_Mask = 0x01; | ||
6268 | if(cause[2] != ie[2]) Info_Element = cause; | ||
6269 | break; | ||
6270 | case 19: /* Redirected Number */ | ||
6271 | dbug(1,dprintf("RDN")); | ||
6272 | Info_Number = 0x0074; | ||
6273 | Info_Mask = 0x400; | ||
6274 | break; | ||
6275 | case 22: /* Redirecing Number */ | ||
6276 | dbug(1,dprintf("RIN")); | ||
6277 | Info_Number = 0x0076; | ||
6278 | Info_Mask = 0x400; | ||
6279 | break; | ||
6280 | case 23: /* Notification Indicator */ | ||
6281 | dbug(1,dprintf("NI")); | ||
6282 | Info_Number = (word)NI; | ||
6283 | Info_Mask = 0x210; | ||
6284 | break; | ||
6285 | case 26: /* Call State */ | ||
6286 | dbug(1,dprintf("CST")); | ||
6287 | Info_Number = (word)CST; | ||
6288 | Info_Mask = 0x01; /* do with cause i.e. for now */ | ||
6289 | break; | ||
6290 | case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */ | ||
6291 | dbug(1,dprintf("ESC/MT[0x%x]",ie[3])); | ||
6292 | Info_Number = 0x8000 |ie[3]; | ||
6293 | if(iesent) Info_Mask = 0xffff; | ||
6294 | else Info_Mask = 0x10; | ||
6295 | Info_Element = ""; | ||
6296 | break; | ||
6297 | default: | ||
6298 | Info_Number = 0; | ||
6299 | Info_Mask = 0; | ||
6300 | Info_Element = ""; | ||
6301 | break; | ||
6302 | } | ||
6303 | } | ||
6304 | |||
6305 | if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */ | ||
6306 | { | ||
6307 | for(j=0; j<max_appl; j++) | ||
6308 | { | ||
6309 | appl = &application[j]; | ||
6310 | if(Info_Number | ||
6311 | && appl->Id | ||
6312 | && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask) | ||
6313 | { | ||
6314 | dbug(1,dprintf("NCR_Ind")); | ||
6315 | iesent=TRUE; | ||
6316 | sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element); | ||
6317 | } | ||
6318 | } | ||
6319 | } | ||
6320 | else if(!plci->appl) | ||
6321 | { /* overlap receiving broadcast */ | ||
6322 | if(Info_Number==CPN | ||
6323 | || Info_Number==KEY | ||
6324 | || Info_Number==NI | ||
6325 | || Info_Number==DSP | ||
6326 | || Info_Number==UUI ) | ||
6327 | { | ||
6328 | for(j=0; j<max_appl; j++) | ||
6329 | { | ||
6330 | if(test_c_ind_mask_bit (plci, j)) | ||
6331 | { | ||
6332 | dbug(1,dprintf("Ovl_Ind")); | ||
6333 | iesent=TRUE; | ||
6334 | sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element); | ||
6335 | } | ||
6336 | } | ||
6337 | } | ||
6338 | } /* all other signalling states */ | ||
6339 | else if(Info_Number | ||
6340 | && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask) | ||
6341 | { | ||
6342 | dbug(1,dprintf("Std_Ind")); | ||
6343 | iesent=TRUE; | ||
6344 | sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element); | ||
6345 | } | ||
6346 | } | ||
6347 | } | ||
6348 | |||
6349 | |||
6350 | byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse) | ||
6351 | { | ||
6352 | word i; | ||
6353 | word j; | ||
6354 | byte * ie; | ||
6355 | word Info_Number; | ||
6356 | byte * Info_Element; | ||
6357 | APPL *appl; | ||
6358 | word Info_Mask = 0; | ||
6359 | byte iesent=0; | ||
6360 | |||
6361 | if( | ||
6362 | !plci->appl | ||
6363 | && !plci->State | ||
6364 | && plci->Sig.Ind!=NCR_FACILITY | ||
6365 | && !setupParse | ||
6366 | ) | ||
6367 | { | ||
6368 | dbug(1,dprintf("NoM-IEParse ")); | ||
6369 | return 0; | ||
6370 | } | ||
6371 | dbug(1,dprintf("M-IEParse ")); | ||
6372 | |||
6373 | for(i=0; i<MAX_MULTI_IE; i++) | ||
6374 | { | ||
6375 | ie = parms[i]; | ||
6376 | Info_Number = 0; | ||
6377 | Info_Element = ie; | ||
6378 | if(ie[0]) | ||
6379 | { | ||
6380 | dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type)); | ||
6381 | Info_Number = (word)ie_type; | ||
6382 | Info_Mask = (word)info_mask; | ||
6383 | } | ||
6384 | |||
6385 | if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */ | ||
6386 | { | ||
6387 | for(j=0; j<max_appl; j++) | ||
6388 | { | ||
6389 | appl = &application[j]; | ||
6390 | if(Info_Number | ||
6391 | && appl->Id | ||
6392 | && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask) | ||
6393 | { | ||
6394 | iesent = TRUE; | ||
6395 | dbug(1,dprintf("Mlt_NCR_Ind")); | ||
6396 | sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element); | ||
6397 | } | ||
6398 | } | ||
6399 | } | ||
6400 | else if(!plci->appl && Info_Number) | ||
6401 | { /* overlap receiving broadcast */ | ||
6402 | for(j=0; j<max_appl; j++) | ||
6403 | { | ||
6404 | if(test_c_ind_mask_bit (plci, j)) | ||
6405 | { | ||
6406 | iesent = TRUE; | ||
6407 | dbug(1,dprintf("Mlt_Ovl_Ind")); | ||
6408 | sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element); | ||
6409 | } | ||
6410 | } | ||
6411 | } /* all other signalling states */ | ||
6412 | else if(Info_Number | ||
6413 | && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask) | ||
6414 | { | ||
6415 | iesent = TRUE; | ||
6416 | dbug(1,dprintf("Mlt_Std_Ind")); | ||
6417 | sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element); | ||
6418 | } | ||
6419 | } | ||
6420 | return iesent; | ||
6421 | } | ||
6422 | |||
6423 | static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms) | ||
6424 | { | ||
6425 | word i; | ||
6426 | /* Format of multi_ssext_parms[i][]: | ||
6427 | 0 byte length | ||
6428 | 1 byte SSEXTIE | ||
6429 | 2 byte SSEXT_REQ/SSEXT_IND | ||
6430 | 3 byte length | ||
6431 | 4 word SSExtCommand | ||
6432 | 6... Params | ||
6433 | */ | ||
6434 | if( | ||
6435 | plci | ||
6436 | && plci->State | ||
6437 | && plci->Sig.Ind!=NCR_FACILITY | ||
6438 | ) | ||
6439 | for(i=0;i<MAX_MULTI_IE;i++) | ||
6440 | { | ||
6441 | if(parms[i][0]<6) continue; | ||
6442 | if(parms[i][2]==SSEXT_REQ) continue; | ||
6443 | |||
6444 | if(appl) | ||
6445 | { | ||
6446 | parms[i][0]=0; /* kill it */ | ||
6447 | sendf(appl,_MANUFACTURER_I, | ||
6448 | Id, | ||
6449 | 0, | ||
6450 | "dwS", | ||
6451 | _DI_MANU_ID, | ||
6452 | _DI_SSEXT_CTRL, | ||
6453 | &parms[i][3]); | ||
6454 | } | ||
6455 | else if(plci->appl) | ||
6456 | { | ||
6457 | parms[i][0]=0; /* kill it */ | ||
6458 | sendf(plci->appl,_MANUFACTURER_I, | ||
6459 | Id, | ||
6460 | 0, | ||
6461 | "dwS", | ||
6462 | _DI_MANU_ID, | ||
6463 | _DI_SSEXT_CTRL, | ||
6464 | &parms[i][3]); | ||
6465 | } | ||
6466 | } | ||
6467 | }; | ||
6468 | |||
6469 | void nl_ind(PLCI * plci) | ||
6470 | { | ||
6471 | byte ch; | ||
6472 | word ncci; | ||
6473 | dword Id; | ||
6474 | DIVA_CAPI_ADAPTER * a; | ||
6475 | word NCCIcode; | ||
6476 | APPL * APPLptr; | ||
6477 | word count; | ||
6478 | word Num; | ||
6479 | word i, ncpi_state; | ||
6480 | byte len, ncci_state; | ||
6481 | word msg; | ||
6482 | word info = 0; | ||
6483 | word fax_feature_bits; | ||
6484 | byte fax_send_edata_ack; | ||
6485 | static byte v120_header_buffer[2 + 3]; | ||
6486 | static word fax_info[] = { | ||
6487 | 0, /* T30_SUCCESS */ | ||
6488 | _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */ | ||
6489 | _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */ | ||
6490 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */ | ||
6491 | _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */ | ||
6492 | _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */ | ||
6493 | _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */ | ||
6494 | _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */ | ||
6495 | _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */ | ||
6496 | _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */ | ||
6497 | _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */ | ||
6498 | _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */ | ||
6499 | _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */ | ||
6500 | _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */ | ||
6501 | _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */ | ||
6502 | _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */ | ||
6503 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */ | ||
6504 | _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */ | ||
6505 | _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */ | ||
6506 | _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */ | ||
6507 | _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */ | ||
6508 | _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */ | ||
6509 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */ | ||
6510 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */ | ||
6511 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */ | ||
6512 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */ | ||
6513 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */ | ||
6514 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */ | ||
6515 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */ | ||
6516 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */ | ||
6517 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */ | ||
6518 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */ | ||
6519 | _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */ | ||
6520 | 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */ | ||
6521 | 0x331e, /* T30_ERR_PWD_UNSUPPORTED */ | ||
6522 | 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */ | ||
6523 | _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */ | ||
6524 | _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */ | ||
6525 | _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */ | ||
6526 | _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */ | ||
6527 | _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */ | ||
6528 | _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */ | ||
6529 | _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */ | ||
6530 | _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */ | ||
6531 | _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */ | ||
6532 | _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */ | ||
6533 | _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */ | ||
6534 | }; | ||
6535 | |||
6536 | byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1]; | ||
6537 | |||
6538 | |||
6539 | static word rtp_info[] = { | ||
6540 | GOOD, /* RTP_SUCCESS */ | ||
6541 | 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */ | ||
6542 | }; | ||
6543 | |||
6544 | static dword udata_forwarding_table[0x100 / sizeof(dword)] = | ||
6545 | { | ||
6546 | 0x0020301e, 0x00000000, 0x00000000, 0x00000000, | ||
6547 | 0x00000000, 0x00000000, 0x00000000, 0x00000000 | ||
6548 | }; | ||
6549 | |||
6550 | ch = plci->NL.IndCh; | ||
6551 | a = plci->adapter; | ||
6552 | ncci = a->ch_ncci[ch]; | ||
6553 | Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id; | ||
6554 | if(plci->tel) Id|=EXT_CONTROLLER; | ||
6555 | APPLptr = plci->appl; | ||
6556 | dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x", | ||
6557 | plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f)); | ||
6558 | |||
6559 | /* in the case if no connect_active_Ind was sent to the appl we wait for */ | ||
6560 | |||
6561 | if (plci->nl_remove_id) | ||
6562 | { | ||
6563 | plci->NL.RNR = 2; /* discard */ | ||
6564 | dbug(1,dprintf("NL discard while remove pending")); | ||
6565 | return; | ||
6566 | } | ||
6567 | if((plci->NL.Ind &0x0f)==N_CONNECT) | ||
6568 | { | ||
6569 | if(plci->State==INC_DIS_PENDING | ||
6570 | || plci->State==OUTG_DIS_PENDING | ||
6571 | || plci->State==IDLE) | ||
6572 | { | ||
6573 | plci->NL.RNR = 2; /* discard */ | ||
6574 | dbug(1,dprintf("discard n_connect")); | ||
6575 | return; | ||
6576 | } | ||
6577 | if(plci->State < INC_ACT_PENDING) | ||
6578 | { | ||
6579 | plci->NL.RNR = 1; /* flow control */ | ||
6580 | channel_x_off (plci, ch, N_XON_CONNECT_IND); | ||
6581 | return; | ||
6582 | } | ||
6583 | } | ||
6584 | |||
6585 | if(!APPLptr) /* no application or invalid data */ | ||
6586 | { /* while reloading the DSP */ | ||
6587 | dbug(1,dprintf("discard1")); | ||
6588 | plci->NL.RNR = 2; | ||
6589 | return; | ||
6590 | } | ||
6591 | |||
6592 | if (((plci->NL.Ind &0x0f) == N_UDATA) | ||
6593 | && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18))) | ||
6594 | || (plci->B2_prot == 7) | ||
6595 | || (plci->B3_prot == 7)) ) | ||
6596 | { | ||
6597 | plci->ncpi_buffer[0] = 0; | ||
6598 | |||
6599 | ncpi_state = plci->ncpi_state; | ||
6600 | if (plci->NL.complete == 1) | ||
6601 | { | ||
6602 | byte * data = &plci->NL.RBuffer->P[0]; | ||
6603 | |||
6604 | if ((plci->NL.RBuffer->length >= 12) | ||
6605 | &&( (*data == DSP_UDATA_INDICATION_DCD_ON) | ||
6606 | ||(*data == DSP_UDATA_INDICATION_CTS_ON)) ) | ||
6607 | { | ||
6608 | word conn_opt, ncpi_opt = 0x00; | ||
6609 | /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */ | ||
6610 | |||
6611 | if (*data == DSP_UDATA_INDICATION_DCD_ON) | ||
6612 | plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED; | ||
6613 | if (*data == DSP_UDATA_INDICATION_CTS_ON) | ||
6614 | plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED; | ||
6615 | |||
6616 | data++; /* indication code */ | ||
6617 | data += 2; /* timestamp */ | ||
6618 | if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN)) | ||
6619 | ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED); | ||
6620 | data++; /* connected norm */ | ||
6621 | conn_opt = GET_WORD(data); | ||
6622 | data += 2; /* connected options */ | ||
6623 | |||
6624 | PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF)); | ||
6625 | |||
6626 | if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42) | ||
6627 | { | ||
6628 | ncpi_opt |= MDM_NCPI_ECM_V42; | ||
6629 | } | ||
6630 | else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP) | ||
6631 | { | ||
6632 | ncpi_opt |= MDM_NCPI_ECM_MNP; | ||
6633 | } | ||
6634 | else | ||
6635 | { | ||
6636 | ncpi_opt |= MDM_NCPI_TRANSPARENT; | ||
6637 | } | ||
6638 | if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION) | ||
6639 | { | ||
6640 | ncpi_opt |= MDM_NCPI_COMPRESSED; | ||
6641 | } | ||
6642 | PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt); | ||
6643 | plci->ncpi_buffer[0] = 4; | ||
6644 | |||
6645 | plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND; | ||
6646 | } | ||
6647 | } | ||
6648 | if (plci->B3_prot == 7) | ||
6649 | { | ||
6650 | if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING)) | ||
6651 | && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
6652 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
6653 | { | ||
6654 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
6655 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | ||
6656 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
6657 | } | ||
6658 | } | ||
6659 | |||
6660 | if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | ||
6661 | & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN))) | ||
6662 | || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED) | ||
6663 | || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED)) | ||
6664 | |||
6665 | { | ||
6666 | plci->NL.RNR = 2; | ||
6667 | return; | ||
6668 | } | ||
6669 | } | ||
6670 | |||
6671 | if(plci->NL.complete == 2) | ||
6672 | { | ||
6673 | if (((plci->NL.Ind &0x0f) == N_UDATA) | ||
6674 | && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f)))) | ||
6675 | { | ||
6676 | switch(plci->RData[0].P[0]) | ||
6677 | { | ||
6678 | |||
6679 | case DTMF_UDATA_INDICATION_FAX_CALLING_TONE: | ||
6680 | if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG) | ||
6681 | sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X"); | ||
6682 | break; | ||
6683 | case DTMF_UDATA_INDICATION_ANSWER_TONE: | ||
6684 | if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG) | ||
6685 | sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y"); | ||
6686 | break; | ||
6687 | case DTMF_UDATA_INDICATION_DIGITS_RECEIVED: | ||
6688 | dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | ||
6689 | break; | ||
6690 | case DTMF_UDATA_INDICATION_DIGITS_SENT: | ||
6691 | dtmf_confirmation (Id, plci); | ||
6692 | break; | ||
6693 | |||
6694 | |||
6695 | case UDATA_INDICATION_MIXER_TAP_DATA: | ||
6696 | capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1)); | ||
6697 | i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1); | ||
6698 | if (i != 0) | ||
6699 | { | ||
6700 | dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED; | ||
6701 | dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1)); | ||
6702 | } | ||
6703 | break; | ||
6704 | |||
6705 | |||
6706 | case UDATA_INDICATION_MIXER_COEFS_SET: | ||
6707 | mixer_indication_coefs_set (Id, plci); | ||
6708 | break; | ||
6709 | case UDATA_INDICATION_XCONNECT_FROM: | ||
6710 | mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | ||
6711 | break; | ||
6712 | case UDATA_INDICATION_XCONNECT_TO: | ||
6713 | mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | ||
6714 | break; | ||
6715 | |||
6716 | |||
6717 | case LEC_UDATA_INDICATION_DISABLE_DETECT: | ||
6718 | ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength); | ||
6719 | break; | ||
6720 | |||
6721 | |||
6722 | |||
6723 | default: | ||
6724 | break; | ||
6725 | } | ||
6726 | } | ||
6727 | else | ||
6728 | { | ||
6729 | if ((plci->RData[0].PLength != 0) | ||
6730 | && ((plci->B2_prot == B2_V120_ASYNC) | ||
6731 | || (plci->B2_prot == B2_V120_ASYNC_V42BIS) | ||
6732 | || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))) | ||
6733 | { | ||
6734 | |||
6735 | sendf(plci->appl,_DATA_B3_I,Id,0, | ||
6736 | "dwww", | ||
6737 | plci->RData[1].P, | ||
6738 | (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength, | ||
6739 | plci->RNum, | ||
6740 | plci->RFlags); | ||
6741 | |||
6742 | } | ||
6743 | else | ||
6744 | { | ||
6745 | |||
6746 | sendf(plci->appl,_DATA_B3_I,Id,0, | ||
6747 | "dwww", | ||
6748 | plci->RData[0].P, | ||
6749 | plci->RData[0].PLength, | ||
6750 | plci->RNum, | ||
6751 | plci->RFlags); | ||
6752 | |||
6753 | } | ||
6754 | } | ||
6755 | return; | ||
6756 | } | ||
6757 | |||
6758 | fax_feature_bits = 0; | ||
6759 | if((plci->NL.Ind &0x0f)==N_CONNECT || | ||
6760 | (plci->NL.Ind &0x0f)==N_CONNECT_ACK || | ||
6761 | (plci->NL.Ind &0x0f)==N_DISC || | ||
6762 | (plci->NL.Ind &0x0f)==N_EDATA || | ||
6763 | (plci->NL.Ind &0x0f)==N_DISC_ACK) | ||
6764 | { | ||
6765 | info = 0; | ||
6766 | plci->ncpi_buffer[0] = 0; | ||
6767 | switch (plci->B3_prot) { | ||
6768 | case 0: /*XPARENT*/ | ||
6769 | case 1: /*T.90 NL*/ | ||
6770 | break; /* no network control protocol info - jfr */ | ||
6771 | case 2: /*ISO8202*/ | ||
6772 | case 3: /*X25 DCE*/ | ||
6773 | for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i]; | ||
6774 | plci->ncpi_buffer[0] = (byte)(i+3); | ||
6775 | plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0); | ||
6776 | plci->ncpi_buffer[2] = 0; | ||
6777 | plci->ncpi_buffer[3] = 0; | ||
6778 | break; | ||
6779 | case 4: /*T.30 - FAX*/ | ||
6780 | case 5: /*T.30 - FAX*/ | ||
6781 | if(plci->NL.RLength>=sizeof(T30_INFO)) | ||
6782 | { | ||
6783 | dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code)); | ||
6784 | len = 9; | ||
6785 | PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400); | ||
6786 | fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low); | ||
6787 | i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000; | ||
6788 | if (plci->B3_prot == 5) | ||
6789 | { | ||
6790 | if (!(fax_feature_bits & T30_FEATURE_BIT_ECM)) | ||
6791 | i |= 0x8000; /* This is not an ECM connection */ | ||
6792 | if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING) | ||
6793 | i |= 0x4000; /* This is a connection with MMR compression */ | ||
6794 | if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING) | ||
6795 | i |= 0x2000; /* This is a connection with MR compression */ | ||
6796 | if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS) | ||
6797 | i |= 0x0004; /* More documents */ | ||
6798 | if (fax_feature_bits & T30_FEATURE_BIT_POLLING) | ||
6799 | i |= 0x0002; /* Fax-polling indication */ | ||
6800 | } | ||
6801 | dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i)); | ||
6802 | PUT_WORD(&(plci->ncpi_buffer[3]),i); | ||
6803 | PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format); | ||
6804 | plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low; | ||
6805 | plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high; | ||
6806 | plci->ncpi_buffer[len] = 0; | ||
6807 | if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len) | ||
6808 | { | ||
6809 | plci->ncpi_buffer[len] = 20; | ||
6810 | for (i = 0; i < 20; i++) | ||
6811 | plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i]; | ||
6812 | } | ||
6813 | if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) | ||
6814 | { | ||
6815 | if (((T30_INFO *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0])) | ||
6816 | info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code]; | ||
6817 | else | ||
6818 | info = _FAX_PROTOCOL_ERROR; | ||
6819 | } | ||
6820 | |||
6821 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | ||
6822 | & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | ||
6823 | { | ||
6824 | i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; | ||
6825 | while (i < plci->NL.RBuffer->length) | ||
6826 | plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++]; | ||
6827 | } | ||
6828 | |||
6829 | plci->ncpi_buffer[0] = len; | ||
6830 | fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low); | ||
6831 | PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits); | ||
6832 | |||
6833 | plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND; | ||
6834 | if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK) | ||
6835 | || (((plci->NL.Ind &0x0f) == N_CONNECT) | ||
6836 | && (fax_feature_bits & T30_FEATURE_BIT_POLLING)) | ||
6837 | || (((plci->NL.Ind &0x0f) == N_EDATA) | ||
6838 | && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK) | ||
6839 | || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS) | ||
6840 | || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC)))) | ||
6841 | { | ||
6842 | plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT; | ||
6843 | } | ||
6844 | if (((plci->NL.Ind &0x0f) == N_DISC) | ||
6845 | || ((plci->NL.Ind &0x0f) == N_DISC_ACK) | ||
6846 | || (((plci->NL.Ind &0x0f) == N_EDATA) | ||
6847 | && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI))) | ||
6848 | { | ||
6849 | plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND; | ||
6850 | } | ||
6851 | } | ||
6852 | break; | ||
6853 | |||
6854 | case B3_RTP: | ||
6855 | if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) | ||
6856 | { | ||
6857 | if (plci->NL.RLength != 0) | ||
6858 | { | ||
6859 | info = rtp_info[plci->NL.RBuffer->P[0]]; | ||
6860 | plci->ncpi_buffer[0] = plci->NL.RLength - 1; | ||
6861 | for (i = 1; i < plci->NL.RLength; i++) | ||
6862 | plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i]; | ||
6863 | } | ||
6864 | } | ||
6865 | break; | ||
6866 | |||
6867 | } | ||
6868 | plci->NL.RNR = 2; | ||
6869 | } | ||
6870 | switch(plci->NL.Ind &0x0f) { | ||
6871 | case N_EDATA: | ||
6872 | if ((plci->B3_prot == 4) || (plci->B3_prot == 5)) | ||
6873 | { | ||
6874 | dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci], | ||
6875 | ((T30_INFO *)plci->NL.RBuffer->P)->code)); | ||
6876 | fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG); | ||
6877 | |||
6878 | if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | ||
6879 | && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | ||
6880 | && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS) | ||
6881 | && (a->ncci_state[ncci] == OUTG_CON_PENDING) | ||
6882 | && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
6883 | && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT)) | ||
6884 | { | ||
6885 | ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code; | ||
6886 | sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3, | ||
6887 | (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer); | ||
6888 | plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT; | ||
6889 | if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP) | ||
6890 | fax_send_edata_ack = FALSE; | ||
6891 | } | ||
6892 | |||
6893 | if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | ||
6894 | { | ||
6895 | switch (((T30_INFO *)plci->NL.RBuffer->P)->code) | ||
6896 | { | ||
6897 | case EDATA_T30_DIS: | ||
6898 | if ((a->ncci_state[ncci] == OUTG_CON_PENDING) | ||
6899 | && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING) | ||
6900 | && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
6901 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
6902 | { | ||
6903 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
6904 | if (plci->B3_prot == 4) | ||
6905 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
6906 | else | ||
6907 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | ||
6908 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
6909 | } | ||
6910 | break; | ||
6911 | |||
6912 | case EDATA_T30_TRAIN_OK: | ||
6913 | if ((a->ncci_state[ncci] == INC_ACT_PENDING) | ||
6914 | && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
6915 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
6916 | { | ||
6917 | if (plci->B3_prot == 4) | ||
6918 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
6919 | else | ||
6920 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | ||
6921 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
6922 | } | ||
6923 | break; | ||
6924 | |||
6925 | case EDATA_T30_EOP_CAPI: | ||
6926 | if (a->ncci_state[ncci] == CONNECTED) | ||
6927 | { | ||
6928 | sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer); | ||
6929 | a->ncci_state[ncci] = INC_DIS_PENDING; | ||
6930 | plci->ncpi_state = 0; | ||
6931 | fax_send_edata_ack = FALSE; | ||
6932 | } | ||
6933 | break; | ||
6934 | } | ||
6935 | } | ||
6936 | else | ||
6937 | { | ||
6938 | switch (((T30_INFO *)plci->NL.RBuffer->P)->code) | ||
6939 | { | ||
6940 | case EDATA_T30_TRAIN_OK: | ||
6941 | if ((a->ncci_state[ncci] == INC_ACT_PENDING) | ||
6942 | && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
6943 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
6944 | { | ||
6945 | if (plci->B3_prot == 4) | ||
6946 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
6947 | else | ||
6948 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | ||
6949 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
6950 | } | ||
6951 | break; | ||
6952 | } | ||
6953 | } | ||
6954 | if (fax_send_edata_ack) | ||
6955 | { | ||
6956 | ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code; | ||
6957 | plci->fax_edata_ack_length = 1; | ||
6958 | start_internal_command (Id, plci, fax_edata_ack_command); | ||
6959 | } | ||
6960 | } | ||
6961 | else | ||
6962 | { | ||
6963 | dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci])); | ||
6964 | } | ||
6965 | break; | ||
6966 | case N_CONNECT: | ||
6967 | if (!a->ch_ncci[ch]) | ||
6968 | { | ||
6969 | ncci = get_ncci (plci, ch, 0); | ||
6970 | Id = (Id & 0xffff) | (((dword) ncci) << 16); | ||
6971 | } | ||
6972 | dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d", | ||
6973 | ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State)); | ||
6974 | |||
6975 | msg = _CONNECT_B3_I; | ||
6976 | if (a->ncci_state[ncci] == IDLE) | ||
6977 | plci->channels++; | ||
6978 | else if (plci->B3_prot == 1) | ||
6979 | msg = _CONNECT_B3_T90_ACTIVE_I; | ||
6980 | |||
6981 | a->ncci_state[ncci] = INC_CON_PENDING; | ||
6982 | if(plci->B3_prot == 4) | ||
6983 | sendf(plci->appl,msg,Id,0,"s",""); | ||
6984 | else | ||
6985 | sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | ||
6986 | break; | ||
6987 | case N_CONNECT_ACK: | ||
6988 | dbug(1,dprintf("N_connect_Ack")); | ||
6989 | if (plci->internal_command_queue[0] | ||
6990 | && ((plci->adjust_b_state == ADJUST_B_CONNECT_2) | ||
6991 | || (plci->adjust_b_state == ADJUST_B_CONNECT_3) | ||
6992 | || (plci->adjust_b_state == ADJUST_B_CONNECT_4))) | ||
6993 | { | ||
6994 | (*(plci->internal_command_queue[0]))(Id, plci, 0); | ||
6995 | if (!plci->internal_command) | ||
6996 | next_internal_command (Id, plci); | ||
6997 | break; | ||
6998 | } | ||
6999 | msg = _CONNECT_B3_ACTIVE_I; | ||
7000 | if (plci->B3_prot == 1) | ||
7001 | { | ||
7002 | if (a->ncci_state[ncci] != OUTG_CON_PENDING) | ||
7003 | msg = _CONNECT_B3_T90_ACTIVE_I; | ||
7004 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
7005 | sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | ||
7006 | } | ||
7007 | else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7)) | ||
7008 | { | ||
7009 | if ((a->ncci_state[ncci] == OUTG_CON_PENDING) | ||
7010 | && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
7011 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
7012 | { | ||
7013 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
7014 | if (plci->B3_prot == 4) | ||
7015 | sendf(plci->appl,msg,Id,0,"s",""); | ||
7016 | else | ||
7017 | sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | ||
7018 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
7019 | } | ||
7020 | } | ||
7021 | else | ||
7022 | { | ||
7023 | a->ncci_state[ncci] = INC_ACT_PENDING; | ||
7024 | sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer); | ||
7025 | } | ||
7026 | if (plci->adjust_b_restore) | ||
7027 | { | ||
7028 | plci->adjust_b_restore = FALSE; | ||
7029 | start_internal_command (Id, plci, adjust_b_restore); | ||
7030 | } | ||
7031 | break; | ||
7032 | case N_DISC: | ||
7033 | case N_DISC_ACK: | ||
7034 | if (plci->internal_command_queue[0] | ||
7035 | && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1) | ||
7036 | || (plci->internal_command == FAX_DISCONNECT_COMMAND_2) | ||
7037 | || (plci->internal_command == FAX_DISCONNECT_COMMAND_3))) | ||
7038 | { | ||
7039 | (*(plci->internal_command_queue[0]))(Id, plci, 0); | ||
7040 | if (!plci->internal_command) | ||
7041 | next_internal_command (Id, plci); | ||
7042 | } | ||
7043 | ncci_state = a->ncci_state[ncci]; | ||
7044 | ncci_remove (plci, ncci, FALSE); | ||
7045 | |||
7046 | /* with N_DISC or N_DISC_ACK the IDI frees the respective */ | ||
7047 | /* channel, so we cannot store the state in ncci_state! The */ | ||
7048 | /* information which channel we received a N_DISC is thus */ | ||
7049 | /* stored in the inc_dis_ncci_table buffer. */ | ||
7050 | for(i=0; plci->inc_dis_ncci_table[i]; i++); | ||
7051 | plci->inc_dis_ncci_table[i] = (byte) ncci; | ||
7052 | |||
7053 | /* need a connect_b3_ind before a disconnect_b3_ind with FAX */ | ||
7054 | if (!plci->channels | ||
7055 | && (plci->B1_resource == 16) | ||
7056 | && (plci->State <= CONNECTED)) | ||
7057 | { | ||
7058 | len = 9; | ||
7059 | i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400; | ||
7060 | PUT_WORD (&plci->ncpi_buffer[1], i); | ||
7061 | PUT_WORD (&plci->ncpi_buffer[3], 0); | ||
7062 | i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format; | ||
7063 | PUT_WORD (&plci->ncpi_buffer[5], i); | ||
7064 | PUT_WORD (&plci->ncpi_buffer[7], 0); | ||
7065 | plci->ncpi_buffer[len] = 0; | ||
7066 | plci->ncpi_buffer[0] = len; | ||
7067 | if(plci->B3_prot == 4) | ||
7068 | sendf(plci->appl,_CONNECT_B3_I,Id,0,"s",""); | ||
7069 | else | ||
7070 | { | ||
7071 | |||
7072 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | ||
7073 | & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | ||
7074 | { | ||
7075 | plci->ncpi_buffer[++len] = 0; | ||
7076 | plci->ncpi_buffer[++len] = 0; | ||
7077 | plci->ncpi_buffer[++len] = 0; | ||
7078 | plci->ncpi_buffer[0] = len; | ||
7079 | } | ||
7080 | |||
7081 | sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer); | ||
7082 | } | ||
7083 | sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer); | ||
7084 | plci->ncpi_state = 0; | ||
7085 | sig_req(plci,HANGUP,0); | ||
7086 | send_req(plci); | ||
7087 | plci->State = OUTG_DIS_PENDING; | ||
7088 | /* disc here */ | ||
7089 | } | ||
7090 | else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | ||
7091 | && ((plci->B3_prot == 4) || (plci->B3_prot == 5)) | ||
7092 | && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE))) | ||
7093 | { | ||
7094 | if (ncci_state == IDLE) | ||
7095 | { | ||
7096 | if (plci->channels) | ||
7097 | plci->channels--; | ||
7098 | if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){ | ||
7099 | if(plci->State == SUSPENDING){ | ||
7100 | sendf(plci->appl, | ||
7101 | _FACILITY_I, | ||
7102 | Id & 0xffffL, | ||
7103 | 0, | ||
7104 | "ws", (word)3, "\x03\x04\x00\x00"); | ||
7105 | sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0); | ||
7106 | } | ||
7107 | plci_remove(plci); | ||
7108 | plci->State=IDLE; | ||
7109 | } | ||
7110 | } | ||
7111 | } | ||
7112 | else if (plci->channels) | ||
7113 | { | ||
7114 | sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer); | ||
7115 | plci->ncpi_state = 0; | ||
7116 | if ((ncci_state == OUTG_REJ_PENDING) | ||
7117 | && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))) | ||
7118 | { | ||
7119 | sig_req(plci,HANGUP,0); | ||
7120 | send_req(plci); | ||
7121 | plci->State = OUTG_DIS_PENDING; | ||
7122 | } | ||
7123 | } | ||
7124 | break; | ||
7125 | case N_RESET: | ||
7126 | a->ncci_state[ncci] = INC_RES_PENDING; | ||
7127 | sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer); | ||
7128 | break; | ||
7129 | case N_RESET_ACK: | ||
7130 | a->ncci_state[ncci] = CONNECTED; | ||
7131 | sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer); | ||
7132 | break; | ||
7133 | |||
7134 | case N_UDATA: | ||
7135 | if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f)))) | ||
7136 | { | ||
7137 | plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3); | ||
7138 | plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE; | ||
7139 | plci->NL.R = plci->RData; | ||
7140 | plci->NL.RNum = 1; | ||
7141 | return; | ||
7142 | } | ||
7143 | case N_BDATA: | ||
7144 | case N_DATA: | ||
7145 | if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */ | ||
7146 | || (a->ncci_state[ncci] == IDLE) | ||
7147 | || (a->ncci_state[ncci] == INC_DIS_PENDING)) | ||
7148 | { | ||
7149 | plci->NL.RNR = 2; | ||
7150 | break; | ||
7151 | } | ||
7152 | if ((a->ncci_state[ncci] != CONNECTED) | ||
7153 | && (a->ncci_state[ncci] != OUTG_DIS_PENDING) | ||
7154 | && (a->ncci_state[ncci] != OUTG_REJ_PENDING)) | ||
7155 | { | ||
7156 | dbug(1,dprintf("flow control")); | ||
7157 | plci->NL.RNR = 1; /* flow control */ | ||
7158 | channel_x_off (plci, ch, 0); | ||
7159 | break; | ||
7160 | } | ||
7161 | |||
7162 | NCCIcode = ncci | (((word)a->Id) << 8); | ||
7163 | |||
7164 | /* count all buffers within the Application pool */ | ||
7165 | /* belonging to the same NCCI. If this is below the */ | ||
7166 | /* number of buffers available per NCCI we accept */ | ||
7167 | /* this packet, otherwise we reject it */ | ||
7168 | count = 0; | ||
7169 | Num = 0xffff; | ||
7170 | for(i=0; i<APPLptr->MaxBuffer; i++) { | ||
7171 | if(NCCIcode==APPLptr->DataNCCI[i]) count++; | ||
7172 | if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i; | ||
7173 | } | ||
7174 | |||
7175 | if(count>=APPLptr->MaxNCCIData || Num==0xffff) | ||
7176 | { | ||
7177 | dbug(3,dprintf("Flow-Control")); | ||
7178 | plci->NL.RNR = 1; | ||
7179 | if( ++(APPLptr->NCCIDataFlowCtrlTimer)>= | ||
7180 | (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000)) | ||
7181 | { | ||
7182 | plci->NL.RNR = 2; | ||
7183 | dbug(3,dprintf("DiscardData")); | ||
7184 | } else { | ||
7185 | channel_x_off (plci, ch, 0); | ||
7186 | } | ||
7187 | break; | ||
7188 | } | ||
7189 | else | ||
7190 | { | ||
7191 | APPLptr->NCCIDataFlowCtrlTimer = 0; | ||
7192 | } | ||
7193 | |||
7194 | plci->RData[0].P = ReceiveBufferGet(APPLptr,Num); | ||
7195 | if(!plci->RData[0].P) { | ||
7196 | plci->NL.RNR = 1; | ||
7197 | channel_x_off (plci, ch, 0); | ||
7198 | break; | ||
7199 | } | ||
7200 | |||
7201 | APPLptr->DataNCCI[Num] = NCCIcode; | ||
7202 | APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4); | ||
7203 | dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer)); | ||
7204 | |||
7205 | plci->RNum = Num; | ||
7206 | plci->RFlags = plci->NL.Ind>>4; | ||
7207 | plci->RData[0].PLength = APPLptr->MaxDataLength; | ||
7208 | plci->NL.R = plci->RData; | ||
7209 | if ((plci->NL.RLength != 0) | ||
7210 | && ((plci->B2_prot == B2_V120_ASYNC) | ||
7211 | || (plci->B2_prot == B2_V120_ASYNC_V42BIS) | ||
7212 | || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))) | ||
7213 | { | ||
7214 | plci->RData[1].P = plci->RData[0].P; | ||
7215 | plci->RData[1].PLength = plci->RData[0].PLength; | ||
7216 | plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3); | ||
7217 | if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1)) | ||
7218 | plci->RData[0].PLength = 1; | ||
7219 | else | ||
7220 | plci->RData[0].PLength = 2; | ||
7221 | if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT) | ||
7222 | plci->RFlags |= 0x0010; | ||
7223 | if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)) | ||
7224 | plci->RFlags |= 0x8000; | ||
7225 | plci->NL.RNum = 2; | ||
7226 | } | ||
7227 | else | ||
7228 | { | ||
7229 | if((plci->NL.Ind &0x0f)==N_UDATA) | ||
7230 | plci->RFlags |= 0x0010; | ||
7231 | |||
7232 | else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA)) | ||
7233 | plci->RFlags |= 0x0001; | ||
7234 | |||
7235 | plci->NL.RNum = 1; | ||
7236 | } | ||
7237 | break; | ||
7238 | case N_DATA_ACK: | ||
7239 | data_ack (plci, ch); | ||
7240 | break; | ||
7241 | default: | ||
7242 | plci->NL.RNR = 2; | ||
7243 | break; | ||
7244 | } | ||
7245 | } | ||
7246 | |||
7247 | /*------------------------------------------------------------------*/ | ||
7248 | /* find a free PLCI */ | ||
7249 | /*------------------------------------------------------------------*/ | ||
7250 | |||
7251 | word get_plci(DIVA_CAPI_ADAPTER * a) | ||
7252 | { | ||
7253 | word i,j; | ||
7254 | PLCI * plci; | ||
7255 | |||
7256 | dump_plcis (a); | ||
7257 | for(i=0;i<a->max_plci && a->plci[i].Id;i++); | ||
7258 | if(i==a->max_plci) { | ||
7259 | dbug(1,dprintf("get_plci: out of PLCIs")); | ||
7260 | return 0; | ||
7261 | } | ||
7262 | plci = &a->plci[i]; | ||
7263 | plci->Id = (byte)(i+1); | ||
7264 | |||
7265 | plci->Sig.Id = 0; | ||
7266 | plci->NL.Id = 0; | ||
7267 | plci->sig_req = 0; | ||
7268 | plci->nl_req = 0; | ||
7269 | |||
7270 | plci->appl = NULL; | ||
7271 | plci->relatedPTYPLCI = NULL; | ||
7272 | plci->State = IDLE; | ||
7273 | plci->SuppState = IDLE; | ||
7274 | plci->channels = 0; | ||
7275 | plci->tel = 0; | ||
7276 | plci->B1_resource = 0; | ||
7277 | plci->B2_prot = 0; | ||
7278 | plci->B3_prot = 0; | ||
7279 | |||
7280 | plci->command = 0; | ||
7281 | plci->m_command = 0; | ||
7282 | init_internal_command_queue (plci); | ||
7283 | plci->number = 0; | ||
7284 | plci->req_in_start = 0; | ||
7285 | plci->req_in = 0; | ||
7286 | plci->req_out = 0; | ||
7287 | plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE; | ||
7288 | plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE; | ||
7289 | plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE; | ||
7290 | |||
7291 | plci->data_sent = FALSE; | ||
7292 | plci->send_disc = 0; | ||
7293 | plci->sig_global_req = 0; | ||
7294 | plci->sig_remove_id = 0; | ||
7295 | plci->nl_global_req = 0; | ||
7296 | plci->nl_remove_id = 0; | ||
7297 | plci->adv_nl = 0; | ||
7298 | plci->manufacturer = FALSE; | ||
7299 | plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE; | ||
7300 | plci->spoofed_msg = 0; | ||
7301 | plci->ptyState = 0; | ||
7302 | plci->cr_enquiry = FALSE; | ||
7303 | plci->hangup_flow_ctrl_timer = 0; | ||
7304 | |||
7305 | plci->ncci_ring_list = 0; | ||
7306 | for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0; | ||
7307 | clear_c_ind_mask (plci); | ||
7308 | set_group_ind_mask (plci); | ||
7309 | plci->fax_connect_info_length = 0; | ||
7310 | plci->nsf_control_bits = 0; | ||
7311 | plci->ncpi_state = 0x00; | ||
7312 | plci->ncpi_buffer[0] = 0; | ||
7313 | |||
7314 | plci->requested_options_conn = 0; | ||
7315 | plci->requested_options = 0; | ||
7316 | plci->notifiedcall = 0; | ||
7317 | plci->vswitchstate = 0; | ||
7318 | plci->vsprot = 0; | ||
7319 | plci->vsprotdialect = 0; | ||
7320 | init_b1_config (plci); | ||
7321 | dbug(1,dprintf("get_plci(%x)",plci->Id)); | ||
7322 | return i+1; | ||
7323 | } | ||
7324 | |||
7325 | /*------------------------------------------------------------------*/ | ||
7326 | /* put a parameter in the parameter buffer */ | ||
7327 | /*------------------------------------------------------------------*/ | ||
7328 | |||
7329 | static void add_p(PLCI * plci, byte code, byte * p) | ||
7330 | { | ||
7331 | word p_length; | ||
7332 | |||
7333 | p_length = 0; | ||
7334 | if(p) p_length = p[0]; | ||
7335 | add_ie(plci, code, p, p_length); | ||
7336 | } | ||
7337 | |||
7338 | /*------------------------------------------------------------------*/ | ||
7339 | /* put a structure in the parameter buffer */ | ||
7340 | /*------------------------------------------------------------------*/ | ||
7341 | static void add_s(PLCI * plci, byte code, API_PARSE * p) | ||
7342 | { | ||
7343 | if(p) add_ie(plci, code, p->info, (word)p->length); | ||
7344 | } | ||
7345 | |||
7346 | /*------------------------------------------------------------------*/ | ||
7347 | /* put multiple structures in the parameter buffer */ | ||
7348 | /*------------------------------------------------------------------*/ | ||
7349 | static void add_ss(PLCI * plci, byte code, API_PARSE * p) | ||
7350 | { | ||
7351 | byte i; | ||
7352 | |||
7353 | if(p){ | ||
7354 | dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length)); | ||
7355 | for(i=2;i<(byte)p->length;i+=p->info[i]+2){ | ||
7356 | dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i])); | ||
7357 | add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]); | ||
7358 | } | ||
7359 | } | ||
7360 | } | ||
7361 | |||
7362 | /*------------------------------------------------------------------*/ | ||
7363 | /* return the channel number sent by the application in a esc_chi */ | ||
7364 | /*------------------------------------------------------------------*/ | ||
7365 | static byte getChannel(API_PARSE * p) | ||
7366 | { | ||
7367 | byte i; | ||
7368 | |||
7369 | if(p){ | ||
7370 | for(i=2;i<(byte)p->length;i+=p->info[i]+2){ | ||
7371 | if(p->info[i]==2){ | ||
7372 | if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]); | ||
7373 | } | ||
7374 | } | ||
7375 | } | ||
7376 | return 0; | ||
7377 | } | ||
7378 | |||
7379 | |||
7380 | /*------------------------------------------------------------------*/ | ||
7381 | /* put an information element in the parameter buffer */ | ||
7382 | /*------------------------------------------------------------------*/ | ||
7383 | |||
7384 | static void add_ie(PLCI * plci, byte code, byte * p, word p_length) | ||
7385 | { | ||
7386 | word i; | ||
7387 | |||
7388 | if(!(code &0x80) && !p_length) return; | ||
7389 | |||
7390 | if(plci->req_in==plci->req_in_start) { | ||
7391 | plci->req_in +=2; | ||
7392 | } | ||
7393 | else { | ||
7394 | plci->req_in--; | ||
7395 | } | ||
7396 | plci->RBuffer[plci->req_in++] = code; | ||
7397 | |||
7398 | if(p) { | ||
7399 | plci->RBuffer[plci->req_in++] = (byte)p_length; | ||
7400 | for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i]; | ||
7401 | } | ||
7402 | |||
7403 | plci->RBuffer[plci->req_in++] = 0; | ||
7404 | } | ||
7405 | |||
7406 | /*------------------------------------------------------------------*/ | ||
7407 | /* put a unstructured data into the buffer */ | ||
7408 | /*------------------------------------------------------------------*/ | ||
7409 | |||
7410 | void add_d(PLCI * plci, word length, byte * p) | ||
7411 | { | ||
7412 | word i; | ||
7413 | |||
7414 | if(plci->req_in==plci->req_in_start) { | ||
7415 | plci->req_in +=2; | ||
7416 | } | ||
7417 | else { | ||
7418 | plci->req_in--; | ||
7419 | } | ||
7420 | for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i]; | ||
7421 | } | ||
7422 | |||
7423 | /*------------------------------------------------------------------*/ | ||
7424 | /* put parameters from the Additional Info parameter in the */ | ||
7425 | /* parameter buffer */ | ||
7426 | /*------------------------------------------------------------------*/ | ||
7427 | |||
7428 | void add_ai(PLCI * plci, API_PARSE * ai) | ||
7429 | { | ||
7430 | word i; | ||
7431 | API_PARSE ai_parms[5]; | ||
7432 | |||
7433 | for(i=0;i<5;i++) ai_parms[i].length = 0; | ||
7434 | |||
7435 | if(!ai->length) | ||
7436 | return; | ||
7437 | if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms)) | ||
7438 | return; | ||
7439 | |||
7440 | add_s (plci,KEY,&ai_parms[1]); | ||
7441 | add_s (plci,UUI,&ai_parms[2]); | ||
7442 | add_ss(plci,FTY,&ai_parms[3]); | ||
7443 | } | ||
7444 | |||
7445 | /*------------------------------------------------------------------*/ | ||
7446 | /* put parameter for b1 protocol in the parameter buffer */ | ||
7447 | /*------------------------------------------------------------------*/ | ||
7448 | |||
7449 | word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_facilities) | ||
7450 | { | ||
7451 | API_PARSE bp_parms[8]; | ||
7452 | API_PARSE mdm_cfg[9]; | ||
7453 | API_PARSE global_config[2]; | ||
7454 | byte cai[256]; | ||
7455 | byte resource[] = {5,9,13,12,16,39,9,17,17,18}; | ||
7456 | byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08"; | ||
7457 | word i; | ||
7458 | |||
7459 | API_PARSE mdm_cfg_v18[4]; | ||
7460 | word j, n, w; | ||
7461 | dword d; | ||
7462 | |||
7463 | |||
7464 | for(i=0;i<8;i++) bp_parms[i].length = 0; | ||
7465 | for(i=0;i<2;i++) global_config[i].length = 0; | ||
7466 | |||
7467 | dbug(1,dprintf("add_b1")); | ||
7468 | api_save_msg(bp, "s", &plci->B_protocol); | ||
7469 | |||
7470 | if(b_channel_info==2){ | ||
7471 | plci->B1_resource = 0; | ||
7472 | adjust_b1_facilities (plci, plci->B1_resource, b1_facilities); | ||
7473 | add_p(plci, CAI, "\x01\x00"); | ||
7474 | dbug(1,dprintf("Cai=1,0 (no resource)")); | ||
7475 | return 0; | ||
7476 | } | ||
7477 | |||
7478 | if(plci->tel == CODEC_PERMANENT) return 0; | ||
7479 | else if(plci->tel == CODEC){ | ||
7480 | plci->B1_resource = 1; | ||
7481 | adjust_b1_facilities (plci, plci->B1_resource, b1_facilities); | ||
7482 | add_p(plci, CAI, "\x01\x01"); | ||
7483 | dbug(1,dprintf("Cai=1,1 (Codec)")); | ||
7484 | return 0; | ||
7485 | } | ||
7486 | else if(plci->tel == ADV_VOICE){ | ||
7487 | plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE)); | ||
7488 | adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE)); | ||
7489 | voice_cai[1] = plci->B1_resource; | ||
7490 | PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength); | ||
7491 | add_p(plci, CAI, voice_cai); | ||
7492 | dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1])); | ||
7493 | return 0; | ||
7494 | } | ||
7495 | plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER); | ||
7496 | if (plci->call_dir & CALL_DIR_OUT) | ||
7497 | plci->call_dir |= CALL_DIR_ORIGINATE; | ||
7498 | else if (plci->call_dir & CALL_DIR_IN) | ||
7499 | plci->call_dir |= CALL_DIR_ANSWER; | ||
7500 | |||
7501 | if(!bp->length){ | ||
7502 | plci->B1_resource = 0x5; | ||
7503 | adjust_b1_facilities (plci, plci->B1_resource, b1_facilities); | ||
7504 | add_p(plci, CAI, "\x01\x05"); | ||
7505 | return 0; | ||
7506 | } | ||
7507 | |||
7508 | dbug(1,dprintf("b_prot_len=%d",(word)bp->length)); | ||
7509 | if(bp->length>256) return _WRONG_MESSAGE_FORMAT; | ||
7510 | if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms)) | ||
7511 | { | ||
7512 | bp_parms[6].length = 0; | ||
7513 | if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms)) | ||
7514 | { | ||
7515 | dbug(1,dprintf("b-form.!")); | ||
7516 | return _WRONG_MESSAGE_FORMAT; | ||
7517 | } | ||
7518 | } | ||
7519 | else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms)) | ||
7520 | { | ||
7521 | dbug(1,dprintf("b-form.!")); | ||
7522 | return _WRONG_MESSAGE_FORMAT; | ||
7523 | } | ||
7524 | |||
7525 | if(bp_parms[6].length) | ||
7526 | { | ||
7527 | if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config)) | ||
7528 | { | ||
7529 | return _WRONG_MESSAGE_FORMAT; | ||
7530 | } | ||
7531 | switch(GET_WORD(global_config[0].info)) | ||
7532 | { | ||
7533 | case 1: | ||
7534 | plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE; | ||
7535 | break; | ||
7536 | case 2: | ||
7537 | plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER; | ||
7538 | break; | ||
7539 | } | ||
7540 | } | ||
7541 | dbug(1,dprintf("call_dir=%04x", plci->call_dir)); | ||
7542 | |||
7543 | |||
7544 | if ((GET_WORD(bp_parms[0].info) == B1_RTP) | ||
7545 | && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP))) | ||
7546 | { | ||
7547 | plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | ||
7548 | adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | ||
7549 | cai[1] = plci->B1_resource; | ||
7550 | cai[2] = 0; | ||
7551 | cai[3] = 0; | ||
7552 | cai[4] = 0; | ||
7553 | PUT_WORD(&cai[5],plci->appl->MaxDataLength); | ||
7554 | for (i = 0; i < bp_parms[3].length; i++) | ||
7555 | cai[7+i] = bp_parms[3].info[1+i]; | ||
7556 | cai[0] = 6 + bp_parms[3].length; | ||
7557 | add_p(plci, CAI, cai); | ||
7558 | return 0; | ||
7559 | } | ||
7560 | |||
7561 | |||
7562 | if ((GET_WORD(bp_parms[0].info) == B1_PIAFS) | ||
7563 | && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS))) | ||
7564 | { | ||
7565 | plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | ||
7566 | adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | ||
7567 | cai[1] = plci->B1_resource; | ||
7568 | cai[2] = 0; | ||
7569 | cai[3] = 0; | ||
7570 | cai[4] = 0; | ||
7571 | PUT_WORD(&cai[5],plci->appl->MaxDataLength); | ||
7572 | cai[0] = 6; | ||
7573 | add_p(plci, CAI, cai); | ||
7574 | return 0; | ||
7575 | } | ||
7576 | |||
7577 | |||
7578 | if ((GET_WORD(bp_parms[0].info) >= 32) | ||
7579 | || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols) | ||
7580 | && ((GET_WORD(bp_parms[0].info) != 3) | ||
7581 | || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols) | ||
7582 | || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000))))) | ||
7583 | { | ||
7584 | return _B1_NOT_SUPPORTED; | ||
7585 | } | ||
7586 | plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)], | ||
7587 | (word)(b1_facilities & ~B1_FACILITY_VOICE)); | ||
7588 | adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); | ||
7589 | cai[0] = 6; | ||
7590 | cai[1] = plci->B1_resource; | ||
7591 | for (i=2;i<sizeof(cai);i++) cai[i] = 0; | ||
7592 | |||
7593 | if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) | ||
7594 | || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC) | ||
7595 | || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)) | ||
7596 | { /* B1 - modem */ | ||
7597 | for (i=0;i<7;i++) mdm_cfg[i].length = 0; | ||
7598 | |||
7599 | if (bp_parms[3].length) | ||
7600 | { | ||
7601 | if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg)) | ||
7602 | { | ||
7603 | return (_WRONG_MESSAGE_FORMAT); | ||
7604 | } | ||
7605 | |||
7606 | cai[2] = 0; /* Bit rate for adaptation */ | ||
7607 | |||
7608 | dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info))); | ||
7609 | |||
7610 | PUT_WORD (&cai[13], 0); /* Min Tx speed */ | ||
7611 | PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */ | ||
7612 | PUT_WORD (&cai[17], 0); /* Min Rx speed */ | ||
7613 | PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */ | ||
7614 | |||
7615 | cai[3] = 0; /* Async framing parameters */ | ||
7616 | switch (GET_WORD (mdm_cfg[2].info)) | ||
7617 | { /* Parity */ | ||
7618 | case 1: /* odd parity */ | ||
7619 | cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD); | ||
7620 | dbug(1,dprintf("MDM: odd parity")); | ||
7621 | break; | ||
7622 | |||
7623 | case 2: /* even parity */ | ||
7624 | cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN); | ||
7625 | dbug(1,dprintf("MDM: even parity")); | ||
7626 | break; | ||
7627 | |||
7628 | default: | ||
7629 | dbug(1,dprintf("MDM: no parity")); | ||
7630 | break; | ||
7631 | } | ||
7632 | |||
7633 | switch (GET_WORD (mdm_cfg[3].info)) | ||
7634 | { /* stop bits */ | ||
7635 | case 1: /* 2 stop bits */ | ||
7636 | cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS; | ||
7637 | dbug(1,dprintf("MDM: 2 stop bits")); | ||
7638 | break; | ||
7639 | |||
7640 | default: | ||
7641 | dbug(1,dprintf("MDM: 1 stop bit")); | ||
7642 | break; | ||
7643 | } | ||
7644 | |||
7645 | switch (GET_WORD (mdm_cfg[1].info)) | ||
7646 | { /* char length */ | ||
7647 | case 5: | ||
7648 | cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5; | ||
7649 | dbug(1,dprintf("MDM: 5 bits")); | ||
7650 | break; | ||
7651 | |||
7652 | case 6: | ||
7653 | cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6; | ||
7654 | dbug(1,dprintf("MDM: 6 bits")); | ||
7655 | break; | ||
7656 | |||
7657 | case 7: | ||
7658 | cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7; | ||
7659 | dbug(1,dprintf("MDM: 7 bits")); | ||
7660 | break; | ||
7661 | |||
7662 | default: | ||
7663 | dbug(1,dprintf("MDM: 8 bits")); | ||
7664 | break; | ||
7665 | } | ||
7666 | |||
7667 | cai[7] = 0; /* Line taking options */ | ||
7668 | cai[8] = 0; /* Modulation negotiation options */ | ||
7669 | cai[9] = 0; /* Modulation options */ | ||
7670 | |||
7671 | if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0)) | ||
7672 | { | ||
7673 | cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION; | ||
7674 | dbug(1, dprintf("MDM: Reverse direction")); | ||
7675 | } | ||
7676 | |||
7677 | if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN) | ||
7678 | { | ||
7679 | cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN; | ||
7680 | dbug(1, dprintf("MDM: Disable retrain")); | ||
7681 | } | ||
7682 | |||
7683 | if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE) | ||
7684 | { | ||
7685 | cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE; | ||
7686 | dbug(1, dprintf("MDM: Disable ring tone")); | ||
7687 | } | ||
7688 | |||
7689 | if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800) | ||
7690 | { | ||
7691 | cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ; | ||
7692 | dbug(1, dprintf("MDM: 1800 guard tone")); | ||
7693 | } | ||
7694 | else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 ) | ||
7695 | { | ||
7696 | cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ; | ||
7697 | dbug(1, dprintf("MDM: 550 guard tone")); | ||
7698 | } | ||
7699 | |||
7700 | if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100) | ||
7701 | { | ||
7702 | cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100; | ||
7703 | dbug(1, dprintf("MDM: V100")); | ||
7704 | } | ||
7705 | else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS) | ||
7706 | { | ||
7707 | cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS; | ||
7708 | dbug(1, dprintf("MDM: IN CLASS")); | ||
7709 | } | ||
7710 | else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED) | ||
7711 | { | ||
7712 | cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED; | ||
7713 | dbug(1, dprintf("MDM: DISABLED")); | ||
7714 | } | ||
7715 | cai[0] = 20; | ||
7716 | |||
7717 | if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18)) | ||
7718 | && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */ | ||
7719 | { | ||
7720 | plci->requested_options |= 1L << PRIVATE_V18; | ||
7721 | } | ||
7722 | if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */ | ||
7723 | plci->requested_options |= 1L << PRIVATE_VOWN; | ||
7724 | |||
7725 | if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | ||
7726 | & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN))) | ||
7727 | { | ||
7728 | if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg)) | ||
7729 | { | ||
7730 | i = 27; | ||
7731 | if (mdm_cfg[6].length >= 4) | ||
7732 | { | ||
7733 | d = GET_DWORD(&mdm_cfg[6].info[1]); | ||
7734 | cai[7] |= (byte) d; /* line taking options */ | ||
7735 | cai[9] |= (byte)(d >> 8); /* modulation options */ | ||
7736 | cai[++i] = (byte)(d >> 16); /* vown modulation options */ | ||
7737 | cai[++i] = (byte)(d >> 24); | ||
7738 | if (mdm_cfg[6].length >= 8) | ||
7739 | { | ||
7740 | d = GET_DWORD(&mdm_cfg[6].info[5]); | ||
7741 | cai[10] |= (byte) d; /* disabled modulations mask */ | ||
7742 | cai[11] |= (byte)(d >> 8); | ||
7743 | if (mdm_cfg[6].length >= 12) | ||
7744 | { | ||
7745 | d = GET_DWORD(&mdm_cfg[6].info[9]); | ||
7746 | cai[12] = (byte) d; /* enabled modulations mask */ | ||
7747 | cai[++i] = (byte)(d >> 8); /* vown enabled modulations */ | ||
7748 | cai[++i] = (byte)(d >> 16); | ||
7749 | cai[++i] = (byte)(d >> 24); | ||
7750 | cai[++i] = 0; | ||
7751 | if (mdm_cfg[6].length >= 14) | ||
7752 | { | ||
7753 | w = GET_WORD(&mdm_cfg[6].info[13]); | ||
7754 | if (w != 0) | ||
7755 | PUT_WORD(&cai[13], w); /* min tx speed */ | ||
7756 | if (mdm_cfg[6].length >= 16) | ||
7757 | { | ||
7758 | w = GET_WORD(&mdm_cfg[6].info[15]); | ||
7759 | if (w != 0) | ||
7760 | PUT_WORD(&cai[15], w); /* max tx speed */ | ||
7761 | if (mdm_cfg[6].length >= 18) | ||
7762 | { | ||
7763 | w = GET_WORD(&mdm_cfg[6].info[17]); | ||
7764 | if (w != 0) | ||
7765 | PUT_WORD(&cai[17], w); /* min rx speed */ | ||
7766 | if (mdm_cfg[6].length >= 20) | ||
7767 | { | ||
7768 | w = GET_WORD(&mdm_cfg[6].info[19]); | ||
7769 | if (w != 0) | ||
7770 | PUT_WORD(&cai[19], w); /* max rx speed */ | ||
7771 | if (mdm_cfg[6].length >= 22) | ||
7772 | { | ||
7773 | w = GET_WORD(&mdm_cfg[6].info[21]); | ||
7774 | cai[23] = (byte)(-((short) w)); /* transmit level */ | ||
7775 | if (mdm_cfg[6].length >= 24) | ||
7776 | { | ||
7777 | w = GET_WORD(&mdm_cfg[6].info[23]); | ||
7778 | cai[22] |= (byte) w; /* info options mask */ | ||
7779 | cai[21] |= (byte)(w >> 8); /* disabled symbol rates */ | ||
7780 | } | ||
7781 | } | ||
7782 | } | ||
7783 | } | ||
7784 | } | ||
7785 | } | ||
7786 | } | ||
7787 | } | ||
7788 | } | ||
7789 | cai[27] = i - 27; | ||
7790 | i++; | ||
7791 | if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg)) | ||
7792 | { | ||
7793 | if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18)) | ||
7794 | { | ||
7795 | for (n = 0; n < 3; n++) | ||
7796 | { | ||
7797 | cai[i] = (byte)(mdm_cfg_v18[n].length); | ||
7798 | for (j = 1; j < ((word)(cai[i] + 1)); j++) | ||
7799 | cai[i+j] = mdm_cfg_v18[n].info[j]; | ||
7800 | i += cai[i] + 1; | ||
7801 | } | ||
7802 | } | ||
7803 | } | ||
7804 | cai[0] = (byte)(i - 1); | ||
7805 | } | ||
7806 | } | ||
7807 | |||
7808 | } | ||
7809 | } | ||
7810 | if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */ | ||
7811 | GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */ | ||
7812 | { | ||
7813 | if(bp_parms[3].length){ | ||
7814 | dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1]))); | ||
7815 | switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */ | ||
7816 | case 0: | ||
7817 | case 56000: | ||
7818 | if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */ | ||
7819 | dbug(1,dprintf("56k sync HSCX")); | ||
7820 | cai[1] = 8; | ||
7821 | cai[2] = 0; | ||
7822 | cai[3] = 0; | ||
7823 | } | ||
7824 | else if(GET_WORD(bp_parms[0].info)==2){ | ||
7825 | dbug(1,dprintf("56k async DSP")); | ||
7826 | cai[2] = 9; | ||
7827 | } | ||
7828 | break; | ||
7829 | case 50: cai[2] = 1; break; | ||
7830 | case 75: cai[2] = 1; break; | ||
7831 | case 110: cai[2] = 1; break; | ||
7832 | case 150: cai[2] = 1; break; | ||
7833 | case 200: cai[2] = 1; break; | ||
7834 | case 300: cai[2] = 1; break; | ||
7835 | case 600: cai[2] = 1; break; | ||
7836 | case 1200: cai[2] = 2; break; | ||
7837 | case 2400: cai[2] = 3; break; | ||
7838 | case 4800: cai[2] = 4; break; | ||
7839 | case 7200: cai[2] = 10; break; | ||
7840 | case 9600: cai[2] = 5; break; | ||
7841 | case 12000: cai[2] = 13; break; | ||
7842 | case 24000: cai[2] = 0; break; | ||
7843 | case 14400: cai[2] = 11; break; | ||
7844 | case 19200: cai[2] = 6; break; | ||
7845 | case 28800: cai[2] = 12; break; | ||
7846 | case 38400: cai[2] = 7; break; | ||
7847 | case 48000: cai[2] = 8; break; | ||
7848 | case 76: cai[2] = 15; break; /* 75/1200 */ | ||
7849 | case 1201: cai[2] = 14; break; /* 1200/75 */ | ||
7850 | case 56001: cai[2] = 9; break; /* V.110 56000 */ | ||
7851 | |||
7852 | default: | ||
7853 | return _B1_PARM_NOT_SUPPORTED; | ||
7854 | } | ||
7855 | cai[3] = 0; | ||
7856 | if (cai[1] == 13) /* v.110 async */ | ||
7857 | { | ||
7858 | if (bp_parms[3].length >= 8) | ||
7859 | { | ||
7860 | switch (GET_WORD (&bp_parms[3].info[3])) | ||
7861 | { /* char length */ | ||
7862 | case 5: | ||
7863 | cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5; | ||
7864 | break; | ||
7865 | case 6: | ||
7866 | cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6; | ||
7867 | break; | ||
7868 | case 7: | ||
7869 | cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7; | ||
7870 | break; | ||
7871 | } | ||
7872 | switch (GET_WORD (&bp_parms[3].info[5])) | ||
7873 | { /* Parity */ | ||
7874 | case 1: /* odd parity */ | ||
7875 | cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD); | ||
7876 | break; | ||
7877 | case 2: /* even parity */ | ||
7878 | cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN); | ||
7879 | break; | ||
7880 | } | ||
7881 | switch (GET_WORD (&bp_parms[3].info[7])) | ||
7882 | { /* stop bits */ | ||
7883 | case 1: /* 2 stop bits */ | ||
7884 | cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS; | ||
7885 | break; | ||
7886 | } | ||
7887 | } | ||
7888 | } | ||
7889 | } | ||
7890 | else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){ | ||
7891 | dbug(1,dprintf("V.110 default 56k sync")); | ||
7892 | cai[1] = 8; | ||
7893 | cai[2] = 0; | ||
7894 | cai[3] = 0; | ||
7895 | } | ||
7896 | else { | ||
7897 | dbug(1,dprintf("V.110 default 9600 async")); | ||
7898 | cai[2] = 5; | ||
7899 | } | ||
7900 | } | ||
7901 | PUT_WORD(&cai[5],plci->appl->MaxDataLength); | ||
7902 | dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6])); | ||
7903 | /* HexDump ("CAI", sizeof(cai), &cai[0]); */ | ||
7904 | |||
7905 | add_p(plci, CAI, cai); | ||
7906 | return 0; | ||
7907 | } | ||
7908 | |||
7909 | /*------------------------------------------------------------------*/ | ||
7910 | /* put parameter for b2 and B3 protocol in the parameter buffer */ | ||
7911 | /*------------------------------------------------------------------*/ | ||
7912 | |||
7913 | word add_b23(PLCI * plci, API_PARSE * bp) | ||
7914 | { | ||
7915 | word i, fax_control_bits; | ||
7916 | byte pos, len; | ||
7917 | byte SAPI = 0x40; /* default SAPI 16 for x.31 */ | ||
7918 | API_PARSE bp_parms[8]; | ||
7919 | API_PARSE * b1_config; | ||
7920 | API_PARSE * b2_config; | ||
7921 | API_PARSE b2_config_parms[8]; | ||
7922 | API_PARSE * b3_config; | ||
7923 | API_PARSE b3_config_parms[6]; | ||
7924 | API_PARSE global_config[2]; | ||
7925 | |||
7926 | static byte llc[3] = {2,0,0}; | ||
7927 | static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | ||
7928 | static byte nlc[256]; | ||
7929 | static byte lli[12] = {1,1}; | ||
7930 | |||
7931 | const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6}; | ||
7932 | const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6}; | ||
7933 | |||
7934 | const byte llc3[] = {4,3,2,2,6,6,0}; | ||
7935 | const byte header[] = {0,2,3,3,0,0,0}; | ||
7936 | |||
7937 | for(i=0;i<8;i++) bp_parms[i].length = 0; | ||
7938 | for(i=0;i<6;i++) b2_config_parms[i].length = 0; | ||
7939 | for(i=0;i<5;i++) b3_config_parms[i].length = 0; | ||
7940 | |||
7941 | lli[0] = 1; | ||
7942 | lli[1] = 1; | ||
7943 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) | ||
7944 | lli[1] |= 2; | ||
7945 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) | ||
7946 | lli[1] |= 4; | ||
7947 | |||
7948 | if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) { | ||
7949 | lli[1] |= 0x10; | ||
7950 | if (plci->rx_dma_descriptor <= 0) { | ||
7951 | plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic); | ||
7952 | if (plci->rx_dma_descriptor >= 0) | ||
7953 | plci->rx_dma_descriptor++; | ||
7954 | } | ||
7955 | if (plci->rx_dma_descriptor > 0) { | ||
7956 | lli[0] = 6; | ||
7957 | lli[1] |= 0x40; | ||
7958 | lli[2] = (byte)(plci->rx_dma_descriptor - 1); | ||
7959 | lli[3] = (byte)plci->rx_dma_magic; | ||
7960 | lli[4] = (byte)(plci->rx_dma_magic >> 8); | ||
7961 | lli[5] = (byte)(plci->rx_dma_magic >> 16); | ||
7962 | lli[6] = (byte)(plci->rx_dma_magic >> 24); | ||
7963 | } | ||
7964 | } | ||
7965 | |||
7966 | if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) { | ||
7967 | lli[1] |= 0x20; | ||
7968 | } | ||
7969 | |||
7970 | dbug(1,dprintf("add_b23")); | ||
7971 | api_save_msg(bp, "s", &plci->B_protocol); | ||
7972 | |||
7973 | if(!bp->length && plci->tel) | ||
7974 | { | ||
7975 | plci->adv_nl = TRUE; | ||
7976 | dbug(1,dprintf("Default adv.Nl")); | ||
7977 | add_p(plci,LLI,lli); | ||
7978 | plci->B2_prot = 1 /*XPARENT*/; | ||
7979 | plci->B3_prot = 0 /*XPARENT*/; | ||
7980 | llc[1] = 2; | ||
7981 | llc[2] = 4; | ||
7982 | add_p(plci, LLC, llc); | ||
7983 | dlc[0] = 2; | ||
7984 | PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | ||
7985 | add_p(plci, DLC, dlc); | ||
7986 | return 0; | ||
7987 | } | ||
7988 | |||
7989 | if(!bp->length) /*default*/ | ||
7990 | { | ||
7991 | dbug(1,dprintf("ret default")); | ||
7992 | add_p(plci,LLI,lli); | ||
7993 | plci->B2_prot = 0 /*X.75 */; | ||
7994 | plci->B3_prot = 0 /*XPARENT*/; | ||
7995 | llc[1] = 1; | ||
7996 | llc[2] = 4; | ||
7997 | add_p(plci, LLC, llc); | ||
7998 | dlc[0] = 2; | ||
7999 | PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | ||
8000 | add_p(plci, DLC, dlc); | ||
8001 | return 0; | ||
8002 | } | ||
8003 | dbug(1,dprintf("b_prot_len=%d",(word)bp->length)); | ||
8004 | if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT; | ||
8005 | |||
8006 | if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms)) | ||
8007 | { | ||
8008 | bp_parms[6].length = 0; | ||
8009 | if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms)) | ||
8010 | { | ||
8011 | dbug(1,dprintf("b-form.!")); | ||
8012 | return _WRONG_MESSAGE_FORMAT; | ||
8013 | } | ||
8014 | } | ||
8015 | else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms)) | ||
8016 | { | ||
8017 | dbug(1,dprintf("b-form.!")); | ||
8018 | return _WRONG_MESSAGE_FORMAT; | ||
8019 | } | ||
8020 | |||
8021 | if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */ | ||
8022 | { | ||
8023 | if(GET_WORD(bp_parms[1].info)!=1 | ||
8024 | || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED; | ||
8025 | plci->adv_nl = TRUE; | ||
8026 | } | ||
8027 | else if(plci->tel) return _B2_NOT_SUPPORTED; | ||
8028 | |||
8029 | |||
8030 | if ((GET_WORD(bp_parms[1].info) == B2_RTP) | ||
8031 | && (GET_WORD(bp_parms[2].info) == B3_RTP) | ||
8032 | && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP))) | ||
8033 | { | ||
8034 | add_p(plci,LLI,lli); | ||
8035 | plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); | ||
8036 | plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); | ||
8037 | llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13; | ||
8038 | llc[2] = 4; | ||
8039 | add_p(plci, LLC, llc); | ||
8040 | dlc[0] = 2; | ||
8041 | PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | ||
8042 | dlc[3] = 3; /* Addr A */ | ||
8043 | dlc[4] = 1; /* Addr B */ | ||
8044 | dlc[5] = 7; /* modulo mode */ | ||
8045 | dlc[6] = 7; /* window size */ | ||
8046 | dlc[7] = 0; /* XID len Lo */ | ||
8047 | dlc[8] = 0; /* XID len Hi */ | ||
8048 | for (i = 0; i < bp_parms[4].length; i++) | ||
8049 | dlc[9+i] = bp_parms[4].info[1+i]; | ||
8050 | dlc[0] = (byte)(8 + bp_parms[4].length); | ||
8051 | add_p(plci, DLC, dlc); | ||
8052 | for (i = 0; i < bp_parms[5].length; i++) | ||
8053 | nlc[1+i] = bp_parms[5].info[1+i]; | ||
8054 | nlc[0] = (byte)(bp_parms[5].length); | ||
8055 | add_p(plci, NLC, nlc); | ||
8056 | return 0; | ||
8057 | } | ||
8058 | |||
8059 | |||
8060 | |||
8061 | if ((GET_WORD(bp_parms[1].info) >= 32) | ||
8062 | || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols) | ||
8063 | && ((GET_WORD(bp_parms[1].info) != B2_PIAFS) | ||
8064 | || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS))))) | ||
8065 | |||
8066 | { | ||
8067 | return _B2_NOT_SUPPORTED; | ||
8068 | } | ||
8069 | if ((GET_WORD(bp_parms[2].info) >= 32) | ||
8070 | || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols)) | ||
8071 | { | ||
8072 | return _B3_NOT_SUPPORTED; | ||
8073 | } | ||
8074 | if ((GET_WORD(bp_parms[1].info) != B2_SDLC) | ||
8075 | && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) | ||
8076 | || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC) | ||
8077 | || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))) | ||
8078 | { | ||
8079 | return (add_modem_b23 (plci, bp_parms)); | ||
8080 | } | ||
8081 | |||
8082 | add_p(plci,LLI,lli); | ||
8083 | |||
8084 | plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); | ||
8085 | plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); | ||
8086 | if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */ | ||
8087 | |||
8088 | if(bp_parms[6].length) | ||
8089 | { | ||
8090 | if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config)) | ||
8091 | { | ||
8092 | return _WRONG_MESSAGE_FORMAT; | ||
8093 | } | ||
8094 | switch(GET_WORD(global_config[0].info)) | ||
8095 | { | ||
8096 | case 1: | ||
8097 | plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE; | ||
8098 | break; | ||
8099 | case 2: | ||
8100 | plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER; | ||
8101 | break; | ||
8102 | } | ||
8103 | } | ||
8104 | dbug(1,dprintf("call_dir=%04x", plci->call_dir)); | ||
8105 | |||
8106 | |||
8107 | if (plci->B2_prot == B2_PIAFS) | ||
8108 | llc[1] = PIAFS_CRC; | ||
8109 | else | ||
8110 | /* IMPLEMENT_PIAFS */ | ||
8111 | { | ||
8112 | llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? | ||
8113 | llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)]; | ||
8114 | } | ||
8115 | llc[2] = llc3[GET_WORD(bp_parms[2].info)]; | ||
8116 | |||
8117 | add_p(plci, LLC, llc); | ||
8118 | |||
8119 | dlc[0] = 2; | ||
8120 | PUT_WORD(&dlc[1], plci->appl->MaxDataLength + | ||
8121 | header[GET_WORD(bp_parms[2].info)]); | ||
8122 | |||
8123 | b1_config = &bp_parms[3]; | ||
8124 | nlc[0] = 0; | ||
8125 | if(plci->B3_prot == 4 | ||
8126 | || plci->B3_prot == 5) | ||
8127 | { | ||
8128 | for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0; | ||
8129 | nlc[0] = sizeof(T30_INFO); | ||
8130 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | ||
8131 | ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI; | ||
8132 | ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff; | ||
8133 | if(b1_config->length>=2) | ||
8134 | { | ||
8135 | ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400); | ||
8136 | } | ||
8137 | } | ||
8138 | b2_config = &bp_parms[4]; | ||
8139 | |||
8140 | |||
8141 | if (llc[1] == PIAFS_CRC) | ||
8142 | { | ||
8143 | if (plci->B3_prot != B3_TRANSPARENT) | ||
8144 | { | ||
8145 | return _B_STACK_NOT_SUPPORTED; | ||
8146 | } | ||
8147 | if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) { | ||
8148 | return _WRONG_MESSAGE_FORMAT; | ||
8149 | } | ||
8150 | PUT_WORD(&dlc[1],plci->appl->MaxDataLength); | ||
8151 | dlc[3] = 0; /* Addr A */ | ||
8152 | dlc[4] = 0; /* Addr B */ | ||
8153 | dlc[5] = 0; /* modulo mode */ | ||
8154 | dlc[6] = 0; /* window size */ | ||
8155 | if (b2_config->length >= 7){ | ||
8156 | dlc[ 7] = 7; | ||
8157 | dlc[ 8] = 0; | ||
8158 | dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */ | ||
8159 | dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */ | ||
8160 | dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */ | ||
8161 | dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */ | ||
8162 | dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */ | ||
8163 | dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */ | ||
8164 | dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */ | ||
8165 | dlc[ 0] = 15; | ||
8166 | if(b2_config->length >= 8) { /* PIAFS control abilities */ | ||
8167 | dlc[ 7] = 10; | ||
8168 | dlc[16] = 2; /* Length of PIAFS extention */ | ||
8169 | dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */ | ||
8170 | dlc[18] = b2_config_parms[4].info[0]; /* value */ | ||
8171 | dlc[ 0] = 18; | ||
8172 | } | ||
8173 | } | ||
8174 | else /* default values, 64K, variable, no compression */ | ||
8175 | { | ||
8176 | dlc[ 7] = 7; | ||
8177 | dlc[ 8] = 0; | ||
8178 | dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */ | ||
8179 | dlc[10] = 0x03; /* V.42bis P0 */ | ||
8180 | dlc[11] = 0; /* V.42bis P0 */ | ||
8181 | dlc[12] = 0; /* V.42bis P1 */ | ||
8182 | dlc[13] = 0; /* V.42bis P1 */ | ||
8183 | dlc[14] = 0; /* V.42bis P2 */ | ||
8184 | dlc[15] = 0; /* V.42bis P2 */ | ||
8185 | dlc[ 0] = 15; | ||
8186 | } | ||
8187 | add_p(plci, DLC, dlc); | ||
8188 | } | ||
8189 | else | ||
8190 | |||
8191 | if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS)) | ||
8192 | { | ||
8193 | if (plci->B3_prot != B3_TRANSPARENT) | ||
8194 | return _B_STACK_NOT_SUPPORTED; | ||
8195 | |||
8196 | dlc[0] = 6; | ||
8197 | PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2); | ||
8198 | dlc[3] = 0x08; | ||
8199 | dlc[4] = 0x01; | ||
8200 | dlc[5] = 127; | ||
8201 | dlc[6] = 7; | ||
8202 | if (b2_config->length != 0) | ||
8203 | { | ||
8204 | if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) { | ||
8205 | return _WRONG_MESSAGE_FORMAT; | ||
8206 | } | ||
8207 | dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04)); | ||
8208 | dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01); | ||
8209 | if (b2_config->info[3] != 128) | ||
8210 | { | ||
8211 | dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4])); | ||
8212 | return _B2_PARM_NOT_SUPPORTED; | ||
8213 | } | ||
8214 | dlc[5] = (byte)(b2_config->info[3] - 1); | ||
8215 | dlc[6] = b2_config->info[4]; | ||
8216 | if(llc[1]==V120_V42BIS){ | ||
8217 | if (b2_config->length >= 10){ | ||
8218 | dlc[ 7] = 6; | ||
8219 | dlc[ 8] = 0; | ||
8220 | dlc[ 9] = b2_config_parms[4].info[0]; | ||
8221 | dlc[10] = b2_config_parms[4].info[1]; | ||
8222 | dlc[11] = b2_config_parms[5].info[0]; | ||
8223 | dlc[12] = b2_config_parms[5].info[1]; | ||
8224 | dlc[13] = b2_config_parms[6].info[0]; | ||
8225 | dlc[14] = b2_config_parms[6].info[1]; | ||
8226 | dlc[ 0] = 14; | ||
8227 | dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1])); | ||
8228 | dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1])); | ||
8229 | dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1])); | ||
8230 | } | ||
8231 | else { | ||
8232 | dlc[ 6] = 14; | ||
8233 | } | ||
8234 | } | ||
8235 | } | ||
8236 | } | ||
8237 | else | ||
8238 | { | ||
8239 | if(b2_config->length) | ||
8240 | { | ||
8241 | dbug(1,dprintf("B2-Config")); | ||
8242 | if(llc[1]==X75_V42BIS){ | ||
8243 | if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) | ||
8244 | { | ||
8245 | return _WRONG_MESSAGE_FORMAT; | ||
8246 | } | ||
8247 | } | ||
8248 | else { | ||
8249 | if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms)) | ||
8250 | { | ||
8251 | return _WRONG_MESSAGE_FORMAT; | ||
8252 | } | ||
8253 | } | ||
8254 | /* if B2 Protocol is LAPD, b2_config structure is different */ | ||
8255 | if(llc[1]==6) | ||
8256 | { | ||
8257 | dlc[0] = 4; | ||
8258 | if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */ | ||
8259 | else dlc[2] = 0x01; | ||
8260 | if( (b2_config->length>=2) && (plci->B2_prot==12) ) | ||
8261 | { | ||
8262 | SAPI = b2_config->info[2]; /* SAPI */ | ||
8263 | } | ||
8264 | dlc[1] = SAPI; | ||
8265 | if( (b2_config->length>=3) && (b2_config->info[3]==128) ) | ||
8266 | { | ||
8267 | dlc[3] = 127; /* Mode */ | ||
8268 | } | ||
8269 | else | ||
8270 | { | ||
8271 | dlc[3] = 7; /* Mode */ | ||
8272 | } | ||
8273 | |||
8274 | if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */ | ||
8275 | else dlc[4] = 1; | ||
8276 | dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4])); | ||
8277 | if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED; | ||
8278 | } | ||
8279 | else | ||
8280 | { | ||
8281 | dlc[0] = (byte)(b2_config_parms[4].length+6); | ||
8282 | dlc[3] = b2_config->info[1]; | ||
8283 | dlc[4] = b2_config->info[2]; | ||
8284 | if(b2_config->info[3]!=8 && b2_config->info[3]!=128){ | ||
8285 | dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4])); | ||
8286 | return _B2_PARM_NOT_SUPPORTED; | ||
8287 | } | ||
8288 | |||
8289 | dlc[5] = (byte)(b2_config->info[3]-1); | ||
8290 | dlc[6] = b2_config->info[4]; | ||
8291 | if(dlc[6]>dlc[5]){ | ||
8292 | dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6])); | ||
8293 | return _B2_PARM_NOT_SUPPORTED; | ||
8294 | } | ||
8295 | |||
8296 | if(llc[1]==X75_V42BIS) { | ||
8297 | if (b2_config->length >= 10){ | ||
8298 | dlc[ 7] = 6; | ||
8299 | dlc[ 8] = 0; | ||
8300 | dlc[ 9] = b2_config_parms[4].info[0]; | ||
8301 | dlc[10] = b2_config_parms[4].info[1]; | ||
8302 | dlc[11] = b2_config_parms[5].info[0]; | ||
8303 | dlc[12] = b2_config_parms[5].info[1]; | ||
8304 | dlc[13] = b2_config_parms[6].info[0]; | ||
8305 | dlc[14] = b2_config_parms[6].info[1]; | ||
8306 | dlc[ 0] = 14; | ||
8307 | dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1])); | ||
8308 | dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1])); | ||
8309 | dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1])); | ||
8310 | } | ||
8311 | else { | ||
8312 | dlc[ 6] = 14; | ||
8313 | } | ||
8314 | |||
8315 | } | ||
8316 | else { | ||
8317 | PUT_WORD(&dlc[7], (word)b2_config_parms[4].length); | ||
8318 | for(i=0; i<b2_config_parms[4].length; i++) | ||
8319 | dlc[11+i] = b2_config_parms[4].info[1+i]; | ||
8320 | } | ||
8321 | } | ||
8322 | } | ||
8323 | } | ||
8324 | add_p(plci, DLC, dlc); | ||
8325 | |||
8326 | b3_config = &bp_parms[5]; | ||
8327 | if(b3_config->length) | ||
8328 | { | ||
8329 | if(plci->B3_prot == 4 | ||
8330 | || plci->B3_prot == 5) | ||
8331 | { | ||
8332 | if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms)) | ||
8333 | { | ||
8334 | return _WRONG_MESSAGE_FORMAT; | ||
8335 | } | ||
8336 | i = GET_WORD((byte *)(b3_config_parms[0].info)); | ||
8337 | ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) || | ||
8338 | ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0); | ||
8339 | ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info)); | ||
8340 | fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES; | ||
8341 | if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6)) | ||
8342 | fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX; | ||
8343 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS) | ||
8344 | { | ||
8345 | |||
8346 | if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | ||
8347 | & (1L << PRIVATE_FAX_PAPER_FORMATS)) | ||
8348 | { | ||
8349 | ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 | | ||
8350 | T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 | | ||
8351 | T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED; | ||
8352 | } | ||
8353 | |||
8354 | ((T30_INFO *)&nlc[1])->recording_properties = | ||
8355 | T30_RECORDING_WIDTH_ISO_A3 | | ||
8356 | (T30_RECORDING_LENGTH_UNLIMITED << 2) | | ||
8357 | (T30_MIN_SCANLINE_TIME_00_00_00 << 4); | ||
8358 | } | ||
8359 | if(plci->B3_prot == 5) | ||
8360 | { | ||
8361 | if (i & 0x0002) /* Accept incoming fax-polling requests */ | ||
8362 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING; | ||
8363 | if (i & 0x2000) /* Do not use MR compression */ | ||
8364 | fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING; | ||
8365 | if (i & 0x4000) /* Do not use MMR compression */ | ||
8366 | fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING; | ||
8367 | if (i & 0x8000) /* Do not use ECM */ | ||
8368 | fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM; | ||
8369 | if (plci->fax_connect_info_length != 0) | ||
8370 | { | ||
8371 | ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution; | ||
8372 | ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format; | ||
8373 | ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties; | ||
8374 | fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & | ||
8375 | (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS); | ||
8376 | } | ||
8377 | } | ||
8378 | /* copy station id to NLC */ | ||
8379 | for(i=0; i<20; i++) | ||
8380 | { | ||
8381 | if(i<b3_config_parms[2].length) | ||
8382 | { | ||
8383 | ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i]; | ||
8384 | } | ||
8385 | else | ||
8386 | { | ||
8387 | ((T30_INFO *)&nlc[1])->station_id[i] = ' '; | ||
8388 | } | ||
8389 | } | ||
8390 | ((T30_INFO *)&nlc[1])->station_id_len = 20; | ||
8391 | /* copy head line to NLC */ | ||
8392 | if(b3_config_parms[3].length) | ||
8393 | { | ||
8394 | |||
8395 | pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20]))); | ||
8396 | if (pos != 0) | ||
8397 | { | ||
8398 | if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE) | ||
8399 | pos = 0; | ||
8400 | else | ||
8401 | { | ||
8402 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | ||
8403 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | ||
8404 | len = (byte)b3_config_parms[2].length; | ||
8405 | if (len > 20) | ||
8406 | len = 20; | ||
8407 | if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE) | ||
8408 | { | ||
8409 | for (i = 0; i < len; i++) | ||
8410 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; | ||
8411 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | ||
8412 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | ||
8413 | } | ||
8414 | } | ||
8415 | } | ||
8416 | |||
8417 | len = (byte)b3_config_parms[3].length; | ||
8418 | if (len > CAPI_MAX_HEAD_LINE_SPACE - pos) | ||
8419 | len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos); | ||
8420 | ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len); | ||
8421 | nlc[0] += (byte)(pos + len); | ||
8422 | for (i = 0; i < len; i++) | ||
8423 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; | ||
8424 | } | ||
8425 | else | ||
8426 | ((T30_INFO *)&nlc[1])->head_line_len = 0; | ||
8427 | |||
8428 | plci->nsf_control_bits = 0; | ||
8429 | if(plci->B3_prot == 5) | ||
8430 | { | ||
8431 | if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | ||
8432 | && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */ | ||
8433 | { | ||
8434 | plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD; | ||
8435 | } | ||
8436 | if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD)) | ||
8437 | && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */ | ||
8438 | { | ||
8439 | plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD; | ||
8440 | } | ||
8441 | if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | ||
8442 | & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | ||
8443 | { | ||
8444 | if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | ||
8445 | & (1L << PRIVATE_FAX_SUB_SEP_PWD)) | ||
8446 | { | ||
8447 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD; | ||
8448 | if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING) | ||
8449 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; | ||
8450 | } | ||
8451 | len = nlc[0]; | ||
8452 | pos = ((byte)(((T30_INFO *) 0)->station_id + 20)); | ||
8453 | if (pos < plci->fax_connect_info_length) | ||
8454 | { | ||
8455 | for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | ||
8456 | nlc[++len] = plci->fax_connect_info_buffer[pos++]; | ||
8457 | } | ||
8458 | else | ||
8459 | nlc[++len] = 0; | ||
8460 | if (pos < plci->fax_connect_info_length) | ||
8461 | { | ||
8462 | for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | ||
8463 | nlc[++len] = plci->fax_connect_info_buffer[pos++]; | ||
8464 | } | ||
8465 | else | ||
8466 | nlc[++len] = 0; | ||
8467 | if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) | ||
8468 | & (1L << PRIVATE_FAX_NONSTANDARD)) | ||
8469 | { | ||
8470 | if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0)) | ||
8471 | { | ||
8472 | if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2)) | ||
8473 | plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]); | ||
8474 | for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | ||
8475 | nlc[++len] = plci->fax_connect_info_buffer[pos++]; | ||
8476 | } | ||
8477 | else | ||
8478 | { | ||
8479 | if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms)) | ||
8480 | { | ||
8481 | dbug(1,dprintf("non-standard facilities info missing or wrong format")); | ||
8482 | nlc[++len] = 0; | ||
8483 | } | ||
8484 | else | ||
8485 | { | ||
8486 | if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2)) | ||
8487 | plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]); | ||
8488 | nlc[++len] = (byte)(b3_config_parms[4].length); | ||
8489 | for (i = 0; i < b3_config_parms[4].length; i++) | ||
8490 | nlc[++len] = b3_config_parms[4].info[1+i]; | ||
8491 | } | ||
8492 | } | ||
8493 | } | ||
8494 | nlc[0] = len; | ||
8495 | if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | ||
8496 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | ||
8497 | { | ||
8498 | ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG; | ||
8499 | } | ||
8500 | } | ||
8501 | } | ||
8502 | |||
8503 | PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); | ||
8504 | len = ((byte)(((T30_INFO *) 0)->station_id + 20)); | ||
8505 | for (i = 0; i < len; i++) | ||
8506 | plci->fax_connect_info_buffer[i] = nlc[1+i]; | ||
8507 | ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0; | ||
8508 | i += ((T30_INFO *)&nlc[1])->head_line_len; | ||
8509 | while (i < nlc[0]) | ||
8510 | plci->fax_connect_info_buffer[len++] = nlc[++i]; | ||
8511 | plci->fax_connect_info_length = len; | ||
8512 | } | ||
8513 | else | ||
8514 | { | ||
8515 | nlc[0] = 14; | ||
8516 | if(b3_config->length!=16) | ||
8517 | return _B3_PARM_NOT_SUPPORTED; | ||
8518 | for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i]; | ||
8519 | if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128) | ||
8520 | return _B3_PARM_NOT_SUPPORTED; | ||
8521 | nlc[13] = b3_config->info[13]; | ||
8522 | if(GET_WORD(&b3_config->info[15])>=nlc[13]) | ||
8523 | return _B3_PARM_NOT_SUPPORTED; | ||
8524 | nlc[14] = b3_config->info[15]; | ||
8525 | } | ||
8526 | } | ||
8527 | else | ||
8528 | { | ||
8529 | if (plci->B3_prot == 4 | ||
8530 | || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED; | ||
8531 | } | ||
8532 | add_p(plci, NLC, nlc); | ||
8533 | return 0; | ||
8534 | } | ||
8535 | |||
8536 | /*----------------------------------------------------------------*/ | ||
8537 | /* make the same as add_b23, but only for the modem related */ | ||
8538 | /* L2 and L3 B-Chan protocol. */ | ||
8539 | /* */ | ||
8540 | /* Enabled L2 and L3 Configurations: */ | ||
8541 | /* If L1 == Modem all negotiation */ | ||
8542 | /* only L2 == Modem with full negotiation is allowed */ | ||
8543 | /* If L1 == Modem async or sync */ | ||
8544 | /* only L2 == Transparent is allowed */ | ||
8545 | /* L3 == Modem or L3 == Transparent are allowed */ | ||
8546 | /* B2 Configuration for modem: */ | ||
8547 | /* word : enable/disable compression, bitoptions */ | ||
8548 | /* B3 Configuration for modem: */ | ||
8549 | /* empty */ | ||
8550 | /*----------------------------------------------------------------*/ | ||
8551 | static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms) | ||
8552 | { | ||
8553 | static byte lli[12] = {1,1}; | ||
8554 | static byte llc[3] = {2,0,0}; | ||
8555 | static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | ||
8556 | API_PARSE mdm_config[2]; | ||
8557 | word i; | ||
8558 | word b2_config = 0; | ||
8559 | |||
8560 | for(i=0;i<2;i++) mdm_config[i].length = 0; | ||
8561 | for(i=0;i<sizeof(dlc);i++) dlc[i] = 0; | ||
8562 | |||
8563 | if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) | ||
8564 | && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION)) | ||
8565 | || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE) | ||
8566 | && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT))) | ||
8567 | { | ||
8568 | return (_B_STACK_NOT_SUPPORTED); | ||
8569 | } | ||
8570 | if ((GET_WORD(bp_parms[2].info) != B3_MODEM) | ||
8571 | && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT)) | ||
8572 | { | ||
8573 | return (_B_STACK_NOT_SUPPORTED); | ||
8574 | } | ||
8575 | |||
8576 | plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); | ||
8577 | plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); | ||
8578 | |||
8579 | if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length) | ||
8580 | { | ||
8581 | if (api_parse (&bp_parms[4].info[1], | ||
8582 | (word)bp_parms[4].length, "w", | ||
8583 | mdm_config)) | ||
8584 | { | ||
8585 | return (_WRONG_MESSAGE_FORMAT); | ||
8586 | } | ||
8587 | b2_config = GET_WORD(mdm_config[0].info); | ||
8588 | } | ||
8589 | |||
8590 | /* OK, L2 is modem */ | ||
8591 | |||
8592 | lli[0] = 1; | ||
8593 | lli[1] = 1; | ||
8594 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) | ||
8595 | lli[1] |= 2; | ||
8596 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) | ||
8597 | lli[1] |= 4; | ||
8598 | |||
8599 | if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) { | ||
8600 | lli[1] |= 0x10; | ||
8601 | if (plci->rx_dma_descriptor <= 0) { | ||
8602 | plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic); | ||
8603 | if (plci->rx_dma_descriptor >= 0) | ||
8604 | plci->rx_dma_descriptor++; | ||
8605 | } | ||
8606 | if (plci->rx_dma_descriptor > 0) { | ||
8607 | lli[1] |= 0x40; | ||
8608 | lli[0] = 6; | ||
8609 | lli[2] = (byte)(plci->rx_dma_descriptor - 1); | ||
8610 | lli[3] = (byte)plci->rx_dma_magic; | ||
8611 | lli[4] = (byte)(plci->rx_dma_magic >> 8); | ||
8612 | lli[5] = (byte)(plci->rx_dma_magic >> 16); | ||
8613 | lli[6] = (byte)(plci->rx_dma_magic >> 24); | ||
8614 | } | ||
8615 | } | ||
8616 | |||
8617 | if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) { | ||
8618 | lli[1] |= 0x20; | ||
8619 | } | ||
8620 | |||
8621 | llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? | ||
8622 | /*V42*/ 10 : /*V42_IN*/ 9; | ||
8623 | llc[2] = 4; /* pass L3 always transparent */ | ||
8624 | add_p(plci, LLI, lli); | ||
8625 | add_p(plci, LLC, llc); | ||
8626 | i = 1; | ||
8627 | PUT_WORD (&dlc[i], plci->appl->MaxDataLength); | ||
8628 | i += 2; | ||
8629 | if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) | ||
8630 | { | ||
8631 | if (bp_parms[4].length) | ||
8632 | { | ||
8633 | dbug(1, dprintf("MDM b2_config=%02x", b2_config)); | ||
8634 | dlc[i++] = 3; /* Addr A */ | ||
8635 | dlc[i++] = 1; /* Addr B */ | ||
8636 | dlc[i++] = 7; /* modulo mode */ | ||
8637 | dlc[i++] = 7; /* window size */ | ||
8638 | dlc[i++] = 0; /* XID len Lo */ | ||
8639 | dlc[i++] = 0; /* XID len Hi */ | ||
8640 | |||
8641 | if (b2_config & MDM_B2_DISABLE_V42bis) | ||
8642 | { | ||
8643 | dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS; | ||
8644 | } | ||
8645 | if (b2_config & MDM_B2_DISABLE_MNP) | ||
8646 | { | ||
8647 | dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5; | ||
8648 | } | ||
8649 | if (b2_config & MDM_B2_DISABLE_TRANS) | ||
8650 | { | ||
8651 | dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL; | ||
8652 | } | ||
8653 | if (b2_config & MDM_B2_DISABLE_V42) | ||
8654 | { | ||
8655 | dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT; | ||
8656 | } | ||
8657 | if (b2_config & MDM_B2_DISABLE_COMP) | ||
8658 | { | ||
8659 | dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION; | ||
8660 | } | ||
8661 | i++; | ||
8662 | } | ||
8663 | } | ||
8664 | else | ||
8665 | { | ||
8666 | dlc[i++] = 3; /* Addr A */ | ||
8667 | dlc[i++] = 1; /* Addr B */ | ||
8668 | dlc[i++] = 7; /* modulo mode */ | ||
8669 | dlc[i++] = 7; /* window size */ | ||
8670 | dlc[i++] = 0; /* XID len Lo */ | ||
8671 | dlc[i++] = 0; /* XID len Hi */ | ||
8672 | dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS | | ||
8673 | DLC_MODEMPROT_DISABLE_MNP_MNP5 | | ||
8674 | DLC_MODEMPROT_DISABLE_V42_DETECT | | ||
8675 | DLC_MODEMPROT_DISABLE_COMPRESSION; | ||
8676 | } | ||
8677 | dlc[0] = (byte)(i - 1); | ||
8678 | /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */ | ||
8679 | add_p(plci, DLC, dlc); | ||
8680 | return (0); | ||
8681 | } | ||
8682 | |||
8683 | |||
8684 | /*------------------------------------------------------------------*/ | ||
8685 | /* send a request for the signaling entity */ | ||
8686 | /*------------------------------------------------------------------*/ | ||
8687 | |||
8688 | void sig_req(PLCI * plci, byte req, byte Id) | ||
8689 | { | ||
8690 | if(!plci) return; | ||
8691 | if(plci->adapter->adapter_disabled) return; | ||
8692 | dbug(1,dprintf("sig_req(%x)",req)); | ||
8693 | if (req == REMOVE) | ||
8694 | plci->sig_remove_id = plci->Sig.Id; | ||
8695 | if(plci->req_in==plci->req_in_start) { | ||
8696 | plci->req_in +=2; | ||
8697 | plci->RBuffer[plci->req_in++] = 0; | ||
8698 | } | ||
8699 | PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); | ||
8700 | plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */ | ||
8701 | plci->RBuffer[plci->req_in++] = req; /* request */ | ||
8702 | plci->RBuffer[plci->req_in++] = 0; /* channel */ | ||
8703 | plci->req_in_start = plci->req_in; | ||
8704 | } | ||
8705 | |||
8706 | /*------------------------------------------------------------------*/ | ||
8707 | /* send a request for the network layer entity */ | ||
8708 | /*------------------------------------------------------------------*/ | ||
8709 | |||
8710 | void nl_req_ncci(PLCI * plci, byte req, byte ncci) | ||
8711 | { | ||
8712 | if(!plci) return; | ||
8713 | if(plci->adapter->adapter_disabled) return; | ||
8714 | dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci)); | ||
8715 | if (req == REMOVE) | ||
8716 | { | ||
8717 | plci->nl_remove_id = plci->NL.Id; | ||
8718 | ncci_remove (plci, 0, (byte)(ncci != 0)); | ||
8719 | ncci = 0; | ||
8720 | } | ||
8721 | if(plci->req_in==plci->req_in_start) { | ||
8722 | plci->req_in +=2; | ||
8723 | plci->RBuffer[plci->req_in++] = 0; | ||
8724 | } | ||
8725 | PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); | ||
8726 | plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */ | ||
8727 | plci->RBuffer[plci->req_in++] = req; /* request */ | ||
8728 | plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */ | ||
8729 | plci->req_in_start = plci->req_in; | ||
8730 | } | ||
8731 | |||
8732 | void send_req(PLCI * plci) | ||
8733 | { | ||
8734 | ENTITY * e; | ||
8735 | word l; | ||
8736 | /* word i; */ | ||
8737 | |||
8738 | if(!plci) return; | ||
8739 | if(plci->adapter->adapter_disabled) return; | ||
8740 | channel_xmit_xon (plci); | ||
8741 | |||
8742 | /* if nothing to do, return */ | ||
8743 | if(plci->req_in==plci->req_out) return; | ||
8744 | dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out)); | ||
8745 | |||
8746 | if(plci->nl_req || plci->sig_req) return; | ||
8747 | |||
8748 | l = GET_WORD(&plci->RBuffer[plci->req_out]); | ||
8749 | plci->req_out += 2; | ||
8750 | plci->XData[0].P = &plci->RBuffer[plci->req_out]; | ||
8751 | plci->req_out += l; | ||
8752 | if(plci->RBuffer[plci->req_out]==1) | ||
8753 | { | ||
8754 | e = &plci->NL; | ||
8755 | plci->req_out++; | ||
8756 | e->Req = plci->nl_req = plci->RBuffer[plci->req_out++]; | ||
8757 | e->ReqCh = plci->RBuffer[plci->req_out++]; | ||
8758 | if(!(e->Id & 0x1f)) | ||
8759 | { | ||
8760 | e->Id = NL_ID; | ||
8761 | plci->RBuffer[plci->req_out-4] = CAI; | ||
8762 | plci->RBuffer[plci->req_out-3] = 1; | ||
8763 | plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id; | ||
8764 | plci->RBuffer[plci->req_out-1] = 0; | ||
8765 | l+=3; | ||
8766 | plci->nl_global_req = plci->nl_req; | ||
8767 | } | ||
8768 | dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh)); | ||
8769 | } | ||
8770 | else | ||
8771 | { | ||
8772 | e = &plci->Sig; | ||
8773 | if(plci->RBuffer[plci->req_out]) | ||
8774 | e->Id = plci->RBuffer[plci->req_out]; | ||
8775 | plci->req_out++; | ||
8776 | e->Req = plci->sig_req = plci->RBuffer[plci->req_out++]; | ||
8777 | e->ReqCh = plci->RBuffer[plci->req_out++]; | ||
8778 | if(!(e->Id & 0x1f)) | ||
8779 | plci->sig_global_req = plci->sig_req; | ||
8780 | dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh)); | ||
8781 | } | ||
8782 | plci->XData[0].PLength = l; | ||
8783 | e->X = plci->XData; | ||
8784 | plci->adapter->request(e); | ||
8785 | dbug(1,dprintf("send_ok")); | ||
8786 | } | ||
8787 | |||
8788 | void send_data(PLCI * plci) | ||
8789 | { | ||
8790 | DIVA_CAPI_ADAPTER * a; | ||
8791 | DATA_B3_DESC * data; | ||
8792 | NCCI *ncci_ptr; | ||
8793 | word ncci; | ||
8794 | |||
8795 | if (!plci->nl_req && plci->ncci_ring_list) | ||
8796 | { | ||
8797 | a = plci->adapter; | ||
8798 | ncci = plci->ncci_ring_list; | ||
8799 | do | ||
8800 | { | ||
8801 | ncci = a->ncci_next[ncci]; | ||
8802 | ncci_ptr = &(a->ncci[ncci]); | ||
8803 | if (!(a->ncci_ch[ncci] | ||
8804 | && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING))) | ||
8805 | { | ||
8806 | if (ncci_ptr->data_pending) | ||
8807 | { | ||
8808 | if ((a->ncci_state[ncci] == CONNECTED) | ||
8809 | || (a->ncci_state[ncci] == INC_ACT_PENDING) | ||
8810 | || (plci->send_disc == ncci)) | ||
8811 | { | ||
8812 | data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]); | ||
8813 | if ((plci->B2_prot == B2_V120_ASYNC) | ||
8814 | || (plci->B2_prot == B2_V120_ASYNC_V42BIS) | ||
8815 | || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)) | ||
8816 | { | ||
8817 | plci->NData[1].P = TransmitBufferGet (plci->appl, data->P); | ||
8818 | plci->NData[1].PLength = data->Length; | ||
8819 | if (data->Flags & 0x10) | ||
8820 | plci->NData[0].P = v120_break_header; | ||
8821 | else | ||
8822 | plci->NData[0].P = v120_default_header; | ||
8823 | plci->NData[0].PLength = 1 ; | ||
8824 | plci->NL.XNum = 2; | ||
8825 | plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA); | ||
8826 | } | ||
8827 | else | ||
8828 | { | ||
8829 | plci->NData[0].P = TransmitBufferGet (plci->appl, data->P); | ||
8830 | plci->NData[0].PLength = data->Length; | ||
8831 | if (data->Flags & 0x10) | ||
8832 | plci->NL.Req = plci->nl_req = (byte)N_UDATA; | ||
8833 | |||
8834 | else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01)) | ||
8835 | plci->NL.Req = plci->nl_req = (byte)N_BDATA; | ||
8836 | |||
8837 | else | ||
8838 | plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA); | ||
8839 | } | ||
8840 | plci->NL.X = plci->NData; | ||
8841 | plci->NL.ReqCh = a->ncci_ch[ncci]; | ||
8842 | dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req)); | ||
8843 | plci->data_sent = TRUE; | ||
8844 | plci->data_sent_ptr = data->P; | ||
8845 | a->request(&plci->NL); | ||
8846 | } | ||
8847 | else { | ||
8848 | cleanup_ncci_data (plci, ncci); | ||
8849 | } | ||
8850 | } | ||
8851 | else if (plci->send_disc == ncci) | ||
8852 | { | ||
8853 | /* dprintf("N_DISC"); */ | ||
8854 | plci->NData[0].PLength = 0; | ||
8855 | plci->NL.ReqCh = a->ncci_ch[ncci]; | ||
8856 | plci->NL.Req = plci->nl_req = N_DISC; | ||
8857 | a->request(&plci->NL); | ||
8858 | plci->command = _DISCONNECT_B3_R; | ||
8859 | plci->send_disc = 0; | ||
8860 | } | ||
8861 | } | ||
8862 | } while (!plci->nl_req && (ncci != plci->ncci_ring_list)); | ||
8863 | plci->ncci_ring_list = ncci; | ||
8864 | } | ||
8865 | } | ||
8866 | |||
8867 | void listen_check(DIVA_CAPI_ADAPTER * a) | ||
8868 | { | ||
8869 | word i,j; | ||
8870 | PLCI * plci; | ||
8871 | byte activnotifiedcalls = 0; | ||
8872 | |||
8873 | dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen)); | ||
8874 | if (!remove_started && !a->adapter_disabled) | ||
8875 | { | ||
8876 | for(i=0;i<a->max_plci;i++) | ||
8877 | { | ||
8878 | plci = &(a->plci[i]); | ||
8879 | if(plci->notifiedcall) activnotifiedcalls++; | ||
8880 | } | ||
8881 | dbug(1,dprintf("listen_check(%d)",activnotifiedcalls)); | ||
8882 | |||
8883 | for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) { | ||
8884 | if((j=get_plci(a))) { | ||
8885 | a->listen_active++; | ||
8886 | plci = &a->plci[j-1]; | ||
8887 | plci->State = LISTENING; | ||
8888 | |||
8889 | add_p(plci,OAD,"\x01\xfd"); | ||
8890 | |||
8891 | add_p(plci,KEY,"\x04\x43\x41\x32\x30"); | ||
8892 | |||
8893 | add_p(plci,CAI,"\x01\xc0"); | ||
8894 | add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
8895 | add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */ | ||
8896 | add_p(plci,SHIFT|6,NULL); | ||
8897 | add_p(plci,SIN,"\x02\x00\x00"); | ||
8898 | plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */ | ||
8899 | sig_req(plci,ASSIGN,DSIG_ID); | ||
8900 | send_req(plci); | ||
8901 | } | ||
8902 | } | ||
8903 | } | ||
8904 | } | ||
8905 | |||
8906 | /*------------------------------------------------------------------*/ | ||
8907 | /* functions for all parameters sent in INDs */ | ||
8908 | /*------------------------------------------------------------------*/ | ||
8909 | |||
8910 | void IndParse(PLCI * plci, word * parms_id, byte ** parms, byte multiIEsize) | ||
8911 | { | ||
8912 | word ploc; /* points to current location within packet */ | ||
8913 | byte w; | ||
8914 | byte wlen; | ||
8915 | byte codeset,lock; | ||
8916 | byte * in; | ||
8917 | word i; | ||
8918 | word code; | ||
8919 | word mIEindex = 0; | ||
8920 | ploc = 0; | ||
8921 | codeset = 0; | ||
8922 | lock = 0; | ||
8923 | |||
8924 | in = plci->Sig.RBuffer->P; | ||
8925 | for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */ | ||
8926 | { /* element but parms array is larger */ | ||
8927 | parms[i] = (byte *)""; | ||
8928 | } | ||
8929 | for(i=0; i<multiIEsize; i++) | ||
8930 | { | ||
8931 | parms[i] = (byte *)""; | ||
8932 | } | ||
8933 | |||
8934 | while(ploc<plci->Sig.RBuffer->length-1) { | ||
8935 | |||
8936 | /* read information element id and length */ | ||
8937 | w = in[ploc]; | ||
8938 | |||
8939 | if(w & 0x80) { | ||
8940 | /* w &=0xf0; removed, cannot detect congestion levels */ | ||
8941 | /* upper 4 bit masked with w==SHIFT now */ | ||
8942 | wlen = 0; | ||
8943 | } | ||
8944 | else { | ||
8945 | wlen = (byte)(in[ploc+1]+1); | ||
8946 | } | ||
8947 | /* check if length valid (not exceeding end of packet) */ | ||
8948 | if((ploc+wlen) > 270) return ; | ||
8949 | if(lock & 0x80) lock &=0x7f; | ||
8950 | else codeset = lock; | ||
8951 | |||
8952 | if((w&0xf0)==SHIFT) { | ||
8953 | codeset = in[ploc]; | ||
8954 | if(!(codeset & 0x08)) lock = (byte)(codeset & 7); | ||
8955 | codeset &=7; | ||
8956 | lock |=0x80; | ||
8957 | } | ||
8958 | else { | ||
8959 | if(w==ESC && wlen>=3) code = in[ploc+2] |0x800; | ||
8960 | else code = w; | ||
8961 | code |= (codeset<<8); | ||
8962 | |||
8963 | for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++); | ||
8964 | |||
8965 | if(i<parms_id[0]+1) { | ||
8966 | if(!multiIEsize) { /* with multiIEs use next field index, */ | ||
8967 | mIEindex = i-1; /* with normal IEs use same index like parms_id */ | ||
8968 | } | ||
8969 | |||
8970 | parms[mIEindex] = &in[ploc+1]; | ||
8971 | dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc])); | ||
8972 | if(parms_id[i]==OAD | ||
8973 | || parms_id[i]==CONN_NR | ||
8974 | || parms_id[i]==CAD) { | ||
8975 | if(in[ploc+2] &0x80) { | ||
8976 | in[ploc+0] = (byte)(in[ploc+1]+1); | ||
8977 | in[ploc+1] = (byte)(in[ploc+2] &0x7f); | ||
8978 | in[ploc+2] = 0x80; | ||
8979 | parms[mIEindex] = &in[ploc]; | ||
8980 | } | ||
8981 | } | ||
8982 | mIEindex++; /* effects multiIEs only */ | ||
8983 | } | ||
8984 | } | ||
8985 | |||
8986 | ploc +=(wlen+1); | ||
8987 | } | ||
8988 | return ; | ||
8989 | } | ||
8990 | |||
8991 | /*------------------------------------------------------------------*/ | ||
8992 | /* try to match a cip from received BC and HLC */ | ||
8993 | /*------------------------------------------------------------------*/ | ||
8994 | |||
8995 | byte ie_compare(byte * ie1, byte * ie2) | ||
8996 | { | ||
8997 | word i; | ||
8998 | if(!ie1 || ! ie2) return FALSE; | ||
8999 | if(!ie1[0]) return FALSE; | ||
9000 | for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE; | ||
9001 | return TRUE; | ||
9002 | } | ||
9003 | |||
9004 | word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc) | ||
9005 | { | ||
9006 | word i; | ||
9007 | word j; | ||
9008 | |||
9009 | for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--); | ||
9010 | |||
9011 | for(j=16;j<29 && | ||
9012 | (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++); | ||
9013 | if(j==29) return i; | ||
9014 | return j; | ||
9015 | } | ||
9016 | |||
9017 | |||
9018 | static byte AddInfo(byte **add_i, | ||
9019 | byte **fty_i, | ||
9020 | byte *esc_chi, | ||
9021 | byte *facility) | ||
9022 | { | ||
9023 | byte i; | ||
9024 | byte j; | ||
9025 | byte k; | ||
9026 | byte flen; | ||
9027 | byte len=0; | ||
9028 | /* facility is a nested structure */ | ||
9029 | /* FTY can be more than once */ | ||
9030 | |||
9031 | if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f ) | ||
9032 | { | ||
9033 | add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */ | ||
9034 | } | ||
9035 | |||
9036 | else | ||
9037 | { | ||
9038 | add_i[0] = (byte *)""; | ||
9039 | } | ||
9040 | if(!fty_i[0][0]) | ||
9041 | { | ||
9042 | add_i[3] = (byte *)""; | ||
9043 | } | ||
9044 | else | ||
9045 | { /* facility array found */ | ||
9046 | for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++) | ||
9047 | { | ||
9048 | dbug(1,dprintf("AddIFac[%d]",fty_i[i][0])); | ||
9049 | len += fty_i[i][0]; | ||
9050 | len += 2; | ||
9051 | flen=fty_i[i][0]; | ||
9052 | facility[j++]=0x1c; /* copy fac IE */ | ||
9053 | for(k=0;k<=flen;k++,j++) | ||
9054 | { | ||
9055 | facility[j]=fty_i[i][k]; | ||
9056 | /* dbug(1,dprintf("%x ",facility[j])); */ | ||
9057 | } | ||
9058 | } | ||
9059 | facility[0] = len; | ||
9060 | add_i[3] = facility; | ||
9061 | } | ||
9062 | /* dbug(1,dprintf("FacArrLen=%d ",len)); */ | ||
9063 | len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0]; | ||
9064 | len += 4; /* calculate length of all */ | ||
9065 | return(len); | ||
9066 | } | ||
9067 | |||
9068 | /*------------------------------------------------------------------*/ | ||
9069 | /* voice and codec features */ | ||
9070 | /*------------------------------------------------------------------*/ | ||
9071 | |||
9072 | void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER * a) | ||
9073 | { | ||
9074 | byte voice_chi[] = "\x02\x18\x01"; | ||
9075 | byte channel; | ||
9076 | |||
9077 | channel = chi[chi[0]]&0x3; | ||
9078 | dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel)); | ||
9079 | voice_chi[2] = (channel) ? channel : 1; | ||
9080 | add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */ | ||
9081 | add_p(plci,ESC,voice_chi); /* Channel */ | ||
9082 | sig_req(plci,TEL_CTRL,0); | ||
9083 | send_req(plci); | ||
9084 | if(a->AdvSignalPLCI) | ||
9085 | { | ||
9086 | adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION); | ||
9087 | } | ||
9088 | } | ||
9089 | |||
9090 | void VoiceChannelOff(PLCI *plci) | ||
9091 | { | ||
9092 | dbug(1,dprintf("ExtDevOFF")); | ||
9093 | add_p(plci,FTY,"\x02\x01\x08"); /* B Off */ | ||
9094 | sig_req(plci,TEL_CTRL,0); | ||
9095 | send_req(plci); | ||
9096 | if(plci->adapter->AdvSignalPLCI) | ||
9097 | { | ||
9098 | adv_voice_clear_config (plci->adapter->AdvSignalPLCI); | ||
9099 | } | ||
9100 | } | ||
9101 | |||
9102 | |||
9103 | word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte hook_listen) | ||
9104 | { | ||
9105 | word j; | ||
9106 | PLCI *splci; | ||
9107 | |||
9108 | /* check if hardware supports handset with hook states (adv.codec) */ | ||
9109 | /* or if just a on board codec is supported */ | ||
9110 | /* the advanced codec plci is just for internal use */ | ||
9111 | |||
9112 | /* diva Pro with on-board codec: */ | ||
9113 | if(a->profile.Global_Options & HANDSET) | ||
9114 | { | ||
9115 | /* new call, but hook states are already signalled */ | ||
9116 | if(a->AdvCodecFLAG) | ||
9117 | { | ||
9118 | if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI) | ||
9119 | { | ||
9120 | dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI)); | ||
9121 | return 0x2001; /* codec in use by another application */ | ||
9122 | } | ||
9123 | if(plci!=0) | ||
9124 | { | ||
9125 | a->AdvSignalPLCI = plci; | ||
9126 | plci->tel=ADV_VOICE; | ||
9127 | } | ||
9128 | return 0; /* adv codec still used */ | ||
9129 | } | ||
9130 | if((j=get_plci(a))) | ||
9131 | { | ||
9132 | splci = &a->plci[j-1]; | ||
9133 | splci->tel = CODEC_PERMANENT; | ||
9134 | /* hook_listen indicates if a facility_req with handset/hook support */ | ||
9135 | /* was sent. Otherwise if just a call on an external device was made */ | ||
9136 | /* the codec will be used but the hook info will be discarded (just */ | ||
9137 | /* the external controller is in use */ | ||
9138 | if(hook_listen) splci->State = ADVANCED_VOICE_SIG; | ||
9139 | else | ||
9140 | { | ||
9141 | splci->State = ADVANCED_VOICE_NOSIG; | ||
9142 | if(plci) | ||
9143 | { | ||
9144 | plci->spoofed_msg = SPOOFING_REQUIRED; | ||
9145 | } | ||
9146 | /* indicate D-ch connect if */ | ||
9147 | } /* codec is connected OK */ | ||
9148 | if(plci!=0) | ||
9149 | { | ||
9150 | a->AdvSignalPLCI = plci; | ||
9151 | plci->tel=ADV_VOICE; | ||
9152 | } | ||
9153 | a->AdvSignalAppl = appl; | ||
9154 | a->AdvCodecFLAG = TRUE; | ||
9155 | a->AdvCodecPLCI = splci; | ||
9156 | add_p(splci,CAI,"\x01\x15"); | ||
9157 | add_p(splci,LLI,"\x01\x00"); | ||
9158 | add_p(splci,ESC,"\x02\x18\x00"); | ||
9159 | add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
9160 | splci->internal_command = PERM_COD_ASSIGN; | ||
9161 | dbug(1,dprintf("Codec Assign")); | ||
9162 | sig_req(splci,ASSIGN,DSIG_ID); | ||
9163 | send_req(splci); | ||
9164 | } | ||
9165 | else | ||
9166 | { | ||
9167 | return 0x2001; /* wrong state, no more plcis */ | ||
9168 | } | ||
9169 | } | ||
9170 | else if(a->profile.Global_Options & ON_BOARD_CODEC) | ||
9171 | { | ||
9172 | if(hook_listen) return 0x300B; /* Facility not supported */ | ||
9173 | /* no hook with SCOM */ | ||
9174 | if(plci!=0) plci->tel = CODEC; | ||
9175 | dbug(1,dprintf("S/SCOM codec")); | ||
9176 | /* first time we use the scom-s codec we must shut down the internal */ | ||
9177 | /* handset application of the card. This can be done by an assign with */ | ||
9178 | /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/ | ||
9179 | if(!a->scom_appl_disable){ | ||
9180 | if((j=get_plci(a))) { | ||
9181 | splci = &a->plci[j-1]; | ||
9182 | add_p(splci,CAI,"\x01\x80"); | ||
9183 | add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
9184 | sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */ | ||
9185 | send_req(splci); | ||
9186 | a->scom_appl_disable = TRUE; | ||
9187 | } | ||
9188 | else{ | ||
9189 | return 0x2001; /* wrong state, no more plcis */ | ||
9190 | } | ||
9191 | } | ||
9192 | } | ||
9193 | else return 0x300B; /* Facility not supported */ | ||
9194 | |||
9195 | return 0; | ||
9196 | } | ||
9197 | |||
9198 | |||
9199 | void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci) | ||
9200 | { | ||
9201 | |||
9202 | dbug(1,dprintf("CodecIdCheck")); | ||
9203 | |||
9204 | if(a->AdvSignalPLCI == plci) | ||
9205 | { | ||
9206 | dbug(1,dprintf("PLCI owns codec")); | ||
9207 | VoiceChannelOff(a->AdvCodecPLCI); | ||
9208 | if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG) | ||
9209 | { | ||
9210 | dbug(1,dprintf("remove temp codec PLCI")); | ||
9211 | plci_remove(a->AdvCodecPLCI); | ||
9212 | a->AdvCodecFLAG = 0; | ||
9213 | a->AdvCodecPLCI = NULL; | ||
9214 | a->AdvSignalAppl = NULL; | ||
9215 | } | ||
9216 | a->AdvSignalPLCI = NULL; | ||
9217 | } | ||
9218 | } | ||
9219 | |||
9220 | /* ------------------------------------------------------------------- | ||
9221 | Ask for physical address of card on PCI bus | ||
9222 | ------------------------------------------------------------------- */ | ||
9223 | static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a, | ||
9224 | IDI_SYNC_REQ * preq) { | ||
9225 | a->sdram_bar = 0; | ||
9226 | if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) { | ||
9227 | ENTITY * e = (ENTITY *)preq; | ||
9228 | |||
9229 | e->user[0] = a->Id - 1; | ||
9230 | preq->xdi_sdram_bar.info.bar = 0; | ||
9231 | preq->xdi_sdram_bar.Req = 0; | ||
9232 | preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR; | ||
9233 | |||
9234 | (*(a->request))(e); | ||
9235 | |||
9236 | a->sdram_bar = preq->xdi_sdram_bar.info.bar; | ||
9237 | dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar)); | ||
9238 | } | ||
9239 | } | ||
9240 | |||
9241 | /* ------------------------------------------------------------------- | ||
9242 | Ask XDI about extended features | ||
9243 | ------------------------------------------------------------------- */ | ||
9244 | static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) { | ||
9245 | IDI_SYNC_REQ * preq; | ||
9246 | char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)]; | ||
9247 | |||
9248 | char features[4]; | ||
9249 | preq = (IDI_SYNC_REQ *)&buffer[0]; | ||
9250 | |||
9251 | if (!diva_xdi_extended_features) { | ||
9252 | ENTITY * e = (ENTITY *)preq; | ||
9253 | diva_xdi_extended_features |= 0x80000000; | ||
9254 | |||
9255 | e->user[0] = a->Id - 1; | ||
9256 | preq->xdi_extended_features.Req = 0; | ||
9257 | preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES; | ||
9258 | preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features); | ||
9259 | preq->xdi_extended_features.info.features = &features[0]; | ||
9260 | |||
9261 | (*(a->request))(e); | ||
9262 | |||
9263 | if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) { | ||
9264 | /* | ||
9265 | Check features located in the byte '0' | ||
9266 | */ | ||
9267 | if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) { | ||
9268 | diva_xdi_extended_features |= DIVA_CAPI_USE_CMA; | ||
9269 | } | ||
9270 | if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) { | ||
9271 | diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA; | ||
9272 | dbug(1,dprintf("XDI provides RxDMA")); | ||
9273 | } | ||
9274 | if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) { | ||
9275 | diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR; | ||
9276 | } | ||
9277 | if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) { | ||
9278 | diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL; | ||
9279 | dbug(3,dprintf("XDI provides NO_CANCEL_RC feature")); | ||
9280 | } | ||
9281 | |||
9282 | } | ||
9283 | } | ||
9284 | |||
9285 | diva_ask_for_xdi_sdram_bar (a, preq); | ||
9286 | } | ||
9287 | |||
9288 | /*------------------------------------------------------------------*/ | ||
9289 | /* automatic law */ | ||
9290 | /*------------------------------------------------------------------*/ | ||
9291 | /* called from OS specific part after init time to get the Law */ | ||
9292 | /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */ | ||
9293 | void AutomaticLaw(DIVA_CAPI_ADAPTER *a) | ||
9294 | { | ||
9295 | word j; | ||
9296 | PLCI *splci; | ||
9297 | |||
9298 | if(a->automatic_law) { | ||
9299 | return; | ||
9300 | } | ||
9301 | if((j=get_plci(a))) { | ||
9302 | diva_get_extended_adapter_features (a); | ||
9303 | splci = &a->plci[j-1]; | ||
9304 | a->automatic_lawPLCI = splci; | ||
9305 | a->automatic_law = 1; | ||
9306 | add_p(splci,CAI,"\x01\x80"); | ||
9307 | add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
9308 | splci->internal_command = USELAW_REQ; | ||
9309 | splci->command = 0; | ||
9310 | splci->number = 0; | ||
9311 | sig_req(splci,ASSIGN,DSIG_ID); | ||
9312 | send_req(splci); | ||
9313 | } | ||
9314 | } | ||
9315 | |||
9316 | /* called from OS specific part if an application sends an Capi20Release */ | ||
9317 | word CapiRelease(word Id) | ||
9318 | { | ||
9319 | word i, j, appls_found; | ||
9320 | PLCI *plci; | ||
9321 | APPL *this; | ||
9322 | DIVA_CAPI_ADAPTER *a; | ||
9323 | |||
9324 | if (!Id) | ||
9325 | { | ||
9326 | dbug(0,dprintf("A: CapiRelease(Id==0)")); | ||
9327 | return (_WRONG_APPL_ID); | ||
9328 | } | ||
9329 | |||
9330 | this = &application[Id-1]; /* get application pointer */ | ||
9331 | |||
9332 | for(i=0,appls_found=0; i<max_appl; i++) | ||
9333 | { | ||
9334 | if(application[i].Id) /* an application has been found */ | ||
9335 | { | ||
9336 | appls_found++; | ||
9337 | } | ||
9338 | } | ||
9339 | |||
9340 | for(i=0; i<max_adapter; i++) /* scan all adapters... */ | ||
9341 | { | ||
9342 | a = &adapter[i]; | ||
9343 | if (a->request) | ||
9344 | { | ||
9345 | a->Info_Mask[Id-1] = 0; | ||
9346 | a->CIP_Mask[Id-1] = 0; | ||
9347 | a->Notification_Mask[Id-1] = 0; | ||
9348 | a->codec_listen[Id-1] = NULL; | ||
9349 | a->requested_options_table[Id-1] = 0; | ||
9350 | for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */ | ||
9351 | { /* with this application */ | ||
9352 | plci = &a->plci[j]; | ||
9353 | if(plci->Id) /* if plci owns no application */ | ||
9354 | { /* it may be not jet connected */ | ||
9355 | if(plci->State==INC_CON_PENDING | ||
9356 | || plci->State==INC_CON_ALERT) | ||
9357 | { | ||
9358 | if(test_c_ind_mask_bit (plci, (word)(Id-1))) | ||
9359 | { | ||
9360 | clear_c_ind_mask_bit (plci, (word)(Id-1)); | ||
9361 | if(c_ind_mask_empty (plci)) | ||
9362 | { | ||
9363 | sig_req(plci,HANGUP,0); | ||
9364 | send_req(plci); | ||
9365 | plci->State = OUTG_DIS_PENDING; | ||
9366 | } | ||
9367 | } | ||
9368 | } | ||
9369 | if(test_c_ind_mask_bit (plci, (word)(Id-1))) | ||
9370 | { | ||
9371 | clear_c_ind_mask_bit (plci, (word)(Id-1)); | ||
9372 | if(c_ind_mask_empty (plci)) | ||
9373 | { | ||
9374 | if(!plci->appl) | ||
9375 | { | ||
9376 | plci_remove(plci); | ||
9377 | plci->State = IDLE; | ||
9378 | } | ||
9379 | } | ||
9380 | } | ||
9381 | if(plci->appl==this) | ||
9382 | { | ||
9383 | plci->appl = NULL; | ||
9384 | plci_remove(plci); | ||
9385 | plci->State = IDLE; | ||
9386 | } | ||
9387 | } | ||
9388 | } | ||
9389 | listen_check(a); | ||
9390 | |||
9391 | if(a->flag_dynamic_l1_down) | ||
9392 | { | ||
9393 | if(appls_found==1) /* last application does a capi release */ | ||
9394 | { | ||
9395 | if((j=get_plci(a))) | ||
9396 | { | ||
9397 | plci = &a->plci[j-1]; | ||
9398 | plci->command = 0; | ||
9399 | add_p(plci,OAD,"\x01\xfd"); | ||
9400 | add_p(plci,CAI,"\x01\x80"); | ||
9401 | add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
9402 | add_p(plci,SHIFT|6,NULL); | ||
9403 | add_p(plci,SIN,"\x02\x00\x00"); | ||
9404 | plci->internal_command = REM_L1_SIG_ASSIGN_PEND; | ||
9405 | sig_req(plci,ASSIGN,DSIG_ID); | ||
9406 | add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */ | ||
9407 | sig_req(plci,SIG_CTRL,0); | ||
9408 | send_req(plci); | ||
9409 | } | ||
9410 | } | ||
9411 | } | ||
9412 | if(a->AdvSignalAppl==this) | ||
9413 | { | ||
9414 | this->NullCREnable = FALSE; | ||
9415 | if (a->AdvCodecPLCI) | ||
9416 | { | ||
9417 | plci_remove(a->AdvCodecPLCI); | ||
9418 | a->AdvCodecPLCI->tel = 0; | ||
9419 | a->AdvCodecPLCI->adv_nl = 0; | ||
9420 | } | ||
9421 | a->AdvSignalAppl = NULL; | ||
9422 | a->AdvSignalPLCI = NULL; | ||
9423 | a->AdvCodecFLAG = 0; | ||
9424 | a->AdvCodecPLCI = NULL; | ||
9425 | } | ||
9426 | } | ||
9427 | } | ||
9428 | |||
9429 | this->Id = 0; | ||
9430 | |||
9431 | return GOOD; | ||
9432 | } | ||
9433 | |||
9434 | static word plci_remove_check(PLCI *plci) | ||
9435 | { | ||
9436 | if(!plci) return TRUE; | ||
9437 | if(!plci->NL.Id && c_ind_mask_empty (plci)) | ||
9438 | { | ||
9439 | if(plci->Sig.Id == 0xff) | ||
9440 | plci->Sig.Id = 0; | ||
9441 | if(!plci->Sig.Id) | ||
9442 | { | ||
9443 | dbug(1,dprintf("plci_remove_complete(%x)",plci->Id)); | ||
9444 | dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id)); | ||
9445 | if (plci->Id) | ||
9446 | { | ||
9447 | CodecIdCheck(plci->adapter, plci); | ||
9448 | clear_b1_config (plci); | ||
9449 | ncci_remove (plci, 0, FALSE); | ||
9450 | plci_free_msg_in_queue (plci); | ||
9451 | channel_flow_control_remove (plci); | ||
9452 | plci->Id = 0; | ||
9453 | plci->State = IDLE; | ||
9454 | plci->channels = 0; | ||
9455 | plci->appl = NULL; | ||
9456 | plci->notifiedcall = 0; | ||
9457 | } | ||
9458 | listen_check(plci->adapter); | ||
9459 | return TRUE; | ||
9460 | } | ||
9461 | } | ||
9462 | return FALSE; | ||
9463 | } | ||
9464 | |||
9465 | |||
9466 | /*------------------------------------------------------------------*/ | ||
9467 | |||
9468 | static byte plci_nl_busy (PLCI *plci) | ||
9469 | { | ||
9470 | /* only applicable for non-multiplexed protocols */ | ||
9471 | return (plci->nl_req | ||
9472 | || (plci->ncci_ring_list | ||
9473 | && plci->adapter->ncci_ch[plci->ncci_ring_list] | ||
9474 | && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING))); | ||
9475 | } | ||
9476 | |||
9477 | |||
9478 | /*------------------------------------------------------------------*/ | ||
9479 | /* DTMF facilities */ | ||
9480 | /*------------------------------------------------------------------*/ | ||
9481 | |||
9482 | |||
9483 | static struct | ||
9484 | { | ||
9485 | byte send_mask; | ||
9486 | byte listen_mask; | ||
9487 | byte character; | ||
9488 | byte code; | ||
9489 | } dtmf_digit_map[] = | ||
9490 | { | ||
9491 | { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK }, | ||
9492 | { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR }, | ||
9493 | { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 }, | ||
9494 | { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 }, | ||
9495 | { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 }, | ||
9496 | { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 }, | ||
9497 | { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 }, | ||
9498 | { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 }, | ||
9499 | { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 }, | ||
9500 | { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 }, | ||
9501 | { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 }, | ||
9502 | { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 }, | ||
9503 | { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A }, | ||
9504 | { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B }, | ||
9505 | { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C }, | ||
9506 | { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D }, | ||
9507 | { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A }, | ||
9508 | { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B }, | ||
9509 | { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C }, | ||
9510 | { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D }, | ||
9511 | |||
9512 | { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE }, | ||
9513 | { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE }, | ||
9514 | { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE }, | ||
9515 | { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE }, | ||
9516 | { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE }, | ||
9517 | { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE }, | ||
9518 | { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE }, | ||
9519 | { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE }, | ||
9520 | { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE }, | ||
9521 | { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE }, | ||
9522 | { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE }, | ||
9523 | { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE }, | ||
9524 | { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE }, | ||
9525 | { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE }, | ||
9526 | { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE }, | ||
9527 | { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE }, | ||
9528 | { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE }, | ||
9529 | { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE }, | ||
9530 | { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE }, | ||
9531 | { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE }, | ||
9532 | { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE }, | ||
9533 | { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE }, | ||
9534 | { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE }, | ||
9535 | { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL }, | ||
9536 | { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE }, | ||
9537 | { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE }, | ||
9538 | { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE }, | ||
9539 | { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE }, | ||
9540 | { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE }, | ||
9541 | { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE }, | ||
9542 | { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE }, | ||
9543 | { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE }, | ||
9544 | { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE }, | ||
9545 | { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS }, | ||
9546 | { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID }, | ||
9547 | { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH }, | ||
9548 | { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 }, | ||
9549 | { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 }, | ||
9550 | { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 }, | ||
9551 | { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 }, | ||
9552 | { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 }, | ||
9553 | { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 }, | ||
9554 | { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 }, | ||
9555 | { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 }, | ||
9556 | { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 }, | ||
9557 | { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 }, | ||
9558 | { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 }, | ||
9559 | { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 }, | ||
9560 | { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 }, | ||
9561 | { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP }, | ||
9562 | { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 }, | ||
9563 | { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST }, | ||
9564 | |||
9565 | }; | ||
9566 | |||
9567 | #define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0])) | ||
9568 | |||
9569 | |||
9570 | static void dtmf_enable_receiver (PLCI *plci, byte enable_mask) | ||
9571 | { | ||
9572 | word min_digit_duration, min_gap_duration; | ||
9573 | |||
9574 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x", | ||
9575 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
9576 | (char *)(FILE_), __LINE__, enable_mask)); | ||
9577 | |||
9578 | if (enable_mask != 0) | ||
9579 | { | ||
9580 | min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms; | ||
9581 | min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms; | ||
9582 | plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER; | ||
9583 | PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration); | ||
9584 | PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration); | ||
9585 | plci->NData[0].PLength = 5; | ||
9586 | |||
9587 | PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE); | ||
9588 | plci->NData[0].PLength += 2; | ||
9589 | capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration); | ||
9590 | |||
9591 | } | ||
9592 | else | ||
9593 | { | ||
9594 | plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER; | ||
9595 | plci->NData[0].PLength = 1; | ||
9596 | |||
9597 | capidtmf_recv_disable (&(plci->capidtmf_state)); | ||
9598 | |||
9599 | } | ||
9600 | plci->NData[0].P = plci->internal_req_buffer; | ||
9601 | plci->NL.X = plci->NData; | ||
9602 | plci->NL.ReqCh = 0; | ||
9603 | plci->NL.Req = plci->nl_req = (byte) N_UDATA; | ||
9604 | plci->adapter->request (&plci->NL); | ||
9605 | } | ||
9606 | |||
9607 | |||
9608 | static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count) | ||
9609 | { | ||
9610 | word w, i; | ||
9611 | |||
9612 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d", | ||
9613 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
9614 | (char *)(FILE_), __LINE__, digit_count)); | ||
9615 | |||
9616 | plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS; | ||
9617 | w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms; | ||
9618 | PUT_WORD (&plci->internal_req_buffer[1], w); | ||
9619 | w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms; | ||
9620 | PUT_WORD (&plci->internal_req_buffer[3], w); | ||
9621 | for (i = 0; i < digit_count; i++) | ||
9622 | { | ||
9623 | w = 0; | ||
9624 | while ((w < DTMF_DIGIT_MAP_ENTRIES) | ||
9625 | && (digit_buffer[i] != dtmf_digit_map[w].character)) | ||
9626 | { | ||
9627 | w++; | ||
9628 | } | ||
9629 | plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ? | ||
9630 | dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR; | ||
9631 | } | ||
9632 | plci->NData[0].PLength = 5 + digit_count; | ||
9633 | plci->NData[0].P = plci->internal_req_buffer; | ||
9634 | plci->NL.X = plci->NData; | ||
9635 | plci->NL.ReqCh = 0; | ||
9636 | plci->NL.Req = plci->nl_req = (byte) N_UDATA; | ||
9637 | plci->adapter->request (&plci->NL); | ||
9638 | } | ||
9639 | |||
9640 | |||
9641 | static void dtmf_rec_clear_config (PLCI *plci) | ||
9642 | { | ||
9643 | |||
9644 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config", | ||
9645 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
9646 | (char *)(FILE_), __LINE__)); | ||
9647 | |||
9648 | plci->dtmf_rec_active = 0; | ||
9649 | plci->dtmf_rec_pulse_ms = 0; | ||
9650 | plci->dtmf_rec_pause_ms = 0; | ||
9651 | |||
9652 | capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law); | ||
9653 | |||
9654 | } | ||
9655 | |||
9656 | |||
9657 | static void dtmf_send_clear_config (PLCI *plci) | ||
9658 | { | ||
9659 | |||
9660 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config", | ||
9661 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
9662 | (char *)(FILE_), __LINE__)); | ||
9663 | |||
9664 | plci->dtmf_send_requests = 0; | ||
9665 | plci->dtmf_send_pulse_ms = 0; | ||
9666 | plci->dtmf_send_pause_ms = 0; | ||
9667 | } | ||
9668 | |||
9669 | |||
9670 | static void dtmf_prepare_switch (dword Id, PLCI *plci) | ||
9671 | { | ||
9672 | |||
9673 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch", | ||
9674 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9675 | |||
9676 | while (plci->dtmf_send_requests != 0) | ||
9677 | dtmf_confirmation (Id, plci); | ||
9678 | } | ||
9679 | |||
9680 | |||
9681 | static word dtmf_save_config (dword Id, PLCI *plci, byte Rc) | ||
9682 | { | ||
9683 | |||
9684 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d", | ||
9685 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
9686 | |||
9687 | return (GOOD); | ||
9688 | } | ||
9689 | |||
9690 | |||
9691 | static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc) | ||
9692 | { | ||
9693 | word Info; | ||
9694 | |||
9695 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d", | ||
9696 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
9697 | |||
9698 | Info = GOOD; | ||
9699 | if (plci->B1_facilities & B1_FACILITY_DTMFR) | ||
9700 | { | ||
9701 | switch (plci->adjust_b_state) | ||
9702 | { | ||
9703 | case ADJUST_B_RESTORE_DTMF_1: | ||
9704 | plci->internal_command = plci->adjust_b_command; | ||
9705 | if (plci_nl_busy (plci)) | ||
9706 | { | ||
9707 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | ||
9708 | break; | ||
9709 | } | ||
9710 | dtmf_enable_receiver (plci, plci->dtmf_rec_active); | ||
9711 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2; | ||
9712 | break; | ||
9713 | case ADJUST_B_RESTORE_DTMF_2: | ||
9714 | if ((Rc != OK) && (Rc != OK_FC)) | ||
9715 | { | ||
9716 | dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x", | ||
9717 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
9718 | Info = _WRONG_STATE; | ||
9719 | break; | ||
9720 | } | ||
9721 | break; | ||
9722 | } | ||
9723 | } | ||
9724 | return (Info); | ||
9725 | } | ||
9726 | |||
9727 | |||
9728 | static void dtmf_command (dword Id, PLCI *plci, byte Rc) | ||
9729 | { | ||
9730 | word internal_command, Info; | ||
9731 | byte mask; | ||
9732 | byte result[4]; | ||
9733 | |||
9734 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d", | ||
9735 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command, | ||
9736 | plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms, | ||
9737 | plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms)); | ||
9738 | |||
9739 | Info = GOOD; | ||
9740 | result[0] = 2; | ||
9741 | PUT_WORD (&result[1], DTMF_SUCCESS); | ||
9742 | internal_command = plci->internal_command; | ||
9743 | plci->internal_command = 0; | ||
9744 | mask = 0x01; | ||
9745 | switch (plci->dtmf_cmd) | ||
9746 | { | ||
9747 | |||
9748 | case DTMF_LISTEN_TONE_START: | ||
9749 | mask <<= 1; | ||
9750 | case DTMF_LISTEN_MF_START: | ||
9751 | mask <<= 1; | ||
9752 | |||
9753 | case DTMF_LISTEN_START: | ||
9754 | switch (internal_command) | ||
9755 | { | ||
9756 | default: | ||
9757 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | ||
9758 | B1_FACILITY_DTMFR), DTMF_COMMAND_1); | ||
9759 | case DTMF_COMMAND_1: | ||
9760 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
9761 | { | ||
9762 | dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed", | ||
9763 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9764 | Info = _FACILITY_NOT_SUPPORTED; | ||
9765 | break; | ||
9766 | } | ||
9767 | if (plci->internal_command) | ||
9768 | return; | ||
9769 | case DTMF_COMMAND_2: | ||
9770 | if (plci_nl_busy (plci)) | ||
9771 | { | ||
9772 | plci->internal_command = DTMF_COMMAND_2; | ||
9773 | return; | ||
9774 | } | ||
9775 | plci->internal_command = DTMF_COMMAND_3; | ||
9776 | dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask)); | ||
9777 | return; | ||
9778 | case DTMF_COMMAND_3: | ||
9779 | if ((Rc != OK) && (Rc != OK_FC)) | ||
9780 | { | ||
9781 | dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x", | ||
9782 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
9783 | Info = _FACILITY_NOT_SUPPORTED; | ||
9784 | break; | ||
9785 | } | ||
9786 | |||
9787 | plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE; | ||
9788 | |||
9789 | plci->dtmf_rec_active |= mask; | ||
9790 | break; | ||
9791 | } | ||
9792 | break; | ||
9793 | |||
9794 | |||
9795 | case DTMF_LISTEN_TONE_STOP: | ||
9796 | mask <<= 1; | ||
9797 | case DTMF_LISTEN_MF_STOP: | ||
9798 | mask <<= 1; | ||
9799 | |||
9800 | case DTMF_LISTEN_STOP: | ||
9801 | switch (internal_command) | ||
9802 | { | ||
9803 | default: | ||
9804 | plci->dtmf_rec_active &= ~mask; | ||
9805 | if (plci->dtmf_rec_active) | ||
9806 | break; | ||
9807 | /* | ||
9808 | case DTMF_COMMAND_1: | ||
9809 | if (plci->dtmf_rec_active) | ||
9810 | { | ||
9811 | if (plci_nl_busy (plci)) | ||
9812 | { | ||
9813 | plci->internal_command = DTMF_COMMAND_1; | ||
9814 | return; | ||
9815 | } | ||
9816 | plci->dtmf_rec_active &= ~mask; | ||
9817 | plci->internal_command = DTMF_COMMAND_2; | ||
9818 | dtmf_enable_receiver (plci, FALSE); | ||
9819 | return; | ||
9820 | } | ||
9821 | Rc = OK; | ||
9822 | case DTMF_COMMAND_2: | ||
9823 | if ((Rc != OK) && (Rc != OK_FC)) | ||
9824 | { | ||
9825 | dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x", | ||
9826 | UnMapId (Id), (char far *)(FILE_), __LINE__, Rc)); | ||
9827 | Info = _FACILITY_NOT_SUPPORTED; | ||
9828 | break; | ||
9829 | } | ||
9830 | */ | ||
9831 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities & | ||
9832 | ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3); | ||
9833 | case DTMF_COMMAND_3: | ||
9834 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
9835 | { | ||
9836 | dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed", | ||
9837 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9838 | Info = _FACILITY_NOT_SUPPORTED; | ||
9839 | break; | ||
9840 | } | ||
9841 | if (plci->internal_command) | ||
9842 | return; | ||
9843 | break; | ||
9844 | } | ||
9845 | break; | ||
9846 | |||
9847 | |||
9848 | case DTMF_SEND_TONE: | ||
9849 | mask <<= 1; | ||
9850 | case DTMF_SEND_MF: | ||
9851 | mask <<= 1; | ||
9852 | |||
9853 | case DTMF_DIGITS_SEND: | ||
9854 | switch (internal_command) | ||
9855 | { | ||
9856 | default: | ||
9857 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | ||
9858 | ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)), | ||
9859 | DTMF_COMMAND_1); | ||
9860 | case DTMF_COMMAND_1: | ||
9861 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
9862 | { | ||
9863 | dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed", | ||
9864 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9865 | Info = _FACILITY_NOT_SUPPORTED; | ||
9866 | break; | ||
9867 | } | ||
9868 | if (plci->internal_command) | ||
9869 | return; | ||
9870 | case DTMF_COMMAND_2: | ||
9871 | if (plci_nl_busy (plci)) | ||
9872 | { | ||
9873 | plci->internal_command = DTMF_COMMAND_2; | ||
9874 | return; | ||
9875 | } | ||
9876 | plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number; | ||
9877 | plci->internal_command = DTMF_COMMAND_3; | ||
9878 | dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length); | ||
9879 | return; | ||
9880 | case DTMF_COMMAND_3: | ||
9881 | if ((Rc != OK) && (Rc != OK_FC)) | ||
9882 | { | ||
9883 | dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x", | ||
9884 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
9885 | if (plci->dtmf_send_requests != 0) | ||
9886 | (plci->dtmf_send_requests)--; | ||
9887 | Info = _FACILITY_NOT_SUPPORTED; | ||
9888 | break; | ||
9889 | } | ||
9890 | return; | ||
9891 | } | ||
9892 | break; | ||
9893 | } | ||
9894 | sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number, | ||
9895 | "wws", Info, SELECTOR_DTMF, result); | ||
9896 | } | ||
9897 | |||
9898 | |||
9899 | static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg) | ||
9900 | { | ||
9901 | word Info; | ||
9902 | word i, j; | ||
9903 | byte mask; | ||
9904 | API_PARSE dtmf_parms[5]; | ||
9905 | byte result[40]; | ||
9906 | |||
9907 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request", | ||
9908 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9909 | |||
9910 | Info = GOOD; | ||
9911 | result[0] = 2; | ||
9912 | PUT_WORD (&result[1], DTMF_SUCCESS); | ||
9913 | if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED)) | ||
9914 | { | ||
9915 | dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | ||
9916 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9917 | Info = _FACILITY_NOT_SUPPORTED; | ||
9918 | } | ||
9919 | else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms)) | ||
9920 | { | ||
9921 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
9922 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9923 | Info = _WRONG_MESSAGE_FORMAT; | ||
9924 | } | ||
9925 | |||
9926 | else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) | ||
9927 | || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES)) | ||
9928 | { | ||
9929 | if (!((a->requested_options_table[appl->Id-1]) | ||
9930 | & (1L << PRIVATE_DTMF_TONE))) | ||
9931 | { | ||
9932 | dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | ||
9933 | UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); | ||
9934 | PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | ||
9935 | } | ||
9936 | else | ||
9937 | { | ||
9938 | for (i = 0; i < 32; i++) | ||
9939 | result[4 + i] = 0; | ||
9940 | if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) | ||
9941 | { | ||
9942 | for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++) | ||
9943 | { | ||
9944 | if (dtmf_digit_map[i].listen_mask != 0) | ||
9945 | result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7)); | ||
9946 | } | ||
9947 | } | ||
9948 | else | ||
9949 | { | ||
9950 | for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++) | ||
9951 | { | ||
9952 | if (dtmf_digit_map[i].send_mask != 0) | ||
9953 | result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7)); | ||
9954 | } | ||
9955 | } | ||
9956 | result[0] = 3 + 32; | ||
9957 | result[3] = 32; | ||
9958 | } | ||
9959 | } | ||
9960 | |||
9961 | else if (plci == NULL) | ||
9962 | { | ||
9963 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | ||
9964 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9965 | Info = _WRONG_IDENTIFIER; | ||
9966 | } | ||
9967 | else | ||
9968 | { | ||
9969 | if (!plci->State | ||
9970 | || !plci->NL.Id || plci->nl_remove_id) | ||
9971 | { | ||
9972 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | ||
9973 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
9974 | Info = _WRONG_STATE; | ||
9975 | } | ||
9976 | else | ||
9977 | { | ||
9978 | plci->command = 0; | ||
9979 | plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info); | ||
9980 | mask = 0x01; | ||
9981 | switch (plci->dtmf_cmd) | ||
9982 | { | ||
9983 | |||
9984 | case DTMF_LISTEN_TONE_START: | ||
9985 | case DTMF_LISTEN_TONE_STOP: | ||
9986 | mask <<= 1; | ||
9987 | case DTMF_LISTEN_MF_START: | ||
9988 | case DTMF_LISTEN_MF_STOP: | ||
9989 | mask <<= 1; | ||
9990 | if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1]) | ||
9991 | & (1L << PRIVATE_DTMF_TONE))) | ||
9992 | { | ||
9993 | dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | ||
9994 | UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); | ||
9995 | PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | ||
9996 | break; | ||
9997 | } | ||
9998 | |||
9999 | case DTMF_LISTEN_START: | ||
10000 | case DTMF_LISTEN_STOP: | ||
10001 | if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF) | ||
10002 | && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)) | ||
10003 | { | ||
10004 | dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | ||
10005 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10006 | Info = _FACILITY_NOT_SUPPORTED; | ||
10007 | break; | ||
10008 | } | ||
10009 | if (mask & DTMF_LISTEN_ACTIVE_FLAG) | ||
10010 | { | ||
10011 | if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms)) | ||
10012 | { | ||
10013 | plci->dtmf_rec_pulse_ms = 0; | ||
10014 | plci->dtmf_rec_pause_ms = 0; | ||
10015 | } | ||
10016 | else | ||
10017 | { | ||
10018 | plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info); | ||
10019 | plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info); | ||
10020 | } | ||
10021 | } | ||
10022 | start_internal_command (Id, plci, dtmf_command); | ||
10023 | return (FALSE); | ||
10024 | |||
10025 | |||
10026 | case DTMF_SEND_TONE: | ||
10027 | mask <<= 1; | ||
10028 | case DTMF_SEND_MF: | ||
10029 | mask <<= 1; | ||
10030 | if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1]) | ||
10031 | & (1L << PRIVATE_DTMF_TONE))) | ||
10032 | { | ||
10033 | dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | ||
10034 | UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); | ||
10035 | PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | ||
10036 | break; | ||
10037 | } | ||
10038 | |||
10039 | case DTMF_DIGITS_SEND: | ||
10040 | if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms)) | ||
10041 | { | ||
10042 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
10043 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10044 | Info = _WRONG_MESSAGE_FORMAT; | ||
10045 | break; | ||
10046 | } | ||
10047 | if (mask & DTMF_LISTEN_ACTIVE_FLAG) | ||
10048 | { | ||
10049 | plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info); | ||
10050 | plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info); | ||
10051 | } | ||
10052 | i = 0; | ||
10053 | j = 0; | ||
10054 | while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES)) | ||
10055 | { | ||
10056 | j = 0; | ||
10057 | while ((j < DTMF_DIGIT_MAP_ENTRIES) | ||
10058 | && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character) | ||
10059 | || ((dtmf_digit_map[j].send_mask & mask) == 0))) | ||
10060 | { | ||
10061 | j++; | ||
10062 | } | ||
10063 | i++; | ||
10064 | } | ||
10065 | if (j == DTMF_DIGIT_MAP_ENTRIES) | ||
10066 | { | ||
10067 | dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x", | ||
10068 | UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i])); | ||
10069 | PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT); | ||
10070 | break; | ||
10071 | } | ||
10072 | if (plci->dtmf_send_requests >= | ||
10073 | sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0])) | ||
10074 | { | ||
10075 | dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun", | ||
10076 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10077 | Info = _WRONG_STATE; | ||
10078 | break; | ||
10079 | } | ||
10080 | api_save_msg (dtmf_parms, "wwws", &plci->saved_msg); | ||
10081 | start_internal_command (Id, plci, dtmf_command); | ||
10082 | return (FALSE); | ||
10083 | |||
10084 | default: | ||
10085 | dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", | ||
10086 | UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd)); | ||
10087 | PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); | ||
10088 | } | ||
10089 | } | ||
10090 | } | ||
10091 | sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | ||
10092 | "wws", Info, SELECTOR_DTMF, result); | ||
10093 | return (FALSE); | ||
10094 | } | ||
10095 | |||
10096 | |||
10097 | static void dtmf_confirmation (dword Id, PLCI *plci) | ||
10098 | { | ||
10099 | word Info; | ||
10100 | word i; | ||
10101 | byte result[4]; | ||
10102 | |||
10103 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation", | ||
10104 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10105 | |||
10106 | Info = GOOD; | ||
10107 | result[0] = 2; | ||
10108 | PUT_WORD (&result[1], DTMF_SUCCESS); | ||
10109 | if (plci->dtmf_send_requests != 0) | ||
10110 | { | ||
10111 | sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0], | ||
10112 | "wws", GOOD, SELECTOR_DTMF, result); | ||
10113 | (plci->dtmf_send_requests)--; | ||
10114 | for (i = 0; i < plci->dtmf_send_requests; i++) | ||
10115 | plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1]; | ||
10116 | } | ||
10117 | } | ||
10118 | |||
10119 | |||
10120 | static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length) | ||
10121 | { | ||
10122 | word i, j, n; | ||
10123 | |||
10124 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication", | ||
10125 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10126 | |||
10127 | n = 0; | ||
10128 | for (i = 1; i < length; i++) | ||
10129 | { | ||
10130 | j = 0; | ||
10131 | while ((j < DTMF_DIGIT_MAP_ENTRIES) | ||
10132 | && ((msg[i] != dtmf_digit_map[j].code) | ||
10133 | || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0))) | ||
10134 | { | ||
10135 | j++; | ||
10136 | } | ||
10137 | if (j < DTMF_DIGIT_MAP_ENTRIES) | ||
10138 | { | ||
10139 | |||
10140 | if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG) | ||
10141 | && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE) | ||
10142 | && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE)) | ||
10143 | { | ||
10144 | if (n + 1 == i) | ||
10145 | { | ||
10146 | for (i = length; i > n + 1; i--) | ||
10147 | msg[i] = msg[i - 1]; | ||
10148 | length++; | ||
10149 | i++; | ||
10150 | } | ||
10151 | msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE; | ||
10152 | } | ||
10153 | plci->tone_last_indication_code = dtmf_digit_map[j].character; | ||
10154 | |||
10155 | msg[++n] = dtmf_digit_map[j].character; | ||
10156 | } | ||
10157 | } | ||
10158 | if (n != 0) | ||
10159 | { | ||
10160 | msg[0] = (byte) n; | ||
10161 | sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg); | ||
10162 | } | ||
10163 | } | ||
10164 | |||
10165 | |||
10166 | /*------------------------------------------------------------------*/ | ||
10167 | /* DTMF parameters */ | ||
10168 | /*------------------------------------------------------------------*/ | ||
10169 | |||
10170 | static void dtmf_parameter_write (PLCI *plci) | ||
10171 | { | ||
10172 | word i; | ||
10173 | byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2]; | ||
10174 | |||
10175 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write", | ||
10176 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10177 | (char *)(FILE_), __LINE__)); | ||
10178 | |||
10179 | parameter_buffer[0] = plci->dtmf_parameter_length + 1; | ||
10180 | parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS; | ||
10181 | for (i = 0; i < plci->dtmf_parameter_length; i++) | ||
10182 | parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i]; | ||
10183 | add_p (plci, FTY, parameter_buffer); | ||
10184 | sig_req (plci, TEL_CTRL, 0); | ||
10185 | send_req (plci); | ||
10186 | } | ||
10187 | |||
10188 | |||
10189 | static void dtmf_parameter_clear_config (PLCI *plci) | ||
10190 | { | ||
10191 | |||
10192 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config", | ||
10193 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10194 | (char *)(FILE_), __LINE__)); | ||
10195 | |||
10196 | plci->dtmf_parameter_length = 0; | ||
10197 | } | ||
10198 | |||
10199 | |||
10200 | static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci) | ||
10201 | { | ||
10202 | |||
10203 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch", | ||
10204 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10205 | |||
10206 | } | ||
10207 | |||
10208 | |||
10209 | static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc) | ||
10210 | { | ||
10211 | |||
10212 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d", | ||
10213 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
10214 | |||
10215 | return (GOOD); | ||
10216 | } | ||
10217 | |||
10218 | |||
10219 | static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc) | ||
10220 | { | ||
10221 | word Info; | ||
10222 | |||
10223 | dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d", | ||
10224 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
10225 | |||
10226 | Info = GOOD; | ||
10227 | if ((plci->B1_facilities & B1_FACILITY_DTMFR) | ||
10228 | && (plci->dtmf_parameter_length != 0)) | ||
10229 | { | ||
10230 | switch (plci->adjust_b_state) | ||
10231 | { | ||
10232 | case ADJUST_B_RESTORE_DTMF_PARAMETER_1: | ||
10233 | plci->internal_command = plci->adjust_b_command; | ||
10234 | if (plci->sig_req) | ||
10235 | { | ||
10236 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1; | ||
10237 | break; | ||
10238 | } | ||
10239 | dtmf_parameter_write (plci); | ||
10240 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2; | ||
10241 | break; | ||
10242 | case ADJUST_B_RESTORE_DTMF_PARAMETER_2: | ||
10243 | if ((Rc != OK) && (Rc != OK_FC)) | ||
10244 | { | ||
10245 | dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x", | ||
10246 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
10247 | Info = _WRONG_STATE; | ||
10248 | break; | ||
10249 | } | ||
10250 | break; | ||
10251 | } | ||
10252 | } | ||
10253 | return (Info); | ||
10254 | } | ||
10255 | |||
10256 | |||
10257 | /*------------------------------------------------------------------*/ | ||
10258 | /* Line interconnect facilities */ | ||
10259 | /*------------------------------------------------------------------*/ | ||
10260 | |||
10261 | |||
10262 | LI_CONFIG *li_config_table; | ||
10263 | word li_total_channels; | ||
10264 | |||
10265 | |||
10266 | /*------------------------------------------------------------------*/ | ||
10267 | /* translate a CHI information element to a channel number */ | ||
10268 | /* returns 0xff - any channel */ | ||
10269 | /* 0xfe - chi wrong coding */ | ||
10270 | /* 0xfd - D-channel */ | ||
10271 | /* 0x00 - no channel */ | ||
10272 | /* else channel number / PRI: timeslot */ | ||
10273 | /* if channels is provided we accept more than one channel. */ | ||
10274 | /*------------------------------------------------------------------*/ | ||
10275 | |||
10276 | static byte chi_to_channel (byte *chi, dword *pchannelmap) | ||
10277 | { | ||
10278 | int p; | ||
10279 | int i; | ||
10280 | dword map; | ||
10281 | byte excl; | ||
10282 | byte ofs; | ||
10283 | byte ch; | ||
10284 | |||
10285 | if (pchannelmap) *pchannelmap = 0; | ||
10286 | if(!chi[0]) return 0xff; | ||
10287 | excl = 0; | ||
10288 | |||
10289 | if(chi[1] & 0x20) { | ||
10290 | if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */ | ||
10291 | for(i=1; i<chi[0] && !(chi[i] &0x80); i++); | ||
10292 | if(i==chi[0] || !(chi[i] &0x80)) return 0xfe; | ||
10293 | if((chi[1] |0xc8)!=0xe9) return 0xfe; | ||
10294 | if(chi[1] &0x08) excl = 0x40; | ||
10295 | |||
10296 | /* int. id present */ | ||
10297 | if(chi[1] &0x40) { | ||
10298 | p=i+1; | ||
10299 | for(i=p; i<chi[0] && !(chi[i] &0x80); i++); | ||
10300 | if(i==chi[0] || !(chi[i] &0x80)) return 0xfe; | ||
10301 | } | ||
10302 | |||
10303 | /* coding standard, Number/Map, Channel Type */ | ||
10304 | p=i+1; | ||
10305 | for(i=p; i<chi[0] && !(chi[i] &0x80); i++); | ||
10306 | if(i==chi[0] || !(chi[i] &0x80)) return 0xfe; | ||
10307 | if((chi[p]|0xd0)!=0xd3) return 0xfe; | ||
10308 | |||
10309 | /* Number/Map */ | ||
10310 | if(chi[p] &0x10) { | ||
10311 | |||
10312 | /* map */ | ||
10313 | if((chi[0]-p)==4) ofs = 0; | ||
10314 | else if((chi[0]-p)==3) ofs = 1; | ||
10315 | else return 0xfe; | ||
10316 | ch = 0; | ||
10317 | map = 0; | ||
10318 | for(i=0; i<4 && p<chi[0]; i++) { | ||
10319 | p++; | ||
10320 | ch += 8; | ||
10321 | map <<= 8; | ||
10322 | if(chi[p]) { | ||
10323 | for (ch=0; !(chi[p] & (1 << ch)); ch++); | ||
10324 | map |= chi[p]; | ||
10325 | } | ||
10326 | } | ||
10327 | ch += ofs; | ||
10328 | map <<= ofs; | ||
10329 | } | ||
10330 | else { | ||
10331 | |||
10332 | /* number */ | ||
10333 | p=i+1; | ||
10334 | ch = chi[p] &0x3f; | ||
10335 | if(pchannelmap) { | ||
10336 | if((byte)(chi[0]-p)>30) return 0xfe; | ||
10337 | map = 0; | ||
10338 | for(i=p; i<=chi[0]; i++) { | ||
10339 | if ((chi[i] &0x7f) > 31) return 0xfe; | ||
10340 | map |= (1L << (chi[i] &0x7f)); | ||
10341 | } | ||
10342 | } | ||
10343 | else { | ||
10344 | if(p!=chi[0]) return 0xfe; | ||
10345 | if (ch > 31) return 0xfe; | ||
10346 | map = (1L << ch); | ||
10347 | } | ||
10348 | if(chi[p] &0x40) return 0xfe; | ||
10349 | } | ||
10350 | if (pchannelmap) *pchannelmap = map; | ||
10351 | else if (map != ((dword)(1L << ch))) return 0xfe; | ||
10352 | return (byte)(excl | ch); | ||
10353 | } | ||
10354 | else { /* not PRI */ | ||
10355 | for(i=1; i<chi[0] && !(chi[i] &0x80); i++); | ||
10356 | if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe; | ||
10357 | if(chi[1] &0x08) excl = 0x40; | ||
10358 | |||
10359 | switch(chi[1] |0x98) { | ||
10360 | case 0x98: return 0; | ||
10361 | case 0x99: | ||
10362 | if (pchannelmap) *pchannelmap = 2; | ||
10363 | return excl |1; | ||
10364 | case 0x9a: | ||
10365 | if (pchannelmap) *pchannelmap = 4; | ||
10366 | return excl |2; | ||
10367 | case 0x9b: return 0xff; | ||
10368 | case 0x9c: return 0xfd; /* d-ch */ | ||
10369 | default: return 0xfe; | ||
10370 | } | ||
10371 | } | ||
10372 | } | ||
10373 | |||
10374 | |||
10375 | static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id) | ||
10376 | { | ||
10377 | DIVA_CAPI_ADAPTER *a; | ||
10378 | PLCI *splci; | ||
10379 | byte old_id; | ||
10380 | |||
10381 | a = plci->adapter; | ||
10382 | old_id = plci->li_bchannel_id; | ||
10383 | if (a->li_pri) | ||
10384 | { | ||
10385 | if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | ||
10386 | li_config_table[a->li_base + (old_id - 1)].plci = NULL; | ||
10387 | plci->li_bchannel_id = (bchannel_id & 0x1f) + 1; | ||
10388 | if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | ||
10389 | li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | ||
10390 | } | ||
10391 | else | ||
10392 | { | ||
10393 | if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2)) | ||
10394 | { | ||
10395 | if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | ||
10396 | li_config_table[a->li_base + (old_id - 1)].plci = NULL; | ||
10397 | plci->li_bchannel_id = bchannel_id & 0x03; | ||
10398 | if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | ||
10399 | { | ||
10400 | splci = a->AdvSignalPLCI; | ||
10401 | if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL) | ||
10402 | { | ||
10403 | if ((splci->li_bchannel_id != 0) | ||
10404 | && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci)) | ||
10405 | { | ||
10406 | li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL; | ||
10407 | } | ||
10408 | splci->li_bchannel_id = 3 - plci->li_bchannel_id; | ||
10409 | li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci; | ||
10410 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d", | ||
10411 | (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)), | ||
10412 | (char *)(FILE_), __LINE__, splci->li_bchannel_id)); | ||
10413 | } | ||
10414 | } | ||
10415 | if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | ||
10416 | li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | ||
10417 | } | ||
10418 | } | ||
10419 | if ((old_id == 0) && (plci->li_bchannel_id != 0) | ||
10420 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
10421 | { | ||
10422 | mixer_clear_config (plci); | ||
10423 | } | ||
10424 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d", | ||
10425 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10426 | (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id)); | ||
10427 | } | ||
10428 | |||
10429 | |||
10430 | static void mixer_set_bchannel_id (PLCI *plci, byte *chi) | ||
10431 | { | ||
10432 | DIVA_CAPI_ADAPTER *a; | ||
10433 | PLCI *splci; | ||
10434 | byte ch, old_id; | ||
10435 | |||
10436 | a = plci->adapter; | ||
10437 | old_id = plci->li_bchannel_id; | ||
10438 | ch = chi_to_channel (chi, NULL); | ||
10439 | if (!(ch & 0x80)) | ||
10440 | { | ||
10441 | if (a->li_pri) | ||
10442 | { | ||
10443 | if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | ||
10444 | li_config_table[a->li_base + (old_id - 1)].plci = NULL; | ||
10445 | plci->li_bchannel_id = (ch & 0x1f) + 1; | ||
10446 | if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | ||
10447 | li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | ||
10448 | } | ||
10449 | else | ||
10450 | { | ||
10451 | if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2)) | ||
10452 | { | ||
10453 | if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci)) | ||
10454 | li_config_table[a->li_base + (old_id - 1)].plci = NULL; | ||
10455 | plci->li_bchannel_id = ch & 0x1f; | ||
10456 | if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | ||
10457 | { | ||
10458 | splci = a->AdvSignalPLCI; | ||
10459 | if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL) | ||
10460 | { | ||
10461 | if ((splci->li_bchannel_id != 0) | ||
10462 | && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci)) | ||
10463 | { | ||
10464 | li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL; | ||
10465 | } | ||
10466 | splci->li_bchannel_id = 3 - plci->li_bchannel_id; | ||
10467 | li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci; | ||
10468 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d", | ||
10469 | (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)), | ||
10470 | (char *)(FILE_), __LINE__, splci->li_bchannel_id)); | ||
10471 | } | ||
10472 | } | ||
10473 | if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL) | ||
10474 | li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci; | ||
10475 | } | ||
10476 | } | ||
10477 | } | ||
10478 | if ((old_id == 0) && (plci->li_bchannel_id != 0) | ||
10479 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
10480 | { | ||
10481 | mixer_clear_config (plci); | ||
10482 | } | ||
10483 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d", | ||
10484 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10485 | (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id)); | ||
10486 | } | ||
10487 | |||
10488 | |||
10489 | #define MIXER_MAX_DUMP_CHANNELS 34 | ||
10490 | |||
10491 | static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a) | ||
10492 | { | ||
10493 | static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; | ||
10494 | word n, i, j; | ||
10495 | char *p; | ||
10496 | char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4]; | ||
10497 | |||
10498 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs", | ||
10499 | (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__)); | ||
10500 | |||
10501 | for (i = 0; i < li_total_channels; i++) | ||
10502 | { | ||
10503 | li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET; | ||
10504 | if (li_config_table[i].chflags != 0) | ||
10505 | li_config_table[i].channel |= LI_CHANNEL_INVOLVED; | ||
10506 | else | ||
10507 | { | ||
10508 | for (j = 0; j < li_total_channels; j++) | ||
10509 | { | ||
10510 | if (((li_config_table[i].flag_table[j]) != 0) | ||
10511 | || ((li_config_table[j].flag_table[i]) != 0)) | ||
10512 | { | ||
10513 | li_config_table[i].channel |= LI_CHANNEL_INVOLVED; | ||
10514 | } | ||
10515 | if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0) | ||
10516 | || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0)) | ||
10517 | { | ||
10518 | li_config_table[i].channel |= LI_CHANNEL_CONFERENCE; | ||
10519 | } | ||
10520 | } | ||
10521 | } | ||
10522 | } | ||
10523 | for (i = 0; i < li_total_channels; i++) | ||
10524 | { | ||
10525 | for (j = 0; j < li_total_channels; j++) | ||
10526 | { | ||
10527 | li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC); | ||
10528 | if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) | ||
10529 | li_config_table[i].coef_table[j] |= LI_COEF_CH_CH; | ||
10530 | } | ||
10531 | } | ||
10532 | for (n = 0; n < li_total_channels; n++) | ||
10533 | { | ||
10534 | if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE) | ||
10535 | { | ||
10536 | for (i = 0; i < li_total_channels; i++) | ||
10537 | { | ||
10538 | if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE) | ||
10539 | { | ||
10540 | for (j = 0; j < li_total_channels; j++) | ||
10541 | { | ||
10542 | li_config_table[i].coef_table[j] |= | ||
10543 | li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j]; | ||
10544 | } | ||
10545 | } | ||
10546 | } | ||
10547 | } | ||
10548 | } | ||
10549 | for (i = 0; i < li_total_channels; i++) | ||
10550 | { | ||
10551 | if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | ||
10552 | { | ||
10553 | li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH; | ||
10554 | for (j = 0; j < li_total_channels; j++) | ||
10555 | { | ||
10556 | if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH) | ||
10557 | li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE; | ||
10558 | } | ||
10559 | if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE) | ||
10560 | li_config_table[i].coef_table[i] |= LI_COEF_CH_CH; | ||
10561 | } | ||
10562 | } | ||
10563 | for (i = 0; i < li_total_channels; i++) | ||
10564 | { | ||
10565 | if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | ||
10566 | { | ||
10567 | for (j = 0; j < li_total_channels; j++) | ||
10568 | { | ||
10569 | if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | ||
10570 | li_config_table[i].coef_table[j] |= LI_COEF_CH_CH; | ||
10571 | if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR) | ||
10572 | li_config_table[i].coef_table[j] |= LI_COEF_CH_PC; | ||
10573 | if (li_config_table[i].flag_table[j] & LI_FLAG_MIX) | ||
10574 | li_config_table[i].coef_table[j] |= LI_COEF_PC_CH; | ||
10575 | if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT) | ||
10576 | li_config_table[i].coef_table[j] |= LI_COEF_PC_PC; | ||
10577 | } | ||
10578 | if (li_config_table[i].chflags & LI_CHFLAG_MONITOR) | ||
10579 | { | ||
10580 | for (j = 0; j < li_total_channels; j++) | ||
10581 | { | ||
10582 | if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | ||
10583 | { | ||
10584 | li_config_table[i].coef_table[j] |= LI_COEF_CH_PC; | ||
10585 | if (li_config_table[j].chflags & LI_CHFLAG_MIX) | ||
10586 | li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC; | ||
10587 | } | ||
10588 | } | ||
10589 | } | ||
10590 | if (li_config_table[i].chflags & LI_CHFLAG_MIX) | ||
10591 | { | ||
10592 | for (j = 0; j < li_total_channels; j++) | ||
10593 | { | ||
10594 | if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT) | ||
10595 | li_config_table[j].coef_table[i] |= LI_COEF_PC_CH; | ||
10596 | } | ||
10597 | } | ||
10598 | if (li_config_table[i].chflags & LI_CHFLAG_LOOP) | ||
10599 | { | ||
10600 | for (j = 0; j < li_total_channels; j++) | ||
10601 | { | ||
10602 | if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | ||
10603 | { | ||
10604 | for (n = 0; n < li_total_channels; n++) | ||
10605 | { | ||
10606 | if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT) | ||
10607 | { | ||
10608 | li_config_table[n].coef_table[j] |= LI_COEF_CH_CH; | ||
10609 | if (li_config_table[j].chflags & LI_CHFLAG_MIX) | ||
10610 | { | ||
10611 | li_config_table[n].coef_table[j] |= LI_COEF_PC_CH; | ||
10612 | if (li_config_table[n].chflags & LI_CHFLAG_MONITOR) | ||
10613 | li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC; | ||
10614 | } | ||
10615 | else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR) | ||
10616 | li_config_table[n].coef_table[j] |= LI_COEF_CH_PC; | ||
10617 | } | ||
10618 | } | ||
10619 | } | ||
10620 | } | ||
10621 | } | ||
10622 | } | ||
10623 | } | ||
10624 | for (i = 0; i < li_total_channels; i++) | ||
10625 | { | ||
10626 | if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | ||
10627 | { | ||
10628 | if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP)) | ||
10629 | li_config_table[i].channel |= LI_CHANNEL_ACTIVE; | ||
10630 | if (li_config_table[i].chflags & LI_CHFLAG_MONITOR) | ||
10631 | li_config_table[i].channel |= LI_CHANNEL_RX_DATA; | ||
10632 | if (li_config_table[i].chflags & LI_CHFLAG_MIX) | ||
10633 | li_config_table[i].channel |= LI_CHANNEL_TX_DATA; | ||
10634 | for (j = 0; j < li_total_channels; j++) | ||
10635 | { | ||
10636 | if ((li_config_table[i].flag_table[j] & | ||
10637 | (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR)) | ||
10638 | || (li_config_table[j].flag_table[i] & | ||
10639 | (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))) | ||
10640 | { | ||
10641 | li_config_table[i].channel |= LI_CHANNEL_ACTIVE; | ||
10642 | } | ||
10643 | if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR)) | ||
10644 | li_config_table[i].channel |= LI_CHANNEL_RX_DATA; | ||
10645 | if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)) | ||
10646 | li_config_table[i].channel |= LI_CHANNEL_TX_DATA; | ||
10647 | } | ||
10648 | if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE)) | ||
10649 | { | ||
10650 | li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC; | ||
10651 | li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA; | ||
10652 | } | ||
10653 | } | ||
10654 | } | ||
10655 | for (i = 0; i < li_total_channels; i++) | ||
10656 | { | ||
10657 | if (li_config_table[i].channel & LI_CHANNEL_INVOLVED) | ||
10658 | { | ||
10659 | j = 0; | ||
10660 | while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)) | ||
10661 | j++; | ||
10662 | if (j < li_total_channels) | ||
10663 | { | ||
10664 | for (j = 0; j < li_total_channels; j++) | ||
10665 | { | ||
10666 | li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH); | ||
10667 | if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT) | ||
10668 | li_config_table[i].coef_table[j] |= LI_COEF_PC_CH; | ||
10669 | } | ||
10670 | } | ||
10671 | } | ||
10672 | } | ||
10673 | n = li_total_channels; | ||
10674 | if (n > MIXER_MAX_DUMP_CHANNELS) | ||
10675 | n = MIXER_MAX_DUMP_CHANNELS; | ||
10676 | p = hex_line; | ||
10677 | for (j = 0; j < n; j++) | ||
10678 | { | ||
10679 | if ((j & 0x7) == 0) | ||
10680 | *(p++) = ' '; | ||
10681 | *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4]; | ||
10682 | *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf]; | ||
10683 | } | ||
10684 | *p = '\0'; | ||
10685 | dbug (1, dprintf ("[%06lx] CURRENT %s", | ||
10686 | (dword)(UnMapController (a->Id)), (char *) hex_line)); | ||
10687 | p = hex_line; | ||
10688 | for (j = 0; j < n; j++) | ||
10689 | { | ||
10690 | if ((j & 0x7) == 0) | ||
10691 | *(p++) = ' '; | ||
10692 | *(p++) = hex_digit_table[li_config_table[j].channel >> 4]; | ||
10693 | *(p++) = hex_digit_table[li_config_table[j].channel & 0xf]; | ||
10694 | } | ||
10695 | *p = '\0'; | ||
10696 | dbug (1, dprintf ("[%06lx] CHANNEL %s", | ||
10697 | (dword)(UnMapController (a->Id)), (char *) hex_line)); | ||
10698 | p = hex_line; | ||
10699 | for (j = 0; j < n; j++) | ||
10700 | { | ||
10701 | if ((j & 0x7) == 0) | ||
10702 | *(p++) = ' '; | ||
10703 | *(p++) = hex_digit_table[li_config_table[j].chflags >> 4]; | ||
10704 | *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf]; | ||
10705 | } | ||
10706 | *p = '\0'; | ||
10707 | dbug (1, dprintf ("[%06lx] CHFLAG %s", | ||
10708 | (dword)(UnMapController (a->Id)), (char *) hex_line)); | ||
10709 | for (i = 0; i < n; i++) | ||
10710 | { | ||
10711 | p = hex_line; | ||
10712 | for (j = 0; j < n; j++) | ||
10713 | { | ||
10714 | if ((j & 0x7) == 0) | ||
10715 | *(p++) = ' '; | ||
10716 | *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4]; | ||
10717 | *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf]; | ||
10718 | } | ||
10719 | *p = '\0'; | ||
10720 | dbug (1, dprintf ("[%06lx] FLAG[%02x]%s", | ||
10721 | (dword)(UnMapController (a->Id)), i, (char *) hex_line)); | ||
10722 | } | ||
10723 | for (i = 0; i < n; i++) | ||
10724 | { | ||
10725 | p = hex_line; | ||
10726 | for (j = 0; j < n; j++) | ||
10727 | { | ||
10728 | if ((j & 0x7) == 0) | ||
10729 | *(p++) = ' '; | ||
10730 | *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4]; | ||
10731 | *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf]; | ||
10732 | } | ||
10733 | *p = '\0'; | ||
10734 | dbug (1, dprintf ("[%06lx] COEF[%02x]%s", | ||
10735 | (dword)(UnMapController (a->Id)), i, (char *) hex_line)); | ||
10736 | } | ||
10737 | } | ||
10738 | |||
10739 | |||
10740 | static struct | ||
10741 | { | ||
10742 | byte mask; | ||
10743 | byte line_flags; | ||
10744 | } mixer_write_prog_pri[] = | ||
10745 | { | ||
10746 | { LI_COEF_CH_CH, 0 }, | ||
10747 | { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG }, | ||
10748 | { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG }, | ||
10749 | { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG } | ||
10750 | }; | ||
10751 | |||
10752 | static struct | ||
10753 | { | ||
10754 | byte from_ch; | ||
10755 | byte to_ch; | ||
10756 | byte mask; | ||
10757 | byte xconnect_override; | ||
10758 | } mixer_write_prog_bri[] = | ||
10759 | { | ||
10760 | { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */ | ||
10761 | { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */ | ||
10762 | { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */ | ||
10763 | { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */ | ||
10764 | { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */ | ||
10765 | { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */ | ||
10766 | { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */ | ||
10767 | { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */ | ||
10768 | { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */ | ||
10769 | { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */ | ||
10770 | { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */ | ||
10771 | { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */ | ||
10772 | { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */ | ||
10773 | { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */ | ||
10774 | { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */ | ||
10775 | { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */ | ||
10776 | { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */ | ||
10777 | { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */ | ||
10778 | { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */ | ||
10779 | { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */ | ||
10780 | { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */ | ||
10781 | { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */ | ||
10782 | { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */ | ||
10783 | { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */ | ||
10784 | { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */ | ||
10785 | { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */ | ||
10786 | { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */ | ||
10787 | { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */ | ||
10788 | { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */ | ||
10789 | { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */ | ||
10790 | { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */ | ||
10791 | { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */ | ||
10792 | { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */ | ||
10793 | { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */ | ||
10794 | { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */ | ||
10795 | { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */ | ||
10796 | }; | ||
10797 | |||
10798 | static byte mixer_swapped_index_bri[] = | ||
10799 | { | ||
10800 | 18, /* B to B */ | ||
10801 | 19, /* Alt B to B */ | ||
10802 | 20, /* PC to B */ | ||
10803 | 21, /* Alt PC to B */ | ||
10804 | 22, /* IC to B */ | ||
10805 | 23, /* Alt IC to B */ | ||
10806 | 24, /* B to PC */ | ||
10807 | 25, /* Alt B to PC */ | ||
10808 | 26, /* PC to PC */ | ||
10809 | 27, /* Alt PC to PC */ | ||
10810 | 28, /* IC to PC */ | ||
10811 | 29, /* Alt IC to PC */ | ||
10812 | 30, /* B to IC */ | ||
10813 | 31, /* Alt B to IC */ | ||
10814 | 32, /* PC to IC */ | ||
10815 | 33, /* Alt PC to IC */ | ||
10816 | 34, /* IC to IC */ | ||
10817 | 35, /* Alt IC to IC */ | ||
10818 | 0, /* Alt B to Alt B */ | ||
10819 | 1, /* B to Alt B */ | ||
10820 | 2, /* Alt PC to Alt B */ | ||
10821 | 3, /* PC to Alt B */ | ||
10822 | 4, /* Alt IC to Alt B */ | ||
10823 | 5, /* IC to Alt B */ | ||
10824 | 6, /* Alt B to Alt PC */ | ||
10825 | 7, /* B to Alt PC */ | ||
10826 | 8, /* Alt PC to Alt PC */ | ||
10827 | 9, /* PC to Alt PC */ | ||
10828 | 10, /* Alt IC to Alt PC */ | ||
10829 | 11, /* IC to Alt PC */ | ||
10830 | 12, /* Alt B to Alt IC */ | ||
10831 | 13, /* B to Alt IC */ | ||
10832 | 14, /* Alt PC to Alt IC */ | ||
10833 | 15, /* PC to Alt IC */ | ||
10834 | 16, /* Alt IC to Alt IC */ | ||
10835 | 17 /* IC to Alt IC */ | ||
10836 | }; | ||
10837 | |||
10838 | static struct | ||
10839 | { | ||
10840 | byte mask; | ||
10841 | byte from_pc; | ||
10842 | byte to_pc; | ||
10843 | } xconnect_write_prog[] = | ||
10844 | { | ||
10845 | { LI_COEF_CH_CH, FALSE, FALSE }, | ||
10846 | { LI_COEF_CH_PC, FALSE, TRUE }, | ||
10847 | { LI_COEF_PC_CH, TRUE, FALSE }, | ||
10848 | { LI_COEF_PC_PC, TRUE, TRUE } | ||
10849 | }; | ||
10850 | |||
10851 | |||
10852 | static void xconnect_query_addresses (PLCI *plci) | ||
10853 | { | ||
10854 | DIVA_CAPI_ADAPTER *a; | ||
10855 | word w, ch; | ||
10856 | byte *p; | ||
10857 | |||
10858 | dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses", | ||
10859 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10860 | (char *)(FILE_), __LINE__)); | ||
10861 | |||
10862 | a = plci->adapter; | ||
10863 | if (a->li_pri && ((plci->li_bchannel_id == 0) | ||
10864 | || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))) | ||
10865 | { | ||
10866 | dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out", | ||
10867 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10868 | (char *)(FILE_), __LINE__)); | ||
10869 | return; | ||
10870 | } | ||
10871 | p = plci->internal_req_buffer; | ||
10872 | ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0; | ||
10873 | *(p++) = UDATA_REQUEST_XCONNECT_FROM; | ||
10874 | w = ch; | ||
10875 | *(p++) = (byte) w; | ||
10876 | *(p++) = (byte)(w >> 8); | ||
10877 | w = ch | XCONNECT_CHANNEL_PORT_PC; | ||
10878 | *(p++) = (byte) w; | ||
10879 | *(p++) = (byte)(w >> 8); | ||
10880 | plci->NData[0].P = plci->internal_req_buffer; | ||
10881 | plci->NData[0].PLength = p - plci->internal_req_buffer; | ||
10882 | plci->NL.X = plci->NData; | ||
10883 | plci->NL.ReqCh = 0; | ||
10884 | plci->NL.Req = plci->nl_req = (byte) N_UDATA; | ||
10885 | plci->adapter->request (&plci->NL); | ||
10886 | } | ||
10887 | |||
10888 | |||
10889 | static void xconnect_write_coefs (PLCI *plci, word internal_command) | ||
10890 | { | ||
10891 | |||
10892 | dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x", | ||
10893 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
10894 | (char *)(FILE_), __LINE__, internal_command)); | ||
10895 | |||
10896 | plci->li_write_command = internal_command; | ||
10897 | plci->li_write_channel = 0; | ||
10898 | } | ||
10899 | |||
10900 | |||
10901 | static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc) | ||
10902 | { | ||
10903 | DIVA_CAPI_ADAPTER *a; | ||
10904 | word w, n, i, j, r, s, to_ch; | ||
10905 | dword d; | ||
10906 | byte *p; | ||
10907 | struct xconnect_transfer_address_s *transfer_address; | ||
10908 | byte ch_map[MIXER_CHANNELS_BRI]; | ||
10909 | |||
10910 | dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d", | ||
10911 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel)); | ||
10912 | |||
10913 | a = plci->adapter; | ||
10914 | if ((plci->li_bchannel_id == 0) | ||
10915 | || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)) | ||
10916 | { | ||
10917 | dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out", | ||
10918 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
10919 | return (TRUE); | ||
10920 | } | ||
10921 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
10922 | j = plci->li_write_channel; | ||
10923 | p = plci->internal_req_buffer; | ||
10924 | if (j != 0) | ||
10925 | { | ||
10926 | if ((Rc != OK) && (Rc != OK_FC)) | ||
10927 | { | ||
10928 | dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x", | ||
10929 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
10930 | return (FALSE); | ||
10931 | } | ||
10932 | } | ||
10933 | if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
10934 | { | ||
10935 | r = 0; | ||
10936 | s = 0; | ||
10937 | if (j < li_total_channels) | ||
10938 | { | ||
10939 | if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET) | ||
10940 | { | ||
10941 | s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ? | ||
10942 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) & | ||
10943 | ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ? | ||
10944 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH)); | ||
10945 | } | ||
10946 | r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
10947 | while ((j < li_total_channels) | ||
10948 | && ((r == 0) | ||
10949 | || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET)) | ||
10950 | || (!li_config_table[j].adapter->li_pri | ||
10951 | && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI)) | ||
10952 | || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low) | ||
10953 | || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high)) | ||
10954 | && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT) | ||
10955 | || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT))) | ||
10956 | || ((li_config_table[j].adapter->li_base != a->li_base) | ||
10957 | && !(r & s & | ||
10958 | ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ? | ||
10959 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) & | ||
10960 | ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ? | ||
10961 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC)))))) | ||
10962 | { | ||
10963 | j++; | ||
10964 | if (j < li_total_channels) | ||
10965 | r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
10966 | } | ||
10967 | } | ||
10968 | if (j < li_total_channels) | ||
10969 | { | ||
10970 | plci->internal_command = plci->li_write_command; | ||
10971 | if (plci_nl_busy (plci)) | ||
10972 | return (TRUE); | ||
10973 | to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0; | ||
10974 | *(p++) = UDATA_REQUEST_XCONNECT_TO; | ||
10975 | do | ||
10976 | { | ||
10977 | if (li_config_table[j].adapter->li_base != a->li_base) | ||
10978 | { | ||
10979 | r &= s & | ||
10980 | ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ? | ||
10981 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) & | ||
10982 | ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ? | ||
10983 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC)); | ||
10984 | } | ||
10985 | n = 0; | ||
10986 | do | ||
10987 | { | ||
10988 | if (r & xconnect_write_prog[n].mask) | ||
10989 | { | ||
10990 | if (xconnect_write_prog[n].from_pc) | ||
10991 | transfer_address = &(li_config_table[j].send_pc); | ||
10992 | else | ||
10993 | transfer_address = &(li_config_table[j].send_b); | ||
10994 | d = transfer_address->card_address.low; | ||
10995 | *(p++) = (byte) d; | ||
10996 | *(p++) = (byte)(d >> 8); | ||
10997 | *(p++) = (byte)(d >> 16); | ||
10998 | *(p++) = (byte)(d >> 24); | ||
10999 | d = transfer_address->card_address.high; | ||
11000 | *(p++) = (byte) d; | ||
11001 | *(p++) = (byte)(d >> 8); | ||
11002 | *(p++) = (byte)(d >> 16); | ||
11003 | *(p++) = (byte)(d >> 24); | ||
11004 | d = transfer_address->offset; | ||
11005 | *(p++) = (byte) d; | ||
11006 | *(p++) = (byte)(d >> 8); | ||
11007 | *(p++) = (byte)(d >> 16); | ||
11008 | *(p++) = (byte)(d >> 24); | ||
11009 | w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch; | ||
11010 | *(p++) = (byte) w; | ||
11011 | *(p++) = (byte)(w >> 8); | ||
11012 | w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 : | ||
11013 | (li_config_table[i].adapter->u_law ? | ||
11014 | (li_config_table[j].adapter->u_law ? 0x80 : 0x86) : | ||
11015 | (li_config_table[j].adapter->u_law ? 0x7a : 0x80)); | ||
11016 | *(p++) = (byte) w; | ||
11017 | *(p++) = (byte) 0; | ||
11018 | li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4; | ||
11019 | } | ||
11020 | n++; | ||
11021 | } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0])) | ||
11022 | && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE)); | ||
11023 | if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0])) | ||
11024 | { | ||
11025 | do | ||
11026 | { | ||
11027 | j++; | ||
11028 | if (j < li_total_channels) | ||
11029 | r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
11030 | } while ((j < li_total_channels) | ||
11031 | && ((r == 0) | ||
11032 | || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET)) | ||
11033 | || (!li_config_table[j].adapter->li_pri | ||
11034 | && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI)) | ||
11035 | || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low) | ||
11036 | || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high)) | ||
11037 | && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT) | ||
11038 | || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT))) | ||
11039 | || ((li_config_table[j].adapter->li_base != a->li_base) | ||
11040 | && !(r & s & | ||
11041 | ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ? | ||
11042 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) & | ||
11043 | ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ? | ||
11044 | (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC)))))); | ||
11045 | } | ||
11046 | } while ((j < li_total_channels) | ||
11047 | && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE)); | ||
11048 | } | ||
11049 | else if (j == li_total_channels) | ||
11050 | { | ||
11051 | plci->internal_command = plci->li_write_command; | ||
11052 | if (plci_nl_busy (plci)) | ||
11053 | return (TRUE); | ||
11054 | if (a->li_pri) | ||
11055 | { | ||
11056 | *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC; | ||
11057 | w = 0; | ||
11058 | if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | ||
11059 | w |= MIXER_FEATURE_ENABLE_TX_DATA; | ||
11060 | if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | ||
11061 | w |= MIXER_FEATURE_ENABLE_RX_DATA; | ||
11062 | *(p++) = (byte) w; | ||
11063 | *(p++) = (byte)(w >> 8); | ||
11064 | } | ||
11065 | else | ||
11066 | { | ||
11067 | *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI; | ||
11068 | w = 0; | ||
11069 | if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI) | ||
11070 | && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)) | ||
11071 | { | ||
11072 | w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); | ||
11073 | } | ||
11074 | if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | ||
11075 | w |= MIXER_FEATURE_ENABLE_TX_DATA; | ||
11076 | if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | ||
11077 | w |= MIXER_FEATURE_ENABLE_RX_DATA; | ||
11078 | *(p++) = (byte) w; | ||
11079 | *(p++) = (byte)(w >> 8); | ||
11080 | for (j = 0; j < sizeof(ch_map); j += 2) | ||
11081 | { | ||
11082 | if (plci->li_bchannel_id == 2) | ||
11083 | { | ||
11084 | ch_map[j] = (byte)(j+1); | ||
11085 | ch_map[j+1] = (byte) j; | ||
11086 | } | ||
11087 | else | ||
11088 | { | ||
11089 | ch_map[j] = (byte) j; | ||
11090 | ch_map[j+1] = (byte)(j+1); | ||
11091 | } | ||
11092 | } | ||
11093 | for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++) | ||
11094 | { | ||
11095 | i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch]; | ||
11096 | j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch]; | ||
11097 | if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED) | ||
11098 | { | ||
11099 | *p = (mixer_write_prog_bri[n].xconnect_override != 0) ? | ||
11100 | mixer_write_prog_bri[n].xconnect_override : | ||
11101 | ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01); | ||
11102 | if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI)) | ||
11103 | { | ||
11104 | w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
11105 | li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4; | ||
11106 | } | ||
11107 | } | ||
11108 | else | ||
11109 | { | ||
11110 | *p = 0x00; | ||
11111 | if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | ||
11112 | { | ||
11113 | w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n]; | ||
11114 | if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length) | ||
11115 | *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w]; | ||
11116 | } | ||
11117 | } | ||
11118 | p++; | ||
11119 | } | ||
11120 | } | ||
11121 | j = li_total_channels + 1; | ||
11122 | } | ||
11123 | } | ||
11124 | else | ||
11125 | { | ||
11126 | if (j <= li_total_channels) | ||
11127 | { | ||
11128 | plci->internal_command = plci->li_write_command; | ||
11129 | if (plci_nl_busy (plci)) | ||
11130 | return (TRUE); | ||
11131 | if (j < a->li_base) | ||
11132 | j = a->li_base; | ||
11133 | if (a->li_pri) | ||
11134 | { | ||
11135 | *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC; | ||
11136 | w = 0; | ||
11137 | if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | ||
11138 | w |= MIXER_FEATURE_ENABLE_TX_DATA; | ||
11139 | if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | ||
11140 | w |= MIXER_FEATURE_ENABLE_RX_DATA; | ||
11141 | *(p++) = (byte) w; | ||
11142 | *(p++) = (byte)(w >> 8); | ||
11143 | for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++) | ||
11144 | { | ||
11145 | *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags); | ||
11146 | for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++) | ||
11147 | { | ||
11148 | w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
11149 | if (w & mixer_write_prog_pri[n].mask) | ||
11150 | { | ||
11151 | *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01; | ||
11152 | li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4; | ||
11153 | } | ||
11154 | else | ||
11155 | *(p++) = 0x00; | ||
11156 | } | ||
11157 | *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags); | ||
11158 | for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++) | ||
11159 | { | ||
11160 | w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4)); | ||
11161 | if (w & mixer_write_prog_pri[n].mask) | ||
11162 | { | ||
11163 | *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01; | ||
11164 | li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4; | ||
11165 | } | ||
11166 | else | ||
11167 | *(p++) = 0x00; | ||
11168 | } | ||
11169 | } | ||
11170 | } | ||
11171 | else | ||
11172 | { | ||
11173 | *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI; | ||
11174 | w = 0; | ||
11175 | if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI) | ||
11176 | && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)) | ||
11177 | { | ||
11178 | w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); | ||
11179 | } | ||
11180 | if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | ||
11181 | w |= MIXER_FEATURE_ENABLE_TX_DATA; | ||
11182 | if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | ||
11183 | w |= MIXER_FEATURE_ENABLE_RX_DATA; | ||
11184 | *(p++) = (byte) w; | ||
11185 | *(p++) = (byte)(w >> 8); | ||
11186 | for (j = 0; j < sizeof(ch_map); j += 2) | ||
11187 | { | ||
11188 | if (plci->li_bchannel_id == 2) | ||
11189 | { | ||
11190 | ch_map[j] = (byte)(j+1); | ||
11191 | ch_map[j+1] = (byte) j; | ||
11192 | } | ||
11193 | else | ||
11194 | { | ||
11195 | ch_map[j] = (byte) j; | ||
11196 | ch_map[j+1] = (byte)(j+1); | ||
11197 | } | ||
11198 | } | ||
11199 | for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++) | ||
11200 | { | ||
11201 | i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch]; | ||
11202 | j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch]; | ||
11203 | if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED) | ||
11204 | { | ||
11205 | *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01); | ||
11206 | w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
11207 | li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4; | ||
11208 | } | ||
11209 | else | ||
11210 | { | ||
11211 | *p = 0x00; | ||
11212 | if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE)) | ||
11213 | { | ||
11214 | w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n]; | ||
11215 | if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length) | ||
11216 | *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w]; | ||
11217 | } | ||
11218 | } | ||
11219 | p++; | ||
11220 | } | ||
11221 | } | ||
11222 | j = li_total_channels + 1; | ||
11223 | } | ||
11224 | } | ||
11225 | plci->li_write_channel = j; | ||
11226 | if (p != plci->internal_req_buffer) | ||
11227 | { | ||
11228 | plci->NData[0].P = plci->internal_req_buffer; | ||
11229 | plci->NData[0].PLength = p - plci->internal_req_buffer; | ||
11230 | plci->NL.X = plci->NData; | ||
11231 | plci->NL.ReqCh = 0; | ||
11232 | plci->NL.Req = plci->nl_req = (byte) N_UDATA; | ||
11233 | plci->adapter->request (&plci->NL); | ||
11234 | } | ||
11235 | return (TRUE); | ||
11236 | } | ||
11237 | |||
11238 | |||
11239 | static void mixer_notify_update (PLCI *plci, byte others) | ||
11240 | { | ||
11241 | DIVA_CAPI_ADAPTER *a; | ||
11242 | word i, w; | ||
11243 | PLCI *notify_plci; | ||
11244 | byte msg[sizeof(CAPI_MSG_HEADER) + 6]; | ||
11245 | |||
11246 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d", | ||
11247 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
11248 | (char *)(FILE_), __LINE__, others)); | ||
11249 | |||
11250 | a = plci->adapter; | ||
11251 | if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED) | ||
11252 | { | ||
11253 | if (others) | ||
11254 | plci->li_notify_update = TRUE; | ||
11255 | i = 0; | ||
11256 | do | ||
11257 | { | ||
11258 | notify_plci = NULL; | ||
11259 | if (others) | ||
11260 | { | ||
11261 | while ((i < li_total_channels) && (li_config_table[i].plci == NULL)) | ||
11262 | i++; | ||
11263 | if (i < li_total_channels) | ||
11264 | notify_plci = li_config_table[i++].plci; | ||
11265 | } | ||
11266 | else | ||
11267 | { | ||
11268 | if ((plci->li_bchannel_id != 0) | ||
11269 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
11270 | { | ||
11271 | notify_plci = plci; | ||
11272 | } | ||
11273 | } | ||
11274 | if ((notify_plci != NULL) | ||
11275 | && !notify_plci->li_notify_update | ||
11276 | && (notify_plci->appl != NULL) | ||
11277 | && (notify_plci->State) | ||
11278 | && notify_plci->NL.Id && !notify_plci->nl_remove_id) | ||
11279 | { | ||
11280 | notify_plci->li_notify_update = TRUE; | ||
11281 | ((CAPI_MSG *) msg)->header.length = 18; | ||
11282 | ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id; | ||
11283 | ((CAPI_MSG *) msg)->header.command = _FACILITY_R; | ||
11284 | ((CAPI_MSG *) msg)->header.number = 0; | ||
11285 | ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id; | ||
11286 | ((CAPI_MSG *) msg)->header.plci = notify_plci->Id; | ||
11287 | ((CAPI_MSG *) msg)->header.ncci = 0; | ||
11288 | ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT; | ||
11289 | ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3; | ||
11290 | PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE); | ||
11291 | ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0; | ||
11292 | w = api_put (notify_plci->appl, (CAPI_MSG *) msg); | ||
11293 | if (w != _QUEUE_FULL) | ||
11294 | { | ||
11295 | if (w != 0) | ||
11296 | { | ||
11297 | dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d", | ||
11298 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
11299 | (char *)(FILE_), __LINE__, | ||
11300 | (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w)); | ||
11301 | } | ||
11302 | notify_plci->li_notify_update = FALSE; | ||
11303 | } | ||
11304 | } | ||
11305 | } while (others && (notify_plci != NULL)); | ||
11306 | if (others) | ||
11307 | plci->li_notify_update = FALSE; | ||
11308 | } | ||
11309 | } | ||
11310 | |||
11311 | |||
11312 | static void mixer_clear_config (PLCI *plci) | ||
11313 | { | ||
11314 | DIVA_CAPI_ADAPTER *a; | ||
11315 | word i, j; | ||
11316 | |||
11317 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config", | ||
11318 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
11319 | (char *)(FILE_), __LINE__)); | ||
11320 | |||
11321 | plci->li_notify_update = FALSE; | ||
11322 | plci->li_plci_b_write_pos = 0; | ||
11323 | plci->li_plci_b_read_pos = 0; | ||
11324 | plci->li_plci_b_req_pos = 0; | ||
11325 | a = plci->adapter; | ||
11326 | if ((plci->li_bchannel_id != 0) | ||
11327 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
11328 | { | ||
11329 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
11330 | li_config_table[i].curchnl = 0; | ||
11331 | li_config_table[i].channel = 0; | ||
11332 | li_config_table[i].chflags = 0; | ||
11333 | for (j = 0; j < li_total_channels; j++) | ||
11334 | { | ||
11335 | li_config_table[j].flag_table[i] = 0; | ||
11336 | li_config_table[i].flag_table[j] = 0; | ||
11337 | li_config_table[i].coef_table[j] = 0; | ||
11338 | li_config_table[j].coef_table[i] = 0; | ||
11339 | } | ||
11340 | if (!a->li_pri) | ||
11341 | { | ||
11342 | li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET; | ||
11343 | if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | ||
11344 | { | ||
11345 | i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | ||
11346 | li_config_table[i].curchnl = 0; | ||
11347 | li_config_table[i].channel = 0; | ||
11348 | li_config_table[i].chflags = 0; | ||
11349 | for (j = 0; j < li_total_channels; j++) | ||
11350 | { | ||
11351 | li_config_table[i].flag_table[j] = 0; | ||
11352 | li_config_table[j].flag_table[i] = 0; | ||
11353 | li_config_table[i].coef_table[j] = 0; | ||
11354 | li_config_table[j].coef_table[i] = 0; | ||
11355 | } | ||
11356 | if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | ||
11357 | { | ||
11358 | i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | ||
11359 | li_config_table[i].curchnl = 0; | ||
11360 | li_config_table[i].channel = 0; | ||
11361 | li_config_table[i].chflags = 0; | ||
11362 | for (j = 0; j < li_total_channels; j++) | ||
11363 | { | ||
11364 | li_config_table[i].flag_table[j] = 0; | ||
11365 | li_config_table[j].flag_table[i] = 0; | ||
11366 | li_config_table[i].coef_table[j] = 0; | ||
11367 | li_config_table[j].coef_table[i] = 0; | ||
11368 | } | ||
11369 | } | ||
11370 | } | ||
11371 | } | ||
11372 | } | ||
11373 | } | ||
11374 | |||
11375 | |||
11376 | static void mixer_prepare_switch (dword Id, PLCI *plci) | ||
11377 | { | ||
11378 | |||
11379 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch", | ||
11380 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11381 | |||
11382 | do | ||
11383 | { | ||
11384 | mixer_indication_coefs_set (Id, plci); | ||
11385 | } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos); | ||
11386 | } | ||
11387 | |||
11388 | |||
11389 | static word mixer_save_config (dword Id, PLCI *plci, byte Rc) | ||
11390 | { | ||
11391 | DIVA_CAPI_ADAPTER *a; | ||
11392 | word i, j; | ||
11393 | |||
11394 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d", | ||
11395 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
11396 | |||
11397 | a = plci->adapter; | ||
11398 | if ((plci->li_bchannel_id != 0) | ||
11399 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
11400 | { | ||
11401 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
11402 | for (j = 0; j < li_total_channels; j++) | ||
11403 | { | ||
11404 | li_config_table[i].coef_table[j] &= 0xf; | ||
11405 | li_config_table[j].coef_table[i] &= 0xf; | ||
11406 | } | ||
11407 | if (!a->li_pri) | ||
11408 | li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET; | ||
11409 | } | ||
11410 | return (GOOD); | ||
11411 | } | ||
11412 | |||
11413 | |||
11414 | static word mixer_restore_config (dword Id, PLCI *plci, byte Rc) | ||
11415 | { | ||
11416 | DIVA_CAPI_ADAPTER *a; | ||
11417 | word Info; | ||
11418 | |||
11419 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d", | ||
11420 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
11421 | |||
11422 | Info = GOOD; | ||
11423 | a = plci->adapter; | ||
11424 | if ((plci->B1_facilities & B1_FACILITY_MIXER) | ||
11425 | && (plci->li_bchannel_id != 0) | ||
11426 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
11427 | { | ||
11428 | switch (plci->adjust_b_state) | ||
11429 | { | ||
11430 | case ADJUST_B_RESTORE_MIXER_1: | ||
11431 | if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
11432 | { | ||
11433 | plci->internal_command = plci->adjust_b_command; | ||
11434 | if (plci_nl_busy (plci)) | ||
11435 | { | ||
11436 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1; | ||
11437 | break; | ||
11438 | } | ||
11439 | xconnect_query_addresses (plci); | ||
11440 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2; | ||
11441 | break; | ||
11442 | } | ||
11443 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; | ||
11444 | Rc = OK; | ||
11445 | case ADJUST_B_RESTORE_MIXER_2: | ||
11446 | case ADJUST_B_RESTORE_MIXER_3: | ||
11447 | case ADJUST_B_RESTORE_MIXER_4: | ||
11448 | if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0)) | ||
11449 | { | ||
11450 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x", | ||
11451 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
11452 | Info = _WRONG_STATE; | ||
11453 | break; | ||
11454 | } | ||
11455 | if (Rc == OK) | ||
11456 | { | ||
11457 | if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2) | ||
11458 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3; | ||
11459 | else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4) | ||
11460 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; | ||
11461 | } | ||
11462 | else if (Rc == 0) | ||
11463 | { | ||
11464 | if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2) | ||
11465 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4; | ||
11466 | else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3) | ||
11467 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5; | ||
11468 | } | ||
11469 | if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5) | ||
11470 | { | ||
11471 | plci->internal_command = plci->adjust_b_command; | ||
11472 | break; | ||
11473 | } | ||
11474 | case ADJUST_B_RESTORE_MIXER_5: | ||
11475 | xconnect_write_coefs (plci, plci->adjust_b_command); | ||
11476 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6; | ||
11477 | Rc = OK; | ||
11478 | case ADJUST_B_RESTORE_MIXER_6: | ||
11479 | if (!xconnect_write_coefs_process (Id, plci, Rc)) | ||
11480 | { | ||
11481 | dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed", | ||
11482 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11483 | Info = _FACILITY_NOT_SUPPORTED; | ||
11484 | break; | ||
11485 | } | ||
11486 | if (plci->internal_command) | ||
11487 | break; | ||
11488 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7; | ||
11489 | case ADJUST_B_RESTORE_MIXER_7: | ||
11490 | break; | ||
11491 | } | ||
11492 | } | ||
11493 | return (Info); | ||
11494 | } | ||
11495 | |||
11496 | |||
11497 | static void mixer_command (dword Id, PLCI *plci, byte Rc) | ||
11498 | { | ||
11499 | DIVA_CAPI_ADAPTER *a; | ||
11500 | word i, internal_command, Info; | ||
11501 | |||
11502 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x", | ||
11503 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command, | ||
11504 | plci->li_cmd)); | ||
11505 | |||
11506 | Info = GOOD; | ||
11507 | a = plci->adapter; | ||
11508 | internal_command = plci->internal_command; | ||
11509 | plci->internal_command = 0; | ||
11510 | switch (plci->li_cmd) | ||
11511 | { | ||
11512 | case LI_REQ_CONNECT: | ||
11513 | case LI_REQ_DISCONNECT: | ||
11514 | case LI_REQ_SILENT_UPDATE: | ||
11515 | switch (internal_command) | ||
11516 | { | ||
11517 | default: | ||
11518 | if (plci->li_channel_bits & LI_CHANNEL_INVOLVED) | ||
11519 | { | ||
11520 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | ||
11521 | B1_FACILITY_MIXER), MIXER_COMMAND_1); | ||
11522 | } | ||
11523 | case MIXER_COMMAND_1: | ||
11524 | if (plci->li_channel_bits & LI_CHANNEL_INVOLVED) | ||
11525 | { | ||
11526 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
11527 | { | ||
11528 | dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed", | ||
11529 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11530 | Info = _FACILITY_NOT_SUPPORTED; | ||
11531 | break; | ||
11532 | } | ||
11533 | if (plci->internal_command) | ||
11534 | return; | ||
11535 | } | ||
11536 | plci->li_plci_b_req_pos = plci->li_plci_b_write_pos; | ||
11537 | if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED) | ||
11538 | || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER) | ||
11539 | && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities & | ||
11540 | ~B1_FACILITY_MIXER)) == plci->B1_resource))) | ||
11541 | { | ||
11542 | xconnect_write_coefs (plci, MIXER_COMMAND_2); | ||
11543 | } | ||
11544 | else | ||
11545 | { | ||
11546 | do | ||
11547 | { | ||
11548 | mixer_indication_coefs_set (Id, plci); | ||
11549 | } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos); | ||
11550 | } | ||
11551 | case MIXER_COMMAND_2: | ||
11552 | if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED) | ||
11553 | || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER) | ||
11554 | && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities & | ||
11555 | ~B1_FACILITY_MIXER)) == plci->B1_resource))) | ||
11556 | { | ||
11557 | if (!xconnect_write_coefs_process (Id, plci, Rc)) | ||
11558 | { | ||
11559 | dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed", | ||
11560 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11561 | if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos) | ||
11562 | { | ||
11563 | do | ||
11564 | { | ||
11565 | plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ? | ||
11566 | LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1; | ||
11567 | i = (plci->li_plci_b_write_pos == 0) ? | ||
11568 | LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1; | ||
11569 | } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos) | ||
11570 | && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)); | ||
11571 | } | ||
11572 | Info = _FACILITY_NOT_SUPPORTED; | ||
11573 | break; | ||
11574 | } | ||
11575 | if (plci->internal_command) | ||
11576 | return; | ||
11577 | } | ||
11578 | if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED)) | ||
11579 | { | ||
11580 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities & | ||
11581 | ~B1_FACILITY_MIXER), MIXER_COMMAND_3); | ||
11582 | } | ||
11583 | case MIXER_COMMAND_3: | ||
11584 | if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED)) | ||
11585 | { | ||
11586 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
11587 | { | ||
11588 | dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed", | ||
11589 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11590 | Info = _FACILITY_NOT_SUPPORTED; | ||
11591 | break; | ||
11592 | } | ||
11593 | if (plci->internal_command) | ||
11594 | return; | ||
11595 | } | ||
11596 | break; | ||
11597 | } | ||
11598 | break; | ||
11599 | } | ||
11600 | if ((plci->li_bchannel_id == 0) | ||
11601 | || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)) | ||
11602 | { | ||
11603 | dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d", | ||
11604 | UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id))); | ||
11605 | } | ||
11606 | else | ||
11607 | { | ||
11608 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
11609 | li_config_table[i].curchnl = plci->li_channel_bits; | ||
11610 | if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | ||
11611 | { | ||
11612 | i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | ||
11613 | li_config_table[i].curchnl = plci->li_channel_bits; | ||
11614 | if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | ||
11615 | { | ||
11616 | i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | ||
11617 | li_config_table[i].curchnl = plci->li_channel_bits; | ||
11618 | } | ||
11619 | } | ||
11620 | } | ||
11621 | } | ||
11622 | |||
11623 | |||
11624 | static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci, | ||
11625 | dword plci_b_id, byte connect, dword li_flags) | ||
11626 | { | ||
11627 | word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s; | ||
11628 | PLCI *plci_b; | ||
11629 | DIVA_CAPI_ADAPTER *a_b; | ||
11630 | |||
11631 | a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]); | ||
11632 | plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]); | ||
11633 | ch_a = a->li_base + (plci->li_bchannel_id - 1); | ||
11634 | if (!a->li_pri && (plci->tel == ADV_VOICE) | ||
11635 | && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER)) | ||
11636 | { | ||
11637 | ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE; | ||
11638 | ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | ||
11639 | a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v; | ||
11640 | } | ||
11641 | else | ||
11642 | { | ||
11643 | ch_a_v = ch_a; | ||
11644 | ch_a_s = ch_a; | ||
11645 | } | ||
11646 | ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1); | ||
11647 | if (!a_b->li_pri && (plci_b->tel == ADV_VOICE) | ||
11648 | && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER)) | ||
11649 | { | ||
11650 | ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE; | ||
11651 | ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | ||
11652 | a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v; | ||
11653 | } | ||
11654 | else | ||
11655 | { | ||
11656 | ch_b_v = ch_b; | ||
11657 | ch_b_s = ch_b; | ||
11658 | } | ||
11659 | if (connect) | ||
11660 | { | ||
11661 | li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR; | ||
11662 | li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR; | ||
11663 | li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | ||
11664 | li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | ||
11665 | } | ||
11666 | li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR; | ||
11667 | li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR; | ||
11668 | li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | ||
11669 | li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX); | ||
11670 | if (ch_a_v == ch_b_v) | ||
11671 | { | ||
11672 | li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE; | ||
11673 | li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE; | ||
11674 | } | ||
11675 | else | ||
11676 | { | ||
11677 | if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE) | ||
11678 | { | ||
11679 | for (i = 0; i < li_total_channels; i++) | ||
11680 | { | ||
11681 | if (i != ch_a_v) | ||
11682 | li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE; | ||
11683 | } | ||
11684 | } | ||
11685 | if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE) | ||
11686 | { | ||
11687 | for (i = 0; i < li_total_channels; i++) | ||
11688 | { | ||
11689 | if (i != ch_a_s) | ||
11690 | li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE; | ||
11691 | } | ||
11692 | } | ||
11693 | if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE) | ||
11694 | { | ||
11695 | for (i = 0; i < li_total_channels; i++) | ||
11696 | { | ||
11697 | if (i != ch_a_v) | ||
11698 | li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE; | ||
11699 | } | ||
11700 | } | ||
11701 | if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE) | ||
11702 | { | ||
11703 | for (i = 0; i < li_total_channels; i++) | ||
11704 | { | ||
11705 | if (i != ch_a_s) | ||
11706 | li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE; | ||
11707 | } | ||
11708 | } | ||
11709 | } | ||
11710 | if (li_flags & LI_FLAG_CONFERENCE_A_B) | ||
11711 | { | ||
11712 | li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | ||
11713 | li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | ||
11714 | li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | ||
11715 | li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | ||
11716 | } | ||
11717 | if (li_flags & LI_FLAG_CONFERENCE_B_A) | ||
11718 | { | ||
11719 | li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | ||
11720 | li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | ||
11721 | li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | ||
11722 | li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | ||
11723 | } | ||
11724 | if (li_flags & LI_FLAG_MONITOR_A) | ||
11725 | { | ||
11726 | li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR; | ||
11727 | li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR; | ||
11728 | } | ||
11729 | if (li_flags & LI_FLAG_MONITOR_B) | ||
11730 | { | ||
11731 | li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR; | ||
11732 | li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR; | ||
11733 | } | ||
11734 | if (li_flags & LI_FLAG_ANNOUNCEMENT_A) | ||
11735 | { | ||
11736 | li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | ||
11737 | li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | ||
11738 | } | ||
11739 | if (li_flags & LI_FLAG_ANNOUNCEMENT_B) | ||
11740 | { | ||
11741 | li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | ||
11742 | li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT; | ||
11743 | } | ||
11744 | if (li_flags & LI_FLAG_MIX_A) | ||
11745 | { | ||
11746 | li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX; | ||
11747 | li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX; | ||
11748 | } | ||
11749 | if (li_flags & LI_FLAG_MIX_B) | ||
11750 | { | ||
11751 | li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX; | ||
11752 | li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX; | ||
11753 | } | ||
11754 | if (ch_a_v != ch_a_s) | ||
11755 | { | ||
11756 | li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | ||
11757 | li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | ||
11758 | } | ||
11759 | if (ch_b_v != ch_b_s) | ||
11760 | { | ||
11761 | li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | ||
11762 | li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | ||
11763 | } | ||
11764 | } | ||
11765 | |||
11766 | |||
11767 | static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci, | ||
11768 | dword plci_b_id, byte connect, dword li_flags) | ||
11769 | { | ||
11770 | word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s; | ||
11771 | PLCI *plci_b; | ||
11772 | DIVA_CAPI_ADAPTER *a_b; | ||
11773 | |||
11774 | a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]); | ||
11775 | plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]); | ||
11776 | ch_a = a->li_base + (plci->li_bchannel_id - 1); | ||
11777 | if (!a->li_pri && (plci->tel == ADV_VOICE) | ||
11778 | && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER)) | ||
11779 | { | ||
11780 | ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE; | ||
11781 | ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | ||
11782 | a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v; | ||
11783 | } | ||
11784 | else | ||
11785 | { | ||
11786 | ch_a_v = ch_a; | ||
11787 | ch_a_s = ch_a; | ||
11788 | } | ||
11789 | ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1); | ||
11790 | if (!a_b->li_pri && (plci_b->tel == ADV_VOICE) | ||
11791 | && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER)) | ||
11792 | { | ||
11793 | ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE; | ||
11794 | ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ? | ||
11795 | a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v; | ||
11796 | } | ||
11797 | else | ||
11798 | { | ||
11799 | ch_b_v = ch_b; | ||
11800 | ch_b_s = ch_b; | ||
11801 | } | ||
11802 | if (connect) | ||
11803 | { | ||
11804 | li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR; | ||
11805 | li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR; | ||
11806 | li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX; | ||
11807 | li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX; | ||
11808 | li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT; | ||
11809 | li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP); | ||
11810 | } | ||
11811 | li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11812 | li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11813 | li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11814 | li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11815 | li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11816 | li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11817 | li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11818 | li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE); | ||
11819 | if (li_flags & LI2_FLAG_INTERCONNECT_A_B) | ||
11820 | { | ||
11821 | li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT; | ||
11822 | li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT; | ||
11823 | li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT; | ||
11824 | li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT; | ||
11825 | } | ||
11826 | if (li_flags & LI2_FLAG_INTERCONNECT_B_A) | ||
11827 | { | ||
11828 | li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | ||
11829 | li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | ||
11830 | li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | ||
11831 | li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | ||
11832 | } | ||
11833 | if (li_flags & LI2_FLAG_MONITOR_B) | ||
11834 | { | ||
11835 | li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR; | ||
11836 | li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR; | ||
11837 | } | ||
11838 | if (li_flags & LI2_FLAG_MIX_B) | ||
11839 | { | ||
11840 | li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX; | ||
11841 | li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX; | ||
11842 | } | ||
11843 | if (li_flags & LI2_FLAG_MONITOR_X) | ||
11844 | li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR; | ||
11845 | if (li_flags & LI2_FLAG_MIX_X) | ||
11846 | li_config_table[ch_b].chflags |= LI_CHFLAG_MIX; | ||
11847 | if (li_flags & LI2_FLAG_LOOP_B) | ||
11848 | { | ||
11849 | li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | ||
11850 | li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT; | ||
11851 | li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | ||
11852 | li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT; | ||
11853 | } | ||
11854 | if (li_flags & LI2_FLAG_LOOP_PC) | ||
11855 | li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT; | ||
11856 | if (li_flags & LI2_FLAG_LOOP_X) | ||
11857 | li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP; | ||
11858 | if (li_flags & LI2_FLAG_PCCONNECT_A_B) | ||
11859 | li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT; | ||
11860 | if (li_flags & LI2_FLAG_PCCONNECT_B_A) | ||
11861 | li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT; | ||
11862 | if (ch_a_v != ch_a_s) | ||
11863 | { | ||
11864 | li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE; | ||
11865 | li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE; | ||
11866 | } | ||
11867 | if (ch_b_v != ch_b_s) | ||
11868 | { | ||
11869 | li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE; | ||
11870 | li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE; | ||
11871 | } | ||
11872 | } | ||
11873 | |||
11874 | |||
11875 | static word li_check_main_plci (dword Id, PLCI *plci) | ||
11876 | { | ||
11877 | if (plci == NULL) | ||
11878 | { | ||
11879 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | ||
11880 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11881 | return (_WRONG_IDENTIFIER); | ||
11882 | } | ||
11883 | if (!plci->State | ||
11884 | || !plci->NL.Id || plci->nl_remove_id | ||
11885 | || (plci->li_bchannel_id == 0)) | ||
11886 | { | ||
11887 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | ||
11888 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11889 | return (_WRONG_STATE); | ||
11890 | } | ||
11891 | li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci; | ||
11892 | return (GOOD); | ||
11893 | } | ||
11894 | |||
11895 | |||
11896 | static PLCI *li_check_plci_b (dword Id, PLCI *plci, | ||
11897 | dword plci_b_id, word plci_b_write_pos, byte *p_result) | ||
11898 | { | ||
11899 | byte ctlr_b; | ||
11900 | PLCI *plci_b; | ||
11901 | |||
11902 | if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | ||
11903 | LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2) | ||
11904 | { | ||
11905 | dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | ||
11906 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11907 | PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); | ||
11908 | return (NULL); | ||
11909 | } | ||
11910 | ctlr_b = 0; | ||
11911 | if ((plci_b_id & 0x7f) != 0) | ||
11912 | { | ||
11913 | ctlr_b = MapController ((byte)(plci_b_id & 0x7f)); | ||
11914 | if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL))) | ||
11915 | ctlr_b = 0; | ||
11916 | } | ||
11917 | if ((ctlr_b == 0) | ||
11918 | || (((plci_b_id >> 8) & 0xff) == 0) | ||
11919 | || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci)) | ||
11920 | { | ||
11921 | dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx", | ||
11922 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); | ||
11923 | PUT_WORD (p_result, _WRONG_IDENTIFIER); | ||
11924 | return (NULL); | ||
11925 | } | ||
11926 | plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]); | ||
11927 | if (!plci_b->State | ||
11928 | || !plci_b->NL.Id || plci_b->nl_remove_id | ||
11929 | || (plci_b->li_bchannel_id == 0)) | ||
11930 | { | ||
11931 | dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx", | ||
11932 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); | ||
11933 | PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); | ||
11934 | return (NULL); | ||
11935 | } | ||
11936 | li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b; | ||
11937 | if (((byte)(plci_b_id & ~EXT_CONTROLLER)) != | ||
11938 | ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER)) | ||
11939 | && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
11940 | || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT))) | ||
11941 | { | ||
11942 | dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx", | ||
11943 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); | ||
11944 | PUT_WORD (p_result, _WRONG_IDENTIFIER); | ||
11945 | return (NULL); | ||
11946 | } | ||
11947 | if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource, | ||
11948 | (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER)) | ||
11949 | { | ||
11950 | dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d", | ||
11951 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource)); | ||
11952 | PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); | ||
11953 | return (NULL); | ||
11954 | } | ||
11955 | return (plci_b); | ||
11956 | } | ||
11957 | |||
11958 | |||
11959 | static PLCI *li2_check_plci_b (dword Id, PLCI *plci, | ||
11960 | dword plci_b_id, word plci_b_write_pos, byte *p_result) | ||
11961 | { | ||
11962 | byte ctlr_b; | ||
11963 | PLCI *plci_b; | ||
11964 | |||
11965 | if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | ||
11966 | LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2) | ||
11967 | { | ||
11968 | dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | ||
11969 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
11970 | PUT_WORD (p_result, _WRONG_STATE); | ||
11971 | return (NULL); | ||
11972 | } | ||
11973 | ctlr_b = 0; | ||
11974 | if ((plci_b_id & 0x7f) != 0) | ||
11975 | { | ||
11976 | ctlr_b = MapController ((byte)(plci_b_id & 0x7f)); | ||
11977 | if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL))) | ||
11978 | ctlr_b = 0; | ||
11979 | } | ||
11980 | if ((ctlr_b == 0) | ||
11981 | || (((plci_b_id >> 8) & 0xff) == 0) | ||
11982 | || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci)) | ||
11983 | { | ||
11984 | dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx", | ||
11985 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); | ||
11986 | PUT_WORD (p_result, _WRONG_IDENTIFIER); | ||
11987 | return (NULL); | ||
11988 | } | ||
11989 | plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]); | ||
11990 | if (!plci_b->State | ||
11991 | || !plci_b->NL.Id || plci_b->nl_remove_id | ||
11992 | || (plci_b->li_bchannel_id == 0) | ||
11993 | || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b)) | ||
11994 | { | ||
11995 | dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx", | ||
11996 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); | ||
11997 | PUT_WORD (p_result, _WRONG_STATE); | ||
11998 | return (NULL); | ||
11999 | } | ||
12000 | if (((byte)(plci_b_id & ~EXT_CONTROLLER)) != | ||
12001 | ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER)) | ||
12002 | && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12003 | || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT))) | ||
12004 | { | ||
12005 | dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx", | ||
12006 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); | ||
12007 | PUT_WORD (p_result, _WRONG_IDENTIFIER); | ||
12008 | return (NULL); | ||
12009 | } | ||
12010 | if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource, | ||
12011 | (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER)) | ||
12012 | { | ||
12013 | dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d", | ||
12014 | UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource)); | ||
12015 | PUT_WORD (p_result, _WRONG_STATE); | ||
12016 | return (NULL); | ||
12017 | } | ||
12018 | return (plci_b); | ||
12019 | } | ||
12020 | |||
12021 | |||
12022 | static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg) | ||
12023 | { | ||
12024 | word Info; | ||
12025 | word i; | ||
12026 | dword d, li_flags, plci_b_id; | ||
12027 | PLCI *plci_b; | ||
12028 | API_PARSE li_parms[3]; | ||
12029 | API_PARSE li_req_parms[3]; | ||
12030 | API_PARSE li_participant_struct[2]; | ||
12031 | API_PARSE li_participant_parms[3]; | ||
12032 | word participant_parms_pos; | ||
12033 | byte result_buffer[32]; | ||
12034 | byte *result; | ||
12035 | word result_pos; | ||
12036 | word plci_b_write_pos; | ||
12037 | |||
12038 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_request", | ||
12039 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12040 | |||
12041 | Info = GOOD; | ||
12042 | result = result_buffer; | ||
12043 | result_buffer[0] = 0; | ||
12044 | if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)) | ||
12045 | { | ||
12046 | dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | ||
12047 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12048 | Info = _FACILITY_NOT_SUPPORTED; | ||
12049 | } | ||
12050 | else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms)) | ||
12051 | { | ||
12052 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12053 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12054 | Info = _WRONG_MESSAGE_FORMAT; | ||
12055 | } | ||
12056 | else | ||
12057 | { | ||
12058 | result_buffer[0] = 3; | ||
12059 | PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info)); | ||
12060 | result_buffer[3] = 0; | ||
12061 | switch (GET_WORD (li_parms[0].info)) | ||
12062 | { | ||
12063 | case LI_GET_SUPPORTED_SERVICES: | ||
12064 | if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) | ||
12065 | { | ||
12066 | result_buffer[0] = 17; | ||
12067 | result_buffer[3] = 14; | ||
12068 | PUT_WORD (&result_buffer[4], GOOD); | ||
12069 | d = 0; | ||
12070 | if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH) | ||
12071 | d |= LI_CONFERENCING_SUPPORTED; | ||
12072 | if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC) | ||
12073 | d |= LI_MONITORING_SUPPORTED; | ||
12074 | if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH) | ||
12075 | d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED; | ||
12076 | if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12077 | d |= LI_CROSS_CONTROLLER_SUPPORTED; | ||
12078 | PUT_DWORD (&result_buffer[6], d); | ||
12079 | if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12080 | { | ||
12081 | d = 0; | ||
12082 | for (i = 0; i < li_total_channels; i++) | ||
12083 | { | ||
12084 | if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12085 | && (li_config_table[i].adapter->li_pri | ||
12086 | || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI))) | ||
12087 | { | ||
12088 | d++; | ||
12089 | } | ||
12090 | } | ||
12091 | } | ||
12092 | else | ||
12093 | { | ||
12094 | d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI; | ||
12095 | } | ||
12096 | PUT_DWORD (&result_buffer[10], d / 2); | ||
12097 | PUT_DWORD (&result_buffer[14], d); | ||
12098 | } | ||
12099 | else | ||
12100 | { | ||
12101 | result_buffer[0] = 25; | ||
12102 | result_buffer[3] = 22; | ||
12103 | PUT_WORD (&result_buffer[4], GOOD); | ||
12104 | d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED; | ||
12105 | if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC) | ||
12106 | d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED; | ||
12107 | if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH) | ||
12108 | d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED; | ||
12109 | if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC) | ||
12110 | d |= LI2_PC_LOOPING_SUPPORTED; | ||
12111 | if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12112 | d |= LI2_CROSS_CONTROLLER_SUPPORTED; | ||
12113 | PUT_DWORD (&result_buffer[6], d); | ||
12114 | d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI; | ||
12115 | PUT_DWORD (&result_buffer[10], d / 2); | ||
12116 | PUT_DWORD (&result_buffer[14], d - 1); | ||
12117 | if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12118 | { | ||
12119 | d = 0; | ||
12120 | for (i = 0; i < li_total_channels; i++) | ||
12121 | { | ||
12122 | if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) | ||
12123 | && (li_config_table[i].adapter->li_pri | ||
12124 | || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI))) | ||
12125 | { | ||
12126 | d++; | ||
12127 | } | ||
12128 | } | ||
12129 | } | ||
12130 | PUT_DWORD (&result_buffer[18], d / 2); | ||
12131 | PUT_DWORD (&result_buffer[22], d - 1); | ||
12132 | } | ||
12133 | break; | ||
12134 | |||
12135 | case LI_REQ_CONNECT: | ||
12136 | if (li_parms[1].length == 8) | ||
12137 | { | ||
12138 | appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC; | ||
12139 | if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms)) | ||
12140 | { | ||
12141 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12142 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12143 | Info = _WRONG_MESSAGE_FORMAT; | ||
12144 | break; | ||
12145 | } | ||
12146 | plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff; | ||
12147 | li_flags = GET_DWORD (li_req_parms[1].info); | ||
12148 | Info = li_check_main_plci (Id, plci); | ||
12149 | result_buffer[0] = 9; | ||
12150 | result_buffer[3] = 6; | ||
12151 | PUT_DWORD (&result_buffer[4], plci_b_id); | ||
12152 | PUT_WORD (&result_buffer[8], GOOD); | ||
12153 | if (Info != GOOD) | ||
12154 | break; | ||
12155 | result = plci->saved_msg.info; | ||
12156 | for (i = 0; i <= result_buffer[0]; i++) | ||
12157 | result[i] = result_buffer[i]; | ||
12158 | plci_b_write_pos = plci->li_plci_b_write_pos; | ||
12159 | plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]); | ||
12160 | if (plci_b == NULL) | ||
12161 | break; | ||
12162 | li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags); | ||
12163 | plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG; | ||
12164 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12165 | plci->li_plci_b_write_pos = plci_b_write_pos; | ||
12166 | } | ||
12167 | else | ||
12168 | { | ||
12169 | appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC; | ||
12170 | if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms)) | ||
12171 | { | ||
12172 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12173 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12174 | Info = _WRONG_MESSAGE_FORMAT; | ||
12175 | break; | ||
12176 | } | ||
12177 | li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A); | ||
12178 | Info = li_check_main_plci (Id, plci); | ||
12179 | result_buffer[0] = 7; | ||
12180 | result_buffer[3] = 4; | ||
12181 | PUT_WORD (&result_buffer[4], Info); | ||
12182 | result_buffer[6] = 0; | ||
12183 | if (Info != GOOD) | ||
12184 | break; | ||
12185 | result = plci->saved_msg.info; | ||
12186 | for (i = 0; i <= result_buffer[0]; i++) | ||
12187 | result[i] = result_buffer[i]; | ||
12188 | plci_b_write_pos = plci->li_plci_b_write_pos; | ||
12189 | participant_parms_pos = 0; | ||
12190 | result_pos = 7; | ||
12191 | li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags); | ||
12192 | while (participant_parms_pos < li_req_parms[1].length) | ||
12193 | { | ||
12194 | result[result_pos] = 6; | ||
12195 | result_pos += 7; | ||
12196 | PUT_DWORD (&result[result_pos - 6], 0); | ||
12197 | PUT_WORD (&result[result_pos - 2], GOOD); | ||
12198 | if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos], | ||
12199 | (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct)) | ||
12200 | { | ||
12201 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12202 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12203 | PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | ||
12204 | break; | ||
12205 | } | ||
12206 | if (api_parse (&li_participant_struct[0].info[1], | ||
12207 | li_participant_struct[0].length, "dd", li_participant_parms)) | ||
12208 | { | ||
12209 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12210 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12211 | PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | ||
12212 | break; | ||
12213 | } | ||
12214 | plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff; | ||
12215 | li_flags = GET_DWORD (li_participant_parms[1].info); | ||
12216 | PUT_DWORD (&result[result_pos - 6], plci_b_id); | ||
12217 | if (sizeof(result) - result_pos < 7) | ||
12218 | { | ||
12219 | dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun", | ||
12220 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12221 | PUT_WORD (&result[result_pos - 2], _WRONG_STATE); | ||
12222 | break; | ||
12223 | } | ||
12224 | plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]); | ||
12225 | if (plci_b != NULL) | ||
12226 | { | ||
12227 | li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags); | ||
12228 | plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | | ||
12229 | ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A | | ||
12230 | LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG); | ||
12231 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12232 | } | ||
12233 | participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) - | ||
12234 | (&li_req_parms[1].info[1])); | ||
12235 | } | ||
12236 | result[0] = (byte)(result_pos - 1); | ||
12237 | result[3] = (byte)(result_pos - 4); | ||
12238 | result[6] = (byte)(result_pos - 7); | ||
12239 | i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1; | ||
12240 | if ((plci_b_write_pos == plci->li_plci_b_read_pos) | ||
12241 | || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)) | ||
12242 | { | ||
12243 | plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG; | ||
12244 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12245 | } | ||
12246 | else | ||
12247 | plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG; | ||
12248 | plci->li_plci_b_write_pos = plci_b_write_pos; | ||
12249 | } | ||
12250 | mixer_calculate_coefs (a); | ||
12251 | plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; | ||
12252 | mixer_notify_update (plci, TRUE); | ||
12253 | sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | ||
12254 | "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); | ||
12255 | plci->command = 0; | ||
12256 | plci->li_cmd = GET_WORD (li_parms[0].info); | ||
12257 | start_internal_command (Id, plci, mixer_command); | ||
12258 | return (FALSE); | ||
12259 | |||
12260 | case LI_REQ_DISCONNECT: | ||
12261 | if (li_parms[1].length == 4) | ||
12262 | { | ||
12263 | appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC; | ||
12264 | if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms)) | ||
12265 | { | ||
12266 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12267 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12268 | Info = _WRONG_MESSAGE_FORMAT; | ||
12269 | break; | ||
12270 | } | ||
12271 | plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff; | ||
12272 | Info = li_check_main_plci (Id, plci); | ||
12273 | result_buffer[0] = 9; | ||
12274 | result_buffer[3] = 6; | ||
12275 | PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info)); | ||
12276 | PUT_WORD (&result_buffer[8], GOOD); | ||
12277 | if (Info != GOOD) | ||
12278 | break; | ||
12279 | result = plci->saved_msg.info; | ||
12280 | for (i = 0; i <= result_buffer[0]; i++) | ||
12281 | result[i] = result_buffer[i]; | ||
12282 | plci_b_write_pos = plci->li_plci_b_write_pos; | ||
12283 | plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]); | ||
12284 | if (plci_b == NULL) | ||
12285 | break; | ||
12286 | li_update_connect (Id, a, plci, plci_b_id, FALSE, 0); | ||
12287 | plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG; | ||
12288 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12289 | plci->li_plci_b_write_pos = plci_b_write_pos; | ||
12290 | } | ||
12291 | else | ||
12292 | { | ||
12293 | appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC; | ||
12294 | if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms)) | ||
12295 | { | ||
12296 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12297 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12298 | Info = _WRONG_MESSAGE_FORMAT; | ||
12299 | break; | ||
12300 | } | ||
12301 | Info = li_check_main_plci (Id, plci); | ||
12302 | result_buffer[0] = 7; | ||
12303 | result_buffer[3] = 4; | ||
12304 | PUT_WORD (&result_buffer[4], Info); | ||
12305 | result_buffer[6] = 0; | ||
12306 | if (Info != GOOD) | ||
12307 | break; | ||
12308 | result = plci->saved_msg.info; | ||
12309 | for (i = 0; i <= result_buffer[0]; i++) | ||
12310 | result[i] = result_buffer[i]; | ||
12311 | plci_b_write_pos = plci->li_plci_b_write_pos; | ||
12312 | participant_parms_pos = 0; | ||
12313 | result_pos = 7; | ||
12314 | while (participant_parms_pos < li_req_parms[0].length) | ||
12315 | { | ||
12316 | result[result_pos] = 6; | ||
12317 | result_pos += 7; | ||
12318 | PUT_DWORD (&result[result_pos - 6], 0); | ||
12319 | PUT_WORD (&result[result_pos - 2], GOOD); | ||
12320 | if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos], | ||
12321 | (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct)) | ||
12322 | { | ||
12323 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12324 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12325 | PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | ||
12326 | break; | ||
12327 | } | ||
12328 | if (api_parse (&li_participant_struct[0].info[1], | ||
12329 | li_participant_struct[0].length, "d", li_participant_parms)) | ||
12330 | { | ||
12331 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12332 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12333 | PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); | ||
12334 | break; | ||
12335 | } | ||
12336 | plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff; | ||
12337 | PUT_DWORD (&result[result_pos - 6], plci_b_id); | ||
12338 | if (sizeof(result) - result_pos < 7) | ||
12339 | { | ||
12340 | dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun", | ||
12341 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12342 | PUT_WORD (&result[result_pos - 2], _WRONG_STATE); | ||
12343 | break; | ||
12344 | } | ||
12345 | plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]); | ||
12346 | if (plci_b != NULL) | ||
12347 | { | ||
12348 | li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0); | ||
12349 | plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG; | ||
12350 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12351 | } | ||
12352 | participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) - | ||
12353 | (&li_req_parms[0].info[1])); | ||
12354 | } | ||
12355 | result[0] = (byte)(result_pos - 1); | ||
12356 | result[3] = (byte)(result_pos - 4); | ||
12357 | result[6] = (byte)(result_pos - 7); | ||
12358 | i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1; | ||
12359 | if ((plci_b_write_pos == plci->li_plci_b_read_pos) | ||
12360 | || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)) | ||
12361 | { | ||
12362 | plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG; | ||
12363 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12364 | } | ||
12365 | else | ||
12366 | plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG; | ||
12367 | plci->li_plci_b_write_pos = plci_b_write_pos; | ||
12368 | } | ||
12369 | mixer_calculate_coefs (a); | ||
12370 | plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; | ||
12371 | mixer_notify_update (plci, TRUE); | ||
12372 | sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | ||
12373 | "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); | ||
12374 | plci->command = 0; | ||
12375 | plci->li_cmd = GET_WORD (li_parms[0].info); | ||
12376 | start_internal_command (Id, plci, mixer_command); | ||
12377 | return (FALSE); | ||
12378 | |||
12379 | case LI_REQ_SILENT_UPDATE: | ||
12380 | if (!plci || !plci->State | ||
12381 | || !plci->NL.Id || plci->nl_remove_id | ||
12382 | || (plci->li_bchannel_id == 0) | ||
12383 | || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci)) | ||
12384 | { | ||
12385 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | ||
12386 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12387 | return (FALSE); | ||
12388 | } | ||
12389 | plci_b_write_pos = plci->li_plci_b_write_pos; | ||
12390 | if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | ||
12391 | LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2) | ||
12392 | { | ||
12393 | dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | ||
12394 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12395 | return (FALSE); | ||
12396 | } | ||
12397 | i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1; | ||
12398 | if ((plci_b_write_pos == plci->li_plci_b_read_pos) | ||
12399 | || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG)) | ||
12400 | { | ||
12401 | plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG; | ||
12402 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12403 | } | ||
12404 | else | ||
12405 | plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG; | ||
12406 | plci->li_plci_b_write_pos = plci_b_write_pos; | ||
12407 | plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; | ||
12408 | plci->command = 0; | ||
12409 | plci->li_cmd = GET_WORD (li_parms[0].info); | ||
12410 | start_internal_command (Id, plci, mixer_command); | ||
12411 | return (FALSE); | ||
12412 | |||
12413 | default: | ||
12414 | dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x", | ||
12415 | UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info))); | ||
12416 | Info = _FACILITY_NOT_SUPPORTED; | ||
12417 | } | ||
12418 | } | ||
12419 | sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | ||
12420 | "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); | ||
12421 | return (FALSE); | ||
12422 | } | ||
12423 | |||
12424 | |||
12425 | static void mixer_indication_coefs_set (dword Id, PLCI *plci) | ||
12426 | { | ||
12427 | dword d; | ||
12428 | DIVA_CAPI_ADAPTER *a; | ||
12429 | byte result[12]; | ||
12430 | |||
12431 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set", | ||
12432 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12433 | |||
12434 | a = plci->adapter; | ||
12435 | if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos) | ||
12436 | { | ||
12437 | do | ||
12438 | { | ||
12439 | d = plci->li_plci_b_queue[plci->li_plci_b_read_pos]; | ||
12440 | if (!(d & LI_PLCI_B_SKIP_FLAG)) | ||
12441 | { | ||
12442 | if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) | ||
12443 | { | ||
12444 | if (d & LI_PLCI_B_DISC_FLAG) | ||
12445 | { | ||
12446 | result[0] = 5; | ||
12447 | PUT_WORD (&result[1], LI_IND_DISCONNECT); | ||
12448 | result[3] = 2; | ||
12449 | PUT_WORD (&result[4], _LI_USER_INITIATED); | ||
12450 | } | ||
12451 | else | ||
12452 | { | ||
12453 | result[0] = 7; | ||
12454 | PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE); | ||
12455 | result[3] = 4; | ||
12456 | PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); | ||
12457 | } | ||
12458 | } | ||
12459 | else | ||
12460 | { | ||
12461 | if (d & LI_PLCI_B_DISC_FLAG) | ||
12462 | { | ||
12463 | result[0] = 9; | ||
12464 | PUT_WORD (&result[1], LI_IND_DISCONNECT); | ||
12465 | result[3] = 6; | ||
12466 | PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); | ||
12467 | PUT_WORD (&result[8], _LI_USER_INITIATED); | ||
12468 | } | ||
12469 | else | ||
12470 | { | ||
12471 | result[0] = 7; | ||
12472 | PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE); | ||
12473 | result[3] = 4; | ||
12474 | PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); | ||
12475 | } | ||
12476 | } | ||
12477 | sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, | ||
12478 | "ws", SELECTOR_LINE_INTERCONNECT, result); | ||
12479 | } | ||
12480 | plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? | ||
12481 | 0 : plci->li_plci_b_read_pos + 1; | ||
12482 | } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)); | ||
12483 | } | ||
12484 | } | ||
12485 | |||
12486 | |||
12487 | static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length) | ||
12488 | { | ||
12489 | word i, j, ch; | ||
12490 | struct xconnect_transfer_address_s s, *p; | ||
12491 | DIVA_CAPI_ADAPTER *a; | ||
12492 | |||
12493 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d", | ||
12494 | UnMapId (Id), (char *)(FILE_), __LINE__, (int) length)); | ||
12495 | |||
12496 | a = plci->adapter; | ||
12497 | i = 1; | ||
12498 | for (i = 1; i < length; i += 16) | ||
12499 | { | ||
12500 | s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24); | ||
12501 | s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24); | ||
12502 | s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24); | ||
12503 | ch = msg[i+12] | (msg[i+13] << 8); | ||
12504 | j = ch & XCONNECT_CHANNEL_NUMBER_MASK; | ||
12505 | if (!a->li_pri && (plci->li_bchannel_id == 2)) | ||
12506 | j = 1 - j; | ||
12507 | j += a->li_base; | ||
12508 | if (ch & XCONNECT_CHANNEL_PORT_PC) | ||
12509 | p = &(li_config_table[j].send_pc); | ||
12510 | else | ||
12511 | p = &(li_config_table[j].send_b); | ||
12512 | p->card_address.low = s.card_address.low; | ||
12513 | p->card_address.high = s.card_address.high; | ||
12514 | p->offset = s.offset; | ||
12515 | li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET; | ||
12516 | } | ||
12517 | if (plci->internal_command_queue[0] | ||
12518 | && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2) | ||
12519 | || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3) | ||
12520 | || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4))) | ||
12521 | { | ||
12522 | (*(plci->internal_command_queue[0]))(Id, plci, 0); | ||
12523 | if (!plci->internal_command) | ||
12524 | next_internal_command (Id, plci); | ||
12525 | } | ||
12526 | mixer_notify_update (plci, TRUE); | ||
12527 | } | ||
12528 | |||
12529 | |||
12530 | static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length) | ||
12531 | { | ||
12532 | |||
12533 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d", | ||
12534 | UnMapId (Id), (char *)(FILE_), __LINE__, (int) length)); | ||
12535 | |||
12536 | } | ||
12537 | |||
12538 | |||
12539 | static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id) | ||
12540 | { | ||
12541 | word plci_b_write_pos; | ||
12542 | |||
12543 | plci_b_write_pos = plci->li_plci_b_write_pos; | ||
12544 | if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos : | ||
12545 | LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1) | ||
12546 | { | ||
12547 | dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", | ||
12548 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
12549 | (char *)(FILE_), __LINE__)); | ||
12550 | return (FALSE); | ||
12551 | } | ||
12552 | plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG; | ||
12553 | plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1; | ||
12554 | plci->li_plci_b_write_pos = plci_b_write_pos; | ||
12555 | return (TRUE); | ||
12556 | } | ||
12557 | |||
12558 | |||
12559 | static void mixer_remove (PLCI *plci) | ||
12560 | { | ||
12561 | DIVA_CAPI_ADAPTER *a; | ||
12562 | PLCI *notify_plci; | ||
12563 | dword plci_b_id; | ||
12564 | word i, j; | ||
12565 | |||
12566 | dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove", | ||
12567 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
12568 | (char *)(FILE_), __LINE__)); | ||
12569 | |||
12570 | a = plci->adapter; | ||
12571 | plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id); | ||
12572 | if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED) | ||
12573 | { | ||
12574 | if ((plci->li_bchannel_id != 0) | ||
12575 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
12576 | { | ||
12577 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
12578 | if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED) | ||
12579 | { | ||
12580 | for (j = 0; j < li_total_channels; j++) | ||
12581 | { | ||
12582 | if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT) | ||
12583 | || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)) | ||
12584 | { | ||
12585 | notify_plci = li_config_table[j].plci; | ||
12586 | if ((notify_plci != NULL) | ||
12587 | && (notify_plci != plci) | ||
12588 | && (notify_plci->appl != NULL) | ||
12589 | && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) | ||
12590 | && (notify_plci->State) | ||
12591 | && notify_plci->NL.Id && !notify_plci->nl_remove_id) | ||
12592 | { | ||
12593 | mixer_notify_source_removed (notify_plci, plci_b_id); | ||
12594 | } | ||
12595 | } | ||
12596 | } | ||
12597 | mixer_clear_config (plci); | ||
12598 | mixer_calculate_coefs (a); | ||
12599 | mixer_notify_update (plci, TRUE); | ||
12600 | } | ||
12601 | li_config_table[i].plci = NULL; | ||
12602 | plci->li_bchannel_id = 0; | ||
12603 | } | ||
12604 | } | ||
12605 | } | ||
12606 | |||
12607 | |||
12608 | /*------------------------------------------------------------------*/ | ||
12609 | /* Echo canceller facilities */ | ||
12610 | /*------------------------------------------------------------------*/ | ||
12611 | |||
12612 | |||
12613 | static void ec_write_parameters (PLCI *plci) | ||
12614 | { | ||
12615 | word w; | ||
12616 | byte parameter_buffer[6]; | ||
12617 | |||
12618 | dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters", | ||
12619 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
12620 | (char *)(FILE_), __LINE__)); | ||
12621 | |||
12622 | parameter_buffer[0] = 5; | ||
12623 | parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS; | ||
12624 | PUT_WORD (¶meter_buffer[2], plci->ec_idi_options); | ||
12625 | plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS; | ||
12626 | w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length; | ||
12627 | PUT_WORD (¶meter_buffer[4], w); | ||
12628 | add_p (plci, FTY, parameter_buffer); | ||
12629 | sig_req (plci, TEL_CTRL, 0); | ||
12630 | send_req (plci); | ||
12631 | } | ||
12632 | |||
12633 | |||
12634 | static void ec_clear_config (PLCI *plci) | ||
12635 | { | ||
12636 | |||
12637 | dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config", | ||
12638 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
12639 | (char *)(FILE_), __LINE__)); | ||
12640 | |||
12641 | plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER | | ||
12642 | LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING; | ||
12643 | plci->ec_tail_length = 0; | ||
12644 | } | ||
12645 | |||
12646 | |||
12647 | static void ec_prepare_switch (dword Id, PLCI *plci) | ||
12648 | { | ||
12649 | |||
12650 | dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch", | ||
12651 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12652 | |||
12653 | } | ||
12654 | |||
12655 | |||
12656 | static word ec_save_config (dword Id, PLCI *plci, byte Rc) | ||
12657 | { | ||
12658 | |||
12659 | dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d", | ||
12660 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
12661 | |||
12662 | return (GOOD); | ||
12663 | } | ||
12664 | |||
12665 | |||
12666 | static word ec_restore_config (dword Id, PLCI *plci, byte Rc) | ||
12667 | { | ||
12668 | word Info; | ||
12669 | |||
12670 | dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d", | ||
12671 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
12672 | |||
12673 | Info = GOOD; | ||
12674 | if (plci->B1_facilities & B1_FACILITY_EC) | ||
12675 | { | ||
12676 | switch (plci->adjust_b_state) | ||
12677 | { | ||
12678 | case ADJUST_B_RESTORE_EC_1: | ||
12679 | plci->internal_command = plci->adjust_b_command; | ||
12680 | if (plci->sig_req) | ||
12681 | { | ||
12682 | plci->adjust_b_state = ADJUST_B_RESTORE_EC_1; | ||
12683 | break; | ||
12684 | } | ||
12685 | ec_write_parameters (plci); | ||
12686 | plci->adjust_b_state = ADJUST_B_RESTORE_EC_2; | ||
12687 | break; | ||
12688 | case ADJUST_B_RESTORE_EC_2: | ||
12689 | if ((Rc != OK) && (Rc != OK_FC)) | ||
12690 | { | ||
12691 | dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x", | ||
12692 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
12693 | Info = _WRONG_STATE; | ||
12694 | break; | ||
12695 | } | ||
12696 | break; | ||
12697 | } | ||
12698 | } | ||
12699 | return (Info); | ||
12700 | } | ||
12701 | |||
12702 | |||
12703 | static void ec_command (dword Id, PLCI *plci, byte Rc) | ||
12704 | { | ||
12705 | word internal_command, Info; | ||
12706 | byte result[8]; | ||
12707 | |||
12708 | dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d", | ||
12709 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command, | ||
12710 | plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length)); | ||
12711 | |||
12712 | Info = GOOD; | ||
12713 | if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) | ||
12714 | { | ||
12715 | result[0] = 2; | ||
12716 | PUT_WORD (&result[1], EC_SUCCESS); | ||
12717 | } | ||
12718 | else | ||
12719 | { | ||
12720 | result[0] = 5; | ||
12721 | PUT_WORD (&result[1], plci->ec_cmd); | ||
12722 | result[3] = 2; | ||
12723 | PUT_WORD (&result[4], GOOD); | ||
12724 | } | ||
12725 | internal_command = plci->internal_command; | ||
12726 | plci->internal_command = 0; | ||
12727 | switch (plci->ec_cmd) | ||
12728 | { | ||
12729 | case EC_ENABLE_OPERATION: | ||
12730 | case EC_FREEZE_COEFFICIENTS: | ||
12731 | case EC_RESUME_COEFFICIENT_UPDATE: | ||
12732 | case EC_RESET_COEFFICIENTS: | ||
12733 | switch (internal_command) | ||
12734 | { | ||
12735 | default: | ||
12736 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities | | ||
12737 | B1_FACILITY_EC), EC_COMMAND_1); | ||
12738 | case EC_COMMAND_1: | ||
12739 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
12740 | { | ||
12741 | dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed", | ||
12742 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12743 | Info = _FACILITY_NOT_SUPPORTED; | ||
12744 | break; | ||
12745 | } | ||
12746 | if (plci->internal_command) | ||
12747 | return; | ||
12748 | case EC_COMMAND_2: | ||
12749 | if (plci->sig_req) | ||
12750 | { | ||
12751 | plci->internal_command = EC_COMMAND_2; | ||
12752 | return; | ||
12753 | } | ||
12754 | plci->internal_command = EC_COMMAND_3; | ||
12755 | ec_write_parameters (plci); | ||
12756 | return; | ||
12757 | case EC_COMMAND_3: | ||
12758 | if ((Rc != OK) && (Rc != OK_FC)) | ||
12759 | { | ||
12760 | dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x", | ||
12761 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
12762 | Info = _FACILITY_NOT_SUPPORTED; | ||
12763 | break; | ||
12764 | } | ||
12765 | break; | ||
12766 | } | ||
12767 | break; | ||
12768 | |||
12769 | case EC_DISABLE_OPERATION: | ||
12770 | switch (internal_command) | ||
12771 | { | ||
12772 | default: | ||
12773 | case EC_COMMAND_1: | ||
12774 | if (plci->B1_facilities & B1_FACILITY_EC) | ||
12775 | { | ||
12776 | if (plci->sig_req) | ||
12777 | { | ||
12778 | plci->internal_command = EC_COMMAND_1; | ||
12779 | return; | ||
12780 | } | ||
12781 | plci->internal_command = EC_COMMAND_2; | ||
12782 | ec_write_parameters (plci); | ||
12783 | return; | ||
12784 | } | ||
12785 | Rc = OK; | ||
12786 | case EC_COMMAND_2: | ||
12787 | if ((Rc != OK) && (Rc != OK_FC)) | ||
12788 | { | ||
12789 | dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x", | ||
12790 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
12791 | Info = _FACILITY_NOT_SUPPORTED; | ||
12792 | break; | ||
12793 | } | ||
12794 | adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities & | ||
12795 | ~B1_FACILITY_EC), EC_COMMAND_3); | ||
12796 | case EC_COMMAND_3: | ||
12797 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
12798 | { | ||
12799 | dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed", | ||
12800 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12801 | Info = _FACILITY_NOT_SUPPORTED; | ||
12802 | break; | ||
12803 | } | ||
12804 | if (plci->internal_command) | ||
12805 | return; | ||
12806 | break; | ||
12807 | } | ||
12808 | break; | ||
12809 | } | ||
12810 | sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number, | ||
12811 | "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ? | ||
12812 | PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result); | ||
12813 | } | ||
12814 | |||
12815 | |||
12816 | static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg) | ||
12817 | { | ||
12818 | word Info; | ||
12819 | word opt; | ||
12820 | API_PARSE ec_parms[3]; | ||
12821 | byte result[16]; | ||
12822 | |||
12823 | dbug (1, dprintf ("[%06lx] %s,%d: ec_request", | ||
12824 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12825 | |||
12826 | Info = GOOD; | ||
12827 | result[0] = 0; | ||
12828 | if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER))) | ||
12829 | { | ||
12830 | dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", | ||
12831 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12832 | Info = _FACILITY_NOT_SUPPORTED; | ||
12833 | } | ||
12834 | else | ||
12835 | { | ||
12836 | if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) | ||
12837 | { | ||
12838 | if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms)) | ||
12839 | { | ||
12840 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12841 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12842 | Info = _WRONG_MESSAGE_FORMAT; | ||
12843 | } | ||
12844 | else | ||
12845 | { | ||
12846 | if (plci == NULL) | ||
12847 | { | ||
12848 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | ||
12849 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12850 | Info = _WRONG_IDENTIFIER; | ||
12851 | } | ||
12852 | else if (!plci->State || !plci->NL.Id || plci->nl_remove_id) | ||
12853 | { | ||
12854 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | ||
12855 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12856 | Info = _WRONG_STATE; | ||
12857 | } | ||
12858 | else | ||
12859 | { | ||
12860 | plci->command = 0; | ||
12861 | plci->ec_cmd = GET_WORD (ec_parms[0].info); | ||
12862 | plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS); | ||
12863 | result[0] = 2; | ||
12864 | PUT_WORD (&result[1], EC_SUCCESS); | ||
12865 | if (msg[1].length >= 4) | ||
12866 | { | ||
12867 | opt = GET_WORD (&ec_parms[0].info[2]); | ||
12868 | plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING | | ||
12869 | LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS); | ||
12870 | if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING)) | ||
12871 | plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING; | ||
12872 | if (opt & EC_DETECT_DISABLE_TONE) | ||
12873 | plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR; | ||
12874 | if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS)) | ||
12875 | plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS; | ||
12876 | if (msg[1].length >= 6) | ||
12877 | { | ||
12878 | plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]); | ||
12879 | } | ||
12880 | } | ||
12881 | switch (plci->ec_cmd) | ||
12882 | { | ||
12883 | case EC_ENABLE_OPERATION: | ||
12884 | plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS; | ||
12885 | start_internal_command (Id, plci, ec_command); | ||
12886 | return (FALSE); | ||
12887 | |||
12888 | case EC_DISABLE_OPERATION: | ||
12889 | plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER | | ||
12890 | LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING | | ||
12891 | LEC_RESET_COEFFICIENTS; | ||
12892 | start_internal_command (Id, plci, ec_command); | ||
12893 | return (FALSE); | ||
12894 | |||
12895 | case EC_FREEZE_COEFFICIENTS: | ||
12896 | plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS; | ||
12897 | start_internal_command (Id, plci, ec_command); | ||
12898 | return (FALSE); | ||
12899 | |||
12900 | case EC_RESUME_COEFFICIENT_UPDATE: | ||
12901 | plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS; | ||
12902 | start_internal_command (Id, plci, ec_command); | ||
12903 | return (FALSE); | ||
12904 | |||
12905 | case EC_RESET_COEFFICIENTS: | ||
12906 | plci->ec_idi_options |= LEC_RESET_COEFFICIENTS; | ||
12907 | start_internal_command (Id, plci, ec_command); | ||
12908 | return (FALSE); | ||
12909 | |||
12910 | default: | ||
12911 | dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x", | ||
12912 | UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd)); | ||
12913 | PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION); | ||
12914 | } | ||
12915 | } | ||
12916 | } | ||
12917 | } | ||
12918 | else | ||
12919 | { | ||
12920 | if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms)) | ||
12921 | { | ||
12922 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", | ||
12923 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12924 | Info = _WRONG_MESSAGE_FORMAT; | ||
12925 | } | ||
12926 | else | ||
12927 | { | ||
12928 | if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES) | ||
12929 | { | ||
12930 | result[0] = 11; | ||
12931 | PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES); | ||
12932 | result[3] = 8; | ||
12933 | PUT_WORD (&result[4], GOOD); | ||
12934 | PUT_WORD (&result[6], 0x0007); | ||
12935 | PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH); | ||
12936 | PUT_WORD (&result[10], 0); | ||
12937 | } | ||
12938 | else if (plci == NULL) | ||
12939 | { | ||
12940 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI", | ||
12941 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12942 | Info = _WRONG_IDENTIFIER; | ||
12943 | } | ||
12944 | else if (!plci->State || !plci->NL.Id || plci->nl_remove_id) | ||
12945 | { | ||
12946 | dbug (1, dprintf ("[%06lx] %s,%d: Wrong state", | ||
12947 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
12948 | Info = _WRONG_STATE; | ||
12949 | } | ||
12950 | else | ||
12951 | { | ||
12952 | plci->command = 0; | ||
12953 | plci->ec_cmd = GET_WORD (ec_parms[0].info); | ||
12954 | plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS); | ||
12955 | result[0] = 5; | ||
12956 | PUT_WORD (&result[1], plci->ec_cmd); | ||
12957 | result[3] = 2; | ||
12958 | PUT_WORD (&result[4], GOOD); | ||
12959 | plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING | | ||
12960 | LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS); | ||
12961 | plci->ec_tail_length = 0; | ||
12962 | if (ec_parms[1].length >= 2) | ||
12963 | { | ||
12964 | opt = GET_WORD (&ec_parms[1].info[1]); | ||
12965 | if (opt & EC_ENABLE_NON_LINEAR_PROCESSING) | ||
12966 | plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING; | ||
12967 | if (opt & EC_DETECT_DISABLE_TONE) | ||
12968 | plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR; | ||
12969 | if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS)) | ||
12970 | plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS; | ||
12971 | if (ec_parms[1].length >= 4) | ||
12972 | { | ||
12973 | plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]); | ||
12974 | } | ||
12975 | } | ||
12976 | switch (plci->ec_cmd) | ||
12977 | { | ||
12978 | case EC_ENABLE_OPERATION: | ||
12979 | plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS; | ||
12980 | start_internal_command (Id, plci, ec_command); | ||
12981 | return (FALSE); | ||
12982 | |||
12983 | case EC_DISABLE_OPERATION: | ||
12984 | plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER | | ||
12985 | LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING | | ||
12986 | LEC_RESET_COEFFICIENTS; | ||
12987 | start_internal_command (Id, plci, ec_command); | ||
12988 | return (FALSE); | ||
12989 | |||
12990 | default: | ||
12991 | dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x", | ||
12992 | UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd)); | ||
12993 | PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP); | ||
12994 | } | ||
12995 | } | ||
12996 | } | ||
12997 | } | ||
12998 | } | ||
12999 | sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, | ||
13000 | "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ? | ||
13001 | PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result); | ||
13002 | return (FALSE); | ||
13003 | } | ||
13004 | |||
13005 | |||
13006 | static void ec_indication (dword Id, PLCI *plci, byte *msg, word length) | ||
13007 | { | ||
13008 | byte result[8]; | ||
13009 | |||
13010 | dbug (1, dprintf ("[%06lx] %s,%d: ec_indication", | ||
13011 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
13012 | |||
13013 | if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE)) | ||
13014 | { | ||
13015 | if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) | ||
13016 | { | ||
13017 | result[0] = 2; | ||
13018 | PUT_WORD (&result[1], 0); | ||
13019 | switch (msg[1]) | ||
13020 | { | ||
13021 | case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ: | ||
13022 | PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); | ||
13023 | break; | ||
13024 | case LEC_DISABLE_TYPE_REVERSED_2100HZ: | ||
13025 | PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ); | ||
13026 | break; | ||
13027 | case LEC_DISABLE_RELEASED: | ||
13028 | PUT_WORD (&result[1], EC_BYPASS_RELEASED); | ||
13029 | break; | ||
13030 | } | ||
13031 | } | ||
13032 | else | ||
13033 | { | ||
13034 | result[0] = 5; | ||
13035 | PUT_WORD (&result[1], EC_BYPASS_INDICATION); | ||
13036 | result[3] = 2; | ||
13037 | PUT_WORD (&result[4], 0); | ||
13038 | switch (msg[1]) | ||
13039 | { | ||
13040 | case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ: | ||
13041 | PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); | ||
13042 | break; | ||
13043 | case LEC_DISABLE_TYPE_REVERSED_2100HZ: | ||
13044 | PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ); | ||
13045 | break; | ||
13046 | case LEC_DISABLE_RELEASED: | ||
13047 | PUT_WORD (&result[4], EC_BYPASS_RELEASED); | ||
13048 | break; | ||
13049 | } | ||
13050 | } | ||
13051 | sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ? | ||
13052 | PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result); | ||
13053 | } | ||
13054 | } | ||
13055 | |||
13056 | |||
13057 | |||
13058 | /*------------------------------------------------------------------*/ | ||
13059 | /* Advanced voice */ | ||
13060 | /*------------------------------------------------------------------*/ | ||
13061 | |||
13062 | static void adv_voice_write_coefs (PLCI *plci, word write_command) | ||
13063 | { | ||
13064 | DIVA_CAPI_ADAPTER *a; | ||
13065 | word i; | ||
13066 | byte *p; | ||
13067 | |||
13068 | word w, n, j, k; | ||
13069 | byte ch_map[MIXER_CHANNELS_BRI]; | ||
13070 | |||
13071 | byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2]; | ||
13072 | |||
13073 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d", | ||
13074 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13075 | (char *)(FILE_), __LINE__, write_command)); | ||
13076 | |||
13077 | a = plci->adapter; | ||
13078 | p = coef_buffer + 1; | ||
13079 | *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS; | ||
13080 | i = 0; | ||
13081 | while (i + sizeof(word) <= a->adv_voice_coef_length) | ||
13082 | { | ||
13083 | PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i)); | ||
13084 | p += 2; | ||
13085 | i += 2; | ||
13086 | } | ||
13087 | while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word)) | ||
13088 | { | ||
13089 | PUT_WORD (p, 0x8000); | ||
13090 | p += 2; | ||
13091 | i += 2; | ||
13092 | } | ||
13093 | |||
13094 | if (!a->li_pri && (plci->li_bchannel_id == 0)) | ||
13095 | { | ||
13096 | if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL)) | ||
13097 | { | ||
13098 | plci->li_bchannel_id = 1; | ||
13099 | li_config_table[a->li_base].plci = plci; | ||
13100 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d", | ||
13101 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13102 | (char *)(FILE_), __LINE__, plci->li_bchannel_id)); | ||
13103 | } | ||
13104 | else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL)) | ||
13105 | { | ||
13106 | plci->li_bchannel_id = 2; | ||
13107 | li_config_table[a->li_base + 1].plci = plci; | ||
13108 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d", | ||
13109 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13110 | (char *)(FILE_), __LINE__, plci->li_bchannel_id)); | ||
13111 | } | ||
13112 | } | ||
13113 | if (!a->li_pri && (plci->li_bchannel_id != 0) | ||
13114 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
13115 | { | ||
13116 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
13117 | switch (write_command) | ||
13118 | { | ||
13119 | case ADV_VOICE_WRITE_ACTIVATION: | ||
13120 | j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | ||
13121 | k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | ||
13122 | if (!(plci->B1_facilities & B1_FACILITY_MIXER)) | ||
13123 | { | ||
13124 | li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX; | ||
13125 | li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR; | ||
13126 | } | ||
13127 | if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | ||
13128 | { | ||
13129 | li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX; | ||
13130 | li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR; | ||
13131 | li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE; | ||
13132 | li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE; | ||
13133 | } | ||
13134 | mixer_calculate_coefs (a); | ||
13135 | li_config_table[i].curchnl = li_config_table[i].channel; | ||
13136 | li_config_table[j].curchnl = li_config_table[j].channel; | ||
13137 | if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | ||
13138 | li_config_table[k].curchnl = li_config_table[k].channel; | ||
13139 | break; | ||
13140 | |||
13141 | case ADV_VOICE_WRITE_DEACTIVATION: | ||
13142 | for (j = 0; j < li_total_channels; j++) | ||
13143 | { | ||
13144 | li_config_table[i].flag_table[j] = 0; | ||
13145 | li_config_table[j].flag_table[i] = 0; | ||
13146 | } | ||
13147 | k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | ||
13148 | for (j = 0; j < li_total_channels; j++) | ||
13149 | { | ||
13150 | li_config_table[k].flag_table[j] = 0; | ||
13151 | li_config_table[j].flag_table[k] = 0; | ||
13152 | } | ||
13153 | if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | ||
13154 | { | ||
13155 | k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | ||
13156 | for (j = 0; j < li_total_channels; j++) | ||
13157 | { | ||
13158 | li_config_table[k].flag_table[j] = 0; | ||
13159 | li_config_table[j].flag_table[k] = 0; | ||
13160 | } | ||
13161 | } | ||
13162 | mixer_calculate_coefs (a); | ||
13163 | break; | ||
13164 | } | ||
13165 | if (plci->B1_facilities & B1_FACILITY_MIXER) | ||
13166 | { | ||
13167 | w = 0; | ||
13168 | if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length) | ||
13169 | w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); | ||
13170 | if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) | ||
13171 | w |= MIXER_FEATURE_ENABLE_TX_DATA; | ||
13172 | if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) | ||
13173 | w |= MIXER_FEATURE_ENABLE_RX_DATA; | ||
13174 | *(p++) = (byte) w; | ||
13175 | *(p++) = (byte)(w >> 8); | ||
13176 | for (j = 0; j < sizeof(ch_map); j += 2) | ||
13177 | { | ||
13178 | ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1)); | ||
13179 | ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id)); | ||
13180 | } | ||
13181 | for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++) | ||
13182 | { | ||
13183 | i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch]; | ||
13184 | j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch]; | ||
13185 | if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED) | ||
13186 | { | ||
13187 | *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01); | ||
13188 | w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4)); | ||
13189 | li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4; | ||
13190 | } | ||
13191 | else | ||
13192 | { | ||
13193 | *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ? | ||
13194 | a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00; | ||
13195 | } | ||
13196 | } | ||
13197 | } | ||
13198 | else | ||
13199 | { | ||
13200 | for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++) | ||
13201 | *(p++) = a->adv_voice_coef_buffer[i]; | ||
13202 | } | ||
13203 | } | ||
13204 | else | ||
13205 | |||
13206 | { | ||
13207 | for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++) | ||
13208 | *(p++) = a->adv_voice_coef_buffer[i]; | ||
13209 | } | ||
13210 | coef_buffer[0] = (p - coef_buffer) - 1; | ||
13211 | add_p (plci, FTY, coef_buffer); | ||
13212 | sig_req (plci, TEL_CTRL, 0); | ||
13213 | send_req (plci); | ||
13214 | } | ||
13215 | |||
13216 | |||
13217 | static void adv_voice_clear_config (PLCI *plci) | ||
13218 | { | ||
13219 | DIVA_CAPI_ADAPTER *a; | ||
13220 | |||
13221 | word i, j; | ||
13222 | |||
13223 | |||
13224 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config", | ||
13225 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13226 | (char *)(FILE_), __LINE__)); | ||
13227 | |||
13228 | a = plci->adapter; | ||
13229 | if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | ||
13230 | { | ||
13231 | a->adv_voice_coef_length = 0; | ||
13232 | |||
13233 | if (!a->li_pri && (plci->li_bchannel_id != 0) | ||
13234 | && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
13235 | { | ||
13236 | i = a->li_base + (plci->li_bchannel_id - 1); | ||
13237 | li_config_table[i].curchnl = 0; | ||
13238 | li_config_table[i].channel = 0; | ||
13239 | li_config_table[i].chflags = 0; | ||
13240 | for (j = 0; j < li_total_channels; j++) | ||
13241 | { | ||
13242 | li_config_table[i].flag_table[j] = 0; | ||
13243 | li_config_table[j].flag_table[i] = 0; | ||
13244 | li_config_table[i].coef_table[j] = 0; | ||
13245 | li_config_table[j].coef_table[i] = 0; | ||
13246 | } | ||
13247 | li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET; | ||
13248 | i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1); | ||
13249 | li_config_table[i].curchnl = 0; | ||
13250 | li_config_table[i].channel = 0; | ||
13251 | li_config_table[i].chflags = 0; | ||
13252 | for (j = 0; j < li_total_channels; j++) | ||
13253 | { | ||
13254 | li_config_table[i].flag_table[j] = 0; | ||
13255 | li_config_table[j].flag_table[i] = 0; | ||
13256 | li_config_table[i].coef_table[j] = 0; | ||
13257 | li_config_table[j].coef_table[i] = 0; | ||
13258 | } | ||
13259 | if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) | ||
13260 | { | ||
13261 | i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id); | ||
13262 | li_config_table[i].curchnl = 0; | ||
13263 | li_config_table[i].channel = 0; | ||
13264 | li_config_table[i].chflags = 0; | ||
13265 | for (j = 0; j < li_total_channels; j++) | ||
13266 | { | ||
13267 | li_config_table[i].flag_table[j] = 0; | ||
13268 | li_config_table[j].flag_table[i] = 0; | ||
13269 | li_config_table[i].coef_table[j] = 0; | ||
13270 | li_config_table[j].coef_table[i] = 0; | ||
13271 | } | ||
13272 | } | ||
13273 | } | ||
13274 | |||
13275 | } | ||
13276 | } | ||
13277 | |||
13278 | |||
13279 | static void adv_voice_prepare_switch (dword Id, PLCI *plci) | ||
13280 | { | ||
13281 | |||
13282 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch", | ||
13283 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
13284 | |||
13285 | } | ||
13286 | |||
13287 | |||
13288 | static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc) | ||
13289 | { | ||
13290 | |||
13291 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d", | ||
13292 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
13293 | |||
13294 | return (GOOD); | ||
13295 | } | ||
13296 | |||
13297 | |||
13298 | static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc) | ||
13299 | { | ||
13300 | DIVA_CAPI_ADAPTER *a; | ||
13301 | word Info; | ||
13302 | |||
13303 | dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d", | ||
13304 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
13305 | |||
13306 | Info = GOOD; | ||
13307 | a = plci->adapter; | ||
13308 | if ((plci->B1_facilities & B1_FACILITY_VOICE) | ||
13309 | && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)) | ||
13310 | { | ||
13311 | switch (plci->adjust_b_state) | ||
13312 | { | ||
13313 | case ADJUST_B_RESTORE_VOICE_1: | ||
13314 | plci->internal_command = plci->adjust_b_command; | ||
13315 | if (plci->sig_req) | ||
13316 | { | ||
13317 | plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1; | ||
13318 | break; | ||
13319 | } | ||
13320 | adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE); | ||
13321 | plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2; | ||
13322 | break; | ||
13323 | case ADJUST_B_RESTORE_VOICE_2: | ||
13324 | if ((Rc != OK) && (Rc != OK_FC)) | ||
13325 | { | ||
13326 | dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x", | ||
13327 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
13328 | Info = _WRONG_STATE; | ||
13329 | break; | ||
13330 | } | ||
13331 | break; | ||
13332 | } | ||
13333 | } | ||
13334 | return (Info); | ||
13335 | } | ||
13336 | |||
13337 | |||
13338 | |||
13339 | |||
13340 | /*------------------------------------------------------------------*/ | ||
13341 | /* B1 resource switching */ | ||
13342 | /*------------------------------------------------------------------*/ | ||
13343 | |||
13344 | static byte b1_facilities_table[] = | ||
13345 | { | ||
13346 | 0x00, /* 0 No bchannel resources */ | ||
13347 | 0x00, /* 1 Codec (automatic law) */ | ||
13348 | 0x00, /* 2 Codec (A-law) */ | ||
13349 | 0x00, /* 3 Codec (y-law) */ | ||
13350 | 0x00, /* 4 HDLC for X.21 */ | ||
13351 | 0x00, /* 5 HDLC */ | ||
13352 | 0x00, /* 6 External Device 0 */ | ||
13353 | 0x00, /* 7 External Device 1 */ | ||
13354 | 0x00, /* 8 HDLC 56k */ | ||
13355 | 0x00, /* 9 Transparent */ | ||
13356 | 0x00, /* 10 Loopback to network */ | ||
13357 | 0x00, /* 11 Test pattern to net */ | ||
13358 | 0x00, /* 12 Rate adaptation sync */ | ||
13359 | 0x00, /* 13 Rate adaptation async */ | ||
13360 | 0x00, /* 14 R-Interface */ | ||
13361 | 0x00, /* 15 HDLC 128k leased line */ | ||
13362 | 0x00, /* 16 FAX */ | ||
13363 | 0x00, /* 17 Modem async */ | ||
13364 | 0x00, /* 18 Modem sync HDLC */ | ||
13365 | 0x00, /* 19 V.110 async HDLC */ | ||
13366 | 0x12, /* 20 Adv voice (Trans,mixer) */ | ||
13367 | 0x00, /* 21 Codec connected to IC */ | ||
13368 | 0x0c, /* 22 Trans,DTMF */ | ||
13369 | 0x1e, /* 23 Trans,DTMF+mixer */ | ||
13370 | 0x1f, /* 24 Trans,DTMF+mixer+local */ | ||
13371 | 0x13, /* 25 Trans,mixer+local */ | ||
13372 | 0x12, /* 26 HDLC,mixer */ | ||
13373 | 0x12, /* 27 HDLC 56k,mixer */ | ||
13374 | 0x2c, /* 28 Trans,LEC+DTMF */ | ||
13375 | 0x3e, /* 29 Trans,LEC+DTMF+mixer */ | ||
13376 | 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */ | ||
13377 | 0x2c, /* 31 RTP,LEC+DTMF */ | ||
13378 | 0x3e, /* 32 RTP,LEC+DTMF+mixer */ | ||
13379 | 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */ | ||
13380 | 0x00, /* 34 Signaling task */ | ||
13381 | 0x00, /* 35 PIAFS */ | ||
13382 | 0x0c, /* 36 Trans,DTMF+TONE */ | ||
13383 | 0x1e, /* 37 Trans,DTMF+TONE+mixer */ | ||
13384 | 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/ | ||
13385 | }; | ||
13386 | |||
13387 | |||
13388 | static word get_b1_facilities (PLCI * plci, byte b1_resource) | ||
13389 | { | ||
13390 | word b1_facilities; | ||
13391 | |||
13392 | b1_facilities = b1_facilities_table[b1_resource]; | ||
13393 | if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25)) | ||
13394 | { | ||
13395 | |||
13396 | if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE)) | ||
13397 | || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE))))) | ||
13398 | |||
13399 | { | ||
13400 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND) | ||
13401 | b1_facilities |= B1_FACILITY_DTMFX; | ||
13402 | if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE) | ||
13403 | b1_facilities |= B1_FACILITY_DTMFR; | ||
13404 | } | ||
13405 | } | ||
13406 | if ((b1_resource == 17) || (b1_resource == 18)) | ||
13407 | { | ||
13408 | if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN)) | ||
13409 | b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR; | ||
13410 | } | ||
13411 | /* | ||
13412 | dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x", | ||
13413 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13414 | (char far *)(FILE_), __LINE__, b1_resource, b1_facilites)); | ||
13415 | */ | ||
13416 | return (b1_facilities); | ||
13417 | } | ||
13418 | |||
13419 | |||
13420 | static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities) | ||
13421 | { | ||
13422 | byte b; | ||
13423 | |||
13424 | switch (b1_resource) | ||
13425 | { | ||
13426 | case 5: | ||
13427 | case 26: | ||
13428 | if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13429 | b = 26; | ||
13430 | else | ||
13431 | b = 5; | ||
13432 | break; | ||
13433 | |||
13434 | case 8: | ||
13435 | case 27: | ||
13436 | if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13437 | b = 27; | ||
13438 | else | ||
13439 | b = 8; | ||
13440 | break; | ||
13441 | |||
13442 | case 9: | ||
13443 | case 20: | ||
13444 | case 22: | ||
13445 | case 23: | ||
13446 | case 24: | ||
13447 | case 25: | ||
13448 | case 28: | ||
13449 | case 29: | ||
13450 | case 30: | ||
13451 | case 36: | ||
13452 | case 37: | ||
13453 | case 38: | ||
13454 | if (b1_facilities & B1_FACILITY_EC) | ||
13455 | { | ||
13456 | if (b1_facilities & B1_FACILITY_LOCAL) | ||
13457 | b = 30; | ||
13458 | else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13459 | b = 29; | ||
13460 | else | ||
13461 | b = 28; | ||
13462 | } | ||
13463 | |||
13464 | else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER)) | ||
13465 | && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE)) | ||
13466 | || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE))))) | ||
13467 | { | ||
13468 | if (b1_facilities & B1_FACILITY_LOCAL) | ||
13469 | b = 38; | ||
13470 | else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13471 | b = 37; | ||
13472 | else | ||
13473 | b = 36; | ||
13474 | } | ||
13475 | |||
13476 | else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF) | ||
13477 | && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)) | ||
13478 | || ((b1_facilities & B1_FACILITY_DTMFR) | ||
13479 | && ((b1_facilities & B1_FACILITY_MIXER) | ||
13480 | || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))) | ||
13481 | || ((b1_facilities & B1_FACILITY_DTMFX) | ||
13482 | && ((b1_facilities & B1_FACILITY_MIXER) | ||
13483 | || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)))) | ||
13484 | { | ||
13485 | if (b1_facilities & B1_FACILITY_LOCAL) | ||
13486 | b = 24; | ||
13487 | else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13488 | b = 23; | ||
13489 | else | ||
13490 | b = 22; | ||
13491 | } | ||
13492 | else | ||
13493 | { | ||
13494 | if (b1_facilities & B1_FACILITY_LOCAL) | ||
13495 | b = 25; | ||
13496 | else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13497 | b = 20; | ||
13498 | else | ||
13499 | b = 9; | ||
13500 | } | ||
13501 | break; | ||
13502 | |||
13503 | case 31: | ||
13504 | case 32: | ||
13505 | case 33: | ||
13506 | if (b1_facilities & B1_FACILITY_LOCAL) | ||
13507 | b = 33; | ||
13508 | else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE)) | ||
13509 | b = 32; | ||
13510 | else | ||
13511 | b = 31; | ||
13512 | break; | ||
13513 | |||
13514 | default: | ||
13515 | b = b1_resource; | ||
13516 | } | ||
13517 | dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x", | ||
13518 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13519 | (char *)(FILE_), __LINE__, | ||
13520 | b1_resource, b1_facilities, b, get_b1_facilities (plci, b))); | ||
13521 | return (b); | ||
13522 | } | ||
13523 | |||
13524 | |||
13525 | static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities) | ||
13526 | { | ||
13527 | word removed_facilities; | ||
13528 | |||
13529 | dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x", | ||
13530 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13531 | (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities, | ||
13532 | new_b1_facilities & get_b1_facilities (plci, new_b1_resource))); | ||
13533 | |||
13534 | new_b1_facilities &= get_b1_facilities (plci, new_b1_resource); | ||
13535 | removed_facilities = plci->B1_facilities & ~new_b1_facilities; | ||
13536 | |||
13537 | if (removed_facilities & B1_FACILITY_EC) | ||
13538 | ec_clear_config (plci); | ||
13539 | |||
13540 | |||
13541 | if (removed_facilities & B1_FACILITY_DTMFR) | ||
13542 | { | ||
13543 | dtmf_rec_clear_config (plci); | ||
13544 | dtmf_parameter_clear_config (plci); | ||
13545 | } | ||
13546 | if (removed_facilities & B1_FACILITY_DTMFX) | ||
13547 | dtmf_send_clear_config (plci); | ||
13548 | |||
13549 | |||
13550 | if (removed_facilities & B1_FACILITY_MIXER) | ||
13551 | mixer_clear_config (plci); | ||
13552 | |||
13553 | if (removed_facilities & B1_FACILITY_VOICE) | ||
13554 | adv_voice_clear_config (plci); | ||
13555 | plci->B1_facilities = new_b1_facilities; | ||
13556 | } | ||
13557 | |||
13558 | |||
13559 | static void adjust_b_clear (PLCI *plci) | ||
13560 | { | ||
13561 | |||
13562 | dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear", | ||
13563 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
13564 | (char *)(FILE_), __LINE__)); | ||
13565 | |||
13566 | plci->adjust_b_restore = FALSE; | ||
13567 | } | ||
13568 | |||
13569 | |||
13570 | static word adjust_b_process (dword Id, PLCI *plci, byte Rc) | ||
13571 | { | ||
13572 | word Info; | ||
13573 | byte b1_resource; | ||
13574 | NCCI * ncci_ptr; | ||
13575 | API_PARSE bp[2]; | ||
13576 | |||
13577 | dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d", | ||
13578 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state)); | ||
13579 | |||
13580 | Info = GOOD; | ||
13581 | switch (plci->adjust_b_state) | ||
13582 | { | ||
13583 | case ADJUST_B_START: | ||
13584 | if ((plci->adjust_b_parms_msg == NULL) | ||
13585 | && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1) | ||
13586 | && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | | ||
13587 | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0)) | ||
13588 | { | ||
13589 | b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ? | ||
13590 | 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities); | ||
13591 | if (b1_resource == plci->B1_resource) | ||
13592 | { | ||
13593 | adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities); | ||
13594 | break; | ||
13595 | } | ||
13596 | if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource)) | ||
13597 | { | ||
13598 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x", | ||
13599 | UnMapId (Id), (char *)(FILE_), __LINE__, | ||
13600 | plci->B1_resource, b1_resource, plci->adjust_b_facilities)); | ||
13601 | Info = _WRONG_STATE; | ||
13602 | break; | ||
13603 | } | ||
13604 | } | ||
13605 | if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | ||
13606 | { | ||
13607 | |||
13608 | mixer_prepare_switch (Id, plci); | ||
13609 | |||
13610 | |||
13611 | dtmf_prepare_switch (Id, plci); | ||
13612 | dtmf_parameter_prepare_switch (Id, plci); | ||
13613 | |||
13614 | |||
13615 | ec_prepare_switch (Id, plci); | ||
13616 | |||
13617 | adv_voice_prepare_switch (Id, plci); | ||
13618 | } | ||
13619 | plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1; | ||
13620 | Rc = OK; | ||
13621 | case ADJUST_B_SAVE_MIXER_1: | ||
13622 | if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | ||
13623 | { | ||
13624 | |||
13625 | Info = mixer_save_config (Id, plci, Rc); | ||
13626 | if ((Info != GOOD) || plci->internal_command) | ||
13627 | break; | ||
13628 | |||
13629 | } | ||
13630 | plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1; | ||
13631 | Rc = OK; | ||
13632 | case ADJUST_B_SAVE_DTMF_1: | ||
13633 | if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | ||
13634 | { | ||
13635 | |||
13636 | Info = dtmf_save_config (Id, plci, Rc); | ||
13637 | if ((Info != GOOD) || plci->internal_command) | ||
13638 | break; | ||
13639 | |||
13640 | } | ||
13641 | plci->adjust_b_state = ADJUST_B_REMOVE_L23_1; | ||
13642 | case ADJUST_B_REMOVE_L23_1: | ||
13643 | if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23) | ||
13644 | && plci->NL.Id && !plci->nl_remove_id) | ||
13645 | { | ||
13646 | plci->internal_command = plci->adjust_b_command; | ||
13647 | if (plci->adjust_b_ncci != 0) | ||
13648 | { | ||
13649 | ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]); | ||
13650 | while (ncci_ptr->data_pending) | ||
13651 | { | ||
13652 | plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P; | ||
13653 | data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]); | ||
13654 | } | ||
13655 | while (ncci_ptr->data_ack_pending) | ||
13656 | data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]); | ||
13657 | } | ||
13658 | nl_req_ncci (plci, REMOVE, | ||
13659 | (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0)); | ||
13660 | send_req (plci); | ||
13661 | plci->adjust_b_state = ADJUST_B_REMOVE_L23_2; | ||
13662 | break; | ||
13663 | } | ||
13664 | plci->adjust_b_state = ADJUST_B_REMOVE_L23_2; | ||
13665 | Rc = OK; | ||
13666 | case ADJUST_B_REMOVE_L23_2: | ||
13667 | if ((Rc != OK) && (Rc != OK_FC)) | ||
13668 | { | ||
13669 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x", | ||
13670 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
13671 | Info = _WRONG_STATE; | ||
13672 | break; | ||
13673 | } | ||
13674 | if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23) | ||
13675 | { | ||
13676 | if (plci_nl_busy (plci)) | ||
13677 | { | ||
13678 | plci->internal_command = plci->adjust_b_command; | ||
13679 | break; | ||
13680 | } | ||
13681 | } | ||
13682 | plci->adjust_b_state = ADJUST_B_SAVE_EC_1; | ||
13683 | Rc = OK; | ||
13684 | case ADJUST_B_SAVE_EC_1: | ||
13685 | if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | ||
13686 | { | ||
13687 | |||
13688 | Info = ec_save_config (Id, plci, Rc); | ||
13689 | if ((Info != GOOD) || plci->internal_command) | ||
13690 | break; | ||
13691 | |||
13692 | } | ||
13693 | plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1; | ||
13694 | Rc = OK; | ||
13695 | case ADJUST_B_SAVE_DTMF_PARAMETER_1: | ||
13696 | if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | ||
13697 | { | ||
13698 | |||
13699 | Info = dtmf_parameter_save_config (Id, plci, Rc); | ||
13700 | if ((Info != GOOD) || plci->internal_command) | ||
13701 | break; | ||
13702 | |||
13703 | } | ||
13704 | plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1; | ||
13705 | Rc = OK; | ||
13706 | case ADJUST_B_SAVE_VOICE_1: | ||
13707 | if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE) | ||
13708 | { | ||
13709 | Info = adv_voice_save_config (Id, plci, Rc); | ||
13710 | if ((Info != GOOD) || plci->internal_command) | ||
13711 | break; | ||
13712 | } | ||
13713 | plci->adjust_b_state = ADJUST_B_SWITCH_L1_1; | ||
13714 | case ADJUST_B_SWITCH_L1_1: | ||
13715 | if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1) | ||
13716 | { | ||
13717 | if (plci->sig_req) | ||
13718 | { | ||
13719 | plci->internal_command = plci->adjust_b_command; | ||
13720 | break; | ||
13721 | } | ||
13722 | if (plci->adjust_b_parms_msg != NULL) | ||
13723 | api_load_msg (plci->adjust_b_parms_msg, bp); | ||
13724 | else | ||
13725 | api_load_msg (&plci->B_protocol, bp); | ||
13726 | Info = add_b1 (plci, bp, | ||
13727 | (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0), | ||
13728 | plci->adjust_b_facilities); | ||
13729 | if (Info != GOOD) | ||
13730 | { | ||
13731 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x", | ||
13732 | UnMapId (Id), (char *)(FILE_), __LINE__, | ||
13733 | plci->B1_resource, plci->adjust_b_facilities)); | ||
13734 | break; | ||
13735 | } | ||
13736 | plci->internal_command = plci->adjust_b_command; | ||
13737 | sig_req (plci, RESOURCES, 0); | ||
13738 | send_req (plci); | ||
13739 | plci->adjust_b_state = ADJUST_B_SWITCH_L1_2; | ||
13740 | break; | ||
13741 | } | ||
13742 | plci->adjust_b_state = ADJUST_B_SWITCH_L1_2; | ||
13743 | Rc = OK; | ||
13744 | case ADJUST_B_SWITCH_L1_2: | ||
13745 | if ((Rc != OK) && (Rc != OK_FC)) | ||
13746 | { | ||
13747 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x", | ||
13748 | UnMapId (Id), (char *)(FILE_), __LINE__, | ||
13749 | Rc, plci->B1_resource, plci->adjust_b_facilities)); | ||
13750 | Info = _WRONG_STATE; | ||
13751 | break; | ||
13752 | } | ||
13753 | plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1; | ||
13754 | Rc = OK; | ||
13755 | case ADJUST_B_RESTORE_VOICE_1: | ||
13756 | case ADJUST_B_RESTORE_VOICE_2: | ||
13757 | if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | ||
13758 | { | ||
13759 | Info = adv_voice_restore_config (Id, plci, Rc); | ||
13760 | if ((Info != GOOD) || plci->internal_command) | ||
13761 | break; | ||
13762 | } | ||
13763 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1; | ||
13764 | Rc = OK; | ||
13765 | case ADJUST_B_RESTORE_DTMF_PARAMETER_1: | ||
13766 | case ADJUST_B_RESTORE_DTMF_PARAMETER_2: | ||
13767 | if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | ||
13768 | { | ||
13769 | |||
13770 | Info = dtmf_parameter_restore_config (Id, plci, Rc); | ||
13771 | if ((Info != GOOD) || plci->internal_command) | ||
13772 | break; | ||
13773 | |||
13774 | } | ||
13775 | plci->adjust_b_state = ADJUST_B_RESTORE_EC_1; | ||
13776 | Rc = OK; | ||
13777 | case ADJUST_B_RESTORE_EC_1: | ||
13778 | case ADJUST_B_RESTORE_EC_2: | ||
13779 | if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | ||
13780 | { | ||
13781 | |||
13782 | Info = ec_restore_config (Id, plci, Rc); | ||
13783 | if ((Info != GOOD) || plci->internal_command) | ||
13784 | break; | ||
13785 | |||
13786 | } | ||
13787 | plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1; | ||
13788 | case ADJUST_B_ASSIGN_L23_1: | ||
13789 | if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23) | ||
13790 | { | ||
13791 | if (plci_nl_busy (plci)) | ||
13792 | { | ||
13793 | plci->internal_command = plci->adjust_b_command; | ||
13794 | break; | ||
13795 | } | ||
13796 | if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) | ||
13797 | plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; | ||
13798 | if (plci->adjust_b_parms_msg != NULL) | ||
13799 | api_load_msg (plci->adjust_b_parms_msg, bp); | ||
13800 | else | ||
13801 | api_load_msg (&plci->B_protocol, bp); | ||
13802 | Info = add_b23 (plci, bp); | ||
13803 | if (Info != GOOD) | ||
13804 | { | ||
13805 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x", | ||
13806 | UnMapId (Id), (char *)(FILE_), __LINE__, Info)); | ||
13807 | break; | ||
13808 | } | ||
13809 | plci->internal_command = plci->adjust_b_command; | ||
13810 | nl_req_ncci (plci, ASSIGN, 0); | ||
13811 | send_req (plci); | ||
13812 | plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2; | ||
13813 | break; | ||
13814 | } | ||
13815 | plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2; | ||
13816 | Rc = ASSIGN_OK; | ||
13817 | case ADJUST_B_ASSIGN_L23_2: | ||
13818 | if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK)) | ||
13819 | { | ||
13820 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x", | ||
13821 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
13822 | Info = _WRONG_STATE; | ||
13823 | break; | ||
13824 | } | ||
13825 | if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23) | ||
13826 | { | ||
13827 | if (Rc != ASSIGN_OK) | ||
13828 | { | ||
13829 | plci->internal_command = plci->adjust_b_command; | ||
13830 | break; | ||
13831 | } | ||
13832 | } | ||
13833 | if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT) | ||
13834 | { | ||
13835 | plci->adjust_b_restore = TRUE; | ||
13836 | break; | ||
13837 | } | ||
13838 | plci->adjust_b_state = ADJUST_B_CONNECT_1; | ||
13839 | case ADJUST_B_CONNECT_1: | ||
13840 | if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) | ||
13841 | { | ||
13842 | plci->internal_command = plci->adjust_b_command; | ||
13843 | if (plci_nl_busy (plci)) | ||
13844 | break; | ||
13845 | nl_req_ncci (plci, N_CONNECT, 0); | ||
13846 | send_req (plci); | ||
13847 | plci->adjust_b_state = ADJUST_B_CONNECT_2; | ||
13848 | break; | ||
13849 | } | ||
13850 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | ||
13851 | Rc = OK; | ||
13852 | case ADJUST_B_CONNECT_2: | ||
13853 | case ADJUST_B_CONNECT_3: | ||
13854 | case ADJUST_B_CONNECT_4: | ||
13855 | if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0)) | ||
13856 | { | ||
13857 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x", | ||
13858 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
13859 | Info = _WRONG_STATE; | ||
13860 | break; | ||
13861 | } | ||
13862 | if (Rc == OK) | ||
13863 | { | ||
13864 | if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) | ||
13865 | { | ||
13866 | get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci); | ||
13867 | Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16); | ||
13868 | } | ||
13869 | if (plci->adjust_b_state == ADJUST_B_CONNECT_2) | ||
13870 | plci->adjust_b_state = ADJUST_B_CONNECT_3; | ||
13871 | else if (plci->adjust_b_state == ADJUST_B_CONNECT_4) | ||
13872 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | ||
13873 | } | ||
13874 | else if (Rc == 0) | ||
13875 | { | ||
13876 | if (plci->adjust_b_state == ADJUST_B_CONNECT_2) | ||
13877 | plci->adjust_b_state = ADJUST_B_CONNECT_4; | ||
13878 | else if (plci->adjust_b_state == ADJUST_B_CONNECT_3) | ||
13879 | plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1; | ||
13880 | } | ||
13881 | if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1) | ||
13882 | { | ||
13883 | plci->internal_command = plci->adjust_b_command; | ||
13884 | break; | ||
13885 | } | ||
13886 | Rc = OK; | ||
13887 | case ADJUST_B_RESTORE_DTMF_1: | ||
13888 | case ADJUST_B_RESTORE_DTMF_2: | ||
13889 | if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | ||
13890 | { | ||
13891 | |||
13892 | Info = dtmf_restore_config (Id, plci, Rc); | ||
13893 | if ((Info != GOOD) || plci->internal_command) | ||
13894 | break; | ||
13895 | |||
13896 | } | ||
13897 | plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1; | ||
13898 | Rc = OK; | ||
13899 | case ADJUST_B_RESTORE_MIXER_1: | ||
13900 | case ADJUST_B_RESTORE_MIXER_2: | ||
13901 | case ADJUST_B_RESTORE_MIXER_3: | ||
13902 | case ADJUST_B_RESTORE_MIXER_4: | ||
13903 | case ADJUST_B_RESTORE_MIXER_5: | ||
13904 | case ADJUST_B_RESTORE_MIXER_6: | ||
13905 | case ADJUST_B_RESTORE_MIXER_7: | ||
13906 | if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE) | ||
13907 | { | ||
13908 | |||
13909 | Info = mixer_restore_config (Id, plci, Rc); | ||
13910 | if ((Info != GOOD) || plci->internal_command) | ||
13911 | break; | ||
13912 | |||
13913 | } | ||
13914 | plci->adjust_b_state = ADJUST_B_END; | ||
13915 | case ADJUST_B_END: | ||
13916 | break; | ||
13917 | } | ||
13918 | return (Info); | ||
13919 | } | ||
13920 | |||
13921 | |||
13922 | static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command) | ||
13923 | { | ||
13924 | |||
13925 | dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x", | ||
13926 | UnMapId (Id), (char *)(FILE_), __LINE__, | ||
13927 | plci->B1_resource, b1_facilities)); | ||
13928 | |||
13929 | plci->adjust_b_parms_msg = bp_msg; | ||
13930 | plci->adjust_b_facilities = b1_facilities; | ||
13931 | plci->adjust_b_command = internal_command; | ||
13932 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
13933 | if ((bp_msg == NULL) && (plci->B1_resource == 0)) | ||
13934 | plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1; | ||
13935 | else | ||
13936 | plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE; | ||
13937 | plci->adjust_b_state = ADJUST_B_START; | ||
13938 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...", | ||
13939 | UnMapId (Id), (char *)(FILE_), __LINE__, | ||
13940 | plci->B1_resource, b1_facilities)); | ||
13941 | } | ||
13942 | |||
13943 | |||
13944 | static void adjust_b_restore (dword Id, PLCI *plci, byte Rc) | ||
13945 | { | ||
13946 | word internal_command; | ||
13947 | |||
13948 | dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x", | ||
13949 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
13950 | |||
13951 | internal_command = plci->internal_command; | ||
13952 | plci->internal_command = 0; | ||
13953 | switch (internal_command) | ||
13954 | { | ||
13955 | default: | ||
13956 | plci->command = 0; | ||
13957 | if (plci->req_in != 0) | ||
13958 | { | ||
13959 | plci->internal_command = ADJUST_B_RESTORE_1; | ||
13960 | break; | ||
13961 | } | ||
13962 | Rc = OK; | ||
13963 | case ADJUST_B_RESTORE_1: | ||
13964 | if ((Rc != OK) && (Rc != OK_FC)) | ||
13965 | { | ||
13966 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x", | ||
13967 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
13968 | } | ||
13969 | plci->adjust_b_parms_msg = NULL; | ||
13970 | plci->adjust_b_facilities = plci->B1_facilities; | ||
13971 | plci->adjust_b_command = ADJUST_B_RESTORE_2; | ||
13972 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
13973 | plci->adjust_b_mode = ADJUST_B_MODE_RESTORE; | ||
13974 | plci->adjust_b_state = ADJUST_B_START; | ||
13975 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...", | ||
13976 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
13977 | case ADJUST_B_RESTORE_2: | ||
13978 | if (adjust_b_process (Id, plci, Rc) != GOOD) | ||
13979 | { | ||
13980 | dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed", | ||
13981 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
13982 | } | ||
13983 | if (plci->internal_command) | ||
13984 | break; | ||
13985 | break; | ||
13986 | } | ||
13987 | } | ||
13988 | |||
13989 | |||
13990 | static void reset_b3_command (dword Id, PLCI *plci, byte Rc) | ||
13991 | { | ||
13992 | word Info; | ||
13993 | word internal_command; | ||
13994 | |||
13995 | dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x", | ||
13996 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
13997 | |||
13998 | Info = GOOD; | ||
13999 | internal_command = plci->internal_command; | ||
14000 | plci->internal_command = 0; | ||
14001 | switch (internal_command) | ||
14002 | { | ||
14003 | default: | ||
14004 | plci->command = 0; | ||
14005 | plci->adjust_b_parms_msg = NULL; | ||
14006 | plci->adjust_b_facilities = plci->B1_facilities; | ||
14007 | plci->adjust_b_command = RESET_B3_COMMAND_1; | ||
14008 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
14009 | plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT; | ||
14010 | plci->adjust_b_state = ADJUST_B_START; | ||
14011 | dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...", | ||
14012 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14013 | case RESET_B3_COMMAND_1: | ||
14014 | Info = adjust_b_process (Id, plci, Rc); | ||
14015 | if (Info != GOOD) | ||
14016 | { | ||
14017 | dbug (1, dprintf ("[%06lx] %s,%d: Reset failed", | ||
14018 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14019 | break; | ||
14020 | } | ||
14021 | if (plci->internal_command) | ||
14022 | return; | ||
14023 | break; | ||
14024 | } | ||
14025 | /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/ | ||
14026 | sendf(plci->appl,_RESET_B3_I,Id,0,"s",""); | ||
14027 | } | ||
14028 | |||
14029 | |||
14030 | static void select_b_command (dword Id, PLCI *plci, byte Rc) | ||
14031 | { | ||
14032 | word Info; | ||
14033 | word internal_command; | ||
14034 | byte esc_chi[3]; | ||
14035 | |||
14036 | dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x", | ||
14037 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14038 | |||
14039 | Info = GOOD; | ||
14040 | internal_command = plci->internal_command; | ||
14041 | plci->internal_command = 0; | ||
14042 | switch (internal_command) | ||
14043 | { | ||
14044 | default: | ||
14045 | plci->command = 0; | ||
14046 | plci->adjust_b_parms_msg = &plci->saved_msg; | ||
14047 | if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI)) | ||
14048 | plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE; | ||
14049 | else | ||
14050 | plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE; | ||
14051 | plci->adjust_b_command = SELECT_B_COMMAND_1; | ||
14052 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
14053 | if (plci->saved_msg.parms[0].length == 0) | ||
14054 | { | ||
14055 | plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 | | ||
14056 | ADJUST_B_MODE_NO_RESOURCE; | ||
14057 | } | ||
14058 | else | ||
14059 | { | ||
14060 | plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 | | ||
14061 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE; | ||
14062 | } | ||
14063 | plci->adjust_b_state = ADJUST_B_START; | ||
14064 | dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...", | ||
14065 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14066 | case SELECT_B_COMMAND_1: | ||
14067 | Info = adjust_b_process (Id, plci, Rc); | ||
14068 | if (Info != GOOD) | ||
14069 | { | ||
14070 | dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed", | ||
14071 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14072 | break; | ||
14073 | } | ||
14074 | if (plci->internal_command) | ||
14075 | return; | ||
14076 | if (plci->tel == ADV_VOICE) | ||
14077 | { | ||
14078 | esc_chi[0] = 0x02; | ||
14079 | esc_chi[1] = 0x18; | ||
14080 | esc_chi[2] = plci->b_channel; | ||
14081 | SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter); | ||
14082 | } | ||
14083 | break; | ||
14084 | } | ||
14085 | sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info); | ||
14086 | } | ||
14087 | |||
14088 | |||
14089 | static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc) | ||
14090 | { | ||
14091 | word Info; | ||
14092 | word internal_command; | ||
14093 | |||
14094 | dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x", | ||
14095 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14096 | |||
14097 | Info = GOOD; | ||
14098 | internal_command = plci->internal_command; | ||
14099 | plci->internal_command = 0; | ||
14100 | switch (internal_command) | ||
14101 | { | ||
14102 | default: | ||
14103 | plci->command = 0; | ||
14104 | case FAX_CONNECT_ACK_COMMAND_1: | ||
14105 | if (plci_nl_busy (plci)) | ||
14106 | { | ||
14107 | plci->internal_command = FAX_CONNECT_ACK_COMMAND_1; | ||
14108 | return; | ||
14109 | } | ||
14110 | plci->internal_command = FAX_CONNECT_ACK_COMMAND_2; | ||
14111 | plci->NData[0].P = plci->fax_connect_info_buffer; | ||
14112 | plci->NData[0].PLength = plci->fax_connect_info_length; | ||
14113 | plci->NL.X = plci->NData; | ||
14114 | plci->NL.ReqCh = 0; | ||
14115 | plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK; | ||
14116 | plci->adapter->request (&plci->NL); | ||
14117 | return; | ||
14118 | case FAX_CONNECT_ACK_COMMAND_2: | ||
14119 | if ((Rc != OK) && (Rc != OK_FC)) | ||
14120 | { | ||
14121 | dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x", | ||
14122 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
14123 | break; | ||
14124 | } | ||
14125 | } | ||
14126 | if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) | ||
14127 | && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) | ||
14128 | { | ||
14129 | if (plci->B3_prot == 4) | ||
14130 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s",""); | ||
14131 | else | ||
14132 | sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer); | ||
14133 | plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT; | ||
14134 | } | ||
14135 | } | ||
14136 | |||
14137 | |||
14138 | static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc) | ||
14139 | { | ||
14140 | word Info; | ||
14141 | word internal_command; | ||
14142 | |||
14143 | dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x", | ||
14144 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14145 | |||
14146 | Info = GOOD; | ||
14147 | internal_command = plci->internal_command; | ||
14148 | plci->internal_command = 0; | ||
14149 | switch (internal_command) | ||
14150 | { | ||
14151 | default: | ||
14152 | plci->command = 0; | ||
14153 | case FAX_EDATA_ACK_COMMAND_1: | ||
14154 | if (plci_nl_busy (plci)) | ||
14155 | { | ||
14156 | plci->internal_command = FAX_EDATA_ACK_COMMAND_1; | ||
14157 | return; | ||
14158 | } | ||
14159 | plci->internal_command = FAX_EDATA_ACK_COMMAND_2; | ||
14160 | plci->NData[0].P = plci->fax_connect_info_buffer; | ||
14161 | plci->NData[0].PLength = plci->fax_edata_ack_length; | ||
14162 | plci->NL.X = plci->NData; | ||
14163 | plci->NL.ReqCh = 0; | ||
14164 | plci->NL.Req = plci->nl_req = (byte) N_EDATA; | ||
14165 | plci->adapter->request (&plci->NL); | ||
14166 | return; | ||
14167 | case FAX_EDATA_ACK_COMMAND_2: | ||
14168 | if ((Rc != OK) && (Rc != OK_FC)) | ||
14169 | { | ||
14170 | dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x", | ||
14171 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
14172 | break; | ||
14173 | } | ||
14174 | } | ||
14175 | } | ||
14176 | |||
14177 | |||
14178 | static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc) | ||
14179 | { | ||
14180 | word Info; | ||
14181 | word internal_command; | ||
14182 | |||
14183 | dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x", | ||
14184 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14185 | |||
14186 | Info = GOOD; | ||
14187 | internal_command = plci->internal_command; | ||
14188 | plci->internal_command = 0; | ||
14189 | switch (internal_command) | ||
14190 | { | ||
14191 | default: | ||
14192 | plci->command = 0; | ||
14193 | case FAX_CONNECT_INFO_COMMAND_1: | ||
14194 | if (plci_nl_busy (plci)) | ||
14195 | { | ||
14196 | plci->internal_command = FAX_CONNECT_INFO_COMMAND_1; | ||
14197 | return; | ||
14198 | } | ||
14199 | plci->internal_command = FAX_CONNECT_INFO_COMMAND_2; | ||
14200 | plci->NData[0].P = plci->fax_connect_info_buffer; | ||
14201 | plci->NData[0].PLength = plci->fax_connect_info_length; | ||
14202 | plci->NL.X = plci->NData; | ||
14203 | plci->NL.ReqCh = 0; | ||
14204 | plci->NL.Req = plci->nl_req = (byte) N_EDATA; | ||
14205 | plci->adapter->request (&plci->NL); | ||
14206 | return; | ||
14207 | case FAX_CONNECT_INFO_COMMAND_2: | ||
14208 | if ((Rc != OK) && (Rc != OK_FC)) | ||
14209 | { | ||
14210 | dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x", | ||
14211 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
14212 | Info = _WRONG_STATE; | ||
14213 | break; | ||
14214 | } | ||
14215 | if (plci_nl_busy (plci)) | ||
14216 | { | ||
14217 | plci->internal_command = FAX_CONNECT_INFO_COMMAND_2; | ||
14218 | return; | ||
14219 | } | ||
14220 | plci->command = _CONNECT_B3_R; | ||
14221 | nl_req_ncci (plci, N_CONNECT, 0); | ||
14222 | send_req (plci); | ||
14223 | return; | ||
14224 | } | ||
14225 | sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info); | ||
14226 | } | ||
14227 | |||
14228 | |||
14229 | static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc) | ||
14230 | { | ||
14231 | word Info; | ||
14232 | word internal_command; | ||
14233 | |||
14234 | dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x", | ||
14235 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14236 | |||
14237 | Info = GOOD; | ||
14238 | internal_command = plci->internal_command; | ||
14239 | plci->internal_command = 0; | ||
14240 | switch (internal_command) | ||
14241 | { | ||
14242 | default: | ||
14243 | plci->command = 0; | ||
14244 | plci->adjust_b_parms_msg = NULL; | ||
14245 | plci->adjust_b_facilities = plci->B1_facilities; | ||
14246 | plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1; | ||
14247 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
14248 | plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23; | ||
14249 | plci->adjust_b_state = ADJUST_B_START; | ||
14250 | dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...", | ||
14251 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14252 | case FAX_ADJUST_B23_COMMAND_1: | ||
14253 | Info = adjust_b_process (Id, plci, Rc); | ||
14254 | if (Info != GOOD) | ||
14255 | { | ||
14256 | dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed", | ||
14257 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14258 | break; | ||
14259 | } | ||
14260 | if (plci->internal_command) | ||
14261 | return; | ||
14262 | case FAX_ADJUST_B23_COMMAND_2: | ||
14263 | if (plci_nl_busy (plci)) | ||
14264 | { | ||
14265 | plci->internal_command = FAX_ADJUST_B23_COMMAND_2; | ||
14266 | return; | ||
14267 | } | ||
14268 | plci->command = _CONNECT_B3_R; | ||
14269 | nl_req_ncci (plci, N_CONNECT, 0); | ||
14270 | send_req (plci); | ||
14271 | return; | ||
14272 | } | ||
14273 | sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info); | ||
14274 | } | ||
14275 | |||
14276 | |||
14277 | static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc) | ||
14278 | { | ||
14279 | word internal_command; | ||
14280 | |||
14281 | dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x", | ||
14282 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14283 | |||
14284 | internal_command = plci->internal_command; | ||
14285 | plci->internal_command = 0; | ||
14286 | switch (internal_command) | ||
14287 | { | ||
14288 | default: | ||
14289 | plci->command = 0; | ||
14290 | plci->internal_command = FAX_DISCONNECT_COMMAND_1; | ||
14291 | return; | ||
14292 | case FAX_DISCONNECT_COMMAND_1: | ||
14293 | case FAX_DISCONNECT_COMMAND_2: | ||
14294 | case FAX_DISCONNECT_COMMAND_3: | ||
14295 | if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0)) | ||
14296 | { | ||
14297 | dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x", | ||
14298 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
14299 | break; | ||
14300 | } | ||
14301 | if (Rc == OK) | ||
14302 | { | ||
14303 | if ((internal_command == FAX_DISCONNECT_COMMAND_1) | ||
14304 | || (internal_command == FAX_DISCONNECT_COMMAND_2)) | ||
14305 | { | ||
14306 | plci->internal_command = FAX_DISCONNECT_COMMAND_2; | ||
14307 | } | ||
14308 | } | ||
14309 | else if (Rc == 0) | ||
14310 | { | ||
14311 | if (internal_command == FAX_DISCONNECT_COMMAND_1) | ||
14312 | plci->internal_command = FAX_DISCONNECT_COMMAND_3; | ||
14313 | } | ||
14314 | return; | ||
14315 | } | ||
14316 | } | ||
14317 | |||
14318 | |||
14319 | |||
14320 | static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc) | ||
14321 | { | ||
14322 | word Info; | ||
14323 | word internal_command; | ||
14324 | |||
14325 | dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x", | ||
14326 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14327 | |||
14328 | Info = GOOD; | ||
14329 | internal_command = plci->internal_command; | ||
14330 | plci->internal_command = 0; | ||
14331 | switch (internal_command) | ||
14332 | { | ||
14333 | default: | ||
14334 | plci->command = 0; | ||
14335 | case RTP_CONNECT_B3_REQ_COMMAND_1: | ||
14336 | if (plci_nl_busy (plci)) | ||
14337 | { | ||
14338 | plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1; | ||
14339 | return; | ||
14340 | } | ||
14341 | plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2; | ||
14342 | nl_req_ncci (plci, N_CONNECT, 0); | ||
14343 | send_req (plci); | ||
14344 | return; | ||
14345 | case RTP_CONNECT_B3_REQ_COMMAND_2: | ||
14346 | if ((Rc != OK) && (Rc != OK_FC)) | ||
14347 | { | ||
14348 | dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x", | ||
14349 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
14350 | Info = _WRONG_STATE; | ||
14351 | break; | ||
14352 | } | ||
14353 | if (plci_nl_busy (plci)) | ||
14354 | { | ||
14355 | plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2; | ||
14356 | return; | ||
14357 | } | ||
14358 | plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3; | ||
14359 | plci->NData[0].PLength = plci->internal_req_buffer[0]; | ||
14360 | plci->NData[0].P = plci->internal_req_buffer + 1; | ||
14361 | plci->NL.X = plci->NData; | ||
14362 | plci->NL.ReqCh = 0; | ||
14363 | plci->NL.Req = plci->nl_req = (byte) N_UDATA; | ||
14364 | plci->adapter->request (&plci->NL); | ||
14365 | break; | ||
14366 | case RTP_CONNECT_B3_REQ_COMMAND_3: | ||
14367 | return; | ||
14368 | } | ||
14369 | sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info); | ||
14370 | } | ||
14371 | |||
14372 | |||
14373 | static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc) | ||
14374 | { | ||
14375 | word Info; | ||
14376 | word internal_command; | ||
14377 | |||
14378 | dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x", | ||
14379 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14380 | |||
14381 | Info = GOOD; | ||
14382 | internal_command = plci->internal_command; | ||
14383 | plci->internal_command = 0; | ||
14384 | switch (internal_command) | ||
14385 | { | ||
14386 | default: | ||
14387 | plci->command = 0; | ||
14388 | case RTP_CONNECT_B3_RES_COMMAND_1: | ||
14389 | if (plci_nl_busy (plci)) | ||
14390 | { | ||
14391 | plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1; | ||
14392 | return; | ||
14393 | } | ||
14394 | plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2; | ||
14395 | nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16)); | ||
14396 | send_req (plci); | ||
14397 | return; | ||
14398 | case RTP_CONNECT_B3_RES_COMMAND_2: | ||
14399 | if ((Rc != OK) && (Rc != OK_FC)) | ||
14400 | { | ||
14401 | dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x", | ||
14402 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc)); | ||
14403 | Info = _WRONG_STATE; | ||
14404 | break; | ||
14405 | } | ||
14406 | if (plci_nl_busy (plci)) | ||
14407 | { | ||
14408 | plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2; | ||
14409 | return; | ||
14410 | } | ||
14411 | sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", ""); | ||
14412 | plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3; | ||
14413 | plci->NData[0].PLength = plci->internal_req_buffer[0]; | ||
14414 | plci->NData[0].P = plci->internal_req_buffer + 1; | ||
14415 | plci->NL.X = plci->NData; | ||
14416 | plci->NL.ReqCh = 0; | ||
14417 | plci->NL.Req = plci->nl_req = (byte) N_UDATA; | ||
14418 | plci->adapter->request (&plci->NL); | ||
14419 | return; | ||
14420 | case RTP_CONNECT_B3_RES_COMMAND_3: | ||
14421 | return; | ||
14422 | } | ||
14423 | } | ||
14424 | |||
14425 | |||
14426 | |||
14427 | static void hold_save_command (dword Id, PLCI *plci, byte Rc) | ||
14428 | { | ||
14429 | byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/ | ||
14430 | word Info; | ||
14431 | word internal_command; | ||
14432 | |||
14433 | dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x", | ||
14434 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14435 | |||
14436 | Info = GOOD; | ||
14437 | internal_command = plci->internal_command; | ||
14438 | plci->internal_command = 0; | ||
14439 | switch (internal_command) | ||
14440 | { | ||
14441 | default: | ||
14442 | if (!plci->NL.Id) | ||
14443 | break; | ||
14444 | plci->command = 0; | ||
14445 | plci->adjust_b_parms_msg = NULL; | ||
14446 | plci->adjust_b_facilities = plci->B1_facilities; | ||
14447 | plci->adjust_b_command = HOLD_SAVE_COMMAND_1; | ||
14448 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
14449 | plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23; | ||
14450 | plci->adjust_b_state = ADJUST_B_START; | ||
14451 | dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...", | ||
14452 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14453 | case HOLD_SAVE_COMMAND_1: | ||
14454 | Info = adjust_b_process (Id, plci, Rc); | ||
14455 | if (Info != GOOD) | ||
14456 | { | ||
14457 | dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed", | ||
14458 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14459 | break; | ||
14460 | } | ||
14461 | if (plci->internal_command) | ||
14462 | return; | ||
14463 | } | ||
14464 | sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind); | ||
14465 | } | ||
14466 | |||
14467 | |||
14468 | static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc) | ||
14469 | { | ||
14470 | byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/ | ||
14471 | word Info; | ||
14472 | word internal_command; | ||
14473 | |||
14474 | dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x", | ||
14475 | UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command)); | ||
14476 | |||
14477 | Info = GOOD; | ||
14478 | internal_command = plci->internal_command; | ||
14479 | plci->internal_command = 0; | ||
14480 | switch (internal_command) | ||
14481 | { | ||
14482 | default: | ||
14483 | plci->command = 0; | ||
14484 | plci->adjust_b_parms_msg = NULL; | ||
14485 | plci->adjust_b_facilities = plci->B1_facilities; | ||
14486 | plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1; | ||
14487 | plci->adjust_b_ncci = (word)(Id >> 16); | ||
14488 | plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE; | ||
14489 | plci->adjust_b_state = ADJUST_B_START; | ||
14490 | dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...", | ||
14491 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14492 | case RETRIEVE_RESTORE_COMMAND_1: | ||
14493 | Info = adjust_b_process (Id, plci, Rc); | ||
14494 | if (Info != GOOD) | ||
14495 | { | ||
14496 | dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed", | ||
14497 | UnMapId (Id), (char *)(FILE_), __LINE__)); | ||
14498 | break; | ||
14499 | } | ||
14500 | if (plci->internal_command) | ||
14501 | return; | ||
14502 | } | ||
14503 | sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind); | ||
14504 | } | ||
14505 | |||
14506 | |||
14507 | static void init_b1_config (PLCI *plci) | ||
14508 | { | ||
14509 | |||
14510 | dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config", | ||
14511 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
14512 | (char *)(FILE_), __LINE__)); | ||
14513 | |||
14514 | plci->B1_resource = 0; | ||
14515 | plci->B1_facilities = 0; | ||
14516 | |||
14517 | plci->li_bchannel_id = 0; | ||
14518 | mixer_clear_config (plci); | ||
14519 | |||
14520 | |||
14521 | ec_clear_config (plci); | ||
14522 | |||
14523 | |||
14524 | dtmf_rec_clear_config (plci); | ||
14525 | dtmf_send_clear_config (plci); | ||
14526 | dtmf_parameter_clear_config (plci); | ||
14527 | |||
14528 | adv_voice_clear_config (plci); | ||
14529 | adjust_b_clear (plci); | ||
14530 | } | ||
14531 | |||
14532 | |||
14533 | static void clear_b1_config (PLCI *plci) | ||
14534 | { | ||
14535 | |||
14536 | dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config", | ||
14537 | (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)), | ||
14538 | (char *)(FILE_), __LINE__)); | ||
14539 | |||
14540 | adv_voice_clear_config (plci); | ||
14541 | adjust_b_clear (plci); | ||
14542 | |||
14543 | ec_clear_config (plci); | ||
14544 | |||
14545 | |||
14546 | dtmf_rec_clear_config (plci); | ||
14547 | dtmf_send_clear_config (plci); | ||
14548 | dtmf_parameter_clear_config (plci); | ||
14549 | |||
14550 | |||
14551 | if ((plci->li_bchannel_id != 0) | ||
14552 | && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci)) | ||
14553 | { | ||
14554 | mixer_clear_config (plci); | ||
14555 | li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL; | ||
14556 | plci->li_bchannel_id = 0; | ||
14557 | } | ||
14558 | |||
14559 | plci->B1_resource = 0; | ||
14560 | plci->B1_facilities = 0; | ||
14561 | } | ||
14562 | |||
14563 | |||
14564 | /* ----------------------------------------------------------------- | ||
14565 | XON protocol local helpers | ||
14566 | ----------------------------------------------------------------- */ | ||
14567 | static void channel_flow_control_remove (PLCI * plci) { | ||
14568 | DIVA_CAPI_ADAPTER * a = plci->adapter; | ||
14569 | word i; | ||
14570 | for(i=1;i<MAX_NL_CHANNEL+1;i++) { | ||
14571 | if (a->ch_flow_plci[i] == plci->Id) { | ||
14572 | a->ch_flow_plci[i] = 0; | ||
14573 | a->ch_flow_control[i] = 0; | ||
14574 | } | ||
14575 | } | ||
14576 | } | ||
14577 | |||
14578 | static void channel_x_on (PLCI * plci, byte ch) { | ||
14579 | DIVA_CAPI_ADAPTER * a = plci->adapter; | ||
14580 | if (a->ch_flow_control[ch] & N_XON_SENT) { | ||
14581 | a->ch_flow_control[ch] &= ~N_XON_SENT; | ||
14582 | } | ||
14583 | } | ||
14584 | |||
14585 | static void channel_x_off (PLCI * plci, byte ch, byte flag) { | ||
14586 | DIVA_CAPI_ADAPTER * a = plci->adapter; | ||
14587 | if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) { | ||
14588 | a->ch_flow_control[ch] |= (N_CH_XOFF | flag); | ||
14589 | a->ch_flow_plci[ch] = plci->Id; | ||
14590 | a->ch_flow_control_pending++; | ||
14591 | } | ||
14592 | } | ||
14593 | |||
14594 | static void channel_request_xon (PLCI * plci, byte ch) { | ||
14595 | DIVA_CAPI_ADAPTER * a = plci->adapter; | ||
14596 | |||
14597 | if (a->ch_flow_control[ch] & N_CH_XOFF) { | ||
14598 | a->ch_flow_control[ch] |= N_XON_REQ; | ||
14599 | a->ch_flow_control[ch] &= ~N_CH_XOFF; | ||
14600 | a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND; | ||
14601 | } | ||
14602 | } | ||
14603 | |||
14604 | static void channel_xmit_extended_xon (PLCI * plci) { | ||
14605 | DIVA_CAPI_ADAPTER * a; | ||
14606 | int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]); | ||
14607 | int i, one_requested = 0; | ||
14608 | |||
14609 | if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) { | ||
14610 | return; | ||
14611 | } | ||
14612 | |||
14613 | for (i = 0; i < max_ch; i++) { | ||
14614 | if ((a->ch_flow_control[i] & N_CH_XOFF) && | ||
14615 | (a->ch_flow_control[i] & N_XON_CONNECT_IND) && | ||
14616 | (plci->Id == a->ch_flow_plci[i])) { | ||
14617 | channel_request_xon (plci, (byte)i); | ||
14618 | one_requested = 1; | ||
14619 | } | ||
14620 | } | ||
14621 | |||
14622 | if (one_requested) { | ||
14623 | channel_xmit_xon (plci); | ||
14624 | } | ||
14625 | } | ||
14626 | |||
14627 | /* | ||
14628 | Try to xmit next X_ON | ||
14629 | */ | ||
14630 | static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) { | ||
14631 | int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]); | ||
14632 | int i; | ||
14633 | |||
14634 | if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) { | ||
14635 | return (0); | ||
14636 | } | ||
14637 | |||
14638 | if (a->last_flow_control_ch >= max_ch) { | ||
14639 | a->last_flow_control_ch = 1; | ||
14640 | } | ||
14641 | for (i=a->last_flow_control_ch; i < max_ch; i++) { | ||
14642 | if ((a->ch_flow_control[i] & N_XON_REQ) && | ||
14643 | (plci->Id == a->ch_flow_plci[i])) { | ||
14644 | a->last_flow_control_ch = i+1; | ||
14645 | return (i); | ||
14646 | } | ||
14647 | } | ||
14648 | |||
14649 | for (i = 1; i < a->last_flow_control_ch; i++) { | ||
14650 | if ((a->ch_flow_control[i] & N_XON_REQ) && | ||
14651 | (plci->Id == a->ch_flow_plci[i])) { | ||
14652 | a->last_flow_control_ch = i+1; | ||
14653 | return (i); | ||
14654 | } | ||
14655 | } | ||
14656 | |||
14657 | return (0); | ||
14658 | } | ||
14659 | |||
14660 | static void channel_xmit_xon (PLCI * plci) { | ||
14661 | DIVA_CAPI_ADAPTER * a = plci->adapter; | ||
14662 | byte ch; | ||
14663 | |||
14664 | if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) { | ||
14665 | return; | ||
14666 | } | ||
14667 | if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) { | ||
14668 | return; | ||
14669 | } | ||
14670 | a->ch_flow_control[ch] &= ~N_XON_REQ; | ||
14671 | a->ch_flow_control[ch] |= N_XON_SENT; | ||
14672 | |||
14673 | plci->NL.Req = plci->nl_req = (byte)N_XON; | ||
14674 | plci->NL.ReqCh = ch; | ||
14675 | plci->NL.X = plci->NData; | ||
14676 | plci->NL.XNum = 1; | ||
14677 | plci->NData[0].P = &plci->RBuffer[0]; | ||
14678 | plci->NData[0].PLength = 0; | ||
14679 | |||
14680 | plci->adapter->request(&plci->NL); | ||
14681 | } | ||
14682 | |||
14683 | static int channel_can_xon (PLCI * plci, byte ch) { | ||
14684 | APPL * APPLptr; | ||
14685 | DIVA_CAPI_ADAPTER * a; | ||
14686 | word NCCIcode; | ||
14687 | dword count; | ||
14688 | word Num; | ||
14689 | word i; | ||
14690 | |||
14691 | APPLptr = plci->appl; | ||
14692 | a = plci->adapter; | ||
14693 | |||
14694 | if (!APPLptr) | ||
14695 | return (0); | ||
14696 | |||
14697 | NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8); | ||
14698 | |||
14699 | /* count all buffers within the Application pool */ | ||
14700 | /* belonging to the same NCCI. XON if a first is */ | ||
14701 | /* used. */ | ||
14702 | count = 0; | ||
14703 | Num = 0xffff; | ||
14704 | for(i=0; i<APPLptr->MaxBuffer; i++) { | ||
14705 | if(NCCIcode==APPLptr->DataNCCI[i]) count++; | ||
14706 | if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i; | ||
14707 | } | ||
14708 | if ((count > 2) || (Num == 0xffff)) { | ||
14709 | return (0); | ||
14710 | } | ||
14711 | return (1); | ||
14712 | } | ||
14713 | |||
14714 | |||
14715 | /*------------------------------------------------------------------*/ | ||
14716 | |||
14717 | static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset) | ||
14718 | { | ||
14719 | return 1; | ||
14720 | } | ||
14721 | |||
14722 | |||
14723 | |||
14724 | /**********************************************************************************/ | ||
14725 | /* function groups the listening applications according to the CIP mask and the */ | ||
14726 | /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */ | ||
14727 | /* are not multi-instance capable, so they start e.g. 30 applications what causes */ | ||
14728 | /* big problems on application level (one call, 30 Connect_Ind, ect). The */ | ||
14729 | /* function must be enabled by setting "a->group_optimization_enabled" from the */ | ||
14730 | /* OS specific part (per adapter). */ | ||
14731 | /**********************************************************************************/ | ||
14732 | static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci) | ||
14733 | { | ||
14734 | word i,j,k,busy,group_found; | ||
14735 | dword info_mask_group[MAX_CIP_TYPES]; | ||
14736 | dword cip_mask_group[MAX_CIP_TYPES]; | ||
14737 | word appl_number_group_type[MAX_APPL]; | ||
14738 | PLCI *auxplci; | ||
14739 | |||
14740 | set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */ | ||
14741 | |||
14742 | if(!a->group_optimization_enabled) | ||
14743 | { | ||
14744 | dbug(1,dprintf("No group optimization")); | ||
14745 | return; | ||
14746 | } | ||
14747 | |||
14748 | dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled)); | ||
14749 | |||
14750 | for(i=0;i<MAX_CIP_TYPES;i++) | ||
14751 | { | ||
14752 | info_mask_group[i] = 0; | ||
14753 | cip_mask_group [i] = 0; | ||
14754 | } | ||
14755 | for(i=0;i<MAX_APPL;i++) | ||
14756 | { | ||
14757 | appl_number_group_type[i] = 0; | ||
14758 | } | ||
14759 | for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */ | ||
14760 | { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */ | ||
14761 | if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) ) | ||
14762 | { | ||
14763 | dbug(1,dprintf("Multi-Instance capable, no optimization required")); | ||
14764 | return; /* allow good application unfiltered access */ | ||
14765 | } | ||
14766 | } | ||
14767 | for(i=0; i<max_appl; i++) /* Build CIP Groups */ | ||
14768 | { | ||
14769 | if(application[i].Id && a->CIP_Mask[i] ) | ||
14770 | { | ||
14771 | for(k=0,busy=FALSE; k<a->max_plci; k++) | ||
14772 | { | ||
14773 | if(a->plci[k].Id) | ||
14774 | { | ||
14775 | auxplci = &a->plci[k]; | ||
14776 | if(auxplci->appl == &application[i]) /* application has a busy PLCI */ | ||
14777 | { | ||
14778 | busy = TRUE; | ||
14779 | dbug(1,dprintf("Appl 0x%x is busy",i+1)); | ||
14780 | } | ||
14781 | else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */ | ||
14782 | { | ||
14783 | busy = TRUE; | ||
14784 | dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1)); | ||
14785 | } | ||
14786 | } | ||
14787 | } | ||
14788 | |||
14789 | for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */ | ||
14790 | { | ||
14791 | if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */ | ||
14792 | { /* the MAX_CIP_TYPES group enables all calls because of field overflow */ | ||
14793 | appl_number_group_type[i] = MAX_CIP_TYPES; | ||
14794 | group_found=TRUE; | ||
14795 | dbug(1,dprintf("Field overflow appl 0x%x",i+1)); | ||
14796 | } | ||
14797 | else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) ) | ||
14798 | { /* is group already present ? */ | ||
14799 | appl_number_group_type[i] = j|0x80; /* store the group number for each application */ | ||
14800 | group_found=TRUE; | ||
14801 | dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j])); | ||
14802 | } | ||
14803 | else if(!info_mask_group[j]) | ||
14804 | { /* establish a new group */ | ||
14805 | appl_number_group_type[i] = j|0x80; /* store the group number for each application */ | ||
14806 | info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */ | ||
14807 | cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */ | ||
14808 | group_found=TRUE; | ||
14809 | dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j])); | ||
14810 | } | ||
14811 | } | ||
14812 | } | ||
14813 | } | ||
14814 | |||
14815 | for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */ | ||
14816 | { | ||
14817 | if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */ | ||
14818 | { | ||
14819 | if(appl_number_group_type[i] == MAX_CIP_TYPES) | ||
14820 | { | ||
14821 | dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1)); | ||
14822 | } | ||
14823 | else | ||
14824 | { | ||
14825 | dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1)); | ||
14826 | for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */ | ||
14827 | { | ||
14828 | if(appl_number_group_type[i] == appl_number_group_type[j]) | ||
14829 | { | ||
14830 | dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j])); | ||
14831 | clear_group_ind_mask_bit (plci, j); /* disable call on other group members */ | ||
14832 | appl_number_group_type[j] = 0; /* remove disabled group member from group list */ | ||
14833 | } | ||
14834 | } | ||
14835 | } | ||
14836 | } | ||
14837 | else /* application should not get a call */ | ||
14838 | { | ||
14839 | clear_group_ind_mask_bit (plci, i); | ||
14840 | } | ||
14841 | } | ||
14842 | |||
14843 | } | ||
14844 | |||
14845 | |||
14846 | |||
14847 | /* OS notifies the driver about a application Capi_Register */ | ||
14848 | word CapiRegister(word id) | ||
14849 | { | ||
14850 | word i,j,appls_found; | ||
14851 | |||
14852 | PLCI *plci; | ||
14853 | DIVA_CAPI_ADAPTER *a; | ||
14854 | |||
14855 | for(i=0,appls_found=0; i<max_appl; i++) | ||
14856 | { | ||
14857 | if( application[i].Id && (application[i].Id!=id) ) | ||
14858 | { | ||
14859 | appls_found++; /* an application has been found */ | ||
14860 | } | ||
14861 | } | ||
14862 | |||
14863 | if(appls_found) return TRUE; | ||
14864 | for(i=0; i<max_adapter; i++) /* scan all adapters... */ | ||
14865 | { | ||
14866 | a = &adapter[i]; | ||
14867 | if(a->request) | ||
14868 | { | ||
14869 | if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */ | ||
14870 | { | ||
14871 | if(!appls_found) /* first application does a capi register */ | ||
14872 | { | ||
14873 | if((j=get_plci(a))) /* activate L1 of all adapters */ | ||
14874 | { | ||
14875 | plci = &a->plci[j-1]; | ||
14876 | plci->command = 0; | ||
14877 | add_p(plci,OAD,"\x01\xfd"); | ||
14878 | add_p(plci,CAI,"\x01\x80"); | ||
14879 | add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); | ||
14880 | add_p(plci,SHIFT|6,NULL); | ||
14881 | add_p(plci,SIN,"\x02\x00\x00"); | ||
14882 | plci->internal_command = START_L1_SIG_ASSIGN_PEND; | ||
14883 | sig_req(plci,ASSIGN,DSIG_ID); | ||
14884 | add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */ | ||
14885 | sig_req(plci,SIG_CTRL,0); | ||
14886 | send_req(plci); | ||
14887 | } | ||
14888 | } | ||
14889 | } | ||
14890 | } | ||
14891 | } | ||
14892 | return FALSE; | ||
14893 | } | ||
14894 | |||
14895 | /*------------------------------------------------------------------*/ | ||
14896 | |||
14897 | /* Functions for virtual Switching e.g. Transfer by join, Conference */ | ||
14898 | |||
14899 | static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms) | ||
14900 | { | ||
14901 | word i; | ||
14902 | /* Format of vswitch_t: | ||
14903 | 0 byte length | ||
14904 | 1 byte VSWITCHIE | ||
14905 | 2 byte VSWITCH_REQ/VSWITCH_IND | ||
14906 | 3 byte reserved | ||
14907 | 4 word VSwitchcommand | ||
14908 | 6 word returnerror | ||
14909 | 8... Params | ||
14910 | */ | ||
14911 | if(!plci || | ||
14912 | !plci->appl || | ||
14913 | !plci->State || | ||
14914 | plci->Sig.Ind==NCR_FACILITY | ||
14915 | ) | ||
14916 | return; | ||
14917 | |||
14918 | for(i=0;i<MAX_MULTI_IE;i++) | ||
14919 | { | ||
14920 | if(!parms[i][0]) continue; | ||
14921 | if(parms[i][0]<7) | ||
14922 | { | ||
14923 | parms[i][0]=0; /* kill it */ | ||
14924 | continue; | ||
14925 | } | ||
14926 | dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4])); | ||
14927 | switch(parms[i][4]) | ||
14928 | { | ||
14929 | case VSJOIN: | ||
14930 | if(!plci->relatedPTYPLCI || | ||
14931 | (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT)) | ||
14932 | { /* Error */ | ||
14933 | break; | ||
14934 | } | ||
14935 | /* remember all necessary informations */ | ||
14936 | if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */ | ||
14937 | { | ||
14938 | break; | ||
14939 | } | ||
14940 | if(parms[i][2]==VSWITCH_IND && parms[i][9]==1) | ||
14941 | { /* first indication after ECT-Request on Consultation Call */ | ||
14942 | plci->vswitchstate=parms[i][9]; | ||
14943 | parms[i][9]=2; /* State */ | ||
14944 | /* now ask first Call to join */ | ||
14945 | } | ||
14946 | else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3) | ||
14947 | { /* Answer of VSWITCH_REQ from first Call */ | ||
14948 | plci->vswitchstate=parms[i][9]; | ||
14949 | /* tell consultation call to join | ||
14950 | and the protocol capabilities of the first call */ | ||
14951 | } | ||
14952 | else | ||
14953 | { /* Error */ | ||
14954 | break; | ||
14955 | } | ||
14956 | plci->vsprot=parms[i][10]; /* protocol */ | ||
14957 | plci->vsprotdialect=parms[i][11]; /* protocoldialect */ | ||
14958 | /* send join request to related PLCI */ | ||
14959 | parms[i][1]=VSWITCHIE; | ||
14960 | parms[i][2]=VSWITCH_REQ; | ||
14961 | |||
14962 | plci->relatedPTYPLCI->command = 0; | ||
14963 | plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND; | ||
14964 | add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]); | ||
14965 | sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0); | ||
14966 | send_req(plci->relatedPTYPLCI); | ||
14967 | break; | ||
14968 | case VSTRANSPORT: | ||
14969 | default: | ||
14970 | if(plci->relatedPTYPLCI && | ||
14971 | plci->vswitchstate==3 && | ||
14972 | plci->relatedPTYPLCI->vswitchstate==3) | ||
14973 | { | ||
14974 | add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]); | ||
14975 | sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0); | ||
14976 | send_req(plci->relatedPTYPLCI); | ||
14977 | } | ||
14978 | break; | ||
14979 | } | ||
14980 | parms[i][0]=0; /* kill it */ | ||
14981 | } | ||
14982 | } | ||
14983 | |||
14984 | |||
14985 | /*------------------------------------------------------------------*/ | ||
14986 | |||
14987 | static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) { | ||
14988 | ENTITY e; | ||
14989 | IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; | ||
14990 | |||
14991 | if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) { | ||
14992 | return (-1); | ||
14993 | } | ||
14994 | |||
14995 | pReq->xdi_dma_descriptor_operation.Req = 0; | ||
14996 | pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; | ||
14997 | |||
14998 | pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC; | ||
14999 | pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1; | ||
15000 | pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; | ||
15001 | pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0; | ||
15002 | |||
15003 | e.user[0] = plci->adapter->Id - 1; | ||
15004 | plci->adapter->request((ENTITY*)pReq); | ||
15005 | |||
15006 | if (!pReq->xdi_dma_descriptor_operation.info.operation && | ||
15007 | (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) && | ||
15008 | pReq->xdi_dma_descriptor_operation.info.descriptor_magic) { | ||
15009 | *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic; | ||
15010 | dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)", | ||
15011 | plci->adapter->Id, | ||
15012 | pReq->xdi_dma_descriptor_operation.info.descriptor_number, | ||
15013 | *dma_magic)); | ||
15014 | return (pReq->xdi_dma_descriptor_operation.info.descriptor_number); | ||
15015 | } else { | ||
15016 | dbug(1,dprintf("dma_alloc failed")); | ||
15017 | return (-1); | ||
15018 | } | ||
15019 | } | ||
15020 | |||
15021 | static void diva_free_dma_descriptor (PLCI *plci, int nr) { | ||
15022 | ENTITY e; | ||
15023 | IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; | ||
15024 | |||
15025 | if (nr < 0) { | ||
15026 | return; | ||
15027 | } | ||
15028 | |||
15029 | pReq->xdi_dma_descriptor_operation.Req = 0; | ||
15030 | pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; | ||
15031 | |||
15032 | pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE; | ||
15033 | pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr; | ||
15034 | pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; | ||
15035 | pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0; | ||
15036 | |||
15037 | e.user[0] = plci->adapter->Id - 1; | ||
15038 | plci->adapter->request((ENTITY*)pReq); | ||
15039 | |||
15040 | if (!pReq->xdi_dma_descriptor_operation.info.operation) { | ||
15041 | dbug(1,dprintf("dma_free(%d)", nr)); | ||
15042 | } else { | ||
15043 | dbug(1,dprintf("dma_free failed (%d)", nr)); | ||
15044 | } | ||
15045 | } | ||
15046 | |||
15047 | /*------------------------------------------------------------------*/ | ||