This source file includes following definitions.
- ftdm_sangoma_isdn_process_phy_events
- ftdm_sangoma_isdn_poll_events
- ftdm_sangoma_isdn_dchan_set_queue_size
- ftdm_sangoma_isdn_wakeup_phy
- ftdm_sangoma_isdn_dchan_run
- ftdm_sangoma_isdn_run
- ftdm_sangoma_isdn_process_event_states
- ftdm_sangoma_isdn_process_stack_event
- ftdm_sangoma_isdn_process_state_change
- FIO_CHANNEL_SEND_MSG_FUNCTION
- FIO_CHANNEL_OUTGOING_CALL_FUNCTION
- FIO_CHANNEL_GET_SIG_STATUS_FUNCTION
- FIO_CHANNEL_SET_SIG_STATUS_FUNCTION
- FIO_SPAN_GET_SIG_STATUS_FUNCTION
- FIO_SPAN_SET_SIG_STATUS_FUNCTION
- ftdm_sangoma_isdn_start
- ftdm_sangoma_isdn_stop
- FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- FIO_SIG_UNLOAD_FUNCTION
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include "ftmod_sangoma_isdn.h"
38
39 #ifdef FTDM_DEBUG_CHAN_MEMORY
40 #include <sys/mman.h>
41 #endif
42
43
44 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
45 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span);
46 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
47
48 ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
49 static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
50 static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event);
51 static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
52 static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
53 static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan);
54 static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *ftdmchan);
55
56 static ftdm_io_interface_t g_sngisdn_io_interface;
57 static sng_isdn_event_interface_t g_sngisdn_event_interface;
58
59 ftdm_sngisdn_data_t g_sngisdn_data;
60
61 ftdm_state_map_t sangoma_isdn_state_map = {
62 {
63 {
64 ZSD_INBOUND,
65 ZSM_UNACCEPTABLE,
66 {FTDM_ANY_STATE, FTDM_END},
67 {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_END}
68 },
69 {
70 ZSD_INBOUND,
71 ZSM_UNACCEPTABLE,
72 {FTDM_CHANNEL_STATE_RESET, FTDM_END},
73 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
74 },
75 {
76 ZSD_INBOUND,
77 ZSM_UNACCEPTABLE,
78 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
79 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
80 },
81 {
82 ZSD_INBOUND,
83 ZSM_UNACCEPTABLE,
84 {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
85 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
86 },
87 {
88 ZSD_INBOUND,
89 ZSM_UNACCEPTABLE,
90 {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
91 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING,
92 FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
93 FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
94 },
95 {
96 ZSD_INBOUND,
97 ZSM_UNACCEPTABLE,
98 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
99 {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
100 },
101 {
102 ZSD_INBOUND,
103 ZSM_UNACCEPTABLE,
104 {FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_END},
105 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
106 },
107 {
108 ZSD_INBOUND,
109 ZSM_UNACCEPTABLE,
110 {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
111 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
112 },
113 {
114 ZSD_INBOUND,
115 ZSM_UNACCEPTABLE,
116 {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
117 {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
118 },
119 {
120 ZSD_INBOUND,
121 ZSM_UNACCEPTABLE,
122 {FTDM_CHANNEL_STATE_RING, FTDM_END},
123 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
124 },
125 {
126 ZSD_INBOUND,
127 ZSM_UNACCEPTABLE,
128 {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
129 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
130 FTDM_CHANNEL_STATE_UP, FTDM_END}
131 },
132 {
133 ZSD_INBOUND,
134 ZSM_UNACCEPTABLE,
135 {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
136 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
137 },
138 {
139 ZSD_INBOUND,
140 ZSM_UNACCEPTABLE,
141 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
142 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
143 },
144 {
145 ZSD_INBOUND,
146 ZSM_UNACCEPTABLE,
147 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
148 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END},
149 },
150 {
151 ZSD_INBOUND,
152 ZSM_UNACCEPTABLE,
153 {FTDM_CHANNEL_STATE_UP, FTDM_END},
154 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
155 },
156 {
157 ZSD_INBOUND,
158 ZSM_UNACCEPTABLE,
159 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
160 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
161 },
162 {
163 ZSD_INBOUND,
164 ZSM_UNACCEPTABLE,
165 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
166 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
167 },
168 {
169 ZSD_INBOUND,
170 ZSM_UNACCEPTABLE,
171 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
172 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
173 },
174 {
175 ZSD_OUTBOUND,
176 ZSM_UNACCEPTABLE,
177 {FTDM_ANY_STATE, FTDM_END},
178 {FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
179 },
180 {
181 ZSD_OUTBOUND,
182 ZSM_UNACCEPTABLE,
183 {FTDM_CHANNEL_STATE_RESET, FTDM_END},
184 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
185 },
186 {
187 ZSD_OUTBOUND,
188 ZSM_UNACCEPTABLE,
189 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
190 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
191 },
192 {
193 ZSD_OUTBOUND,
194 ZSM_UNACCEPTABLE,
195 {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
196 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
197 },
198 {
199 ZSD_OUTBOUND,
200 ZSM_UNACCEPTABLE,
201 {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
202 {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING,
203 FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
204 FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
205 },
206 {
207 ZSD_OUTBOUND,
208 ZSM_UNACCEPTABLE,
209 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
210 {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
211 },
212 {
213 ZSD_OUTBOUND,
214 ZSM_UNACCEPTABLE,
215 {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
216 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
217 FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
218 FTDM_CHANNEL_STATE_DOWN, FTDM_END}
219 },
220 {
221 ZSD_OUTBOUND,
222 ZSM_UNACCEPTABLE,
223 {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
224 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
225 FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
226 },
227 {
228 ZSD_OUTBOUND,
229 ZSM_UNACCEPTABLE,
230 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
231 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
232 },
233 {
234 ZSD_OUTBOUND,
235 ZSM_UNACCEPTABLE,
236 {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
237 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
238 },
239 {
240 ZSD_OUTBOUND,
241 ZSM_UNACCEPTABLE,
242 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
243 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END},
244 },
245 {
246 ZSD_OUTBOUND,
247 ZSM_UNACCEPTABLE,
248 {FTDM_CHANNEL_STATE_UP, FTDM_END},
249 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
250 },
251 {
252 ZSD_OUTBOUND,
253 ZSM_UNACCEPTABLE,
254 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
255 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
256 },
257 {
258 ZSD_OUTBOUND,
259 ZSM_UNACCEPTABLE,
260 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
261 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
262 },
263 {
264 ZSD_OUTBOUND,
265 ZSM_UNACCEPTABLE,
266 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
267 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
268 }
269 }
270 };
271
272 static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event)
273 {
274 sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
275 sngisdn_snd_event(signal_data->dchan, event);
276
277 switch (event) {
278
279 case FTDM_OOB_ALARM_CLEAR:
280 if (FTDM_SPAN_IS_BRI(span)) {
281 ftdm_channel_t *ftdmchan;
282 sngisdn_chan_data_t *sngisdn_info;
283 ftdm_iterator_t *chaniter = NULL;
284 ftdm_iterator_t *curr = NULL;
285
286 chaniter = ftdm_span_get_chan_iterator(span, NULL);
287 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
288 ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
289 sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
290
291 if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
292 ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
293
294 ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL);
295 }
296 }
297 ftdm_iterator_free(chaniter);
298 }
299 break;
300 default:
301
302 break;
303 }
304 }
305
306 static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
307 {
308 ftdm_status_t ret_status;
309
310 ret_status = ftdm_span_poll_event(span, 0, NULL);
311 switch(ret_status) {
312 case FTDM_SUCCESS:
313 {
314 ftdm_event_t *event;
315 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
316 ftdm_sangoma_isdn_process_phy_events(span, event->enum_id);
317 }
318 }
319 break;
320 case FTDM_TIMEOUT:
321
322 break;
323 default:
324 ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
325 }
326 }
327
328 static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan)
329 {
330 ftdm_status_t ret_status;
331 uint32_t queue_size;
332
333 queue_size = SNGISDN_DCHAN_QUEUE_LEN;
334 ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &queue_size);
335 ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Rx Queue size");
336
337 queue_size = SNGISDN_DCHAN_QUEUE_LEN;
338 ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &queue_size);
339 ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Tx Queue size");
340
341 RETVOID;
342 }
343
344 static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan)
345 {
346 ftdm_status_t ret_status;
347 ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
348 ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
349 if (ret_status != FTDM_SUCCESS) {
350 ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to wake-up link\n");
351 }
352 return;
353 }
354
355 static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
356 {
357 uint8_t data[1000];
358 ftdm_status_t status = FTDM_SUCCESS;
359 ftdm_wait_flag_t wflags = FTDM_READ;
360 ftdm_span_t *span = (ftdm_span_t*) obj;
361 ftdm_channel_t *dchan = ((sngisdn_span_data_t*)span->signal_data)->dchan;
362 ftdm_size_t len = 0;
363
364 ftdm_channel_set_feature(dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
365 ftdm_sangoma_isdn_dchan_set_queue_size(dchan);
366
367 ftdm_assert(dchan, "Span does not have a dchannel");
368 ftdm_channel_open_chan(dchan);
369
370 while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
371 wflags = FTDM_READ;
372 status = ftdm_channel_wait(dchan, &wflags, 10000);
373 switch(status) {
374 case FTDM_FAIL:
375 ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to wait for d-channel\n");
376 break;
377 case FTDM_TIMEOUT:
378 break;
379 case FTDM_SUCCESS:
380 if ((wflags & FTDM_READ)) {
381 len = 1000;
382 status = ftdm_channel_read(dchan, data, &len);
383 if (status == FTDM_SUCCESS) {
384 sngisdn_snd_data(dchan, data, len);
385 } else {
386 ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n");
387 }
388 #ifndef WIN32
389 } else {
390 ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to poll for d-channel\n");
391 #endif
392 }
393 break;
394 default:
395 ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Unhandled IO event\n");
396 }
397 }
398 ftdm_channel_close(&dchan);
399 return NULL;
400 }
401
402 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
403 {
404 ftdm_interrupt_t *ftdm_sangoma_isdn_int[3];
405 ftdm_status_t ret_status;
406 ftdm_span_t *span = (ftdm_span_t *) obj;
407 ftdm_channel_t *ftdmchan = NULL;
408 sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
409 sngisdn_event_data_t *sngisdn_event = NULL;
410 int32_t sleep = SNGISDN_EVENT_POLL_RATE;
411
412 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span=%u started.\n", span->span_id);
413
414
415 ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
416
417
418 if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) {
419 ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
420 goto ftdm_sangoma_isdn_run_exit;
421 }
422
423 if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
424 ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a signal interrupt for span = %s!\n", span->name);
425 goto ftdm_sangoma_isdn_run_exit;
426 }
427
428 if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) {
429 ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
430 goto ftdm_sangoma_isdn_run_exit;
431 }
432
433 while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
434
435
436 ftdm_sched_run(signal_data->sched);
437 ftdm_span_trigger_signals(span);
438
439 if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
440 if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
441 sleep = SNGISDN_EVENT_POLL_RATE;
442 }
443 }
444 ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 3, sleep);
445
446 switch (ret_status) {
447 case FTDM_SUCCESS:
448
449 while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
450
451 ftdm_channel_lock(ftdmchan);
452 ftdm_channel_advance_states(ftdmchan);
453 ftdm_channel_unlock(ftdmchan);
454 }
455
456 while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) {
457 ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event);
458 ftdm_safe_free(sngisdn_event);
459 }
460 break;
461 case FTDM_TIMEOUT:
462
463 break;
464 case FTDM_FAIL:
465 ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned error!\n", span->name);
466 break;
467
468 default:
469 ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned with unknown code\n", span->name);
470 break;
471 }
472
473
474 ftdm_sangoma_isdn_poll_events(span);
475 }
476
477
478 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
479
480 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping.\n", span->name);
481
482 return NULL;
483
484 ftdm_sangoma_isdn_run_exit:
485
486
487 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
488
489 ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span %s stopping due to error.\n", span->name);
490
491 return NULL;
492 }
493
494
495
496
497
498
499
500
501
502 ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
503 {
504 ftdm_channel_t *ftdmchan = NULL;
505 switch (sngisdn_event->event_id) {
506
507 case SNGISDN_EVENT_SRV_IND:
508 case SNGISDN_EVENT_SRV_CFM:
509 case SNGISDN_EVENT_RST_CFM:
510 case SNGISDN_EVENT_RST_IND:
511 return NULL;
512 break;
513 case SNGISDN_EVENT_CON_IND:
514 case SNGISDN_EVENT_CON_CFM:
515 case SNGISDN_EVENT_CNST_IND:
516 case SNGISDN_EVENT_DISC_IND:
517 case SNGISDN_EVENT_REL_IND:
518 case SNGISDN_EVENT_DAT_IND:
519 case SNGISDN_EVENT_SSHL_IND:
520 case SNGISDN_EVENT_SSHL_CFM:
521 case SNGISDN_EVENT_RMRT_IND:
522 case SNGISDN_EVENT_RMRT_CFM:
523 case SNGISDN_EVENT_FLC_IND:
524 case SNGISDN_EVENT_FAC_IND:
525 case SNGISDN_EVENT_STA_CFM:
526 ftdmchan = sngisdn_event->sngisdn_info->ftdmchan;
527 ftdm_assert_return(ftdmchan, NULL,"Event should have a channel associated\n");
528 break;
529 }
530 ftdm_channel_lock(ftdmchan);
531 ftdm_channel_advance_states(ftdmchan);
532 return ftdmchan;
533 }
534
535
536
537 static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
538 {
539 ftdm_channel_t *ftdmchan = NULL;
540
541 ftdmchan = ftdm_sangoma_isdn_process_event_states(span, sngisdn_event);
542 switch(sngisdn_event->event_id) {
543 case SNGISDN_EVENT_CON_IND:
544 sngisdn_process_con_ind(sngisdn_event);
545 break;
546 case SNGISDN_EVENT_CON_CFM:
547 sngisdn_process_con_cfm(sngisdn_event);
548 break;
549 case SNGISDN_EVENT_CNST_IND:
550 sngisdn_process_cnst_ind(sngisdn_event);
551 break;
552 case SNGISDN_EVENT_DISC_IND:
553 sngisdn_process_disc_ind(sngisdn_event);
554 break;
555 case SNGISDN_EVENT_REL_IND:
556 sngisdn_process_rel_ind(sngisdn_event);
557 break;
558 case SNGISDN_EVENT_DAT_IND:
559 sngisdn_process_dat_ind(sngisdn_event);
560 break;
561 case SNGISDN_EVENT_SSHL_IND:
562 sngisdn_process_sshl_ind(sngisdn_event);
563 break;
564 case SNGISDN_EVENT_SSHL_CFM:
565 sngisdn_process_sshl_cfm(sngisdn_event);
566 break;
567 case SNGISDN_EVENT_RMRT_IND:
568 sngisdn_process_rmrt_ind(sngisdn_event);
569 break;
570 case SNGISDN_EVENT_RMRT_CFM:
571 sngisdn_process_rmrt_cfm(sngisdn_event);
572 break;
573 case SNGISDN_EVENT_FLC_IND:
574 sngisdn_process_flc_ind(sngisdn_event);
575 break;
576 case SNGISDN_EVENT_FAC_IND:
577 sngisdn_process_fac_ind(sngisdn_event);
578 break;
579 case SNGISDN_EVENT_STA_CFM:
580 sngisdn_process_sta_cfm(sngisdn_event);
581 break;
582 case SNGISDN_EVENT_SRV_IND:
583 sngisdn_process_srv_ind(sngisdn_event);
584 break;
585 case SNGISDN_EVENT_SRV_CFM:
586 sngisdn_process_srv_cfm(sngisdn_event);
587 break;
588 case SNGISDN_EVENT_RST_CFM:
589 sngisdn_process_rst_cfm(sngisdn_event);
590 break;
591 case SNGISDN_EVENT_RST_IND:
592 sngisdn_process_rst_ind(sngisdn_event);
593 break;
594 }
595 if (ftdmchan != NULL) {
596 ftdm_channel_advance_states(ftdmchan);
597 ftdm_channel_unlock(ftdmchan);
598 }
599 }
600
601
602 static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
603 {
604 ftdm_sigmsg_t sigev;
605 ftdm_channel_state_t initial_state;
606 sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
607
608 memset(&sigev, 0, sizeof(sigev));
609
610 sigev.chan_id = ftdmchan->chan_id;
611 sigev.span_id = ftdmchan->span_id;
612 sigev.channel = ftdmchan;
613
614
615 ftdm_channel_complete_state(ftdmchan);
616
617 #ifdef FTDM_DEBUG_CHAN_MEMORY
618 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
619 ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ) == 0, "Failed to mprotect");
620 }
621 #endif
622
623
624 initial_state = ftdmchan->state;
625
626 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state change to %s\n", ftdm_channel_state2str(ftdmchan->state));
627
628 switch (ftdmchan->state) {
629 case FTDM_CHANNEL_STATE_COLLECT:
630 {
631
632 sngisdn_snd_setup_ack(ftdmchan);
633
634 }
635 break;
636 case FTDM_CHANNEL_STATE_GET_CALLERID:
637 {
638 if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
639
640 ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
641
642 sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
643 sngisdn_snd_proceed(ftdmchan, prog_ind);
644 }
645
646 }
647 break;
648 case FTDM_CHANNEL_STATE_RING:
649 {
650 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits);
651
652
653 sigev.event_id = FTDM_SIGEVENT_START;
654 ftdm_span_send_signal(ftdmchan->span, &sigev);
655 }
656 break;
657 case FTDM_CHANNEL_STATE_DIALING:
658 {
659 if (FTDM_SPAN_IS_BRI(ftdmchan->span) &&
660 ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) &&
661 ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
662
663 sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
664
665 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n");
666 sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
667 ftdm_sangoma_isdn_wakeup_phy(ftdmchan);
668 ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL);
669 } else {
670 sngisdn_snd_setup(ftdmchan);
671 }
672 }
673 break;
674 case FTDM_CHANNEL_STATE_PROCEED:
675 {
676 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
677
678 sigev.event_id = FTDM_SIGEVENT_PROCEED;
679 ftdm_span_send_signal(ftdmchan->span, &sigev);
680 } else {
681 if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
682
683 ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
684
685 sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
686 sngisdn_snd_proceed(ftdmchan, prog_ind);
687 }
688 }
689 }
690 break;
691 case FTDM_CHANNEL_STATE_RINGING:
692 {
693 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
694
695 sigev.event_id = FTDM_SIGEVENT_RINGING;
696 ftdm_span_send_signal(ftdmchan->span, &sigev);
697 if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
698 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
699 }
700 } else {
701 ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
702 sngisdn_snd_alert(ftdmchan, prog_ind);
703 }
704 }
705 break;
706 case FTDM_CHANNEL_STATE_PROGRESS:
707 {
708
709 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
710
711 sigev.event_id = FTDM_SIGEVENT_PROGRESS;
712 ftdm_span_send_signal(ftdmchan->span, &sigev);
713 } else {
714
715 ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
716 sngisdn_snd_progress(ftdmchan, prog_ind);
717 }
718 }
719 break;
720 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
721 {
722 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
723 sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
724 ftdm_span_send_signal(ftdmchan->span, &sigev);
725 } else {
726
727 ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL};
728 sngisdn_snd_progress(ftdmchan, prog_ind);
729 }
730 }
731 break;
732 case FTDM_CHANNEL_STATE_UP:
733 {
734
735 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
736
737 sigev.event_id = FTDM_SIGEVENT_UP;
738 ftdm_span_send_signal(ftdmchan->span, &sigev);
739
740 if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
741 ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
742
743 sngisdn_snd_con_complete(ftdmchan);
744 }
745 } else {
746
747 sngisdn_snd_connect(ftdmchan);
748 }
749 }
750 break;
751 case FTDM_CHANNEL_STATE_CANCEL:
752 {
753 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call before informing user!\n");
754
755
756 sngisdn_snd_release(ftdmchan, 0);
757
758 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
759 }
760 break;
761 case FTDM_CHANNEL_STATE_TERMINATING:
762 {
763
764 sigev.event_id = FTDM_SIGEVENT_STOP;
765 ftdm_span_send_signal(ftdmchan->span, &sigev);
766 }
767 break;
768 case FTDM_CHANNEL_STATE_HANGUP:
769 {
770 if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) {
771 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote abort\n");
772 } else if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_REL)) {
773 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote hangup\n");
774 sngisdn_snd_release(ftdmchan, 0);
775 } else if (sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
776
777 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from local abort\n");
778 } else if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
779
780
781 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n");
782 } else if (sngisdn_test_flag(sngisdn_info, FLAG_SEND_DISC)) {
783
784 sngisdn_snd_disconnect(ftdmchan);
785 } else {
786 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n");
787
788
789 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
790
791 switch(ftdmchan->last_state) {
792 case FTDM_CHANNEL_STATE_RING:
793
794 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
795 sngisdn_snd_release(ftdmchan, 0);
796 break;
797 case FTDM_CHANNEL_STATE_DIALING:
798
799 sngisdn_snd_release(ftdmchan, 0);
800 break;
801 default:
802 sngisdn_snd_disconnect(ftdmchan);
803 break;
804 }
805 }
806
807 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
808 }
809 break;
810 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
811 {
812 if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) ||
813 sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
814
815 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
816 } else {
817
818 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for release from stack\n");
819 }
820 }
821 break;
822 case FTDM_CHANNEL_STATE_DOWN:
823 {
824 uint8_t glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
825
826 clear_call_data(sngisdn_info);
827
828
829
830 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
831 ftdm_channel_t *close_chan = ftdmchan;
832
833 ftdm_channel_close(&close_chan);
834 }
835 if (glare) {
836
837 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n");
838
839
840
841
842 sngisdn_rcv_con_ind(sngisdn_info->glare.suId, sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, &sngisdn_info->glare.setup, sngisdn_info->glare.dChan, sngisdn_info->glare.ces);
843 }
844 }
845 break;
846 case FTDM_CHANNEL_STATE_RESTART:
847 {
848
849 }
850
851 break;
852 case FTDM_CHANNEL_STATE_SUSPENDED:
853 {
854
855 }
856 break;
857 case FTDM_CHANNEL_STATE_RESET:
858 {
859 sngisdn_snd_restart(ftdmchan);
860 }
861 break;
862 default:
863 {
864 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
865 }
866 break;
867 }
868
869 if (ftdmchan->state == initial_state) {
870 ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n");
871 }
872 #ifdef FTDM_DEBUG_CHAN_MEMORY
873 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
874 ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ|PROT_WRITE) == 0, "Failed to mprotect");
875 }
876 #endif
877 return FTDM_SUCCESS;
878 }
879
880 static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
881 {
882 ftdm_status_t status = FTDM_FAIL;
883
884 switch (sigmsg->event_id) {
885 case FTDM_SIGEVENT_FACILITY:
886 sngisdn_snd_fac_req(ftdmchan);
887 status = FTDM_SUCCESS;
888 break;
889 default:
890 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
891 status = FTDM_BREAK;
892 }
893 ftdm_call_clear_data(&ftdmchan->caller_data);
894 return status;
895 }
896
897 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
898 {
899 sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
900 ftdm_status_t status = FTDM_FAIL;
901
902
903 ftdm_channel_lock(ftdmchan);
904
905 switch (ftdmchan->state) {
906
907 case FTDM_CHANNEL_STATE_DOWN:
908 {
909 if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
910
911 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n");
912
913 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
914 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
915
916 status = FTDM_BREAK;
917 } else {
918 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
919 status = FTDM_SUCCESS;
920 }
921 }
922 break;
923 default:
924 {
925
926 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use\n");
927 status = FTDM_BREAK;
928 }
929 break;
930 }
931
932 ftdm_channel_unlock(ftdmchan);
933 return status;
934 }
935 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status)
936 {
937 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
938 *status = FTDM_SIG_STATE_UP;
939 } else {
940 *status = FTDM_SIG_STATE_DOWN;
941 }
942
943 return FTDM_SUCCESS;
944 }
945
946 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_chan_sig_status)
947 {
948 ftdm_log(FTDM_LOG_ERROR,"Cannot set channel status in this module\n");
949 return FTDM_NOTIMPL;
950 }
951
952 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_span_sig_status)
953 {
954 if (ftdm_test_flag(span->channels[1], FTDM_CHANNEL_SIG_UP)) {
955 *status = FTDM_SIG_STATE_UP;
956 } else {
957 *status = FTDM_SIG_STATE_DOWN;
958 }
959
960 return FTDM_SUCCESS;
961 }
962
963 static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
964 {
965 ftdm_log(FTDM_LOG_ERROR,"Cannot set span status in this module\n");
966 return FTDM_NOTIMPL;
967 }
968
969 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
970 {
971 sngisdn_span_data_t *signal_data = span->signal_data;
972 ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
973 if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
974 ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
975 return FTDM_FAIL;
976 }
977
978 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
979 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
980
981 if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
982 sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
983 }
984
985 if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
986 sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
987 }
988
989
990 if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
991 ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
992 return FTDM_FAIL;
993 }
994
995
996 if (ftdm_thread_create_detached(ftdm_sangoma_isdn_dchan_run, span) != FTDM_SUCCESS) {
997 ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN d-channel Monitor Thread!\n");
998 return FTDM_FAIL;
999 }
1000
1001 ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
1002 return FTDM_SUCCESS;
1003 }
1004
1005 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
1006 {
1007 ftdm_iterator_t *chaniter = NULL;
1008 ftdm_iterator_t *curr = NULL;
1009 unsigned i;
1010 sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
1011 ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name);
1012
1013
1014 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
1015
1016
1017 while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
1018 ftdm_log(FTDM_LOG_DEBUG, "Waiting for monitor thread to end for span %s\n", span->name);
1019 ftdm_sleep(10);
1020 }
1021
1022 if (sngisdn_stack_stop(span) != FTDM_SUCCESS) {
1023 ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name);
1024 }
1025
1026 chaniter = ftdm_span_get_chan_iterator(span, NULL);
1027 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
1028 ftdm_safe_free(((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data);
1029 ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = NULL;
1030 }
1031 ftdm_iterator_free(chaniter);
1032
1033 ftdm_sched_destroy(&signal_data->sched);
1034 ftdm_queue_destroy(&signal_data->event_queue);
1035 for (i = 0 ; i < signal_data->num_local_numbers ; i++) {
1036 if (signal_data->local_numbers[i] != NULL) {
1037 ftdm_safe_free(signal_data->local_numbers[i]);
1038 }
1039 }
1040 ftdm_safe_free(span->signal_data);
1041
1042 ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);
1043
1044 return FTDM_SUCCESS;
1045 }
1046
1047 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
1048 {
1049 ftdm_iterator_t *chaniter = NULL;
1050 ftdm_iterator_t *curr = NULL;
1051
1052 sngisdn_span_data_t *span_data;
1053
1054 ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_isdn span = %s\n", span->name);
1055
1056 span_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t));
1057 span_data->ftdm_span = span;
1058 span->signal_data = span_data;
1059
1060 chaniter = ftdm_span_get_chan_iterator(span, NULL);
1061 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
1062 sngisdn_chan_data_t *chan_data = ftdm_calloc(1, sizeof(sngisdn_chan_data_t));
1063 chan_data->ftdmchan = ((ftdm_channel_t*)ftdm_iterator_current(curr));
1064 ((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = chan_data;
1065
1066 }
1067 ftdm_iterator_free(chaniter);
1068
1069 if (ftmod_isdn_parse_cfg(ftdm_parameters, span) != FTDM_SUCCESS) {
1070 ftdm_log(FTDM_LOG_ERROR, "Failed to parse configuration\n");
1071 return FTDM_FAIL;
1072 }
1073
1074 if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) {
1075 ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n");
1076 return FTDM_FAIL;
1077 }
1078
1079
1080 span->start = ftdm_sangoma_isdn_start;
1081 span->stop = ftdm_sangoma_isdn_stop;
1082 span->signal_type = FTDM_SIGTYPE_ISDN;
1083 span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
1084 span->send_msg = ftdm_sangoma_isdn_send_msg;
1085 span->channel_request = NULL;
1086 span->signal_cb = sig_cb;
1087 span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
1088 span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status;
1089 span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status;
1090 span->set_span_sig_status = ftdm_sangoma_isdn_set_span_sig_status;
1091 span->state_map = &sangoma_isdn_state_map;
1092 span->state_processor = ftdm_sangoma_isdn_process_state_change;
1093 ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
1094 ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
1095 ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
1096 ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
1097 ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE);
1098
1099 if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
1100 span->trunk_type == FTDM_TRUNK_BRI) {
1101
1102 sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
1103 }
1104
1105
1106 ftdm_assert(ftdm_sched_create(&((sngisdn_span_data_t*)span->signal_data)->sched, "sngisdn_schedule") == FTDM_SUCCESS, "Failed to create a new schedule!!");
1107
1108
1109 ftdm_assert(ftdm_queue_create(&((sngisdn_span_data_t*)span->signal_data)->event_queue, SNGISDN_EVENT_QUEUE_SIZE) == FTDM_SUCCESS, "Failed to create a new queue!!");
1110
1111 ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_isdn span = %s\n", span->name);
1112 return FTDM_SUCCESS;
1113 }
1114
1115 static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
1116 {
1117 unsigned i;
1118 ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n");
1119
1120 memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data));
1121 memset(&g_sngisdn_event_interface, 0, sizeof(g_sngisdn_event_interface));
1122
1123 g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind;
1124 g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm;
1125 g_sngisdn_event_interface.cc.sng_cnst_ind = sngisdn_rcv_cnst_ind;
1126 g_sngisdn_event_interface.cc.sng_disc_ind = sngisdn_rcv_disc_ind;
1127 g_sngisdn_event_interface.cc.sng_rel_ind = sngisdn_rcv_rel_ind;
1128 g_sngisdn_event_interface.cc.sng_dat_ind = sngisdn_rcv_dat_ind;
1129 g_sngisdn_event_interface.cc.sng_sshl_ind = sngisdn_rcv_sshl_ind;
1130 g_sngisdn_event_interface.cc.sng_sshl_cfm = sngisdn_rcv_sshl_cfm;
1131 g_sngisdn_event_interface.cc.sng_rmrt_ind = sngisdn_rcv_rmrt_ind;
1132 g_sngisdn_event_interface.cc.sng_rmrt_cfm = sngisdn_rcv_rmrt_cfm;
1133 g_sngisdn_event_interface.cc.sng_flc_ind = sngisdn_rcv_flc_ind;
1134 g_sngisdn_event_interface.cc.sng_fac_ind = sngisdn_rcv_fac_ind;
1135 g_sngisdn_event_interface.cc.sng_sta_cfm = sngisdn_rcv_sta_cfm;
1136 g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_ind;
1137 g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_cfm;
1138 g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_cfm;
1139 g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_ind;
1140 g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm;
1141
1142 g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log;
1143 g_sngisdn_event_interface.lg.sng_assert = sngisdn_rcv_sng_assert;
1144
1145 g_sngisdn_event_interface.sta.sng_phy_sta_ind = sngisdn_rcv_phy_ind;
1146 g_sngisdn_event_interface.sta.sng_q921_sta_ind = sngisdn_rcv_q921_ind;
1147 g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace;
1148 g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind;
1149 g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace;
1150 g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
1151
1152 g_sngisdn_event_interface.io.sng_l1_data_req = sngisdn_rcv_l1_data_req;
1153 g_sngisdn_event_interface.io.sng_l1_cmd_req = sngisdn_rcv_l1_cmd_req;
1154
1155 for(i=1;i<=MAX_VARIANTS;i++) {
1156 ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
1157 }
1158
1159
1160
1161 ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n");
1162 return FTDM_SUCCESS;
1163 }
1164
1165 static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload)
1166 {
1167 unsigned i;
1168 ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_isdn unload...\n");
1169
1170 sng_isdn_free();
1171
1172 for(i=1;i<=MAX_VARIANTS;i++) {
1173 ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].mutex);
1174 }
1175
1176 ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_isdn unload!\n");
1177 return FTDM_SUCCESS;
1178 }
1179
1180 static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
1181 {
1182 ftdm_status_t status = FTDM_SUCCESS;
1183 char *mycmd = NULL, *argv[10] = { 0 };
1184 int argc = 0;
1185
1186 if (data) {
1187 mycmd = ftdm_strdup(data);
1188 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
1189 }
1190
1191
1192 if (argc <= 0) {
1193 ftdm_log(FTDM_LOG_ERROR, "No parameters provided\n");
1194 goto done;
1195 }
1196
1197
1198 if (!strcasecmp(argv[0], "trace")) {
1199 char *trace_opt;
1200
1201 ftdm_span_t *span;
1202
1203 if (argc < 3) {
1204 ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn trace <q921|q931> <span name>\n");
1205 status = FTDM_FAIL;
1206 goto done;
1207 }
1208 trace_opt = argv[1];
1209
1210 status = ftdm_span_find_by_name(argv[2], &span);
1211 if (FTDM_SUCCESS != status) {
1212 stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
1213 goto done;
1214 }
1215
1216 if (!strcasecmp(trace_opt, "q921")) {
1217 sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
1218 } else if (!strcasecmp(trace_opt, "q931")) {
1219 sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
1220 } else if (!strcasecmp(trace_opt, "disable")) {
1221 sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
1222 } else {
1223 stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
1224 }
1225 }
1226 if (!strcasecmp(argv[0], "l1_stats")) {
1227 ftdm_span_t *span;
1228 if (argc < 2) {
1229 stream->write_function(stream, "Usage: ftdm sangoma_isdn l1_stats <span name>\n");
1230 status = FTDM_FAIL;
1231 goto done;
1232 }
1233 status = ftdm_span_find_by_name(argv[1], &span);
1234 if (FTDM_SUCCESS != status) {
1235 stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
1236
1237 status = FTDM_SUCCESS;
1238 goto done;
1239 }
1240 sngisdn_print_phy_stats(stream, span);
1241 }
1242
1243 if (!strcasecmp(argv[0], "show_spans")) {
1244 ftdm_span_t *span = NULL;
1245 if (argc == 2) {
1246 status = ftdm_span_find_by_name(argv[1], &span);
1247 if (FTDM_SUCCESS != status) {
1248 stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
1249
1250 status = FTDM_SUCCESS;
1251 goto done;
1252 }
1253 sngisdn_print_span(stream, span);
1254 status = FTDM_SUCCESS;
1255 goto done;
1256 }
1257 sngisdn_print_spans(stream);
1258 }
1259 if (!strcasecmp(argv[0], "check_ids")) {
1260 sngisdn_check_free_ids();
1261 }
1262 done:
1263 ftdm_safe_free(mycmd);
1264 return status;
1265 }
1266
1267 static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_isdn_io_init)
1268 {
1269 memset(&g_sngisdn_io_interface, 0, sizeof(g_sngisdn_io_interface));
1270
1271 g_sngisdn_io_interface.name = "sangoma_isdn";
1272 g_sngisdn_io_interface.api = ftdm_sangoma_isdn_api;
1273
1274 *fio = &g_sngisdn_io_interface;
1275
1276 return FTDM_SUCCESS;
1277 }
1278
1279 EX_DECLARE_DATA ftdm_module_t ftdm_module =
1280 {
1281 "sangoma_isdn",
1282 ftdm_sangoma_isdn_io_init,
1283 NULL,
1284 ftdm_sangoma_isdn_init,
1285 NULL,
1286 ftdm_sangoma_isdn_unload,
1287 ftdm_sangoma_isdn_span_config
1288 };
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304