res_fax_spandsp.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009-2010, Digium, Inc.
  5. *
  6. * Matthew Nicholson <mnicholson@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Spandsp T.38 and G.711 FAX Resource
  21. *
  22. * \author Matthew Nicholson <mnicholson@digium.com>
  23. *
  24. * This module registers the Spandsp FAX technology with the res_fax module.
  25. */
  26. /*** MODULEINFO
  27. <depend>spandsp</depend>
  28. <depend>res_fax</depend>
  29. <support_level>extended</support_level>
  30. <defaultenabled>no</defaultenabled>
  31. ***/
  32. #include "asterisk.h"
  33. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  34. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  35. #include <spandsp.h>
  36. #include <spandsp/version.h>
  37. #include "asterisk/logger.h"
  38. #include "asterisk/module.h"
  39. #include "asterisk/strings.h"
  40. #include "asterisk/cli.h"
  41. #include "asterisk/utils.h"
  42. #include "asterisk/timing.h"
  43. #include "asterisk/astobj2.h"
  44. #include "asterisk/res_fax.h"
  45. #define SPANDSP_FAX_SAMPLES 160
  46. #define SPANDSP_FAX_TIMER_RATE 8000 / SPANDSP_FAX_SAMPLES /* 50 ticks per second, 20ms, 160 samples per second */
  47. static void *spandsp_fax_new(struct ast_fax_session *s, struct ast_fax_tech_token *token);
  48. static void spandsp_fax_destroy(struct ast_fax_session *s);
  49. static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s);
  50. static int spandsp_fax_write(struct ast_fax_session *s, const struct ast_frame *f);
  51. static int spandsp_fax_start(struct ast_fax_session *s);
  52. static int spandsp_fax_cancel(struct ast_fax_session *s);
  53. static int spandsp_fax_switch_to_t38(struct ast_fax_session *s);
  54. static char *spandsp_fax_cli_show_capabilities(int fd);
  55. static char *spandsp_fax_cli_show_session(struct ast_fax_session *s, int fd);
  56. static char *spandsp_fax_cli_show_stats(int fd);
  57. static char *spandsp_fax_cli_show_settings(int fd);
  58. static struct ast_fax_tech spandsp_fax_tech = {
  59. .type = "Spandsp",
  60. .description = "Spandsp FAX Driver",
  61. #if SPANDSP_RELEASE_DATE >= 20090220
  62. /* spandsp 0.0.6 */
  63. .version = SPANDSP_RELEASE_DATETIME_STRING,
  64. #else
  65. /* spandsp 0.0.5
  66. * TODO: maybe we should determine the version better way
  67. */
  68. .version = "pre-20090220",
  69. #endif
  70. .caps = AST_FAX_TECH_AUDIO | AST_FAX_TECH_T38 | AST_FAX_TECH_SEND | AST_FAX_TECH_RECEIVE,
  71. .new_session = spandsp_fax_new,
  72. .destroy_session = spandsp_fax_destroy,
  73. .read = spandsp_fax_read,
  74. .write = spandsp_fax_write,
  75. .start_session = spandsp_fax_start,
  76. .cancel_session = spandsp_fax_cancel,
  77. .switch_to_t38 = spandsp_fax_switch_to_t38,
  78. .cli_show_capabilities = spandsp_fax_cli_show_capabilities,
  79. .cli_show_session = spandsp_fax_cli_show_session,
  80. .cli_show_stats = spandsp_fax_cli_show_stats,
  81. .cli_show_settings = spandsp_fax_cli_show_settings,
  82. };
  83. struct spandsp_fax_stats {
  84. int success;
  85. int nofax;
  86. int neg_failed;
  87. int failed_to_train;
  88. int rx_protocol_error;
  89. int tx_protocol_error;
  90. int protocol_error;
  91. int retries_exceeded;
  92. int file_error;
  93. int mem_error;
  94. int call_dropped;
  95. int unknown_error;
  96. int switched;
  97. };
  98. static struct {
  99. ast_mutex_t lock;
  100. struct spandsp_fax_stats g711;
  101. struct spandsp_fax_stats t38;
  102. } spandsp_global_stats;
  103. struct spandsp_pvt {
  104. unsigned int ist38:1;
  105. unsigned int isdone:1;
  106. fax_state_t fax_state;
  107. t38_terminal_state_t t38_state;
  108. t30_state_t *t30_state;
  109. t38_core_state_t *t38_core_state;
  110. struct spandsp_fax_stats *stats;
  111. struct ast_timer *timer;
  112. AST_LIST_HEAD(frame_queue, ast_frame) read_frames;
  113. };
  114. static void session_destroy(struct spandsp_pvt *p);
  115. static int t38_tx_packet_handler(t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count);
  116. static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code);
  117. static void spandsp_log(int level, const char *msg);
  118. static int update_stats(struct spandsp_pvt *p, int completion_code);
  119. static int spandsp_modems(struct ast_fax_session_details *details);
  120. static void set_logging(logging_state_t *state, struct ast_fax_session_details *details);
  121. static void set_local_info(t30_state_t *t30_state, struct ast_fax_session_details *details);
  122. static void set_file(t30_state_t *t30_state, struct ast_fax_session_details *details);
  123. static void set_ecm(t30_state_t *t30_state, struct ast_fax_session_details *details);
  124. static void session_destroy(struct spandsp_pvt *p)
  125. {
  126. struct ast_frame *f;
  127. t30_terminate(p->t30_state);
  128. p->isdone = 1;
  129. ast_timer_close(p->timer);
  130. fax_release(&p->fax_state);
  131. t38_terminal_release(&p->t38_state);
  132. while ((f = AST_LIST_REMOVE_HEAD(&p->read_frames, frame_list))) {
  133. ast_frfree(f);
  134. }
  135. }
  136. /*! \brief
  137. *
  138. */
  139. static int t38_tx_packet_handler(t38_core_state_t *t38_core_state, void *data, const uint8_t *buf, int len, int count)
  140. {
  141. struct spandsp_pvt *p = data;
  142. struct ast_frame fax_frame = {
  143. .frametype = AST_FRAME_MODEM,
  144. .subclass.integer = AST_MODEM_T38,
  145. .src = "res_fax_spandsp_t38",
  146. };
  147. struct ast_frame *f = &fax_frame;
  148. /* TODO: Asterisk does not provide means of resending the same packet multiple
  149. times so count is ignored at the moment */
  150. AST_FRAME_SET_BUFFER(f, buf, 0, len);
  151. if (!(f = ast_frisolate(f))) {
  152. return -1;
  153. }
  154. /* no need to lock, this all runs in the same thread */
  155. AST_LIST_INSERT_TAIL(&p->read_frames, f, frame_list);
  156. return 0;
  157. }
  158. static int update_stats(struct spandsp_pvt *p, int completion_code)
  159. {
  160. switch (completion_code) {
  161. case T30_ERR_OK:
  162. ast_atomic_fetchadd_int(&p->stats->success, 1);
  163. break;
  164. /* Link problems */
  165. case T30_ERR_CEDTONE: /*! The CED tone exceeded 5s */
  166. case T30_ERR_T0_EXPIRED: /*! Timed out waiting for initial communication */
  167. case T30_ERR_T1_EXPIRED: /*! Timed out waiting for the first message */
  168. case T30_ERR_T3_EXPIRED: /*! Timed out waiting for procedural interrupt */
  169. case T30_ERR_HDLC_CARRIER: /*! The HDLC carrier did not stop in a timely manner */
  170. case T30_ERR_CANNOT_TRAIN: /*! Failed to train with any of the compatible modems */
  171. ast_atomic_fetchadd_int(&p->stats->failed_to_train, 1);
  172. break;
  173. case T30_ERR_OPER_INT_FAIL: /*! Operator intervention failed */
  174. case T30_ERR_INCOMPATIBLE: /*! Far end is not compatible */
  175. case T30_ERR_RX_INCAPABLE: /*! Far end is not able to receive */
  176. case T30_ERR_TX_INCAPABLE: /*! Far end is not able to transmit */
  177. case T30_ERR_NORESSUPPORT: /*! Far end cannot receive at the resolution of the image */
  178. case T30_ERR_NOSIZESUPPORT: /*! Far end cannot receive at the size of image */
  179. ast_atomic_fetchadd_int(&p->stats->neg_failed, 1);
  180. break;
  181. case T30_ERR_UNEXPECTED: /*! Unexpected message received */
  182. ast_atomic_fetchadd_int(&p->stats->protocol_error, 1);
  183. break;
  184. /* Phase E status values returned to a transmitter */
  185. case T30_ERR_TX_BADDCS: /*! Received bad response to DCS or training */
  186. case T30_ERR_TX_BADPG: /*! Received a DCN from remote after sending a page */
  187. case T30_ERR_TX_ECMPHD: /*! Invalid ECM response received from receiver */
  188. case T30_ERR_TX_GOTDCN: /*! Received a DCN while waiting for a DIS */
  189. case T30_ERR_TX_INVALRSP: /*! Invalid response after sending a page */
  190. case T30_ERR_TX_NODIS: /*! Received other than DIS while waiting for DIS */
  191. case T30_ERR_TX_PHBDEAD: /*! Received no response to DCS, training or TCF */
  192. case T30_ERR_TX_PHDDEAD: /*! No response after sending a page */
  193. case T30_ERR_TX_T5EXP: /*! Timed out waiting for receiver ready (ECM mode) */
  194. ast_atomic_fetchadd_int(&p->stats->tx_protocol_error, 1);
  195. break;
  196. /* Phase E status values returned to a receiver */
  197. case T30_ERR_RX_ECMPHD: /*! Invalid ECM response received from transmitter */
  198. case T30_ERR_RX_GOTDCS: /*! DCS received while waiting for DTC */
  199. case T30_ERR_RX_INVALCMD: /*! Unexpected command after page received */
  200. case T30_ERR_RX_NOCARRIER: /*! Carrier lost during fax receive */
  201. case T30_ERR_RX_NOEOL: /*! Timed out while waiting for EOL (end Of line) */
  202. ast_atomic_fetchadd_int(&p->stats->rx_protocol_error, 1);
  203. break;
  204. case T30_ERR_RX_NOFAX: /*! Timed out while waiting for first line */
  205. ast_atomic_fetchadd_int(&p->stats->nofax, 1);
  206. break;
  207. case T30_ERR_RX_T2EXPDCN: /*! Timer T2 expired while waiting for DCN */
  208. case T30_ERR_RX_T2EXPD: /*! Timer T2 expired while waiting for phase D */
  209. case T30_ERR_RX_T2EXPFAX: /*! Timer T2 expired while waiting for fax page */
  210. case T30_ERR_RX_T2EXPMPS: /*! Timer T2 expired while waiting for next fax page */
  211. case T30_ERR_RX_T2EXPRR: /*! Timer T2 expired while waiting for RR command */
  212. case T30_ERR_RX_T2EXP: /*! Timer T2 expired while waiting for NSS, DCS or MCF */
  213. case T30_ERR_RX_DCNWHY: /*! Unexpected DCN while waiting for DCS or DIS */
  214. case T30_ERR_RX_DCNDATA: /*! Unexpected DCN while waiting for image data */
  215. case T30_ERR_RX_DCNFAX: /*! Unexpected DCN while waiting for EOM, EOP or MPS */
  216. case T30_ERR_RX_DCNPHD: /*! Unexpected DCN after EOM or MPS sequence */
  217. case T30_ERR_RX_DCNRRD: /*! Unexpected DCN after RR/RNR sequence */
  218. case T30_ERR_RX_DCNNORTN: /*! Unexpected DCN after requested retransmission */
  219. ast_atomic_fetchadd_int(&p->stats->rx_protocol_error, 1);
  220. break;
  221. /* TIFF file problems */
  222. case T30_ERR_FILEERROR: /*! TIFF/F file cannot be opened */
  223. case T30_ERR_NOPAGE: /*! TIFF/F page not found */
  224. case T30_ERR_BADTIFF: /*! TIFF/F format is not compatible */
  225. case T30_ERR_BADPAGE: /*! TIFF/F page number tag missing */
  226. case T30_ERR_BADTAG: /*! Incorrect values for TIFF/F tags */
  227. case T30_ERR_BADTIFFHDR: /*! Bad TIFF/F header - incorrect values in fields */
  228. ast_atomic_fetchadd_int(&p->stats->file_error, 1);
  229. break;
  230. case T30_ERR_NOMEM: /*! Cannot allocate memory for more pages */
  231. ast_atomic_fetchadd_int(&p->stats->mem_error, 1);
  232. break;
  233. /* General problems */
  234. case T30_ERR_RETRYDCN: /*! Disconnected after permitted retries */
  235. ast_atomic_fetchadd_int(&p->stats->retries_exceeded, 1);
  236. break;
  237. case T30_ERR_CALLDROPPED: /*! The call dropped prematurely */
  238. ast_atomic_fetchadd_int(&p->stats->call_dropped, 1);
  239. break;
  240. /* Feature negotiation issues */
  241. case T30_ERR_NOPOLL: /*! Poll not accepted */
  242. case T30_ERR_IDENT_UNACCEPTABLE: /*! Far end's ident is not acceptable */
  243. case T30_ERR_SUB_UNACCEPTABLE: /*! Far end's sub-address is not acceptable */
  244. case T30_ERR_SEP_UNACCEPTABLE: /*! Far end's selective polling address is not acceptable */
  245. case T30_ERR_PSA_UNACCEPTABLE: /*! Far end's polled sub-address is not acceptable */
  246. case T30_ERR_SID_UNACCEPTABLE: /*! Far end's sender identification is not acceptable */
  247. case T30_ERR_PWD_UNACCEPTABLE: /*! Far end's password is not acceptable */
  248. case T30_ERR_TSA_UNACCEPTABLE: /*! Far end's transmitting subscriber internet address is not acceptable */
  249. case T30_ERR_IRA_UNACCEPTABLE: /*! Far end's internet routing address is not acceptable */
  250. case T30_ERR_CIA_UNACCEPTABLE: /*! Far end's calling subscriber internet address is not acceptable */
  251. case T30_ERR_ISP_UNACCEPTABLE: /*! Far end's internet selective polling address is not acceptable */
  252. case T30_ERR_CSA_UNACCEPTABLE: /*! Far end's called subscriber internet address is not acceptable */
  253. ast_atomic_fetchadd_int(&p->stats->neg_failed, 1);
  254. break;
  255. default:
  256. ast_atomic_fetchadd_int(&p->stats->unknown_error, 1);
  257. ast_log(LOG_WARNING, "unknown FAX session result '%d' (%s)\n", completion_code, t30_completion_code_to_str(completion_code));
  258. return -1;
  259. }
  260. return 0;
  261. }
  262. /*! \brief Phase E handler callback.
  263. * \param t30_state the span t30 state
  264. * \param data this will be the ast_fax_session
  265. * \param completion_code the result of the fax session
  266. *
  267. * This function pulls stats from the spandsp stack and stores them for res_fax
  268. * to use later.
  269. */
  270. static void t30_phase_e_handler(t30_state_t *t30_state, void *data, int completion_code)
  271. {
  272. struct ast_fax_session *s = data;
  273. struct spandsp_pvt *p = s->tech_pvt;
  274. char headerinfo[T30_MAX_PAGE_HEADER_INFO + 1];
  275. const char *c;
  276. t30_stats_t stats;
  277. ast_debug(5, "FAX session '%d' entering phase E\n", s->id);
  278. p->isdone = 1;
  279. update_stats(p, completion_code);
  280. t30_get_transfer_statistics(t30_state, &stats);
  281. if (completion_code == T30_ERR_OK) {
  282. ast_string_field_set(s->details, result, "SUCCESS");
  283. } else {
  284. ast_string_field_set(s->details, result, "FAILED");
  285. ast_string_field_set(s->details, error, t30_completion_code_to_str(completion_code));
  286. }
  287. ast_string_field_set(s->details, resultstr, t30_completion_code_to_str(completion_code));
  288. ast_debug(5, "FAX session '%d' completed with result: %s (%s)\n", s->id, s->details->result, s->details->resultstr);
  289. if ((c = t30_get_tx_ident(t30_state))) {
  290. ast_string_field_set(s->details, localstationid, c);
  291. }
  292. if ((c = t30_get_rx_ident(t30_state))) {
  293. ast_string_field_set(s->details, remotestationid, c);
  294. }
  295. #if SPANDSP_RELEASE_DATE >= 20090220
  296. s->details->pages_transferred = (s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx;
  297. #else
  298. s->details->pages_transferred = stats.pages_transferred;
  299. #endif
  300. ast_string_field_build(s->details, transfer_rate, "%d", stats.bit_rate);
  301. ast_string_field_build(s->details, resolution, "%dx%d", stats.x_resolution, stats.y_resolution);
  302. t30_get_tx_page_header_info(t30_state, headerinfo);
  303. ast_string_field_set(s->details, headerinfo, headerinfo);
  304. }
  305. /*! \brief Send spandsp log messages to asterisk.
  306. * \param level the spandsp logging level
  307. * \param msg the log message
  308. *
  309. * \note This function is a callback function called by spandsp.
  310. */
  311. static void spandsp_log(int level, const char *msg)
  312. {
  313. if (level == SPAN_LOG_ERROR) {
  314. ast_log(LOG_ERROR, "%s", msg);
  315. } else if (level == SPAN_LOG_WARNING) {
  316. ast_log(LOG_WARNING, "%s", msg);
  317. } else {
  318. ast_fax_log(LOG_DEBUG, msg);
  319. }
  320. }
  321. static void set_logging(logging_state_t *state, struct ast_fax_session_details *details)
  322. {
  323. int level = SPAN_LOG_WARNING;
  324. if (details->option.debug) {
  325. level = SPAN_LOG_DEBUG_3;
  326. }
  327. span_log_set_message_handler(state, spandsp_log);
  328. span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
  329. }
  330. static void set_local_info(t30_state_t *t30_state, struct ast_fax_session_details *details)
  331. {
  332. if (!ast_strlen_zero(details->localstationid)) {
  333. t30_set_tx_ident(t30_state, details->localstationid);
  334. }
  335. if (!ast_strlen_zero(details->headerinfo)) {
  336. t30_set_tx_page_header_info(t30_state, details->headerinfo);
  337. }
  338. }
  339. static void set_file(t30_state_t *t30_state, struct ast_fax_session_details *details)
  340. {
  341. if (details->caps & AST_FAX_TECH_RECEIVE) {
  342. t30_set_rx_file(t30_state, AST_LIST_FIRST(&details->documents)->filename, -1);
  343. } else {
  344. /* if not AST_FAX_TECH_RECEIVE, assume AST_FAX_TECH_SEND, this
  345. * should be safe because we ensure either RECEIVE or SEND is
  346. * indicated in spandsp_fax_new() */
  347. t30_set_tx_file(t30_state, AST_LIST_FIRST(&details->documents)->filename, -1, -1);
  348. }
  349. }
  350. static void set_ecm(t30_state_t *t30_state, struct ast_fax_session_details *details)
  351. {
  352. t30_set_ecm_capability(t30_state, details->option.ecm);
  353. t30_set_supported_compressions(t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
  354. }
  355. static int spandsp_modems(struct ast_fax_session_details *details)
  356. {
  357. int modems = 0;
  358. if (AST_FAX_MODEM_V17 & details->modems) {
  359. modems |= T30_SUPPORT_V17;
  360. }
  361. if (AST_FAX_MODEM_V27 & details->modems) {
  362. modems |= T30_SUPPORT_V27TER;
  363. }
  364. if (AST_FAX_MODEM_V29 & details->modems) {
  365. modems |= T30_SUPPORT_V29;
  366. }
  367. if (AST_FAX_MODEM_V34 & details->modems) {
  368. #if defined(T30_SUPPORT_V34)
  369. modems |= T30_SUPPORT_V34;
  370. #elif defined(T30_SUPPORT_V34HDX)
  371. modems |= T30_SUPPORT_V34HDX;
  372. #else
  373. ast_log(LOG_WARNING, "v34 not supported in this version of spandsp\n");
  374. #endif
  375. }
  376. return modems;
  377. }
  378. /*! \brief create an instance of the spandsp tech_pvt for a fax session */
  379. static void *spandsp_fax_new(struct ast_fax_session *s, struct ast_fax_tech_token *token)
  380. {
  381. struct spandsp_pvt *p;
  382. int caller_mode;
  383. if ((!(p = ast_calloc(1, sizeof(*p))))) {
  384. ast_log(LOG_ERROR, "Cannot initialize the spandsp private FAX technology structure.\n");
  385. goto e_return;
  386. }
  387. AST_LIST_HEAD_INIT(&p->read_frames);
  388. if (s->details->caps & AST_FAX_TECH_RECEIVE) {
  389. caller_mode = 0;
  390. } else if (s->details->caps & AST_FAX_TECH_SEND) {
  391. caller_mode = 1;
  392. } else {
  393. ast_log(LOG_ERROR, "Are we sending or receiving? The FAX requirements (capabilities: 0x%X) were not properly set.\n", s->details->caps);
  394. goto e_free;
  395. }
  396. if (!(p->timer = ast_timer_open())) {
  397. ast_log(LOG_ERROR, "Channel '%s' FAX session '%d' failed to create timing source.\n", s->channame, s->id);
  398. goto e_free;
  399. }
  400. s->fd = ast_timer_fd(p->timer);
  401. p->stats = &spandsp_global_stats.g711;
  402. if (s->details->caps & AST_FAX_TECH_T38) {
  403. if ((s->details->caps & AST_FAX_TECH_AUDIO) == 0) {
  404. /* audio mode was not requested, start in T.38 mode */
  405. p->ist38 = 1;
  406. p->stats = &spandsp_global_stats.t38;
  407. }
  408. /* init t38 stuff */
  409. t38_terminal_init(&p->t38_state, caller_mode, t38_tx_packet_handler, p);
  410. set_logging(&p->t38_state.logging, s->details);
  411. }
  412. if (s->details->caps & AST_FAX_TECH_AUDIO) {
  413. /* init audio stuff */
  414. fax_init(&p->fax_state, caller_mode);
  415. set_logging(&p->fax_state.logging, s->details);
  416. }
  417. s->state = AST_FAX_STATE_INITIALIZED;
  418. return p;
  419. e_free:
  420. ast_free(p);
  421. e_return:
  422. return NULL;
  423. }
  424. /*! \brief Destroy a spandsp fax session.
  425. */
  426. static void spandsp_fax_destroy(struct ast_fax_session *s)
  427. {
  428. struct spandsp_pvt *p = s->tech_pvt;
  429. session_destroy(p);
  430. ast_free(p);
  431. s->tech_pvt = NULL;
  432. s->fd = -1;
  433. }
  434. /*! \brief Read a frame from the spandsp fax stack.
  435. */
  436. static struct ast_frame *spandsp_fax_read(struct ast_fax_session *s)
  437. {
  438. struct spandsp_pvt *p = s->tech_pvt;
  439. uint8_t buffer[AST_FRIENDLY_OFFSET + SPANDSP_FAX_SAMPLES * sizeof(uint16_t)];
  440. int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
  441. int samples;
  442. struct ast_frame fax_frame = {
  443. .frametype = AST_FRAME_VOICE,
  444. .subclass.codec = AST_FORMAT_SLINEAR,
  445. .src = "res_fax_spandsp_g711",
  446. };
  447. struct ast_frame *f = &fax_frame;
  448. ast_timer_ack(p->timer, 1);
  449. /* XXX do we need to lock here? */
  450. if (p->isdone) {
  451. s->state = AST_FAX_STATE_COMPLETE;
  452. ast_debug(5, "FAX session '%d' is complete.\n", s->id);
  453. return NULL;
  454. }
  455. if (p->ist38) {
  456. t38_terminal_send_timeout(&p->t38_state, SPANDSP_FAX_SAMPLES);
  457. if ((f = AST_LIST_REMOVE_HEAD(&p->read_frames, frame_list))) {
  458. return f;
  459. }
  460. } else {
  461. if ((samples = fax_tx(&p->fax_state, buf, SPANDSP_FAX_SAMPLES)) > 0) {
  462. f->samples = samples;
  463. AST_FRAME_SET_BUFFER(f, buffer, AST_FRIENDLY_OFFSET, samples * sizeof(int16_t));
  464. return ast_frisolate(f);
  465. }
  466. }
  467. return &ast_null_frame;
  468. }
  469. /*! \brief Write a frame to the spandsp fax stack.
  470. * \param s a fax session
  471. * \param f the frame to write
  472. *
  473. * \note res_fax does not currently use the return value of this function.
  474. * Also the fax_rx() function never fails.
  475. *
  476. * \retval 0 success
  477. * \retval -1 failure
  478. */
  479. static int spandsp_fax_write(struct ast_fax_session *s, const struct ast_frame *f)
  480. {
  481. struct spandsp_pvt *p = s->tech_pvt;
  482. /* XXX do we need to lock here? */
  483. if (s->state == AST_FAX_STATE_COMPLETE) {
  484. ast_log(LOG_WARNING, "FAX session '%d' is in the '%s' state.\n", s->id, ast_fax_state_to_str(s->state));
  485. return -1;
  486. }
  487. if (p->ist38) {
  488. return t38_core_rx_ifp_packet(p->t38_core_state, f->data.ptr, f->datalen, f->seqno);
  489. } else {
  490. return fax_rx(&p->fax_state, f->data.ptr, f->samples);
  491. }
  492. }
  493. /*! \brief */
  494. static int spandsp_fax_start(struct ast_fax_session *s)
  495. {
  496. struct spandsp_pvt *p = s->tech_pvt;
  497. s->state = AST_FAX_STATE_OPEN;
  498. if (p->ist38) {
  499. #if SPANDSP_RELEASE_DATE >= 20080725
  500. /* for spandsp shaphots 0.0.6 and higher */
  501. p->t30_state = &p->t38_state.t30;
  502. p->t38_core_state = &p->t38_state.t38_fe.t38;
  503. #else
  504. /* for spandsp releases 0.0.5 */
  505. p->t30_state = &p->t38_state.t30_state;
  506. p->t38_core_state = &p->t38_state.t38;
  507. #endif
  508. } else {
  509. #if SPANDSP_RELEASE_DATE >= 20080725
  510. /* for spandsp shaphots 0.0.6 and higher */
  511. p->t30_state = &p->fax_state.t30;
  512. #else
  513. /* for spandsp release 0.0.5 */
  514. p->t30_state = &p->fax_state.t30_state;
  515. #endif
  516. }
  517. set_logging(&p->t30_state->logging, s->details);
  518. /* set some parameters */
  519. set_local_info(p->t30_state, s->details);
  520. set_file(p->t30_state, s->details);
  521. set_ecm(p->t30_state, s->details);
  522. t30_set_supported_modems(p->t30_state, spandsp_modems(s->details));
  523. /* perhaps set_transmit_on_idle() should be called */
  524. t30_set_phase_e_handler(p->t30_state, t30_phase_e_handler, s);
  525. /* set T.38 parameters */
  526. if (p->ist38) {
  527. set_logging(&p->t38_core_state->logging, s->details);
  528. t38_set_max_datagram_size(p->t38_core_state, s->details->their_t38_parameters.max_ifp);
  529. if (s->details->their_t38_parameters.fill_bit_removal) {
  530. t38_set_fill_bit_removal(p->t38_core_state, TRUE);
  531. }
  532. if (s->details->their_t38_parameters.transcoding_mmr) {
  533. t38_set_mmr_transcoding(p->t38_core_state, TRUE);
  534. }
  535. if (s->details->their_t38_parameters.transcoding_jbig) {
  536. t38_set_jbig_transcoding(p->t38_core_state, TRUE);
  537. }
  538. } else {
  539. /* have the fax stack generate silence if it has no data to send */
  540. fax_set_transmit_on_idle(&p->fax_state, 1);
  541. }
  542. /* start the timer */
  543. if (ast_timer_set_rate(p->timer, SPANDSP_FAX_TIMER_RATE)) {
  544. ast_log(LOG_ERROR, "FAX session '%d' error setting rate on timing source.\n", s->id);
  545. return -1;
  546. }
  547. s->state = AST_FAX_STATE_ACTIVE;
  548. return 0;
  549. }
  550. /*! \brief */
  551. static int spandsp_fax_cancel(struct ast_fax_session *s)
  552. {
  553. struct spandsp_pvt *p = s->tech_pvt;
  554. t30_terminate(p->t30_state);
  555. p->isdone = 1;
  556. return 0;
  557. }
  558. /*! \brief */
  559. static int spandsp_fax_switch_to_t38(struct ast_fax_session *s)
  560. {
  561. struct spandsp_pvt *p = s->tech_pvt;
  562. /* prevent the phase E handler from running, this is not a real termination */
  563. t30_set_phase_e_handler(p->t30_state, NULL, NULL);
  564. t30_terminate(p->t30_state);
  565. s->details->option.switch_to_t38 = 1;
  566. ast_atomic_fetchadd_int(&p->stats->switched, 1);
  567. p->ist38 = 1;
  568. p->stats = &spandsp_global_stats.t38;
  569. spandsp_fax_start(s);
  570. return 0;
  571. }
  572. /*! \brief */
  573. static char *spandsp_fax_cli_show_capabilities(int fd)
  574. {
  575. ast_cli(fd, "SEND RECEIVE T.38 G.711\n\n");
  576. return CLI_SUCCESS;
  577. }
  578. /*! \brief */
  579. static char *spandsp_fax_cli_show_session(struct ast_fax_session *s, int fd)
  580. {
  581. struct spandsp_pvt *p = s->tech_pvt;
  582. t30_stats_t stats;
  583. ao2_lock(s);
  584. ast_cli(fd, "%-22s : %d\n", "session", s->id);
  585. ast_cli(fd, "%-22s : %s\n", "operation", (s->details->caps & AST_FAX_TECH_RECEIVE) ? "Receive" : "Transmit");
  586. ast_cli(fd, "%-22s : %s\n", "state", ast_fax_state_to_str(s->state));
  587. if (s->state != AST_FAX_STATE_UNINITIALIZED) {
  588. t30_get_transfer_statistics(p->t30_state, &stats);
  589. ast_cli(fd, "%-22s : %s\n", "Last Status", t30_completion_code_to_str(stats.current_status));
  590. ast_cli(fd, "%-22s : %s\n", "ECM Mode", stats.error_correcting_mode ? "Yes" : "No");
  591. ast_cli(fd, "%-22s : %d\n", "Data Rate", stats.bit_rate);
  592. ast_cli(fd, "%-22s : %dx%d\n", "Image Resolution", stats.x_resolution, stats.y_resolution);
  593. #if SPANDSP_RELEASE_DATE >= 20090220
  594. ast_cli(fd, "%-22s : %d\n", "Page Number", ((s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_rx : stats.pages_tx) + 1);
  595. #else
  596. ast_cli(fd, "%-22s : %d\n", "Page Number", stats.pages_transferred + 1);
  597. #endif
  598. 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);
  599. ast_cli(fd, "\nData Statistics:\n");
  600. #if SPANDSP_RELEASE_DATE >= 20090220
  601. ast_cli(fd, "%-22s : %d\n", "Tx Pages", stats.pages_tx);
  602. ast_cli(fd, "%-22s : %d\n", "Rx Pages", stats.pages_rx);
  603. #else
  604. ast_cli(fd, "%-22s : %d\n", "Tx Pages", (s->details->caps & AST_FAX_TECH_SEND) ? stats.pages_transferred : 0);
  605. ast_cli(fd, "%-22s : %d\n", "Rx Pages", (s->details->caps & AST_FAX_TECH_RECEIVE) ? stats.pages_transferred : 0);
  606. #endif
  607. ast_cli(fd, "%-22s : %d\n", "Longest Bad Line Run", stats.longest_bad_row_run);
  608. ast_cli(fd, "%-22s : %d\n", "Total Bad Lines", stats.bad_rows);
  609. }
  610. ao2_unlock(s);
  611. ast_cli(fd, "\n\n");
  612. return CLI_SUCCESS;
  613. }
  614. /*! \brief */
  615. static char *spandsp_fax_cli_show_stats(int fd)
  616. {
  617. ast_mutex_lock(&spandsp_global_stats.lock);
  618. ast_cli(fd, "\n%-20.20s\n", "Spandsp G.711");
  619. ast_cli(fd, "%-20.20s : %d\n", "Success", spandsp_global_stats.g711.success);
  620. ast_cli(fd, "%-20.20s : %d\n", "Switched to T.38", spandsp_global_stats.g711.switched);
  621. ast_cli(fd, "%-20.20s : %d\n", "Call Dropped", spandsp_global_stats.g711.call_dropped);
  622. ast_cli(fd, "%-20.20s : %d\n", "No FAX", spandsp_global_stats.g711.nofax);
  623. ast_cli(fd, "%-20.20s : %d\n", "Negotiation Failed", spandsp_global_stats.g711.neg_failed);
  624. ast_cli(fd, "%-20.20s : %d\n", "Train Failure", spandsp_global_stats.g711.failed_to_train);
  625. ast_cli(fd, "%-20.20s : %d\n", "Retries Exceeded", spandsp_global_stats.g711.retries_exceeded);
  626. ast_cli(fd, "%-20.20s : %d\n", "Protocol Error", spandsp_global_stats.g711.protocol_error);
  627. ast_cli(fd, "%-20.20s : %d\n", "TX Protocol Error", spandsp_global_stats.g711.tx_protocol_error);
  628. ast_cli(fd, "%-20.20s : %d\n", "RX Protocol Error", spandsp_global_stats.g711.rx_protocol_error);
  629. ast_cli(fd, "%-20.20s : %d\n", "File Error", spandsp_global_stats.g711.file_error);
  630. ast_cli(fd, "%-20.20s : %d\n", "Memory Error", spandsp_global_stats.g711.mem_error);
  631. ast_cli(fd, "%-20.20s : %d\n", "Unknown Error", spandsp_global_stats.g711.unknown_error);
  632. ast_cli(fd, "\n%-20.20s\n", "Spandsp T.38");
  633. ast_cli(fd, "%-20.20s : %d\n", "Success", spandsp_global_stats.t38.success);
  634. ast_cli(fd, "%-20.20s : %d\n", "Call Dropped", spandsp_global_stats.t38.call_dropped);
  635. ast_cli(fd, "%-20.20s : %d\n", "No FAX", spandsp_global_stats.t38.nofax);
  636. ast_cli(fd, "%-20.20s : %d\n", "Negotiation Failed", spandsp_global_stats.t38.neg_failed);
  637. ast_cli(fd, "%-20.20s : %d\n", "Train Failure", spandsp_global_stats.t38.failed_to_train);
  638. ast_cli(fd, "%-20.20s : %d\n", "Retries Exceeded", spandsp_global_stats.t38.retries_exceeded);
  639. ast_cli(fd, "%-20.20s : %d\n", "Protocol Error", spandsp_global_stats.t38.protocol_error);
  640. ast_cli(fd, "%-20.20s : %d\n", "TX Protocol Error", spandsp_global_stats.t38.tx_protocol_error);
  641. ast_cli(fd, "%-20.20s : %d\n", "RX Protocol Error", spandsp_global_stats.t38.rx_protocol_error);
  642. ast_cli(fd, "%-20.20s : %d\n", "File Error", spandsp_global_stats.t38.file_error);
  643. ast_cli(fd, "%-20.20s : %d\n", "Memory Error", spandsp_global_stats.t38.mem_error);
  644. ast_cli(fd, "%-20.20s : %d\n", "Unknown Error", spandsp_global_stats.t38.unknown_error);
  645. ast_mutex_unlock(&spandsp_global_stats.lock);
  646. return CLI_SUCCESS;
  647. }
  648. /*! \brief Show res_fax_spandsp settings */
  649. static char *spandsp_fax_cli_show_settings(int fd)
  650. {
  651. /* no settings at the moment */
  652. return CLI_SUCCESS;
  653. }
  654. /*! \brief unload res_fax_spandsp */
  655. static int unload_module(void)
  656. {
  657. ast_fax_tech_unregister(&spandsp_fax_tech);
  658. ast_mutex_destroy(&spandsp_global_stats.lock);
  659. return AST_MODULE_LOAD_SUCCESS;
  660. }
  661. /*! \brief load res_fax_spandsp */
  662. static int load_module(void)
  663. {
  664. ast_mutex_init(&spandsp_global_stats.lock);
  665. spandsp_fax_tech.module = ast_module_info->self;
  666. if (ast_fax_tech_register(&spandsp_fax_tech) < 0) {
  667. ast_log(LOG_ERROR, "failed to register FAX technology\n");
  668. return AST_MODULE_LOAD_DECLINE;
  669. }
  670. /* prevent logging to stderr */
  671. span_set_message_handler(NULL);
  672. return AST_MODULE_LOAD_SUCCESS;
  673. }
  674. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Spandsp G.711 and T.38 FAX Technologies",
  675. .load = load_module,
  676. .unload = unload_module,
  677. );