[asterisk-commits] jdixon: branch jdixon/chan_usbradio-1.4 r114640 - in /team/jdixon/chan_usbrad...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 24 21:15:15 CDT 2008


Author: jdixon
Date: Thu Apr 24 21:15:07 2008
New Revision: 114640

URL: http://svn.digium.com/view/asterisk?view=rev&rev=114640
Log:
Updated to latest and greatest

Modified:
    team/jdixon/chan_usbradio-1.4/channels/chan_usbradio.c
    team/jdixon/chan_usbradio-1.4/channels/xpmr/sinetabx.h
    team/jdixon/chan_usbradio-1.4/channels/xpmr/xpmr.c
    team/jdixon/chan_usbradio-1.4/channels/xpmr/xpmr.h
    team/jdixon/chan_usbradio-1.4/channels/xpmr/xpmr_coef.h

Modified: team/jdixon/chan_usbradio-1.4/channels/chan_usbradio.c
URL: http://svn.digium.com/view/asterisk/team/jdixon/chan_usbradio-1.4/channels/chan_usbradio.c?view=diff&rev=114640&r1=114639&r2=114640
==============================================================================
--- team/jdixon/chan_usbradio-1.4/channels/chan_usbradio.c (original)
+++ team/jdixon/chan_usbradio-1.4/channels/chan_usbradio.c Thu Apr 24 21:15:07 2008
@@ -2,7 +2,7 @@
  * Asterisk -- An open source telephony toolkit.
  *
  * Copyright (C) 1999 - 2005, Digium, Inc.
- * Copyright (C) 2007, Jim Dixon
+ * Copyright (C) 2007 - 2008, Jim Dixon
  *
  * Jim Dixon, WB6NIL <jim at lambdatel.com>
  * Steve Henke, W9SH  <w9sh at arrl.net>
@@ -33,9 +33,10 @@
  */
 
 /*** MODULEINFO
-	<depend>alsa</depend>
-	<depend>usb</depend>
+	<depend>ossaudio</depend>
  ***/
+
+// 20070918 1600 EDT sph at xelatec.com changing to rx driven streams
 
 #include "asterisk.h"
 
@@ -46,6 +47,7 @@
 #include <math.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/io.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <sys/time.h>
@@ -54,14 +56,16 @@
 #include <usb.h>
 #include <alsa/asoundlib.h>
 
+//#define HAVE_XPMRX				1
+#ifdef RADIO_XPMRX
+#define HAVE_XPMRX				1
+#endif
+
 #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"
@@ -80,7 +84,16 @@
 #define	MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
 #define	MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
 
+#define	DELIMCHR ','
+#define	QUOTECHR 34
+
+#define	READERR_THRESHOLD 50
+
 #include "./xpmr/xpmr.h"
+#ifdef HAVE_XPMRX
+#include "./xpmrx/xpmrx.h"
+#include "./xpmrx/bitweight.h"
+#endif
 
 #if 0
 #define traceusb1(a) {printf a;}
@@ -136,6 +149,21 @@
 #define HID_RT_INPUT		0x01
 #define HID_RT_OUTPUT		0x02
 
+#define	EEPROM_START_ADDR	6
+#define	EEPROM_END_ADDR		63
+#define	EEPROM_PHYSICAL_LEN	64
+#define EEPROM_TEST_ADDR	EEPROM_END_ADDR
+#define	EEPROM_MAGIC_ADDR	6
+#define	EEPROM_MAGIC		34329
+#define	EEPROM_CS_ADDR		62
+#define	EEPROM_RXMIXERSET	8
+#define	EEPROM_TXMIXASET	9
+#define	EEPROM_TXMIXBSET	10
+#define	EEPROM_RXVOICEADJ	11
+#define	EEPROM_RXCTCSSADJ	13
+#define	EEPROM_TXCTCSSADJ	15
+#define	EEPROM_RXSQUELCHADJ	16
+
 /*! Global jitterbuffer configuration - by default, jb is disabled */
 static struct ast_jb_conf default_jbconf =
 {
@@ -151,9 +179,10 @@
 START_CONFIG
 
 [general]
-    ; General config options, with default values shown.
-    ; You should use one section per device, with [general] being used
-    ; for the device.
+    ; General config options which propigate to all devices, with
+    ; default values shown. You may have as many devices as the
+    ; system will allow. You must use one section per device, with
+    ; [usb] generally (although its up to you) being the first device.
     ;
     ;
     ; debug = 0x0		; misc debug flags, default is 0
@@ -163,10 +192,11 @@
 	; Set hardware type here
 	; hdwtype=0               ; 0=limey, 1=sph
 
-	; rxboostset=0          ; no rx gain boost
+	; rxboost=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
+	; rxctcssfreqs=100.0,123.0      ; list of rx ctcss freq in floating point. must be in table
+	; txctcssfreqs=100.0,123.0      ; list tx ctcss freq, any frequency permitted
+	; txctcssdefault=100.0      ; default tx ctcss freq, any frequency permitted
 
 	; carrierfrom=dsp     ;no,usb,usbinvert,dsp,vox
 	; ctcssfrom=dsp       ;no,usb,dsp
@@ -203,6 +233,13 @@
     ; jblog = no                  ; Enables jitterbuffer frame logging. Defaults to "no".
     ;-----------------------------------------------------------------------------------
 
+[usb]
+
+; First channel unique config
+
+[usb1]
+
+; Second channel config
 
 END_CONFIG
 
@@ -267,7 +304,7 @@
  */
 
 #define FRAME_SIZE	160
-#define	QUEUE_SIZE	20
+#define	QUEUE_SIZE	2				
 
 #if defined(__FreeBSD__)
 #define	FRAGS	0x8
@@ -300,10 +337,13 @@
 #endif
 
 static char *config = "usbradio.conf";	/* default config file */
-static char *config1 = "usbradio_tune.conf";    /* tune config file */
+static char *config1 = "usbradio_tune_%s.conf";    /* tune config file */
 
 static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
 static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
+
+static char *usb_device_list = NULL;
+static int usb_device_list_size = 0;
 
 static int usbradio_debug;
 #if 0 //maw asdf sph
@@ -367,6 +407,7 @@
 	int sampsent;				/* # of sound samples sent  */
 	int nosound;				/* set to block audio from the PBX */
 
+	int pttkick[2];
 	int total_blocks;			/* total blocks in the output device */
 	int sounddev;
 	enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
@@ -394,6 +435,7 @@
 #define	BOOST_MAX	40			/* slightly less than 7 bits */
 	int boost;					/* input boost, scaled by BOOST_SCALE */
 	char devicenum;
+	char devstr[128];
 	int spkrmax;
 	int micmax;
 
@@ -401,6 +443,8 @@
 	pthread_t hidthread;
 
 	int stophid;
+	FILE *hkickhid;
+
 	struct ast_channel *owner;
 	char ext[AST_MAX_EXTENSION];
 	char ctx[AST_MAX_CONTEXT];
@@ -421,15 +465,27 @@
 	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 	debuglevel;
+	char 	radioduplex;			// 
+	char    wanteeprom;
+
+	int  	tracetype;
+	int     tracelevel;
+	char    area;
+	char 	rptnum;
+	int     idleinterval;
+	int		turnoffs;
+	int  	txsettletime;
+	char    ukey[48];
 
 	char lastrx;
 	char rxhidsq;
 	char rxcarrierdetect;		// status from pmr channel
 	char rxctcssdecode;			// status from pmr channel
+
+	int  rxdcsdecode;
+	int  rxlsddecode;
 
 	char rxkeytype;
 	char rxkeyed;	  			// indicates rx signal present
@@ -463,8 +519,40 @@
 
 	char	rxctcssrelax;
 	float	rxctcssgain;
-	float 	rxctcssfreq;
-	float 	txctcssfreq;
+
+	char    txctcssdefault[16];				// for repeater operation
+	char	rxctcssfreqs[512];				// a string
+	char    txctcssfreqs[512];
+
+	char	txctcssfreq[32];				// encode now
+	char	rxctcssfreq[32];				// decode now
+
+	char    numrxctcssfreqs;	  			// how many
+	char    numtxctcssfreqs;
+
+	char    *rxctcss[CTCSS_NUM_CODES]; 		// pointers to strings
+	char    *txctcss[CTCSS_NUM_CODES];
+
+	int   	txfreq;			 				// in Hz
+	int     rxfreq;
+
+	// 		start remote operation info
+	char    set_txctcssdefault[16];				// for remote operation
+	char	set_txctcssfreq[16];				// encode now
+	char	set_rxctcssfreq[16];				// decode now
+
+	char    set_numrxctcssfreqs;	  			// how many
+	char    set_numtxctcssfreqs;
+
+	char	set_rxctcssfreqs[16];				// a string
+	char    set_txctcssfreqs[16];
+
+	char    *set_rxctcss; 					    // pointers to strings
+	char    *set_txctcss;
+
+	int   	set_txfreq;			 				// in Hz
+	int     set_rxfreq;
+	// 		end remote operation info
 
 	int	   	rxmixerset;	   	
 	int 	rxboostset;
@@ -489,7 +577,23 @@
 		unsigned txcapraw:1;
 		unsigned txcap2:1;
 		unsigned rxcap2:1;
+		unsigned rxplmon:1;
+		unsigned remoted:1;
+		unsigned txpolarity:1;
+		unsigned rxpolarity:1;
+		unsigned dcstxpolarity:1;
+		unsigned dcsrxpolarity:1;
+		unsigned lsdtxpolarity:1;
+		unsigned lsdrxpolarity:1;
+		unsigned loopback:1;
+		unsigned radioactive:1;
 	}b;
+	unsigned short eeprom[EEPROM_PHYSICAL_LEN];
+	char eepromctl;
+	ast_mutex_t eepromlock;
+
+	struct usb_dev_handle *usb_handle;
+	int readerrs;
 };
 
 // maw add additional defaults !!!
@@ -506,6 +610,9 @@
 	.readpos = AST_FRIENDLY_OFFSET,	/* start here on reads */
 	.lastopen = { 0, 0 },
 	.boost = BOOST_SCALE,
+	.wanteeprom = 1,
+	.area = 0,
+	.rptnum = 0,
 };
 
 /*	DECLARE FUNCTION PROTOTYPES	*/
@@ -517,10 +624,10 @@
 static void mult_set(struct chan_usbradio_pvt *o);
 static int  mult_calc(int value);
 static void mixer_write(struct chan_usbradio_pvt *o);
-static void tune_rxinput(struct chan_usbradio_pvt *o);
-static void tune_rxvoice(struct chan_usbradio_pvt *o);
-static void tune_rxctcss(struct chan_usbradio_pvt *o);
-static void tune_txoutput(struct chan_usbradio_pvt *o, int value);
+static void tune_rxinput(int fd, struct chan_usbradio_pvt *o);
+static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o);
+static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o);
+static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd);
 static void tune_write(struct chan_usbradio_pvt *o);
 
 static char *usbradio_active;	 /* the active device */
@@ -539,6 +646,7 @@
 static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
 static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static int xpmr_config(struct chan_usbradio_pvt *o);
 
 #if	DEBUG_FILETEST == 1
 static int RxTestIt(struct chan_usbradio_pvt *o);
@@ -662,6 +770,7 @@
 static void hid_set_outputs(struct usb_dev_handle *handle,
          unsigned char *outputs)
 {
+	usleep(1500);
 	usb_control_msg(handle,
 	      USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
 	      HID_REPORT_SET,
@@ -673,6 +782,7 @@
 static void hid_get_inputs(struct usb_dev_handle *handle,
          unsigned char *inputs)
 {
+	usleep(1500);
 	usb_control_msg(handle,
 	      USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
 	      HID_REPORT_GET,
@@ -681,10 +791,71 @@
 	      (char*)inputs, 4, 5000);
 }
 
-static struct usb_device *hid_device_init(void)
+static unsigned short read_eeprom(struct usb_dev_handle *handle, int addr)
+{
+	unsigned char buf[4];
+
+	buf[0] = 0x80;
+	buf[1] = 0;
+	buf[2] = 0;
+	buf[3] = 0x80 | (addr & 0x3f);
+	hid_set_outputs(handle,buf);
+	memset(buf,0,sizeof(buf));
+	hid_get_inputs(handle,buf);
+	return(buf[1] + (buf[2] << 8));
+}
+
+static void write_eeprom(struct usb_dev_handle *handle, int addr, 
+   unsigned short data)
+{
+
+	unsigned char buf[4];
+
+	buf[0] = 0x80;
+	buf[1] = data & 0xff;
+	buf[2] = data >> 8;
+	buf[3] = 0xc0 | (addr & 0x3f);
+	hid_set_outputs(handle,buf);
+}
+
+static unsigned short get_eeprom(struct usb_dev_handle *handle,
+	unsigned short *buf)
+{
+int	i;
+unsigned short cs;
+
+	cs = 0xffff;
+	for(i = EEPROM_START_ADDR; i < EEPROM_END_ADDR; i++)
+	{
+		cs += buf[i] = read_eeprom(handle,i);
+	}
+	return(cs);
+}
+
+static void put_eeprom(struct usb_dev_handle *handle,unsigned short *buf)
+{
+int	i;
+unsigned short cs;
+
+	cs = 0xffff;
+	buf[EEPROM_MAGIC_ADDR] = EEPROM_MAGIC;
+	for(i = EEPROM_START_ADDR; i < EEPROM_CS_ADDR; i++)
+	{
+		write_eeprom(handle,i,buf[i]);
+		cs += buf[i];
+	}
+	buf[EEPROM_CS_ADDR] = (65535 - cs) + 1;
+	write_eeprom(handle,i,buf[EEPROM_CS_ADDR]);
+}
+
+static struct usb_device *hid_device_init(char *desired_device)
 {
     struct usb_bus *usb_bus;
     struct usb_device *dev;
+    char devstr[200],str[200],desdev[200],*cp;
+    int i;
+    FILE *fp;
+
     usb_init();
     usb_find_busses();
     usb_find_devices();
@@ -698,11 +869,167 @@
                   == C108_VENDOR_ID) &&
                 (dev->descriptor.idProduct
                   == C108_PRODUCT_ID))
-                return dev;
+		{
+                        sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
+			for(i = 0; i < 32; i++)
+			{
+				sprintf(str,"/proc/asound/card%d/usbbus",i);
+				fp = fopen(str,"r");
+				if (!fp) continue;
+				if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
+				{
+					fclose(fp);
+					continue;
+				}
+				fclose(fp);
+				if (desdev[strlen(desdev) - 1] == '\n')
+			        	desdev[strlen(desdev) -1 ] = 0;
+				if (strcasecmp(desdev,devstr)) continue;
+				if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
+				else strcpy(str,"/sys/class/sound/dsp/device");
+				memset(desdev,0,sizeof(desdev));
+				if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
+				{
+					sprintf(str,"/sys/class/sound/controlC%d/device",i);
+					memset(desdev,0,sizeof(desdev));
+					if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
+				}
+				cp = strrchr(desdev,'/');
+				if (cp) *cp = 0; else continue;
+				cp = strrchr(desdev,'/');
+				if (!cp) continue;
+				cp++;
+				break;
+			}
+			if (i >= 32) continue;
+                        if (!strcmp(cp,desired_device)) return dev;
+		}
+
         }
     }
     return NULL;
 }
+
+static int hid_device_mklist(void)
+{
+    struct usb_bus *usb_bus;
+    struct usb_device *dev;
+    char devstr[200],str[200],desdev[200],*cp;
+    int i;
+    FILE *fp;
+
+    usb_device_list = ast_malloc(2);
+    if (!usb_device_list) return -1;
+    memset(usb_device_list,0,2);
+
+    usb_init();
+    usb_find_busses();
+    usb_find_devices();
+    for (usb_bus = usb_busses;
+         usb_bus;
+         usb_bus = usb_bus->next) {
+        for (dev = usb_bus->devices;
+             dev;
+             dev = dev->next) {
+            if ((dev->descriptor.idVendor
+                  == C108_VENDOR_ID) &&
+                (dev->descriptor.idProduct
+                  == C108_PRODUCT_ID))
+		{
+                        sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
+			for(i = 0;i < 32; i++)
+			{
+				sprintf(str,"/proc/asound/card%d/usbbus",i);
+				fp = fopen(str,"r");
+				if (!fp) continue;
+				if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
+				{
+					fclose(fp);
+					continue;
+				}
+				fclose(fp);
+				if (desdev[strlen(desdev) - 1] == '\n')
+			        	desdev[strlen(desdev) -1 ] = 0;
+				if (strcasecmp(desdev,devstr)) continue;
+				if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
+				else strcpy(str,"/sys/class/sound/dsp/device");
+				memset(desdev,0,sizeof(desdev));
+				if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
+				{
+					sprintf(str,"/sys/class/sound/controlC%d/device",i);
+					memset(desdev,0,sizeof(desdev));
+					if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
+				}
+				cp = strrchr(desdev,'/');
+				if (cp) *cp = 0; else continue;
+				cp = strrchr(desdev,'/');
+				if (!cp) continue;
+				cp++;
+				break;
+			}
+			if (i >= 32) return -1;
+			usb_device_list = ast_realloc(usb_device_list,
+				usb_device_list_size + 2 +
+					strlen(cp));
+			if (!usb_device_list) return -1;
+			usb_device_list_size += strlen(cp) + 2;
+			i = 0;
+			while(usb_device_list[i])
+			{
+				i += strlen(usb_device_list + i) + 1;
+			}
+			strcat(usb_device_list + i,cp);
+			usb_device_list[strlen(cp) + i + 1] = 0;
+		}
+
+        }
+    }
+    return 0;
+}
+
+/* returns internal formatted string from external one */
+static int usb_get_usbdev(char *devstr)
+{
+int	i;
+char	str[200],desdev[200],*cp;
+
+	for(i = 0;i < 32; i++)
+	{
+		if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
+		else strcpy(str,"/sys/class/sound/dsp/device");
+		memset(desdev,0,sizeof(desdev));
+		if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
+		{
+			sprintf(str,"/sys/class/sound/controlC%d/device",i);
+			memset(desdev,0,sizeof(desdev));
+			if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
+		}
+		cp = strrchr(desdev,'/');
+		if (cp) *cp = 0; else continue;
+		cp = strrchr(desdev,'/');
+		if (!cp) continue;
+		cp++;
+		if (!strcasecmp(cp,devstr)) break;
+	}
+	if (i >= 32) return -1;
+	return i;
+
+}
+
+static int usb_list_check(char *devstr)
+{
+
+char *s = usb_device_list;
+
+	if (!s) return(0);
+	while(*s)
+	{
+		if (!strcasecmp(s,devstr)) return(1);
+		s += strlen(s) + 1;
+	}
+	return(0);
+}
+
 
 static int	hidhdwconfig(struct chan_usbradio_pvt *o)
 {
@@ -742,17 +1069,30 @@
 
 	return 0;
 }
-
-
+/*
+*/
+static void kickptt(struct chan_usbradio_pvt *o)
+{
+	char c = 0;
+	//printf("kickptt  %i  %i  %i\n",o->txkeyed,o->txchankey,o->txtestkey);
+	if (!o) return;
+	if (!o->pttkick) return;
+	write(o->pttkick[1],&c,1);
+}
+/*
+*/
 static void *hidthread(void *arg)
 {
-	unsigned char buf[4],keyed;
+	unsigned char buf[4],bufsave[4],keyed;
 	char lastrx, txtmp;
+	int res;
 	struct usb_device *usb_dev;
 	struct usb_dev_handle *usb_handle;
 	struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
-
-	usb_dev = hid_device_init();
+	struct timeval to;
+	fd_set rfds;
+
+	usb_dev = hid_device_init(o->devstr);
 	if (usb_dev == NULL) {
 		ast_log(LOG_ERROR,"USB HID device not found\n");
 		pthread_exit(NULL);
@@ -764,7 +1104,7 @@
 	}
 	if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0)
 	{
-	        if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
+	    if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
 		        ast_log(LOG_ERROR,"Not able to detach the USB device\n");
 			pthread_exit(NULL);
 		}
@@ -777,35 +1117,104 @@
 	buf[2] = o->hid_gpio_ctl;
 	buf[1] = 0;
 	hid_set_outputs(usb_handle,buf);
-	traceusb1(("hidthread: Starting normally!!\n"));
+	memcpy(bufsave,buf,sizeof(buf));
+	if (pipe(o->pttkick) == -1)
+	{
+	    ast_log(LOG_ERROR,"Not able to create pipe\n");
+		pthread_exit(NULL);
+	}
+	traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
 	lastrx = 0;
+	// popen 
 	while(!o->stophid)
 	{
+		to.tv_sec = 0;
+		to.tv_usec = 50000;   // maw sph
+
+		FD_ZERO(&rfds);
+		FD_SET(o->pttkick[0],&rfds);
+		/* ast_select emulates linux behaviour in terms of timeout handling */
+		res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+			usleep(10000);
+			continue;
+		}
+		if (FD_ISSET(o->pttkick[0],&rfds))
+		{
+			char c;
+
+			read(o->pttkick[0],&c,1);
+		}
+		if(o->wanteeprom)
+		{
+			ast_mutex_lock(&o->eepromlock);
+			if (o->eepromctl == 1)  /* to read */
+			{
+				/* if CS okay */
+				if (!get_eeprom(usb_handle,o->eeprom))
+				{
+					if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC)
+					{
+						ast_log(LOG_NOTICE,"UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n",o->name);
+					}
+					else
+					{
+						o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
+						o->txmixaset = 	o->eeprom[EEPROM_TXMIXASET];
+						o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
+						memcpy(&o->rxvoiceadj,&o->eeprom[EEPROM_RXVOICEADJ],sizeof(float));
+						memcpy(&o->rxctcssadj,&o->eeprom[EEPROM_RXCTCSSADJ],sizeof(float));
+						o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
+						o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
+						ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
+					}
+				}
+				else
+				{
+					ast_log(LOG_NOTICE,"USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n",o->name);
+				}
+				hid_set_outputs(usb_handle,bufsave);
+			} 
+			if (o->eepromctl == 2) /* to write */
+			{
+				put_eeprom(usb_handle,o->eeprom);
+				hid_set_outputs(usb_handle,bufsave);
+				ast_log(LOG_NOTICE,"USB Parameters written to EEPROM on %s\n",o->name);
+			}
+			o->eepromctl = 0;
+			ast_mutex_unlock(&o->eepromlock);
+		}
 		buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
 		hid_get_inputs(usb_handle,buf);
 		keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
 		if (keyed != o->rxhidsq)
 		{
 			if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed);
-			o->rxhidsq=keyed;		 
-		}
-
-		/* if change in tx stuff */
-		txtmp=0;
-		if(o->txkeyed || o->txchankey || o->txtestkey || o->pmrChan->txPttOut) txtmp=1;
-		
+			o->rxhidsq=keyed;
+		}
+
+		/* if change in tx state as controlled by xpmr */
+		txtmp=o->pmrChan->txPttOut;
+				
 		if (o->lasttx != txtmp)
 		{
-			o->lasttx = txtmp;
+			o->pmrChan->txPttHid=o->lasttx = txtmp;
 			if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp);
 			buf[o->hid_gpio_loc] = 0;
-			if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+			if (!o->invertptt)
+			{
+				if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+			}
+			else
+			{
+				if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+			}
 			buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
+			memcpy(bufsave,buf,sizeof(buf));
 			hid_set_outputs(usb_handle,buf);
 		}
-
 		time(&o->lasthidtime);
-		usleep(50000);
 	}
 	buf[o->hid_gpio_loc] = 0;
 	if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt;
@@ -825,9 +1234,23 @@
 		ast_log(LOG_WARNING, "null dev\n");
 
 	for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
-
 	if (!o)
+	{
 		ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
+		pthread_exit(0);
+	}
+
+	return o;
+}
+
+static struct chan_usbradio_pvt *find_desc_usb(char *devstr)
+{
+	struct chan_usbradio_pvt *o = NULL;
+
+	if (!devstr)
+		ast_log(LOG_WARNING, "null dev\n");
+
+	for (o = usbradio_default.next; o && devstr && strcmp(o->devstr, devstr) != 0; o = o->next);
 
 	return o;
 }
@@ -901,6 +1324,13 @@
 		setformat(o, O_RDWR);
 	if (o->sounddev < 0)
 		return 0;				/* not fatal */
+	//  maw maw sph !!! may or may not be a good thing
+	//  drop the frame if not transmitting, this keeps from gradually
+	//  filling the buffer when asterisk clock > usb sound clock
+	if(!o->pmrChan->txPttIn && !o->pmrChan->txPttOut)
+	{
+		//return 0;
+	}
 	/*
 	 * Nothing complex to manage the audio device queue.
 	 * If the buffer is full just drop the extra, otherwise write.
@@ -909,6 +1339,7 @@
 	 */
 	res = used_blocks(o);
 	if (res > o->queuesize) {	/* no room to write a block */
+	    // ast_log(LOG_WARNING, "sound device write buffer overflow\n");
 		if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
 			ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
 		return 0;
@@ -1062,8 +1493,6 @@
 	}
 	if (mode == O_CLOSE)		/* we are done */
 		return 0;
-	if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000)
-		return -1;				/* don't open too often */
 	o->lastopen = ast_tvnow();
 	strcpy(device,"/dev/dsp");
 	if (o->devicenum)
@@ -1163,11 +1592,59 @@
 		digit, duration);
 	return 0;
 }
-
+/*
+	SETFREQ - sets spi programmable xcvr
+	SETCHAN - sets binary parallel xcvr
+*/
 static int usbradio_text(struct ast_channel *c, const char *text)
 {
+	struct chan_usbradio_pvt *o = find_desc(usbradio_active);
+	double tx,rx;
+	char cnt,rxs[16],txs[16],txpl[16],rxpl[16];
+	char pwr,*cmd;
+
+	cmd = alloca(strlen(text) + 10);
+
 	/* print received messages */
-	ast_verbose(" << Console Received text %s >> \n", text);
+	if(o->debuglevel)ast_verbose(" << Console Received usbradio text %s >> \n", text);
+
+	cnt=sscanf(text,"%s %s %s %s %s %c",cmd,rxs,txs,rxpl,txpl,&pwr);
+
+	if (strcmp(cmd,"SETCHAN")==0)
+    { 
+		u8 chan;
+		chan=strtod(rxs,NULL);
+		ppbinout(chan);
+        if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETCHAN cmd: %s chan: %i\n",text,chan);
+        return 0;
+    }
+	
+    if (cnt < 6)
+    {
+	    ast_log(LOG_ERROR,"Cannot parse usbradio text: %s\n",text);
+	    return 0;
+    }
+	else
+	{
+		if(o->debuglevel)ast_verbose(" << %s %s %s %s %s %c >> \n", cmd,rxs,txs,rxpl,txpl,pwr);	
+	}
+    
+    if (strcmp(cmd,"SETFREQ")==0)
+    {
+        if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETFREQ cmd: %s\n",text);
+		tx=strtod(txs,NULL);
+		rx=strtod(rxs,NULL);
+		o->set_txfreq = round(tx * (double)1000000);
+		o->set_rxfreq = round(rx * (double)1000000);
+		o->pmrChan->txpower = (pwr == 'H');
+		strcpy(o->set_rxctcssfreqs,rxpl);
+		strcpy(o->set_txctcssfreqs,txpl);
+	
+		o->b.remoted=1;
+		xpmr_config(o);
+        return 0;
+    }
+	ast_log(LOG_ERROR,"Cannot parse usbradio cmd: %s\n",text);
 	return 0;
 }
 
@@ -1184,6 +1661,7 @@
 {
 	struct chan_usbradio_pvt *o = c->tech_pvt;
 
+	o->stophid = 0;
 	time(&o->lasthidtime);
 	ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
 	ast_setstate(c, AST_STATE_UP);
@@ -1207,6 +1685,7 @@
 {
 	struct chan_usbradio_pvt *o = c->tech_pvt;
 
+	//ast_log(LOG_NOTICE, "usbradio_hangup()\n");
 	o->cursound = -1;
 	o->nosound = 0;
 	c->tech_pvt = NULL;
@@ -1231,10 +1710,9 @@
 /* used for data coming from the network */
 static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
 {
-	int src,datalen;
 	struct chan_usbradio_pvt *o = c->tech_pvt;
 
-	traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound));	//sph maw asdf
+	traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound));
 
 	/* Immediately return if no sound is enabled */
 	if (o->nosound)
@@ -1248,9 +1726,6 @@
 	 * Keep the residue stored for future use.
 	 */
 
-	if(o->txkeyed||o->txtestkey)o->pmrChan->txPttIn=1;
-	else o->pmrChan->txPttIn=0;
-
 	#if DEBUG_CAPTURES == 1	// to write input data to a file   datalen=320
 	if (ftxcapraw && o->b.txcapraw)
 	{
@@ -1265,47 +1740,23 @@
 	}
 	#endif
 
-	PmrTx(o->pmrChan,(i16*)f->data,(i16*)o->usbradio_write_buf_1);
-
-	#if 0	// to write 48KS/s stereo data to a file
-	if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
-	if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,f->datalen * 2 * 6,ftxoutraw);
-	#endif
-
-	#if DEBUG_CAPTURES == 1
-    if (o->b.txcap2 && ftxcaptrace) fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace);
-	#endif
-
-	src = 0;					/* read position into f->data */
-	datalen = f->datalen * 12;
-	while (src < datalen) {
-		/* Compute spare room in the buffer */
-		int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
-
-		if (datalen - src >= l) {	/* enough to fill a frame */
-			memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
-			soundcard_writeframe(o, (short *) o->usbradio_write_buf);
-			src += l;
-			o->usbradio_write_dst = 0;
-		} else {				/* copy residue */
-			l = datalen - src;
-			memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
-			src += l;			/* but really, we are done */
-			o->usbradio_write_dst += l;
-		}
-	}
+	// maw just take the data from the network and save it for PmrRx processing
+
+	PmrTx(o->pmrChan,(i16*)f->data);
+	
 	return 0;
 }
 
 static struct ast_frame *usbradio_read(struct ast_channel *c)
 {
-	int res;
+	int res, src, datalen, oldpttout;
+	int cd,sd;
 	struct chan_usbradio_pvt *o = c->tech_pvt;
 	struct ast_frame *f = &o->read_f,*f1;
 	struct ast_frame wf = { AST_FRAME_CONTROL };
 	time_t now;
 
-	traceusb2(("usbradio_read()\n"));	//sph maw asdf
+	traceusb2(("usbradio_read()\n"));
 
 	if (o->lasthidtime)
 	{
@@ -1315,17 +1766,6 @@
 			ast_log(LOG_ERROR,"HID process has died or something!!\n");
 			return NULL;
 		}
-	}
-	if (o->lastrx && (!o->rxkeyed))
-	{
-		o->lastrx = 0;
-		wf.subclass = AST_CONTROL_RADIO_UNKEY;
-		ast_queue_frame(o->owner, &wf);
-	} else if ((!o->lastrx) && (o->rxkeyed))
-	{
-		o->lastrx = 1;
-		wf.subclass = AST_CONTROL_RADIO_KEY;
-		ast_queue_frame(o->owner, &wf);
 	}
 	/* XXX can be simplified returning &ast_null_frame */
 	/* prepare a NULL frame in case we don't have enough data to return */
@@ -1336,8 +1776,20 @@
 	res = read(o->sounddev, o->usbradio_read_buf + o->readpos, 
 		sizeof(o->usbradio_read_buf) - o->readpos);
 	if (res < 0)				/* audio data not ready, return a NULL frame */
+	{
+		if (errno != EAGAIN) return NULL;
+		if (o->readerrs++ > READERR_THRESHOLD)
+		{
+			ast_log(LOG_ERROR,"Stuck USB read channel [%s], un-sticking it!!\n",o->name);
+			o->readerrs = 0;
+			return NULL;
+		}
+		if (o->readerrs == 1) 
+			ast_log(LOG_ERROR,"Possibly stuck USB read channel??? [%s]\n",o->name);
 		return f;
-
+	}
+	if (o->readerrs) ast_log(LOG_ERROR,"Nope, USB read channel [%s] wasn't stuck after all\n",o->name);
+	o->readerrs = 0;
 	o->readpos += res;
 	if (o->readpos < sizeof(o->usbradio_read_buf))	/* not enough samples */
 		return f;
@@ -1350,10 +1802,66 @@
 	#endif
 
 	#if 1
+	if(o->txkeyed||o->txtestkey)
+	{
+		if(!o->pmrChan->txPttIn)
+		{
+			o->pmrChan->txPttIn=1;
+			if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
+		}
+	}
+	else if(o->pmrChan->txPttIn)
+	{
+		o->pmrChan->txPttIn=0;
+		if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
+	}
+	oldpttout = o->pmrChan->txPttOut;
+
 	PmrRx(         o->pmrChan, 
 		   (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
-		   (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
-
+		   (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),
+		   (i16 *)(o->usbradio_write_buf_1));
+
+	if (oldpttout != o->pmrChan->txPttOut)
+	{
+		if(o->debuglevel) ast_log(LOG_NOTICE,"txPttOut = %i, chan %s\n",o->pmrChan->txPttOut,o->owner->name);
+		kickptt(o);
+	}
+
+	#if 0	// to write 48KS/s stereo tx data to a file
+	if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
+	if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,FRAME_SIZE * 2 * 6,ftxoutraw);
+	#endif
+
+	#if DEBUG_CAPTURES == 1	&& XPMR_DEBUG0 == 1
+    if (o->b.txcap2 && ftxcaptrace) fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace);
+	#endif
+	
+	// 160 samples * 2 bytes/sample * 2 chan * 6x oversampling to 48KS/s
+	datalen = FRAME_SIZE * 24;  
+	src = 0;					/* read position into f->data */
+	while (src < datalen) 
+	{
+		/* Compute spare room in the buffer */
+		int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
+
+		if (datalen - src >= l) 
+		{	
+			/* enough to fill a frame */
+			memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
+			soundcard_writeframe(o, (short *) o->usbradio_write_buf);
+			src += l;
+			o->usbradio_write_dst = 0;
+		} 
+		else 
+		{				
+			/* copy residue */
+			l = datalen - src;
+			memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
+			src += l;			/* but really, we are done */
+			o->usbradio_write_dst += l;
+		}
+	}
 	#else
 	static FILE *hInput;
 	i16 iBuff[FRAME_SIZE*2*6];
@@ -1372,7 +1880,7 @@
 
 	if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit;
 
-	PmrRx(         o->pmrChan, 
+	PmrRx(  o->pmrChan, 
 		   (i16 *)iBuff,
 		   (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
 
@@ -1383,46 +1891,131 @@
     if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw);
 	#endif
 
-	#if DEBUG_CAPTURES == 1
-    if (frxcaptrace && o->b.rxcap2) fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace);
+	#if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
+    if (frxcaptrace && o->b.rxcap2 && o->pmrChan->b.radioactive) fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace);
 	#endif
 
+	cd = 0;
 	if(o->rxcdtype==CD_HID && (o->pmrChan->rxExtCarrierDetect!=o->rxhidsq))
 		o->pmrChan->rxExtCarrierDetect=o->rxhidsq;
+	
 	if(o->rxcdtype==CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect==o->rxhidsq))
 		o->pmrChan->rxExtCarrierDetect=!o->rxhidsq;
 		
-	if( (o->rxcdtype==CD_HID && o->rxhidsq) ||
-		(o->rxcdtype==CD_HID_INVERT && !o->rxhidsq) ||
+	if( (o->rxcdtype==CD_HID        && o->rxhidsq)                  ||
+		(o->rxcdtype==CD_HID_INVERT && !o->rxhidsq)                 ||
 		(o->rxcdtype==CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
-		(o->rxcdtype==CD_XPMR_VOX && o->pmrChan->rxCarrierDetect)
+		(o->rxcdtype==CD_XPMR_VOX   && o->pmrChan->rxCarrierDetect)
 	  )
 	{
-		res=1;	
-	}
-	else res=0;
-
-	if(res!=o->rxcarrierdetect)
-	{
-		o->rxcarrierdetect=res;
-		if(o->debuglevel)printf("rxcarrierdetect = %i\n",res);
-	}
-
-	if(o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
-	{
-		if(o->debuglevel)printf("rxctcssdecode = %i\n",o->pmrChan->rxCtcss->decode);
+		if (!o->pmrChan->txPttOut || o->radioduplex)cd=1;	
+	}
+	else
+	{
+		cd=0;
+	}
+
+	if(cd!=o->rxcarrierdetect)
+	{
+		o->rxcarrierdetect=cd;
+		if(o->debuglevel) ast_log(LOG_NOTICE,"rxcarrierdetect = %i, chan %s\n",cd,o->owner->name);
+		// printf("rxcarrierdetect = %i, chan %s\n",res,o->owner->name);
+	}
+
+	if(o->pmrChan->b.ctcssRxEnable && o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
+	{
+		if(o->debuglevel)ast_log(LOG_NOTICE,"rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
+		// printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
 		o->rxctcssdecode=o->pmrChan->rxCtcss->decode;
-	}
-
-	if ( 	 
-	      (  o->rxctcssfreq &&  (o->rxctcssdecode == o->pmrChan->rxCtcssIndex)) || 
-	      ( !o->rxctcssfreq && 	o->rxcarrierdetect)
-	   ) 
-	{
+		strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
+	}
+
+	#ifndef HAVE_XPMRX
+	if(  !o->pmrChan->b.ctcssRxEnable ||
+		( o->pmrChan->b.ctcssRxEnable && 
+	      o->pmrChan->rxCtcss->decode>CTCSS_NULL && 
+	      o->pmrChan->smode==SMODE_CTCSS )  
+	)
+	{
+		sd=1;	
+	}
+	else
+	{
+		sd=0;
+	}
+	#else
+	if( (!o->pmrChan->b.ctcssRxEnable && !o->pmrChan->b.dcsRxEnable && !o->pmrChan->b.lmrRxEnable) ||
+		( o->pmrChan->b.ctcssRxEnable && 
+	      o->pmrChan->rxCtcss->decode>CTCSS_NULL && 
+	      o->pmrChan->smode==SMODE_CTCSS ) ||
+		( o->pmrChan->b.dcsRxEnable && 
+	      o->pmrChan->decDcs->decode > 0 &&
+	      o->pmrChan->smode==SMODE_DCS )
+	)
+	{
+		sd=1;	
+	}
+	else
+	{
+		sd=0;
+	}
+
+	if(o->pmrChan->decDcs->decode!=o->rxdcsdecode)
+	{													
+		if(o->debuglevel)ast_log(LOG_NOTICE,"rxdcsdecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
+		// printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
+		o->rxdcsdecode=o->pmrChan->decDcs->decode;
+		strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
+	}																							  
+
+	if(o->pmrChan->rptnum && (o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed != o->rxlsddecode))
+	{								
+		if(o->debuglevel)ast_log(LOG_NOTICE,"rxLSDecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
+		o->rxlsddecode=o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed;
+		strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
+	}
+
+	if( (o->pmrChan->rptnum>0 && o->pmrChan->smode==SMODE_LSD && o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed)||
+	    (o->pmrChan->smode==SMODE_DCS && o->pmrChan->decDcs->decode>0) )
+	{
+		sd=1;
+	}
+	#endif
+
+	if ( cd && sd )
+	{
+		//if(!o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
+		if(!o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 1, chan %s\n", o->owner->name);
 		o->rxkeyed = 1;
 	}
-	else o->rxkeyed = 0;
-
+	else 
+	{
+		//if(o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
+		if(o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 0, chan %s\n",o->owner->name);
+		o->rxkeyed = 0;
+	}
+
+	// provide rx signal detect conditions
+	if (o->lastrx && (!o->rxkeyed))
+	{
+		o->lastrx = 0;
+		//printf("AST_CONTROL_RADIO_UNKEY\n");
+		wf.subclass = AST_CONTROL_RADIO_UNKEY;
+		ast_queue_frame(o->owner, &wf);
+	}
+	else if ((!o->lastrx) && (o->rxkeyed))
+	{
+		o->lastrx = 1;
+		//printf("AST_CONTROL_RADIO_KEY\n");
+		wf.subclass = AST_CONTROL_RADIO_KEY;
+		if(o->rxctcssdecode)  	
+        {
+	        wf.data = o->rxctcssfreq;
+	        wf.datalen = strlen(o->rxctcssfreq) + 1;
+			TRACEO(1,("AST_CONTROL_RADIO_KEY text=%s\n",o->rxctcssfreq));
+        }
+		ast_queue_frame(o->owner, &wf);
+	}
 
 	o->readpos = AST_FRIENDLY_OFFSET;	/* reset read pointer for next frame */
 	if (c->_state != AST_STATE_UP)	/* drop data if frame is not up */
@@ -1448,18 +2041,22 @@
 
 	f->offset = AST_FRIENDLY_OFFSET;
 	if (o->dsp)
-	  {
+	{
 	    f1 = ast_dsp_process(c,o->dsp,f);
-		if ((f1->frametype == AST_FRAME_DTMF_END) ||
-		(f1->frametype == AST_FRAME_DTMF_BEGIN))
-		{
+	    if ((f1->frametype == AST_FRAME_DTMF_END) ||
+	      (f1->frametype == AST_FRAME_DTMF_BEGIN))
+	    {
 		if ((f1->subclass == 'm') || (f1->subclass == 'u'))
-		    f1->frametype = AST_FRAME_DTMF_BEGIN;
+		{
+			f1->frametype = AST_FRAME_NULL;
+			f1->subclass = 0;
+			return(f1);
+		}
 		if (f1->frametype == AST_FRAME_DTMF_END)
-		    ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
+			ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
 		return(f1);
-		}
-	  }
+	    }
+	}
 	return f;
 }
 
@@ -1509,11 +2106,11 @@
 			break;
 		case AST_CONTROL_RADIO_KEY:
 			o->txkeyed = 1;
-			if(o->debuglevel)ast_verbose(" << Radio Transmit On. >> \n");
+			if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_KEY Radio Transmit On. >> \n");
 			break;
 		case AST_CONTROL_RADIO_UNKEY:
 			o->txkeyed = 0;
-			if(o->debuglevel)ast_verbose(" << Radio Transmit Off. >> \n");
+			if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_UNKEY Radio Transmit Off. >> \n");
 			break;
 		default:
 			ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
@@ -1532,11 +2129,8 @@
 static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state)
 {
 	struct ast_channel *c;
-	char device[100];
-
-	strcpy(device,"dsp");
-	if (o->devicenum) sprintf(device,"dsp%d",o->devicenum);
-	c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "usbRadio/%s", device);
+
+	c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "Radio/%s", o->name);
 	if (c == NULL)
 		return NULL;
 	c->tech = &usbradio_tech;
@@ -1573,15 +2167,18 @@
 
 	return c;
 }
-
+/*
+*/
 static struct ast_channel *usbradio_request(const char *type, int format, void *data, int *cause)
 {
 	struct ast_channel *c;
 	struct chan_usbradio_pvt *o = find_desc(data);
 
+	TRACEO(1,("usbradio_request()\n"));
+
 	if (0)
 	{
-		ast_log(LOG_WARNING, "usbradio_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data);
+		ast_log(LOG_WARNING, "usbradio_request type <%s> data 0x%p <%s>\n", type, data, (char *) data);
 	}
 	if (o == NULL) {
 		ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
@@ -1602,9 +2199,14 @@
 		ast_log(LOG_WARNING, "Unable to create new usb channel\n");
 		return NULL;
 	}
+		
+	o->b.remoted=0;
+	xpmr_config(o);
+
 	return c;
 }
-
+/*
+*/
 static int console_key(int fd, int argc, char *argv[])
 {
 	struct chan_usbradio_pvt *o = find_desc(usbradio_active);
@@ -1614,7 +2216,8 @@
 	o->txtestkey = 1;
 	return RESULT_SUCCESS;
 }
-
+/*
+*/
 static int console_unkey(int fd, int argc, char *argv[])
 {
 	struct chan_usbradio_pvt *o = find_desc(usbradio_active);
@@ -1622,7 +2225,6 @@
 	if (argc != 2)
 		return RESULT_SHOWUSAGE;
 	o->txtestkey = 0;
-
 	return RESULT_SUCCESS;
 }
 
@@ -1636,6 +2238,7 @@
 
 	if (argc == 2) /* just show stuff */
 	{
+		ast_cli(fd,"Active radio interface is [%s]\n",usbradio_active);
 		ast_cli(fd,"Output A is currently set to ");
 		if(o->txmixa==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
 		else if (o->txmixa==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
@@ -1653,12 +2256,15 @@
 		ast_cli(fd,"Tx Voice Level currently set to %d\n",o->txmixaset);
 		ast_cli(fd,"Tx Tone Level currently set to %d\n",o->txctcssadj);
 		ast_cli(fd,"Rx Squelch currently set to %d\n",o->rxsquelchadj);
+		ast_cli(fd,"Device String is %s\n",o->devstr);
 		return RESULT_SHOWUSAGE;
 	}
 
-	if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(o);
-	else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(o);
-	else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(o);
+	o->pmrChan->b.tuning=1;
+
+	if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(fd,o);
+	else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(fd,o);
+	else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(fd,o);
 	else if (!strcasecmp(argv[2],"rxsquelch"))
 	{
 		if (argc == 3)
@@ -1710,7 +2316,46 @@
 			mult_set(o);
 			ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
 		}
-		tune_txoutput(o,i);
+		o->pmrChan->b.txCtcssInhibit=1;
+		tune_txoutput(o,i,fd);
+		o->pmrChan->b.txCtcssInhibit=0;
+	}
+	else if (!strcasecmp(argv[2],"txall")) {
+		i = 0;
+
+		if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
+			(o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
+		  )
+		{

[... 5961 lines stripped ...]



More information about the asterisk-commits mailing list