Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |