52 #define ASTMM_LIBC ASTMM_IGNORE
62 #include "asterisk/res_fax.h"
66 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
68 #include <spandsp/version.h>
70 #define SPANDSP_FAX_SAMPLES 160
71 #define SPANDSP_FAX_TIMER_RATE 8000 / SPANDSP_FAX_SAMPLES
72 #define SPANDSP_ENGAGE_UDPTL_NAT_RETRY 3
86 static void spandsp_v21_tone(
void *
data,
int code,
int level,
int delay);
88 static char *spandsp_fax_cli_show_capabilities(
int fd);
89 static char *spandsp_fax_cli_show_session(
struct ast_fax_session *s,
int fd);
90 static void spandsp_manager_fax_session(
struct mansession *s,
92 static char *spandsp_fax_cli_show_stats(
int fd);
97 .description =
"Spandsp FAX Driver",
98 #if SPANDSP_RELEASE_DATE >= 20090220
100 .version = SPANDSP_RELEASE_DATETIME_STRING,
105 .version =
"pre-20090220",
107 .caps = AST_FAX_TECH_AUDIO | AST_FAX_TECH_T38 | AST_FAX_TECH_SEND
108 | AST_FAX_TECH_RECEIVE | AST_FAX_TECH_GATEWAY
109 | AST_FAX_TECH_V21_DETECT,
114 .start_session = spandsp_fax_start,
115 .cancel_session = spandsp_fax_cancel,
116 .switch_to_t38 = spandsp_fax_switch_to_t38,
117 .cli_show_capabilities = spandsp_fax_cli_show_capabilities,
118 .cli_show_session = spandsp_fax_cli_show_session,
119 .manager_fax_session = spandsp_manager_fax_session,
120 .cli_show_stats = spandsp_fax_cli_show_stats,
129 int rx_protocol_error;
130 int tx_protocol_error;
132 int retries_exceeded;
144 } spandsp_global_stats;
147 unsigned int ist38:1;
148 unsigned int isdone:1;
150 fax_state_t fax_state;
152 t30_state_t *t30_state;
153 t38_core_state_t *t38_core_state;
157 struct spandsp_fax_gw_stats *t38stats;
158 t38_gateway_state_t t38_gw_state;
164 modem_connect_tones_rx_state_t *tone_state;
168 static
void session_destroy(struct
spandsp_pvt *p);
169 static
int t38_tx_packet_handler(t38_core_state_t *t38_core_state,
void *data, const uint8_t *buf,
int len,
int count);
172 #if SPANDSP_RELEASE_DATE >= 20120902
175 static void spandsp_log(
void *user_data,
int level,
const char *msg);
179 static void spandsp_log(
int level,
const char *msg);
190 t30_state_t *t30_to_terminate;
193 t30_to_terminate = p->t30_state;
194 }
else if (p->ist38) {
195 #if SPANDSP_RELEASE_DATE >= 20080725
196 t30_to_terminate = &p->t38_state.t30;
198 t30_to_terminate = &p->t38_state.t30_state;
201 #if SPANDSP_RELEASE_DATE >= 20080725
202 t30_to_terminate = &p->fax_state.t30;
204 t30_to_terminate = &p->fax_state.t30_state;
208 t30_terminate(t30_to_terminate);
213 fax_release(&p->fax_state);
214 t38_terminal_release(&p->t38_state);
224 static int t38_tx_packet_handler(t38_core_state_t *t38_core_state,
void *data,
const uint8_t *buf,
int len,
int count)
232 .src =
"res_fax_spandsp_t38",
248 ast_set_flag(f, AST_FAX_FRFLAG_GATEWAY);
266 switch (completion_code) {
272 case T30_ERR_CEDTONE:
273 case T30_ERR_T0_EXPIRED:
274 case T30_ERR_T1_EXPIRED:
275 case T30_ERR_T3_EXPIRED:
276 case T30_ERR_HDLC_CARRIER:
277 case T30_ERR_CANNOT_TRAIN:
281 case T30_ERR_OPER_INT_FAIL:
282 case T30_ERR_INCOMPATIBLE:
283 case T30_ERR_RX_INCAPABLE:
284 case T30_ERR_TX_INCAPABLE:
285 case T30_ERR_NORESSUPPORT:
286 case T30_ERR_NOSIZESUPPORT:
290 case T30_ERR_UNEXPECTED:
295 case T30_ERR_TX_BADDCS:
296 case T30_ERR_TX_BADPG:
297 case T30_ERR_TX_ECMPHD:
298 case T30_ERR_TX_GOTDCN:
299 case T30_ERR_TX_INVALRSP:
300 case T30_ERR_TX_NODIS:
301 case T30_ERR_TX_PHBDEAD:
302 case T30_ERR_TX_PHDDEAD:
303 case T30_ERR_TX_T5EXP:
308 case T30_ERR_RX_ECMPHD:
309 case T30_ERR_RX_GOTDCS:
310 case T30_ERR_RX_INVALCMD:
311 case T30_ERR_RX_NOCARRIER:
312 case T30_ERR_RX_NOEOL:
315 case T30_ERR_RX_NOFAX:
318 case T30_ERR_RX_T2EXPDCN:
319 case T30_ERR_RX_T2EXPD:
320 case T30_ERR_RX_T2EXPFAX:
321 case T30_ERR_RX_T2EXPMPS:
322 case T30_ERR_RX_T2EXPRR:
323 case T30_ERR_RX_T2EXP:
324 case T30_ERR_RX_DCNWHY:
325 case T30_ERR_RX_DCNDATA:
326 case T30_ERR_RX_DCNFAX:
327 case T30_ERR_RX_DCNPHD:
328 case T30_ERR_RX_DCNRRD:
329 case T30_ERR_RX_DCNNORTN:
334 case T30_ERR_FILEERROR:
336 case T30_ERR_BADTIFF:
337 case T30_ERR_BADPAGE:
339 case T30_ERR_BADTIFFHDR:
347 case T30_ERR_RETRYDCN:
350 case T30_ERR_CALLDROPPED:
356 case T30_ERR_IDENT_UNACCEPTABLE:
357 case T30_ERR_SUB_UNACCEPTABLE:
358 case T30_ERR_SEP_UNACCEPTABLE:
359 case T30_ERR_PSA_UNACCEPTABLE:
360 case T30_ERR_SID_UNACCEPTABLE:
361 case T30_ERR_PWD_UNACCEPTABLE:
362 case T30_ERR_TSA_UNACCEPTABLE:
363 case T30_ERR_IRA_UNACCEPTABLE:
364 case T30_ERR_CIA_UNACCEPTABLE:
365 case T30_ERR_ISP_UNACCEPTABLE:
366 case T30_ERR_CSA_UNACCEPTABLE:
371 ast_log(LOG_WARNING,
"unknown FAX session result '%d' (%s)\n", completion_code, t30_completion_code_to_str(completion_code));
385 #if SPANDSP_RELEASE_DATE >= 20120902
395 char headerinfo[T30_MAX_PAGE_HEADER_INFO + 1];
398 #if SPANDSP_RELEASE_DATE >= 20120902
400 t30_state_t *t30_state = p->t30_state;
403 ast_debug(5,
"FAX session '%u' entering phase E\n", s->
id);
409 t30_get_transfer_statistics(t30_state, &stats);
411 if (completion_code == T30_ERR_OK) {
422 if ((c = t30_get_tx_ident(t30_state))) {
426 if ((c = t30_get_rx_ident(t30_state))) {
430 #if SPANDSP_RELEASE_DATE >= 20090220
440 t30_get_tx_page_header_info(t30_state, headerinfo);
450 #if SPANDSP_RELEASE_DATE >= 20120902
452 static void spandsp_log(
void *user_data,
int level,
const char *msg)
458 if (level == SPAN_LOG_ERROR) {
459 ast_log(LOG_ERROR,
"%s", msg);
460 }
else if (level == SPAN_LOG_WARNING) {
461 ast_log(LOG_WARNING,
"%s", msg);
469 int level = SPAN_LOG_WARNING;
472 level = SPAN_LOG_DEBUG_3;
475 #if SPANDSP_RELEASE_DATE >= 20120902
477 span_log_set_message_handler(state,
spandsp_log, NULL);
482 span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
492 t30_set_tx_page_header_info(t30_state, details->
headerinfo);
498 if (details->
caps & AST_FAX_TECH_RECEIVE) {
510 t30_set_ecm_capability(t30_state, details->
option.
ecm);
511 #if SPANDSP_RELEASE_DATE >= 20120902
513 t30_set_supported_compressions(t30_state, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);
516 t30_set_supported_compressions(t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
526 p->tone_state = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, spandsp_v21_tone, p);
527 if (!p->tone_state) {
537 if (AST_FAX_MODEM_V17 & details->
modems) {
538 modems |= T30_SUPPORT_V17;
540 if (AST_FAX_MODEM_V27TER & details->
modems) {
541 modems |= T30_SUPPORT_V27TER;
543 if (AST_FAX_MODEM_V29 & details->
modems) {
544 modems |= T30_SUPPORT_V29;
546 if (AST_FAX_MODEM_V34 & details->
modems) {
547 #if defined(T30_SUPPORT_V34)
548 modems |= T30_SUPPORT_V34;
549 #elif defined(T30_SUPPORT_V34HDX)
550 modems |= T30_SUPPORT_V34HDX;
552 ast_log(LOG_WARNING,
"v34 not supported in this version of spandsp\n");
566 ast_log(LOG_ERROR,
"Cannot initialize the spandsp private FAX technology structure.\n");
571 if (spandsp_v21_new(p)) {
572 ast_log(LOG_ERROR,
"Cannot initialize the spandsp private v21 technology structure.\n");
575 s->
state = AST_FAX_STATE_ACTIVE;
580 s->
state = AST_FAX_STATE_INITIALIZED;
591 ast_log(LOG_ERROR,
"Are we sending or receiving? The FAX requirements (capabilities: 0x%X) were not properly set.\n", s->
details->
caps);
596 ast_log(LOG_ERROR,
"Channel '%s' FAX session '%u' failed to create timing source.\n", s->
channame, s->
id);
602 p->stats = &spandsp_global_stats.g711;
604 if (s->
details->
caps & (AST_FAX_TECH_T38 | AST_FAX_TECH_AUDIO)) {
605 if ((s->
details->
caps & AST_FAX_TECH_AUDIO) == 0) {
608 p->stats = &spandsp_global_stats.t38;
612 t38_terminal_init(&p->t38_state, caller_mode, t38_tx_packet_handler, s);
613 set_logging(&p->t38_state.logging, s->
details);
616 fax_init(&p->fax_state, caller_mode);
617 set_logging(&p->fax_state.logging, s->
details);
620 s->
state = AST_FAX_STATE_INITIALIZED;
633 modem_connect_tones_rx_free(p->tone_state);
644 }
else if (s->
details->
caps & AST_FAX_TECH_V21_DETECT) {
645 spandsp_v21_cleanup(s);
666 .src =
"res_fax_spandsp_g711",
672 ast_log(LOG_ERROR,
"Failed to acknowledge timer for FAX session '%u'\n", s->
id);
678 s->
state = AST_FAX_STATE_COMPLETE;
679 ast_debug(5,
"FAX session '%u' is complete.\n", s->
id);
684 t38_terminal_send_timeout(&p->t38_state, SPANDSP_FAX_SAMPLES);
689 if ((samples = fax_tx(&p->fax_state, buf, SPANDSP_FAX_SAMPLES)) > 0) {
699 static void spandsp_v21_tone(
void *data,
int code,
int level,
int delay)
703 if (code == MODEM_CONNECT_TONES_FAX_PREAMBLE) {
712 g711_state_t *decoder;
714 if (p->v21_detected) {
723 ast_debug(5,
"frame={ datalen=%d, samples=%d, mallocd=%d, src=%s, flags=%u, ts=%ld, len=%ld, seqno=%d, data.ptr=%p, subclass.format=%s }\n", f->
datalen, f->
samples, f->
mallocd, f->
src, f->
flags, f->
ts, f->
len, f->
seqno, f->
data.ptr,
ast_format_get_name(f->
subclass.
format));
727 modem_connect_tones_rx(p->tone_state, f->
data.ptr, f->
samples);
736 g711_decode(decoder, slndata, f->
data.ptr, f->
samples);
738 modem_connect_tones_rx(p->tone_state, slndata, f->
samples);
739 g711_release(decoder);
740 #if SPANDSP_RELEASE_DATE >= 20090220
751 if (p->v21_detected) {
774 return spandsp_v21_detect(s, f);
782 if (s->
state == AST_FAX_STATE_COMPLETE) {
788 return t38_core_rx_ifp_packet(p->t38_core_state, f->
data.ptr, f->
datalen, f->
seqno);
790 return fax_rx(&p->fax_state, f->
data.ptr, f->
samples);
810 .src =
"res_fax_spandsp_g711",
812 .flags = AST_FAX_FRFLAG_GATEWAY,
818 return p->isdone ? -1 : res;
827 return p->isdone ? -1 : res;
840 static void spandsp_fax_gw_gen_release(
struct ast_channel *chan,
void *data)
856 .release = spandsp_fax_gw_gen_release,
860 #if SPANDSP_RELEASE_DATE >= 20081012
862 p->t38_core_state=&p->t38_gw_state.t38x.t38;
865 p->t38_core_state=&p->t38_gw_state.t38;
868 if (!t38_gateway_init(&p->t38_gw_state, t38_tx_packet_handler, s)) {
887 set_logging(&p->t38_gw_state.logging, s->
details);
888 set_logging(&p->t38_core_state->logging, s->
details);
891 t38_set_t38_version(p->t38_core_state, t38_param->
version);
893 t38_set_max_datagram_size(p->t38_core_state, t38_param->
max_ifp);
895 t38_set_mmr_transcoding(p->t38_core_state, t38_param->
transcoding_mmr);
897 t38_set_data_rate_management_method(p->t38_core_state,
898 (t38_param->
rate_management == AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF)? 1 : 2);
900 t38_gateway_set_transmit_on_idle(&p->t38_gw_state, TRUE);
901 t38_set_sequence_number_handling(p->t38_core_state, TRUE);
904 t38_gateway_set_supported_modems(&p->t38_gw_state, spandsp_modems(s->
details));
910 for (i=0; i < SPANDSP_ENGAGE_UDPTL_NAT_RETRY; i++) {
911 #if SPANDSP_RELEASE_DATE >= 20091228
912 t38_core_send_indicator(&p->t38_gw_state.t38x.t38, T38_IND_NO_SIGNAL);
913 #elif SPANDSP_RELEASE_DATE >= 20081012
914 t38_core_send_indicator(&p->t38_gw_state.t38x.t38, T38_IND_NO_SIGNAL, p->t38_gw_state.t38x.t38.indicator_tx_count);
916 t38_core_send_indicator(&p->t38_gw_state.t38, T38_IND_NO_SIGNAL, p->t38_gw_state.t38.indicator_tx_count);
920 s->
state = AST_FAX_STATE_ACTIVE;
940 return t38_core_rx_ifp_packet(p->t38_core_state, f->
data.ptr, f->
datalen, f->
seqno);
943 return t38_gateway_rx(&p->t38_gw_state, f->
data.ptr, f->
samples);
954 t38_stats_t t38_stats;
956 t38_gateway_get_transfer_statistics(&p->t38_gw_state, &t38_stats);
958 s->
details->
option.
ecm = t38_stats.error_correcting_mode ? AST_FAX_OPTFLAG_TRUE : AST_FAX_OPTFLAG_FALSE;
968 s->
state = AST_FAX_STATE_OPEN;
975 #if SPANDSP_RELEASE_DATE >= 20080725
977 p->t30_state = &p->t38_state.t30;
978 p->t38_core_state = &p->t38_state.t38_fe.t38;
981 p->t30_state = &p->t38_state.t30_state;
982 p->t38_core_state = &p->t38_state.t38;
985 #if SPANDSP_RELEASE_DATE >= 20080725
987 p->t30_state = &p->fax_state.t30;
990 p->t30_state = &p->fax_state.t30_state;
994 set_logging(&p->t30_state->logging, s->
details);
997 set_local_info(p->t30_state, s->
details);
998 set_file(p->t30_state, s->
details);
999 set_ecm(p->t30_state, s->
details);
1000 t30_set_supported_modems(p->t30_state, spandsp_modems(s->
details));
1008 set_logging(&p->t38_core_state->logging, s->
details);
1013 t38_set_fill_bit_removal(p->t38_core_state, TRUE);
1017 t38_set_mmr_transcoding(p->t38_core_state, TRUE);
1021 t38_set_jbig_transcoding(p->t38_core_state, TRUE);
1025 fax_set_transmit_on_idle(&p->fax_state, 1);
1031 ast_log(LOG_ERROR,
"FAX session '%u' error setting rate on timing source.\n", s->
id);
1035 s->
state = AST_FAX_STATE_ACTIVE;
1050 t30_terminate(p->t30_state);
1061 t30_set_phase_e_handler(p->t30_state, NULL, NULL);
1063 t30_terminate(p->t30_state);
1069 p->stats = &spandsp_global_stats.t38;
1070 spandsp_fax_start(s);
1076 static char *spandsp_fax_cli_show_capabilities(
int fd)
1078 ast_cli(fd,
"SEND RECEIVE T.38 G.711 GATEWAY\n\n");
1083 static char *spandsp_fax_cli_show_session(
struct ast_fax_session *s,
int fd)
1089 ast_cli(fd,
"%-22s : %u\n",
"session", s->
id);
1090 ast_cli(fd,
"%-22s : %s\n",
"operation",
"Gateway");
1092 if (s->
state != AST_FAX_STATE_UNINITIALIZED) {
1094 t38_gateway_get_transfer_statistics(&p->t38_gw_state, &stats);
1095 ast_cli(fd,
"%-22s : %s\n",
"ECM Mode", stats.error_correcting_mode ?
"Yes" :
"No");
1096 ast_cli(fd,
"%-22s : %d\n",
"Data Rate", stats.bit_rate);
1097 ast_cli(fd,
"%-22s : %d\n",
"Page Number", stats.pages_transferred + 1);
1099 }
else if (s->
details->
caps & AST_FAX_TECH_V21_DETECT) {
1100 ast_cli(fd,
"%-22s : %u\n",
"session", s->
id);
1101 ast_cli(fd,
"%-22s : %s\n",
"operation",
"V.21 Detect");
1106 ast_cli(fd,
"%-22s : %u\n",
"session", s->
id);
1107 ast_cli(fd,
"%-22s : %s\n",
"operation", (s->
details->
caps & AST_FAX_TECH_RECEIVE) ?
"Receive" :
"Transmit");
1109 if (s->
state != AST_FAX_STATE_UNINITIALIZED) {
1111 t30_get_transfer_statistics(p->t30_state, &stats);
1112 ast_cli(fd,
"%-22s : %s\n",
"Last Status", t30_completion_code_to_str(stats.current_status));
1113 ast_cli(fd,
"%-22s : %s\n",
"ECM Mode", stats.error_correcting_mode ?
"Yes" :
"No");
1114 ast_cli(fd,
"%-22s : %d\n",
"Data Rate", stats.bit_rate);
1115 ast_cli(fd,
"%-22s : %dx%d\n",
"Image Resolution", stats.x_resolution, stats.y_resolution);
1116 #if SPANDSP_RELEASE_DATE >= 20090220
1117 ast_cli(fd,
"%-22s : %d\n",
"Page Number", ((s->
details->
caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
1119 ast_cli(fd,
"%-22s : %d\n",
"Page Number", stats.pages_transferred + 1);
1121 ast_cli(fd,
"%-22s : %s\n",
"File Name", s->
details->
caps & AST_FAX_TECH_RECEIVE ? p->t30_state->rx_file : p->t30_state->tx_file);
1123 ast_cli(fd,
"\nData Statistics:\n");
1124 #if SPANDSP_RELEASE_DATE >= 20090220
1125 ast_cli(fd,
"%-22s : %d\n",
"Tx Pages", stats.pages_tx);
1126 ast_cli(fd,
"%-22s : %d\n",
"Rx Pages", stats.pages_rx);
1128 ast_cli(fd,
"%-22s : %d\n",
"Tx Pages", (s->
details->
caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
1129 ast_cli(fd,
"%-22s : %d\n",
"Rx Pages", (s->
details->
caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
1131 ast_cli(fd,
"%-22s : %d\n",
"Longest Bad Line Run", stats.longest_bad_row_run);
1132 ast_cli(fd,
"%-22s : %d\n",
"Total Bad Lines", stats.bad_rows);
1136 ast_cli(fd,
"\n\n");
1140 static void spandsp_manager_fax_session(
struct mansession *s,
1143 struct ast_str *message_string;
1149 if (!message_string) {
1154 res =
ast_str_append(&message_string, 0,
"SessionNumber: %u\r\n", session->
id);
1158 if (session->
details->
caps & AST_FAX_TECH_GATEWAY) {
1161 if (session->
state == AST_FAX_STATE_UNINITIALIZED) {
1162 goto skip_cap_additions;
1165 t38_gateway_get_transfer_statistics(&span_pvt->t38_gw_state, &stats);
1166 res |=
ast_str_append(&message_string, 0,
"ErrorCorrectionMode: %s\r\n",
1167 stats.error_correcting_mode ?
"yes" :
"no");
1171 stats.pages_transferred + 1);
1172 }
else if (!(session->
details->
caps & AST_FAX_TECH_V21_DETECT)) {
1175 if (session->
state == AST_FAX_STATE_UNINITIALIZED) {
1176 goto skip_cap_additions;
1179 t30_get_transfer_statistics(span_pvt->t30_state, &stats);
1180 res |=
ast_str_append(&message_string, 0,
"ErrorCorrectionMode: %s\r\n",
1181 stats.error_correcting_mode ?
"Yes" :
"No");
1184 res |=
ast_str_append(&message_string, 0,
"ImageResolution: %dx%d\r\n",
1185 stats.x_resolution, stats.y_resolution);
1186 #if SPANDSP_RELEASE_DATE >= 20090220
1188 ((session->
details->
caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
1191 stats.pages_transferred + 1);
1194 session->
details->
caps & AST_FAX_TECH_RECEIVE ? span_pvt->t30_state->rx_file :
1195 span_pvt->t30_state->tx_file);
1196 #if SPANDSP_RELEASE_DATE >= 20090220
1197 res |=
ast_str_append(&message_string, 0,
"PagesTransmitted: %d\r\n",
1199 res |=
ast_str_append(&message_string, 0,
"PagesReceived: %d\r\n",
1202 res |=
ast_str_append(&message_string, 0,
"PagesTransmitted: %d\r\n",
1203 (session->
details->
caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
1204 res |=
ast_str_append(&message_string, 0,
"PagesReceived: %d\r\n",
1205 (session->
details->
caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
1207 res |=
ast_str_append(&message_string, 0,
"TotalBadLines: %d\r\n",
1213 ao2_unlock(session);
1217 ast_free(message_string);
1228 ast_free(message_string);
1232 static char *spandsp_fax_cli_show_stats(
int fd)
1234 ast_mutex_lock(&spandsp_global_stats.lock);
1235 ast_cli(fd,
"\n%-20.20s\n",
"Spandsp G.711");
1236 ast_cli(fd,
"%-20.20s : %d\n",
"Success", spandsp_global_stats.g711.success);
1237 ast_cli(fd,
"%-20.20s : %d\n",
"Switched to T.38", spandsp_global_stats.g711.switched);
1238 ast_cli(fd,
"%-20.20s : %d\n",
"Call Dropped", spandsp_global_stats.g711.call_dropped);
1239 ast_cli(fd,
"%-20.20s : %d\n",
"No FAX", spandsp_global_stats.g711.nofax);
1240 ast_cli(fd,
"%-20.20s : %d\n",
"Negotiation Failed", spandsp_global_stats.g711.neg_failed);
1241 ast_cli(fd,
"%-20.20s : %d\n",
"Train Failure", spandsp_global_stats.g711.failed_to_train);
1242 ast_cli(fd,
"%-20.20s : %d\n",
"Retries Exceeded", spandsp_global_stats.g711.retries_exceeded);
1243 ast_cli(fd,
"%-20.20s : %d\n",
"Protocol Error", spandsp_global_stats.g711.protocol_error);
1244 ast_cli(fd,
"%-20.20s : %d\n",
"TX Protocol Error", spandsp_global_stats.g711.tx_protocol_error);
1245 ast_cli(fd,
"%-20.20s : %d\n",
"RX Protocol Error", spandsp_global_stats.g711.rx_protocol_error);
1246 ast_cli(fd,
"%-20.20s : %d\n",
"File Error", spandsp_global_stats.g711.file_error);
1247 ast_cli(fd,
"%-20.20s : %d\n",
"Memory Error", spandsp_global_stats.g711.mem_error);
1248 ast_cli(fd,
"%-20.20s : %d\n",
"Unknown Error", spandsp_global_stats.g711.unknown_error);
1250 ast_cli(fd,
"\n%-20.20s\n",
"Spandsp T.38");
1251 ast_cli(fd,
"%-20.20s : %d\n",
"Success", spandsp_global_stats.t38.success);
1252 ast_cli(fd,
"%-20.20s : %d\n",
"Call Dropped", spandsp_global_stats.t38.call_dropped);
1253 ast_cli(fd,
"%-20.20s : %d\n",
"No FAX", spandsp_global_stats.t38.nofax);
1254 ast_cli(fd,
"%-20.20s : %d\n",
"Negotiation Failed", spandsp_global_stats.t38.neg_failed);
1255 ast_cli(fd,
"%-20.20s : %d\n",
"Train Failure", spandsp_global_stats.t38.failed_to_train);
1256 ast_cli(fd,
"%-20.20s : %d\n",
"Retries Exceeded", spandsp_global_stats.t38.retries_exceeded);
1257 ast_cli(fd,
"%-20.20s : %d\n",
"Protocol Error", spandsp_global_stats.t38.protocol_error);
1258 ast_cli(fd,
"%-20.20s : %d\n",
"TX Protocol Error", spandsp_global_stats.t38.tx_protocol_error);
1259 ast_cli(fd,
"%-20.20s : %d\n",
"RX Protocol Error", spandsp_global_stats.t38.rx_protocol_error);
1260 ast_cli(fd,
"%-20.20s : %d\n",
"File Error", spandsp_global_stats.t38.file_error);
1261 ast_cli(fd,
"%-20.20s : %d\n",
"Memory Error", spandsp_global_stats.t38.mem_error);
1262 ast_cli(fd,
"%-20.20s : %d\n",
"Unknown Error", spandsp_global_stats.t38.unknown_error);
1263 ast_mutex_unlock(&spandsp_global_stats.lock);
1279 ast_mutex_destroy(&spandsp_global_stats.lock);
1286 ast_mutex_init(&spandsp_global_stats.lock);
1289 ast_log(LOG_ERROR,
"failed to register FAX technology\n");
1294 #if SPANDSP_RELEASE_DATE >= 20120902
1296 span_set_message_handler(NULL, NULL);
1299 span_set_message_handler(NULL);
1306 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
"Spandsp G.711 and T.38 FAX Technologies",
1307 .support_level = AST_MODULE_SUPPORT_EXTENDED,
1310 .enhances =
"res_fax",
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
const ast_string_field result
Main Channel structure associated with a channel.
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
static void spandsp_fax_gateway_cleanup(struct ast_fax_session *s)
gather data and clean up after gateway ends
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
static int spandsp_fax_gw_t30_gen(struct ast_channel *chan, void *data, int len, int samples)
generate T.30 packets sent to the T.30 leg of gateway
String manipulation functions.
static char * spandsp_fax_cli_show_settings(int fd)
Show res_fax_spandsp settings.
const ast_string_field headerinfo
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void ast_fax_tech_unregister(struct ast_fax_tech *tech)
unregister a FAX technology module
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
struct ast_timer * ast_timer_open(void)
Open a timer.
ast_t38_state
Possible T38 states on channels.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static struct ast_frame * spandsp_fax_read(struct ast_fax_session *s)
Read a frame from the spandsp fax stack.
struct ast_channel * chan
void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
Log message at FAX or recommended level.
static int spandsp_fax_gateway_process(struct ast_fax_session *s, const struct ast_frame *f)
process a frame from the bridge
static int spandsp_fax_gateway_start(struct ast_fax_session *s)
activate a spandsp gateway based on the information in the given fax session
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
struct ast_frame_subclass subclass
struct ast_fax_t38_parameters our_t38_parameters
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
struct ast_fax_session_details * details
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
The data communicated between the high level applications and the generic fax function.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct ast_module * module
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code)
Phase E handler callback.
unsigned int transcoding_mmr
unsigned int transcoding_jbig
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
unsigned int pages_transferred
Support for dynamic strings.
static void spandsp_fax_destroy(struct ast_fax_session *s)
Destroy a spandsp fax session.
static int load_module(void)
load res_fax_spandsp
struct ast_fax_documents documents
used to register a FAX technology module with res_fax
static int update_stats(struct spandsp_pvt *p, int completion_code)
union ast_frame::@224 data
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_calloc(num, len)
A wrapper for calloc()
enum ast_fax_modems modems
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Support for logging to various files, console and syslog Configuration in file logger.conf.
Module has failed to load, may be in an inconsistent state.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
static int unload_module(void)
unload res_fax_spandsp
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
static int spandsp_fax_write(struct ast_fax_session *s, const struct ast_frame *f)
Write a frame to the spandsp fax stack.
struct ast_frame ast_null_frame
static void spandsp_log(int level, const char *msg)
Send spandsp log messages to asterisk.
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session's operation
Standard Command Line Interface.
union ast_fax_session_details::@249 option
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
The data required to handle a fax session.
Data structure associated with a single frame of data.
enum ast_control_t38_rate_management rate_management
enum ast_fax_capabilities caps
int ast_fax_tech_register(struct ast_fax_tech *tech)
register a FAX technology module
const ast_string_field resultstr
enum ast_frame_type frametype
const ast_string_field localstationid
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
struct ast_format * format
static void * spandsp_fax_new(struct ast_fax_session *s, struct ast_fax_tech_token *token)
create an instance of the spandsp tech_pvt for a fax session
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
unsigned int fill_bit_removal
struct ast_fax_t38_parameters their_t38_parameters
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Timing source management.
Structure for mutex and tracking information.
static void * spandsp_fax_gw_gen_alloc(struct ast_channel *chan, void *params)
simple routine to allocate data to generator
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.