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