| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define	NEW_ASTERISK
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 1999 - 2005, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |  * Copyright (C) 2007 - 2008, Jim Dixon | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Jim Dixon, WB6NIL <jim@lambdatel.com> | 
					
						
							|  |  |  |  * Steve Henke, W9SH  <w9sh@arrl.net> | 
					
						
							|  |  |  |  * Based upon work by Mark Spencer <markster@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@lambdatel.com> | 
					
						
							|  |  |  |  * \author Steve Henke  <w9sh@arrl.net> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \par See also | 
					
						
							|  |  |  |  * \arg \ref Config_usbradio | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \ingroup channel_drivers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*** MODULEINFO
 | 
					
						
							| 
									
										
										
										
											2008-11-04 15:07:54 +00:00
										 |  |  | 	<depend>oss</depend> | 
					
						
							| 
									
										
										
										
											2010-03-25 20:08:40 +00:00
										 |  |  | 	<depend>alsa</depend> | 
					
						
							| 
									
										
										
										
											2008-05-22 21:43:54 +00:00
										 |  |  | 	<depend>usb</depend> | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	<defaultenabled>no</defaultenabled> | 
					
						
							| 
									
										
										
										
											2008-05-22 21:43:54 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*** MAKEOPTS
 | 
					
						
							| 
									
										
										
										
											2010-02-16 00:52:45 +00:00
										 |  |  | <category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes"> | 
					
						
							|  |  |  | 	<member name="RADIO_RTX" displayname="Build RTX/DTX Radio Programming" touch_on_change="channels/chan_usbradio.c channels/xpmr/xpmr.h"> | 
					
						
							| 
									
										
										
										
											2008-05-22 21:43:54 +00:00
										 |  |  | 		<defaultenabled>no</defaultenabled> | 
					
						
							|  |  |  | 		<depend>chan_usbradio</depend> | 
					
						
							|  |  |  | 	</member> | 
					
						
							| 
									
										
										
										
											2010-02-16 00:52:45 +00:00
										 |  |  | 	<member name="RADIO_XPMRX" displayname="Build Experimental Radio Protocols" touch_on_change="channels/chan_usbradio.c"> | 
					
						
							| 
									
										
										
										
											2008-05-22 21:43:54 +00:00
										 |  |  | 		<defaultenabled>no</defaultenabled> | 
					
						
							|  |  |  | 		<depend>chan_usbradio</depend> | 
					
						
							|  |  |  | 	</member> | 
					
						
							|  |  |  | </category> | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | // 20070918 1600 EDT sph@xelatec.com changing to rx driven streams
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2008-11-25 05:02:11 +00:00
										 |  |  | #ifdef HAVE_SYS_IO_H
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #include <sys/io.h>
 | 
					
						
							| 
									
										
										
										
											2008-11-25 05:02:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include <sys/ioctl.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <sys/time.h>
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include <usb.h>
 | 
					
						
							|  |  |  | #include <alsa/asoundlib.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | //#define HAVE_XPMRX				1
 | 
					
						
							|  |  |  | #ifdef RADIO_XPMRX
 | 
					
						
							|  |  |  | #define HAVE_XPMRX				1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define CHAN_USBRADIO           1
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define	DELIMCHR ','
 | 
					
						
							|  |  |  | #define	QUOTECHR 34
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define	READERR_THRESHOLD 50
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include "./xpmr/xpmr.h"
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifdef HAVE_XPMRX
 | 
					
						
							|  |  |  | #include "./xpmrx/xpmrx.h"
 | 
					
						
							|  |  |  | #include "./xpmrx/bitweight.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define traceusb1(a) {printf a;}
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define traceusb1(a)
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define traceusb2(a) {printf a;}
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define traceusb2(a)
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #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"
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #include "asterisk/logger.h"
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include "asterisk/callerid.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #include "asterisk/options.h"
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ringtones we use */ | 
					
						
							|  |  |  | #include "busy.h"
 | 
					
						
							|  |  |  | #include "ringtone.h"
 | 
					
						
							|  |  |  | #include "ring10.h"
 | 
					
						
							|  |  |  | #include "answer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*! Global jitterbuffer configuration - by default, jb is disabled */ | 
					
						
							|  |  |  | static struct ast_jb_conf default_jbconf = | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	.flags = 0, | 
					
						
							|  |  |  | 	.max_size = -1, | 
					
						
							|  |  |  | 	.resync_threshold = -1, | 
					
						
							|  |  |  | 	.impl = "", | 
					
						
							| 
									
										
										
										
											2010-03-02 19:08:38 +00:00
										 |  |  | 	.target_extra = -1, | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | static struct ast_jb_conf global_jbconf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  * usbradio.conf parameters are | 
					
						
							|  |  |  | START_CONFIG | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [general] | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |     ; 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. | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |     ; | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  |     ; 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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	; rxboost=0          ; no rx gain boost | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	; rxctcssrelax=1        ; reduce talkoff from radios w/o CTCSS Tx HPF | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	; 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 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	; 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". | 
					
						
							|  |  |  |     ;----------------------------------------------------------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | [usb] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ; First channel unique config | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [usb1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ; Second channel config | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | END_CONFIG | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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)))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  * 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
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define	QUEUE_SIZE	2				
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | static const char *config = "usbradio.conf";	/* default config file */ | 
					
						
							|  |  |  | #define config1 "usbradio_tune_%s.conf"    /* tune config file */
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL; | 
					
						
							|  |  |  | static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static char *usb_device_list = NULL; | 
					
						
							|  |  |  | static int usb_device_list_size = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static int usbradio_debug; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #if 0 //maw asdf sph
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 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}; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR};    				 // no,external,externalinvert,software
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 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 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * 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 */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int pttkick[2]; | 
					
						
							|  |  |  | 	int total_blocks;			/* total blocks in the output device */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	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 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int warned;					/* various flags used for warnings */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #define WARN_used_blocks	1
 | 
					
						
							|  |  |  | #define WARN_speed		2
 | 
					
						
							|  |  |  | #define WARN_frag		4
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int w_errors;				/* overfull in the write path */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	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)
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define	BOOST_MAX	40			/* slightly less than 7 bits */
 | 
					
						
							|  |  |  | 	int boost;					/* input boost, scaled by BOOST_SCALE */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	char devicenum; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char devstr[128]; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	int spkrmax; | 
					
						
							|  |  |  | 	int micmax; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	pthread_t sthread; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	pthread_t hidthread; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int stophid; | 
					
						
							|  |  |  | 	FILE *hkickhid; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	struct ast_channel *owner; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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]; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];     | 
					
						
							|  |  |  | 	char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6]; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int usbradio_write_dst; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	/* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
 | 
					
						
							|  |  |  | 	 * plus enough room for a full frame | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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    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
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	char lasttx; | 
					
						
							|  |  |  | 	char txkeyed;				// tx key request from upper layers 
 | 
					
						
							|  |  |  | 	char txchankey; | 
					
						
							|  |  |  | 	char txtestkey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	time_t lasthidtime; | 
					
						
							|  |  |  |     struct ast_dsp *dsp; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	t_pmr_chan	*pmrChan; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char    rxcpusaver; | 
					
						
							|  |  |  | 	char    txcpusaver; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char	rxdemod; | 
					
						
							|  |  |  | 	float	rxgain; | 
					
						
							|  |  |  | 	char 	rxcdtype; | 
					
						
							|  |  |  | 	char 	rxsdtype; | 
					
						
							|  |  |  | 	int		rxsquelchadj;   /* this copy needs to be here for initialization */ | 
					
						
							|  |  |  | 	int     rxsqvoxadj; | 
					
						
							|  |  |  | 	char	txtoctype; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char    txprelim; | 
					
						
							|  |  |  | 	float	txctcssgain; | 
					
						
							|  |  |  | 	char 	txmixa; | 
					
						
							|  |  |  | 	char 	txmixb; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char	invertptt; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char	rxctcssrelax; | 
					
						
							|  |  |  | 	float	rxctcssgain; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char    txctcssdefault[16];				// for repeater operation
 | 
					
						
							|  |  |  | 	char	rxctcssfreqs[512];				// a string
 | 
					
						
							|  |  |  | 	char    txctcssfreqs[512]; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char	txctcssfreq[32];				// encode now
 | 
					
						
							|  |  |  | 	char	rxctcssfreq[32];				// decode now
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 	float	rxvoiceadj; | 
					
						
							|  |  |  | 	float	rxctcssadj; | 
					
						
							|  |  |  | 	int 	txmixaset; | 
					
						
							|  |  |  | 	int 	txmixbset; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	int     txctcssadj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int    	hdwtype; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int		hid_gpio_ctl;		 | 
					
						
							|  |  |  | 	int		hid_gpio_ctl_loc;	 | 
					
						
							|  |  |  | 	int		hid_io_cor; 		 | 
					
						
							|  |  |  | 	int		hid_io_cor_loc; 	 | 
					
						
							|  |  |  | 	int		hid_io_ctcss;		 | 
					
						
							|  |  |  | 	int		hid_io_ctcss_loc; 	 | 
					
						
							|  |  |  | 	int		hid_io_ptt; 		 | 
					
						
							|  |  |  | 	int		hid_gpio_loc; 		 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	struct { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	    unsigned rxcapraw:1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		unsigned txcapraw:1; | 
					
						
							|  |  |  | 		unsigned txcap2:1; | 
					
						
							|  |  |  | 		unsigned rxcap2:1; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | // maw add additional defaults !!!
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static struct chan_usbradio_pvt usbradio_default = { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	.cursound = -1, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	.sounddev = -1, | 
					
						
							|  |  |  | 	.duplex = M_UNSET,			/* XXX check this */ | 
					
						
							|  |  |  | 	.autoanswer = 1, | 
					
						
							|  |  |  | 	.autohangup = 1, | 
					
						
							|  |  |  | 	.queuesize = QUEUE_SIZE, | 
					
						
							|  |  |  | 	.frags = FRAGS, | 
					
						
							|  |  |  | 	.ext = "s", | 
					
						
							|  |  |  | 	.ctx = "default", | 
					
						
							|  |  |  | 	.readpos = AST_FRIENDLY_OFFSET,	/* start here on reads */ | 
					
						
							|  |  |  | 	.lastopen = { 0, 0 }, | 
					
						
							|  |  |  | 	.boost = BOOST_SCALE, | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	.wanteeprom = 1, | 
					
						
							|  |  |  | 	.area = 0, | 
					
						
							|  |  |  | 	.rptnum = 0, | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*	DECLARE FUNCTION PROTOTYPES	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static void store_txtoctype(struct chan_usbradio_pvt *o, char *s); | 
					
						
							|  |  |  | static int	hidhdwconfig(struct chan_usbradio_pvt *o); | 
					
						
							|  |  |  | static int set_txctcss_level(struct chan_usbradio_pvt *o); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static void pmrdump(struct chan_usbradio_pvt *o); | 
					
						
							|  |  |  | static void mult_set(struct chan_usbradio_pvt *o); | 
					
						
							|  |  |  | static int  mult_calc(int value); | 
					
						
							|  |  |  | static void mixer_write(struct chan_usbradio_pvt *o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 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); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static void tune_write(struct chan_usbradio_pvt *o); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *usbradio_active;	 /* the active device */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int setformat(struct chan_usbradio_pvt *o, int mode); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | static struct ast_channel *usbradio_request(const char *type, format_t format, | 
					
						
							|  |  |  | 		const struct ast_channel *requestor, | 
					
						
							|  |  |  | 		void *data, int *cause); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static int usbradio_digit_begin(struct ast_channel *c, char digit); | 
					
						
							|  |  |  | static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration); | 
					
						
							|  |  |  | static int usbradio_text(struct ast_channel *c, const char *text); | 
					
						
							|  |  |  | static int usbradio_hangup(struct ast_channel *c); | 
					
						
							|  |  |  | static int usbradio_answer(struct ast_channel *c); | 
					
						
							|  |  |  | static struct ast_frame *usbradio_read(struct ast_channel *chan); | 
					
						
							|  |  |  | static int usbradio_call(struct ast_channel *c, char *dest, int timeout); | 
					
						
							|  |  |  | 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); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int xpmr_config(struct chan_usbradio_pvt *o); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if	DEBUG_FILETEST == 1
 | 
					
						
							|  |  |  | static int RxTestIt(struct chan_usbradio_pvt *o); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char tdesc[] = "USB (CM108) Radio Channel Driver"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct ast_channel_tech usbradio_tech = { | 
					
						
							|  |  |  | 	.type = "Radio", | 
					
						
							|  |  |  | 	.description = tdesc, | 
					
						
							|  |  |  | 	.capabilities = AST_FORMAT_SLINEAR, | 
					
						
							|  |  |  | 	.requester = usbradio_request, | 
					
						
							|  |  |  | 	.send_digit_begin = usbradio_digit_begin, | 
					
						
							|  |  |  | 	.send_digit_end = usbradio_digit_end, | 
					
						
							|  |  |  | 	.send_text = usbradio_text, | 
					
						
							|  |  |  | 	.hangup = usbradio_hangup, | 
					
						
							|  |  |  | 	.answer = usbradio_answer, | 
					
						
							|  |  |  | 	.read = usbradio_read, | 
					
						
							|  |  |  | 	.call = usbradio_call, | 
					
						
							|  |  |  | 	.write = usbradio_write, | 
					
						
							|  |  |  | 	.indicate = usbradio_indicate, | 
					
						
							|  |  |  | 	.fixup = usbradio_fixup, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Call with:  devnum: alsa major device number, param: ascii Formal
 | 
					
						
							|  |  |  | Parameter Name, val1, first or only value, val2 second value, or 0  | 
					
						
							|  |  |  | if only 1 value. Values: 0-99 (percent) or 0-1 for baboon. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note: must add -lasound to end of linkage */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int amixer_max(int devnum,char *param) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | int	rv,type; | 
					
						
							|  |  |  | char	str[100]; | 
					
						
							|  |  |  | snd_hctl_t *hctl; | 
					
						
							|  |  |  | snd_ctl_elem_id_t *id; | 
					
						
							|  |  |  | snd_hctl_elem_t *elem; | 
					
						
							|  |  |  | snd_ctl_elem_info_t *info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sprintf(str,"hw:%d",devnum); | 
					
						
							|  |  |  | 	if (snd_hctl_open(&hctl, str, 0)) return(-1); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_hctl_load(hctl); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	snd_ctl_elem_id_alloca(&id); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); | 
					
						
							|  |  |  | 	snd_ctl_elem_id_set_name(id, param);   | 
					
						
							|  |  |  | 	elem = snd_hctl_find_elem(hctl, id); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!elem) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		snd_hctl_close(hctl); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		return(-1); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	snd_ctl_elem_info_alloca(&info); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_hctl_elem_info(elem,info); | 
					
						
							|  |  |  | 	type = snd_ctl_elem_info_get_type(info); | 
					
						
							|  |  |  | 	rv = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	switch(type) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    case SND_CTL_ELEM_TYPE_INTEGER: | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		rv = snd_ctl_elem_info_get_max(info); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	    case SND_CTL_ELEM_TYPE_BOOLEAN: | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		rv = 1; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	snd_hctl_close(hctl); | 
					
						
							|  |  |  | 	return(rv); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /* Call with:  devnum: alsa major device number, param: ascii Formal
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | Parameter Name, val1, first or only value, val2 second value, or 0  | 
					
						
							|  |  |  | if only 1 value. Values: 0-99 (percent) or 0-1 for baboon. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note: must add -lasound to end of linkage */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int setamixer(int devnum,char *param, int v1, int v2) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | int	type; | 
					
						
							|  |  |  | char	str[100]; | 
					
						
							|  |  |  | snd_hctl_t *hctl; | 
					
						
							|  |  |  | snd_ctl_elem_id_t *id; | 
					
						
							|  |  |  | snd_ctl_elem_value_t *control; | 
					
						
							|  |  |  | snd_hctl_elem_t *elem; | 
					
						
							|  |  |  | snd_ctl_elem_info_t *info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sprintf(str,"hw:%d",devnum); | 
					
						
							|  |  |  | 	if (snd_hctl_open(&hctl, str, 0)) return(-1); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_hctl_load(hctl); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	snd_ctl_elem_id_alloca(&id); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); | 
					
						
							|  |  |  | 	snd_ctl_elem_id_set_name(id, param);   | 
					
						
							|  |  |  | 	elem = snd_hctl_find_elem(hctl, id); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!elem) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		snd_hctl_close(hctl); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		return(-1); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	snd_ctl_elem_info_alloca(&info); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_hctl_elem_info(elem,info); | 
					
						
							|  |  |  | 	type = snd_ctl_elem_info_get_type(info); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	snd_ctl_elem_value_alloca(&control); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	snd_ctl_elem_value_set_id(control, id);     | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	switch(type) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    case SND_CTL_ELEM_TYPE_INTEGER: | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		snd_ctl_elem_value_set_integer(control, 0, v1); | 
					
						
							|  |  |  | 		if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	    case SND_CTL_ELEM_TYPE_BOOLEAN: | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		snd_ctl_elem_value_set_integer(control, 0, (v1 != 0)); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (snd_hctl_elem_write(elem, control)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		snd_hctl_close(hctl); | 
					
						
							|  |  |  | 		return(-1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	snd_hctl_close(hctl); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	return(0); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hid_set_outputs(struct usb_dev_handle *handle, | 
					
						
							|  |  |  |          unsigned char *outputs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	usleep(1500); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	usb_control_msg(handle, | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	      USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE, | 
					
						
							|  |  |  | 	      HID_REPORT_SET, | 
					
						
							|  |  |  | 	      0 + (HID_RT_OUTPUT << 8), | 
					
						
							|  |  |  | 	      C108_HID_INTERFACE, | 
					
						
							|  |  |  | 	      (char*)outputs, 4, 5000); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hid_get_inputs(struct usb_dev_handle *handle, | 
					
						
							|  |  |  |          unsigned char *inputs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	usleep(1500); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	usb_control_msg(handle, | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	      USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE, | 
					
						
							|  |  |  | 	      HID_REPORT_GET, | 
					
						
							|  |  |  | 	      0 + (HID_RT_INPUT << 8), | 
					
						
							|  |  |  | 	      C108_HID_INTERFACE, | 
					
						
							|  |  |  | 	      (char*)inputs, 4, 5000); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static unsigned short read_eeprom(struct usb_dev_handle *handle, int addr) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	unsigned char buf[4]; | 
					
						
							| 
									
										
										
										
											2007-11-25 21:12:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2007-11-25 21:12:25 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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(); | 
					
						
							|  |  |  |     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) 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; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /* 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; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (i >= 32) return -1; | 
					
						
							|  |  |  | 	return i; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(o->hdwtype==1)	  //sphusb
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->hid_gpio_ctl		=  0x08;	/* set GPIO4 to output mode */ | 
					
						
							|  |  |  | 		o->hid_gpio_ctl_loc	=  2; 	/* For CTL of GPIO */ | 
					
						
							|  |  |  | 		o->hid_io_cor		=  4;	/* GPIO3 is COR */ | 
					
						
							|  |  |  | 		o->hid_io_cor_loc	=  1;	/* GPIO3 is COR */ | 
					
						
							|  |  |  | 		o->hid_io_ctcss		=  2;  	/* GPIO 2 is External CTCSS */ | 
					
						
							|  |  |  | 		o->hid_io_ctcss_loc =  1;	/* is GPIO 2 */ | 
					
						
							|  |  |  | 		o->hid_io_ptt 		=  8;  	/* GPIO 4 is PTT */ | 
					
						
							|  |  |  | 		o->hid_gpio_loc 	=  1;  	/* For ALL GPIO */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(o->hdwtype==0)	//dudeusb
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->hid_gpio_ctl		=  0x0c;	/* set GPIO 3 & 4 to output mode */ | 
					
						
							|  |  |  | 		o->hid_gpio_ctl_loc	=  2; 	/* For CTL of GPIO */ | 
					
						
							|  |  |  | 		o->hid_io_cor		=  2;	/* VOLD DN is COR */ | 
					
						
							|  |  |  | 		o->hid_io_cor_loc	=  0;	/* VOL DN COR */ | 
					
						
							|  |  |  | 		o->hid_io_ctcss		=  2;  	/* GPIO 2 is External CTCSS */ | 
					
						
							|  |  |  | 		o->hid_io_ctcss_loc =  1;	/* is GPIO 2 */ | 
					
						
							|  |  |  | 		o->hid_io_ptt 		=  4;  	/* GPIO 3 is PTT */ | 
					
						
							|  |  |  | 		o->hid_gpio_loc 	=  1;  	/* For ALL GPIO */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(o->hdwtype==3)	// custom version
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->hid_gpio_ctl		=  0x0c;	/* set GPIO 3 & 4 to output mode */ | 
					
						
							|  |  |  | 		o->hid_gpio_ctl_loc	=  2; 	/* For CTL of GPIO */ | 
					
						
							|  |  |  | 		o->hid_io_cor		=  2;	/* VOLD DN is COR */ | 
					
						
							|  |  |  | 		o->hid_io_cor_loc	=  0;	/* VOL DN COR */ | 
					
						
							|  |  |  | 		o->hid_io_ctcss		=  2;  	/* GPIO 2 is External CTCSS */ | 
					
						
							|  |  |  | 		o->hid_io_ctcss_loc =  1;	/* is GPIO 2 */ | 
					
						
							|  |  |  | 		o->hid_io_ptt 		=  4;  	/* GPIO 3 is PTT */ | 
					
						
							|  |  |  | 		o->hid_gpio_loc 	=  1;  	/* For ALL GPIO */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  | 	if (write(o->pttkick[1],&c,1) < 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static void *hidthread(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	unsigned char buf[4],bufsave[4],keyed; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	char lastrx, txtmp; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	struct usb_device *usb_dev; | 
					
						
							|  |  |  | 	struct usb_dev_handle *usb_handle; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg; | 
					
						
							|  |  |  | 	struct timeval to; | 
					
						
							|  |  |  | 	fd_set rfds; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	usb_dev = hid_device_init(o->devstr); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (usb_dev == NULL) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		ast_log(LOG_ERROR,"USB HID device not found\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		pthread_exit(NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	usb_handle = usb_open(usb_dev); | 
					
						
							|  |  |  | 	if (usb_handle == NULL) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	        ast_log(LOG_ERROR,"Not able to open USB device\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		pthread_exit(NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (usb_claim_interface(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"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			pthread_exit(NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0) { | 
					
						
							|  |  |  | 		        ast_log(LOG_ERROR,"Not able to claim the USB device\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			pthread_exit(NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	memset(buf,0,sizeof(buf)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	buf[2] = o->hid_gpio_ctl; | 
					
						
							|  |  |  | 	buf[1] = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	hid_set_outputs(usb_handle,buf); | 
					
						
							|  |  |  | 	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)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	lastrx = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	// 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  | 			if (read(o->pttkick[0],&c,1) < 0) { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		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); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		hid_get_inputs(usb_handle,buf); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if (keyed != o->rxhidsq) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed); | 
					
						
							|  |  |  | 			o->rxhidsq=keyed; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		/* if change in tx state as controlled by xpmr */ | 
					
						
							|  |  |  | 		txtmp=o->pmrChan->txPttOut; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 		if (o->lasttx != txtmp) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			o->pmrChan->txPttHid=o->lasttx = txtmp; | 
					
						
							|  |  |  | 			if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			buf[o->hid_gpio_loc] = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			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; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			memcpy(bufsave,buf,sizeof(buf)); | 
					
						
							|  |  |  | 			hid_set_outputs(usb_handle,buf); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		time(&o->lasthidtime); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	buf[o->hid_gpio_loc] = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	hid_set_outputs(usb_handle,buf); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	pthread_exit(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  * returns a pointer to the descriptor with the given name | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static struct chan_usbradio_pvt *find_desc(char *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!dev) | 
					
						
							|  |  |  | 		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) | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--"); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return o; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  * split a string in extension-context, returns pointers to malloc'ed | 
					
						
							|  |  |  |  * strings. | 
					
						
							|  |  |  |  * If we do not have 'overridecontext' then the last @ is considered as | 
					
						
							|  |  |  |  * a context separator, and the context is overridden. | 
					
						
							|  |  |  |  * This is usually not very necessary as you can play with the dialplan, | 
					
						
							|  |  |  |  * and it is nice not to need it because you have '@' in SIP addresses. | 
					
						
							|  |  |  |  * Return value is the buffer address. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #if	0
 | 
					
						
							|  |  |  | static char *ast_ext_ctx(const char *src, char **ext, char **ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ext == NULL || ctx == NULL) | 
					
						
							|  |  |  | 		return NULL;			/* error */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*ext = *ctx = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (src && *src != '\0') | 
					
						
							|  |  |  | 		*ext = ast_strdup(src); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (*ext == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!o->overridecontext) { | 
					
						
							|  |  |  | 		/* parse from the right */ | 
					
						
							|  |  |  | 		*ctx = strrchr(*ext, '@'); | 
					
						
							|  |  |  | 		if (*ctx) | 
					
						
							|  |  |  | 			*(*ctx)++ = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return *ext; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |  * Returns the number of blocks used in the audio output channel | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int used_blocks(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct audio_buf_info info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) { | 
					
						
							|  |  |  | 		if (!(o->warned & WARN_used_blocks)) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Error reading output space\n"); | 
					
						
							|  |  |  | 			o->warned |= WARN_used_blocks; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (o->total_blocks == 0) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if (0)					/* debugging */ | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->total_blocks = info.fragments; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return o->total_blocks - info.fragments; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /* Write an exactly FRAME_SIZE sized frame */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (o->sounddev < 0) | 
					
						
							|  |  |  | 		setformat(o, O_RDWR); | 
					
						
							|  |  |  | 	if (o->sounddev < 0) | 
					
						
							|  |  |  | 		return 0;				/* not fatal */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//  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;
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Nothing complex to manage the audio device queue. | 
					
						
							|  |  |  | 	 * If the buffer is full just drop the extra, otherwise write. | 
					
						
							|  |  |  | 	 * XXX in some cases it might be useful to write anyways after | 
					
						
							|  |  |  | 	 * a number of failures, to restart the output chain. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	res = used_blocks(o); | 
					
						
							|  |  |  | 	if (res > o->queuesize) {	/* no room to write a block */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	    // ast_log(LOG_WARNING, "sound device write buffer overflow\n");
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		if (o->w_errors++ == 0 && (usbradio_debug & 0x4)) | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	o->w_errors = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Handler for 'sound writable' events from the sound thread. | 
					
						
							|  |  |  |  * Builds a frame from the high level description of the sounds, | 
					
						
							|  |  |  |  * and passes it to the audio device. | 
					
						
							|  |  |  |  * The actual sound is made of 1 or more sequences of sound samples | 
					
						
							|  |  |  |  * (s->datalen, repeated to make s->samplen samples) followed by | 
					
						
							|  |  |  |  * s->silencelen samples of silence. The position in the sequence is stored | 
					
						
							|  |  |  |  * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen. | 
					
						
							|  |  |  |  * In case we fail to write a frame, don't update o->sampsent. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void send_sound(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	short myframe[FRAME_SIZE]; | 
					
						
							|  |  |  | 	int ofs, l, start; | 
					
						
							|  |  |  | 	int l_sampsent = o->sampsent; | 
					
						
							|  |  |  | 	struct sound *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (o->cursound < 0)		/* no sound to send */ | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s = &sounds[o->cursound]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (ofs = 0; ofs < FRAME_SIZE; ofs += l) { | 
					
						
							|  |  |  | 		l = s->samplen - l_sampsent;	/* # of available samples */ | 
					
						
							|  |  |  | 		if (l > 0) { | 
					
						
							|  |  |  | 			start = l_sampsent % s->datalen;	/* source offset */ | 
					
						
							|  |  |  | 			if (l > FRAME_SIZE - ofs)	/* don't overflow the frame */ | 
					
						
							|  |  |  | 				l = FRAME_SIZE - ofs; | 
					
						
							|  |  |  | 			if (l > s->datalen - start)	/* don't overflow the source */ | 
					
						
							|  |  |  | 				l = s->datalen - start; | 
					
						
							| 
									
										
										
										
											2008-10-09 14:17:33 +00:00
										 |  |  | 			memmove(myframe + ofs, s->data + start, l * 2); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			if (0) | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs); | 
					
						
							|  |  |  | 			l_sampsent += l; | 
					
						
							|  |  |  | 		} else {				/* end of samples, maybe some silence */ | 
					
						
							|  |  |  | 			static const short silence[FRAME_SIZE] = { 0, }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			l += s->silencelen; | 
					
						
							|  |  |  | 			if (l > 0) { | 
					
						
							|  |  |  | 				if (l > FRAME_SIZE - ofs) | 
					
						
							|  |  |  | 					l = FRAME_SIZE - ofs; | 
					
						
							| 
									
										
										
										
											2008-10-09 14:17:33 +00:00
										 |  |  | 				memmove(myframe + ofs, silence, l * 2); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 				l_sampsent += l; | 
					
						
							|  |  |  | 			} else {			/* silence is over, restart sound if loop */ | 
					
						
							|  |  |  | 				if (s->repeat == 0) {	/* last block */ | 
					
						
							|  |  |  | 					o->cursound = -1; | 
					
						
							|  |  |  | 					o->nosound = 0;	/* allow audio data */ | 
					
						
							|  |  |  | 					if (ofs < FRAME_SIZE)	/* pad with silence */ | 
					
						
							| 
									
										
										
										
											2008-10-09 14:17:33 +00:00
										 |  |  | 						memmove(myframe + ofs, silence, (FRAME_SIZE - ofs) * 2); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				l_sampsent = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	l = soundcard_writeframe(o, myframe); | 
					
						
							|  |  |  | 	if (l > 0) | 
					
						
							|  |  |  | 		o->sampsent = l_sampsent;	/* update status */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *sound_thread(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char ign[4096]; | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Just in case, kick the driver by trying to read from it. | 
					
						
							|  |  |  | 	 * Ignore errors - this read is almost guaranteed to fail. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	read(o->sounddev, ign, sizeof(ign)); | 
					
						
							|  |  |  | 	for (;;) { | 
					
						
							|  |  |  | 		fd_set rfds, wfds; | 
					
						
							|  |  |  | 		int maxfd, res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		FD_ZERO(&rfds); | 
					
						
							|  |  |  | 		FD_ZERO(&wfds); | 
					
						
							|  |  |  | 		FD_SET(o->sndcmd[0], &rfds); | 
					
						
							|  |  |  | 		maxfd = o->sndcmd[0];	/* pipe from the main process */ | 
					
						
							|  |  |  | 		if (o->cursound > -1 && o->sounddev < 0) | 
					
						
							|  |  |  | 			setformat(o, O_RDWR);	/* need the channel, try to reopen */ | 
					
						
							|  |  |  | 		else if (o->cursound == -1 && o->owner == NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			setformat(o, O_CLOSE);	/* can close */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (o->sounddev > -1) { | 
					
						
							|  |  |  | 			if (!o->owner) {	/* no one owns the audio, so we must drain it */ | 
					
						
							|  |  |  | 				FD_SET(o->sounddev, &rfds); | 
					
						
							|  |  |  | 				maxfd = MAX(o->sounddev, maxfd); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (o->cursound > -1) { | 
					
						
							|  |  |  | 				FD_SET(o->sounddev, &wfds); | 
					
						
							|  |  |  | 				maxfd = MAX(o->sounddev, maxfd); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* ast_select emulates linux behaviour in terms of timeout handling */ | 
					
						
							|  |  |  | 		res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL); | 
					
						
							|  |  |  | 		if (res < 1) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 			sleep(1); | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (FD_ISSET(o->sndcmd[0], &rfds)) { | 
					
						
							|  |  |  | 			/* read which sound to play from the pipe */ | 
					
						
							|  |  |  | 			int i, what = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			read(o->sndcmd[0], &what, sizeof(what)); | 
					
						
							|  |  |  | 			for (i = 0; sounds[i].ind != -1; i++) { | 
					
						
							|  |  |  | 				if (sounds[i].ind == what) { | 
					
						
							|  |  |  | 					o->cursound = i; | 
					
						
							|  |  |  | 					o->sampsent = 0; | 
					
						
							|  |  |  | 					o->nosound = 1;	/* block audio from pbx */ | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (sounds[i].ind == -1) | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, "invalid sound index: %d\n", what); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (o->sounddev > -1) { | 
					
						
							|  |  |  | 			if (FD_ISSET(o->sounddev, &rfds))	/* read and ignore errors */ | 
					
						
							|  |  |  | 				read(o->sounddev, ign, sizeof(ign));  | 
					
						
							|  |  |  | 			if (FD_ISSET(o->sounddev, &wfds)) | 
					
						
							|  |  |  | 				send_sound(o); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL;				/* Never reached */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * reset and close the device if opened, | 
					
						
							|  |  |  |  * then open and initialize it in the desired mode, | 
					
						
							|  |  |  |  * trigger reads and writes so we can start using it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int setformat(struct chan_usbradio_pvt *o, int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int fmt, desired, res, fd; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char device[100]; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (o->sounddev >= 0) { | 
					
						
							|  |  |  | 		ioctl(o->sounddev, SNDCTL_DSP_RESET, 0); | 
					
						
							|  |  |  | 		close(o->sounddev); | 
					
						
							|  |  |  | 		o->duplex = M_UNSET; | 
					
						
							|  |  |  | 		o->sounddev = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mode == O_CLOSE)		/* we are done */ | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	o->lastopen = ast_tvnow(); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	strcpy(device,"/dev/dsp"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (o->devicenum) | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		sprintf(device,"/dev/dsp%d",o->devicenum); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	fd = o->sounddev = open(device, mode | O_NONBLOCK); | 
					
						
							|  |  |  | 	if (fd < 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (o->owner) | 
					
						
							|  |  |  | 		o->owner->fds[0] = fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
					
						
							|  |  |  | 	fmt = AFMT_S16_LE; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	fmt = AFMT_S16_BE; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); | 
					
						
							|  |  |  | 	if (res < 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch (mode) { | 
					
						
							|  |  |  | 		case O_RDWR: | 
					
						
							|  |  |  | 			res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); | 
					
						
							|  |  |  | 			/* Check to see if duplex set (FreeBSD Bug) */ | 
					
						
							|  |  |  | 			res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt); | 
					
						
							|  |  |  | 			if (res == 0 && (fmt & DSP_CAP_DUPLEX)) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 				if (option_verbose > 1) | 
					
						
							|  |  |  | 					ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 				o->duplex = M_FULL; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case O_WRONLY: | 
					
						
							|  |  |  | 			o->duplex = M_WRITE; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case O_RDONLY: | 
					
						
							|  |  |  | 			o->duplex = M_READ; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt = 1; | 
					
						
							|  |  |  | 	res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); | 
					
						
							|  |  |  | 	if (res < 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fmt = desired = 48000;							/* 8000 Hz desired */ | 
					
						
							|  |  |  | 	res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (res < 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (fmt != desired) { | 
					
						
							|  |  |  | 		if (!(o->warned & WARN_speed)) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, | 
					
						
							|  |  |  | 			    "Requested %d Hz, got %d Hz -- sound may be choppy\n", | 
					
						
							|  |  |  | 			    desired, fmt); | 
					
						
							|  |  |  | 			o->warned |= WARN_speed; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * on Freebsd, SETFRAGMENT does not work very well on some cards. | 
					
						
							|  |  |  | 	 * Default to use 256 bytes, let the user override | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (o->frags) { | 
					
						
							|  |  |  | 		fmt = o->frags; | 
					
						
							|  |  |  | 		res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); | 
					
						
							|  |  |  | 		if (res < 0) { | 
					
						
							|  |  |  | 			if (!(o->warned & WARN_frag)) { | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, | 
					
						
							|  |  |  | 					"Unable to set fragment size -- sound may be choppy\n"); | 
					
						
							|  |  |  | 				o->warned |= WARN_frag; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */ | 
					
						
							|  |  |  | 	res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT; | 
					
						
							|  |  |  | 	res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res); | 
					
						
							|  |  |  | 	/* it may fail if we are in half duplex, never mind */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * some of the standard methods supported by channels. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int usbradio_digit_begin(struct ast_channel *c, char digit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* no better use for received digits than print them */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_verbose(" << Console Received digit %c of duration %u ms >> \n",  | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		digit, duration); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 	SETFREQ - sets spi programmable xcvr | 
					
						
							|  |  |  | 	SETCHAN - sets binary parallel xcvr | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static int usbradio_text(struct ast_channel *c, const char *text) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	/* print received messages */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->debuglevel)ast_verbose(" << Console Received usbradio text %s >> \n", text); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	cnt = sscanf(text, "%300s %15s %15s %15s %15s %1c", cmd, rxs, txs, rxpl, txpl, &pwr); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /* Play ringtone 'x' on device 'o' */ | 
					
						
							|  |  |  | static void ring(struct chan_usbradio_pvt *o, int x) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	write(o->sndcmd[1], &x, sizeof(x)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * handler for incoming calls. Either autoanswer, or start ringing | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int usbradio_call(struct ast_channel *c, char *dest, int timeout) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = c->tech_pvt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->stophid = 0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	time(&o->lasthidtime); | 
					
						
							|  |  |  | 	ast_pthread_create_background(&o->hidthread, NULL, hidthread, o); | 
					
						
							|  |  |  | 	ast_setstate(c, AST_STATE_UP); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * remote side answered the phone | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int usbradio_answer(struct ast_channel *c) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = c->tech_pvt; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-01-05 01:05:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_setstate(c, AST_STATE_UP); | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	o->cursound = -1; | 
					
						
							|  |  |  | 	o->nosound = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int usbradio_hangup(struct ast_channel *c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = c->tech_pvt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//ast_log(LOG_NOTICE, "usbradio_hangup()\n");
 | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	o->cursound = -1; | 
					
						
							|  |  |  | 	o->nosound = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	c->tech_pvt = NULL; | 
					
						
							|  |  |  | 	o->owner = NULL; | 
					
						
							|  |  |  | 	ast_module_unref(ast_module_info->self); | 
					
						
							|  |  |  | 	if (o->hookstate) { | 
					
						
							|  |  |  | 		if (o->autoanswer || o->autohangup) { | 
					
						
							|  |  |  | 			/* Assume auto-hangup too */ | 
					
						
							|  |  |  | 			o->hookstate = 0; | 
					
						
							|  |  |  | 			setformat(o, O_CLOSE); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/* Make congestion noise */ | 
					
						
							|  |  |  | 			ring(o, AST_CONTROL_CONGESTION); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	o->stophid = 1; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pthread_join(o->hidthread,NULL); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* used for data coming from the network */ | 
					
						
							|  |  |  | static int usbradio_write(struct ast_channel *c, struct ast_frame *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = c->tech_pvt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	/* Immediately return if no sound is enabled */ | 
					
						
							|  |  |  | 	if (o->nosound) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	/* Stop any currently playing sound */ | 
					
						
							|  |  |  | 	o->cursound = -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * we could receive a block which is not a multiple of our | 
					
						
							|  |  |  | 	 * FRAME_SIZE, so buffer it locally and write to the device | 
					
						
							|  |  |  | 	 * in FRAME_SIZE chunks. | 
					
						
							|  |  |  | 	 * Keep the residue stored for future use. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	#if DEBUG_CAPTURES == 1	// to write input data to a file   datalen=320
 | 
					
						
							|  |  |  | 	if (ftxcapraw && o->b.txcapraw) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		i16 i, tbuff[f->datalen]; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		for(i=0;i<f->datalen;i+=2) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-05-22 20:01:33 +00:00
										 |  |  | 			tbuff[i]= ((i16*)(f->data.ptr))[i/2]; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			tbuff[i+1]= o->txkeyed*M_Q13; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  | 		if (fwrite(tbuff,2,f->datalen,ftxcapraw) != f->datalen) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		//fwrite(f->data,1,f->datalen,ftxcapraw);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	// maw just take the data from the network and save it for PmrRx processing
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-22 20:01:33 +00:00
										 |  |  | 	PmrTx(o->pmrChan,(i16*)f->data.ptr); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_frame *usbradio_read(struct ast_channel *c) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int res, src, datalen, oldpttout; | 
					
						
							|  |  |  | 	int cd,sd; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	struct chan_usbradio_pvt *o = c->tech_pvt; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	struct ast_frame *f = &o->read_f,*f1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	struct ast_frame wf = { AST_FRAME_CONTROL }; | 
					
						
							|  |  |  | 	time_t now; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	traceusb2(("usbradio_read()\n")); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (o->lasthidtime) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		time(&now); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if ((now - o->lasthidtime) > 3) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"HID process has died or something!!\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* XXX can be simplified returning &ast_null_frame */ | 
					
						
							|  |  |  | 	/* prepare a NULL frame in case we don't have enough data to return */ | 
					
						
							| 
									
										
										
										
											2008-10-09 14:17:33 +00:00
										 |  |  | 	memset(f, '\0', sizeof(struct ast_frame)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	f->frametype = AST_FRAME_NULL; | 
					
						
							|  |  |  | 	f->src = usbradio_tech.type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		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_WARNING,"Possibly stuck USB read channel. [%s]\n",o->name); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		return f; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (o->readerrs) ast_log(LOG_WARNING,"Nope, USB read channel [%s] wasn't stuck after all.\n",o->name); | 
					
						
							|  |  |  | 	o->readerrs = 0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	o->readpos += res; | 
					
						
							|  |  |  | 	if (o->readpos < sizeof(o->usbradio_read_buf))	/* not enough samples */ | 
					
						
							|  |  |  | 		return f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (o->mute) | 
					
						
							|  |  |  | 		return f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if DEBUG_CAPTURES == 1
 | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  | 	if ((o->b.rxcapraw && frxcapraw) && (fwrite((o->usbradio_read_buf + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2 * 2 * 6,frxcapraw) != FRAME_SIZE * 2 * 2 * 6)) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if 1
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	PmrRx(         o->pmrChan,  | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		   (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET), | 
					
						
							|  |  |  | 		   (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET), | 
					
						
							|  |  |  | 		   (i16 *)(o->usbradio_write_buf_1)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	#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); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	#if DEBUG_CAPTURES == 1	&& XPMR_DEBUG0 == 1
 | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  |     if ((o->b.txcap2 && ftxcaptrace) && (fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace) != FRAME_SIZE * 2 * 16)) { | 
					
						
							|  |  |  | 	   ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	#endif
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// 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; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		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]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	o->pmrChan->b.rxCapture=1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(!hInput) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hInput  = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r"); | 
					
						
							|  |  |  | 		if(!hInput) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			printf(" Input Data File Not Found.\n"); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PmrRx(  o->pmrChan,  | 
					
						
							|  |  |  | 		   (i16 *)iBuff, | 
					
						
							|  |  |  | 		   (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if 0
 | 
					
						
							|  |  |  | 	if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE,"w"); | 
					
						
							|  |  |  |     if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw); | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	#if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
 | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  |     if ((frxcaptrace && o->b.rxcap2 && o->pmrChan->b.radioactive) && (fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace) != FRAME_SIZE * 2 * 16 )) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	#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; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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) | 
					
						
							|  |  |  | 	  ) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!o->pmrChan->txPttOut || o->radioduplex)cd=1;	 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		cd=0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 		strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	#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;	 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		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  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		//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); | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 		o->rxkeyed = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	// provide rx signal detect conditions
 | 
					
						
							|  |  |  | 	if (o->lastrx && (!o->rxkeyed)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->lastrx = 0; | 
					
						
							|  |  |  | 		//printf("AST_CONTROL_RADIO_UNKEY\n");
 | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | 		wf.subclass.integer = AST_CONTROL_RADIO_UNKEY; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		ast_queue_frame(o->owner, &wf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if ((!o->lastrx) && (o->rxkeyed)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->lastrx = 1; | 
					
						
							|  |  |  | 		//printf("AST_CONTROL_RADIO_KEY\n");
 | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | 		wf.subclass.integer = AST_CONTROL_RADIO_KEY; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(o->rxctcssdecode)  	 | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2008-05-22 20:01:33 +00:00
										 |  |  | 	        wf.data.ptr = o->rxctcssfreq; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	        wf.datalen = strlen(o->rxctcssfreq) + 1; | 
					
						
							|  |  |  | 			TRACEO(1,("AST_CONTROL_RADIO_KEY text=%s\n",o->rxctcssfreq)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 		ast_queue_frame(o->owner, &wf); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	o->readpos = AST_FRIENDLY_OFFSET;	/* reset read pointer for next frame */ | 
					
						
							|  |  |  | 	if (c->_state != AST_STATE_UP)	/* drop data if frame is not up */ | 
					
						
							|  |  |  | 		return f; | 
					
						
							|  |  |  | 	/* ok we can build and deliver the frame to the caller */ | 
					
						
							|  |  |  | 	f->frametype = AST_FRAME_VOICE; | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | 	f->subclass.codec = AST_FORMAT_SLINEAR; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	f->samples = FRAME_SIZE; | 
					
						
							|  |  |  | 	f->datalen = FRAME_SIZE * 2; | 
					
						
							| 
									
										
										
										
											2008-05-22 20:01:33 +00:00
										 |  |  | 	f->data.ptr = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (o->boost != BOOST_SCALE) {	/* scale and clip values */ | 
					
						
							|  |  |  | 		int i, x; | 
					
						
							| 
									
										
										
										
											2008-05-22 20:01:33 +00:00
										 |  |  | 		int16_t *p = (int16_t *) f->data.ptr; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		for (i = 0; i < f->samples; i++) { | 
					
						
							|  |  |  | 			x = (p[i] * o->boost) / BOOST_SCALE; | 
					
						
							|  |  |  | 			if (x > 32767) | 
					
						
							|  |  |  | 				x = 32767; | 
					
						
							|  |  |  | 			else if (x < -32768) | 
					
						
							|  |  |  | 				x = -32768; | 
					
						
							|  |  |  | 			p[i] = x; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f->offset = AST_FRIENDLY_OFFSET; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (o->dsp) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    f1 = ast_dsp_process(c,o->dsp,f); | 
					
						
							|  |  |  | 	    if ((f1->frametype == AST_FRAME_DTMF_END) || | 
					
						
							|  |  |  | 	      (f1->frametype == AST_FRAME_DTMF_BEGIN)) | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | 		if ((f1->subclass.integer == 'm') || (f1->subclass.integer == 'u')) | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			f1->frametype = AST_FRAME_NULL; | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | 			f1->subclass.integer = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			return(f1); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if (f1->frametype == AST_FRAME_DTMF_END) | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | 			ast_log(LOG_NOTICE, "Got DTMF char %c\n", f1->subclass.integer); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		return(f1); | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = newchan->tech_pvt; | 
					
						
							|  |  |  | 	ast_log(LOG_WARNING,"usbradio_fixup()\n"); | 
					
						
							|  |  |  | 	o->owner = newchan; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = c->tech_pvt; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int res = -1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (cond) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		case AST_CONTROL_BUSY: | 
					
						
							|  |  |  | 		case AST_CONTROL_CONGESTION: | 
					
						
							|  |  |  | 		case AST_CONTROL_RINGING: | 
					
						
							|  |  |  | 			res = cond; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case -1: | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 			o->cursound = -1; | 
					
						
							|  |  |  | 			o->nosound = 0;		/* when cursound is -1 nosound must be 0 */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case AST_CONTROL_VIDUPDATE: | 
					
						
							|  |  |  | 			res = -1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AST_CONTROL_HOLD: | 
					
						
							|  |  |  | 			ast_verbose(" << Console Has Been Placed on Hold >> \n"); | 
					
						
							|  |  |  | 			ast_moh_start(c, data, o->mohinterpret); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AST_CONTROL_UNHOLD: | 
					
						
							|  |  |  | 			ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); | 
					
						
							|  |  |  | 			ast_moh_stop(c); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AST_CONTROL_PROCEEDING: | 
					
						
							|  |  |  | 			ast_verbose(" << Call Proceeding... >> \n"); | 
					
						
							|  |  |  | 			ast_moh_stop(c); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AST_CONTROL_PROGRESS: | 
					
						
							|  |  |  | 			ast_verbose(" << Call Progress... >> \n"); | 
					
						
							|  |  |  | 			ast_moh_stop(c); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case AST_CONTROL_RADIO_KEY: | 
					
						
							|  |  |  | 			o->txkeyed = 1; | 
					
						
							|  |  |  | 			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(" << 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); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (res > -1) | 
					
						
							|  |  |  | 		ring(o, res); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * allocate a new channel. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state, const char *linkedid) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_channel *c; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | 	c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Radio/%s", o->name); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (c == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	c->tech = &usbradio_tech; | 
					
						
							|  |  |  | 	if (o->sounddev < 0) | 
					
						
							|  |  |  | 		setformat(o, O_RDWR); | 
					
						
							|  |  |  | 	c->fds[0] = o->sounddev;	/* -1 if device closed, override later */ | 
					
						
							|  |  |  | 	c->nativeformats = AST_FORMAT_SLINEAR; | 
					
						
							|  |  |  | 	c->readformat = AST_FORMAT_SLINEAR; | 
					
						
							|  |  |  | 	c->writeformat = AST_FORMAT_SLINEAR; | 
					
						
							|  |  |  | 	c->tech_pvt = o; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ast_strlen_zero(o->language)) | 
					
						
							|  |  |  | 		ast_string_field_set(c, language, o->language); | 
					
						
							|  |  |  | 	/* Don't use ast_set_callerid() here because it will
 | 
					
						
							|  |  |  | 	 * generate a needless NewCallerID event */ | 
					
						
							| 
									
										
										
										
											2010-07-14 16:58:03 +00:00
										 |  |  | 	if (!ast_strlen_zero(o->cid_num)) { | 
					
						
							|  |  |  | 		c->caller.ani.number.valid = 1; | 
					
						
							|  |  |  | 		c->caller.ani.number.str = ast_strdup(o->cid_num); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-14 15:48:36 +00:00
										 |  |  | 	if (!ast_strlen_zero(ext)) { | 
					
						
							|  |  |  | 		c->dialed.number.str = ast_strdup(ext); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	o->owner = c; | 
					
						
							|  |  |  | 	ast_module_ref(ast_module_info->self); | 
					
						
							|  |  |  | 	ast_jb_configure(c, &global_jbconf); | 
					
						
							|  |  |  | 	if (state != AST_STATE_DOWN) { | 
					
						
							|  |  |  | 		if (ast_pbx_start(c)) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name); | 
					
						
							|  |  |  | 			ast_hangup(c); | 
					
						
							|  |  |  | 			o->owner = c = NULL; | 
					
						
							|  |  |  | 			/* XXX what about the channel itself ? */ | 
					
						
							|  |  |  | 			/* XXX what about usecnt ? */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return c; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2010-02-08 04:31:03 +00:00
										 |  |  | static struct ast_channel *usbradio_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_channel *c; | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = find_desc(data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	TRACEO(1,("usbradio_request()\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "usbradio_request type <%s> data 0x%p <%s>\n", type, data, (char *) data); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (o == NULL) { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data); | 
					
						
							|  |  |  | 		/* XXX we could default to 'dsp' perhaps ? */ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((format & AST_FORMAT_SLINEAR) == 0) { | 
					
						
							| 
									
										
										
										
											2010-07-29 15:57:57 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Format 0x%" PRIx64 " unsupported\n", format); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (o->owner) { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "Already have a call (chan %p) on the usb channel\n", o->owner); | 
					
						
							|  |  |  | 		*cause = AST_CAUSE_BUSY; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | 	c = usbradio_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (c == NULL) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to create new usb channel\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	o->b.remoted=0; | 
					
						
							|  |  |  | 	xpmr_config(o); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return c; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int console_key(int fd, int argc, char *argv[]) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (argc != 2) | 
					
						
							|  |  |  | 		return RESULT_SHOWUSAGE;  | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	o->txtestkey = 1; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int console_unkey(int fd, int argc, char *argv[]) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (argc != 2) | 
					
						
							|  |  |  | 		return RESULT_SHOWUSAGE; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	o->txtestkey = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int radio_tune(int fd, int argc, char *argv[]) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							|  |  |  | 	int i=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((argc < 2) || (argc > 4)) | 
					
						
							|  |  |  | 		return RESULT_SHOWUSAGE;  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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"); | 
					
						
							|  |  |  | 		else if (o->txmixa==TX_OUT_LSD)ast_cli(fd,"tone.\n"); | 
					
						
							|  |  |  | 		else if (o->txmixa==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n"); | 
					
						
							|  |  |  | 		else ast_cli(fd,"off.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_cli(fd,"Output B is currently set to "); | 
					
						
							|  |  |  | 		if(o->txmixb==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n"); | 
					
						
							|  |  |  | 		else if (o->txmixb==TX_OUT_VOICE)ast_cli(fd,"voice.\n"); | 
					
						
							|  |  |  | 		else if (o->txmixb==TX_OUT_LSD)ast_cli(fd,"tone.\n"); | 
					
						
							|  |  |  | 		else if (o->txmixb==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n"); | 
					
						
							|  |  |  | 		else ast_cli(fd,"off.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		    ast_cli(fd,"Current Signal Strength is %d\n",((32767-o->pmrChan->rxRssi)*1000/32767)); | 
					
						
							|  |  |  | 		    ast_cli(fd,"Current Squelch setting is %d\n",o->rxsquelchadj); | 
					
						
							|  |  |  | 			//ast_cli(fd,"Current Raw RSSI        is %d\n",o->pmrChan->rxRssi);
 | 
					
						
							|  |  |  | 		    //ast_cli(fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			i = atoi(argv[3]); | 
					
						
							|  |  |  | 			if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  | 			ast_cli(fd,"Changed Squelch setting to %d\n",i); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->rxsquelchadj = i; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			*(o->pmrChan->prxSquelchAdjust)= ((999 - i) * 32767) / 1000; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"txvoice")) { | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) && | 
					
						
							|  |  |  | 			(o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE) | 
					
						
							|  |  |  | 		  ) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"No txvoice output configured.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (argc == 3) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE)) | 
					
						
							|  |  |  | 				ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 				ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			i = atoi(argv[3]); | 
					
						
							|  |  |  | 			if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			 	o->txmixaset=i; | 
					
						
							|  |  |  | 				ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			 	o->txmixbset=i;    | 
					
						
							|  |  |  | 				ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			mixer_write(o); | 
					
						
							|  |  |  | 			mult_set(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		o->pmrChan->b.txCtcssInhibit=1; | 
					
						
							|  |  |  | 		tune_txoutput(o,i,fd); | 
					
						
							|  |  |  | 		o->pmrChan->b.txCtcssInhibit=0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"txall")) { | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		i = 0; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) && | 
					
						
							|  |  |  | 			(o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE) | 
					
						
							|  |  |  | 		  ) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"No txvoice output configured.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (argc == 3) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE)) | 
					
						
							|  |  |  | 				ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 				ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			i = atoi(argv[3]); | 
					
						
							|  |  |  | 			if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			 	o->txmixaset=i; | 
					
						
							|  |  |  | 				ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			 	o->txmixbset=i;    | 
					
						
							|  |  |  | 				ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			mixer_write(o); | 
					
						
							|  |  |  | 			mult_set(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tune_txoutput(o,i,fd); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"auxvoice")) { | 
					
						
							|  |  |  | 		i = 0; | 
					
						
							|  |  |  | 		if( (o->txmixa!=TX_OUT_AUX) && (o->txmixb!=TX_OUT_AUX)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING,"No auxvoice output configured.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (argc == 3) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(o->txmixa==TX_OUT_AUX) | 
					
						
							|  |  |  | 				ast_cli(fd,"Current auxvoice setting on Channel A is %d\n",o->txmixaset); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				ast_cli(fd,"Current auxvoice setting on Channel B is %d\n",o->txmixbset); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			i = atoi(argv[3]); | 
					
						
							|  |  |  | 			if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  | 			if(o->txmixa==TX_OUT_AUX) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				o->txmixbset=i; | 
					
						
							|  |  |  | 				ast_cli(fd,"Changed auxvoice setting on Channel A to %d\n",o->txmixaset); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				o->txmixbset=i; | 
					
						
							|  |  |  | 				ast_cli(fd,"Changed auxvoice setting on Channel B to %d\n",o->txmixbset); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			mixer_write(o); | 
					
						
							|  |  |  | 			mult_set(o); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		//tune_auxoutput(o,i);
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"txtone")) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (argc == 3) | 
					
						
							|  |  |  | 			ast_cli(fd,"Current Tx CTCSS modulation setting = %d\n",o->txctcssadj); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			i = atoi(argv[3]); | 
					
						
							|  |  |  | 			if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->txctcssadj = i; | 
					
						
							|  |  |  | 			set_txctcss_level(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			ast_cli(fd,"Changed Tx CTCSS modulation setting to %i\n",i); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		o->txtestkey=1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		usleep(5000000); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		o->txtestkey=0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"dump")) pmrdump(o); | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"nocap")) 	 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_cli(fd,"File capture (trace) was rx=%d tx=%d and now off.\n",o->b.rxcap2,o->b.txcap2); | 
					
						
							|  |  |  | 		ast_cli(fd,"File capture (raw)   was rx=%d tx=%d and now off.\n",o->b.rxcapraw,o->b.txcapraw); | 
					
						
							|  |  |  | 		o->b.rxcapraw=o->b.txcapraw=o->b.rxcap2=o->b.txcap2=o->pmrChan->b.rxCapture=o->pmrChan->b.txCapture=0; | 
					
						
							|  |  |  | 		if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; } | 
					
						
							|  |  |  | 		if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; } | 
					
						
							|  |  |  | 		if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; } | 
					
						
							|  |  |  | 		if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; } | 
					
						
							|  |  |  | 		if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; } | 
					
						
							|  |  |  | 		if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"rxtracecap"))  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!frxcaptrace) frxcaptrace= fopen(RX_CAP_TRACE_FILE,"w"); | 
					
						
							|  |  |  | 		ast_cli(fd,"Trace rx on.\n"); | 
					
						
							|  |  |  | 		o->b.rxcap2=o->pmrChan->b.rxCapture=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"txtracecap"))  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!ftxcaptrace) ftxcaptrace= fopen(TX_CAP_TRACE_FILE,"w"); | 
					
						
							|  |  |  | 		ast_cli(fd,"Trace tx on.\n"); | 
					
						
							|  |  |  | 		o->b.txcap2=o->pmrChan->b.txCapture=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"rxcap"))  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!frxcapraw) frxcapraw = fopen(RX_CAP_RAW_FILE,"w"); | 
					
						
							|  |  |  | 		ast_cli(fd,"cap rx raw on.\n"); | 
					
						
							|  |  |  | 		o->b.rxcapraw=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"txcap"))  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!ftxcapraw) ftxcapraw = fopen(TX_CAP_RAW_FILE,"w"); | 
					
						
							|  |  |  | 		ast_cli(fd,"cap tx raw on.\n"); | 
					
						
							|  |  |  | 		o->b.txcapraw=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"save")) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		tune_write(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		ast_cli(fd,"Saved radio tuning settings to usbradio_tune_%s.conf\n",o->name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(argv[2],"load")) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_mutex_lock(&o->eepromlock); | 
					
						
							|  |  |  | 		while(o->eepromctl) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_mutex_unlock(&o->eepromlock); | 
					
						
							|  |  |  | 			usleep(10000); | 
					
						
							|  |  |  | 			ast_mutex_lock(&o->eepromlock); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o->eepromctl = 1;  /* request a load */ | 
					
						
							|  |  |  | 		ast_mutex_unlock(&o->eepromlock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_cli(fd,"Requesting loading of tuning settings from EEPROM for channel %s\n",o->name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->pmrChan->b.tuning=0; | 
					
						
							|  |  |  | 		return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	o->pmrChan->b.tuning=0; | 
					
						
							|  |  |  | 	return RESULT_SUCCESS; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	set transmit ctcss modulation level | 
					
						
							|  |  |  | 	adjust mixer output or internal gain depending on output type | 
					
						
							|  |  |  | 	setting range is 0.0 to 0.9 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int set_txctcss_level(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | {							   | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (o->txmixa == TX_OUT_LSD) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | //		o->txmixaset=(151*o->txctcssadj) / 1000;
 | 
					
						
							|  |  |  | 		o->txmixaset=o->txctcssadj; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		mixer_write(o); | 
					
						
							|  |  |  | 		mult_set(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (o->txmixb == TX_OUT_LSD) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | //		o->txmixbset=(151*o->txctcssadj) / 1000;
 | 
					
						
							|  |  |  | 		o->txmixbset=o->txctcssadj; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		mixer_write(o); | 
					
						
							|  |  |  | 		mult_set(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*o->pmrChan->ptxCtcssAdjust=(o->txctcssadj * M_Q8) / 1000; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	CLI debugging on and off | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int radio_set_debug(int fd, int argc, char *argv[]) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->debuglevel=1; | 
					
						
							|  |  |  | 	ast_cli(fd,"usbradio debug on.\n"); | 
					
						
							|  |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int radio_set_debug_off(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->debuglevel=0; | 
					
						
							|  |  |  | 	ast_cli(fd,"usbradio debug off.\n"); | 
					
						
							|  |  |  | 	return RESULT_SUCCESS; | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static int radio_active(int fd, int argc, char *argv[]) | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         if (argc == 2) | 
					
						
							|  |  |  |                 ast_cli(fd, "active (command) USB Radio device is [%s]\n", usbradio_active); | 
					
						
							|  |  |  |         else if (argc != 3) | 
					
						
							|  |  |  |                 return RESULT_SHOWUSAGE; | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |                 struct chan_usbradio_pvt *o; | 
					
						
							|  |  |  |                 if (strcmp(argv[2], "show") == 0) { | 
					
						
							|  |  |  |                         for (o = usbradio_default.next; o; o = o->next) | 
					
						
							|  |  |  |                                 ast_cli(fd, "device [%s] exists\n", o->name); | 
					
						
							|  |  |  |                         return RESULT_SUCCESS; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 o = find_desc(argv[2]); | 
					
						
							|  |  |  |                 if (o == NULL) | 
					
						
							|  |  |  |                         ast_cli(fd, "No device [%s] exists\n", argv[2]); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					struct chan_usbradio_pvt *ao; | 
					
						
							|  |  |  | 					for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0; | 
					
						
							|  |  |  |                     usbradio_active = o->name; | 
					
						
							|  |  |  | 				    o->pmrChan->b.radioactive=1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	CLI debugging on and off | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int radio_set_xpmr_debug(int fd, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o = find_desc(usbradio_active); | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (argc == 4) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		i = atoi(argv[3]); | 
					
						
							|  |  |  | 		if ((i >= 0) && (i <= 100)) | 
					
						
							|  |  |  | 		{  | 
					
						
							|  |  |  | 			o->pmrChan->tracelevel=i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 	// add ability to set it for a number of frames after which it reverts
 | 
					
						
							|  |  |  | 	ast_cli(fd,"usbradio xdebug on tracelevel %i\n",o->pmrChan->tracelevel); | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	return RESULT_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static char key_usage[] = | 
					
						
							|  |  |  | 	"Usage: radio key\n" | 
					
						
							|  |  |  | 	"       Simulates COR active.\n"; | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static char unkey_usage[] = | 
					
						
							|  |  |  | 	"Usage: radio unkey\n" | 
					
						
							|  |  |  | 	"       Simulates COR un-active.\n"; | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static char active_usage[] = | 
					
						
							|  |  |  |         "Usage: radio active [device-name]\n" | 
					
						
							|  |  |  |         "       If used without a parameter, displays which device is the current\n" | 
					
						
							|  |  |  |         "one being commanded.  If a device is specified, the commanded radio device is changed\n" | 
					
						
							|  |  |  |         "to the device specified.\n"; | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | radio tune 6 3000		measured tx value | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static char radio_tune_usage[] = | 
					
						
							|  |  |  | 	"Usage: radio tune <function>\n" | 
					
						
							|  |  |  | 	"       rxnoise\n" | 
					
						
							|  |  |  | 	"       rxvoice\n" | 
					
						
							|  |  |  | 	"       rxtone\n" | 
					
						
							|  |  |  | 	"       rxsquelch [newsetting]\n" | 
					
						
							|  |  |  | 	"       txvoice [newsetting]\n" | 
					
						
							|  |  |  | 	"       txtone [newsetting]\n" | 
					
						
							|  |  |  | 	"       auxvoice [newsetting]\n" | 
					
						
							|  |  |  | 	"       save (settings to tuning file)\n" | 
					
						
							|  |  |  | 	"       load (tuning settings from EEPROM)\n" | 
					
						
							|  |  |  | 	"\n       All [newsetting]'s are values 0-999\n\n"; | 
					
						
							|  |  |  | 					   | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							| 
									
										
										
										
											2008-02-08 21:26:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static struct ast_cli_entry cli_usbradio[] = { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	{ { "radio", "key", NULL }, | 
					
						
							|  |  |  | 	console_key, "Simulate Rx Signal Present", | 
					
						
							|  |  |  | 	key_usage, NULL, NULL}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "radio", "unkey", NULL }, | 
					
						
							|  |  |  | 	console_unkey, "Simulate Rx Signal Lusb", | 
					
						
							|  |  |  | 	unkey_usage, NULL, NULL }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "radio", "tune", NULL }, | 
					
						
							|  |  |  | 	radio_tune, "Radio Tune", | 
					
						
							|  |  |  | 	radio_tune_usage, NULL, NULL }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "radio", "set", "debug", NULL }, | 
					
						
							|  |  |  | 	radio_set_debug, "Radio Debug", | 
					
						
							|  |  |  | 	radio_tune_usage, NULL, NULL }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "radio", "set", "debug", "off", NULL }, | 
					
						
							|  |  |  | 	radio_set_debug_off, "Radio Debug", | 
					
						
							|  |  |  | 	radio_tune_usage, NULL, NULL }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ { "radio", "active", NULL }, | 
					
						
							|  |  |  | 	radio_active, "Change commanded device", | 
					
						
							|  |  |  | 	active_usage, NULL, NULL }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { { "radio", "set", "xdebug", NULL }, | 
					
						
							|  |  |  | 	radio_set_xpmr_debug, "Radio set xpmr debug level", | 
					
						
							|  |  |  | 	active_usage, NULL, NULL }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * store the callerid components | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static void store_callerid(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static void store_rxdemod(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!strcasecmp(s,"no")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxdemod = RX_AUDIO_NONE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"speaker")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxdemod = RX_AUDIO_SPEAKER; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"flat")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->rxdemod = RX_AUDIO_FLAT; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Unrecognized rxdemod parameter: %s\n",s); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//ast_log(LOG_WARNING, "set rxdemod = %s\n", s);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					    | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static void store_txmixa(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!strcasecmp(s,"no")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixa = TX_OUT_OFF; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"voice")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixa = TX_OUT_VOICE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"tone")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->txmixa = TX_OUT_LSD; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"composite")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixa = TX_OUT_COMPOSITE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"auxvoice")){ | 
					
						
							|  |  |  | 		o->txmixa = TX_OUT_AUX; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Unrecognized txmixa parameter: %s\n",s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//ast_log(LOG_WARNING, "set txmixa = %s\n", s);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static void store_txmixb(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!strcasecmp(s,"no")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixb = TX_OUT_OFF; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"voice")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixb = TX_OUT_VOICE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"tone")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->txmixb = TX_OUT_LSD; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"composite")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixb = TX_OUT_COMPOSITE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"auxvoice")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixb = TX_OUT_AUX; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Unrecognized txmixb parameter: %s\n",s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//ast_log(LOG_WARNING, "set txmixb = %s\n", s);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void store_rxcdtype(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!strcasecmp(s,"no")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxcdtype = CD_IGNORE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"usb")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxcdtype = CD_HID; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"dsp")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxcdtype = CD_XPMR_NOISE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"vox")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxcdtype = CD_XPMR_VOX; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"usbinvert")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxcdtype = CD_HID_INVERT; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Unrecognized rxcdtype parameter: %s\n",s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//ast_log(LOG_WARNING, "set rxcdtype = %s\n", s);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void store_rxsdtype(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxsdtype = SD_IGNORE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"usb") || !strcasecmp(s,"SD_HID")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxsdtype = SD_HID; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"usbinvert") || !strcasecmp(s,"SD_HID_INVERT")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxsdtype = SD_HID_INVERT; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"software") || !strcasecmp(s,"SD_XPMR")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->rxsdtype = SD_XPMR; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Unrecognized rxsdtype parameter: %s\n",s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//ast_log(LOG_WARNING, "set rxsdtype = %s\n", s);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void store_rxgain(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float f; | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	sscanf(s, "%30f", &f);  | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->rxgain = f; | 
					
						
							|  |  |  | 	//ast_log(LOG_WARNING, "set rxgain = %f\n", f);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void store_rxvoiceadj(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float f; | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	sscanf(s, "%30f", &f); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->rxvoiceadj = f; | 
					
						
							|  |  |  | 	//ast_log(LOG_WARNING, "set rxvoiceadj = %f\n", f);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void store_rxctcssadj(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float f; | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	sscanf(s, "%30f", &f); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->rxctcssadj = f; | 
					
						
							|  |  |  | 	//ast_log(LOG_WARNING, "set rxctcssadj = %f\n", f);
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void store_txtoctype(struct chan_usbradio_pvt *o, char *s) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txtoctype = TOC_NONE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"phase") || !strcasecmp(s,"TOC_PHASE")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txtoctype = TOC_PHASE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (!strcasecmp(s,"notone") || !strcasecmp(s,"TOC_NOTONE")){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txtoctype = TOC_NOTONE; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING,"Unrecognized txtoctype parameter: %s\n",s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->txtestkey=1; | 
					
						
							|  |  |  | 	o->pmrChan->txPttIn=1; | 
					
						
							|  |  |  | 	TxTestTone(o->pmrChan, 1);	  // generate 1KHz tone at 7200 peak
 | 
					
						
							|  |  |  | 	if (fd > 0) ast_cli(fd,"Tone output starting on channel %s...\n",o->name); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	usleep(5000000); | 
					
						
							|  |  |  | 	TxTestTone(o->pmrChan, 0); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (fd > 0) ast_cli(fd,"Tone output ending on channel %s...\n",o->name); | 
					
						
							|  |  |  | 	o->pmrChan->txPttIn=0; | 
					
						
							|  |  |  | 	o->txtestkey=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void tune_rxinput(int fd, struct chan_usbradio_pvt *o) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	const int target=23000; | 
					
						
							|  |  |  | 	const int tolerance=2000; | 
					
						
							|  |  |  | 	const int settingmin=1; | 
					
						
							|  |  |  | 	const int settingstart=2; | 
					
						
							|  |  |  | 	const int maxtries=12; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	float settingmax; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int setting=0, tries=0, tmpdiscfactor, meas; | 
					
						
							|  |  |  | 	int tunetype=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	settingmax = o->micmax; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->pmrChan->rxDemod)tunetype=1; | 
					
						
							|  |  |  | 	o->pmrChan->b.tuning=1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	setting = settingstart; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |     ast_cli(fd,"tune rxnoise maxtries=%i, target=%i, tolerance=%i\n",maxtries,target,tolerance); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(tries<maxtries) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,setting,0); | 
					
						
							|  |  |  | 		setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0); | 
					
						
							|  |  |  |         | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		usleep(100000); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(o->rxcdtype!=CD_XPMR_NOISE || o->rxdemod==RX_AUDIO_SPEAKER)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// printf("Measure Direct Input\n");
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			o->pmrChan->spsMeasure->discfactor=2000; | 
					
						
							|  |  |  | 			o->pmrChan->spsMeasure->enabled=1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0; | 
					
						
							|  |  |  | 			usleep(400000);	 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			meas=o->pmrChan->spsMeasure->apeak; | 
					
						
							|  |  |  | 			o->pmrChan->spsMeasure->enabled=0;	 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// printf("Measure HF Noise\n");
 | 
					
						
							|  |  |  | 			tmpdiscfactor=o->pmrChan->spsRx->discfactor; | 
					
						
							|  |  |  | 			o->pmrChan->spsRx->discfactor=(i16)2000; | 
					
						
							|  |  |  | 			o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0; | 
					
						
							|  |  |  | 			o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			usleep(200000); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			meas=o->pmrChan->rxRssi; | 
					
						
							|  |  |  | 			o->pmrChan->spsRx->discfactor=tmpdiscfactor; | 
					
						
							|  |  |  | 			o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0; | 
					
						
							|  |  |  | 			o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  |         if(!meas)meas++; | 
					
						
							|  |  |  | 		ast_cli(fd,"tries=%i, setting=%i, meas=%i\n",tries,setting,meas); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){ | 
					
						
							|  |  |  | 			setting=setting*target/meas; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) ) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(setting<settingmin)setting=settingmin; | 
					
						
							|  |  |  | 		else if(setting>settingmax)setting=settingmax; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		tries++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_cli(fd,"DONE tries=%i, setting=%i, meas=%i\n",tries, | 
					
						
							|  |  |  | 		(setting * 1000) / o->micmax,meas); | 
					
						
							|  |  |  | 	if( meas<(target-tolerance) || meas>(target+tolerance) ){ | 
					
						
							|  |  |  | 		ast_cli(fd,"ERROR: RX INPUT ADJUST FAILED.\n"); | 
					
						
							|  |  |  | 	}else{ | 
					
						
							|  |  |  | 		ast_cli(fd,"INFO: RX INPUT ADJUST SUCCESS.\n");	 | 
					
						
							|  |  |  | 		o->rxmixerset=(setting * 1000) / o->micmax; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->b.tuning=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	const int target=7200;	 			// peak
 | 
					
						
							|  |  |  | 	const int tolerance=360;	   		// peak to peak
 | 
					
						
							|  |  |  | 	const float settingmin=0.1; | 
					
						
							|  |  |  | 	const float settingmax=4; | 
					
						
							|  |  |  | 	const float settingstart=1; | 
					
						
							|  |  |  | 	const int maxtries=12; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	float setting; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int tries=0, meas; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_cli(fd,"INFO: RX VOICE ADJUST START.\n");	 | 
					
						
							|  |  |  | 	ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->b.tuning=1; | 
					
						
							|  |  |  | 	if(!o->pmrChan->spsMeasure) | 
					
						
							|  |  |  | 		ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n"); | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust ) | 
					
						
							|  |  |  | 		ast_cli(fd,"ERROR: NO SOURCE OR MEASURE SETTING.\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->spsMeasure->source=o->pmrChan->spsRxOut->sink; | 
					
						
							|  |  |  | 	o->pmrChan->spsMeasure->enabled=1; | 
					
						
							|  |  |  | 	o->pmrChan->spsMeasure->discfactor=1000; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	setting=settingstart; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	// ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	while(tries<maxtries) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*(o->pmrChan->prxVoiceAdjust)=setting*M_Q8; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		usleep(10000); | 
					
						
							|  |  |  |     	o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0; | 
					
						
							|  |  |  | 		usleep(1000000); | 
					
						
							|  |  |  | 		meas = o->pmrChan->spsMeasure->apeak; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){ | 
					
						
							|  |  |  | 			setting=setting*target/meas; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) ) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if(setting<settingmin)setting=settingmin; | 
					
						
							|  |  |  | 		else if(setting>settingmax)setting=settingmax; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		tries++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->spsMeasure->enabled=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas); | 
					
						
							|  |  |  | 	if( meas<(target-tolerance) || meas>(target+tolerance) ){ | 
					
						
							|  |  |  | 		ast_cli(fd,"ERROR: RX VOICE GAIN ADJUST FAILED.\n"); | 
					
						
							|  |  |  | 	}else{ | 
					
						
							|  |  |  | 		ast_cli(fd,"INFO: RX VOICE GAIN ADJUST SUCCESS.\n"); | 
					
						
							|  |  |  | 		o->rxvoiceadj=setting; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->b.tuning=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o) | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	const int target=2400;		 // was 4096 pre 20080205
 | 
					
						
							|  |  |  | 	const int tolerance=100; | 
					
						
							|  |  |  | 	const float settingmin=0.1; | 
					
						
							|  |  |  | 	const float settingmax=8; | 
					
						
							|  |  |  | 	const float settingstart=1; | 
					
						
							|  |  |  | 	const int maxtries=12; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	float setting; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int tries=0, meas; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_cli(fd,"INFO: RX CTCSS ADJUST START.\n");	 | 
					
						
							|  |  |  | 	ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->b.tuning=1; | 
					
						
							|  |  |  | 	o->pmrChan->spsMeasure->source=o->pmrChan->prxCtcssMeasure; | 
					
						
							|  |  |  | 	o->pmrChan->spsMeasure->discfactor=400; | 
					
						
							|  |  |  | 	o->pmrChan->spsMeasure->enabled=1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	setting=settingstart; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	while(tries<maxtries) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*(o->pmrChan->prxCtcssAdjust)=setting*M_Q8; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		usleep(10000); | 
					
						
							|  |  |  |     	o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0; | 
					
						
							|  |  |  | 		usleep(500000); | 
					
						
							|  |  |  | 		meas = o->pmrChan->spsMeasure->apeak; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){ | 
					
						
							|  |  |  | 			setting=setting*target/meas; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) ) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if(setting<settingmin)setting=settingmin; | 
					
						
							|  |  |  | 		else if(setting>settingmax)setting=settingmax; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		tries++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->spsMeasure->enabled=0; | 
					
						
							|  |  |  | 	ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas); | 
					
						
							|  |  |  | 	if( meas<(target-tolerance) || meas>(target+tolerance) ){ | 
					
						
							|  |  |  | 		ast_cli(fd,"ERROR: RX CTCSS GAIN ADJUST FAILED.\n"); | 
					
						
							|  |  |  | 	}else{ | 
					
						
							|  |  |  | 		ast_cli(fd,"INFO: RX CTCSS GAIN ADJUST SUCCESS.\n"); | 
					
						
							|  |  |  | 		o->rxctcssadj=setting; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->b.tuning=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	after radio tune is performed data is serialized here  | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | static void tune_write(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	FILE *fp; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	char fname[200]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  	snprintf(fname,sizeof(fname) - 1,"/etc/asterisk/usbradio_tune_%s.conf",o->name); | 
					
						
							|  |  |  | 	fp = fopen(fname,"w"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(fp,"[%s]\n",o->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fprintf(fp,"; name=%s\n",o->name); | 
					
						
							|  |  |  | 	fprintf(fp,"; devicenum=%i\n",o->devicenum); | 
					
						
							|  |  |  | 	fprintf(fp,"devstr=%s\n",o->devstr); | 
					
						
							|  |  |  | 	fprintf(fp,"rxmixerset=%i\n",o->rxmixerset); | 
					
						
							|  |  |  | 	fprintf(fp,"txmixaset=%i\n",o->txmixaset); | 
					
						
							|  |  |  | 	fprintf(fp,"txmixbset=%i\n",o->txmixbset); | 
					
						
							|  |  |  | 	fprintf(fp,"rxvoiceadj=%f\n",o->rxvoiceadj); | 
					
						
							|  |  |  | 	fprintf(fp,"rxctcssadj=%f\n",o->rxctcssadj); | 
					
						
							|  |  |  | 	fprintf(fp,"txctcssadj=%i\n",o->txctcssadj); | 
					
						
							|  |  |  | 	fprintf(fp,"rxsquelchadj=%i\n",o->rxsquelchadj); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	fclose(fp); | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->wanteeprom) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_mutex_lock(&o->eepromlock); | 
					
						
							|  |  |  | 		while(o->eepromctl) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_mutex_unlock(&o->eepromlock); | 
					
						
							|  |  |  | 			usleep(10000); | 
					
						
							|  |  |  | 			ast_mutex_lock(&o->eepromlock); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o->eeprom[EEPROM_RXMIXERSET] = o->rxmixerset; | 
					
						
							|  |  |  | 		o->eeprom[EEPROM_TXMIXASET] = o->txmixaset; | 
					
						
							|  |  |  | 		o->eeprom[EEPROM_TXMIXBSET] = o->txmixbset; | 
					
						
							|  |  |  | 		memcpy(&o->eeprom[EEPROM_RXVOICEADJ],&o->rxvoiceadj,sizeof(float)); | 
					
						
							|  |  |  | 		memcpy(&o->eeprom[EEPROM_RXCTCSSADJ],&o->rxctcssadj,sizeof(float)); | 
					
						
							|  |  |  | 		o->eeprom[EEPROM_TXCTCSSADJ] = o->txctcssadj; | 
					
						
							|  |  |  | 		o->eeprom[EEPROM_RXSQUELCHADJ] = o->rxsquelchadj; | 
					
						
							|  |  |  | 		o->eepromctl = 2;  /* request a write */ | 
					
						
							|  |  |  | 		ast_mutex_unlock(&o->eepromlock); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static void mixer_write(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_SW,0,0); | 
					
						
							|  |  |  | 	setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_VOL,0,0); | 
					
						
							|  |  |  | 	setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_SW,1,0); | 
					
						
							|  |  |  | 	setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL, | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->txmixaset * o->spkrmax / 1000, | 
					
						
							|  |  |  | 		o->txmixbset * o->spkrmax / 1000); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL, | 
					
						
							|  |  |  | 		o->rxmixerset * o->micmax / 1000,0); | 
					
						
							|  |  |  | 	setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0); | 
					
						
							|  |  |  | 	setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_SW,1,0); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	adjust dsp multiplier to add resolution to tx level adjustment | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void mult_set(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->pmrChan->spsTxOutA) { | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->pmrChan->spsTxOutA->outputGain =  | 
					
						
							|  |  |  | 			mult_calc((o->txmixaset * 152) / 1000); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->pmrChan->spsTxOutB){ | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->pmrChan->spsTxOutB->outputGain =  | 
					
						
							|  |  |  | 			mult_calc((o->txmixbset * 152) / 1000); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | //
 | 
					
						
							|  |  |  | // input 0 - 151 outputs are pot and multiplier
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | static int mult_calc(int value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	const int multx=M_Q8; | 
					
						
							|  |  |  | 	int pot,mult; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pot=((int)(value/4)*4)+2; | 
					
						
							|  |  |  | 	mult = multx-( ( multx * (3-(value%4)) ) / (pot+2) ); | 
					
						
							|  |  |  | 	return(mult); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #define pd(x) {printf(#x" = %d\n",x);}
 | 
					
						
							|  |  |  | #define pp(x) {printf(#x" = %p\n",x);}
 | 
					
						
							|  |  |  | #define ps(x) {printf(#x" = %s\n",x);}
 | 
					
						
							|  |  |  | #define pf(x) {printf(#x" = %f\n",x);}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	do hid output if only requirement is ptt out | 
					
						
							|  |  |  | 	this give fastest performance with least overhead | 
					
						
							|  |  |  | 	where gpio inputs are not required. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int usbhider(struct chan_usbradio_pvt *o, int opt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned char buf[4]; | 
					
						
							|  |  |  | 	char lastrx, txtmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(opt) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		struct usb_device *usb_dev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		usb_dev = hid_device_init(o->devstr); | 
					
						
							|  |  |  | 		if (usb_dev == NULL) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"USB HID device not found\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o->usb_handle = usb_open(usb_dev); | 
					
						
							|  |  |  | 		if (o->usb_handle == NULL) { | 
					
						
							|  |  |  | 		    ast_log(LOG_ERROR,"Not able to open USB device\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		    if (usb_detach_kernel_driver_np(o->usb_handle,C108_HID_INTERFACE) < 0) { | 
					
						
							|  |  |  | 			    ast_log(LOG_ERROR,"Not able to detach the USB device\n"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0) { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR,"Not able to claim the USB device\n"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		memset(buf,0,sizeof(buf)); | 
					
						
							|  |  |  | 		buf[2] = o->hid_gpio_ctl; | 
					
						
							|  |  |  | 		buf[1] = 0; | 
					
						
							|  |  |  | 		hid_set_outputs(o->usb_handle,buf); | 
					
						
							|  |  |  | 		memcpy(bufsave,buf,sizeof(buf)); | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 		buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; | 
					
						
							|  |  |  | 		o->lasttx=0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if change in tx state as controlled by xpmr */ | 
					
						
							|  |  |  | 	txtmp=o->pmrChan->txPttOut; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 	if (o->lasttx != txtmp) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->pmrChan->txPttHid=o->lasttx = txtmp; | 
					
						
							|  |  |  | 		if(o->debuglevel)printf("usbhid: tx set to %d\n",txtmp); | 
					
						
							|  |  |  | 		buf[o->hid_gpio_loc] = 0; | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 		hid_set_outputs(o->usb_handle,buf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void pmrdump(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	t_pmr_chan *p; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	p=o->pmrChan; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	printf("\nodump()\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pd(o->devicenum); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ps(o->devstr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(o->micmax); | 
					
						
							|  |  |  | 	pd(o->spkrmax); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pd(o->rxdemod); | 
					
						
							|  |  |  | 	pd(o->rxcdtype); | 
					
						
							|  |  |  | 	pd(o->rxsdtype); | 
					
						
							|  |  |  | 	pd(o->txtoctype); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(o->rxmixerset); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pd(o->rxboostset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	pf(o->rxvoiceadj); | 
					
						
							|  |  |  | 	pf(o->rxctcssadj); | 
					
						
							|  |  |  | 	pd(o->rxsquelchadj); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ps(o->txctcssdefault); | 
					
						
							|  |  |  | 	ps(o->txctcssfreq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(o->numrxctcssfreqs); | 
					
						
							|  |  |  | 	if(o->numrxctcssfreqs>0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for(i=0;i<o->numrxctcssfreqs;i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			printf(" %i =  %s  %s\n",i,o->rxctcss[i],o->txctcss[i]);  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(o->b.rxpolarity); | 
					
						
							|  |  |  | 	pd(o->b.txpolarity); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	pd(o->txprelim); | 
					
						
							|  |  |  | 	pd(o->txmixa); | 
					
						
							|  |  |  | 	pd(o->txmixb); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	pd(o->txmixaset); | 
					
						
							|  |  |  | 	pd(o->txmixbset); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	printf("\npmrdump()\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |   | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pd(p->devicenum); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	printf("prxSquelchAdjust=%i\n",*(o->pmrChan->prxSquelchAdjust)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->rxCarrierPoint); | 
					
						
							|  |  |  | 	pd(p->rxCarrierHyst); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pd(*p->prxVoiceAdjust); | 
					
						
							|  |  |  | 	pd(*p->prxCtcssAdjust); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->rxfreq); | 
					
						
							|  |  |  | 	pd(p->txfreq); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	pd(p->rxCtcss->relax); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	//pf(p->rxCtcssFreq);	
 | 
					
						
							|  |  |  | 	pd(p->numrxcodes); | 
					
						
							|  |  |  | 	if(o->pmrChan->numrxcodes>0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for(i=0;i<o->pmrChan->numrxcodes;i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			printf(" %i = %s\n",i,o->pmrChan->pRxCode[i]);  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->txTocType); | 
					
						
							|  |  |  | 	ps(p->pTxCodeDefault); | 
					
						
							|  |  |  | 	pd(p->txcodedefaultsmode); | 
					
						
							|  |  |  | 	pd(p->numtxcodes); | 
					
						
							|  |  |  | 	if(o->pmrChan->numtxcodes>0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for(i=0;i<o->pmrChan->numtxcodes;i++) | 
					
						
							|  |  |  | 		{													  | 
					
						
							|  |  |  | 			printf(" %i = %s\n",i,o->pmrChan->pTxCode[i]);  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->b.rxpolarity); | 
					
						
							|  |  |  | 	pd(p->b.txpolarity); | 
					
						
							|  |  |  | 	pd(p->b.dcsrxpolarity); | 
					
						
							|  |  |  | 	pd(p->b.dcstxpolarity); | 
					
						
							|  |  |  | 	pd(p->b.lsdrxpolarity); | 
					
						
							|  |  |  | 	pd(p->b.lsdtxpolarity); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->txMixA); | 
					
						
							|  |  |  | 	pd(p->txMixB); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | 	pd(p->rxDeEmpEnable); | 
					
						
							|  |  |  | 	pd(p->rxCenterSlicerEnable); | 
					
						
							|  |  |  | 	pd(p->rxCtcssDecodeEnable); | 
					
						
							|  |  |  | 	pd(p->rxDcsDecodeEnable); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pd(p->b.ctcssRxEnable); | 
					
						
							|  |  |  | 	pd(p->b.dcsRxEnable); | 
					
						
							|  |  |  | 	pd(p->b.lmrRxEnable); | 
					
						
							|  |  |  | 	pd(p->b.dstRxEnable); | 
					
						
							|  |  |  | 	pd(p->smode); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->txHpfEnable); | 
					
						
							|  |  |  | 	pd(p->txLimiterEnable); | 
					
						
							|  |  |  | 	pd(p->txPreEmpEnable); | 
					
						
							|  |  |  | 	pd(p->txLpfEnable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(p->spsTxOutA)pd(p->spsTxOutA->outputGain); | 
					
						
							|  |  |  | 	if(p->spsTxOutB)pd(p->spsTxOutB->outputGain); | 
					
						
							|  |  |  | 	pd(p->txPttIn); | 
					
						
							|  |  |  | 	pd(p->txPttOut); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pd(p->tracetype); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 	takes data from a chan_usbradio_pvt struct (e.g. o->) | 
					
						
							|  |  |  | 	and configures the xpmr radio layer | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int xpmr_config(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	//ast_log(LOG_NOTICE,"xpmr_config()\n");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	TRACEO(1,("xpmr_config()\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(o->pmrChan==NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR,"pmr channel structure NULL\n"); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->pmrChan->rxCtcss->relax = o->rxctcssrelax; | 
					
						
							|  |  |  | 	o->pmrChan->txpower=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->b.remoted) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		o->pmrChan->pTxCodeDefault = o->set_txctcssdefault; | 
					
						
							|  |  |  | 		o->pmrChan->pRxCodeSrc=o->set_rxctcssfreqs; | 
					
						
							|  |  |  | 		o->pmrChan->pTxCodeSrc=o->set_txctcssfreqs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		o->pmrChan->rxfreq=o->set_rxfreq; | 
					
						
							|  |  |  | 		o->pmrChan->txfreq=o->set_txfreq; | 
					
						
							|  |  |  | 		/* printf(" remoted %s %s --> %s \n",o->pmrChan->txctcssdefault,
 | 
					
						
							|  |  |  | 			o->pmrChan->txctcssfreq,o->pmrChan->rxctcssfreq); */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// set xpmr pointers to source strings
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		o->pmrChan->pTxCodeDefault = o->txctcssdefault; | 
					
						
							|  |  |  | 		o->pmrChan->pRxCodeSrc     = o->rxctcssfreqs; | 
					
						
							|  |  |  | 		o->pmrChan->pTxCodeSrc     = o->txctcssfreqs; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		o->pmrChan->rxfreq = o->rxfreq; | 
					
						
							|  |  |  | 		o->pmrChan->txfreq = o->txfreq; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	code_string_parse(o->pmrChan); | 
					
						
							|  |  |  | 	if(o->pmrChan->rxfreq) o->pmrChan->b.reprog=1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * grab fields from the config file, init the descriptor and open the device. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static struct chan_usbradio_pvt *store_config(struct ast_config *cfg, char *ctg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_variable *v; | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o; | 
					
						
							|  |  |  | 	struct ast_config *cfg1; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 	char fname[200]; | 
					
						
							|  |  |  | #ifdef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	struct ast_flags zeroflag = {0}; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	if (ctg == NULL) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		traceusb1((" store_config() ctg == NULL\n")); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o = &usbradio_default; | 
					
						
							|  |  |  | 		ctg = "general"; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* "general" is also the default thing */ | 
					
						
							|  |  |  | 		if (strcmp(ctg, "general") == 0) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			o = &usbradio_default; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 		    // ast_log(LOG_NOTICE,"ast_calloc for chan_usbradio_pvt of %s\n",ctg);
 | 
					
						
							|  |  |  | 			if (!(o = ast_calloc(1, sizeof(*o)))) | 
					
						
							|  |  |  | 				return NULL; | 
					
						
							|  |  |  | 			*o = usbradio_default; | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 			o->name = ast_strdup(ctg); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			if (!usbradio_active)  | 
					
						
							|  |  |  | 				usbradio_active = o->name; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	ast_mutex_init(&o->eepromlock); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	strcpy(o->mohinterpret, "default"); | 
					
						
							|  |  |  | 	/* fill other fields from configuration */ | 
					
						
							|  |  |  | 	for (v = ast_variable_browse(cfg, ctg); v; v = v->next) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		M_START((char *)v->name, (char *)v->value); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* handle jb conf */ | 
					
						
							|  |  |  | 		if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if	0
 | 
					
						
							|  |  |  | 			M_BOOL("autoanswer", o->autoanswer) | 
					
						
							|  |  |  | 			M_BOOL("autohangup", o->autohangup) | 
					
						
							|  |  |  | 			M_BOOL("overridecontext", o->overridecontext) | 
					
						
							|  |  |  | 			M_STR("context", o->ctx) | 
					
						
							|  |  |  | 			M_STR("language", o->language) | 
					
						
							|  |  |  | 			M_STR("mohinterpret", o->mohinterpret) | 
					
						
							|  |  |  | 			M_STR("extension", o->ext) | 
					
						
							|  |  |  | 			M_F("callerid", store_callerid(o, v->value)) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			M_UINT("frags", o->frags) | 
					
						
							|  |  |  | 			M_UINT("queuesize",o->queuesize) | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 			M_UINT("devicenum",o->devicenum) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			M_UINT("debug", usbradio_debug) | 
					
						
							|  |  |  | 			M_BOOL("rxcpusaver",o->rxcpusaver) | 
					
						
							|  |  |  | 			M_BOOL("txcpusaver",o->txcpusaver) | 
					
						
							|  |  |  | 			M_BOOL("invertptt",o->invertptt) | 
					
						
							|  |  |  | 			M_F("rxdemod",store_rxdemod(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_BOOL("txprelim",o->txprelim); | 
					
						
							|  |  |  | 			M_F("txmixa",store_txmixa(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_F("txmixb",store_txmixb(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_F("carrierfrom",store_rxcdtype(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_F("rxsdtype",store_rxsdtype(o,(char *)v->value)) | 
					
						
							|  |  |  | 		    M_UINT("rxsqvox",o->rxsqvoxadj) | 
					
						
							|  |  |  | 			M_STR("txctcssdefault",o->txctcssdefault) | 
					
						
							|  |  |  | 			M_STR("rxctcssfreqs",o->rxctcssfreqs) | 
					
						
							|  |  |  | 			M_STR("txctcssfreqs",o->txctcssfreqs) | 
					
						
							|  |  |  | 			M_UINT("rxfreq",o->rxfreq) | 
					
						
							|  |  |  | 			M_UINT("txfreq",o->txfreq) | 
					
						
							|  |  |  | 			M_F("rxgain",store_rxgain(o,(char *)v->value)) | 
					
						
							|  |  |  |  			M_BOOL("rxboost",o->rxboostset) | 
					
						
							|  |  |  | 			M_UINT("rxctcssrelax",o->rxctcssrelax) | 
					
						
							|  |  |  | 			M_F("txtoctype",store_txtoctype(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_UINT("hdwtype",o->hdwtype) | 
					
						
							|  |  |  | 			M_UINT("eeprom",o->wanteeprom) | 
					
						
							|  |  |  | 			M_UINT("duplex",o->radioduplex) | 
					
						
							|  |  |  | 			M_UINT("txsettletime",o->txsettletime) | 
					
						
							|  |  |  | 			M_BOOL("rxpolarity",o->b.rxpolarity) | 
					
						
							|  |  |  | 			M_BOOL("txpolarity",o->b.txpolarity) | 
					
						
							|  |  |  | 			M_BOOL("dcsrxpolarity",o->b.dcsrxpolarity) | 
					
						
							|  |  |  | 			M_BOOL("dcstxpolarity",o->b.dcstxpolarity) | 
					
						
							|  |  |  | 			M_BOOL("lsdrxpolarity",o->b.lsdrxpolarity) | 
					
						
							|  |  |  | 			M_BOOL("lsdtxpolarity",o->b.lsdtxpolarity) | 
					
						
							|  |  |  | 			M_BOOL("loopback",o->b.loopback) | 
					
						
							|  |  |  | 			M_BOOL("radioactive",o->b.radioactive) | 
					
						
							|  |  |  | 			M_UINT("rptnum",o->rptnum) | 
					
						
							|  |  |  | 			M_UINT("idleinterval",o->idleinterval) | 
					
						
							|  |  |  | 			M_UINT("turnoffs",o->turnoffs) | 
					
						
							|  |  |  | 			M_UINT("tracetype",o->tracetype) | 
					
						
							|  |  |  | 			M_UINT("tracelevel",o->tracelevel) | 
					
						
							|  |  |  | 			M_UINT("area",o->area) | 
					
						
							|  |  |  | 			M_STR("ukey",o->ukey) | 
					
						
							|  |  |  | 			M_END(; | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	o->debuglevel=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (o == &usbradio_default)		/* we are done with the default */ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	snprintf(fname,sizeof(fname) - 1,config1,o->name); | 
					
						
							|  |  |  | #ifdef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	cfg1 = ast_config_load(fname,zeroflag); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	cfg1 = ast_config_load(fname); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	o->rxmixerset = 500; | 
					
						
							|  |  |  | 	o->txmixaset = 500; | 
					
						
							|  |  |  | 	o->txmixbset = 500; | 
					
						
							|  |  |  | 	o->rxvoiceadj = 0.5; | 
					
						
							|  |  |  | 	o->rxctcssadj = 0.5; | 
					
						
							|  |  |  | 	o->txctcssadj = 200; | 
					
						
							|  |  |  | 	o->rxsquelchadj = 500; | 
					
						
							|  |  |  | 	o->devstr[0] = 0; | 
					
						
							| 
									
										
										
										
											2008-11-19 19:25:14 +00:00
										 |  |  | 	if (cfg1 && cfg1 != CONFIG_STATUS_FILEINVALID) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		for (v = ast_variable_browse(cfg1, o->name); v; v = v->next) { | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 			M_START((char *)v->name, (char *)v->value); | 
					
						
							|  |  |  | 			M_UINT("rxmixerset", o->rxmixerset) | 
					
						
							|  |  |  | 			M_UINT("txmixaset", o->txmixaset) | 
					
						
							|  |  |  | 			M_UINT("txmixbset", o->txmixbset) | 
					
						
							|  |  |  | 			M_F("rxvoiceadj",store_rxvoiceadj(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_F("rxctcssadj",store_rxctcssadj(o,(char *)v->value)) | 
					
						
							|  |  |  | 			M_UINT("txctcssadj",o->txctcssadj); | 
					
						
							|  |  |  | 			M_UINT("rxsquelchadj", o->rxsquelchadj) | 
					
						
							|  |  |  | 			M_STR("devstr", o->devstr) | 
					
						
							|  |  |  | 			M_END(; | 
					
						
							|  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		ast_config_destroy(cfg1); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	} else ast_log(LOG_WARNING,"File %s not found, using default parameters.\n",fname); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(o->wanteeprom) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ast_mutex_lock(&o->eepromlock); | 
					
						
							|  |  |  | 		while(o->eepromctl) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_mutex_unlock(&o->eepromlock); | 
					
						
							|  |  |  | 			usleep(10000); | 
					
						
							|  |  |  | 			ast_mutex_lock(&o->eepromlock); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o->eepromctl = 1;  /* request a load */ | 
					
						
							|  |  |  | 		ast_mutex_unlock(&o->eepromlock); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	/* if our specified one exists in the list */ | 
					
						
							|  |  |  | 	if ((!usb_list_check(o->devstr)) || find_desc_usb(o->devstr)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		char *s; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		for(s = usb_device_list; *s; s += strlen(s) + 1) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (!find_desc_usb(s)) break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!*s) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING,"Unable to assign USB device for channel %s\n",o->name); | 
					
						
							|  |  |  | 			goto error; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE,"Assigned USB device %s to usbradio channel %s\n",s,o->name); | 
					
						
							|  |  |  | 		strcpy(o->devstr,s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	i = usb_get_usbdev(o->devstr); | 
					
						
							|  |  |  | 	if (i < 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	        ast_log(LOG_ERROR,"Not able to find alsa USB device\n"); | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	o->devicenum = i; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	o->micmax = amixer_max(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL); | 
					
						
							|  |  |  | 	o->spkrmax = amixer_max(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	o->lastopen = ast_tvnow();	/* don't leave it 0 or tvdiff may wrap */ | 
					
						
							|  |  |  | 	o->dsp = ast_dsp_new(); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if (o->dsp) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #ifdef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	  ast_dsp_set_features(o->dsp,DSP_FEATURE_DIGIT_DETECT); | 
					
						
							|  |  |  | 	  ast_dsp_set_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	  ast_dsp_set_features(o->dsp,DSP_FEATURE_DTMF_DETECT); | 
					
						
							|  |  |  | 	  ast_dsp_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(o->pmrChan==NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 		t_pmr_chan tChan; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		// ast_log(LOG_NOTICE,"createPmrChannel() %s\n",o->name);
 | 
					
						
							|  |  |  | 		memset(&tChan,0,sizeof(t_pmr_chan)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tChan.pTxCodeDefault = o->txctcssdefault; | 
					
						
							|  |  |  | 		tChan.pRxCodeSrc     = o->rxctcssfreqs; | 
					
						
							|  |  |  | 		tChan.pTxCodeSrc     = o->txctcssfreqs; | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tChan.rxDemod=o->rxdemod; | 
					
						
							|  |  |  | 		tChan.rxCdType=o->rxcdtype; | 
					
						
							|  |  |  | 		tChan.rxSqVoxAdj=o->rxsqvoxadj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (o->txprelim)  | 
					
						
							|  |  |  | 			tChan.txMod = 2; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		tChan.txMixA = o->txmixa; | 
					
						
							|  |  |  | 		tChan.txMixB = o->txmixb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tChan.rxCpuSaver=o->rxcpusaver; | 
					
						
							|  |  |  | 		tChan.txCpuSaver=o->txcpusaver; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tChan.b.rxpolarity=o->b.rxpolarity; | 
					
						
							|  |  |  | 		tChan.b.txpolarity=o->b.txpolarity; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tChan.b.dcsrxpolarity=o->b.dcsrxpolarity; | 
					
						
							|  |  |  | 		tChan.b.dcstxpolarity=o->b.dcstxpolarity; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tChan.b.lsdrxpolarity=o->b.lsdrxpolarity; | 
					
						
							|  |  |  | 		tChan.b.lsdtxpolarity=o->b.lsdtxpolarity; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		tChan.tracetype=o->tracetype; | 
					
						
							|  |  |  | 		tChan.tracelevel=o->tracelevel; | 
					
						
							|  |  |  | 		tChan.rptnum=o->rptnum; | 
					
						
							|  |  |  | 		tChan.idleinterval=o->idleinterval; | 
					
						
							|  |  |  | 		tChan.turnoffs=o->turnoffs; | 
					
						
							|  |  |  | 		tChan.area=o->area; | 
					
						
							|  |  |  | 		tChan.ukey=o->ukey; | 
					
						
							|  |  |  | 		tChan.name=o->name; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		o->pmrChan=createPmrChannel(&tChan,FRAME_SIZE); | 
					
						
							|  |  |  | 									  | 
					
						
							|  |  |  | 		o->pmrChan->radioDuplex=o->radioduplex; | 
					
						
							|  |  |  | 		o->pmrChan->b.loopback=0;  | 
					
						
							|  |  |  | 		o->pmrChan->txsettletime=o->txsettletime; | 
					
						
							|  |  |  | 		o->pmrChan->rxCpuSaver=o->rxcpusaver; | 
					
						
							|  |  |  | 		o->pmrChan->txCpuSaver=o->txcpusaver; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		*(o->pmrChan->prxSquelchAdjust) =  | 
					
						
							|  |  |  | 			((999 - o->rxsquelchadj) * 32767) / 1000; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		*(o->pmrChan->prxVoiceAdjust)=o->rxvoiceadj*M_Q8; | 
					
						
							|  |  |  | 		*(o->pmrChan->prxCtcssAdjust)=o->rxctcssadj*M_Q8; | 
					
						
							|  |  |  | 		o->pmrChan->rxCtcss->relax=o->rxctcssrelax; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		o->pmrChan->txTocType = o->txtoctype; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         if (    (o->txmixa == TX_OUT_LSD) || | 
					
						
							|  |  |  |                 (o->txmixa == TX_OUT_COMPOSITE) || | 
					
						
							|  |  |  |                 (o->txmixb == TX_OUT_LSD) || | 
					
						
							|  |  |  |                 (o->txmixb == TX_OUT_COMPOSITE)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |                 set_txctcss_level(o); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) && | 
					
						
							|  |  |  | 			(o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE) | 
					
						
							|  |  |  | 		  ) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"No txvoice output configured.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		if( o->txctcssfreq[0] &&  | 
					
						
							|  |  |  | 		    o->txmixa!=TX_OUT_LSD && o->txmixa!=TX_OUT_COMPOSITE  && | 
					
						
							|  |  |  | 			o->txmixb!=TX_OUT_LSD && o->txmixb!=TX_OUT_COMPOSITE | 
					
						
							|  |  |  | 		  ) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR,"No txtone output configured.\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(o->b.radioactive) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		    // 20080328 sphenke asdf maw !!!
 | 
					
						
							|  |  |  | 		    // this diagnostic option was working but now appears broken
 | 
					
						
							|  |  |  | 			// it's not required for operation so I'll fix it later.
 | 
					
						
							|  |  |  | 			//struct chan_usbradio_pvt *ao;
 | 
					
						
							|  |  |  | 			//for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
 | 
					
						
							|  |  |  | 			usbradio_active = o->name; | 
					
						
							|  |  |  | 			// o->pmrChan->b.radioactive=1;
 | 
					
						
							|  |  |  | 			//o->b.radioactive=0;
 | 
					
						
							|  |  |  | 			//o->pmrChan->b.radioactive=0;
 | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE,"radio active set to [%s]\n",o->name); | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	xpmr_config(o); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	TRACEO(1,("store_config() 120\n")); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	mixer_write(o); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	TRACEO(1,("store_config() 130\n")); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	mult_set(o);     | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	TRACEO(1,("store_config() 140\n")); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	hidhdwconfig(o); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	TRACEO(1,("store_config() 200\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	if (pipe(o->sndcmd) != 0) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unable to create pipe\n"); | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_pthread_create_background(&o->sthread, NULL, sound_thread, o); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* link into list of devices */ | 
					
						
							|  |  |  | 	if (o != &usbradio_default) { | 
					
						
							|  |  |  | 		o->next = usbradio_default.next; | 
					
						
							|  |  |  | 		usbradio_default.next = o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	TRACEO(1,("store_config() complete\n")); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	return o; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   error: | 
					
						
							|  |  |  | 	if (o != &usbradio_default) | 
					
						
							|  |  |  | 		free(o); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #if	DEBUG_FILETEST == 1
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	Test It on a File | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | int RxTestIt(struct chan_usbradio_pvt *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const int numSamples = SAMPLES_PER_BLOCK; | 
					
						
							|  |  |  | 	const int numChannels = 16; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	i16 sample,i,ii; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	i32 txHangTime; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i16 txEnable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	t_pmr_chan	tChan; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	t_pmr_chan *pChan; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	FILE *hInput=NULL, *hOutput=NULL, *hOutputTx=NULL; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  |   | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	i16 iBuff[numSamples*2*6], oBuff[numSamples]; | 
					
						
							|  |  |  | 				   | 
					
						
							|  |  |  | 	printf("RxTestIt()\n"); | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pChan=o->pmrChan; | 
					
						
							|  |  |  | 	pChan->b.txCapture=1; | 
					
						
							|  |  |  | 	pChan->b.rxCapture=1; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	txEnable = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	hInput  = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r"); | 
					
						
							|  |  |  | 	if(!hInput){ | 
					
						
							|  |  |  | 		printf(" RxTestIt() File Not Found.\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	hOutput = fopen("/usr/src/xpmr/testdata/rx_debug.pcm","w"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	printf(" RxTestIt() Working...\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 			 	 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	while(!feof(hInput)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		fread((void *)iBuff,2,numSamples*2*6,hInput); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		  | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(txHangTime)txHangTime-=numSamples; | 
					
						
							|  |  |  | 		if(txHangTime<0)txHangTime=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(pChan->rxCtcss->decode)txHangTime=(8000/1000*2000); | 
					
						
							| 
									
										
										
										
											2007-12-04 21:46:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(pChan->rxCtcss->decode && !txEnable) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			txEnable=1; | 
					
						
							|  |  |  | 			//pChan->inputBlanking=(8000/1000*200);
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if(!pChan->rxCtcss->decode && txEnable) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			txEnable=0;	 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		PmrRx(pChan,iBuff,oBuff); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-25 03:49:30 +00:00
										 |  |  | 		if (fwrite((void *)pChan->prxDebug,2,numSamples*numChannels,hOutput) != numSamples * numChannels) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	pChan->b.txCapture=0; | 
					
						
							|  |  |  | 	pChan->b.rxCapture=0; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	if(hInput)fclose(hInput); | 
					
						
							|  |  |  | 	if(hOutput)fclose(hOutput); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 	printf(" RxTestIt() Complete.\n"); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifdef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *res2cli(int r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch (r) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	    case RESULT_SUCCESS: | 
					
						
							|  |  |  | 		return(CLI_SUCCESS); | 
					
						
							|  |  |  | 	    case RESULT_SHOWUSAGE: | 
					
						
							|  |  |  | 		return(CLI_SHOWUSAGE); | 
					
						
							|  |  |  | 	    default: | 
					
						
							|  |  |  | 		return(CLI_FAILURE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_console_key(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	char *argv[] = { "radio", "key", NULL }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio key"; | 
					
						
							|  |  |  |                 e->usage = key_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(console_key(a->fd, 2, argv)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_console_unkey(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	char *argv[] = { "radio", "unkey", NULL }; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio unkey"; | 
					
						
							|  |  |  |                 e->usage = unkey_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(console_unkey(a->fd, 2, argv)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_radio_tune(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	char *argv[5] = { "radio", "tune", a->argc > 2 ? (char *) a->argv[2] : NULL, a->argc > 3 ? (char *) a->argv[3] : NULL }; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio tune"; | 
					
						
							|  |  |  |                 e->usage = radio_tune_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(radio_tune(a->fd, a->argc, argv)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_radio_debug(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio debug"; | 
					
						
							|  |  |  |                 e->usage = radio_tune_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(radio_set_debug(a->fd, a->argc, NULL /* ignored */)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_radio_debug_off(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio debug off"; | 
					
						
							|  |  |  |                 e->usage = radio_tune_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(radio_set_debug_off(a->fd, a->argc, NULL /* ignored */)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_radio_active(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	char *argv[4] = { "radio", "active", a->argc > 2 ? (char *) a->argv[2] : NULL, }; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio active"; | 
					
						
							|  |  |  |                 e->usage = active_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(radio_active(a->fd, a->argc, argv)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *handle_set_xdebug(struct ast_cli_entry *e, | 
					
						
							|  |  |  | 	int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	char *argv[5] = { "radio", "set", "xdebug", a->argc == 4 ? (char *) a->argv[3] : NULL, }; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  |         switch (cmd) { | 
					
						
							|  |  |  |         case CLI_INIT: | 
					
						
							|  |  |  |                 e->command = "radio set xdebug"; | 
					
						
							|  |  |  |                 e->usage = active_usage; | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         case CLI_GENERATE: | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 	return res2cli(radio_set_xpmr_debug(a->fd, a->argc, argv)); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_cli_entry cli_usbradio[] = { | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_console_key,"Simulate Rx Signal Present"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_console_unkey,"Simulate Rx Signal Loss"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_radio_tune,"Radio Tune"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_radio_debug,"Radio Debug On"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_radio_debug_off,"Radio Debug Off"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_radio_active,"Change commanded device"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_set_xdebug,"Radio set xpmr debug level") | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | #include "./xpmr/xpmr.c"
 | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifdef HAVE_XPMRX
 | 
					
						
							|  |  |  | #include "./xpmrx/xpmrx.c"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int load_module(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_config *cfg = NULL; | 
					
						
							|  |  |  | 	char *ctg = NULL; | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifdef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 	struct ast_flags zeroflag = {0}; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hid_device_mklist()) { | 
					
						
							|  |  |  | 		ast_log(LOG_NOTICE, "Unable to make hid list\n"); | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	usb_list_check(""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	usbradio_active = NULL; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Copy the default jb config over global_jbconf */ | 
					
						
							|  |  |  | 	memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* load config file */ | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifdef	NEW_ASTERISK
 | 
					
						
							| 
									
										
										
										
											2008-11-19 19:25:14 +00:00
										 |  |  | 	if (!(cfg = ast_config_load(config,zeroflag)) || cfg == CONFIG_STATUS_FILEINVALID) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-11-19 19:25:14 +00:00
										 |  |  | 	if (!(cfg = ast_config_load(config))) || cfg == CONFIG_STATUS_FILEINVALID { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "Unable to load config %s\n", config); | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		store_config(cfg, ctg); | 
					
						
							|  |  |  | 	} while ( (ctg = ast_category_browse(cfg, ctg)) != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_config_destroy(cfg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (find_desc(usbradio_active) == NULL) { | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		ast_log(LOG_NOTICE, "radio active device %s not found\n", usbradio_active); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		/* XXX we could default to 'dsp' perhaps ? */ | 
					
						
							|  |  |  | 		/* XXX should cleanup allocated memory etc. */ | 
					
						
							| 
									
										
										
										
											2010-06-03 17:31:41 +00:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_channel_register(&usbradio_tech)) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unable to register channel type 'usb'\n"); | 
					
						
							| 
									
										
										
										
											2010-06-03 17:31:41 +00:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-05 10:31:25 +00:00
										 |  |  | 	ast_cli_register_multiple(cli_usbradio, ARRAY_LEN(cli_usbradio)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int unload_module(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct chan_usbradio_pvt *o; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_log(LOG_WARNING, "unload_module() called\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_channel_unregister(&usbradio_tech); | 
					
						
							| 
									
										
										
										
											2008-12-05 10:31:25 +00:00
										 |  |  | 	ast_cli_unregister_multiple(cli_usbradio, ARRAY_LEN(cli_usbradio)); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (o = usbradio_default.next; o; o = o->next) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "destroyPmrChannel() called\n"); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | 		if(o->pmrChan)destroyPmrChannel(o->pmrChan); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		#if DEBUG_CAPTURES == 1
 | 
					
						
							|  |  |  | 		if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; } | 
					
						
							|  |  |  | 		if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; } | 
					
						
							|  |  |  | 		if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; } | 
					
						
							|  |  |  | 		if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; } | 
					
						
							|  |  |  | 		if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; } | 
					
						
							|  |  |  | 		if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; } | 
					
						
							|  |  |  | 		#endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		close(o->sounddev); | 
					
						
							| 
									
										
										
										
											2008-05-16 00:51:14 +00:00
										 |  |  | #ifndef	NEW_ASTERISK
 | 
					
						
							|  |  |  | 		if (o->sndcmd[0] > 0) { | 
					
						
							|  |  |  | 			close(o->sndcmd[0]); | 
					
						
							|  |  |  | 			close(o->sndcmd[1]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		if (o->dsp) ast_dsp_free(o->dsp); | 
					
						
							| 
									
										
										
										
											2007-09-14 15:58:31 +00:00
										 |  |  | 		if (o->owner) | 
					
						
							|  |  |  | 			ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); | 
					
						
							|  |  |  | 		if (o->owner)			/* XXX how ??? */ | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		/* XXX what about the thread ? */ | 
					
						
							|  |  |  | 		/* XXX what about the memory allocated ? */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "usb Console Channel Driver"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*	end of file */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |