comparison spandsp-0.0.6pre17/src/adsi.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * adsi.c - Analogue display service interfaces of various types, including
5 * ADSI, TDD and most caller ID formats.
6 *
7 * Written by Steve Underwood <steveu@coppice.org>
8 *
9 * Copyright (C) 2003 Steve Underwood
10 *
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License version 2.1,
15 * as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 * $Id: adsi.c,v 1.77 2009/11/02 13:25:20 steveu Exp $
27 */
28
29 /*! \file */
30
31 #if defined(HAVE_CONFIG_H)
32 #include "config.h"
33 #endif
34
35 #include <inttypes.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #if defined(HAVE_TGMATH_H)
40 #include <tgmath.h>
41 #endif
42 #if defined(HAVE_MATH_H)
43 #include <math.h>
44 #endif
45 #include "floating_fudge.h"
46 #include <assert.h>
47
48 #include "spandsp/telephony.h"
49 #include "spandsp/fast_convert.h"
50 #include "spandsp/logging.h"
51 #include "spandsp/queue.h"
52 #include "spandsp/complex.h"
53 #include "spandsp/dds.h"
54 #include "spandsp/power_meter.h"
55 #include "spandsp/async.h"
56 #include "spandsp/crc.h"
57 #include "spandsp/fsk.h"
58 #include "spandsp/tone_detect.h"
59 #include "spandsp/tone_generate.h"
60 #include "spandsp/super_tone_rx.h"
61 #include "spandsp/dtmf.h"
62 #include "spandsp/adsi.h"
63
64 #include "spandsp/private/logging.h"
65 #include "spandsp/private/queue.h"
66 #include "spandsp/private/tone_generate.h"
67 #include "spandsp/private/async.h"
68 #include "spandsp/private/fsk.h"
69 #include "spandsp/private/dtmf.h"
70 #include "spandsp/private/adsi.h"
71
72 /*! The baudot code to shift from alpha to digits and symbols */
73 #define BAUDOT_FIGURE_SHIFT 0x1B
74 /*! The baudot code to shift from digits and symbols to alpha */
75 #define BAUDOT_LETTER_SHIFT 0x1F
76
77 enum
78 {
79 SOH = 0x01,
80 STX = 0x02,
81 ETX = 0x03,
82 DLE = 0x10,
83 SUB = 0x1A
84 };
85
86 static uint16_t adsi_encode_baudot(adsi_tx_state_t *s, uint8_t ch);
87 static uint8_t adsi_decode_baudot(adsi_rx_state_t *s, uint8_t ch);
88
89 static int adsi_tx_get_bit(void *user_data)
90 {
91 int bit;
92 adsi_tx_state_t *s;
93
94 s = (adsi_tx_state_t *) user_data;
95 /* This is similar to the async. handling code in fsk.c, but a few special
96 things are needed in the preamble, and postamble of an ADSI message. */
97 if (s->bit_no < s->preamble_len)
98 {
99 /* Alternating bit preamble */
100 bit = s->bit_no & 1;
101 s->bit_no++;
102 }
103 else if (s->bit_no < s->preamble_len + s->preamble_ones_len)
104 {
105 /* All 1s for receiver conditioning */
106 /* NB: The receiver is an async one. It needs a rest after the
107 alternating 1/0 sequence so it can reliably pick up on
108 the next start bit, and sync to the byte stream. */
109 /* The length of this period varies with the circumstance */
110 bit = 1;
111 s->bit_no++;
112 }
113 else if (s->bit_no <= s->preamble_len + s->preamble_ones_len)
114 {
115 /* Push out the 8 bit async. chars, with an appropriate number of stop bits */
116 if (s->bit_pos == 0)
117 {
118 /* Start bit */
119 bit = 0;
120 s->bit_pos++;
121 }
122 else if (s->bit_pos < 1 + 8)
123 {
124 bit = (s->msg[s->byte_no] >> (s->bit_pos - 1)) & 1;
125 s->bit_pos++;
126 }
127 else if (s->bit_pos < 1 + 8 + s->stop_bits - 1)
128 {
129 /* Stop bit */
130 bit = 1;
131 s->bit_pos++;
132 }
133 else
134 {
135 /* Stop bit */
136 bit = 1;
137 s->bit_pos = 0;
138 if (++s->byte_no >= s->msg_len)
139 s->bit_no++;
140 }
141 }
142 else if (s->bit_no <= s->preamble_len + s->preamble_ones_len + s->postamble_ones_len)
143 {
144 /* Extra stop bits beyond the last character, to meet the specs., and ensure
145 all bits are out of the DSP before we shut off the FSK modem. */
146 bit = 1;
147 s->bit_no++;
148 }
149 else
150 {
151 bit = SIG_STATUS_END_OF_DATA;
152 if (s->tx_signal_on)
153 {
154 /* The FSK should now be switched off. */
155 s->tx_signal_on = FALSE;
156 s->msg_len = 0;
157 }
158 }
159 //printf("Tx bit %d\n", bit);
160 return bit;
161 }
162 /*- End of function --------------------------------------------------------*/
163
164 static int adsi_tdd_get_async_byte(void *user_data)
165 {
166 adsi_tx_state_t *s;
167
168 s = (adsi_tx_state_t *) user_data;
169 if (s->byte_no < s->msg_len)
170 return s->msg[s->byte_no++];
171 if (s->tx_signal_on)
172 {
173 /* The FSK should now be switched off. */
174 s->tx_signal_on = FALSE;
175 s->msg_len = 0;
176 }
177 return 0x1F;
178 }
179 /*- End of function --------------------------------------------------------*/
180
181 static void adsi_rx_put_bit(void *user_data, int bit)
182 {
183 adsi_rx_state_t *s;
184 int i;
185 int sum;
186
187 s = (adsi_rx_state_t *) user_data;
188 if (bit < 0)
189 {
190 /* Special conditions */
191 span_log(&s->logging, SPAN_LOG_FLOW, "ADSI signal status is %s (%d)\n", signal_status_to_str(bit), bit);
192 switch (bit)
193 {
194 case SIG_STATUS_CARRIER_UP:
195 s->consecutive_ones = 0;
196 s->bit_pos = 0;
197 s->in_progress = 0;
198 s->msg_len = 0;
199 break;
200 case SIG_STATUS_CARRIER_DOWN:
201 break;
202 default:
203 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put bit value - %d!\n", bit);
204 break;
205 }
206 return;
207 }
208 bit &= 1;
209 if (s->bit_pos == 0)
210 {
211 if (bit == 0)
212 {
213 /* Start bit */
214 s->bit_pos++;
215 if (s->consecutive_ones > 10)
216 {
217 /* This is a line idle condition, which means we should
218 restart message acquisition */
219 s->msg_len = 0;
220 }
221 s->consecutive_ones = 0;
222 }
223 else
224 {
225 s->consecutive_ones++;
226 }
227 }
228 else if (s->bit_pos <= 8)
229 {
230 s->in_progress >>= 1;
231 if (bit)
232 s->in_progress |= 0x80;
233 s->bit_pos++;
234 }
235 else
236 {
237 /* Stop bit */
238 if (bit)
239 {
240 if (s->msg_len < 256)
241 {
242 if (s->standard == ADSI_STANDARD_JCLIP)
243 {
244 if (s->msg_len == 0)
245 {
246 /* A message should start DLE SOH, but let's just check
247 we are starting with a DLE for now */
248 if (s->in_progress == (0x80 | DLE))
249 s->msg[s->msg_len++] = (uint8_t) s->in_progress;
250 }
251 else
252 {
253 s->msg[s->msg_len++] = (uint8_t) s->in_progress;
254 }
255 if (s->msg_len >= 11 && s->msg_len == ((s->msg[6] & 0x7F) + 11))
256 {
257 /* Test the CRC-16 */
258 if (crc_itu16_calc(s->msg + 2, s->msg_len - 2, 0) == 0)
259 {
260 /* Strip off the parity bits. It doesn't seem
261 worthwhile actually checking the parity if a
262 CRC check has succeeded. */
263 for (i = 0; i < s->msg_len - 2; i++)
264 s->msg[i] &= 0x7F;
265 /* Put everything, except the CRC octets */
266 s->put_msg(s->user_data, s->msg, s->msg_len - 2);
267 }
268 else
269 {
270 span_log(&s->logging, SPAN_LOG_WARNING, "CRC failed\n");
271 }
272 s->msg_len = 0;
273 }
274 }
275 else
276 {
277 s->msg[s->msg_len++] = (uint8_t) s->in_progress;
278 if (s->msg_len >= 3 && s->msg_len == (s->msg[1] + 3))
279 {
280 /* Test the checksum */
281 sum = 0;
282 for (i = 0; i < s->msg_len - 1; i++)
283 sum += s->msg[i];
284 if ((-sum & 0xFF) == s->msg[i])
285 s->put_msg(s->user_data, s->msg, s->msg_len - 1);
286 else
287 span_log(&s->logging, SPAN_LOG_WARNING, "Sumcheck failed\n");
288 s->msg_len = 0;
289 }
290 }
291 }
292 }
293 else
294 {
295 s->framing_errors++;
296 }
297 s->bit_pos = 0;
298 s->in_progress = 0;
299 }
300 }
301 /*- End of function --------------------------------------------------------*/
302
303 static void adsi_tdd_put_async_byte(void *user_data, int byte)
304 {
305 adsi_rx_state_t *s;
306 uint8_t octet;
307
308 s = (adsi_rx_state_t *) user_data;
309 //printf("Rx bit %x\n", bit);
310 if (byte < 0)
311 {
312 /* Special conditions */
313 span_log(&s->logging, SPAN_LOG_FLOW, "ADSI signal status is %s (%d)\n", signal_status_to_str(byte), byte);
314 switch (byte)
315 {
316 case SIG_STATUS_CARRIER_UP:
317 s->consecutive_ones = 0;
318 s->bit_pos = 0;
319 s->in_progress = 0;
320 s->msg_len = 0;
321 break;
322 case SIG_STATUS_CARRIER_DOWN:
323 if (s->msg_len > 0)
324 {
325 /* Whatever we have to date constitutes the message */
326 s->put_msg(s->user_data, s->msg, s->msg_len);
327 s->msg_len = 0;
328 }
329 break;
330 default:
331 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put byte value - %d!\n", byte);
332 break;
333 }
334 return;
335 }
336 if ((octet = adsi_decode_baudot(s, (uint8_t) (byte & 0x1F))))
337 s->msg[s->msg_len++] = octet;
338 if (s->msg_len >= 256)
339 {
340 s->put_msg(s->user_data, s->msg, s->msg_len);
341 s->msg_len = 0;
342 }
343 }
344 /*- End of function --------------------------------------------------------*/
345
346 static void adsi_rx_dtmf(void *user_data, const char *digits, int len)
347 {
348 adsi_rx_state_t *s;
349
350 s = (adsi_rx_state_t *) user_data;
351 if (s->msg_len == 0)
352 {
353 /* Message starting. Start a 10s timeout, to make things more noise
354 tolerant for a detector running continuously when on hook. */
355 s->in_progress = 80000;
356 }
357 /* It seems all the DTMF variants are a string of digits and letters,
358 terminated by a "#", or a "C". It appears these are unambiguous, and
359 non-conflicting. */
360 for ( ; len && s->msg_len < 256; len--)
361 {
362 s->msg[s->msg_len++] = *digits;
363 if (*digits == '#' || *digits == 'C')
364 {
365 s->put_msg(s->user_data, s->msg, s->msg_len);
366 s->msg_len = 0;
367 }
368 digits++;
369 }
370 }
371 /*- End of function --------------------------------------------------------*/
372
373 static void start_tx(adsi_tx_state_t *s)
374 {
375 switch (s->standard)
376 {
377 case ADSI_STANDARD_CLASS:
378 fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_BELL202], adsi_tx_get_bit, s);
379 break;
380 case ADSI_STANDARD_CLIP:
381 case ADSI_STANDARD_ACLIP:
382 case ADSI_STANDARD_JCLIP:
383 fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_V23CH1], adsi_tx_get_bit, s);
384 break;
385 case ADSI_STANDARD_CLIP_DTMF:
386 dtmf_tx_init(&(s->dtmftx));
387 break;
388 case ADSI_STANDARD_TDD:
389 fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
390 async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, adsi_tdd_get_async_byte, s);
391 /* Schedule an explicit shift at the start of baudot transmission */
392 s->baudot_shift = 2;
393 break;
394 }
395 s->tx_signal_on = TRUE;
396 }
397 /*- End of function --------------------------------------------------------*/
398
399 SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len)
400 {
401 switch (s->standard)
402 {
403 case ADSI_STANDARD_CLIP_DTMF:
404 /* Apply a message timeout. */
405 s->in_progress -= len;
406 if (s->in_progress <= 0)
407 s->msg_len = 0;
408 dtmf_rx(&(s->dtmfrx), amp, len);
409 break;
410 default:
411 fsk_rx(&(s->fskrx), amp, len);
412 break;
413 }
414 return 0;
415 }
416 /*- End of function --------------------------------------------------------*/
417
418 SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s,
419 int standard,
420 put_msg_func_t put_msg,
421 void *user_data)
422 {
423 if (s == NULL)
424 {
425 if ((s = (adsi_rx_state_t *) malloc(sizeof(*s))) == NULL)
426 return NULL;
427 }
428 memset(s, 0, sizeof(*s));
429 s->put_msg = put_msg;
430 s->user_data = user_data;
431 switch (standard)
432 {
433 case ADSI_STANDARD_CLASS:
434 fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_BELL202], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
435 break;
436 case ADSI_STANDARD_CLIP:
437 case ADSI_STANDARD_ACLIP:
438 case ADSI_STANDARD_JCLIP:
439 fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_V23CH1], FSK_FRAME_MODE_ASYNC, adsi_rx_put_bit, s);
440 break;
441 case ADSI_STANDARD_CLIP_DTMF:
442 dtmf_rx_init(&(s->dtmfrx), adsi_rx_dtmf, s);
443 break;
444 case ADSI_STANDARD_TDD:
445 /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
446 ride over the fraction. */
447 fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, adsi_tdd_put_async_byte, s);
448 break;
449 }
450 s->standard = standard;
451 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
452 return s;
453 }
454 /*- End of function --------------------------------------------------------*/
455
456 SPAN_DECLARE(int) adsi_rx_release(adsi_rx_state_t *s)
457 {
458 return 0;
459 }
460 /*- End of function --------------------------------------------------------*/
461
462 SPAN_DECLARE(int) adsi_rx_free(adsi_rx_state_t *s)
463 {
464 free(s);
465 return 0;
466 }
467 /*- End of function --------------------------------------------------------*/
468
469 SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
470 {
471 int len;
472 int lenx;
473
474 len = tone_gen(&(s->alert_tone_gen), amp, max_len);
475 if (s->tx_signal_on)
476 {
477 switch (s->standard)
478 {
479 case ADSI_STANDARD_CLIP_DTMF:
480 if (len < max_len)
481 len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
482 break;
483 default:
484 if (len < max_len)
485 {
486 if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
487 s->tx_signal_on = FALSE;
488 len += lenx;
489 }
490 break;
491 }
492 }
493 return len;
494 }
495 /*- End of function --------------------------------------------------------*/
496
497 SPAN_DECLARE(void) adsi_tx_send_alert_tone(adsi_tx_state_t *s)
498 {
499 tone_gen_init(&(s->alert_tone_gen), &(s->alert_tone_desc));
500 }
501 /*- End of function --------------------------------------------------------*/
502
503 SPAN_DECLARE(void) adsi_tx_set_preamble(adsi_tx_state_t *s,
504 int preamble_len,
505 int preamble_ones_len,
506 int postamble_ones_len,
507 int stop_bits)
508 {
509 if (preamble_len < 0)
510 {
511 if (s->standard == ADSI_STANDARD_JCLIP)
512 s->preamble_len = 0;
513 else
514 s->preamble_len = 300;
515 }
516 else
517 {
518 s->preamble_len = preamble_len;
519 }
520 if (preamble_ones_len < 0)
521 {
522 if (s->standard == ADSI_STANDARD_JCLIP)
523 s->preamble_ones_len = 75;
524 else
525 s->preamble_ones_len = 80;
526 }
527 else
528 {
529 s->preamble_ones_len = preamble_ones_len;
530 }
531 if (postamble_ones_len < 0)
532 {
533 if (s->standard == ADSI_STANDARD_JCLIP)
534 s->postamble_ones_len = 5;
535 else
536 s->postamble_ones_len = 5;
537 }
538 else
539 {
540 s->postamble_ones_len = postamble_ones_len;
541 }
542 if (stop_bits < 0)
543 {
544 if (s->standard == ADSI_STANDARD_JCLIP)
545 s->stop_bits = 4;
546 else
547 s->stop_bits = 1;
548 }
549 else
550 {
551 s->stop_bits = stop_bits;
552 }
553 }
554 /*- End of function --------------------------------------------------------*/
555
556 SPAN_DECLARE(int) adsi_tx_put_message(adsi_tx_state_t *s, const uint8_t *msg, int len)
557 {
558 int i;
559 int j;
560 int k;
561 int byte;
562 int parity;
563 int sum;
564 size_t ii;
565 uint16_t crc_value;
566
567 /* Don't inject a new message when a previous one is still in progress */
568 if (s->msg_len > 0)
569 return 0;
570 if (!s->tx_signal_on)
571 {
572 /* We need to restart the modem */
573 start_tx(s);
574 }
575 switch (s->standard)
576 {
577 case ADSI_STANDARD_CLIP_DTMF:
578 if (len >= 128)
579 return -1;
580 len -= (int) dtmf_tx_put(&(s->dtmftx), (char *) msg, len);
581 break;
582 case ADSI_STANDARD_JCLIP:
583 if (len > 128 - 9)
584 return -1;
585 i = 0;
586 s->msg[i++] = DLE;
587 s->msg[i++] = SOH;
588 s->msg[i++] = 0x07; //header
589 s->msg[i++] = DLE;
590 s->msg[i++] = STX;
591 s->msg[i++] = msg[0];
592 s->msg[i++] = (uint8_t) (len - 2);
593 /* We might need to byte stuff the overall length, but the rest of the
594 message should already be stuffed. */
595 if (len - 2 == DLE)
596 s->msg[i++] = DLE;
597 memcpy(&s->msg[i], &msg[2], len - 2);
598 i += len - 2;
599 s->msg[i++] = DLE;
600 s->msg[i++] = ETX;
601
602 /* Set the parity bits */
603 for (j = 0; j < i; j++)
604 {
605 byte = s->msg[j];
606 parity = 0;
607 for (k = 1; k <= 7; k++)
608 parity ^= (byte << k);
609 s->msg[j] = (s->msg[j] & 0x7F) | ((uint8_t) parity & 0x80);
610 }
611
612 crc_value = crc_itu16_calc(s->msg + 2, i - 2, 0);
613 s->msg[i++] = (uint8_t) (crc_value & 0xFF);
614 s->msg[i++] = (uint8_t) ((crc_value >> 8) & 0xFF);
615 s->msg_len = i;
616 break;
617 case ADSI_STANDARD_TDD:
618 if (len > 255)
619 return -1;
620 memcpy(s->msg, msg, len);
621 s->msg_len = len;
622 break;
623 default:
624 if (len > 255)
625 return -1;
626 memcpy(s->msg, msg, len);
627 /* Force the length in case it is wrong */
628 s->msg[1] = (uint8_t) (len - 2);
629 /* Add the sumcheck */
630 sum = 0;
631 for (ii = 0; ii < (size_t) len; ii++)
632 sum += s->msg[ii];
633 s->msg[len] = (uint8_t) ((-sum) & 0xFF);
634 s->msg_len = len + 1;
635 break;
636 }
637 /* Prepare the bit sequencing */
638 s->byte_no = 0;
639 s->bit_pos = 0;
640 s->bit_no = 0;
641 return len;
642 }
643 /*- End of function --------------------------------------------------------*/
644
645 SPAN_DECLARE(adsi_tx_state_t *) adsi_tx_init(adsi_tx_state_t *s, int standard)
646 {
647 if (s == NULL)
648 {
649 if ((s = (adsi_tx_state_t *) malloc(sizeof(*s))) == NULL)
650 return NULL;
651 }
652 memset(s, 0, sizeof(*s));
653 make_tone_gen_descriptor(&(s->alert_tone_desc),
654 2130,
655 -13,
656 2750,
657 -13,
658 110,
659 60,
660 0,
661 0,
662 FALSE);
663 s->standard = standard;
664 adsi_tx_set_preamble(s, -1, -1, -1, -1);
665 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
666 start_tx(s);
667 return s;
668 }
669 /*- End of function --------------------------------------------------------*/
670
671 SPAN_DECLARE(int) adsi_tx_release(adsi_tx_state_t *s)
672 {
673 return 0;
674 }
675 /*- End of function --------------------------------------------------------*/
676
677 SPAN_DECLARE(int) adsi_tx_free(adsi_tx_state_t *s)
678 {
679 free(s);
680 return 0;
681 }
682 /*- End of function --------------------------------------------------------*/
683
684 static uint16_t adsi_encode_baudot(adsi_tx_state_t *s, uint8_t ch)
685 {
686 static const uint8_t conv[128] =
687 {
688 0x00, /* NUL */
689 0xFF, /* */
690 0xFF, /* */
691 0xFF, /* */
692 0xFF, /* */
693 0xFF, /* */
694 0xFF, /* */
695 0xFF, /* */
696 0xFF, /* */
697 0xFF, /* */
698 0x42, /* LF */
699 0xFF, /* */
700 0xFF, /* */
701 0x48, /* CR */
702 0xFF, /* */
703 0xFF, /* */
704 0xFF, /* */
705 0xFF, /* */
706 0xFF, /* */
707 0xFF, /* */
708 0xFF, /* */
709 0xFF, /* */
710 0xFF, /* */
711 0xFF, /* */
712 0xFF, /* */
713 0xFF, /* */
714 0xFF, /* */
715 0xFF, /* */
716 0xFF, /* */
717 0xFF, /* */
718 0xFF, /* */
719 0xFF, /* */
720 0x44, /* */
721 0xFF, /* ! */
722 0xFF, /* " */
723 0x94, /* # */
724 0x89, /* $ */
725 0xFF, /* % */
726 0xFF, /* & */
727 0x85, /* ' */
728 0x8F, /* ( */
729 0x92, /* ) */
730 0x8B, /* * */
731 0x91, /* + */
732 0x8C, /* , */
733 0x83, /* - */
734 0x9C, /* . */
735 0x9D, /* / */
736 0x96, /* 0 */
737 0x97, /* 1 */
738 0x93, /* 2 */
739 0x81, /* 3 */
740 0x8A, /* 4 */
741 0x90, /* 5 */
742 0x95, /* 6 */
743 0x87, /* 7 */
744 0x86, /* 8 */
745 0x98, /* 9 */
746 0x8E, /* : */
747 0xFF, /* ; */
748 0xFF, /* < */
749 0x9E, /* = */
750 0xFF, /* > */
751 0x99, /* ? */
752 0xFF, /* @ */
753 0x03, /* A */
754 0x19, /* B */
755 0x0E, /* C */
756 0x09, /* D */
757 0x01, /* E */
758 0x0D, /* F */
759 0x1A, /* G */
760 0x14, /* H */
761 0x06, /* I */
762 0x0B, /* J */
763 0x0F, /* K */
764 0x12, /* L */
765 0x1C, /* M */
766 0x0C, /* N */
767 0x18, /* O */
768 0x16, /* P */
769 0x17, /* Q */
770 0x0A, /* R */
771 0x05, /* S */
772 0x10, /* T */
773 0x07, /* U */
774 0x1E, /* V */
775 0x13, /* W */
776 0x1D, /* X */
777 0x15, /* Y */
778 0x11, /* Z */
779 0xFF, /* [ */
780 0xFF, /* \ */
781 0xFF, /* ] */
782 0x9B, /* ^ */
783 0xFF, /* _ */
784 0xFF, /* ` */
785 0x03, /* a */
786 0x19, /* b */
787 0x0E, /* c */
788 0x09, /* d */
789 0x01, /* e */
790 0x0D, /* f */
791 0x1A, /* g */
792 0x14, /* h */
793 0x06, /* i */
794 0x0B, /* j */
795 0x0F, /* k */
796 0x12, /* l */
797 0x1C, /* m */
798 0x0C, /* n */
799 0x18, /* o */
800 0x16, /* p */
801 0x17, /* q */
802 0x0A, /* r */
803 0x05, /* s */
804 0x10, /* t */
805 0x07, /* u */
806 0x1E, /* v */
807 0x13, /* w */
808 0x1D, /* x */
809 0x15, /* y */
810 0x11, /* z */
811 0xFF, /* { */
812 0xFF, /* | */
813 0xFF, /* } */
814 0xFF, /* ~ */
815 0xFF, /* DEL */
816 };
817 uint16_t shift;
818
819 ch = conv[ch];
820 if (ch == 0xFF)
821 return 0;
822 if ((ch & 0x40))
823 return ch & 0x1F;
824 if ((ch & 0x80))
825 {
826 if (s->baudot_shift == 1)
827 return ch & 0x1F;
828 s->baudot_shift = 1;
829 shift = BAUDOT_FIGURE_SHIFT;
830 }
831 else
832 {
833 if (s->baudot_shift == 0)
834 return ch & 0x1F;
835 s->baudot_shift = 0;
836 shift = BAUDOT_LETTER_SHIFT;
837 }
838 return (shift << 5) | (ch & 0x1F);
839 }
840 /*- End of function --------------------------------------------------------*/
841
842 static uint8_t adsi_decode_baudot(adsi_rx_state_t *s, uint8_t ch)
843 {
844 static const uint8_t conv[2][32] =
845 {
846 {"\000E\nA SIU\rDRJNFCKTZLWHYPQOBG^MXV^"},
847 {"\0003\n- '87\r$4*,*:(5+)2#6019?*^./=^"}
848 };
849
850 switch (ch)
851 {
852 case BAUDOT_FIGURE_SHIFT:
853 s->baudot_shift = 1;
854 break;
855 case BAUDOT_LETTER_SHIFT:
856 s->baudot_shift = 0;
857 break;
858 default:
859 return conv[s->baudot_shift][ch];
860 }
861 /* return 0 if we did not produce a character */
862 return 0;
863 }
864 /*- End of function --------------------------------------------------------*/
865
866 SPAN_DECLARE(int) adsi_next_field(adsi_rx_state_t *s, const uint8_t *msg, int msg_len, int pos, uint8_t *field_type, uint8_t const **field_body, int *field_len)
867 {
868 int i;
869
870 /* Return -1 for no more fields. Return -2 for message structure corrupt. */
871 switch (s->standard)
872 {
873 case ADSI_STANDARD_CLASS:
874 case ADSI_STANDARD_CLIP:
875 case ADSI_STANDARD_ACLIP:
876 if (pos >= msg_len)
877 return -1;
878 /* For MDMF type messages, these standards all use "IE" type fields - type,
879 length, contents - and similar headers */
880 if (pos <= 0)
881 {
882 /* Return the message type */
883 *field_type = msg[0];
884 *field_len = 0;
885 *field_body = NULL;
886 pos = 2;
887 }
888 else
889 {
890 if ((msg[0] & 0x80))
891 {
892 /* MDMF messages seem to always have a message type with the MSB set. Is that
893 guaranteed? */
894 *field_type = msg[pos++];
895 *field_len = msg[pos++];
896 *field_body = msg + pos;
897 }
898 else
899 {
900 /* SDMF */
901 *field_type = 0;
902 *field_len = msg_len - pos;
903 *field_body = msg + pos;
904 }
905 pos += *field_len;
906 }
907 if (pos > msg_len)
908 return -2;
909 break;
910 case ADSI_STANDARD_JCLIP:
911 if (pos >= msg_len - 2)
912 return -1;
913 if (pos <= 0)
914 {
915 /* Return the message type */
916 pos = 5;
917 *field_type = msg[pos++];
918 if (*field_type == DLE)
919 pos++;
920 if (msg[pos++] == DLE)
921 pos++;
922 *field_len = 0;
923 *field_body = NULL;
924 }
925 else
926 {
927 *field_type = msg[pos++];
928 if (*field_type == DLE)
929 pos++;
930 *field_len = msg[pos++];
931 if (*field_len == DLE)
932 pos++;
933 /* TODO: we assume here that the body contains no DLE's that would have been stuffed */
934 *field_body = msg + pos;
935 pos += *field_len;
936 }
937 if (pos > msg_len - 2)
938 return -2;
939 break;
940 case ADSI_STANDARD_CLIP_DTMF:
941 if (pos > msg_len)
942 return -1;
943 if (pos <= 0)
944 {
945 pos = 1;
946 *field_type = msg[msg_len - 1];
947 *field_len = 0;
948 *field_body = NULL;
949 }
950 else
951 {
952 /* Remove bias on the pos value */
953 pos--;
954 if (msg[pos] >= '0' && msg[pos] <= '9')
955 *field_type = CLIP_DTMF_HASH_UNSPECIFIED;
956 else
957 *field_type = msg[pos++];
958 *field_body = msg + pos;
959 i = pos;
960 while (i < msg_len && msg[i] >= '0' && msg[i] <= '9')
961 i++;
962 *field_len = i - pos;
963 pos = i;
964 /* Check if we have reached the end of message marker. */
965 if (msg[pos] == '#' || msg[pos] == 'C')
966 pos++;
967 if (pos > msg_len)
968 return -2;
969 /* Bias the pos value, so we don't return 0 inappropriately */
970 pos++;
971 }
972 break;
973 case ADSI_STANDARD_TDD:
974 if (pos >= msg_len)
975 return -1;
976 *field_type = 0;
977 *field_body = msg;
978 *field_len = msg_len;
979 pos = msg_len;
980 break;
981 }
982 return pos;
983 }
984 /*- End of function --------------------------------------------------------*/
985
986 SPAN_DECLARE(int) adsi_add_field(adsi_tx_state_t *s, uint8_t *msg, int len, uint8_t field_type, uint8_t const *field_body, int field_len)
987 {
988 int i;
989 int x;
990
991 switch (s->standard)
992 {
993 case ADSI_STANDARD_CLASS:
994 case ADSI_STANDARD_CLIP:
995 case ADSI_STANDARD_ACLIP:
996 /* These standards all use "IE" type fields - type, length, value - and similar headers */
997 if (len <= 0)
998 {
999 /* Initialise a new message. The field type is actually the message type. */
1000 msg[0] = field_type;
1001 msg[1] = 0;
1002 len = 2;
1003 }
1004 else
1005 {
1006 /* Add to a message in progress. */
1007 if (field_type)
1008 {
1009 msg[len++] = field_type;
1010 msg[len++] = (uint8_t) field_len;
1011 if (field_len == DLE)
1012 msg[len++] = (uint8_t) field_len;
1013 memcpy(msg + len, field_body, field_len);
1014 len += field_len;
1015 }
1016 else
1017 {
1018 /* No field type or length, for restricted single message formats */
1019 memcpy(msg + len, field_body, field_len);
1020 len += field_len;
1021 }
1022 }
1023 break;
1024 case ADSI_STANDARD_JCLIP:
1025 /* This standard uses "IE" type fields - type, length, value - but escapes DLE characters,
1026 to prevent immitation of a control octet. */
1027 if (len <= 0)
1028 {
1029 /* Initialise a new message. The field type is actually the message type. */
1030 msg[0] = field_type;
1031 msg[1] = 0;
1032 len = 2;
1033 }
1034 else
1035 {
1036 /* Add to a message in progress. */
1037 msg[len++] = field_type;
1038 if (field_type == DLE)
1039 msg[len++] = field_type;
1040 msg[len++] = (uint8_t) field_len;
1041 if (field_len == DLE)
1042 msg[len++] = (uint8_t) field_len;
1043 for (i = 0; i < field_len; i++)
1044 {
1045 msg[len++] = field_body[i];
1046 if (field_body[i] == DLE)
1047 msg[len++] = field_body[i];
1048 }
1049 }
1050 break;
1051 case ADSI_STANDARD_CLIP_DTMF:
1052 if (len <= 0)
1053 {
1054 /* Initialise a new message. The field type is actually the message type. */
1055 msg[0] = field_type;
1056 len = 1;
1057 }
1058 else
1059 {
1060 /* Save and reuse the terminator/message type */
1061 x = msg[--len];
1062 if (field_type != CLIP_DTMF_HASH_UNSPECIFIED)
1063 msg[len++] = field_type;
1064 memcpy(msg + len, field_body, field_len);
1065 msg[len + field_len] = (uint8_t) x;
1066 len += (field_len + 1);
1067 }
1068 break;
1069 case ADSI_STANDARD_TDD:
1070 if (len < 0)
1071 len = 0;
1072 for (i = 0; i < field_len; i++)
1073 {
1074 if ((x = adsi_encode_baudot(s, field_body[i])))
1075 {
1076 if ((x & 0x3E0))
1077 msg[len++] = (uint8_t) ((x >> 5) & 0x1F);
1078 msg[len++] = (uint8_t) (x & 0x1F);
1079 }
1080 }
1081 break;
1082 }
1083
1084 return len;
1085 }
1086 /*- End of function --------------------------------------------------------*/
1087
1088 SPAN_DECLARE(const char *) adsi_standard_to_str(int standard)
1089 {
1090 switch (standard)
1091 {
1092 case ADSI_STANDARD_CLASS:
1093 return "CLASS";
1094 case ADSI_STANDARD_CLIP:
1095 return "CLIP";
1096 case ADSI_STANDARD_ACLIP:
1097 return "A-CLIP";
1098 case ADSI_STANDARD_JCLIP:
1099 return "J-CLIP";
1100 case ADSI_STANDARD_CLIP_DTMF:
1101 return "CLIP-DTMF";
1102 case ADSI_STANDARD_TDD:
1103 return "TDD";
1104 }
1105 return "???";
1106 }
1107 /*- End of function --------------------------------------------------------*/
1108 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.