This source file includes following definitions.
- FIO_CHANNEL_OUTGOING_CALL_FUNCTION
- ftdm_analog_em_start
- FIO_CHANNEL_GET_SIG_STATUS_FUNCTION
- FIO_SPAN_GET_SIG_STATUS_FUNCTION
- FIO_SIG_CONFIGURE_FUNCTION
- teletone_handler
- ftdm_analog_em_channel_run
- process_event
- ftdm_analog_em_run
- FIO_SIG_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
38
39 #include "private/ftdm_core.h"
40 #include "ftdm_analog_em.h"
41
42 #ifndef localtime_r
43 struct tm * localtime_r(const time_t *clock, struct tm *result);
44 #endif
45
46 static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj);
47
48
49
50
51
52
53
54
55 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_em_outgoing_call)
56 {
57 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
58 ftdm_channel_clear_needed_tones(ftdmchan);
59 ftdm_channel_clear_detected_tones(ftdmchan);
60
61 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
62
63 ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL);
64 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_PROGRESS_DETECT, NULL);
65 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
66 ftdm_thread_create_detached(ftdm_analog_em_channel_run, ftdmchan);
67 return FTDM_SUCCESS;
68 }
69
70 return FTDM_FAIL;
71 }
72
73
74
75
76
77
78 static ftdm_status_t ftdm_analog_em_start(ftdm_span_t *span)
79 {
80 ftdm_analog_em_data_t *analog_data = span->signal_data;
81 ftdm_set_flag(analog_data, FTDM_ANALOG_EM_RUNNING);
82 return ftdm_thread_create_detached(ftdm_analog_em_run, span);
83 }
84
85
86
87
88
89
90
91
92 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_em_get_channel_sig_status)
93 {
94 *status = FTDM_SIG_STATE_UP;
95 return FTDM_SUCCESS;
96 }
97
98
99
100
101
102
103
104
105 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status)
106 {
107 *status = FTDM_SIG_STATE_UP;
108 return FTDM_SUCCESS;
109 }
110
111
112
113
114
115
116
117
118 static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
119
120 {
121 ftdm_analog_em_data_t *analog_data;
122 const char *tonemap = "us";
123 uint32_t digit_timeout = 10;
124 uint32_t max_dialstr = 11;
125 const char *var, *val;
126 int *intval;
127
128 assert(sig_cb != NULL);
129
130 if (span->signal_type) {
131 snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
132 return FTDM_FAIL;
133 }
134
135 analog_data = ftdm_malloc(sizeof(*analog_data));
136 assert(analog_data != NULL);
137 memset(analog_data, 0, sizeof(*analog_data));
138
139 while((var = va_arg(ap, char *))) {
140 if (!strcasecmp(var, "tonemap")) {
141 if (!(val = va_arg(ap, char *))) {
142 break;
143 }
144 tonemap = val;
145 } else if (!strcasecmp(var, "digit_timeout")) {
146 if (!(intval = va_arg(ap, int *))) {
147 break;
148 }
149 digit_timeout = *intval;
150 } else if (!strcasecmp(var, "max_dialstr")) {
151 if (!(intval = va_arg(ap, int *))) {
152 break;
153 }
154 max_dialstr = *intval;
155 } else {
156 snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
157 return FTDM_FAIL;
158 }
159 }
160
161
162 if (digit_timeout < 2000 || digit_timeout > 10000) {
163 digit_timeout = 2000;
164 }
165
166 if (max_dialstr < 2 || max_dialstr > MAX_DIALSTRING) {
167 ftdm_log(FTDM_LOG_ERROR, "Invalid max_dialstr, setting to %d\n", MAX_DIALSTRING);
168 max_dialstr = MAX_DIALSTRING;
169 }
170
171 span->start = ftdm_analog_em_start;
172 analog_data->digit_timeout = digit_timeout;
173 analog_data->max_dialstr = max_dialstr;
174 span->signal_cb = sig_cb;
175 span->signal_type = FTDM_SIGTYPE_ANALOG;
176 span->signal_data = analog_data;
177 span->outgoing_call = analog_em_outgoing_call;
178 span->get_channel_sig_status = analog_em_get_channel_sig_status;
179 span->get_span_sig_status = analog_em_get_span_sig_status;
180 ftdm_span_load_tones(span, tonemap);
181
182 return FTDM_SUCCESS;
183
184 }
185
186
187
188
189
190
191
192 static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
193 {
194 ftdm_buffer_t *dt_buffer = ts->user_data;
195 int wrote;
196
197 if (!dt_buffer) {
198 return -1;
199 }
200 wrote = teletone_mux_tones(ts, map);
201 ftdm_buffer_write(dt_buffer, ts->buffer, wrote * 2);
202 return 0;
203 }
204
205
206
207
208
209
210 static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
211 {
212 ftdm_channel_t *ftdmchan = (ftdm_channel_t *) obj;
213 ftdm_buffer_t *dt_buffer = NULL;
214 teletone_generation_session_t ts;
215 uint8_t frame[1024];
216 ftdm_size_t len, rlen;
217 ftdm_tone_type_t tt = FTDM_TONE_DTMF;
218 char dtmf[128] = "";
219 ftdm_size_t dtmf_offset = 0;
220 ftdm_analog_em_data_t *analog_data = ftdmchan->span->signal_data;
221 ftdm_channel_t *closed_chan;
222 uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
223 ftdm_sigmsg_t sig;
224 ftdm_status_t status;
225
226 ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread starting.\n");
227
228 ts.buffer = NULL;
229
230 if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
231 ftdm_log(FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error);
232 goto done;
233 }
234
235 if (ftdm_buffer_create(&dt_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
236 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "memory error!");
237 ftdm_log(FTDM_LOG_ERROR, "MEM ERROR\n");
238 goto done;
239 }
240
241 if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) {
242 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "error initilizing tone detector!");
243 ftdm_log(FTDM_LOG_ERROR, "TONE ERROR\n");
244 goto done;
245 }
246
247 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INTHREAD);
248 teletone_init_session(&ts, 0, teletone_handler, dt_buffer);
249 ts.rate = 8000;
250 #if 0
251 ts.debug = 1;
252 ts.debug_stream = stdout;
253 #endif
254 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval);
255 ftdm_buffer_set_loops(dt_buffer, -1);
256
257 memset(&sig, 0, sizeof(sig));
258 sig.chan_id = ftdmchan->chan_id;
259 sig.span_id = ftdmchan->span_id;
260 sig.channel = ftdmchan;
261
262 assert(interval != 0);
263
264 while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
265 ftdm_wait_flag_t flags = FTDM_READ;
266 ftdm_size_t dlen = 0;
267
268 len = sizeof(frame);
269
270 elapsed += interval;
271 state_counter += interval;
272
273 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
274 switch(ftdmchan->state) {
275 case FTDM_CHANNEL_STATE_DIALING:
276 {
277 if (! ftdmchan->needed_tones[FTDM_TONEMAP_RING]
278 && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
279 if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) {
280 ftdm_log(FTDM_LOG_ERROR, "No Digits to send!\n");
281 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
282 } else {
283 if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) {
284 ftdm_log(FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
285 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
286 } else {
287 state_counter = 0;
288 ftdmchan->needed_tones[FTDM_TONEMAP_RING] = 1;
289 ftdmchan->needed_tones[FTDM_TONEMAP_BUSY] = 1;
290 ftdmchan->needed_tones[FTDM_TONEMAP_FAIL1] = 1;
291 ftdmchan->needed_tones[FTDM_TONEMAP_FAIL2] = 1;
292 ftdmchan->needed_tones[FTDM_TONEMAP_FAIL3] = 1;
293 dial_timeout = ((ftdmchan->dtmf_on + ftdmchan->dtmf_off) * strlen(ftdmchan->caller_data.dnis.digits)) + 2000;
294 }
295 }
296 break;
297 }
298 if (state_counter > dial_timeout) {
299 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
300 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
301 } else {
302 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
303 }
304 }
305 }
306 break;
307 case FTDM_CHANNEL_STATE_DIALTONE:
308 {
309 if (state_counter > 10000) {
310 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
311 }
312 }
313 break;
314 case FTDM_CHANNEL_STATE_BUSY:
315 {
316 if (state_counter > 20000) {
317 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_ATTN);
318 }
319 }
320 break;
321 case FTDM_CHANNEL_STATE_ATTN:
322 {
323 if (state_counter > 20000) {
324 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
325 }
326 }
327 break;
328 case FTDM_CHANNEL_STATE_HANGUP:
329 {
330 if (state_counter > 500) {
331 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
332 (ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
333 || ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) {
334 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
335 } else {
336 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
337 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
338 }
339 }
340 }
341 break;
342 case FTDM_CHANNEL_STATE_UP:
343 case FTDM_CHANNEL_STATE_RING:
344 {
345 ftdm_sleep(interval);
346 continue;
347 }
348 break;
349 case FTDM_CHANNEL_STATE_DOWN:
350 {
351 goto done;
352 }
353 break;
354 default:
355 break;
356 }
357 } else {
358 ftdm_clear_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
359 ftdm_channel_complete_state(ftdmchan);
360 indicate = 0;
361 state_counter = 0;
362
363 ftdm_log(FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n",
364 ftdmchan->span_id, ftdmchan->chan_id,
365 ftdm_channel_state2str(ftdmchan->state));
366 switch(ftdmchan->state) {
367 case FTDM_CHANNEL_STATE_UP:
368 {
369 ftdm_channel_use(ftdmchan);
370 ftdm_channel_clear_needed_tones(ftdmchan);
371 ftdm_channel_flush_dtmf(ftdmchan);
372
373 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
374 ftdm_channel_command(ftdmchan, FTDM_COMMAND_OFFHOOK, NULL);
375 }
376
377 sig.event_id = FTDM_SIGEVENT_UP;
378
379 ftdm_span_send_signal(ftdmchan->span, &sig);
380 continue;
381 }
382 break;
383 case FTDM_CHANNEL_STATE_DIALING:
384 {
385 ftdm_channel_use(ftdmchan);
386 }
387 break;
388 case FTDM_CHANNEL_STATE_RING:
389 {
390 ftdm_channel_use(ftdmchan);
391
392 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
393 ftdm_set_string(ftdmchan->caller_data.dnis.digits, ftdmchan->chan_number);
394 } else {
395 ftdm_set_string(ftdmchan->caller_data.dnis.digits, dtmf);
396 }
397
398 sig.event_id = FTDM_SIGEVENT_START;
399
400 ftdm_span_send_signal(ftdmchan->span, &sig);
401 continue;
402 }
403 break;
404 case FTDM_CHANNEL_STATE_DOWN:
405 {
406 sig.event_id = FTDM_SIGEVENT_STOP;
407 ftdm_span_send_signal(ftdmchan->span, &sig);
408 goto done;
409 }
410 break;
411 case FTDM_CHANNEL_STATE_DIALTONE:
412 {
413 memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
414 *dtmf = '\0';
415 dtmf_offset = 0;
416 ftdm_buffer_zero(dt_buffer);
417 teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_DIAL]);
418 indicate = 1;
419
420 ftdm_channel_command(ftdmchan, FTDM_COMMAND_WINK, NULL);
421 }
422 break;
423 case FTDM_CHANNEL_STATE_RINGING:
424 {
425 ftdm_buffer_zero(dt_buffer);
426 teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
427 indicate = 1;
428 }
429 break;
430 case FTDM_CHANNEL_STATE_BUSY:
431 {
432 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CIRCUIT_CONGESTION;
433 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
434 ftdm_buffer_zero(dt_buffer);
435 teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_BUSY]);
436 indicate = 1;
437 } else {
438 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
439 }
440 }
441 break;
442 case FTDM_CHANNEL_STATE_ATTN:
443 {
444 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
445 ftdm_buffer_zero(dt_buffer);
446 teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_ATTN]);
447 indicate = 1;
448 } else {
449 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
450 }
451 }
452 break;
453 default:
454 break;
455 }
456 }
457
458
459 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE || ftdmchan->state == FTDM_CHANNEL_STATE_COLLECT) {
460 if ((dlen = ftdm_channel_dequeue_dtmf(ftdmchan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) {
461
462 if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALTONE) {
463 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
464 collecting = 1;
465 }
466 dtmf_offset = strlen(dtmf);
467 last_digit = elapsed;
468 sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
469 ftdm_set_string(sig.ev_data.collected.digits, dtmf);
470 if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) {
471 collecting = 0;
472 }
473 }
474 }
475
476
477 if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
478 ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
479 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
480 last_digit = 0;
481 collecting = 0;
482 }
483
484 if (ftdm_channel_wait(ftdmchan, &flags, interval * 2) != FTDM_SUCCESS) {
485 continue;
486 }
487
488 if (!(flags & FTDM_READ)) {
489 continue;
490 }
491
492 if (ftdm_channel_read(ftdmchan, frame, &len) != FTDM_SUCCESS) {
493 ftdm_log(FTDM_LOG_ERROR, "READ ERROR [%s]\n", ftdmchan->last_error);
494 goto done;
495 }
496
497 if (ftdmchan->detected_tones[0]) {
498 int i;
499
500 for (i = 1; i < FTDM_TONEMAP_INVALID; i++) {
501 if (ftdmchan->detected_tones[i]) {
502 ftdm_log(FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id);
503 }
504 }
505
506 if (ftdmchan->detected_tones[FTDM_TONEMAP_BUSY] ||
507 ftdmchan->detected_tones[FTDM_TONEMAP_FAIL1] ||
508 ftdmchan->detected_tones[FTDM_TONEMAP_FAIL2] ||
509 ftdmchan->detected_tones[FTDM_TONEMAP_FAIL3] ||
510 ftdmchan->detected_tones[FTDM_TONEMAP_ATTN]
511 ) {
512 ftdm_log(FTDM_LOG_ERROR, "Failure indication detected!\n");
513 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
514 } else if (ftdmchan->detected_tones[FTDM_TONEMAP_RING]) {
515 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
516 }
517
518 ftdm_channel_clear_detected_tones(ftdmchan);
519 }
520
521 if ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer))) {
522 rlen = len;
523 memset(frame, 0, len);
524 ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen);
525 continue;
526 }
527
528 if (!indicate) {
529 continue;
530 }
531
532 if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) {
533 len *= 2;
534 }
535
536 rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
537
538 if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) {
539 fio_codec_t codec_func = NULL;
540
541 if (ftdmchan->native_codec == FTDM_CODEC_ULAW) {
542 codec_func = fio_slin2ulaw;
543 } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW) {
544 codec_func = fio_slin2alaw;
545 }
546
547 if (codec_func) {
548 status = codec_func(frame, sizeof(frame), &rlen);
549 } else {
550 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
551 goto done;
552 }
553 }
554
555 ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen);
556 }
557
558 done:
559
560 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
561
562 closed_chan = ftdmchan;
563 ftdm_channel_close(&ftdmchan);
564
565 ftdm_channel_command(closed_chan, FTDM_COMMAND_SET_NATIVE_CODEC, NULL);
566
567 if (ts.buffer) {
568 teletone_destroy_session(&ts);
569 }
570
571 if (dt_buffer) {
572 ftdm_buffer_destroy(&dt_buffer);
573 }
574
575 ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD);
576
577 ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread ended.\n");
578
579 return NULL;
580 }
581
582
583
584
585
586
587
588 static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event)
589 {
590 ftdm_sigmsg_t sig;
591 int locked = 0;
592
593 memset(&sig, 0, sizeof(sig));
594 sig.chan_id = event->channel->chan_id;
595 sig.span_id = event->channel->span_id;
596 sig.channel = event->channel;
597
598
599 ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n",
600 ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
601
602 ftdm_mutex_lock(event->channel->mutex);
603 locked++;
604
605 switch(event->enum_id) {
606 case FTDM_OOB_ONHOOK:
607 {
608 if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) {
609 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
610 }
611
612 }
613 break;
614 case FTDM_OOB_OFFHOOK:
615 {
616 if (ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD)) {
617 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
618 } else {
619 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DIALTONE);
620 ftdm_mutex_unlock(event->channel->mutex);
621 locked = 0;
622 ftdm_thread_create_detached(ftdm_analog_em_channel_run, event->channel);
623 }
624 break;
625 }
626 case FTDM_OOB_WINK:
627 {
628 if (event->channel->state != FTDM_CHANNEL_STATE_DIALING) {
629 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
630 } else {
631 ftdm_set_flag_locked(event->channel, FTDM_CHANNEL_WINK);
632 }
633
634 }
635 break;
636 }
637 if (locked) {
638 ftdm_mutex_unlock(event->channel->mutex);
639 }
640 return FTDM_SUCCESS;
641 }
642
643
644
645
646
647
648 static void *ftdm_analog_em_run(ftdm_thread_t *me, void *obj)
649 {
650 ftdm_span_t *span = (ftdm_span_t *) obj;
651 ftdm_analog_em_data_t *analog_data = span->signal_data;
652
653 ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM thread starting.\n");
654
655 while(ftdm_running() && ftdm_test_flag(analog_data, FTDM_ANALOG_EM_RUNNING)) {
656 int waitms = 10;
657 ftdm_status_t status;
658
659 status = ftdm_span_poll_event(span, waitms, NULL);
660
661 switch(status) {
662 case FTDM_SUCCESS:
663 {
664 ftdm_event_t *event;
665 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
666 if (event->enum_id == FTDM_OOB_NOOP) {
667 continue;
668 }
669 if (process_event(span, event) != FTDM_SUCCESS) {
670 goto end;
671 }
672 }
673 }
674 break;
675 case FTDM_FAIL:
676 {
677 ftdm_log(FTDM_LOG_ERROR, "Failure Polling event! [%s]\n", span->last_error);
678 }
679 break;
680 default:
681 break;
682 }
683
684 }
685
686 end:
687
688 ftdm_clear_flag(analog_data, FTDM_ANALOG_EM_RUNNING);
689
690 ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM thread ending.\n");
691
692 return NULL;
693 }
694
695
696
697
698
699 static FIO_SIG_LOAD_FUNCTION(ftdm_analog_em_init)
700 {
701 return FTDM_SUCCESS;
702 }
703
704
705
706
707 EX_DECLARE_DATA ftdm_module_t ftdm_module = {
708 "analog_em",
709 NULL,
710 NULL,
711 ftdm_analog_em_init,
712 ftdm_analog_em_configure_span,
713 NULL
714 };
715
716
717
718
719
720
721
722
723
724
725
726