From 7e8b1a03892198f1c9b02e7e065b65958fafd478 Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Fri, 29 Nov 2002 16:43:28 +0000
Subject: [PATCH] Version 0.3.0 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@558 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 callerid.c                  | 185 ++++++++++++++++++++++++++++--------
 include/asterisk/callerid.h |  23 +++--
 2 files changed, 160 insertions(+), 48 deletions(-)

diff --git a/callerid.c b/callerid.c
index 898396d861..f1827b76be 100755
--- a/callerid.c
+++ b/callerid.c
@@ -21,12 +21,11 @@
 #include <unistd.h>
 #include <math.h>
 #include <asterisk/ulaw.h>
+#include <asterisk/alaw.h>
+#include <asterisk/frame.h>
 #include <asterisk/callerid.h>
 #include <asterisk/logger.h>
 #include <asterisk/fskmodem.h>
-#include "sas.h"
-#include "cas.h"
-
 
 struct callerid_state {
 	fsk_data fskd;
@@ -46,9 +45,51 @@ struct callerid_state {
 
 float cid_dr[4], cid_di[4];
 float clidsb = 8000.0 / 1200.0;
+float sasdr, sasdi;
+float casdr1, casdi1, casdr2, casdi2;
 
 #define CALLERID_SPACE	2200.0		/* 2200 hz for "0" */
 #define CALLERID_MARK	1200.0		/* 1200 hz for "1" */
+#define SAS_FREQ		 440.0
+#define CAS_FREQ1		2130.0
+#define CAS_FREQ2		2750.0
+
+static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
+{
+	int x;
+	float t;
+	for (x=0;x<len;x++) {
+		t = *cr1 * ddr1 - *ci1 * ddi1;
+		*ci1 = *cr1 * ddi1 + *ci1 * ddr1;
+		*cr1 = t;
+		t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
+		*cr1 *= t;
+		*ci1 *= t; 	
+
+		t = *cr2 * ddr2 - *ci2 * ddi2;
+		*ci2 = *cr2 * ddi2 + *ci2 * ddr2;
+		*cr2 = t;
+		t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
+		*cr2 *= t;
+		*ci2 *= t; 	
+		buf[x] = AST_LIN2X((*cr1 + *cr2) * 8192.0);
+	}
+}
+
+static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
+{
+	int x;
+	float t;
+	for (x=0;x<len;x++) {
+		t = *cr1 * ddr1 - *ci1 * ddi1;
+		*ci1 = *cr1 * ddi1 + *ci1 * ddr1;
+		*cr1 = t;
+		t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
+		*cr1 *= t;
+		*ci1 *= t; 	
+		buf[x] = AST_LIN2X(*cr1 * 8192.0);
+	}
+}
 
 void callerid_init(void)
 {
@@ -57,6 +98,12 @@ void callerid_init(void)
 	cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
 	cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
 	cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
+	sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
+	sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
+	casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
+	casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
+	casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
+	casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
 }
 
 struct callerid_state *callerid_new(void)
@@ -99,36 +146,28 @@ void callerid_get(struct callerid_state *cid, char **name, char **number, int *f
 		*number = cid->number;
 }
 
-int ast_gen_cas(unsigned char *outbuf, int sendsas, int len)
+int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
 {
 	int pos = 0;
-	int cnt;
 	int saslen=2400;
+	float cr1 = 1.0;
+	float ci1 = 0.0;
+	float cr2 = 1.0;
+	float ci2 = 0.0;
 	if (sendsas) {
 		if (len < saslen)
 			return -1;
-		while(saslen) {
-			cnt = saslen;
-			if (cnt > sizeof(sas))
-				cnt = sizeof(sas);
-			memcpy(outbuf + pos, sas, cnt);
-			pos += cnt;
-			len -= cnt;
-			saslen -= cnt;
-		}
-	}
-	while(len) {
-		cnt = len;
-		if (cnt > sizeof(cas))
-			cnt = sizeof(cas);
-		memcpy(outbuf + pos, cas, cnt);
-		pos += cnt;
-		len -= cnt;
+		gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
+		len -= saslen;
+		pos += saslen;
+		cr2 = cr1;
+		ci2 = ci1;
 	}
+	gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
 	return 0;
 }
 
-int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
+int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
 {
 	int mylen = len;
 	int olen;
@@ -145,7 +184,7 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
 	memcpy(buf, cid->oldstuff, cid->oldlen);
 	mylen += cid->oldlen/2;
 	for (x=0;x<len;x++) 
-		buf[x+cid->oldlen/2] = AST_MULAW(ubuf[x]);
+		buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
 	while(mylen >= 80) {
 		olen = mylen;
 		res = fsk_serie(&cid->fskd, buf, &mylen, &b);
@@ -282,7 +321,7 @@ void callerid_free(struct callerid_state *cid)
 	free(cid);
 }
 
-static void callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
+static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
 {
 	time_t t;
 	struct tm *tm;
@@ -311,9 +350,9 @@ static void callerid_genmsg(char *msg, int size, char *number, char *name, int f
 		size -= res;
 		ptr += res;
 	} else {
-		/* Send up to 10 digits of number MAX */
+		/* Send up to 16 digits of number MAX */
 		i = strlen(number);
-		if (i > 10) i = 10;
+		if (i > 16) i = 16;
 		res = snprintf(ptr, size, "\002%c", i);
 		size -= res;
 		ptr += res;
@@ -335,7 +374,7 @@ static void callerid_genmsg(char *msg, int size, char *number, char *name, int f
 		size -= res;
 		ptr += res;
 	} else {
-		/* Send up to 10 digits of number MAX */
+		/* Send up to 16 digits of name MAX */
 		i = strlen(name);
 		if (i > 16) i = 16;
 		res = snprintf(ptr, size, "\007%c", i);
@@ -347,19 +386,80 @@ static void callerid_genmsg(char *msg, int size, char *number, char *name, int f
 		ptr += i;
 		size -= i;
 	}
+	return (ptr - msg);
 	
 }
 
-int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting)
+int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
+{
+	unsigned char msg[256];
+	int len=0;
+	int sum;
+	int x;
+	int bytes = 0;
+	float cr = 1.0;
+	float ci = 0.0;
+	float scont = 0.0;
+	if (mdmf) {
+		/* MDMF Message waiting */
+		msg[len++] = 0x82;
+		/* Length is 3 */
+		msg[len++] = 3;
+		/* IE is "Message Waiting Parameter" */
+		msg[len++] = 0xb;
+		/* Length of IE is one */
+		msg[len++] = 1;
+		/* Active or not */
+		if (active)
+			msg[len++] = 0xff;
+		else
+			msg[len++] = 0x00;
+	} else {
+		/* SDMF Message waiting */
+		msg[len++] = 0x6;
+		/* Length is 3 */
+		msg[len++] = 3;
+		if (active) {
+			msg[len++] = 0x42;
+			msg[len++] = 0x42;
+			msg[len++] = 0x42;
+		} else {
+			msg[len++] = 0x6f;
+			msg[len++] = 0x6f;
+			msg[len++] = 0x6f;
+		}
+	}
+	sum = 0;
+	for (x=0;x<len;x++)
+		sum += msg[x];
+	sum = (256 - (sum & 255));
+	msg[len++] = sum;
+	/* Transmit 30 0x55's (looks like a square wave) for channel seizure */
+	for (x=0;x<30;x++)
+		PUT_CLID(0x55);
+	/* Send 170ms of callerid marks */
+	for (x=0;x<170;x++)
+		PUT_CLID_MARKMS;
+	for (x=0;x<len;x++) {
+		PUT_CLID(msg[x]);
+	}
+	/* Send 50 more ms of marks */
+	for (x=0;x<50;x++)
+		PUT_CLID_MARKMS;
+	return bytes;
+}
+
+int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
 {
 	int bytes=0;
 	int x, sum;
+	int len;
 	/* Initial carriers (real/imaginary) */
 	float cr = 1.0;
 	float ci = 0.0;
 	float scont = 0.0;
-	char msg[256];
-	callerid_genmsg(msg, sizeof(msg), number, name, flags);
+	unsigned char msg[256];
+	len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
 	if (!callwaiting) {
 		/* Wait a half a second */
 		for (x=0;x<4000;x++)
@@ -374,15 +474,16 @@ int callerid_generate(unsigned char *buf, char *number, char *name, int flags, i
 	/* Send 0x80 indicating MDMF format */
 	PUT_CLID(0x80);
 	/* Put length of whole message */
-	PUT_CLID(strlen(msg));
+	PUT_CLID(len);
 	sum = 0x80 + strlen(msg);
 	/* Put each character of message and update checksum */
-	for (x=0;x<strlen(msg); x++) {
+	for (x=0;x<len; x++) {
 		PUT_CLID(msg[x]);
 		sum += msg[x];
 	}
 	/* Send 2's compliment of sum */
 	PUT_CLID(256 - (sum & 255));
+
 	/* Send 50 more ms of marks */
 	for (x=0;x<50;x++)
 		PUT_CLID_MARKMS;
@@ -455,30 +556,30 @@ int ast_callerid_parse(char *instr, char **name, char **location)
 	return -1;
 }
 
-static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callwaiting)
+static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callwaiting, int codec)
 {
 	char tmp[256];
 	char *n, *l;
 	if (!callerid)
-		return callerid_generate(buf, NULL, NULL, 0, callwaiting);
+		return callerid_generate(buf, NULL, NULL, 0, callwaiting, codec);
 	strncpy(tmp, callerid, sizeof(tmp)-1);
 	if (ast_callerid_parse(tmp, &n, &l)) {
 		ast_log(LOG_WARNING, "Unable to parse '%s' into CallerID name & number\n", callerid);
-		return callerid_generate(buf, NULL, NULL, 0, callwaiting);
+		return callerid_generate(buf, NULL, NULL, 0, callwaiting, codec);
 	}
 	if (l)
 		ast_shrink_phone_number(l);
 	if (!ast_isphonenumber(l))
-		return callerid_generate(buf, NULL, n, 0, callwaiting);
-	return callerid_generate(buf, l, n, 0, callwaiting);
+		return callerid_generate(buf, NULL, n, 0, callwaiting, codec);
+	return callerid_generate(buf, l, n, 0, callwaiting, codec);
 }
 
-int ast_callerid_generate(unsigned char *buf, char *callerid)
+int ast_callerid_generate(unsigned char *buf, char *callerid, int codec)
 {
-	return __ast_callerid_generate(buf, callerid, 0);
+	return __ast_callerid_generate(buf, callerid, 0, codec);
 }
 
-int ast_callerid_callwaiting_generate(unsigned char *buf, char *callerid)
+int ast_callerid_callwaiting_generate(unsigned char *buf, char *callerid, int codec)
 {
-	return __ast_callerid_generate(buf, callerid, 1);
+	return __ast_callerid_generate(buf, callerid, 1, codec);
 }
diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h
index 6d77e19ceb..8f8df457f5 100755
--- a/include/asterisk/callerid.h
+++ b/include/asterisk/callerid.h
@@ -24,6 +24,10 @@
 #define CID_UNKNOWN_NAME		(1 << 2)
 #define CID_UNKNOWN_NUMBER		(1 << 3)
 
+#define AST_LIN2X(a) ((codec == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a)))
+#define AST_XLAW(a) ((codec == AST_FORMAT_ALAW) ? (AST_ALAW(a)) : (AST_MULAW(a)))
+
+
 struct callerid_state;
 typedef struct callerid_state CIDSTATE;
 
@@ -39,10 +43,11 @@ extern void callerid_init(void);
  * \param number Use NULL for no number or "P" for "private"
  * \param name name to be used
  * \param callwaiting callwaiting flag
+ * \param codec -- either AST_FORMAT_ULAW or AST_FORMAT_ALAW
  * This function creates a stream of callerid (a callerid spill) data in ulaw format. It returns the size
  * (in bytes) of the data (if it returns a size of 0, there is probably an error)
 */
-extern int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting);
+extern int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec);
 
 //! Create a callerID state machine
 /*!
@@ -56,12 +61,13 @@ extern struct callerid_state *callerid_new(void);
  * \param cid Which state machine to act upon
  * \param buffer containing your samples
  * \param samples number of samples contained within the buffer.
+ * \param codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
  *
  * Send received audio to the Caller*ID demodulator.
  * Returns -1 on error, 0 for "needs more samples", 
  * and 1 if the CallerID spill reception is complete.
  */
-extern int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples);
+extern int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, int codec);
 
 //! Extract info out of callerID state machine.  Flags are listed above
 /*!
@@ -89,16 +95,20 @@ extern void callerid_free(struct callerid_state *cid);
 /*!
  * \param buf buffer for output samples. See callerid_generate() for details regarding buffer.
  * \param astcid Asterisk format callerid string, taken from the callerid field of asterisk.
+ * \param codec Asterisk codec (either AST_FORMAT_ALAW or AST_FORMAT_ULAW)
  *
  * Acts like callerid_generate except uses an asterisk format callerid string.
  */
-extern int ast_callerid_generate(unsigned char *buf, char *astcid);
+extern int ast_callerid_generate(unsigned char *buf, char *astcid, int codec);
+
+//! Generate message waiting indicator 
+extern int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec);
 
 //! Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
 /*!
  * See ast_callerid_generate for other details
  */
-extern int ast_callerid_callwaiting_generate(unsigned char *buf, char *astcid);
+extern int ast_callerid_callwaiting_generate(unsigned char *buf, char *astcid, int codec);
 
 //! Destructively parse inbuf into name and location (or number)
 /*!
@@ -115,9 +125,10 @@ extern int ast_callerid_parse(char *instr, char **name, char **location);
  * \param outbuf Allocated buffer for data.  Must be at least 2400 bytes unless no SAS is desired
  * \param sas Non-zero if CAS should be preceeded by SAS
  * \param len How many samples to generate.
+ * \param codec Which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
  * Returns -1 on error (if len is less than 2400), 0 on success.
  */
-extern int ast_gen_cas(unsigned char *outbuf, int sas, int len);
+extern int ast_gen_cas(unsigned char *outbuf, int sas, int len, int codec);
 
 //! Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
 /*!
@@ -164,7 +175,7 @@ static inline float callerid_getcarrier(float *cr, float *ci, int bit)
 
 #define PUT_AUDIO_SAMPLE(y) do { \
 	int index = (short)(rint(8192.0 * (y))); \
-	*(buf++) = AST_LIN2MU(index); \
+	*(buf++) = AST_LIN2X(index); \
 	bytes++; \
 } while(0)
 	
-- 
GitLab