1 /*
2  * Copyright (c) 2010, Sangoma Technologies
3  * David Yat Sin <davidy@sangoma.com>
4  * Moises Silva <moy@sangoma.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * * Neither the name of the original author; nor the names of any contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
27  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "ftmod_sangoma_isdn.h"
37 
38 void stack_resp_hdr_init(Header *hdr);
39 
40 ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span);
41 ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span);
42 
43 ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span);
44 
45 ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
46 ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
47 
48 
49 extern ftdm_sngisdn_data_t	g_sngisdn_data;
50 
51 ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
52 
53 
sngisdn_stack_start(ftdm_span_t * span)54 ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
55 {
56 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
57 
58 	if (signal_data->dchan) {
59 		if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
60 			ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name);
61 			return FTDM_FAIL;
62 		}
63 		ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name);
64 	}
65 
66 	/* Try to find an alternative for this */
67 	/* LAPD will call LdUiDatBndCfm before it received a LdLiMacBndCfm from L1,
68 	so we need to give some time before activating q931, as q931 will send a
69 	LdUiDatConReq when activated, and this requires the Mac SAP to be already
70 	bound first */
71 	ftdm_sleep(500);
72 
73 	if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) {
74 		g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1;
75 		if (sngisdn_activate_cc(span) != FTDM_SUCCESS) {
76 			ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack CC\n", span->name);
77 			return FTDM_FAIL;
78 		}
79 		ftdm_log(FTDM_LOG_DEBUG, "%s:Stack CC activated\n", span->name);
80 	}
81 
82 	if (sngisdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
83 		ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name);
84 		return FTDM_FAIL;
85 	}
86 	ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q931 activated\n", span->name);
87 
88 	ftdm_log(FTDM_LOG_INFO, "%s:Stack activated\n",span->name);
89 	return FTDM_SUCCESS;
90 }
91 
sngisdn_stack_stop(ftdm_span_t * span)92 ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span)
93 {
94 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
95 	/* Stop L1 first, so we do not receive any more frames */
96 	if (!signal_data->dchan) {
97 		return FTDM_SUCCESS;
98 	}
99 	if (sngisdn_deactivate_phy(span) != FTDM_SUCCESS) {
100 		ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name);
101 		return FTDM_FAIL;
102 	}
103 
104 	if (sngisdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
105 		ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q931\n", span->name);
106 		return FTDM_FAIL;
107 	}
108 
109 	if (sngisdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
110 		ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q921\n", span->name);
111 		return FTDM_FAIL;
112 	}
113 
114 	ftdm_log(FTDM_LOG_INFO, "%s:Signalling stopped\n", span->name);
115 	return FTDM_SUCCESS;
116 }
117 
118 
sngisdn_activate_phy(ftdm_span_t * span)119 ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span)
120 {
121 
122 	/* There is no need to start phy, as it will Q921 will send a activate request to phy when it starts */
123 
124 	return FTDM_SUCCESS;
125 }
126 
sngisdn_deactivate_phy(ftdm_span_t * span)127 ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span)
128 {
129 	L1Mngmt cntrl;
130 	Pst pst;
131 
132 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
133 
134 	/* initalize the post structure */
135 	stack_pst_init(&pst);
136 
137 	/* insert the destination Entity */
138 	pst.dstEnt = ENTL1;
139 
140 	/* initalize the control structure */
141 	memset(&cntrl, 0, sizeof(cntrl));
142 
143 	/* initalize the control header */
144 	stack_hdr_init(&cntrl.hdr);
145 
146 	cntrl.hdr.msgType = TCNTRL;			/* configuration */
147 	cntrl.hdr.entId.ent = ENTL1;		/* entity */
148 	cntrl.hdr.entId.inst = S_INST;		/* instance */
149 	cntrl.hdr.elmId.elmnt = STTSAP;		/* SAP Specific cntrl */
150 
151 	cntrl.t.cntrl.action = AUBND_DIS;
152 	cntrl.t.cntrl.subAction = SAELMNT;
153 
154 	cntrl.t.cntrl.sapId = signal_data->link_id;
155 
156 	if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
157 		return FTDM_FAIL;
158 	}
159 	return FTDM_SUCCESS;
160 }
161 
sngisdn_wake_up_phy(ftdm_span_t * span)162 ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span)
163 {
164 	L1Mngmt cntrl;
165 	Pst pst;
166 
167 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
168 
169 	/* initalize the post structure */
170 	stack_pst_init(&pst);
171 
172 	/* insert the destination Entity */
173 	pst.dstEnt = ENTL1;
174 
175 	/* initalize the control structure */
176 	memset(&cntrl, 0, sizeof(cntrl));
177 
178 	/* initalize the control header */
179 	stack_hdr_init(&cntrl.hdr);
180 
181 	cntrl.hdr.msgType = TCNTRL;			/* configuration */
182 	cntrl.hdr.entId.ent = ENTL1;		/* entity */
183 	cntrl.hdr.entId.inst = S_INST;		/* instance */
184 	cntrl.hdr.elmId.elmnt = STTSAP;		/* SAP Specific cntrl */
185 
186 	cntrl.t.cntrl.action = AENA;
187 	cntrl.t.cntrl.subAction = SAELMNT;
188 
189 	cntrl.t.cntrl.sapId = signal_data->link_id;
190 
191 	if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
192 		return FTDM_FAIL;
193 	}
194 	return FTDM_SUCCESS;
195 }
196 
sngisdn_activate_cc(ftdm_span_t * span)197 ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span)
198 {
199 	CcMngmt cntrl;
200     Pst pst;
201 
202 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
203 
204     /* initalize the post structure */
205    stack_pst_init(&pst);
206 
207     /* insert the destination Entity */
208     pst.dstEnt = ENTCC;
209 
210     /* initalize the control structure */
211 	memset(&cntrl, 0, sizeof(cntrl));
212 
213     /* initalize the control header */
214     stack_hdr_init(&cntrl.hdr);
215 
216 	cntrl.hdr.msgType = TCNTRL;			/* configuration */
217 	cntrl.hdr.entId.ent = ENTCC;		/* entity */
218 	cntrl.hdr.entId.inst = S_INST;		/* instance */
219 	cntrl.hdr.elmId.elmnt = STTSAP;		/* physical sap */
220 
221 	cntrl.t.cntrl.action = ABND_ENA;
222 	cntrl.t.cntrl.subAction = SAELMNT;
223 
224   	cntrl.t.cntrl.sapId = signal_data->cc_id;
225 	if (sng_isdn_cc_cntrl(&pst, &cntrl)) {
226 		return FTDM_FAIL;
227 	}
228 	return FTDM_SUCCESS;
229 }
230 
sngisdn_activate_trace(ftdm_span_t * span,sngisdn_tracetype_t trace_opt)231 ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
232 {
233 	sngisdn_span_data_t *signal_data = sngisdn_dchan((sngisdn_span_data_t*)span->signal_data);
234 
235 	if (!signal_data) {
236 		ftdm_log(FTDM_LOG_ERROR, "%s:Span is not used by signalling module\n", span->name);
237 		return FTDM_FAIL;
238 	}
239 
240 	switch (trace_opt) {
241 		case SNGISDN_TRACE_DISABLE:
242 			if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) {
243 				ftdm_log(FTDM_LOG_INFO, "%s:Disabling q921 trace\n", signal_data->ftdm_span->name);
244 				sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921);
245 
246 				if (sngisdn_cntrl_q921(signal_data->ftdm_span, ADISIMM, SATRC) != FTDM_SUCCESS) {
247 					ftdm_log(FTDM_LOG_INFO, "%s:Failed to disable q921 trace\n", signal_data->ftdm_span->name);
248 				}
249 			}
250 			if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q931)) {
251 				ftdm_log(FTDM_LOG_INFO, "%s:Disabling q921 trace\n", signal_data->ftdm_span->name);
252 				sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931);
253 
254 				if (sngisdn_cntrl_q931(signal_data->ftdm_span, ADISIMM, SATRC) != FTDM_SUCCESS) {
255 					ftdm_log(FTDM_LOG_INFO, "%s:Failed to disable q921 trace\n", signal_data->ftdm_span->name);
256 				}
257 			}
258 			break;
259 		case SNGISDN_TRACE_Q921:
260 			if (!sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) {
261 				ftdm_log(FTDM_LOG_INFO, "%s:Enabling q921 trace\n", signal_data->ftdm_span->name);
262 				sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921);
263 
264 				if (sngisdn_cntrl_q921(signal_data->ftdm_span, AENA, SATRC) != FTDM_SUCCESS) {
265 					ftdm_log(FTDM_LOG_INFO, "%s:Failed to enable q921 trace\n", signal_data->ftdm_span->name);
266 				}
267 			}
268 			break;
269 		case SNGISDN_TRACE_Q931:
270 			if (!sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q931)) {
271 				ftdm_log(FTDM_LOG_INFO, "s%d Enabling q931 trace\n", signal_data->link_id);
272 				sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q931);
273 
274 				if (sngisdn_cntrl_q931(signal_data->ftdm_span, AENA, SATRC) != FTDM_SUCCESS) {
275 					ftdm_log(FTDM_LOG_INFO, "%s:Failed to enable q931 trace\n", signal_data->ftdm_span->name);
276 				}
277 			}
278 			break;
279 	}
280 	return FTDM_SUCCESS;
281 }
282 
283 
sngisdn_cntrl_q931(ftdm_span_t * span,uint8_t action,uint8_t subaction)284 ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction)
285 {
286 	InMngmt cntrl;
287 	Pst pst;
288 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
289 
290 	/* initalize the post structure */
291 	stack_pst_init(&pst);
292 
293 	/* insert the destination Entity */
294 	pst.dstEnt = ENTIN;
295 
296 	/* initalize the control structure */
297 	memset(&cntrl, 0, sizeof(cntrl));
298 
299 	/* initalize the control header */
300 	stack_hdr_init(&cntrl.hdr);
301 
302 	cntrl.hdr.msgType = TCNTRL;			/* configuration */
303 	cntrl.hdr.entId.ent = ENTIN;		/* entity */
304 	cntrl.hdr.entId.inst = S_INST;		/* instance */
305 	cntrl.hdr.elmId.elmnt = STDLSAP;	/* physical sap */
306 
307 	cntrl.t.cntrl.action = action;
308 	cntrl.t.cntrl.subAction = subaction;
309 
310 	if (action == AENA && subaction == SATRC) {
311 		cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */
312 	}
313 
314 	cntrl.t.cntrl.sapId = signal_data->link_id;
315 	cntrl.t.cntrl.ces = 0;
316 
317 	if(sng_isdn_q931_cntrl(&pst, &cntrl)) {
318 		return FTDM_FAIL;
319 	}
320 	return FTDM_SUCCESS;
321 
322 }
323 
sngisdn_cntrl_q921(ftdm_span_t * span,uint8_t action,uint8_t subaction)324 ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction)
325 {
326 	BdMngmt cntrl;
327 	Pst pst;
328 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
329 
330 	/* initalize the post structure */
331 	stack_pst_init(&pst);
332 
333 	/* insert the destination Entity */
334 	pst.dstEnt = ENTLD;
335 
336 	/* initalize the control structure */
337 	memset(&cntrl, 0, sizeof(cntrl));
338 
339 	/* initalize the control header */
340 	stack_hdr_init(&cntrl.hdr);
341 	/* build control request */
342 	cntrl.hdr.msgType          = TCNTRL;
343 	cntrl.hdr.entId.ent        = ENTLD;
344 	cntrl.hdr.entId.inst       = S_INST;
345 
346 #if (SMBD_LMINT3 || BD_LMINT3)
347 	stack_resp_hdr_init(&cntrl.hdr);
348 #endif /* _LMINT3 */
349 
350 	cntrl.hdr.elmId.elmnt      = STMSAP;
351 	cntrl.t.cntrl.action       = action;
352 	cntrl.t.cntrl.subAction    = subaction;
353 
354 #if (SMBD_LMINT3 || BD_LMINT3)
355 	cntrl.t.cntrl.lnkNmb       = signal_data->link_id;
356 	cntrl.t.cntrl.sapi         = NOTUSED;
357 	cntrl.t.cntrl.tei          = NOTUSED;
358 #else /* _LMINT3 */
359 	cntrl.hdr.elmId.elmntInst1 = signal_data->link_id;
360 	cntrl.hdr.elmId.elmntInst2 = NOTUSED;
361 	cntrl.hdr.elmId.elmntInst3 = NOTUSED;
362 #endif /* _LMINT3 */
363 
364 	cntrl.t.cntrl.logInt       = NOTUSED;
365 	cntrl.t.cntrl.trcLen       = NOTUSED;
366 	if (action == AENA && subaction == SATRC) {
367 		cntrl.t.cntrl.trcLen = -1; /* Trace the entire message buffer */
368 	}
369 
370 	SGetDateTime(&(cntrl.t.cntrl.dt));
371 	if(sng_isdn_q921_cntrl(&pst, &cntrl)) {
372 		return FTDM_FAIL;
373 	}
374 
375 	return FTDM_SUCCESS;
376 }
377 
378 
stack_resp_hdr_init(Header * hdr)379 void stack_resp_hdr_init(Header *hdr)
380 {
381 	hdr->response.selector   = 0;
382 	hdr->response.mem.region = RTESPEC;
383 	hdr->response.mem.pool   = S_POOL;
384 	hdr->response.prior      = PRIOR0;
385 	hdr->response.route      = RTESPEC;
386 
387 	return;
388 }
389 
390 
391 
392 /* For Emacs:
393  * Local Variables:
394  * mode:c
395  * indent-tabs-mode:t
396  * tab-width:4
397  * c-basic-offset:4
398  * End:
399  * For VIM:
400  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
401  */
402 
403 /******************************************************************************/
404