1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * t30_api.c - ITU T.30 FAX transfer processing
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*! \file */
27
28 #if defined(HAVE_CONFIG_H)
29 #include "config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <inttypes.h>
35 #include <string.h>
36 #include <fcntl.h>
37 #include <time.h>
38 #if defined(HAVE_TGMATH_H)
39 #include <tgmath.h>
40 #endif
41 #if defined(HAVE_MATH_H)
42 #include <math.h>
43 #endif
44 #if defined(HAVE_STDBOOL_H)
45 #include <stdbool.h>
46 #else
47 #include "spandsp/stdbool.h"
48 #endif
49 #include "floating_fudge.h"
50 #include <tiffio.h>
51
52 #include "spandsp/telephony.h"
53 #include "spandsp/alloc.h"
54 #include "spandsp/logging.h"
55 #include "spandsp/bit_operations.h"
56 #include "spandsp/queue.h"
57 #include "spandsp/power_meter.h"
58 #include "spandsp/complex.h"
59 #include "spandsp/tone_generate.h"
60 #include "spandsp/async.h"
61 #include "spandsp/hdlc.h"
62 #include "spandsp/fsk.h"
63 #include "spandsp/v29rx.h"
64 #include "spandsp/v29tx.h"
65 #include "spandsp/v27ter_rx.h"
66 #include "spandsp/v27ter_tx.h"
67 #include "spandsp/timezone.h"
68 #include "spandsp/t4_rx.h"
69 #include "spandsp/t4_tx.h"
70 #include "spandsp/image_translate.h"
71 #include "spandsp/t81_t82_arith_coding.h"
72 #include "spandsp/t85.h"
73 #include "spandsp/t42.h"
74 #include "spandsp/t43.h"
75 #include "spandsp/t4_t6_decode.h"
76 #include "spandsp/t4_t6_encode.h"
77 #include "spandsp/t30_fcf.h"
78 #include "spandsp/t35.h"
79 #include "spandsp/t30.h"
80 #include "spandsp/t30_api.h"
81 #include "spandsp/t30_logging.h"
82
83 #include "spandsp/private/logging.h"
84 #include "spandsp/private/timezone.h"
85 #include "spandsp/private/t81_t82_arith_coding.h"
86 #include "spandsp/private/t85.h"
87 #include "spandsp/private/t42.h"
88 #include "spandsp/private/t43.h"
89 #include "spandsp/private/t4_t6_decode.h"
90 #include "spandsp/private/t4_t6_encode.h"
91 #include "spandsp/private/image_translate.h"
92 #include "spandsp/private/t4_rx.h"
93 #include "spandsp/private/t4_tx.h"
94 #include "spandsp/private/t30.h"
95
96 #include "t30_local.h"
97
t33_sub_address_extract_field(uint8_t num[21],const uint8_t t33[],int field_no)98 SPAN_DECLARE(int) t33_sub_address_extract_field(uint8_t num[21], const uint8_t t33[], int field_no)
99 {
100 int i;
101 int j;
102 int k;
103 int ch;
104 int type;
105
106 num[0] = '\0';
107 k = 0;
108 for (i = 0; t33[i]; )
109 {
110 if (k++ == field_no)
111 {
112 ch = t33[i++];
113 j = 0;
114 if (ch != '#')
115 {
116 num[j++] = ch;
117 type = T33_EXT;
118 }
119 else
120 {
121 type = T33_SST;
122 }
123 /*endif*/
124 while (t33[i])
125 {
126 ch = t33[i++];
127 if (ch == '#')
128 break;
129 /*endif*/
130 num[j++] = ch;
131 if (j >= 20)
132 return -1;
133 /*endif*/
134 }
135 /*endwhile*/
136 num[j] = '\0';
137 return type;
138 }
139 /*endif*/
140 /* Skip this field */
141 i++;
142 while (t33[i])
143 {
144 if (t33[i++] == '#')
145 break;
146 /*endif*/
147 }
148 /*endwhile*/
149 }
150 /*endfor*/
151 return T33_NONE;
152 }
153 /*- End of function --------------------------------------------------------*/
154
t33_sub_address_add_field(uint8_t t33[],const uint8_t field[],int type)155 SPAN_DECLARE(void) t33_sub_address_add_field(uint8_t t33[], const uint8_t field[], int type)
156 {
157 if (t33[0] != '\0')
158 strcat((char *) t33, "#");
159 /*endif*/
160 if (type == T33_SST)
161 strcat((char *) t33, "#");
162 /*endif*/
163 strcat((char *) t33, (const char *) field);
164 }
165 /*- End of function --------------------------------------------------------*/
166
t30_set_tx_ident(t30_state_t * s,const char * id)167 SPAN_DECLARE(int) t30_set_tx_ident(t30_state_t *s, const char *id)
168 {
169 if (id == NULL)
170 {
171 s->tx_info.ident[0] = '\0';
172 return 0;
173 }
174 /*endif*/
175 if (strlen(id) > T30_MAX_IDENT_LEN)
176 return -1;
177 /*endif*/
178 strcpy(s->tx_info.ident, id);
179 t4_tx_set_local_ident(&s->t4.tx, s->tx_info.ident);
180 return 0;
181 }
182 /*- End of function --------------------------------------------------------*/
183
t30_get_tx_ident(t30_state_t * s)184 SPAN_DECLARE(const char *) t30_get_tx_ident(t30_state_t *s)
185 {
186 if (s->tx_info.ident[0] == '\0')
187 return NULL;
188 /*endif*/
189 return s->tx_info.ident;
190 }
191 /*- End of function --------------------------------------------------------*/
192
t30_get_rx_ident(t30_state_t * s)193 SPAN_DECLARE(const char *) t30_get_rx_ident(t30_state_t *s)
194 {
195 if (s->rx_info.ident[0] == '\0')
196 return NULL;
197 /*endif*/
198 return s->rx_info.ident;
199 }
200 /*- End of function --------------------------------------------------------*/
201
t30_set_tx_sub_address(t30_state_t * s,const char * sub_address)202 SPAN_DECLARE(int) t30_set_tx_sub_address(t30_state_t *s, const char *sub_address)
203 {
204 if (sub_address == NULL)
205 {
206 s->tx_info.sub_address[0] = '\0';
207 return 0;
208 }
209 /*endif*/
210 if (strlen(sub_address) > T30_MAX_IDENT_LEN)
211 return -1;
212 /*endif*/
213 strcpy(s->tx_info.sub_address, sub_address);
214 return 0;
215 }
216 /*- End of function --------------------------------------------------------*/
217
t30_get_tx_sub_address(t30_state_t * s)218 SPAN_DECLARE(const char *) t30_get_tx_sub_address(t30_state_t *s)
219 {
220 if (s->tx_info.sub_address[0] == '\0')
221 return NULL;
222 /*endif*/
223 return s->tx_info.sub_address;
224 }
225 /*- End of function --------------------------------------------------------*/
226
t30_get_rx_sub_address(t30_state_t * s)227 SPAN_DECLARE(const char *) t30_get_rx_sub_address(t30_state_t *s)
228 {
229 if (s->rx_info.sub_address[0] == '\0')
230 return NULL;
231 /*endif*/
232 return s->rx_info.sub_address;
233 }
234 /*- End of function --------------------------------------------------------*/
235
t30_set_tx_selective_polling_address(t30_state_t * s,const char * selective_polling_address)236 SPAN_DECLARE(int) t30_set_tx_selective_polling_address(t30_state_t *s, const char *selective_polling_address)
237 {
238 if (selective_polling_address == NULL)
239 {
240 s->tx_info.selective_polling_address[0] = '\0';
241 return 0;
242 }
243 /*endif*/
244 if (strlen(selective_polling_address) > T30_MAX_IDENT_LEN)
245 return -1;
246 /*endif*/
247 strcpy(s->tx_info.selective_polling_address, selective_polling_address);
248 return 0;
249 }
250 /*- End of function --------------------------------------------------------*/
251
t30_get_tx_selective_polling_address(t30_state_t * s)252 SPAN_DECLARE(const char *) t30_get_tx_selective_polling_address(t30_state_t *s)
253 {
254 if (s->tx_info.selective_polling_address[0] == '\0')
255 return NULL;
256 /*endif*/
257 return s->tx_info.selective_polling_address;
258 }
259 /*- End of function --------------------------------------------------------*/
260
t30_get_rx_selective_polling_address(t30_state_t * s)261 SPAN_DECLARE(const char *) t30_get_rx_selective_polling_address(t30_state_t *s)
262 {
263 if (s->rx_info.selective_polling_address[0] == '\0')
264 return NULL;
265 /*endif*/
266 return s->rx_info.selective_polling_address;
267 }
268 /*- End of function --------------------------------------------------------*/
269
t30_set_tx_polled_sub_address(t30_state_t * s,const char * polled_sub_address)270 SPAN_DECLARE(int) t30_set_tx_polled_sub_address(t30_state_t *s, const char *polled_sub_address)
271 {
272 if (polled_sub_address == NULL)
273 {
274 s->tx_info.polled_sub_address[0] = '\0';
275 return 0;
276 }
277 /*endif*/
278 if (strlen(polled_sub_address) > T30_MAX_IDENT_LEN)
279 return -1;
280 /*endif*/
281 strcpy(s->tx_info.polled_sub_address, polled_sub_address);
282 return 0;
283 }
284 /*- End of function --------------------------------------------------------*/
285
t30_get_tx_polled_sub_address(t30_state_t * s)286 SPAN_DECLARE(const char *) t30_get_tx_polled_sub_address(t30_state_t *s)
287 {
288 if (s->tx_info.polled_sub_address[0] == '\0')
289 return NULL;
290 /*endif*/
291 return s->tx_info.polled_sub_address;
292 }
293 /*- End of function --------------------------------------------------------*/
294
t30_get_rx_polled_sub_address(t30_state_t * s)295 SPAN_DECLARE(const char *) t30_get_rx_polled_sub_address(t30_state_t *s)
296 {
297 if (s->rx_info.polled_sub_address[0] == '\0')
298 return NULL;
299 /*endif*/
300 return s->rx_info.polled_sub_address;
301 }
302 /*- End of function --------------------------------------------------------*/
303
t30_set_tx_sender_ident(t30_state_t * s,const char * sender_ident)304 SPAN_DECLARE(int) t30_set_tx_sender_ident(t30_state_t *s, const char *sender_ident)
305 {
306 if (sender_ident == NULL)
307 {
308 s->tx_info.sender_ident[0] = '\0';
309 return 0;
310 }
311 /*endif*/
312 if (strlen(sender_ident) > T30_MAX_IDENT_LEN)
313 return -1;
314 /*endif*/
315 strcpy(s->tx_info.sender_ident, sender_ident);
316 return 0;
317 }
318 /*- End of function --------------------------------------------------------*/
319
t30_get_tx_sender_ident(t30_state_t * s)320 SPAN_DECLARE(const char *) t30_get_tx_sender_ident(t30_state_t *s)
321 {
322 if (s->tx_info.sender_ident[0] == '\0')
323 return NULL;
324 /*endif*/
325 return s->tx_info.sender_ident;
326 }
327 /*- End of function --------------------------------------------------------*/
328
t30_get_rx_sender_ident(t30_state_t * s)329 SPAN_DECLARE(const char *) t30_get_rx_sender_ident(t30_state_t *s)
330 {
331 if (s->rx_info.sender_ident[0] == '\0')
332 return NULL;
333 /*endif*/
334 return s->rx_info.sender_ident;
335 }
336 /*- End of function --------------------------------------------------------*/
337
t30_set_tx_password(t30_state_t * s,const char * password)338 SPAN_DECLARE(int) t30_set_tx_password(t30_state_t *s, const char *password)
339 {
340 if (password == NULL)
341 {
342 s->tx_info.password[0] = '\0';
343 return 0;
344 }
345 /*endif*/
346 if (strlen(password) > T30_MAX_IDENT_LEN)
347 return -1;
348 /*endif*/
349 strcpy(s->tx_info.password, password);
350 return 0;
351 }
352 /*- End of function --------------------------------------------------------*/
353
t30_get_tx_password(t30_state_t * s)354 SPAN_DECLARE(const char *) t30_get_tx_password(t30_state_t *s)
355 {
356 if (s->tx_info.password[0] == '\0')
357 return NULL;
358 /*endif*/
359 return s->tx_info.password;
360 }
361 /*- End of function --------------------------------------------------------*/
362
t30_get_rx_password(t30_state_t * s)363 SPAN_DECLARE(const char *) t30_get_rx_password(t30_state_t *s)
364 {
365 if (s->rx_info.password[0] == '\0')
366 return NULL;
367 /*endif*/
368 return s->rx_info.password;
369 }
370 /*- End of function --------------------------------------------------------*/
371
t30_set_tx_nsf(t30_state_t * s,const uint8_t * nsf,int len)372 SPAN_DECLARE(int) t30_set_tx_nsf(t30_state_t *s, const uint8_t *nsf, int len)
373 {
374 if (s->tx_info.nsf)
375 span_free(s->tx_info.nsf);
376 /*endif*/
377 if (nsf && len > 0 && (s->tx_info.nsf = span_alloc(len + 3)))
378 {
379 memcpy(&s->tx_info.nsf[3], nsf, len);
380 s->tx_info.nsf_len = len;
381 }
382 else
383 {
384 s->tx_info.nsf = NULL;
385 s->tx_info.nsf_len = 0;
386 }
387 /*endif*/
388 return 0;
389 }
390 /*- End of function --------------------------------------------------------*/
391
t30_get_tx_nsf(t30_state_t * s,const uint8_t * nsf[])392 SPAN_DECLARE(size_t) t30_get_tx_nsf(t30_state_t *s, const uint8_t *nsf[])
393 {
394 if (nsf)
395 *nsf = s->tx_info.nsf;
396 /*endif*/
397 return s->tx_info.nsf_len;
398 }
399 /*- End of function --------------------------------------------------------*/
400
t30_get_rx_nsf(t30_state_t * s,const uint8_t * nsf[])401 SPAN_DECLARE(size_t) t30_get_rx_nsf(t30_state_t *s, const uint8_t *nsf[])
402 {
403 if (nsf)
404 *nsf = s->rx_info.nsf;
405 /*endif*/
406 return s->rx_info.nsf_len;
407 }
408 /*- End of function --------------------------------------------------------*/
409
t30_set_tx_nsc(t30_state_t * s,const uint8_t * nsc,int len)410 SPAN_DECLARE(int) t30_set_tx_nsc(t30_state_t *s, const uint8_t *nsc, int len)
411 {
412 if (s->tx_info.nsc)
413 span_free(s->tx_info.nsc);
414 /*endif*/
415 if (nsc && len > 0 && (s->tx_info.nsc = span_alloc(len + 3)))
416 {
417 memcpy(&s->tx_info.nsc[3], nsc, len);
418 s->tx_info.nsc_len = len;
419 }
420 else
421 {
422 s->tx_info.nsc = NULL;
423 s->tx_info.nsc_len = 0;
424 }
425 /*endif*/
426 return 0;
427 }
428 /*- End of function --------------------------------------------------------*/
429
t30_get_tx_nsc(t30_state_t * s,const uint8_t * nsc[])430 SPAN_DECLARE(size_t) t30_get_tx_nsc(t30_state_t *s, const uint8_t *nsc[])
431 {
432 if (nsc)
433 *nsc = s->tx_info.nsc;
434 /*endif*/
435 return s->tx_info.nsc_len;
436 }
437 /*- End of function --------------------------------------------------------*/
438
t30_get_rx_nsc(t30_state_t * s,const uint8_t * nsc[])439 SPAN_DECLARE(size_t) t30_get_rx_nsc(t30_state_t *s, const uint8_t *nsc[])
440 {
441 if (nsc)
442 *nsc = s->rx_info.nsc;
443 /*endif*/
444 return s->rx_info.nsc_len;
445 }
446 /*- End of function --------------------------------------------------------*/
447
t30_set_tx_nss(t30_state_t * s,const uint8_t * nss,int len)448 SPAN_DECLARE(int) t30_set_tx_nss(t30_state_t *s, const uint8_t *nss, int len)
449 {
450 if (s->tx_info.nss)
451 span_free(s->tx_info.nss);
452 /*endif*/
453 if (nss && len > 0 && (s->tx_info.nss = span_alloc(len + 3)))
454 {
455 memcpy(&s->tx_info.nss[3], nss, len);
456 s->tx_info.nss_len = len;
457 }
458 else
459 {
460 s->tx_info.nss = NULL;
461 s->tx_info.nss_len = 0;
462 }
463 /*endif*/
464 return 0;
465 }
466 /*- End of function --------------------------------------------------------*/
467
t30_get_tx_nss(t30_state_t * s,const uint8_t * nss[])468 SPAN_DECLARE(size_t) t30_get_tx_nss(t30_state_t *s, const uint8_t *nss[])
469 {
470 if (nss)
471 *nss = s->tx_info.nss;
472 /*endif*/
473 return s->tx_info.nss_len;
474 }
475 /*- End of function --------------------------------------------------------*/
476
t30_get_rx_nss(t30_state_t * s,const uint8_t * nss[])477 SPAN_DECLARE(size_t) t30_get_rx_nss(t30_state_t *s, const uint8_t *nss[])
478 {
479 if (nss)
480 *nss = s->rx_info.nss;
481 /*endif*/
482 return s->rx_info.nss_len;
483 }
484 /*- End of function --------------------------------------------------------*/
485
t30_set_tx_tsa(t30_state_t * s,int type,const char * address,int len)486 SPAN_DECLARE(int) t30_set_tx_tsa(t30_state_t *s, int type, const char *address, int len)
487 {
488 if (s->tx_info.tsa)
489 span_free(s->tx_info.tsa);
490 /*endif*/
491 if (address == NULL || len == 0)
492 {
493 s->tx_info.tsa = NULL;
494 s->tx_info.tsa_len = 0;
495 return 0;
496 }
497 /*endif*/
498 s->tx_info.tsa_type = type;
499 if (len < 0)
500 len = strlen(address);
501 /*endif*/
502 if ((s->tx_info.tsa = span_alloc(len)))
503 {
504 memcpy(s->tx_info.tsa, address, len);
505 s->tx_info.tsa_len = len;
506 }
507 /*endif*/
508 return 0;
509 }
510 /*- End of function --------------------------------------------------------*/
511
t30_get_tx_tsa(t30_state_t * s,int * type,const char * address[])512 SPAN_DECLARE(size_t) t30_get_tx_tsa(t30_state_t *s, int *type, const char *address[])
513 {
514 if (type)
515 *type = s->tx_info.tsa_type;
516 /*endif*/
517 if (address)
518 *address = s->tx_info.tsa;
519 /*endif*/
520 return s->tx_info.tsa_len;
521 }
522 /*- End of function --------------------------------------------------------*/
523
t30_get_rx_tsa(t30_state_t * s,int * type,const char * address[])524 SPAN_DECLARE(size_t) t30_get_rx_tsa(t30_state_t *s, int *type, const char *address[])
525 {
526 if (type)
527 *type = s->rx_info.tsa_type;
528 /*endif*/
529 if (address)
530 *address = s->rx_info.tsa;
531 /*endif*/
532 return s->rx_info.tsa_len;
533 }
534 /*- End of function --------------------------------------------------------*/
535
t30_set_tx_ira(t30_state_t * s,int type,const char * address,int len)536 SPAN_DECLARE(int) t30_set_tx_ira(t30_state_t *s, int type, const char *address, int len)
537 {
538 if (s->tx_info.ira)
539 span_free(s->tx_info.ira);
540 /*endif*/
541 if (address == NULL)
542 {
543 s->tx_info.ira = NULL;
544 return 0;
545 }
546 /*endif*/
547 s->tx_info.ira = strdup(address);
548 return 0;
549 }
550 /*- End of function --------------------------------------------------------*/
551
t30_get_tx_ira(t30_state_t * s,int * type,const char * address[])552 SPAN_DECLARE(size_t) t30_get_tx_ira(t30_state_t *s, int *type, const char *address[])
553 {
554 if (type)
555 *type = s->tx_info.ira_type;
556 /*endif*/
557 if (address)
558 *address = s->tx_info.ira;
559 /*endif*/
560 return s->tx_info.ira_len;
561 }
562 /*- End of function --------------------------------------------------------*/
563
t30_get_rx_ira(t30_state_t * s,int * type,const char * address[])564 SPAN_DECLARE(size_t) t30_get_rx_ira(t30_state_t *s, int *type, const char *address[])
565 {
566 if (type)
567 *type = s->rx_info.ira_type;
568 /*endif*/
569 if (address)
570 *address = s->rx_info.ira;
571 /*endif*/
572 return s->rx_info.ira_len;
573 }
574 /*- End of function --------------------------------------------------------*/
575
t30_set_tx_cia(t30_state_t * s,int type,const char * address,int len)576 SPAN_DECLARE(int) t30_set_tx_cia(t30_state_t *s, int type, const char *address, int len)
577 {
578 if (s->tx_info.cia)
579 span_free(s->tx_info.cia);
580 /*endif*/
581 if (address == NULL)
582 {
583 s->tx_info.cia = NULL;
584 return 0;
585 }
586 /*endif*/
587 s->tx_info.cia = strdup(address);
588 return 0;
589 }
590 /*- End of function --------------------------------------------------------*/
591
t30_get_tx_cia(t30_state_t * s,int * type,const char * address[])592 SPAN_DECLARE(size_t) t30_get_tx_cia(t30_state_t *s, int *type, const char *address[])
593 {
594 if (type)
595 *type = s->tx_info.cia_type;
596 /*endif*/
597 if (address)
598 *address = s->tx_info.cia;
599 /*endif*/
600 return s->tx_info.cia_len;
601 }
602 /*- End of function --------------------------------------------------------*/
603
t30_get_rx_cia(t30_state_t * s,int * type,const char * address[])604 SPAN_DECLARE(size_t) t30_get_rx_cia(t30_state_t *s, int *type, const char *address[])
605 {
606 if (type)
607 *type = s->rx_info.cia_type;
608 /*endif*/
609 if (address)
610 *address = s->rx_info.cia;
611 /*endif*/
612 return s->rx_info.cia_len;
613 }
614 /*- End of function --------------------------------------------------------*/
615
t30_set_tx_isp(t30_state_t * s,int type,const char * address,int len)616 SPAN_DECLARE(int) t30_set_tx_isp(t30_state_t *s, int type, const char *address, int len)
617 {
618 if (s->tx_info.isp)
619 span_free(s->tx_info.isp);
620 /*endif*/
621 if (address == NULL)
622 {
623 s->tx_info.isp = NULL;
624 return 0;
625 }
626 /*endif*/
627 s->tx_info.isp = strdup(address);
628 return 0;
629 }
630 /*- End of function --------------------------------------------------------*/
631
t30_get_tx_isp(t30_state_t * s,int * type,const char * address[])632 SPAN_DECLARE(size_t) t30_get_tx_isp(t30_state_t *s, int *type, const char *address[])
633 {
634 if (type)
635 *type = s->tx_info.isp_type;
636 /*endif*/
637 if (address)
638 *address = s->tx_info.isp;
639 /*endif*/
640 return s->tx_info.isp_len;
641 }
642 /*- End of function --------------------------------------------------------*/
643
t30_get_rx_isp(t30_state_t * s,int * type,const char * address[])644 SPAN_DECLARE(size_t) t30_get_rx_isp(t30_state_t *s, int *type, const char *address[])
645 {
646 if (type)
647 *type = s->rx_info.isp_type;
648 /*endif*/
649 if (address)
650 *address = s->rx_info.isp;
651 /*endif*/
652 return s->rx_info.isp_len;
653 }
654 /*- End of function --------------------------------------------------------*/
655
t30_set_tx_csa(t30_state_t * s,int type,const char * address,int len)656 SPAN_DECLARE(int) t30_set_tx_csa(t30_state_t *s, int type, const char *address, int len)
657 {
658 if (s->tx_info.csa)
659 span_free(s->tx_info.csa);
660 /*endif*/
661 if (address == NULL)
662 {
663 s->tx_info.csa = NULL;
664 return 0;
665 }
666 /*endif*/
667 s->tx_info.csa = strdup(address);
668 return 0;
669 }
670 /*- End of function --------------------------------------------------------*/
671
t30_get_tx_csa(t30_state_t * s,int * type,const char * address[])672 SPAN_DECLARE(size_t) t30_get_tx_csa(t30_state_t *s, int *type, const char *address[])
673 {
674 if (type)
675 *type = s->tx_info.csa_type;
676 /*endif*/
677 if (address)
678 *address = s->tx_info.csa;
679 /*endif*/
680 return s->tx_info.csa_len;
681 }
682 /*- End of function --------------------------------------------------------*/
683
t30_get_rx_csa(t30_state_t * s,int * type,const char * address[])684 SPAN_DECLARE(size_t) t30_get_rx_csa(t30_state_t *s, int *type, const char *address[])
685 {
686 if (type)
687 *type = s->rx_info.csa_type;
688 /*endif*/
689 if (address)
690 *address = s->rx_info.csa;
691 /*endif*/
692 return s->rx_info.csa_len;
693 }
694 /*- End of function --------------------------------------------------------*/
695
t30_set_tx_page_header_overlays_image(t30_state_t * s,bool header_overlays_image)696 SPAN_DECLARE(int) t30_set_tx_page_header_overlays_image(t30_state_t *s, bool header_overlays_image)
697 {
698 s->header_overlays_image = header_overlays_image;
699 t4_tx_set_header_overlays_image(&s->t4.tx, s->header_overlays_image);
700 return 0;
701 }
702 /*- End of function --------------------------------------------------------*/
703
t30_set_tx_page_header_info(t30_state_t * s,const char * info)704 SPAN_DECLARE(int) t30_set_tx_page_header_info(t30_state_t *s, const char *info)
705 {
706 if (info == NULL)
707 {
708 s->header_info[0] = '\0';
709 return 0;
710 }
711 /*endif*/
712 if (strlen(info) > T30_MAX_PAGE_HEADER_INFO)
713 return -1;
714 /*endif*/
715 strcpy(s->header_info, info);
716 t4_tx_set_header_info(&s->t4.tx, s->header_info);
717 return 0;
718 }
719 /*- End of function --------------------------------------------------------*/
720
t30_get_tx_page_header_info(t30_state_t * s,char * info)721 SPAN_DECLARE(size_t) t30_get_tx_page_header_info(t30_state_t *s, char *info)
722 {
723 if (info)
724 strcpy(info, s->header_info);
725 /*endif*/
726 return strlen(s->header_info);
727 }
728 /*- End of function --------------------------------------------------------*/
729
t30_set_tx_page_header_tz(t30_state_t * s,const char * tzstring)730 SPAN_DECLARE(int) t30_set_tx_page_header_tz(t30_state_t *s, const char *tzstring)
731 {
732 if (tz_init(&s->tz, tzstring))
733 {
734 s->use_own_tz = true;
735 t4_tx_set_header_tz(&s->t4.tx, &s->tz);
736 return 0;
737 }
738 /*endif*/
739 return -1;
740 }
741 /*- End of function --------------------------------------------------------*/
742
t30_get_rx_country(t30_state_t * s)743 SPAN_DECLARE(const char *) t30_get_rx_country(t30_state_t *s)
744 {
745 return s->country;
746 }
747 /*- End of function --------------------------------------------------------*/
748
t30_get_rx_vendor(t30_state_t * s)749 SPAN_DECLARE(const char *) t30_get_rx_vendor(t30_state_t *s)
750 {
751 return s->vendor;
752 }
753 /*- End of function --------------------------------------------------------*/
754
t30_get_rx_model(t30_state_t * s)755 SPAN_DECLARE(const char *) t30_get_rx_model(t30_state_t *s)
756 {
757 return s->model;
758 }
759 /*- End of function --------------------------------------------------------*/
760
t30_set_rx_file(t30_state_t * s,const char * file,int stop_page)761 SPAN_DECLARE(void) t30_set_rx_file(t30_state_t *s, const char *file, int stop_page)
762 {
763 strncpy(s->rx_file, file, sizeof(s->rx_file));
764 s->rx_file[sizeof(s->rx_file) - 1] = '\0';
765 s->rx_stop_page = stop_page;
766 }
767 /*- End of function --------------------------------------------------------*/
768
t30_set_tx_file(t30_state_t * s,const char * file,int start_page,int stop_page)769 SPAN_DECLARE(void) t30_set_tx_file(t30_state_t *s, const char *file, int start_page, int stop_page)
770 {
771 strncpy(s->tx_file, file, sizeof(s->tx_file));
772 s->tx_file[sizeof(s->tx_file) - 1] = '\0';
773 s->tx_start_page = start_page;
774 s->tx_stop_page = stop_page;
775 }
776 /*- End of function --------------------------------------------------------*/
777
t30_set_iaf_mode(t30_state_t * s,bool iaf)778 SPAN_DECLARE(void) t30_set_iaf_mode(t30_state_t *s, bool iaf)
779 {
780 s->iaf = iaf;
781 }
782 /*- End of function --------------------------------------------------------*/
783
t30_set_ecm_capability(t30_state_t * s,bool enabled)784 SPAN_DECLARE(int) t30_set_ecm_capability(t30_state_t *s, bool enabled)
785 {
786 s->ecm_allowed = enabled;
787 t30_build_dis_or_dtc(s);
788 return 0;
789 }
790 /*- End of function --------------------------------------------------------*/
791
t30_set_keep_bad_quality_pages(t30_state_t * s,bool keep_bad_pages)792 SPAN_DECLARE(void) t30_set_keep_bad_quality_pages(t30_state_t *s, bool keep_bad_pages)
793 {
794 s->keep_bad_pages = keep_bad_pages;
795 }
796 /*- End of function --------------------------------------------------------*/
797
t30_set_supported_output_compressions(t30_state_t * s,int supported_compressions)798 SPAN_DECLARE(int) t30_set_supported_output_compressions(t30_state_t *s, int supported_compressions)
799 {
800 /* Mask out the ones we actually support today. */
801 supported_compressions &= T4_COMPRESSION_T4_1D
802 | T4_COMPRESSION_T4_2D
803 | T4_COMPRESSION_T6
804 | T4_COMPRESSION_T85
805 | T4_COMPRESSION_T85_L0
806 #if defined(SPANDSP_SUPPORT_T88)
807 | T4_COMPRESSION_T88
808 #endif
809 | T4_COMPRESSION_T42_T81
810 #if defined(SPANDSP_SUPPORT_SYCC_T81)
811 | T4_COMPRESSION_SYCC_T81
812 #endif
813 #if defined(SPANDSP_SUPPORT_T43)
814 | T4_COMPRESSION_T43
815 #endif
816 #if defined(SPANDSP_SUPPORT_T45)
817 | T4_COMPRESSION_T45
818 #endif
819 | T4_COMPRESSION_UNCOMPRESSED
820 | T4_COMPRESSION_JPEG
821 | 0;
822 s->supported_output_compressions = supported_compressions;
823 return 0;
824 }
825 /*- End of function --------------------------------------------------------*/
826
t30_set_minimum_scan_line_time(t30_state_t * s,int min_time)827 SPAN_DECLARE(int) t30_set_minimum_scan_line_time(t30_state_t *s, int min_time)
828 {
829 /* There are only certain possible times supported, so we need to select
830 the code which best matches the request. */
831 if (min_time == 0)
832 s->local_min_scan_time_code = 7;
833 else if (min_time <= 5)
834 s->local_min_scan_time_code = 1;
835 else if (min_time <= 10)
836 s->local_min_scan_time_code = 2;
837 else if (min_time <= 20)
838 s->local_min_scan_time_code = 0;
839 else if (min_time <= 40)
840 s->local_min_scan_time_code = 4;
841 else
842 return -1;
843 /*endif*/
844 t30_build_dis_or_dtc(s);
845 return 0;
846 }
847 /*- End of function --------------------------------------------------------*/
848
t30_set_supported_modems(t30_state_t * s,int supported_modems)849 SPAN_DECLARE(int) t30_set_supported_modems(t30_state_t *s, int supported_modems)
850 {
851 s->supported_modems = supported_modems;
852 t30_build_dis_or_dtc(s);
853 return 0;
854 }
855 /*- End of function --------------------------------------------------------*/
856
t30_set_supported_compressions(t30_state_t * s,int supported_compressions)857 SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_compressions)
858 {
859 /* Mask out the ones we actually support today. */
860 supported_compressions &= T4_COMPRESSION_T4_1D
861 | T4_COMPRESSION_T4_2D
862 | T4_COMPRESSION_T6
863 | T4_COMPRESSION_T85
864 | T4_COMPRESSION_T85_L0
865 #if defined(SPANDSP_SUPPORT_T88)
866 | T4_COMPRESSION_T88
867 #endif
868 | T4_COMPRESSION_T42_T81
869 #if defined(SPANDSP_SUPPORT_SYCC_T81)
870 | T4_COMPRESSION_SYCC_T81
871 #endif
872 #if defined(SPANDSP_SUPPORT_T43)
873 | T4_COMPRESSION_T43
874 #endif
875 #if defined(SPANDSP_SUPPORT_T45)
876 | T4_COMPRESSION_T45
877 #endif
878 | T4_COMPRESSION_GRAYSCALE
879 | T4_COMPRESSION_COLOUR
880 | T4_COMPRESSION_12BIT
881 | T4_COMPRESSION_COLOUR_TO_GRAY
882 | T4_COMPRESSION_GRAY_TO_BILEVEL
883 | T4_COMPRESSION_COLOUR_TO_BILEVEL
884 | T4_COMPRESSION_RESCALING
885 | 0;
886
887 s->supported_compressions = supported_compressions;
888 t30_build_dis_or_dtc(s);
889 return 0;
890 }
891 /*- End of function --------------------------------------------------------*/
892
t30_set_supported_bilevel_resolutions(t30_state_t * s,int supported_resolutions)893 SPAN_DECLARE(int) t30_set_supported_bilevel_resolutions(t30_state_t *s, int supported_resolutions)
894 {
895 supported_resolutions &= T4_RESOLUTION_R8_STANDARD
896 | T4_RESOLUTION_R8_FINE
897 | T4_RESOLUTION_R8_SUPERFINE
898 | T4_RESOLUTION_R16_SUPERFINE
899 | T4_RESOLUTION_200_100
900 | T4_RESOLUTION_200_200
901 | T4_RESOLUTION_200_400
902 | T4_RESOLUTION_300_300
903 | T4_RESOLUTION_300_600
904 | T4_RESOLUTION_400_400
905 | T4_RESOLUTION_400_800
906 | T4_RESOLUTION_600_600
907 | T4_RESOLUTION_600_1200
908 | T4_RESOLUTION_1200_1200;
909 /* Make sure anything needed for colour is enabled as a bi-level image, as that is a
910 rule from T.30. 100x100 is an exception, as it doesn't exist as a bi-level resolution. */
911 supported_resolutions |= (s->supported_colour_resolutions & ~T4_RESOLUTION_100_100);
912 s->supported_bilevel_resolutions = supported_resolutions;
913 t30_build_dis_or_dtc(s);
914 return 0;
915 }
916 /*- End of function --------------------------------------------------------*/
917
t30_set_supported_colour_resolutions(t30_state_t * s,int supported_resolutions)918 SPAN_DECLARE(int) t30_set_supported_colour_resolutions(t30_state_t *s, int supported_resolutions)
919 {
920 supported_resolutions &= T4_RESOLUTION_100_100
921 | T4_RESOLUTION_200_200
922 | T4_RESOLUTION_300_300
923 | T4_RESOLUTION_400_400
924 | T4_RESOLUTION_600_600
925 | T4_RESOLUTION_1200_1200;
926 s->supported_colour_resolutions = supported_resolutions;
927 /* Make sure anything needed for colour is enabled as a bi-level image, as that is a
928 rule from T.30. 100x100 is an exception, as it doesn't exist as a bi-level resolution. */
929 s->supported_bilevel_resolutions |= (s->supported_colour_resolutions & ~T4_RESOLUTION_100_100);
930 t30_build_dis_or_dtc(s);
931 return 0;
932 }
933 /*- End of function --------------------------------------------------------*/
934
t30_set_supported_image_sizes(t30_state_t * s,int supported_image_sizes)935 SPAN_DECLARE(int) t30_set_supported_image_sizes(t30_state_t *s, int supported_image_sizes)
936 {
937 /* Force the sizes which are always available */
938 supported_image_sizes |= (T4_SUPPORT_WIDTH_215MM | T4_SUPPORT_LENGTH_A4);
939 /* Force the sizes which depend on sizes which are supported */
940 if ((supported_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
941 supported_image_sizes |= T4_SUPPORT_LENGTH_B4;
942 /*endif*/
943 if ((supported_image_sizes & T4_SUPPORT_WIDTH_303MM))
944 supported_image_sizes |= T4_SUPPORT_WIDTH_255MM;
945 /*endif*/
946 s->supported_image_sizes = supported_image_sizes;
947 t30_build_dis_or_dtc(s);
948 return 0;
949 }
950 /*- End of function --------------------------------------------------------*/
951
t30_set_supported_t30_features(t30_state_t * s,int supported_t30_features)952 SPAN_DECLARE(int) t30_set_supported_t30_features(t30_state_t *s, int supported_t30_features)
953 {
954 s->supported_t30_features = supported_t30_features;
955 t30_build_dis_or_dtc(s);
956 return 0;
957 }
958 /*- End of function --------------------------------------------------------*/
959
t30_set_status(t30_state_t * s,int status)960 SPAN_DECLARE(void) t30_set_status(t30_state_t *s, int status)
961 {
962 if (s->current_status != status)
963 {
964 span_log(&s->logging, SPAN_LOG_FLOW, "Status changing to '%s'\n", t30_completion_code_to_str(status));
965 s->current_status = status;
966 }
967 /*endif*/
968 }
969 /*- End of function --------------------------------------------------------*/
970
t30_set_receiver_not_ready(t30_state_t * s,int count)971 SPAN_DECLARE(int) t30_set_receiver_not_ready(t30_state_t *s, int count)
972 {
973 s->receiver_not_ready_count = count;
974 return 0;
975 }
976 /*- End of function --------------------------------------------------------*/
977
t30_set_phase_b_handler(t30_state_t * s,t30_phase_b_handler_t handler,void * user_data)978 SPAN_DECLARE(void) t30_set_phase_b_handler(t30_state_t *s, t30_phase_b_handler_t handler, void *user_data)
979 {
980 s->phase_b_handler = handler;
981 s->phase_b_user_data = user_data;
982 }
983 /*- End of function --------------------------------------------------------*/
984
t30_set_phase_d_handler(t30_state_t * s,t30_phase_d_handler_t handler,void * user_data)985 SPAN_DECLARE(void) t30_set_phase_d_handler(t30_state_t *s, t30_phase_d_handler_t handler, void *user_data)
986 {
987 s->phase_d_handler = handler;
988 s->phase_d_user_data = user_data;
989 }
990 /*- End of function --------------------------------------------------------*/
991
t30_set_phase_e_handler(t30_state_t * s,t30_phase_e_handler_t handler,void * user_data)992 SPAN_DECLARE(void) t30_set_phase_e_handler(t30_state_t *s, t30_phase_e_handler_t handler, void *user_data)
993 {
994 s->phase_e_handler = handler;
995 s->phase_e_user_data = user_data;
996 }
997 /*- End of function --------------------------------------------------------*/
998
t30_set_document_handler(t30_state_t * s,t30_document_handler_t handler,void * user_data)999 SPAN_DECLARE(void) t30_set_document_handler(t30_state_t *s, t30_document_handler_t handler, void *user_data)
1000 {
1001 s->document_handler = handler;
1002 s->document_user_data = user_data;
1003 }
1004 /*- End of function --------------------------------------------------------*/
1005
t30_set_real_time_frame_handler(t30_state_t * s,t30_real_time_frame_handler_t handler,void * user_data)1006 SPAN_DECLARE(void) t30_set_real_time_frame_handler(t30_state_t *s, t30_real_time_frame_handler_t handler, void *user_data)
1007 {
1008 s->real_time_frame_handler = handler;
1009 s->real_time_frame_user_data = user_data;
1010 }
1011 /*- End of function --------------------------------------------------------*/
1012
t30_set_document_get_handler(t30_state_t * s,t30_document_get_handler_t handler,void * user_data)1013 SPAN_DECLARE(void) t30_set_document_get_handler(t30_state_t *s, t30_document_get_handler_t handler, void *user_data)
1014 {
1015 s->document_get_handler = handler;
1016 s->document_get_user_data = user_data;
1017 }
1018 /*- End of function --------------------------------------------------------*/
1019
t30_set_document_put_handler(t30_state_t * s,t30_document_put_handler_t handler,void * user_data)1020 SPAN_DECLARE(void) t30_set_document_put_handler(t30_state_t *s, t30_document_put_handler_t handler, void *user_data)
1021 {
1022 s->document_put_handler = handler;
1023 s->document_put_user_data = user_data;
1024 }
1025 /*- End of function --------------------------------------------------------*/
1026
t30_get_logging_state(t30_state_t * s)1027 SPAN_DECLARE(logging_state_t *) t30_get_logging_state(t30_state_t *s)
1028 {
1029 return &s->logging;
1030 }
1031 /*- End of function --------------------------------------------------------*/
1032 /*- End of file ------------------------------------------------------------*/
1033