[svn-commits] jdixon: branch 1.4 r82366 - in /branches/1.4: apps/ channels/ channels/xpmr/ ...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Sep 13 19:34:13 CDT 2007


Author: jdixon
Date: Thu Sep 13 19:34:13 2007
New Revision: 82366

URL: http://svn.digium.com/view/asterisk?view=rev&rev=82366
Log:
Added channel driver for USB Radio device and
support thereof.

Added:
    branches/1.4/channels/chan_usbradio.c   (with props)
    branches/1.4/channels/xpmr/
    branches/1.4/channels/xpmr/LICENSE   (with props)
    branches/1.4/channels/xpmr/sinetabx.h   (with props)
    branches/1.4/channels/xpmr/xpmr.c   (with props)
    branches/1.4/channels/xpmr/xpmr.h   (with props)
    branches/1.4/channels/xpmr/xpmr_coef.h   (with props)
    branches/1.4/configs/usbradio.conf.sample   (with props)
Modified:
    branches/1.4/apps/app_rpt.c
    branches/1.4/channels/Makefile

Modified: branches/1.4/apps/app_rpt.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/apps/app_rpt.c?view=diff&rev=82366&r1=82365&r2=82366
==============================================================================
--- branches/1.4/apps/app_rpt.c (original)
+++ branches/1.4/apps/app_rpt.c Thu Sep 13 19:34:13 2007
@@ -18,11 +18,10 @@
  * the GNU General Public License Version 2. See the LICENSE file
  * at the top of the source tree.
  */
-
 /*! \file
  *
  * \brief Radio Repeater / Remote Base program 
- *  version 0.70 07/22/07
+ *  version 0.73 09/04/07
  * 
  * \author Jim Dixon, WB6NIL <jim at lambdatel.com>
  *
@@ -179,7 +178,7 @@
 
 #define	RETRY_TIMER_MS 5000
 
-#define	START_DELAY 10
+#define	START_DELAY 2
 
 #define MAXPEERSTR 31
 #define	MAXREMSTR 15
@@ -226,6 +225,8 @@
 #define	DTMF_LOCAL_STARTTIME 500
 
 #define	IC706_PL_MEMORY_OFFSET 50
+
+#define	ALLOW_LOCAL_CHANNELS
 
 enum {REM_OFF,REM_MONITOR,REM_TX};
 
@@ -301,6 +302,7 @@
 #include "asterisk/say.h"
 #include "asterisk/localtime.h"
 #include "asterisk/cdr.h"
+#include "asterisk/options.h"
 #include <termios.h>
 
 /* Start a tone-list going */
@@ -308,7 +310,7 @@
 /*! Stop the tones from playing */
 void ast_playtones_stop(struct ast_channel *chan);
 
-static  char *tdesc = "Radio Repeater / Remote Base  version 0.70  07/22/2007";
+static  char *tdesc = "Radio Repeater / Remote Base  version 0.73  09/04/2007";
 
 static char *app = "Rpt";
 
@@ -591,7 +593,7 @@
 	char lastdtmfcommand[MAXDTMF];
 	char cmdnode[50];
 	struct ast_channel *rxchannel,*txchannel, *monchannel;
-	struct ast_channel *pchannel,*txpchannel;
+	struct ast_channel *pchannel,*txpchannel, *zaprxchannel, *zaptxchannel;
 	struct ast_frame *lastf1,*lastf2;
 	struct rpt_tele tele;
 	struct timeval lasttv,curtv;
@@ -1186,6 +1188,57 @@
 		ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
 	return(fd);	
 }
+
+static void mdc1200_notify(struct rpt *myrpt,char *fromnode, unsigned int unit)
+{
+	if (!fromnode)
+	{
+		ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
+			unit,myrpt->name);
+	}
+	else
+	{
+		ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
+			unit,fromnode,myrpt->name);
+	}
+}
+
+#ifdef	_MDC_DECODE_H_
+
+static void mdc1200_send(struct rpt *myrpt, unsigned int unit)
+{
+struct rpt_link *l;
+struct	ast_frame wf;
+char	str[200];
+
+
+	sprintf(str,"I %s %04X",myrpt->name,unit);
+
+	wf.frametype = AST_FRAME_TEXT;
+	wf.subclass = 0;
+	wf.offset = 0;
+	wf.mallocd = 0;
+	wf.datalen = strlen(str) + 1;
+	wf.samples = 0;
+
+
+	l = myrpt->links.next;
+	/* otherwise, send it to all of em */
+	while(l != &myrpt->links)
+	{
+		if (l->name[0] == '0') 
+		{
+			l = l->next;
+			continue;
+		}
+		wf.data = str;
+		if (l->chan) ast_write(l->chan,&wf); 
+		l = l->next;
+	}
+	return;
+}
+
+#endif
 
 static char func_xlat(struct rpt *myrpt,char c,struct rpt_xlat *xlat)
 {
@@ -3113,7 +3166,7 @@
 				 	ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);		
 			}	
 		}
-#ifdef	_MDC_DECODE_H_
+#if	defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
 		if (myrpt->lastunit)
 		{
 			char mystr[10];
@@ -3334,14 +3387,14 @@
 				break;
 			}
 			i = ZT_FLUSH_EVENT;
-			if (ioctl(myrpt->txchannel->fds[0],ZT_FLUSH,&i) == -1)
+			if (ioctl(myrpt->zaptxchannel->fds[0],ZT_FLUSH,&i) == -1)
 			{
 				ast_mutex_unlock(&myrpt->remlock);
 				ast_log(LOG_ERROR,"Cant flush events");
 				res = -1;
 				break;
 			}
-			if (ioctl(myrpt->rxchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
+			if (ioctl(myrpt->zaprxchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
 			{
 				ast_mutex_unlock(&myrpt->remlock);
 				ast_log(LOG_ERROR,"Cant get params");
@@ -4490,7 +4543,14 @@
 	l->isremote = (s && ast_true(s));
 	if (modechange) l->connected = 1;
 	l->hasconnected = l->perma = perma;
+#ifdef ALLOW_LOCAL_CHANNELS
+	if ((strncasecmp(s1,"iax2/", 5) == 0) || (strncasecmp(s1, "local/", 6) == 0))
+        	strncpy(deststr, s1, sizeof(deststr));
+	else
+	        snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
+#else
 	snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
+#endif
 	tele = strchr(deststr, '/');
 	if (!tele){
 		ast_log(LOG_WARNING,"link3:Dial number (%s) must be in format tech/number\n",deststr);
@@ -4771,6 +4831,14 @@
 			break;
 
 
+#ifdef	_MDC_DECODE_H_
+		case 8:
+			myrpt->lastunit = 0xd00d; 
+			mdc1200_notify(myrpt,NULL,myrpt->lastunit);
+			mdc1200_send(myrpt,myrpt->lastunit);
+			break;
+#endif
+
 		case 16: /* Restore links disconnected with "disconnect all links" command */
 			strcpy(tmp, myrpt->savednodes); /* Make a copy */
 			finddelim(tmp, strs, MAXLINKLIST); /* convert into substrings */
@@ -5253,15 +5321,28 @@
 			myrpt->name,tmp,mylink->name);
 		return;
 	}
-	if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
-	{
-		ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
-		return;
-	}
-	if (strcmp(cmd,"D"))
-	{
-		ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
-		return;
+	if (tmp[0] == 'I')
+	{
+		if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
+		{
+			ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
+			return;
+		}
+		mdc1200_notify(myrpt,src,seq);
+		strcpy(dest,"*");
+	}
+	else
+	{
+		if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
+		{
+			ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
+			return;
+		}
+		if (strcmp(cmd,"D"))
+		{
+			ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
+			return;
+		}
 	}
 	if (dest[0] == '0')
 	{
@@ -5727,6 +5808,7 @@
 
 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
     {
+#ifdef __i386__
     int i,j;
     unsigned char od,d;
     static volatile long long delayvar;
@@ -5749,6 +5831,7 @@
         }
 	/* >= 50 us */
         for(delayvar = 1; delayvar < 50000; delayvar++); 
+#endif
     }
 
 static void rbi_out(struct rpt *myrpt,unsigned char *data)
@@ -5759,16 +5842,16 @@
 	r.radpar = ZT_RADPAR_REMMODE;
 	r.data = ZT_RADPAR_REM_RBI1;
 	/* if setparam ioctl fails, its probably not a pciradio card */
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
 	{
 		rbi_out_parallel(myrpt,data);
 		return;
 	}
 	r.radpar = ZT_RADPAR_REMCOMMAND;
 	memcpy(&r.data,data,5);
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
-	{
-		ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name);
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
+	{
+		ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->zaprxchannel->name);
 		return;
 	}
 }
@@ -5803,36 +5886,39 @@
 				if (c == '\r') break;
 			}
 		}					
-	if(debug){
-		printf("String returned was: ");
-		for(j = 0; j < i; j++)
-			printf("%02X ", (unsigned char ) rxbuf[j]);
-		printf("\n");
-	}
+		if(debug){
+			printf("String returned was: ");
+			for(j = 0; j < i; j++)
+				printf("%02X ", (unsigned char ) rxbuf[j]);
+			printf("\n");
+		}
 		return(i);
 	}
-	
+
+	/* if not a zap channel, cant use pciradio stuff */
+	if (myrpt->rxchannel != myrpt->zaprxchannel) return -1;	
+
 	prm.radpar = ZT_RADPAR_UIOMODE;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
 	oldmode = prm.data;
 	prm.radpar = ZT_RADPAR_UIODATA;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_GETPARAM,&prm) == -1) return -1;
 	olddata = prm.data;
         prm.radpar = ZT_RADPAR_REMMODE;
         if (asciiflag & 1)  prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
         else prm.data = ZT_RADPAR_REM_SERIAL;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
 	if (asciiflag & 2)
 	{
 		i = ZT_ONHOOK;
-		if (ioctl(myrpt->rxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
+		if (ioctl(myrpt->zaprxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
 		usleep(100000);
 	}
         prm.radpar = ZT_RADPAR_REMCOMMAND;
         prm.data = rxmaxbytes;
         memcpy(prm.buf,txbuf,txbytes);
         prm.index = txbytes;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
         if (rxbuf)
         {
                 *rxbuf = 0;
@@ -5841,18 +5927,18 @@
 	index = prm.index;
         prm.radpar = ZT_RADPAR_REMMODE;
         prm.data = ZT_RADPAR_REM_NONE;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
 	if (asciiflag & 2)
 	{
 		i = ZT_OFFHOOK;
-		if (ioctl(myrpt->rxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
+		if (ioctl(myrpt->zaprxchannel->fds[0],ZT_HOOK,&i) == -1) return -1;
 	}
 	prm.radpar = ZT_RADPAR_UIOMODE;
 	prm.data = oldmode;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
 	prm.radpar = ZT_RADPAR_UIODATA;
 	prm.data = olddata;
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
+	if (ioctl(myrpt->zaprxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
         return(index);
 }
 
@@ -8238,6 +8324,19 @@
  	/* put string in our buffer */
 	strncpy(tmp,str,sizeof(tmp) - 1);
 	if (!strcmp(tmp,discstr)) return 0;
+
+#ifndef	DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
+	if (tmp[0] == 'I')
+	{
+		if (sscanf(tmp,"%s %s %x",cmd,src,&seq) != 3)
+		{
+			ast_log(LOG_WARNING, "Unable to parse ident string %s\n",str);
+			return 0;
+		}
+		mdc1200_notify(myrpt,src,seq);
+		return 0;
+	}
+#endif
 	if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
 	{
 		ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
@@ -8645,7 +8744,6 @@
 
 }
 
-
 /* single thread with one file (request) to dial */
 static void *rpt(void *this)
 {
@@ -8694,6 +8792,9 @@
 	}
 	*tele++ = 0;
 	myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
+	myrpt->zaprxchannel = NULL;
+	if (!strcasecmp(tmpstr,"Zap"))
+		myrpt->zaprxchannel = myrpt->rxchannel;
 	if (myrpt->rxchannel)
 	{
 		if (myrpt->rxchannel->_state == AST_STATE_BUSY)
@@ -8728,6 +8829,7 @@
 		myrpt->rpt_thread = AST_PTHREADT_STOP;
 		pthread_exit(NULL);
 	}
+	myrpt->zaptxchannel = NULL;
 	if (myrpt->txchanname)
 	{
 		strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
@@ -8742,6 +8844,8 @@
 		}
 		*tele++ = 0;
 		myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
+		if (!strcasecmp(tmpstr,"Zap"))
+			myrpt->zaptxchannel = myrpt->txchannel;
 		if (myrpt->txchannel)
 		{
 			if (myrpt->txchannel->_state == AST_STATE_BUSY)
@@ -8798,6 +8902,24 @@
 		myrpt->rpt_thread = AST_PTHREADT_STOP;
 		pthread_exit(NULL);
 	}
+	if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
+	if (!myrpt->zaptxchannel)
+	{
+		/* allocate a pseudo-channel thru asterisk */
+		myrpt->zaptxchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+		if (!myrpt->zaptxchannel)
+		{
+			fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+			rpt_mutex_unlock(&myrpt->lock);
+			if (myrpt->txchannel != myrpt->rxchannel) 
+				ast_hangup(myrpt->txchannel);
+			ast_hangup(myrpt->rxchannel);
+			myrpt->rpt_thread = AST_PTHREADT_STOP;
+			pthread_exit(NULL);
+		}
+		ast_set_read_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
+		ast_set_write_format(myrpt->zaptxchannel,AST_FORMAT_SLINEAR);
+	}
 	/* allocate a pseudo-channel thru asterisk */
 	myrpt->monchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
 	if (!myrpt->monchannel)
@@ -8817,7 +8939,7 @@
 	ci.confno = -1; /* make a new conf */
 	ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
 	/* first put the channel on the conference in proper mode */
-	if (ioctl(myrpt->txchannel->fds[0],ZT_SETCONF,&ci) == -1)
+	if (ioctl(myrpt->zaptxchannel->fds[0],ZT_SETCONF,&ci) == -1)
 	{
 		ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
 		rpt_mutex_unlock(&myrpt->lock);
@@ -8853,7 +8975,8 @@
 	myrpt->conf = ci.confno;
 	/* make a conference for the pseudo */
 	ci.chan = 0;
-	if (strstr(myrpt->txchannel->name,"pseudo") == NULL)
+	if ((strstr(myrpt->txchannel->name,"pseudo") == NULL) &&
+		(myrpt->zaptxchannel == myrpt->txchannel))
 	{
 		/* get tx channel's port number */
 		if (ioctl(myrpt->txchannel->fds[0],ZT_CHANNO,&ci.confno) == -1)
@@ -9059,6 +9182,7 @@
 		if (ast_check_hangup(myrpt->pchannel)) break;
 		if (ast_check_hangup(myrpt->monchannel)) break;
 		if (ast_check_hangup(myrpt->txpchannel)) break;
+		if (myrpt->zaptxchannel && ast_check_hangup(myrpt->zaptxchannel)) break;
 
 		/* Set local tx with keyed */
 		myrpt->localtx = myrpt->keyed;
@@ -9316,6 +9440,8 @@
 		cs[n++] = myrpt->monchannel;
 		cs[n++] = myrpt->txpchannel;
 		if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
+		if (myrpt->zaptxchannel != myrpt->txchannel)
+			cs[n++] = myrpt->zaptxchannel;
 		l = myrpt->links.next;
 		while(l != &myrpt->links)
 		{
@@ -9609,6 +9735,8 @@
 						if ((op == 1) && (arg == 0))
 						{
 							myrpt->lastunit = unitID;
+							mdc1200_notify(myrpt,NULL,myrpt->lastunit);
+							mdc1200_send(myrpt,myrpt->lastunit);
 						}
 				}
 				if ((debug > 2) && (i == 2))
@@ -9629,7 +9757,7 @@
 				/* apply inbound filters, if any */
 				rpt_filter(myrpt,f->data,f->datalen / 2);
 #endif
-				if (ioctl(myrpt->rxchannel->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
+				if (ioctl(myrpt->zaprxchannel->fds[0], ZT_GETCONFMUTE, &ismuted) == -1)
 				{
 					ismuted = 0;
 				}
@@ -9757,6 +9885,30 @@
 			{
 				if (debug) printf("@@@@ rpt:Hung Up\n");
 				break;
+			}
+			if (f->frametype == AST_FRAME_CONTROL)
+			{
+				if (f->subclass == AST_CONTROL_HANGUP)
+				{
+					if (debug) printf("@@@@ rpt:Hung Up\n");
+					ast_frfree(f);
+					break;
+				}
+			}
+			ast_frfree(f);
+			continue;
+		}
+		if (who == myrpt->zaptxchannel) /* if it was a read from pseudo-tx */
+		{
+			f = ast_read(myrpt->zaptxchannel);
+			if (!f)
+			{
+				if (debug) printf("@@@@ rpt:Hung Up\n");
+				break;
+			}
+			if (f->frametype == AST_FRAME_VOICE)
+			{
+				ast_write(myrpt->txchannel,f);
 			}
 			if (f->frametype == AST_FRAME_CONTROL)
 			{
@@ -10178,6 +10330,7 @@
 	ast_hangup(myrpt->monchannel);
 	ast_hangup(myrpt->txpchannel);
 	if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
+	if (myrpt->zaptxchannel != myrpt->txchannel) ast_hangup(myrpt->zaptxchannel);
 	if (myrpt->lastf1) ast_frfree(myrpt->lastf1);
 	myrpt->lastf1 = NULL;
 	if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
@@ -10216,6 +10369,9 @@
 	/* go thru all the specified repeaters */
 	this = NULL;
 	n = 0;
+	/* wait until asterisk starts */
+        while(!ast_test_flag(&ast_options,AST_OPT_FLAG_FULLY_BOOTED))
+                usleep(250000);
 	rpt_vars[n].cfg = ast_config_load("rpt.conf");
 	cfg = rpt_vars[n].cfg;
 	if (!cfg) {
@@ -10395,6 +10551,7 @@
 		ast_log(LOG_WARNING, "Rpt requires an argument (system node)\n");
 		return -1;
 	}
+
 	strncpy(tmp, (char *)data, sizeof(tmp)-1);
 	time(&t);
 	/* if time has externally shifted negative, screw it */
@@ -10443,11 +10600,19 @@
 	}
 	else
 	{
+#ifdef ALLOW_LOCAL_CHANNELS
+	        /* Check to insure the connection is IAX2 or Local*/
+	        if ( (strncmp(chan->name,"IAX2",4)) && (strncmp(chan->name,"Local",5)) ) {
+	            ast_log(LOG_WARNING, "We only accept links via IAX2 or Local!!\n");
+	            return -1;
+	        }
+#else
 		if (strncmp(chan->name,"IAX2",4))
 		{
 			ast_log(LOG_WARNING, "We only accept links via IAX2!!\n");
 			return -1;
 		}
+#endif
 	}
 	if (options && (*options == 'R'))
 	{
@@ -10581,7 +10746,17 @@
 
 		/* get his IP from IAX2 module */
 		memset(hisip,0,sizeof(hisip));
+#ifdef ALLOW_LOCAL_CHANNELS
+	        /* set IP address if this is a local connection*/
+	        if (strncmp(chan->name,"Local",5)==0) {
+	            strcpy(hisip,"127.0.0.1");
+	        } else {
+			pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
+		}
+#else
 		pbx_substitute_variables_helper(chan,"${IAXPEER(CURRENTCHANNEL)}",hisip,sizeof(hisip) - 1);
+#endif
+
 		if (!hisip[0])
 		{
 			ast_log(LOG_WARNING, "Link IP address cannot be determined!!\n");
@@ -10815,6 +10990,9 @@
 	}
 	*tele++ = 0;
 	myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele,NULL);
+	myrpt->zaprxchannel = NULL;
+	if (!strcasecmp(myrpt->rxchanname,"Zap"))
+		myrpt->zaprxchannel = myrpt->rxchannel;
 	if (myrpt->rxchannel)
 	{
 		ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
@@ -10836,6 +11014,7 @@
 		pthread_exit(NULL);
 	}
 	*--tele = '/';
+	myrpt->zaptxchannel = NULL;
 	if (myrpt->txchanname)
 	{
 		tele = strchr(myrpt->txchanname,'/');
@@ -10848,6 +11027,8 @@
 		}
 		*tele++ = 0;
 		myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele,NULL);
+		if (!strcasecmp(myrpt->txchanname,"Zap"))
+			myrpt->zaptxchannel = myrpt->txchannel;
 		if (myrpt->txchannel)
 		{
 			ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
@@ -10888,6 +11069,8 @@
 	}
 	ast_set_read_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
 	ast_set_write_format(myrpt->pchannel,AST_FORMAT_SLINEAR);
+	if (!myrpt->zaprxchannel) myrpt->zaprxchannel = myrpt->pchannel;
+	if (!myrpt->zaptxchannel) myrpt->zaptxchannel = myrpt->pchannel;
 	/* make a conference for the pseudo */
 	ci.chan = 0;
 	ci.confno = -1; /* make a new conf */
@@ -10903,6 +11086,8 @@
 		ast_hangup(myrpt->rxchannel);
 		pthread_exit(NULL);
 	}
+	/* save pseudo channel conference number */
+	myrpt->conf = myrpt->txconf = ci.confno;
 	/* if serial io port, open it */
 	myrpt->iofd = -1;
 	if (myrpt->p.ioport && ((myrpt->iofd = openserial(myrpt->p.ioport)) == -1))
@@ -10916,30 +11101,30 @@
 	}
 	iskenwood_pci4 = 0;
 	memset(&z,0,sizeof(z));
-	if (myrpt->iofd < 1)
+	if ((myrpt->iofd < 1) && (myrpt->txchannel == myrpt->zaptxchannel))
 	{
 		z.radpar = ZT_RADPAR_REMMODE;
 		z.data = ZT_RADPAR_REM_NONE;
-		res = ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z);
+		res = ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z);
 		/* if PCIRADIO and kenwood selected */
 		if ((!res) && (!strcmp(myrpt->remote,remote_rig_kenwood)))
 		{
 			z.radpar = ZT_RADPAR_UIOMODE;
 			z.data = 1;
-			if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+			if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
 			{
 				ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
 				return -1;
 			}
 			z.radpar = ZT_RADPAR_UIODATA;
 			z.data = 3;
-			if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+			if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
 			{
 				ast_log(LOG_ERROR,"Cannot set UIODATA\n");
 				return -1;
 			}
 			i = ZT_OFFHOOK;
-			if (ioctl(myrpt->txchannel->fds[0],ZT_HOOK,&i) == -1)
+			if (ioctl(myrpt->zaptxchannel->fds[0],ZT_HOOK,&i) == -1)
 			{
 				ast_log(LOG_ERROR,"Cannot set hook\n");
 				return -1;
@@ -10947,30 +11132,31 @@
 			iskenwood_pci4 = 1;
 		}
 	}
-	i = ZT_ONHOOK;
-	ioctl(myrpt->txchannel->fds[0],ZT_HOOK,&i);
-	/* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
-	if ((myrpt->iofd < 1) && (!res) &&
-	   (!strcmp(myrpt->remote,remote_rig_ft897) ||
-	      (!strcmp(myrpt->remote,remote_rig_ic706))))
-	{
-		z.radpar = ZT_RADPAR_UIOMODE;
-		z.data = 1;
-		if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
-		{
-			ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
-			return -1;
-		}
-		z.radpar = ZT_RADPAR_UIODATA;
-		z.data = 3;
-		if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
-		{
-			ast_log(LOG_ERROR,"Cannot set UIODATA\n");
-			return -1;
-		}
-	}
-	/* save pseudo channel conference number */
-	myrpt->conf = myrpt->txconf = ci.confno;
+	if (myrpt->txchannel == myrpt->zaptxchannel)
+	{
+		i = ZT_ONHOOK;
+		ioctl(myrpt->zaptxchannel->fds[0],ZT_HOOK,&i);
+		/* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
+		if ((myrpt->iofd < 1) && (!res) &&
+		   (!strcmp(myrpt->remote,remote_rig_ft897) ||
+		      (!strcmp(myrpt->remote,remote_rig_ic706))))
+		{
+			z.radpar = ZT_RADPAR_UIOMODE;
+			z.data = 1;
+			if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+			{
+				ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
+				return -1;
+			}
+			z.radpar = ZT_RADPAR_UIODATA;
+			z.data = 3;
+			if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+			{
+				ast_log(LOG_ERROR,"Cannot set UIODATA\n");
+				return -1;
+			}
+		}
+	}
 	myrpt->remoterx = 0;
 	myrpt->remotetx = 0;
 	myrpt->retxtimer = 0;
@@ -11000,19 +11186,22 @@
 	if (myrpt->remote && (myrpt->rxchannel == myrpt->txchannel))
 	{
 		i = 128;
-		ioctl(myrpt->rxchannel->fds[0],ZT_ECHOCANCEL,&i);
+		ioctl(myrpt->zaprxchannel->fds[0],ZT_ECHOCANCEL,&i);
 	}
 	if (chan->_state != AST_STATE_UP) {
 		ast_answer(chan);
 	}
 
-	if (ioctl(myrpt->rxchannel->fds[0],ZT_GET_PARAMS,&par) != -1)
-	{
-		if (par.rxisoffhook)
-		{
-			ast_indicate(chan,AST_CONTROL_RADIO_KEY);
-			myrpt->remoterx = 1;
-			remkeyed = 1;
+	if (myrpt->rxchannel == myrpt->zaprxchannel)
+	{
+		if (ioctl(myrpt->zaprxchannel->fds[0],ZT_GET_PARAMS,&par) != -1)
+		{
+			if (par.rxisoffhook)
+			{
+				ast_indicate(chan,AST_CONTROL_RADIO_KEY);
+				myrpt->remoterx = 1;
+				remkeyed = 1;
+			}
 		}
 	}
 	if (myrpt->p.archivedir)
@@ -11268,11 +11457,11 @@
 				if((myrpt->remtxfreqok = check_tx_freq(myrpt)))
 				{
 					time(&myrpt->last_activity_time);
-					if (iskenwood_pci4)
+					if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
 					{
 						z.radpar = ZT_RADPAR_UIODATA;
 						z.data = 1;
-						if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+						if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
 						{
 							ast_log(LOG_ERROR,"Cannot set UIODATA\n");
 							return -1;
@@ -11292,11 +11481,11 @@
 			if(!myrpt->remtxfreqok){
 				rpt_telemetry(myrpt,UNAUTHTX,NULL);
 			}
-			if (iskenwood_pci4)
+			if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
 			{
 				z.radpar = ZT_RADPAR_UIODATA;
 				z.data = 3;
-				if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+				if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
 				{
 					ast_log(LOG_ERROR,"Cannot set UIODATA\n");
 					return -1;
@@ -11569,24 +11758,24 @@
 	myrpt->lastf1 = NULL;
 	if (myrpt->lastf2) ast_frfree(myrpt->lastf2);
 	myrpt->lastf2 = NULL;
-	if (iskenwood_pci4)
+	if ((iskenwood_pci4) && (myrpt->txchannel == myrpt->zaptxchannel))
 	{
 		z.radpar = ZT_RADPAR_UIOMODE;
 		z.data = 3;
-		if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+		if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
 		{
 			ast_log(LOG_ERROR,"Cannot set UIOMODE\n");
 			return -1;
 		}
 		z.radpar = ZT_RADPAR_UIODATA;
 		z.data = 3;
-		if (ioctl(myrpt->txchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
+		if (ioctl(myrpt->zaptxchannel->fds[0],ZT_RADIO_SETPARAM,&z) == -1)
 		{
 			ast_log(LOG_ERROR,"Cannot set UIODATA\n");
 			return -1;
 		}
 		i = ZT_OFFHOOK;
-		if (ioctl(myrpt->txchannel->fds[0],ZT_HOOK,&i) == -1)
+		if (ioctl(myrpt->zaptxchannel->fds[0],ZT_HOOK,&i) == -1)
 		{
 			ast_log(LOG_ERROR,"Cannot set hook\n");
 			return -1;

Modified: branches/1.4/channels/Makefile
URL: http://svn.digium.com/view/asterisk/branches/1.4/channels/Makefile?view=diff&rev=82366&r1=82365&r2=82366
==============================================================================
--- branches/1.4/channels/Makefile (original)
+++ branches/1.4/channels/Makefile Thu Sep 13 19:34:13 2007
@@ -116,3 +116,9 @@
 $(if $(filter chan_misdn,$(EMBEDDED_MODS)),modules.link,chan_misdn.so): chan_misdn.o misdn_config.o misdn/isdn_lib.o misdn/isdn_msg_parser.o
 
 chan_vpb.oo: ASTCFLAGS:=$(filter-out -Wdeclaration-after-statement,$(ASTCFLAGS))
+
+chan_usbradio.o: chan_usbradio.c xpmr/xpmr.c xpmr/xpmr.h xpmr/xpmr_coef.h xpmr/sinetabx.h busy.h ringtone.h
+
+chan_usbradio.so: LIBS+=-lusb -lasound
+
+

Added: branches/1.4/channels/chan_usbradio.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/channels/chan_usbradio.c?view=auto&rev=82366
==============================================================================
--- branches/1.4/channels/chan_usbradio.c (added)
+++ branches/1.4/channels/chan_usbradio.c Thu Sep 13 19:34:13 2007
@@ -1,0 +1,2811 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 2007, Jim Dixon
+ *
+ * Jim Dixon, WB6NIL <jim at lambdatel.com>
+ * Steve Henke, W9SH  <w9sh at arrl.net>
+ * Based upon work by Mark Spencer <markster at digium.com> and Luigi Rizzo
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+  * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Channel driver for CM108 USB Cards with Radio Interface
+ *
+ * \author Jim Dixon  <jim at lambdatel.com>
+ * \author Steve Henke  <w9sh at arrl.net>
+ *
+ * \par See also
+ * \arg \ref Config_usbradio
+ *
+ * \ingroup channel_drivers
+ */
+
+/*** MODULEINFO
+	<depend>ossaudio</depend>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <usb.h>
+#include <alsa/asoundlib.h>
+
+#define CHAN_USBRADIO           1
+
+#define DEBUG_USBRADIO          0	
+#define DEBUG_CAPTURES	 		1
+		
+#define DEBUG_CAP_RX_OUT		0   		
+#define DEBUG_CAP_TX_OUT	    0			
+
+#define DEBUG_FILETEST			0			 
+
+#define RX_CAP_RAW_FILE			"/tmp/rx_cap_in.pcm"
+#define RX_CAP_TRACE_FILE		"/tmp/rx_trace.pcm"
+#define RX_CAP_OUT_FILE			"/tmp/rx_cap_out.pcm"
+
+#define TX_CAP_RAW_FILE			"/tmp/tx_cap_in.pcm"
+#define TX_CAP_TRACE_FILE		"/tmp/tx_trace.pcm"
+#define TX_CAP_OUT_FILE			"/tmp/tx_cap_out.pcm"
+
+#define	MIXER_PARAM_MIC_PLAYBACK_SW "Mic Playback Switch"
+#define MIXER_PARAM_MIC_PLAYBACK_VOL "Mic Playback Volume"
+#define	MIXER_PARAM_MIC_CAPTURE_SW "Mic Capture Switch"
+#define	MIXER_PARAM_MIC_CAPTURE_VOL "Mic Capture Volume"
+#define	MIXER_PARAM_MIC_BOOST "Auto Gain Control"
+#define	MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
+#define	MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
+
+#include "./xpmr/xpmr.h"
+
+#if 0
+#define traceusb1(a) {printf a;}
+#else
+#define traceusb1(a)
+#endif
+
+#if 0
+#define traceusb2(a) {printf a;}
+#else
+#define traceusb2(a)
+#endif
+
+#ifdef __linux
+#include <linux/soundcard.h>
+#elif defined(__FreeBSD__)
+#include <sys/soundcard.h>
+#else
+#include <soundcard.h>
+#endif
+
+#include "asterisk/lock.h"
+#include "asterisk/frame.h"
+#include "asterisk/logger.h"
+#include "asterisk/callerid.h"
+#include "asterisk/channel.h"
+#include "asterisk/module.h"
+#include "asterisk/options.h"
+#include "asterisk/pbx.h"
+#include "asterisk/config.h"
+#include "asterisk/cli.h"
+#include "asterisk/utils.h"
+#include "asterisk/causes.h"
+#include "asterisk/endian.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/abstract_jb.h"
+#include "asterisk/musiconhold.h"
+#include "asterisk/dsp.h"
+
+/* ringtones we use */
+#include "busy.h"
+#include "ringtone.h"
+#include "ring10.h"
+#include "answer.h"
+
+#define C108_VENDOR_ID		0x0d8c
+#define C108_PRODUCT_ID  	0x000c
+#define C108_HID_INTERFACE	3
+
+#define HID_REPORT_GET		0x01
+#define HID_REPORT_SET		0x09
+
+#define HID_RT_INPUT		0x01
+#define HID_RT_OUTPUT		0x02
+
+/*! Global jitterbuffer configuration - by default, jb is disabled */
+static struct ast_jb_conf default_jbconf =
+{
+	.flags = 0,
+	.max_size = -1,
+	.resync_threshold = -1,
+	.impl = "",
+};
+static struct ast_jb_conf global_jbconf;
+
+/*
+ * usbradio.conf parameters are
+START_CONFIG
+
+[general]
+    ; General config options, with default values shown.
+    ; You should use one section per device, with [general] being used
+    ; for the device.
+    ;
+    ;
+    ; debug = 0x0		; misc debug flags, default is 0
+
+	; Set the device to use for I/O
+	; devicenum = 0
+	; Set hardware type here
+	; hdwtype=0               ; 0=limey, 1=sph
+
+	; rxboostset=0          ; no rx gain boost
+	; rxctcssrelax=1        ; reduce talkoff from radios w/o CTCSS Tx HPF
+	; rxctcssfreq=100.0      ; rx ctcss freq in floating point. must be in table
+	; txctcssfreq=100.0      ; tx ctcss freq, any frequency permitted
+
+	; carrierfrom=dsp     ;no,usb,usbinvert,dsp,vox
+	; ctcssfrom=dsp       ;no,usb,dsp
+
+	; rxdemod=flat            ; input type from radio: no,speaker,flat
+	; txprelim=yes            ; output is pre-emphasised and limited
+	; txtoctype=no            ; no,phase,notone
+
+	; txmixa=composite        ;no,voice,tone,composite,auxvoice
+	; txmixb=no               ;no,voice,tone,composite,auxvoice
+
+	; invertptt=0
+
+    ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+    ; jbenable = yes              ; Enables the use of a jitterbuffer on the receiving side of an
+                                  ; USBRADIO channel. Defaults to "no". An enabled jitterbuffer will
+                                  ; be used only if the sending side can create and the receiving
+                                  ; side can not accept jitter. The USBRADIO channel can't accept jitter,
+                                  ; thus an enabled jitterbuffer on the receive USBRADIO side will always
+                                  ; be used if the sending side can create jitter.
+
+    ; jbmaxsize = 200             ; Max length of the jitterbuffer in milliseconds.
+
+    ; jbresyncthreshold = 1000    ; Jump in the frame timestamps over which the jitterbuffer is
+                                  ; resynchronized. Useful to improve the quality of the voice, with
+                                  ; big jumps in/broken timestamps, usualy sent from exotic devices
+                                  ; and programs. Defaults to 1000.
+
+    ; jbimpl = fixed              ; Jitterbuffer implementation, used on the receiving side of an USBRADIO
+                                  ; channel. Two implementations are currenlty available - "fixed"
+                                  ; (with size always equals to jbmax-size) and "adaptive" (with
+                                  ; variable size, actually the new jb of IAX2). Defaults to fixed.
+
+    ; jblog = no                  ; Enables jitterbuffer frame logging. Defaults to "no".
+    ;-----------------------------------------------------------------------------------
+
+
+END_CONFIG
+
+ */
+
+/*
+ * Helper macros to parse config arguments. They will go in a common
+ * header file if their usage is globally accepted. In the meantime,
+ * we define them here. Typical usage is as below.
+ * Remember to open a block right before M_START (as it declares
+ * some variables) and use the M_* macros WITHOUT A SEMICOLON:
+ *
+ *	{
+ *		M_START(v->name, v->value) 
+ *
+ *		M_BOOL("dothis", x->flag1)
+ *		M_STR("name", x->somestring)
+ *		M_F("bar", some_c_code)
+ *		M_END(some_final_statement)
+ *		... other code in the block
+ *	}
+ *
+ * XXX NOTE these macros should NOT be replicated in other parts of asterisk. 
+ * Likely we will come up with a better way of doing config file parsing.
+ */
+#define M_START(var, val) \
+        char *__s = var; char *__val = val;
+#define M_END(x)   x;
+#define M_F(tag, f)			if (!strcasecmp((__s), tag)) { f; } else
+#define M_BOOL(tag, dst)	M_F(tag, (dst) = ast_true(__val) )
+#define M_UINT(tag, dst)	M_F(tag, (dst) = strtoul(__val, NULL, 0) )
+#define M_STR(tag, dst)		M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
+
+/*
+ * The following parameters are used in the driver:
+ *
+ *  FRAME_SIZE	the size of an audio frame, in samples.
+ *		160 is used almost universally, so you should not change it.
+ *
+ *  FRAGS	the argument for the SETFRAGMENT ioctl.
+ *		Overridden by the 'frags' parameter in usbradio.conf
+ *
+ *		Bits 0-7 are the base-2 log of the device's block size,
+ *		bits 16-31 are the number of blocks in the driver's queue.
+ *		There are a lot of differences in the way this parameter
+ *		is supported by different drivers, so you may need to
+ *		experiment a bit with the value.
+ *		A good default for linux is 30 blocks of 64 bytes, which
+ *		results in 6 frames of 320 bytes (160 samples).
+ *		FreeBSD works decently with blocks of 256 or 512 bytes,
+ *		leaving the number unspecified.
+ *		Note that this only refers to the device buffer size,
+ *		this module will then try to keep the lenght of audio
+ *		buffered within small constraints.
+ *
+ *  QUEUE_SIZE	The max number of blocks actually allowed in the device
+ *		driver's buffer, irrespective of the available number.
+ *		Overridden by the 'queuesize' parameter in usbradio.conf
+ *
+ *		Should be >=2, and at most as large as the hw queue above
+ *		(otherwise it will never be full).
+ */
+
+#define FRAME_SIZE	160
+#define	QUEUE_SIZE	20
+
+#if defined(__FreeBSD__)
+#define	FRAGS	0x8
+#else
+#define	FRAGS	( ( (6 * 5) << 16 ) | 0xc )
+#endif
+
+/*
+ * XXX text message sizes are probably 256 chars, but i am
+ * not sure if there is a suitable definition anywhere.
+ */
+#define TEXT_SIZE	256
+
+#if 0
+#define	TRYOPEN	1				/* try to open on startup */
+#endif
+#define	O_CLOSE	0x444			/* special 'close' mode for device */
+/* Which device to use */
+#if defined( __OpenBSD__ ) || defined( __NetBSD__ )
+#define DEV_DSP "/dev/audio"
+#else
+#define DEV_DSP "/dev/dsp"
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+static char *config = "usbradio.conf";	/* default config file */
+static char *config1 = "usbradio_tune.conf";    /* tune config file */
+
+static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
+static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
+
+static int usbradio_debug;
+#if 0 //maw asdf sph
+static int usbradio_debug_level = 0;
+#endif
+
+enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
+enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
+enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR};    				 // no,external,externalinvert,software
+enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
+enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
+enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
+
+/*	DECLARE STRUCTURES */
+
+/*
+ * Each sound is made of 'datalen' samples of sound, repeated as needed to
+ * generate 'samplen' samples of data, then followed by 'silencelen' samples
+ * of silence. The loop is repeated if 'repeat' is set.
+ */
+struct sound {
+	int ind;
+	char *desc;
+	short *data;
+	int datalen;
+	int samplen;
+	int silencelen;
+	int repeat;
+};
+
+static struct sound sounds[] = {
+	{ AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
+	{ AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
+	{ AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
+	{ AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
+	{ AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
+	{ -1, NULL, 0, 0, 0, 0 },	/* end marker */
+};
+
+
+/*
+ * descriptor for one of our channels.
+ * There is one used for 'default' values (from the [general] entry in
+ * the configuration file), and then one instance for each device
+ * (the default is cloned from [general], others are only created
+ * if the relevant section exists).
+ */
+struct chan_usbradio_pvt {
+	struct chan_usbradio_pvt *next;
+
+	char *name;
+	/*
+	 * cursound indicates which in struct sound we play. -1 means nothing,
+	 * any other value is a valid sound, in which case sampsent indicates
+	 * the next sample to send in [0..samplen + silencelen]
+	 * nosound is set to disable the audio data from the channel
+	 * (so we can play the tones etc.).
+	 */
+	int sndcmd[2];				/* Sound command pipe */
+	int cursound;				/* index of sound to send */
+	int sampsent;				/* # of sound samples sent  */
+	int nosound;				/* set to block audio from the PBX */
+
+	int total_blocks;			/* total blocks in the output device */
+	int sounddev;
+	enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
+	i16 cdMethod;
+	int autoanswer;
+	int autohangup;
+	int hookstate;
+	unsigned int queuesize;		/* max fragments in queue */
+	unsigned int frags;			/* parameter for SETFRAGMENT */
+
+	int warned;					/* various flags used for warnings */
+#define WARN_used_blocks	1
+#define WARN_speed		2
+#define WARN_frag		4
+	int w_errors;				/* overfull in the write path */
+	struct timeval lastopen;
+
+	int overridecontext;
+	int mute;
+
+	/* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
+	 * be representable in 16 bits to avoid overflows.
+	 */
+#define	BOOST_SCALE	(1<<9)
+#define	BOOST_MAX	40			/* slightly less than 7 bits */
+	int boost;					/* input boost, scaled by BOOST_SCALE */
+	char devicenum;
+	int spkrmax;
+	int micmax;
+
+	pthread_t sthread;
+	pthread_t hidthread;
+
+	int stophid;
+	struct ast_channel *owner;
+	char ext[AST_MAX_EXTENSION];
+	char ctx[AST_MAX_CONTEXT];
+	char language[MAX_LANGUAGE];
+	char cid_name[256];			/*XXX */
+	char cid_num[256];			/*XXX */
+	char mohinterpret[MAX_MUSICCLASS];
+
+	/* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */
+	char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];    
+	char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6];
+
+	int usbradio_write_dst;
+	/* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
+	 * plus enough room for a full frame
+	 */
+	char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
+	char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
+	int readpos;				/* read position above */
+	struct ast_frame read_f;	/* returned by usbradio_read */
+	
+
+	char debuglevel;
+	char radioduplex;			// 
+
+	char lastrx;
+	char rxhidsq;
+	char rxcarrierdetect;		// status from pmr channel
+	char rxctcssdecode;			// status from pmr channel
+
+	char rxkeytype;
+	char rxkeyed;	  			// indicates rx signal present
+
+	char lasttx;
+	char txkeyed;				// tx key request from upper layers 
+	char txchankey;
+	char txtestkey;
+
+	time_t lasthidtime;
+    struct ast_dsp *dsp;
+
+	t_pmr_chan	*pmrChan;
+
+	char    rxcpusaver;
+	char    txcpusaver;
+
+	char	rxdemod;
+	float	rxgain;
+	char 	rxcdtype;
+	char 	rxsdtype;
+	int		rxsquelchadj;   /* this copy needs to be here for initialization */
+	char	txtoctype;
+
+	char    txprelim;
+	float	txctcssgain;
+	char 	txmixa;
+	char 	txmixb;
+
+	char	invertptt;
+
+	char	rxctcssrelax;
+	float	rxctcssgain;
+	float 	rxctcssfreq;
+	float 	txctcssfreq;
+
+	int	   	rxmixerset;	   	
+	int 	rxboostset;
+	float	rxvoiceadj;
+	float	rxctcssadj;
+	int 	txmixaset;

[... 6991 lines stripped ...]



More information about the svn-commits mailing list