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