00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
00037
00038 #include <time.h>
00039 #include <math.h>
00040 #include <ctype.h>
00041
00042 #include "asterisk/logger.h"
00043 #include "asterisk/ulaw.h"
00044 #include "asterisk/tdd.h"
00045 #include "asterisk/fskmodem.h"
00046 #include "ecdisa.h"
00047
00048 struct tdd_state {
00049 fsk_data fskd;
00050 char rawdata[256];
00051 short oldstuff[4096];
00052 int oldlen;
00053 int pos;
00054 int modo;
00055 int mode;
00056 int charnum;
00057 };
00058
00059 static float dr[4], di[4];
00060 static float tddsb = 176.0;
00061
00062 #define TDD_SPACE 1800.0
00063 #define TDD_MARK 1400.0
00064
00065 static int tdd_decode_baudot(struct tdd_state *tdd,unsigned char data)
00066 {
00067 static char ltrs[32] = { '<','E','\n','A',' ','S','I','U',
00068 '\n','D','R','J','N','F','C','K',
00069 'T','Z','L','W','H','Y','P','Q',
00070 'O','B','G','^','M','X','V','^' };
00071 static char figs[32] = { '<','3','\n','-',' ','\'','8','7',
00072 '\n','$','4','\'',',','!',':','(',
00073 '5','\"',')','2','=','6','0','1',
00074 '9','?','+','^','.','/',';','^' };
00075 int d = 0;
00076 if (data < 32) {
00077 switch (data) {
00078 case 0x1f:
00079 tdd->modo = 0;
00080 break;
00081 case 0x1b:
00082 tdd->modo = 1;
00083 break;
00084 default:
00085 if (tdd->modo == 0)
00086 d = ltrs[data];
00087 else
00088 d = figs[data];
00089 break;
00090 }
00091 }
00092 return d;
00093 }
00094
00095 void tdd_init(void)
00096 {
00097
00098 dr[0] = cos(TDD_SPACE * 2.0 * M_PI / 8000.0);
00099 di[0] = sin(TDD_SPACE * 2.0 * M_PI / 8000.0);
00100 dr[1] = cos(TDD_MARK * 2.0 * M_PI / 8000.0);
00101 di[1] = sin(TDD_MARK * 2.0 * M_PI / 8000.0);
00102 }
00103
00104 struct tdd_state *tdd_new(void)
00105 {
00106 struct tdd_state *tdd;
00107 tdd = calloc(1, sizeof(*tdd));
00108 if (tdd) {
00109 #ifdef INTEGER_CALLERID
00110 tdd->fskd.ispb = 176;
00111
00112 tdd->fskd.pllispb = (int)((8000 * 32 * 2) / 90);
00113 tdd->fskd.pllids = tdd->fskd.pllispb / 32;
00114 tdd->fskd.pllispb2 = tdd->fskd.pllispb / 2;
00115 tdd->fskd.hdlc = 0;
00116 tdd->fskd.nbit = 5;
00117 tdd->fskd.instop = 1;
00118 tdd->fskd.parity = 0;
00119 tdd->fskd.bw=0;
00120 tdd->fskd.f_mark_idx = 0;
00121 tdd->fskd.f_space_idx = 1;
00122 tdd->fskd.xi0 = 0;
00123 tdd->fskd.state = 0;
00124 tdd->pos = 0;
00125 tdd->mode = 0;
00126 fskmodem_init(&tdd->fskd);
00127 #else
00128 tdd->fskd.spb = 176;
00129 tdd->fskd.hdlc = 0;
00130 tdd->fskd.nbit = 5;
00131 tdd->fskd.nstop = 1.5;
00132 tdd->fskd.parity = 0;
00133 tdd->fskd.bw=0;
00134 tdd->fskd.f_mark_idx = 0;
00135 tdd->fskd.f_space_idx = 1;
00136 tdd->fskd.pcola = 0;
00137 tdd->fskd.cont = 0;
00138 tdd->fskd.x0 = 0.0;
00139 tdd->fskd.state = 0;
00140 tdd->pos = 0;
00141 tdd->mode = 2;
00142 #endif
00143 tdd->charnum = 0;
00144 } else
00145 ast_log(LOG_WARNING, "Out of memory\n");
00146 return tdd;
00147 }
00148
00149 int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
00150 {
00151 int pos = 0;
00152 int cnt;
00153 while (len) {
00154 cnt = len > sizeof(ecdisa) ? sizeof(ecdisa) : len;
00155 memcpy(outbuf + pos, ecdisa, cnt);
00156 pos += cnt;
00157 len -= cnt;
00158 }
00159 return 0;
00160 }
00161
00162 int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int len)
00163 {
00164 int mylen = len;
00165 int olen;
00166 int b = 'X';
00167 int res;
00168 int c,x;
00169 short *buf = calloc(1, 2 * len + tdd->oldlen);
00170 short *obuf = buf;
00171 if (!buf) {
00172 ast_log(LOG_WARNING, "Out of memory\n");
00173 return -1;
00174 }
00175 memcpy(buf, tdd->oldstuff, tdd->oldlen);
00176 mylen += tdd->oldlen / 2;
00177 for (x = 0; x < len; x++)
00178 buf[x + tdd->oldlen / 2] = AST_MULAW(ubuf[x]);
00179 c = res = 0;
00180 while (mylen >= 1320) {
00181 olen = mylen;
00182 res = fsk_serial(&tdd->fskd, buf, &mylen, &b);
00183 if (mylen < 0) {
00184 ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d) (olen was %d)\n", mylen, olen);
00185 free(obuf);
00186 return -1;
00187 }
00188 buf += (olen - mylen);
00189 if (res < 0) {
00190 ast_log(LOG_NOTICE, "fsk_serial failed\n");
00191 free(obuf);
00192 return -1;
00193 }
00194 if (res == 1) {
00195
00196 if (b > 0x7f)
00197 continue;
00198 c = tdd_decode_baudot(tdd, b);
00199 if ((c < 1) || (c > 126))
00200 continue;
00201 break;
00202 }
00203 }
00204 if (mylen) {
00205 memcpy(tdd->oldstuff, buf, mylen * 2);
00206 tdd->oldlen = mylen * 2;
00207 } else
00208 tdd->oldlen = 0;
00209 free(obuf);
00210 if (res) {
00211 tdd->mode = 2;
00212
00213
00214 return(c);
00215 }
00216 return 0;
00217 }
00218
00219 void tdd_free(struct tdd_state *tdd)
00220 {
00221 free(tdd);
00222 }
00223
00224 static inline float tdd_getcarrier(float *cr, float *ci, int bit)
00225 {
00226
00227 float t;
00228 t = *cr * dr[bit] - *ci * di[bit];
00229 *ci = *cr * di[bit] + *ci * dr[bit];
00230 *cr = t;
00231
00232 t = 2.0 - (*cr * *cr + *ci * *ci);
00233 *cr *= t;
00234 *ci *= t;
00235 return *cr;
00236 }
00237
00238 #define PUT_BYTE(a) do { \
00239 *(buf++) = (a); \
00240 bytes++; \
00241 } while(0)
00242
00243 #define PUT_AUDIO_SAMPLE(y) do { \
00244 int __pas_idx = (short)(rint(8192.0 * (y))); \
00245 *(buf++) = AST_LIN2MU(__pas_idx); \
00246 bytes++; \
00247 } while(0)
00248
00249 #define PUT_TDD_MARKMS do { \
00250 int x; \
00251 for (x = 0; x < 8; x++) \
00252 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
00253 } while(0)
00254
00255 #define PUT_TDD_BAUD(bit) do { \
00256 while (scont < tddsb) { \
00257 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, bit)); \
00258 scont += 1.0; \
00259 } \
00260 scont -= tddsb; \
00261 } while(0)
00262
00263 #define PUT_TDD_STOP do { \
00264 while (scont < (tddsb * 1.5)) { \
00265 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
00266 scont += 1.0; \
00267 } \
00268 scont -= (tddsb * 1.5); \
00269 } while(0)
00270
00271
00272 #define PUT_TDD(byte) do { \
00273 int z; \
00274 unsigned char b = (byte); \
00275 PUT_TDD_BAUD(0); \
00276 for (z = 0; z < 5; z++) { \
00277 PUT_TDD_BAUD(b & 1); \
00278 b >>= 1; \
00279 } \
00280 PUT_TDD_STOP; \
00281 } while(0);
00282
00283
00284
00285
00286 int tdd_gen_holdtone(unsigned char *buf)
00287 {
00288 int bytes = 0;
00289 float scont = 0.0, cr = 1.0, ci=0.0;
00290 while (scont < tddsb * 10.0) {
00291 PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1));
00292 scont += 1.0;
00293 }
00294 return bytes;
00295 }
00296
00297 int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *str)
00298 {
00299 int bytes = 0;
00300 int i,x;
00301 char c;
00302
00303 static unsigned char lstr[31] = "\000E\nA SIU\rDRJNFCKTZLWHYPQOBG\000MXV";
00304
00305 static unsigned char fstr[31] = "\0003\n- \00787\r$4',!:(5\")2\0006019?+\000./;";
00306
00307 float cr = 1.0;
00308 float ci = 0.0;
00309 float scont = 0.0;
00310
00311 for(x = 0; str[x]; x++) {
00312
00313 if ( (tdd->charnum++) % 72 == 0)
00314 PUT_TDD(tdd->mode ? 27 : 31 );
00315
00316 c = toupper(str[x]);
00317 #if 0
00318 printf("%c",c); fflush(stdout);
00319 #endif
00320 if (c == 0) {
00321 PUT_TDD(0);
00322 continue;
00323 }
00324 if (c == '\r') {
00325 PUT_TDD(8);
00326 continue;
00327 }
00328 if (c == '\n') {
00329 PUT_TDD(8);
00330 PUT_TDD(2);
00331 continue;
00332 }
00333 if (c == ' ') {
00334 PUT_TDD(4);
00335 continue;
00336 }
00337 for (i = 0; i < 31; i++) {
00338 if (lstr[i] == c)
00339 break;
00340 }
00341 if (i < 31) {
00342 if (tdd->mode) {
00343 PUT_TDD(31);
00344 tdd->mode = 0;
00345 }
00346 PUT_TDD(i);
00347 continue;
00348 }
00349 for (i = 0; i < 31; i++) {
00350 if (fstr[i] == c)
00351 break;
00352 }
00353 if (i < 31) {
00354 if (tdd->mode != 1) {
00355 PUT_TDD(27);
00356 tdd->mode = 1;
00357 }
00358 PUT_TDD(i);
00359 continue;
00360 }
00361 }
00362 return bytes;
00363 }
00364