3 * Asterisk -- An open source telephony toolkit.
5 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Copyright (C) 2007 - 2008, Jim Dixon
8 * Jim Dixon, WB6NIL <jim@lambdatel.com>
9 * Steve Henke, W9SH <w9sh@arrl.net>
10 * Based upon work by Mark Spencer <markster@digium.com> and Luigi Rizzo
12 * See http://www.asterisk.org for more information about
13 * the Asterisk project. Please do not directly contact
14 * any of the maintainers of this project for assistance;
15 * the project provides a web site, mailing lists and IRC
16 * channels for your use.
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
25 * \brief Channel driver for CM108 USB Cards with Radio Interface
27 * \author Jim Dixon <jim@lambdatel.com>
28 * \author Steve Henke <w9sh@arrl.net>
31 * \arg \ref Config_usbradio
33 * \ingroup channel_drivers
37 <depend>ossaudio</depend>
39 <defaultenabled>no</defaultenabled>
40 <member name="RADIO_RTX" displayname="Build RTX/DTX Radio Programming">
41 <defaultenabled>no</defaultenabled>
43 <member name="RADIO_XPMRX" displayname="Build Experimental Radio Protocols">
44 <defaultenabled>no</defaultenabled>
48 // 20070918 1600 EDT sph@xelatec.com changing to rx driven streams
52 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
60 #include <sys/ioctl.h>
66 #include <alsa/asoundlib.h>
68 //#define HAVE_XPMRX 1
73 #define CHAN_USBRADIO 1
74 #define DEBUG_USBRADIO 0
75 #define DEBUG_CAPTURES 1
76 #define DEBUG_CAP_RX_OUT 0
77 #define DEBUG_CAP_TX_OUT 0
78 #define DEBUG_FILETEST 0
80 #define RX_CAP_RAW_FILE "/tmp/rx_cap_in.pcm"
81 #define RX_CAP_TRACE_FILE "/tmp/rx_trace.pcm"
82 #define RX_CAP_OUT_FILE "/tmp/rx_cap_out.pcm"
84 #define TX_CAP_RAW_FILE "/tmp/tx_cap_in.pcm"
85 #define TX_CAP_TRACE_FILE "/tmp/tx_trace.pcm"
86 #define TX_CAP_OUT_FILE "/tmp/tx_cap_out.pcm"
88 #define MIXER_PARAM_MIC_PLAYBACK_SW "Mic Playback Switch"
89 #define MIXER_PARAM_MIC_PLAYBACK_VOL "Mic Playback Volume"
90 #define MIXER_PARAM_MIC_CAPTURE_SW "Mic Capture Switch"
91 #define MIXER_PARAM_MIC_CAPTURE_VOL "Mic Capture Volume"
92 #define MIXER_PARAM_MIC_BOOST "Auto Gain Control"
93 #define MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
94 #define MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
99 #define READERR_THRESHOLD 50
101 #include "./xpmr/xpmr.h"
103 #include "./xpmrx/xpmrx.h"
104 #include "./xpmrx/bitweight.h"
108 #define traceusb1(a) {printf a;}
114 #define traceusb2(a) {printf a;}
120 #include <linux/soundcard.h>
121 #elif defined(__FreeBSD__)
122 #include <sys/soundcard.h>
124 #include <soundcard.h>
127 #include "asterisk/lock.h"
128 #include "asterisk/frame.h"
129 #include "asterisk/logger.h"
130 #include "asterisk/callerid.h"
131 #include "asterisk/channel.h"
132 #include "asterisk/module.h"
133 #include "asterisk/options.h"
134 #include "asterisk/pbx.h"
135 #include "asterisk/config.h"
136 #include "asterisk/cli.h"
137 #include "asterisk/utils.h"
138 #include "asterisk/causes.h"
139 #include "asterisk/endian.h"
140 #include "asterisk/stringfields.h"
141 #include "asterisk/abstract_jb.h"
142 #include "asterisk/musiconhold.h"
143 #include "asterisk/dsp.h"
147 /* ringtones we use */
149 #include "ringtone.h"
155 #define C108_VENDOR_ID 0x0d8c
156 #define C108_PRODUCT_ID 0x000c
157 #define C108_HID_INTERFACE 3
159 #define HID_REPORT_GET 0x01
160 #define HID_REPORT_SET 0x09
162 #define HID_RT_INPUT 0x01
163 #define HID_RT_OUTPUT 0x02
165 #define EEPROM_START_ADDR 6
166 #define EEPROM_END_ADDR 63
167 #define EEPROM_PHYSICAL_LEN 64
168 #define EEPROM_TEST_ADDR EEPROM_END_ADDR
169 #define EEPROM_MAGIC_ADDR 6
170 #define EEPROM_MAGIC 34329
171 #define EEPROM_CS_ADDR 62
172 #define EEPROM_RXMIXERSET 8
173 #define EEPROM_TXMIXASET 9
174 #define EEPROM_TXMIXBSET 10
175 #define EEPROM_RXVOICEADJ 11
176 #define EEPROM_RXCTCSSADJ 13
177 #define EEPROM_TXCTCSSADJ 15
178 #define EEPROM_RXSQUELCHADJ 16
180 /*! Global jitterbuffer configuration - by default, jb is disabled */
181 static struct ast_jb_conf default_jbconf =
185 .resync_threshold = -1,
188 static struct ast_jb_conf global_jbconf;
191 * usbradio.conf parameters are
195 ; General config options which propigate to all devices, with
196 ; default values shown. You may have as many devices as the
197 ; system will allow. You must use one section per device, with
198 ; [usb] generally (although its up to you) being the first device.
201 ; debug = 0x0 ; misc debug flags, default is 0
203 ; Set the device to use for I/O
205 ; Set hardware type here
206 ; hdwtype=0 ; 0=limey, 1=sph
208 ; rxboost=0 ; no rx gain boost
209 ; rxctcssrelax=1 ; reduce talkoff from radios w/o CTCSS Tx HPF
210 ; rxctcssfreqs=100.0,123.0 ; list of rx ctcss freq in floating point. must be in table
211 ; txctcssfreqs=100.0,123.0 ; list tx ctcss freq, any frequency permitted
212 ; txctcssdefault=100.0 ; default tx ctcss freq, any frequency permitted
214 ; carrierfrom=dsp ;no,usb,usbinvert,dsp,vox
215 ; ctcssfrom=dsp ;no,usb,dsp
217 ; rxdemod=flat ; input type from radio: no,speaker,flat
218 ; txprelim=yes ; output is pre-emphasised and limited
219 ; txtoctype=no ; no,phase,notone
221 ; txmixa=composite ;no,voice,tone,composite,auxvoice
222 ; txmixb=no ;no,voice,tone,composite,auxvoice
226 ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
227 ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an
228 ; USBRADIO channel. Defaults to "no". An enabled jitterbuffer will
229 ; be used only if the sending side can create and the receiving
230 ; side can not accept jitter. The USBRADIO channel can't accept jitter,
231 ; thus an enabled jitterbuffer on the receive USBRADIO side will always
232 ; be used if the sending side can create jitter.
234 ; jbmaxsize = 200 ; Max length of the jitterbuffer in milliseconds.
236 ; jbresyncthreshold = 1000 ; Jump in the frame timestamps over which the jitterbuffer is
237 ; resynchronized. Useful to improve the quality of the voice, with
238 ; big jumps in/broken timestamps, usualy sent from exotic devices
239 ; and programs. Defaults to 1000.
241 ; jbimpl = fixed ; Jitterbuffer implementation, used on the receiving side of an USBRADIO
242 ; channel. Two implementations are currenlty available - "fixed"
243 ; (with size always equals to jbmax-size) and "adaptive" (with
244 ; variable size, actually the new jb of IAX2). Defaults to fixed.
246 ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
247 ;-----------------------------------------------------------------------------------
251 ; First channel unique config
255 ; Second channel config
262 * Helper macros to parse config arguments. They will go in a common
263 * header file if their usage is globally accepted. In the meantime,
264 * we define them here. Typical usage is as below.
265 * Remember to open a block right before M_START (as it declares
266 * some variables) and use the M_* macros WITHOUT A SEMICOLON:
269 * M_START(v->name, v->value)
271 * M_BOOL("dothis", x->flag1)
272 * M_STR("name", x->somestring)
273 * M_F("bar", some_c_code)
274 * M_END(some_final_statement)
275 * ... other code in the block
278 * XXX NOTE these macros should NOT be replicated in other parts of asterisk.
279 * Likely we will come up with a better way of doing config file parsing.
281 #define M_START(var, val) \
282 char *__s = var; char *__val = val;
284 #define M_F(tag, f) if (!strcasecmp((__s), tag)) { f; } else
285 #define M_BOOL(tag, dst) M_F(tag, (dst) = ast_true(__val) )
286 #define M_UINT(tag, dst) M_F(tag, (dst) = strtoul(__val, NULL, 0) )
287 #define M_STR(tag, dst) M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
290 * The following parameters are used in the driver:
292 * FRAME_SIZE the size of an audio frame, in samples.
293 * 160 is used almost universally, so you should not change it.
295 * FRAGS the argument for the SETFRAGMENT ioctl.
296 * Overridden by the 'frags' parameter in usbradio.conf
298 * Bits 0-7 are the base-2 log of the device's block size,
299 * bits 16-31 are the number of blocks in the driver's queue.
300 * There are a lot of differences in the way this parameter
301 * is supported by different drivers, so you may need to
302 * experiment a bit with the value.
303 * A good default for linux is 30 blocks of 64 bytes, which
304 * results in 6 frames of 320 bytes (160 samples).
305 * FreeBSD works decently with blocks of 256 or 512 bytes,
306 * leaving the number unspecified.
307 * Note that this only refers to the device buffer size,
308 * this module will then try to keep the lenght of audio
309 * buffered within small constraints.
311 * QUEUE_SIZE The max number of blocks actually allowed in the device
312 * driver's buffer, irrespective of the available number.
313 * Overridden by the 'queuesize' parameter in usbradio.conf
315 * Should be >=2, and at most as large as the hw queue above
316 * (otherwise it will never be full).
319 #define FRAME_SIZE 160
322 #if defined(__FreeBSD__)
325 #define FRAGS ( ( (6 * 5) << 16 ) | 0xc )
329 * XXX text message sizes are probably 256 chars, but i am
330 * not sure if there is a suitable definition anywhere.
332 #define TEXT_SIZE 256
335 #define TRYOPEN 1 /* try to open on startup */
337 #define O_CLOSE 0x444 /* special 'close' mode for device */
338 /* Which device to use */
339 #if defined( __OpenBSD__ ) || defined( __NetBSD__ )
340 #define DEV_DSP "/dev/audio"
342 #define DEV_DSP "/dev/dsp"
346 #define MIN(a,b) ((a) < (b) ? (a) : (b))
349 #define MAX(a,b) ((a) > (b) ? (a) : (b))
352 static char *config = "usbradio.conf"; /* default config file */
353 static char *config1 = "usbradio_tune_%s.conf"; /* tune config file */
355 static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
356 static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
358 static char *usb_device_list = NULL;
359 static int usb_device_list_size = 0;
361 static int usbradio_debug;
363 static int usbradio_debug_level = 0;
366 enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
367 enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
368 enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR}; // no,external,externalinvert,software
369 enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
370 enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
371 enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
373 /* DECLARE STRUCTURES */
376 * Each sound is made of 'datalen' samples of sound, repeated as needed to
377 * generate 'samplen' samples of data, then followed by 'silencelen' samples
378 * of silence. The loop is repeated if 'repeat' is set.
392 static struct sound sounds[] = {
393 { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
394 { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
395 { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
396 { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
397 { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
398 { -1, NULL, 0, 0, 0, 0 }, /* end marker */
404 * descriptor for one of our channels.
405 * There is one used for 'default' values (from the [general] entry in
406 * the configuration file), and then one instance for each device
407 * (the default is cloned from [general], others are only created
408 * if the relevant section exists).
410 struct chan_usbradio_pvt {
411 struct chan_usbradio_pvt *next;
416 * cursound indicates which in struct sound we play. -1 means nothing,
417 * any other value is a valid sound, in which case sampsent indicates
418 * the next sample to send in [0..samplen + silencelen]
419 * nosound is set to disable the audio data from the channel
420 * (so we can play the tones etc.).
422 int sndcmd[2]; /* Sound command pipe */
423 int cursound; /* index of sound to send */
424 int sampsent; /* # of sound samples sent */
425 int nosound; /* set to block audio from the PBX */
429 int total_blocks; /* total blocks in the output device */
431 enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
436 unsigned int queuesize; /* max fragments in queue */
437 unsigned int frags; /* parameter for SETFRAGMENT */
439 int warned; /* various flags used for warnings */
440 #define WARN_used_blocks 1
443 int w_errors; /* overfull in the write path */
444 struct timeval lastopen;
449 /* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
450 * be representable in 16 bits to avoid overflows.
452 #define BOOST_SCALE (1<<9)
453 #define BOOST_MAX 40 /* slightly less than 7 bits */
454 int boost; /* input boost, scaled by BOOST_SCALE */
468 struct ast_channel *owner;
469 char ext[AST_MAX_EXTENSION];
470 char ctx[AST_MAX_CONTEXT];
471 char language[MAX_LANGUAGE];
472 char cid_name[256]; /*XXX */
473 char cid_num[256]; /*XXX */
474 char mohinterpret[MAX_MUSICCLASS];
476 /* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */
477 char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];
478 char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6];
480 int usbradio_write_dst;
481 /* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
482 * plus enough room for a full frame
484 char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
485 char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
486 int readpos; /* read position above */
487 struct ast_frame read_f; /* returned by usbradio_read */
504 char rxcarrierdetect; // status from pmr channel
505 char rxctcssdecode; // status from pmr channel
511 char rxkeyed; // indicates rx signal present
514 char txkeyed; // tx key request from upper layers
530 int rxsquelchadj; /* this copy needs to be here for initialization */
544 char txctcssdefault[16]; // for repeater operation
545 char rxctcssfreqs[512]; // a string
546 char txctcssfreqs[512];
548 char txctcssfreq[32]; // encode now
549 char rxctcssfreq[32]; // decode now
551 char numrxctcssfreqs; // how many
552 char numtxctcssfreqs;
554 char *rxctcss[CTCSS_NUM_CODES]; // pointers to strings
555 char *txctcss[CTCSS_NUM_CODES];
560 // start remote operation info
561 char set_txctcssdefault[16]; // for remote operation
562 char set_txctcssfreq[16]; // encode now
563 char set_rxctcssfreq[16]; // decode now
565 char set_numrxctcssfreqs; // how many
566 char set_numtxctcssfreqs;
568 char set_rxctcssfreqs[16]; // a string
569 char set_txctcssfreqs[16];
571 char *set_rxctcss; // pointers to strings
574 int set_txfreq; // in Hz
576 // end remote operation info
588 int hid_gpio_ctl_loc;
592 int hid_io_ctcss_loc;
603 unsigned txpolarity:1;
604 unsigned rxpolarity:1;
605 unsigned dcstxpolarity:1;
606 unsigned dcsrxpolarity:1;
607 unsigned lsdtxpolarity:1;
608 unsigned lsdrxpolarity:1;
610 unsigned radioactive:1;
612 unsigned short eeprom[EEPROM_PHYSICAL_LEN];
614 ast_mutex_t eepromlock;
616 struct usb_dev_handle *usb_handle;
620 // maw add additional defaults !!!
621 static struct chan_usbradio_pvt usbradio_default = {
626 .duplex = M_UNSET, /* XXX check this */
629 .queuesize = QUEUE_SIZE,
633 .readpos = AST_FRIENDLY_OFFSET, /* start here on reads */
634 .lastopen = { 0, 0 },
635 .boost = BOOST_SCALE,
641 /* DECLARE FUNCTION PROTOTYPES */
643 static void store_txtoctype(struct chan_usbradio_pvt *o, char *s);
644 static int hidhdwconfig(struct chan_usbradio_pvt *o);
645 static int set_txctcss_level(struct chan_usbradio_pvt *o);
646 static void pmrdump(struct chan_usbradio_pvt *o);
647 static void mult_set(struct chan_usbradio_pvt *o);
648 static int mult_calc(int value);
649 static void mixer_write(struct chan_usbradio_pvt *o);
650 static void tune_rxinput(int fd, struct chan_usbradio_pvt *o);
651 static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o);
652 static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o);
653 static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd);
654 static void tune_write(struct chan_usbradio_pvt *o);
656 static char *usbradio_active; /* the active device */
658 static int setformat(struct chan_usbradio_pvt *o, int mode);
660 static struct ast_channel *usbradio_request(const char *type, int format, void *data
662 static int usbradio_digit_begin(struct ast_channel *c, char digit);
663 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration);
664 static int usbradio_text(struct ast_channel *c, const char *text);
665 static int usbradio_hangup(struct ast_channel *c);
666 static int usbradio_answer(struct ast_channel *c);
667 static struct ast_frame *usbradio_read(struct ast_channel *chan);
668 static int usbradio_call(struct ast_channel *c, char *dest, int timeout);
669 static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
670 static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
671 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
672 static int xpmr_config(struct chan_usbradio_pvt *o);
674 #if DEBUG_FILETEST == 1
675 static int RxTestIt(struct chan_usbradio_pvt *o);
678 static char tdesc[] = "USB (CM108) Radio Channel Driver";
680 static const struct ast_channel_tech usbradio_tech = {
682 .description = tdesc,
683 .capabilities = AST_FORMAT_SLINEAR,
684 .requester = usbradio_request,
685 .send_digit_begin = usbradio_digit_begin,
686 .send_digit_end = usbradio_digit_end,
687 .send_text = usbradio_text,
688 .hangup = usbradio_hangup,
689 .answer = usbradio_answer,
690 .read = usbradio_read,
691 .call = usbradio_call,
692 .write = usbradio_write,
693 .indicate = usbradio_indicate,
694 .fixup = usbradio_fixup,
697 /* Call with: devnum: alsa major device number, param: ascii Formal
698 Parameter Name, val1, first or only value, val2 second value, or 0
699 if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
701 Note: must add -lasound to end of linkage */
703 static int amixer_max(int devnum,char *param)
708 snd_ctl_elem_id_t *id;
709 snd_hctl_elem_t *elem;
710 snd_ctl_elem_info_t *info;
712 sprintf(str,"hw:%d",devnum);
713 if (snd_hctl_open(&hctl, str, 0)) return(-1);
715 snd_ctl_elem_id_alloca(&id);
716 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
717 snd_ctl_elem_id_set_name(id, param);
718 elem = snd_hctl_find_elem(hctl, id);
721 snd_hctl_close(hctl);
724 snd_ctl_elem_info_alloca(&info);
725 snd_hctl_elem_info(elem,info);
726 type = snd_ctl_elem_info_get_type(info);
730 case SND_CTL_ELEM_TYPE_INTEGER:
731 rv = snd_ctl_elem_info_get_max(info);
733 case SND_CTL_ELEM_TYPE_BOOLEAN:
737 snd_hctl_close(hctl);
741 /* Call with: devnum: alsa major device number, param: ascii Formal
742 Parameter Name, val1, first or only value, val2 second value, or 0
743 if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
745 Note: must add -lasound to end of linkage */
747 static int setamixer(int devnum,char *param, int v1, int v2)
752 snd_ctl_elem_id_t *id;
753 snd_ctl_elem_value_t *control;
754 snd_hctl_elem_t *elem;
755 snd_ctl_elem_info_t *info;
757 sprintf(str,"hw:%d",devnum);
758 if (snd_hctl_open(&hctl, str, 0)) return(-1);
760 snd_ctl_elem_id_alloca(&id);
761 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
762 snd_ctl_elem_id_set_name(id, param);
763 elem = snd_hctl_find_elem(hctl, id);
766 snd_hctl_close(hctl);
769 snd_ctl_elem_info_alloca(&info);
770 snd_hctl_elem_info(elem,info);
771 type = snd_ctl_elem_info_get_type(info);
772 snd_ctl_elem_value_alloca(&control);
773 snd_ctl_elem_value_set_id(control, id);
776 case SND_CTL_ELEM_TYPE_INTEGER:
777 snd_ctl_elem_value_set_integer(control, 0, v1);
778 if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2);
780 case SND_CTL_ELEM_TYPE_BOOLEAN:
781 snd_ctl_elem_value_set_integer(control, 0, (v1 != 0));
784 if (snd_hctl_elem_write(elem, control))
786 snd_hctl_close(hctl);
789 snd_hctl_close(hctl);
793 static void hid_set_outputs(struct usb_dev_handle *handle,
794 unsigned char *outputs)
797 usb_control_msg(handle,
798 USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
800 0 + (HID_RT_OUTPUT << 8),
802 (char*)outputs, 4, 5000);
805 static void hid_get_inputs(struct usb_dev_handle *handle,
806 unsigned char *inputs)
809 usb_control_msg(handle,
810 USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
812 0 + (HID_RT_INPUT << 8),
814 (char*)inputs, 4, 5000);
817 static unsigned short read_eeprom(struct usb_dev_handle *handle, int addr)
819 unsigned char buf[4];
824 buf[3] = 0x80 | (addr & 0x3f);
825 hid_set_outputs(handle,buf);
826 memset(buf,0,sizeof(buf));
827 hid_get_inputs(handle,buf);
828 return(buf[1] + (buf[2] << 8));
831 static void write_eeprom(struct usb_dev_handle *handle, int addr,
835 unsigned char buf[4];
838 buf[1] = data & 0xff;
840 buf[3] = 0xc0 | (addr & 0x3f);
841 hid_set_outputs(handle,buf);
844 static unsigned short get_eeprom(struct usb_dev_handle *handle,
851 for(i = EEPROM_START_ADDR; i < EEPROM_END_ADDR; i++)
853 cs += buf[i] = read_eeprom(handle,i);
858 static void put_eeprom(struct usb_dev_handle *handle,unsigned short *buf)
864 buf[EEPROM_MAGIC_ADDR] = EEPROM_MAGIC;
865 for(i = EEPROM_START_ADDR; i < EEPROM_CS_ADDR; i++)
867 write_eeprom(handle,i,buf[i]);
870 buf[EEPROM_CS_ADDR] = (65535 - cs) + 1;
871 write_eeprom(handle,i,buf[EEPROM_CS_ADDR]);
874 static struct usb_device *hid_device_init(char *desired_device)
876 struct usb_bus *usb_bus;
877 struct usb_device *dev;
878 char devstr[200],str[200],desdev[200],*cp;
885 for (usb_bus = usb_busses;
887 usb_bus = usb_bus->next) {
888 for (dev = usb_bus->devices;
891 if ((dev->descriptor.idVendor
892 == C108_VENDOR_ID) &&
893 (dev->descriptor.idProduct
896 sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
897 for(i = 0; i < 32; i++)
899 sprintf(str,"/proc/asound/card%d/usbbus",i);
902 if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
908 if (desdev[strlen(desdev) - 1] == '\n')
909 desdev[strlen(desdev) -1 ] = 0;
910 if (strcasecmp(desdev,devstr)) continue;
911 if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
912 else strcpy(str,"/sys/class/sound/dsp/device");
913 memset(desdev,0,sizeof(desdev));
914 if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
916 sprintf(str,"/sys/class/sound/controlC%d/device",i);
917 memset(desdev,0,sizeof(desdev));
918 if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
920 cp = strrchr(desdev,'/');
921 if (cp) *cp = 0; else continue;
922 cp = strrchr(desdev,'/');
927 if (i >= 32) continue;
928 if (!strcmp(cp,desired_device)) return dev;
936 static int hid_device_mklist(void)
938 struct usb_bus *usb_bus;
939 struct usb_device *dev;
940 char devstr[200],str[200],desdev[200],*cp;
944 usb_device_list = ast_malloc(2);
945 if (!usb_device_list) return -1;
946 memset(usb_device_list,0,2);
951 for (usb_bus = usb_busses;
953 usb_bus = usb_bus->next) {
954 for (dev = usb_bus->devices;
957 if ((dev->descriptor.idVendor
958 == C108_VENDOR_ID) &&
959 (dev->descriptor.idProduct
962 sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
963 for(i = 0;i < 32; i++)
965 sprintf(str,"/proc/asound/card%d/usbbus",i);
968 if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
974 if (desdev[strlen(desdev) - 1] == '\n')
975 desdev[strlen(desdev) -1 ] = 0;
976 if (strcasecmp(desdev,devstr)) continue;
977 if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
978 else strcpy(str,"/sys/class/sound/dsp/device");
979 memset(desdev,0,sizeof(desdev));
980 if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
982 sprintf(str,"/sys/class/sound/controlC%d/device",i);
983 memset(desdev,0,sizeof(desdev));
984 if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
986 cp = strrchr(desdev,'/');
987 if (cp) *cp = 0; else continue;
988 cp = strrchr(desdev,'/');
993 if (i >= 32) return -1;
994 usb_device_list = ast_realloc(usb_device_list,
995 usb_device_list_size + 2 +
997 if (!usb_device_list) return -1;
998 usb_device_list_size += strlen(cp) + 2;
1000 while(usb_device_list[i])
1002 i += strlen(usb_device_list + i) + 1;
1004 strcat(usb_device_list + i,cp);
1005 usb_device_list[strlen(cp) + i + 1] = 0;
1013 /* returns internal formatted string from external one */
1014 static int usb_get_usbdev(char *devstr)
1017 char str[200],desdev[200],*cp;
1019 for(i = 0;i < 32; i++)
1021 if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
1022 else strcpy(str,"/sys/class/sound/dsp/device");
1023 memset(desdev,0,sizeof(desdev));
1024 if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
1026 sprintf(str,"/sys/class/sound/controlC%d/device",i);
1027 memset(desdev,0,sizeof(desdev));
1028 if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
1030 cp = strrchr(desdev,'/');
1031 if (cp) *cp = 0; else continue;
1032 cp = strrchr(desdev,'/');
1035 if (!strcasecmp(cp,devstr)) break;
1037 if (i >= 32) return -1;
1042 static int usb_list_check(char *devstr)
1045 char *s = usb_device_list;
1050 if (!strcasecmp(s,devstr)) return(1);
1057 static int hidhdwconfig(struct chan_usbradio_pvt *o)
1059 if(o->hdwtype==1) //sphusb
1061 o->hid_gpio_ctl = 0x08; /* set GPIO4 to output mode */
1062 o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
1063 o->hid_io_cor = 4; /* GPIO3 is COR */
1064 o->hid_io_cor_loc = 1; /* GPIO3 is COR */
1065 o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
1066 o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
1067 o->hid_io_ptt = 8; /* GPIO 4 is PTT */
1068 o->hid_gpio_loc = 1; /* For ALL GPIO */
1070 else if(o->hdwtype==0) //dudeusb
1072 o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
1073 o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
1074 o->hid_io_cor = 2; /* VOLD DN is COR */
1075 o->hid_io_cor_loc = 0; /* VOL DN COR */
1076 o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
1077 o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
1078 o->hid_io_ptt = 4; /* GPIO 3 is PTT */
1079 o->hid_gpio_loc = 1; /* For ALL GPIO */
1081 else if(o->hdwtype==3) // custom version
1083 o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
1084 o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
1085 o->hid_io_cor = 2; /* VOLD DN is COR */
1086 o->hid_io_cor_loc = 0; /* VOL DN COR */
1087 o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
1088 o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
1089 o->hid_io_ptt = 4; /* GPIO 3 is PTT */
1090 o->hid_gpio_loc = 1; /* For ALL GPIO */
1097 static void kickptt(struct chan_usbradio_pvt *o)
1100 //printf("kickptt %i %i %i\n",o->txkeyed,o->txchankey,o->txtestkey);
1102 if (!o->pttkick) return;
1103 write(o->pttkick[1],&c,1);
1107 static void *hidthread(void *arg)
1109 unsigned char buf[4],bufsave[4],keyed;
1112 struct usb_device *usb_dev;
1113 struct usb_dev_handle *usb_handle;
1114 struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
1118 usb_dev = hid_device_init(o->devstr);
1119 if (usb_dev == NULL) {
1120 ast_log(LOG_ERROR,"USB HID device not found\n");
1123 usb_handle = usb_open(usb_dev);
1124 if (usb_handle == NULL) {
1125 ast_log(LOG_ERROR,"Not able to open USB device\n");
1128 if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0)
1130 if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
1131 ast_log(LOG_ERROR,"Not able to detach the USB device\n");
1134 if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0) {
1135 ast_log(LOG_ERROR,"Not able to claim the USB device\n");
1139 memset(buf,0,sizeof(buf));
1140 buf[2] = o->hid_gpio_ctl;
1142 hid_set_outputs(usb_handle,buf);
1143 memcpy(bufsave,buf,sizeof(buf));
1144 if (pipe(o->pttkick) == -1)
1146 ast_log(LOG_ERROR,"Not able to create pipe\n");
1149 traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
1155 to.tv_usec = 50000; // maw sph
1158 FD_SET(o->pttkick[0],&rfds);
1159 /* ast_select emulates linux behaviour in terms of timeout handling */
1160 res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to);
1162 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
1166 if (FD_ISSET(o->pttkick[0],&rfds))
1170 read(o->pttkick[0],&c,1);
1174 ast_mutex_lock(&o->eepromlock);
1175 if (o->eepromctl == 1) /* to read */
1178 if (!get_eeprom(usb_handle,o->eeprom))
1180 if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC)
1182 ast_log(LOG_NOTICE,"UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n",o->name);
1186 o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
1187 o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
1188 o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
1189 memcpy(&o->rxvoiceadj,&o->eeprom[EEPROM_RXVOICEADJ],sizeof(float));
1190 memcpy(&o->rxctcssadj,&o->eeprom[EEPROM_RXCTCSSADJ],sizeof(float));
1191 o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
1192 o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
1193 ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
1198 ast_log(LOG_NOTICE,"USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n",o->name);
1200 hid_set_outputs(usb_handle,bufsave);
1202 if (o->eepromctl == 2) /* to write */
1204 put_eeprom(usb_handle,o->eeprom);
1205 hid_set_outputs(usb_handle,bufsave);
1206 ast_log(LOG_NOTICE,"USB Parameters written to EEPROM on %s\n",o->name);
1209 ast_mutex_unlock(&o->eepromlock);
1211 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
1212 hid_get_inputs(usb_handle,buf);
1213 keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
1214 if (keyed != o->rxhidsq)
1216 if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed);
1220 /* if change in tx state as controlled by xpmr */
1221 txtmp=o->pmrChan->txPttOut;
1223 if (o->lasttx != txtmp)
1225 o->pmrChan->txPttHid=o->lasttx = txtmp;
1226 if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp);
1227 buf[o->hid_gpio_loc] = 0;
1230 if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
1234 if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
1236 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
1237 memcpy(bufsave,buf,sizeof(buf));
1238 hid_set_outputs(usb_handle,buf);
1240 time(&o->lasthidtime);
1242 buf[o->hid_gpio_loc] = 0;
1243 if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt;
1244 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
1245 hid_set_outputs(usb_handle,buf);
1250 * returns a pointer to the descriptor with the given name
1252 static struct chan_usbradio_pvt *find_desc(char *dev)
1254 struct chan_usbradio_pvt *o = NULL;
1257 ast_log(LOG_WARNING, "null dev\n");
1259 for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
1262 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
1269 static struct chan_usbradio_pvt *find_desc_usb(char *devstr)
1271 struct chan_usbradio_pvt *o = NULL;
1274 ast_log(LOG_WARNING, "null dev\n");
1276 for (o = usbradio_default.next; o && devstr && strcmp(o->devstr, devstr) != 0; o = o->next);
1282 * split a string in extension-context, returns pointers to malloc'ed
1284 * If we do not have 'overridecontext' then the last @ is considered as
1285 * a context separator, and the context is overridden.
1286 * This is usually not very necessary as you can play with the dialplan,
1287 * and it is nice not to need it because you have '@' in SIP addresses.
1288 * Return value is the buffer address.
1291 static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
1293 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
1295 if (ext == NULL || ctx == NULL)
1296 return NULL; /* error */
1300 if (src && *src != '\0')
1301 *ext = ast_strdup(src);
1306 if (!o->overridecontext) {
1307 /* parse from the right */
1308 *ctx = strrchr(*ext, '@');
1318 * Returns the number of blocks used in the audio output channel
1320 static int used_blocks(struct chan_usbradio_pvt *o)
1322 struct audio_buf_info info;
1324 if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
1325 if (!(o->warned & WARN_used_blocks)) {
1326 ast_log(LOG_WARNING, "Error reading output space\n");
1327 o->warned |= WARN_used_blocks;
1332 if (o->total_blocks == 0) {
1333 if (0) /* debugging */
1334 ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
1335 o->total_blocks = info.fragments;
1338 return o->total_blocks - info.fragments;
1341 /* Write an exactly FRAME_SIZE sized frame */
1342 static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
1346 if (o->sounddev < 0)
1347 setformat(o, O_RDWR);
1348 if (o->sounddev < 0)
1349 return 0; /* not fatal */
1350 // maw maw sph !!! may or may not be a good thing
1351 // drop the frame if not transmitting, this keeps from gradually
1352 // filling the buffer when asterisk clock > usb sound clock
1353 if(!o->pmrChan->txPttIn && !o->pmrChan->txPttOut)
1358 * Nothing complex to manage the audio device queue.
1359 * If the buffer is full just drop the extra, otherwise write.
1360 * XXX in some cases it might be useful to write anyways after
1361 * a number of failures, to restart the output chain.
1363 res = used_blocks(o);
1364 if (res > o->queuesize) { /* no room to write a block */
1365 // ast_log(LOG_WARNING, "sound device write buffer overflow\n");
1366 if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
1367 ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
1372 return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12);
1375 #ifndef NEW_ASTERISK
1378 * Handler for 'sound writable' events from the sound thread.
1379 * Builds a frame from the high level description of the sounds,
1380 * and passes it to the audio device.
1381 * The actual sound is made of 1 or more sequences of sound samples
1382 * (s->datalen, repeated to make s->samplen samples) followed by
1383 * s->silencelen samples of silence. The position in the sequence is stored
1384 * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen.
1385 * In case we fail to write a frame, don't update o->sampsent.
1387 static void send_sound(struct chan_usbradio_pvt *o)
1389 short myframe[FRAME_SIZE];
1391 int l_sampsent = o->sampsent;
1394 if (o->cursound < 0) /* no sound to send */
1397 s = &sounds[o->cursound];
1399 for (ofs = 0; ofs < FRAME_SIZE; ofs += l) {
1400 l = s->samplen - l_sampsent; /* # of available samples */
1402 start = l_sampsent % s->datalen; /* source offset */
1403 if (l > FRAME_SIZE - ofs) /* don't overflow the frame */
1404 l = FRAME_SIZE - ofs;
1405 if (l > s->datalen - start) /* don't overflow the source */
1406 l = s->datalen - start;
1407 bcopy(s->data + start, myframe + ofs, l * 2);
1409 ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
1411 } else { /* end of samples, maybe some silence */
1412 static const short silence[FRAME_SIZE] = { 0, };
1416 if (l > FRAME_SIZE - ofs)
1417 l = FRAME_SIZE - ofs;
1418 bcopy(silence, myframe + ofs, l * 2);
1420 } else { /* silence is over, restart sound if loop */
1421 if (s->repeat == 0) { /* last block */
1423 o->nosound = 0; /* allow audio data */
1424 if (ofs < FRAME_SIZE) /* pad with silence */
1425 bcopy(silence, myframe + ofs, (FRAME_SIZE - ofs) * 2);
1431 l = soundcard_writeframe(o, myframe);
1433 o->sampsent = l_sampsent; /* update status */
1436 static void *sound_thread(void *arg)
1439 struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
1442 * Just in case, kick the driver by trying to read from it.
1443 * Ignore errors - this read is almost guaranteed to fail.
1445 read(o->sounddev, ign, sizeof(ign));
1452 FD_SET(o->sndcmd[0], &rfds);
1453 maxfd = o->sndcmd[0]; /* pipe from the main process */
1454 if (o->cursound > -1 && o->sounddev < 0)
1455 setformat(o, O_RDWR); /* need the channel, try to reopen */
1456 else if (o->cursound == -1 && o->owner == NULL)
1458 setformat(o, O_CLOSE); /* can close */
1460 if (o->sounddev > -1) {
1461 if (!o->owner) { /* no one owns the audio, so we must drain it */
1462 FD_SET(o->sounddev, &rfds);
1463 maxfd = MAX(o->sounddev, maxfd);
1465 if (o->cursound > -1) {
1466 FD_SET(o->sounddev, &wfds);
1467 maxfd = MAX(o->sounddev, maxfd);
1470 /* ast_select emulates linux behaviour in terms of timeout handling */
1471 res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
1473 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
1477 if (FD_ISSET(o->sndcmd[0], &rfds)) {
1478 /* read which sound to play from the pipe */
1481 read(o->sndcmd[0], &what, sizeof(what));
1482 for (i = 0; sounds[i].ind != -1; i++) {
1483 if (sounds[i].ind == what) {
1486 o->nosound = 1; /* block audio from pbx */
1490 if (sounds[i].ind == -1)
1491 ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
1493 if (o->sounddev > -1) {
1494 if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
1495 read(o->sounddev, ign, sizeof(ign));
1496 if (FD_ISSET(o->sounddev, &wfds))
1500 return NULL; /* Never reached */
1506 * reset and close the device if opened,
1507 * then open and initialize it in the desired mode,
1508 * trigger reads and writes so we can start using it.
1510 static int setformat(struct chan_usbradio_pvt *o, int mode)
1512 int fmt, desired, res, fd;
1515 if (o->sounddev >= 0) {
1516 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
1518 o->duplex = M_UNSET;
1521 if (mode == O_CLOSE) /* we are done */
1523 o->lastopen = ast_tvnow();
1524 strcpy(device,"/dev/dsp");
1526 sprintf(device,"/dev/dsp%d",o->devicenum);
1527 fd = o->sounddev = open(device, mode | O_NONBLOCK);
1529 ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno));
1533 o->owner->fds[0] = fd;
1535 #if __BYTE_ORDER == __LITTLE_ENDIAN
1540 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
1542 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
1547 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
1548 /* Check to see if duplex set (FreeBSD Bug) */
1549 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
1550 if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
1551 if (option_verbose > 1)
1552 ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
1557 o->duplex = M_WRITE;
1565 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
1567 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
1570 fmt = desired = 48000; /* 8000 Hz desired */
1571 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
1574 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
1577 if (fmt != desired) {
1578 if (!(o->warned & WARN_speed)) {
1579 ast_log(LOG_WARNING,
1580 "Requested %d Hz, got %d Hz -- sound may be choppy\n",
1582 o->warned |= WARN_speed;
1586 * on Freebsd, SETFRAGMENT does not work very well on some cards.
1587 * Default to use 256 bytes, let the user override
1591 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
1593 if (!(o->warned & WARN_frag)) {
1594 ast_log(LOG_WARNING,
1595 "Unable to set fragment size -- sound may be choppy\n");
1596 o->warned |= WARN_frag;
1600 /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */
1601 res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
1602 res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
1603 /* it may fail if we are in half duplex, never mind */
1608 * some of the standard methods supported by channels.
1610 static int usbradio_digit_begin(struct ast_channel *c, char digit)
1615 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration)
1617 /* no better use for received digits than print them */
1618 ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
1623 SETFREQ - sets spi programmable xcvr
1624 SETCHAN - sets binary parallel xcvr
1626 static int usbradio_text(struct ast_channel *c, const char *text)
1628 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
1630 char cnt,rxs[16],txs[16],txpl[16],rxpl[16];
1633 cmd = alloca(strlen(text) + 10);
1635 /* print received messages */
1636 if(o->debuglevel)ast_verbose(" << Console Received usbradio text %s >> \n", text);
1638 cnt=sscanf(text,"%s %s %s %s %s %c",cmd,rxs,txs,rxpl,txpl,&pwr);
1640 if (strcmp(cmd,"SETCHAN")==0)
1643 chan=strtod(rxs,NULL);
1645 if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETCHAN cmd: %s chan: %i\n",text,chan);
1651 ast_log(LOG_ERROR,"Cannot parse usbradio text: %s\n",text);
1656 if(o->debuglevel)ast_verbose(" << %s %s %s %s %s %c >> \n", cmd,rxs,txs,rxpl,txpl,pwr);
1659 if (strcmp(cmd,"SETFREQ")==0)
1661 if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETFREQ cmd: %s\n",text);
1662 tx=strtod(txs,NULL);
1663 rx=strtod(rxs,NULL);
1664 o->set_txfreq = round(tx * (double)1000000);
1665 o->set_rxfreq = round(rx * (double)1000000);
1666 o->pmrChan->txpower = (pwr == 'H');
1667 strcpy(o->set_rxctcssfreqs,rxpl);
1668 strcpy(o->set_txctcssfreqs,txpl);
1674 ast_log(LOG_ERROR,"Cannot parse usbradio cmd: %s\n",text);
1678 /* Play ringtone 'x' on device 'o' */
1679 static void ring(struct chan_usbradio_pvt *o, int x)
1681 #ifndef NEW_ASTERISK
1682 write(o->sndcmd[1], &x, sizeof(x));
1687 * handler for incoming calls. Either autoanswer, or start ringing
1689 static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
1691 struct chan_usbradio_pvt *o = c->tech_pvt;
1694 time(&o->lasthidtime);
1695 ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
1696 ast_setstate(c, AST_STATE_UP);
1701 * remote side answered the phone
1703 static int usbradio_answer(struct ast_channel *c)
1705 #ifndef NEW_ASTERISK
1706 struct chan_usbradio_pvt *o = c->tech_pvt;
1709 ast_setstate(c, AST_STATE_UP);
1710 #ifndef NEW_ASTERISK
1717 static int usbradio_hangup(struct ast_channel *c)
1719 struct chan_usbradio_pvt *o = c->tech_pvt;
1721 //ast_log(LOG_NOTICE, "usbradio_hangup()\n");
1722 #ifndef NEW_ASTERISK
1728 ast_module_unref(ast_module_info->self);
1730 if (o->autoanswer || o->autohangup) {
1731 /* Assume auto-hangup too */
1733 setformat(o, O_CLOSE);
1735 /* Make congestion noise */
1736 ring(o, AST_CONTROL_CONGESTION);
1740 pthread_join(o->hidthread,NULL);
1745 /* used for data coming from the network */
1746 static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
1748 struct chan_usbradio_pvt *o = c->tech_pvt;
1750 traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound));
1752 #ifndef NEW_ASTERISK
1753 /* Immediately return if no sound is enabled */
1756 /* Stop any currently playing sound */
1760 * we could receive a block which is not a multiple of our
1761 * FRAME_SIZE, so buffer it locally and write to the device
1762 * in FRAME_SIZE chunks.
1763 * Keep the residue stored for future use.
1766 #if DEBUG_CAPTURES == 1 // to write input data to a file datalen=320
1767 if (ftxcapraw && o->b.txcapraw)
1769 i16 i, tbuff[f->datalen];
1770 for(i=0;i<f->datalen;i+=2)
1772 tbuff[i]= ((i16*)(f->data.ptr))[i/2];
1773 tbuff[i+1]= o->txkeyed*M_Q13;
1775 fwrite(tbuff,2,f->datalen,ftxcapraw);
1776 //fwrite(f->data,1,f->datalen,ftxcapraw);
1780 // maw just take the data from the network and save it for PmrRx processing
1782 PmrTx(o->pmrChan,(i16*)f->data.ptr);
1787 static struct ast_frame *usbradio_read(struct ast_channel *c)
1789 int res, src, datalen, oldpttout;
1791 struct chan_usbradio_pvt *o = c->tech_pvt;
1792 struct ast_frame *f = &o->read_f,*f1;
1793 struct ast_frame wf = { AST_FRAME_CONTROL };
1796 traceusb2(("usbradio_read()\n"));
1801 if ((now - o->lasthidtime) > 3)
1803 ast_log(LOG_ERROR,"HID process has died or something!!\n");
1807 /* XXX can be simplified returning &ast_null_frame */
1808 /* prepare a NULL frame in case we don't have enough data to return */
1809 bzero(f, sizeof(struct ast_frame));
1810 f->frametype = AST_FRAME_NULL;
1811 f->src = usbradio_tech.type;
1813 res = read(o->sounddev, o->usbradio_read_buf + o->readpos,
1814 sizeof(o->usbradio_read_buf) - o->readpos);
1815 if (res < 0) /* audio data not ready, return a NULL frame */
1817 if (errno != EAGAIN) return NULL;
1818 if (o->readerrs++ > READERR_THRESHOLD)
1820 ast_log(LOG_ERROR,"Stuck USB read channel [%s], un-sticking it!\n",o->name);
1824 if (o->readerrs == 1)
1825 ast_log(LOG_WARNING,"Possibly stuck USB read channel. [%s]\n",o->name);
1828 if (o->readerrs) ast_log(LOG_WARNING,"Nope, USB read channel [%s] wasn't stuck after all.\n",o->name);
1831 if (o->readpos < sizeof(o->usbradio_read_buf)) /* not enough samples */
1837 #if DEBUG_CAPTURES == 1
1838 if (o->b.rxcapraw && frxcapraw) fwrite((o->usbradio_read_buf + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2 * 2 * 6,frxcapraw);
1842 if(o->txkeyed||o->txtestkey)
1844 if(!o->pmrChan->txPttIn)
1846 o->pmrChan->txPttIn=1;
1847 if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
1850 else if(o->pmrChan->txPttIn)
1852 o->pmrChan->txPttIn=0;
1853 if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
1855 oldpttout = o->pmrChan->txPttOut;
1858 (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
1859 (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),
1860 (i16 *)(o->usbradio_write_buf_1));
1862 if (oldpttout != o->pmrChan->txPttOut)
1864 if(o->debuglevel) ast_log(LOG_NOTICE,"txPttOut = %i, chan %s\n",o->pmrChan->txPttOut,o->owner->name);
1868 #if 0 // to write 48KS/s stereo tx data to a file
1869 if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
1870 if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,FRAME_SIZE * 2 * 6,ftxoutraw);
1873 #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
1874 if (o->b.txcap2 && ftxcaptrace) fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace);
1877 // 160 samples * 2 bytes/sample * 2 chan * 6x oversampling to 48KS/s
1878 datalen = FRAME_SIZE * 24;
1879 src = 0; /* read position into f->data */
1880 while (src < datalen)
1882 /* Compute spare room in the buffer */
1883 int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
1885 if (datalen - src >= l)
1887 /* enough to fill a frame */
1888 memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
1889 soundcard_writeframe(o, (short *) o->usbradio_write_buf);
1891 o->usbradio_write_dst = 0;
1897 memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
1898 src += l; /* but really, we are done */
1899 o->usbradio_write_dst += l;
1903 static FILE *hInput;
1904 i16 iBuff[FRAME_SIZE*2*6];
1906 o->pmrChan->b.rxCapture=1;
1910 hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
1913 printf(" Input Data File Not Found.\n");
1918 if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit;
1922 (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
1927 if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE,"w");
1928 if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw);
1931 #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
1932 if (frxcaptrace && o->b.rxcap2 && o->pmrChan->b.radioactive) fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace);
1936 if(o->rxcdtype==CD_HID && (o->pmrChan->rxExtCarrierDetect!=o->rxhidsq))
1937 o->pmrChan->rxExtCarrierDetect=o->rxhidsq;
1939 if(o->rxcdtype==CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect==o->rxhidsq))
1940 o->pmrChan->rxExtCarrierDetect=!o->rxhidsq;
1942 if( (o->rxcdtype==CD_HID && o->rxhidsq) ||
1943 (o->rxcdtype==CD_HID_INVERT && !o->rxhidsq) ||
1944 (o->rxcdtype==CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
1945 (o->rxcdtype==CD_XPMR_VOX && o->pmrChan->rxCarrierDetect)
1948 if (!o->pmrChan->txPttOut || o->radioduplex)cd=1;
1955 if(cd!=o->rxcarrierdetect)
1957 o->rxcarrierdetect=cd;
1958 if(o->debuglevel) ast_log(LOG_NOTICE,"rxcarrierdetect = %i, chan %s\n",cd,o->owner->name);
1959 // printf("rxcarrierdetect = %i, chan %s\n",res,o->owner->name);
1962 if(o->pmrChan->b.ctcssRxEnable && o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
1964 if(o->debuglevel)ast_log(LOG_NOTICE,"rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
1965 // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
1966 o->rxctcssdecode=o->pmrChan->rxCtcss->decode;
1967 strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
1971 if( !o->pmrChan->b.ctcssRxEnable ||
1972 ( o->pmrChan->b.ctcssRxEnable &&
1973 o->pmrChan->rxCtcss->decode>CTCSS_NULL &&
1974 o->pmrChan->smode==SMODE_CTCSS )
1984 if( (!o->pmrChan->b.ctcssRxEnable && !o->pmrChan->b.dcsRxEnable && !o->pmrChan->b.lmrRxEnable) ||
1985 ( o->pmrChan->b.ctcssRxEnable &&
1986 o->pmrChan->rxCtcss->decode>CTCSS_NULL &&
1987 o->pmrChan->smode==SMODE_CTCSS ) ||
1988 ( o->pmrChan->b.dcsRxEnable &&
1989 o->pmrChan->decDcs->decode > 0 &&
1990 o->pmrChan->smode==SMODE_DCS )
2000 if(o->pmrChan->decDcs->decode!=o->rxdcsdecode)
2002 if(o->debuglevel)ast_log(LOG_NOTICE,"rxdcsdecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
2003 // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
2004 o->rxdcsdecode=o->pmrChan->decDcs->decode;
2005 strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
2008 if(o->pmrChan->rptnum && (o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed != o->rxlsddecode))
2010 if(o->debuglevel)ast_log(LOG_NOTICE,"rxLSDecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
2011 o->rxlsddecode=o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed;
2012 strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
2015 if( (o->pmrChan->rptnum>0 && o->pmrChan->smode==SMODE_LSD && o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed)||
2016 (o->pmrChan->smode==SMODE_DCS && o->pmrChan->decDcs->decode>0) )
2024 //if(!o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
2025 if(!o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 1, chan %s\n", o->owner->name);
2030 //if(o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
2031 if(o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 0, chan %s\n",o->owner->name);
2035 // provide rx signal detect conditions
2036 if (o->lastrx && (!o->rxkeyed))
2039 //printf("AST_CONTROL_RADIO_UNKEY\n");
2040 wf.subclass = AST_CONTROL_RADIO_UNKEY;
2041 ast_queue_frame(o->owner, &wf);
2043 else if ((!o->lastrx) && (o->rxkeyed))
2046 //printf("AST_CONTROL_RADIO_KEY\n");
2047 wf.subclass = AST_CONTROL_RADIO_KEY;
2048 if(o->rxctcssdecode)
2050 wf.data.ptr = o->rxctcssfreq;
2051 wf.datalen = strlen(o->rxctcssfreq) + 1;
2052 TRACEO(1,("AST_CONTROL_RADIO_KEY text=%s\n",o->rxctcssfreq));
2054 ast_queue_frame(o->owner, &wf);
2057 o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */
2058 if (c->_state != AST_STATE_UP) /* drop data if frame is not up */
2060 /* ok we can build and deliver the frame to the caller */
2061 f->frametype = AST_FRAME_VOICE;
2062 f->subclass = AST_FORMAT_SLINEAR;
2063 f->samples = FRAME_SIZE;
2064 f->datalen = FRAME_SIZE * 2;
2065 f->data.ptr = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET;
2066 if (o->boost != BOOST_SCALE) { /* scale and clip values */
2068 int16_t *p = (int16_t *) f->data.ptr;
2069 for (i = 0; i < f->samples; i++) {
2070 x = (p[i] * o->boost) / BOOST_SCALE;
2073 else if (x < -32768)
2079 f->offset = AST_FRIENDLY_OFFSET;
2082 f1 = ast_dsp_process(c,o->dsp,f);
2083 if ((f1->frametype == AST_FRAME_DTMF_END) ||
2084 (f1->frametype == AST_FRAME_DTMF_BEGIN))
2086 if ((f1->subclass == 'm') || (f1->subclass == 'u'))
2088 f1->frametype = AST_FRAME_NULL;
2092 if (f1->frametype == AST_FRAME_DTMF_END)
2093 ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
2100 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
2102 struct chan_usbradio_pvt *o = newchan->tech_pvt;
2103 ast_log(LOG_WARNING,"usbradio_fixup()\n");
2108 static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
2110 struct chan_usbradio_pvt *o = c->tech_pvt;
2114 case AST_CONTROL_BUSY:
2115 case AST_CONTROL_CONGESTION:
2116 case AST_CONTROL_RINGING:
2121 #ifndef NEW_ASTERISK
2123 o->nosound = 0; /* when cursound is -1 nosound must be 0 */
2127 case AST_CONTROL_VIDUPDATE:
2130 case AST_CONTROL_HOLD:
2131 ast_verbose(" << Console Has Been Placed on Hold >> \n");
2132 ast_moh_start(c, data, o->mohinterpret);
2134 case AST_CONTROL_UNHOLD:
2135 ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
2138 case AST_CONTROL_PROCEEDING:
2139 ast_verbose(" << Call Proceeding... >> \n");
2142 case AST_CONTROL_PROGRESS:
2143 ast_verbose(" << Call Progress... >> \n");
2146 case AST_CONTROL_RADIO_KEY:
2148 if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_KEY Radio Transmit On. >> \n");
2150 case AST_CONTROL_RADIO_UNKEY:
2152 if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_UNKEY Radio Transmit Off. >> \n");
2155 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
2166 * allocate a new channel.
2168 static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state)
2170 struct ast_channel *c;
2172 c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "Radio/%s", o->name);
2175 c->tech = &usbradio_tech;
2176 if (o->sounddev < 0)
2177 setformat(o, O_RDWR);
2178 c->fds[0] = o->sounddev; /* -1 if device closed, override later */
2179 c->nativeformats = AST_FORMAT_SLINEAR;
2180 c->readformat = AST_FORMAT_SLINEAR;
2181 c->writeformat = AST_FORMAT_SLINEAR;
2184 if (!ast_strlen_zero(o->language))
2185 ast_string_field_set(c, language, o->language);
2186 /* Don't use ast_set_callerid() here because it will
2187 * generate a needless NewCallerID event */
2188 c->cid.cid_num = ast_strdup(o->cid_num);
2189 c->cid.cid_ani = ast_strdup(o->cid_num);
2190 c->cid.cid_name = ast_strdup(o->cid_name);
2191 if (!ast_strlen_zero(ext))
2192 c->cid.cid_dnid = ast_strdup(ext);
2195 ast_module_ref(ast_module_info->self);
2196 ast_jb_configure(c, &global_jbconf);
2197 if (state != AST_STATE_DOWN) {
2198 if (ast_pbx_start(c)) {
2199 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
2201 o->owner = c = NULL;
2202 /* XXX what about the channel itself ? */
2203 /* XXX what about usecnt ? */
2211 static struct ast_channel *usbradio_request(const char *type, int format, void *data, int *cause)
2213 struct ast_channel *c;
2214 struct chan_usbradio_pvt *o = find_desc(data);
2216 TRACEO(1,("usbradio_request()\n"));
2220 ast_log(LOG_WARNING, "usbradio_request type <%s> data 0x%p <%s>\n", type, data, (char *) data);
2223 ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
2224 /* XXX we could default to 'dsp' perhaps ? */
2227 if ((format & AST_FORMAT_SLINEAR) == 0) {
2228 ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format);
2232 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the usb channel\n", o->owner);
2233 *cause = AST_CAUSE_BUSY;
2236 c = usbradio_new(o, NULL, NULL, AST_STATE_DOWN);
2238 ast_log(LOG_WARNING, "Unable to create new usb channel\n");
2249 static int console_key(int fd, int argc, char *argv[])
2251 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2254 return RESULT_SHOWUSAGE;
2256 return RESULT_SUCCESS;
2260 static int console_unkey(int fd, int argc, char *argv[])
2262 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2265 return RESULT_SHOWUSAGE;
2267 return RESULT_SUCCESS;
2270 static int radio_tune(int fd, int argc, char *argv[])
2272 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2275 if ((argc < 2) || (argc > 4))
2276 return RESULT_SHOWUSAGE;
2278 if (argc == 2) /* just show stuff */
2280 ast_cli(fd,"Active radio interface is [%s]\n",usbradio_active);
2281 ast_cli(fd,"Output A is currently set to ");
2282 if(o->txmixa==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
2283 else if (o->txmixa==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
2284 else if (o->txmixa==TX_OUT_LSD)ast_cli(fd,"tone.\n");
2285 else if (o->txmixa==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
2286 else ast_cli(fd,"off.\n");
2288 ast_cli(fd,"Output B is currently set to ");
2289 if(o->txmixb==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
2290 else if (o->txmixb==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
2291 else if (o->txmixb==TX_OUT_LSD)ast_cli(fd,"tone.\n");
2292 else if (o->txmixb==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
2293 else ast_cli(fd,"off.\n");
2295 ast_cli(fd,"Tx Voice Level currently set to %d\n",o->txmixaset);
2296 ast_cli(fd,"Tx Tone Level currently set to %d\n",o->txctcssadj);
2297 ast_cli(fd,"Rx Squelch currently set to %d\n",o->rxsquelchadj);
2298 ast_cli(fd,"Device String is %s\n",o->devstr);
2299 return RESULT_SHOWUSAGE;
2302 o->pmrChan->b.tuning=1;
2304 if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(fd,o);
2305 else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(fd,o);
2306 else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(fd,o);
2307 else if (!strcasecmp(argv[2],"rxsquelch"))
2311 ast_cli(fd,"Current Signal Strength is %d\n",((32767-o->pmrChan->rxRssi)*1000/32767));
2312 ast_cli(fd,"Current Squelch setting is %d\n",o->rxsquelchadj);
2313 //ast_cli(fd,"Current Raw RSSI is %d\n",o->pmrChan->rxRssi);
2314 //ast_cli(fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
2317 if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2318 ast_cli(fd,"Changed Squelch setting to %d\n",i);
2319 o->rxsquelchadj = i;
2320 *(o->pmrChan->prxSquelchAdjust)= ((999 - i) * 32767) / 1000;
2323 else if (!strcasecmp(argv[2],"txvoice")) {
2326 if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
2327 (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
2330 ast_log(LOG_ERROR,"No txvoice output configured.\n");
2334 if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2335 ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
2337 ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
2342 if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2344 if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2347 ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
2352 ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
2356 ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
2358 o->pmrChan->b.txCtcssInhibit=1;
2359 tune_txoutput(o,i,fd);
2360 o->pmrChan->b.txCtcssInhibit=0;
2362 else if (!strcasecmp(argv[2],"txall")) {
2365 if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
2366 (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
2369 ast_log(LOG_ERROR,"No txvoice output configured.\n");
2373 if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2374 ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
2376 ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
2381 if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2383 if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2386 ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
2391 ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
2395 ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
2397 tune_txoutput(o,i,fd);
2399 else if (!strcasecmp(argv[2],"auxvoice")) {
2401 if( (o->txmixa!=TX_OUT_AUX) && (o->txmixb!=TX_OUT_AUX))
2403 ast_log(LOG_WARNING,"No auxvoice output configured.\n");
2407 if(o->txmixa==TX_OUT_AUX)
2408 ast_cli(fd,"Current auxvoice setting on Channel A is %d\n",o->txmixaset);
2410 ast_cli(fd,"Current auxvoice setting on Channel B is %d\n",o->txmixbset);
2415 if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2416 if(o->txmixa==TX_OUT_AUX)
2419 ast_cli(fd,"Changed auxvoice setting on Channel A to %d\n",o->txmixaset);
2424 ast_cli(fd,"Changed auxvoice setting on Channel B to %d\n",o->txmixbset);
2429 //tune_auxoutput(o,i);
2431 else if (!strcasecmp(argv[2],"txtone"))
2434 ast_cli(fd,"Current Tx CTCSS modulation setting = %d\n",o->txctcssadj);
2438 if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2440 set_txctcss_level(o);
2441 ast_cli(fd,"Changed Tx CTCSS modulation setting to %i\n",i);
2447 else if (!strcasecmp(argv[2],"dump")) pmrdump(o);
2448 else if (!strcasecmp(argv[2],"nocap"))
2450 ast_cli(fd,"File capture (trace) was rx=%d tx=%d and now off.\n",o->b.rxcap2,o->b.txcap2);
2451 ast_cli(fd,"File capture (raw) was rx=%d tx=%d and now off.\n",o->b.rxcapraw,o->b.txcapraw);
2452 o->b.rxcapraw=o->b.txcapraw=o->b.rxcap2=o->b.txcap2=o->pmrChan->b.rxCapture=o->pmrChan->b.txCapture=0;
2453 if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
2454 if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
2455 if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
2456 if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
2457 if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
2458 if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
2460 else if (!strcasecmp(argv[2],"rxtracecap"))
2462 if (!frxcaptrace) frxcaptrace= fopen(RX_CAP_TRACE_FILE,"w");
2463 ast_cli(fd,"Trace rx on.\n");
2464 o->b.rxcap2=o->pmrChan->b.rxCapture=1;
2466 else if (!strcasecmp(argv[2],"txtracecap"))
2468 if (!ftxcaptrace) ftxcaptrace= fopen(TX_CAP_TRACE_FILE,"w");
2469 ast_cli(fd,"Trace tx on.\n");
2470 o->b.txcap2=o->pmrChan->b.txCapture=1;
2472 else if (!strcasecmp(argv[2],"rxcap"))
2474 if (!frxcapraw) frxcapraw = fopen(RX_CAP_RAW_FILE,"w");
2475 ast_cli(fd,"cap rx raw on.\n");
2478 else if (!strcasecmp(argv[2],"txcap"))
2480 if (!ftxcapraw) ftxcapraw = fopen(TX_CAP_RAW_FILE,"w");
2481 ast_cli(fd,"cap tx raw on.\n");
2484 else if (!strcasecmp(argv[2],"save"))
2487 ast_cli(fd,"Saved radio tuning settings to usbradio_tune_%s.conf\n",o->name);
2489 else if (!strcasecmp(argv[2],"load"))
2491 ast_mutex_lock(&o->eepromlock);
2494 ast_mutex_unlock(&o->eepromlock);
2496 ast_mutex_lock(&o->eepromlock);
2498 o->eepromctl = 1; /* request a load */
2499 ast_mutex_unlock(&o->eepromlock);
2501 ast_cli(fd,"Requesting loading of tuning settings from EEPROM for channel %s\n",o->name);
2505 o->pmrChan->b.tuning=0;
2506 return RESULT_SHOWUSAGE;
2508 o->pmrChan->b.tuning=0;
2509 return RESULT_SUCCESS;
2513 set transmit ctcss modulation level
2514 adjust mixer output or internal gain depending on output type
2515 setting range is 0.0 to 0.9
2517 static int set_txctcss_level(struct chan_usbradio_pvt *o)
2519 if (o->txmixa == TX_OUT_LSD)
2521 // o->txmixaset=(151*o->txctcssadj) / 1000;
2522 o->txmixaset=o->txctcssadj;
2526 else if (o->txmixb == TX_OUT_LSD)
2528 // o->txmixbset=(151*o->txctcssadj) / 1000;
2529 o->txmixbset=o->txctcssadj;
2535 *o->pmrChan->ptxCtcssAdjust=(o->txctcssadj * M_Q8) / 1000;
2540 CLI debugging on and off
2542 static int radio_set_debug(int fd, int argc, char *argv[])
2544 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2547 ast_cli(fd,"usbradio debug on.\n");
2548 return RESULT_SUCCESS;
2551 static int radio_set_debug_off(int fd, int argc, char *argv[])
2553 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2556 ast_cli(fd,"usbradio debug off.\n");
2557 return RESULT_SUCCESS;
2560 static int radio_active(int fd, int argc, char *argv[])
2563 ast_cli(fd, "active (command) USB Radio device is [%s]\n", usbradio_active);
2565 return RESULT_SHOWUSAGE;
2567 struct chan_usbradio_pvt *o;
2568 if (strcmp(argv[2], "show") == 0) {
2569 for (o = usbradio_default.next; o; o = o->next)
2570 ast_cli(fd, "device [%s] exists\n", o->name);
2571 return RESULT_SUCCESS;
2573 o = find_desc(argv[2]);
2575 ast_cli(fd, "No device [%s] exists\n", argv[2]);
2578 struct chan_usbradio_pvt *ao;
2579 for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
2580 usbradio_active = o->name;
2581 o->pmrChan->b.radioactive=1;
2584 return RESULT_SUCCESS;
2587 CLI debugging on and off
2589 static int radio_set_xpmr_debug(int fd, int argc, char *argv[])
2591 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2597 if ((i >= 0) && (i <= 100))
2599 o->pmrChan->tracelevel=i;
2602 // add ability to set it for a number of frames after which it reverts
2603 ast_cli(fd,"usbradio xdebug on tracelevel %i\n",o->pmrChan->tracelevel);
2605 return RESULT_SUCCESS;
2609 static char key_usage[] =
2610 "Usage: radio key\n"
2611 " Simulates COR active.\n";
2613 static char unkey_usage[] =
2614 "Usage: radio unkey\n"
2615 " Simulates COR un-active.\n";
2617 static char active_usage[] =
2618 "Usage: radio active [device-name]\n"
2619 " If used without a parameter, displays which device is the current\n"
2620 "one being commanded. If a device is specified, the commanded radio device is changed\n"
2621 "to the device specified.\n";
2623 radio tune 6 3000 measured tx value
2625 static char radio_tune_usage[] =
2626 "Usage: radio tune <function>\n"
2630 " rxsquelch [newsetting]\n"
2631 " txvoice [newsetting]\n"
2632 " txtone [newsetting]\n"
2633 " auxvoice [newsetting]\n"
2634 " save (settings to tuning file)\n"
2635 " load (tuning settings from EEPROM)\n"
2636 "\n All [newsetting]'s are values 0-999\n\n";
2638 #ifndef NEW_ASTERISK
2640 static struct ast_cli_entry cli_usbradio[] = {
2641 { { "radio", "key", NULL },
2642 console_key, "Simulate Rx Signal Present",
2643 key_usage, NULL, NULL},
2645 { { "radio", "unkey", NULL },
2646 console_unkey, "Simulate Rx Signal Lusb",
2647 unkey_usage, NULL, NULL },
2649 { { "radio", "tune", NULL },
2650 radio_tune, "Radio Tune",
2651 radio_tune_usage, NULL, NULL },
2653 { { "radio", "set", "debug", NULL },
2654 radio_set_debug, "Radio Debug",
2655 radio_tune_usage, NULL, NULL },
2657 { { "radio", "set", "debug", "off", NULL },
2658 radio_set_debug_off, "Radio Debug",
2659 radio_tune_usage, NULL, NULL },
2661 { { "radio", "active", NULL },
2662 radio_active, "Change commanded device",
2663 active_usage, NULL, NULL },
2665 { { "radio", "set", "xdebug", NULL },
2666 radio_set_xpmr_debug, "Radio set xpmr debug level",
2667 active_usage, NULL, NULL },
2673 * store the callerid components
2676 static void store_callerid(struct chan_usbradio_pvt *o, char *s)
2678 ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
2682 static void store_rxdemod(struct chan_usbradio_pvt *o, char *s)
2684 if (!strcasecmp(s,"no")){
2685 o->rxdemod = RX_AUDIO_NONE;
2687 else if (!strcasecmp(s,"speaker")){
2688 o->rxdemod = RX_AUDIO_SPEAKER;
2690 else if (!strcasecmp(s,"flat")){
2691 o->rxdemod = RX_AUDIO_FLAT;
2694 ast_log(LOG_WARNING,"Unrecognized rxdemod parameter: %s\n",s);
2697 //ast_log(LOG_WARNING, "set rxdemod = %s\n", s);
2701 static void store_txmixa(struct chan_usbradio_pvt *o, char *s)
2703 if (!strcasecmp(s,"no")){
2704 o->txmixa = TX_OUT_OFF;
2706 else if (!strcasecmp(s,"voice")){
2707 o->txmixa = TX_OUT_VOICE;
2709 else if (!strcasecmp(s,"tone")){
2710 o->txmixa = TX_OUT_LSD;
2712 else if (!strcasecmp(s,"composite")){
2713 o->txmixa = TX_OUT_COMPOSITE;
2715 else if (!strcasecmp(s,"auxvoice")){
2716 o->txmixa = TX_OUT_AUX;
2719 ast_log(LOG_WARNING,"Unrecognized txmixa parameter: %s\n",s);
2722 //ast_log(LOG_WARNING, "set txmixa = %s\n", s);
2725 static void store_txmixb(struct chan_usbradio_pvt *o, char *s)
2727 if (!strcasecmp(s,"no")){
2728 o->txmixb = TX_OUT_OFF;
2730 else if (!strcasecmp(s,"voice")){
2731 o->txmixb = TX_OUT_VOICE;
2733 else if (!strcasecmp(s,"tone")){
2734 o->txmixb = TX_OUT_LSD;
2736 else if (!strcasecmp(s,"composite")){
2737 o->txmixb = TX_OUT_COMPOSITE;
2739 else if (!strcasecmp(s,"auxvoice")){
2740 o->txmixb = TX_OUT_AUX;
2743 ast_log(LOG_WARNING,"Unrecognized txmixb parameter: %s\n",s);
2746 //ast_log(LOG_WARNING, "set txmixb = %s\n", s);
2750 static void store_rxcdtype(struct chan_usbradio_pvt *o, char *s)
2752 if (!strcasecmp(s,"no")){
2753 o->rxcdtype = CD_IGNORE;
2755 else if (!strcasecmp(s,"usb")){
2756 o->rxcdtype = CD_HID;
2758 else if (!strcasecmp(s,"dsp")){
2759 o->rxcdtype = CD_XPMR_NOISE;
2761 else if (!strcasecmp(s,"vox")){
2762 o->rxcdtype = CD_XPMR_VOX;
2764 else if (!strcasecmp(s,"usbinvert")){
2765 o->rxcdtype = CD_HID_INVERT;
2768 ast_log(LOG_WARNING,"Unrecognized rxcdtype parameter: %s\n",s);
2771 //ast_log(LOG_WARNING, "set rxcdtype = %s\n", s);
2775 static void store_rxsdtype(struct chan_usbradio_pvt *o, char *s)
2777 if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){
2778 o->rxsdtype = SD_IGNORE;
2780 else if (!strcasecmp(s,"usb") || !strcasecmp(s,"SD_HID")){
2781 o->rxsdtype = SD_HID;
2783 else if (!strcasecmp(s,"usbinvert") || !strcasecmp(s,"SD_HID_INVERT")){
2784 o->rxsdtype = SD_HID_INVERT;
2786 else if (!strcasecmp(s,"software") || !strcasecmp(s,"SD_XPMR")){
2787 o->rxsdtype = SD_XPMR;
2790 ast_log(LOG_WARNING,"Unrecognized rxsdtype parameter: %s\n",s);
2793 //ast_log(LOG_WARNING, "set rxsdtype = %s\n", s);
2797 static void store_rxgain(struct chan_usbradio_pvt *o, char *s)
2802 //ast_log(LOG_WARNING, "set rxgain = %f\n", f);
2806 static void store_rxvoiceadj(struct chan_usbradio_pvt *o, char *s)
2811 //ast_log(LOG_WARNING, "set rxvoiceadj = %f\n", f);
2815 static void store_rxctcssadj(struct chan_usbradio_pvt *o, char *s)
2820 //ast_log(LOG_WARNING, "set rxctcssadj = %f\n", f);
2824 static void store_txtoctype(struct chan_usbradio_pvt *o, char *s)
2826 if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){
2827 o->txtoctype = TOC_NONE;
2829 else if (!strcasecmp(s,"phase") || !strcasecmp(s,"TOC_PHASE")){
2830 o->txtoctype = TOC_PHASE;
2832 else if (!strcasecmp(s,"notone") || !strcasecmp(s,"TOC_NOTONE")){
2833 o->txtoctype = TOC_NOTONE;
2836 ast_log(LOG_WARNING,"Unrecognized txtoctype parameter: %s\n",s);
2841 static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd)
2844 o->pmrChan->txPttIn=1;
2845 TxTestTone(o->pmrChan, 1); // generate 1KHz tone at 7200 peak
2846 if (fd > 0) ast_cli(fd,"Tone output starting on channel %s...\n",o->name);
2848 TxTestTone(o->pmrChan, 0);
2849 if (fd > 0) ast_cli(fd,"Tone output ending on channel %s...\n",o->name);
2850 o->pmrChan->txPttIn=0;
2855 static void tune_rxinput(int fd, struct chan_usbradio_pvt *o)
2857 const int target=23000;
2858 const int tolerance=2000;
2859 const int settingmin=1;
2860 const int settingstart=2;
2861 const int maxtries=12;
2865 int setting=0, tries=0, tmpdiscfactor, meas;
2868 settingmax = o->micmax;
2870 if(o->pmrChan->rxDemod)tunetype=1;
2871 o->pmrChan->b.tuning=1;
2873 setting = settingstart;
2875 ast_cli(fd,"tune rxnoise maxtries=%i, target=%i, tolerance=%i\n",maxtries,target,tolerance);
2877 while(tries<maxtries)
2879 setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,setting,0);
2880 setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
2883 if(o->rxcdtype!=CD_XPMR_NOISE || o->rxdemod==RX_AUDIO_SPEAKER)
2885 // printf("Measure Direct Input\n");
2886 o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source;
2887 o->pmrChan->spsMeasure->discfactor=2000;
2888 o->pmrChan->spsMeasure->enabled=1;
2889 o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
2891 meas=o->pmrChan->spsMeasure->apeak;
2892 o->pmrChan->spsMeasure->enabled=0;
2896 // printf("Measure HF Noise\n");
2897 tmpdiscfactor=o->pmrChan->spsRx->discfactor;
2898 o->pmrChan->spsRx->discfactor=(i16)2000;
2899 o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
2900 o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
2902 meas=o->pmrChan->rxRssi;
2903 o->pmrChan->spsRx->discfactor=tmpdiscfactor;
2904 o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
2905 o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
2908 ast_cli(fd,"tries=%i, setting=%i, meas=%i\n",tries,setting,meas);
2910 if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
2911 setting=setting*target/meas;
2913 else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
2918 if(setting<settingmin)setting=settingmin;
2919 else if(setting>settingmax)setting=settingmax;
2923 ast_cli(fd,"DONE tries=%i, setting=%i, meas=%i\n",tries,
2924 (setting * 1000) / o->micmax,meas);
2925 if( meas<(target-tolerance) || meas>(target+tolerance) ){
2926 ast_cli(fd,"ERROR: RX INPUT ADJUST FAILED.\n");
2928 ast_cli(fd,"INFO: RX INPUT ADJUST SUCCESS.\n");
2929 o->rxmixerset=(setting * 1000) / o->micmax;
2931 o->pmrChan->b.tuning=0;
2935 static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o)
2937 const int target=7200; // peak
2938 const int tolerance=360; // peak to peak
2939 const float settingmin=0.1;
2940 const float settingmax=4;
2941 const float settingstart=1;
2942 const int maxtries=12;
2948 ast_cli(fd,"INFO: RX VOICE ADJUST START.\n");
2949 ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
2951 o->pmrChan->b.tuning=1;
2952 if(!o->pmrChan->spsMeasure)
2953 ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
2955 if(!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
2956 ast_cli(fd,"ERROR: NO SOURCE OR MEASURE SETTING.\n");
2958 o->pmrChan->spsMeasure->source=o->pmrChan->spsRxOut->sink;
2959 o->pmrChan->spsMeasure->enabled=1;
2960 o->pmrChan->spsMeasure->discfactor=1000;
2962 setting=settingstart;
2964 // ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
2966 while(tries<maxtries)
2968 *(o->pmrChan->prxVoiceAdjust)=setting*M_Q8;
2970 o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
2972 meas = o->pmrChan->spsMeasure->apeak;
2973 ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
2975 if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
2976 setting=setting*target/meas;
2978 else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
2982 if(setting<settingmin)setting=settingmin;
2983 else if(setting>settingmax)setting=settingmax;
2988 o->pmrChan->spsMeasure->enabled=0;
2990 ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
2991 if( meas<(target-tolerance) || meas>(target+tolerance) ){
2992 ast_cli(fd,"ERROR: RX VOICE GAIN ADJUST FAILED.\n");
2994 ast_cli(fd,"INFO: RX VOICE GAIN ADJUST SUCCESS.\n");
2995 o->rxvoiceadj=setting;
2997 o->pmrChan->b.tuning=0;
3001 static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o)
3003 const int target=2400; // was 4096 pre 20080205
3004 const int tolerance=100;
3005 const float settingmin=0.1;
3006 const float settingmax=8;
3007 const float settingstart=1;
3008 const int maxtries=12;
3013 ast_cli(fd,"INFO: RX CTCSS ADJUST START.\n");
3014 ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
3016 o->pmrChan->b.tuning=1;
3017 o->pmrChan->spsMeasure->source=o->pmrChan->prxCtcssMeasure;
3018 o->pmrChan->spsMeasure->discfactor=400;
3019 o->pmrChan->spsMeasure->enabled=1;
3021 setting=settingstart;
3023 while(tries<maxtries)
3025 *(o->pmrChan->prxCtcssAdjust)=setting*M_Q8;
3027 o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
3029 meas = o->pmrChan->spsMeasure->apeak;
3030 ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
3032 if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
3033 setting=setting*target/meas;
3035 else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
3039 if(setting<settingmin)setting=settingmin;
3040 else if(setting>settingmax)setting=settingmax;
3044 o->pmrChan->spsMeasure->enabled=0;
3045 ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
3046 if( meas<(target-tolerance) || meas>(target+tolerance) ){
3047 ast_cli(fd,"ERROR: RX CTCSS GAIN ADJUST FAILED.\n");
3049 ast_cli(fd,"INFO: RX CTCSS GAIN ADJUST SUCCESS.\n");
3050 o->rxctcssadj=setting;
3052 o->pmrChan->b.tuning=0;
3055 after radio tune is performed data is serialized here
3057 static void tune_write(struct chan_usbradio_pvt *o)
3062 snprintf(fname,sizeof(fname) - 1,"/etc/asterisk/usbradio_tune_%s.conf",o->name);
3063 fp = fopen(fname,"w");
3065 fprintf(fp,"[%s]\n",o->name);
3067 fprintf(fp,"; name=%s\n",o->name);
3068 fprintf(fp,"; devicenum=%i\n",o->devicenum);
3069 fprintf(fp,"devstr=%s\n",o->devstr);
3070 fprintf(fp,"rxmixerset=%i\n",o->rxmixerset);
3071 fprintf(fp,"txmixaset=%i\n",o->txmixaset);
3072 fprintf(fp,"txmixbset=%i\n",o->txmixbset);
3073 fprintf(fp,"rxvoiceadj=%f\n",o->rxvoiceadj);
3074 fprintf(fp,"rxctcssadj=%f\n",o->rxctcssadj);
3075 fprintf(fp,"txctcssadj=%i\n",o->txctcssadj);
3076 fprintf(fp,"rxsquelchadj=%i\n",o->rxsquelchadj);
3081 ast_mutex_lock(&o->eepromlock);
3084 ast_mutex_unlock(&o->eepromlock);
3086 ast_mutex_lock(&o->eepromlock);
3088 o->eeprom[EEPROM_RXMIXERSET] = o->rxmixerset;
3089 o->eeprom[EEPROM_TXMIXASET] = o->txmixaset;
3090 o->eeprom[EEPROM_TXMIXBSET] = o->txmixbset;
3091 memcpy(&o->eeprom[EEPROM_RXVOICEADJ],&o->rxvoiceadj,sizeof(float));
3092 memcpy(&o->eeprom[EEPROM_RXCTCSSADJ],&o->rxctcssadj,sizeof(float));
3093 o->eeprom[EEPROM_TXCTCSSADJ] = o->txctcssadj;
3094 o->eeprom[EEPROM_RXSQUELCHADJ] = o->rxsquelchadj;
3095 o->eepromctl = 2; /* request a write */
3096 ast_mutex_unlock(&o->eepromlock);
3100 static void mixer_write(struct chan_usbradio_pvt *o)
3102 setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_SW,0,0);
3103 setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_VOL,0,0);
3104 setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_SW,1,0);
3105 setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL,
3106 o->txmixaset * o->spkrmax / 1000,
3107 o->txmixbset * o->spkrmax / 1000);
3108 setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,
3109 o->rxmixerset * o->micmax / 1000,0);
3110 setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
3111 setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_SW,1,0);
3114 adjust dsp multiplier to add resolution to tx level adjustment
3116 static void mult_set(struct chan_usbradio_pvt *o)
3119 if(o->pmrChan->spsTxOutA) {
3120 o->pmrChan->spsTxOutA->outputGain =
3121 mult_calc((o->txmixaset * 152) / 1000);
3123 if(o->pmrChan->spsTxOutB){
3124 o->pmrChan->spsTxOutB->outputGain =
3125 mult_calc((o->txmixbset * 152) / 1000);
3129 // input 0 - 151 outputs are pot and multiplier
3131 static int mult_calc(int value)
3133 const int multx=M_Q8;
3136 pot=((int)(value/4)*4)+2;
3137 mult = multx-( ( multx * (3-(value%4)) ) / (pot+2) );
3141 #define pd(x) {printf(#x" = %d\n",x);}
3142 #define pp(x) {printf(#x" = %p\n",x);}
3143 #define ps(x) {printf(#x" = %s\n",x);}
3144 #define pf(x) {printf(#x" = %f\n",x);}
3149 do hid output if only requirement is ptt out
3150 this give fastest performance with least overhead
3151 where gpio inputs are not required.
3154 static int usbhider(struct chan_usbradio_pvt *o, int opt)
3156 unsigned char buf[4];
3161 struct usb_device *usb_dev;
3163 usb_dev = hid_device_init(o->devstr);
3164 if (usb_dev == NULL) {
3165 ast_log(LOG_ERROR,"USB HID device not found\n");
3168 o->usb_handle = usb_open(usb_dev);
3169 if (o->usb_handle == NULL) {
3170 ast_log(LOG_ERROR,"Not able to open USB device\n");
3173 if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0)
3175 if (usb_detach_kernel_driver_np(o->usb_handle,C108_HID_INTERFACE) < 0) {
3176 ast_log(LOG_ERROR,"Not able to detach the USB device\n");
3179 if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0) {
3180 ast_log(LOG_ERROR,"Not able to claim the USB device\n");
3185 memset(buf,0,sizeof(buf));
3186 buf[2] = o->hid_gpio_ctl;
3188 hid_set_outputs(o->usb_handle,buf);
3189 memcpy(bufsave,buf,sizeof(buf));
3191 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
3195 /* if change in tx state as controlled by xpmr */
3196 txtmp=o->pmrChan->txPttOut;
3198 if (o->lasttx != txtmp)
3200 o->pmrChan->txPttHid=o->lasttx = txtmp;
3201 if(o->debuglevel)printf("usbhid: tx set to %d\n",txtmp);
3202 buf[o->hid_gpio_loc] = 0;
3205 if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
3209 if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
3211 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
3212 hid_set_outputs(o->usb_handle,buf);
3220 static void pmrdump(struct chan_usbradio_pvt *o)
3227 printf("\nodump()\n");
3245 pd(o->rxsquelchadj);
3247 ps(o->txctcssdefault);
3250 pd(o->numrxctcssfreqs);
3251 if(o->numrxctcssfreqs>0)
3253 for(i=0;i<o->numrxctcssfreqs;i++)
3255 printf(" %i = %s %s\n",i,o->rxctcss[i],o->txctcss[i]);
3259 pd(o->b.rxpolarity);
3260 pd(o->b.txpolarity);
3269 printf("\npmrdump()\n");
3273 printf("prxSquelchAdjust=%i\n",*(o->pmrChan->prxSquelchAdjust));
3275 pd(p->rxCarrierPoint);
3276 pd(p->rxCarrierHyst);
3278 pd(*p->prxVoiceAdjust);
3279 pd(*p->prxCtcssAdjust);
3284 pd(p->rxCtcss->relax);
3285 //pf(p->rxCtcssFreq);
3287 if(o->pmrChan->numrxcodes>0)
3289 for(i=0;i<o->pmrChan->numrxcodes;i++)
3291 printf(" %i = %s\n",i,o->pmrChan->pRxCode[i]);
3296 ps(p->pTxCodeDefault);
3297 pd(p->txcodedefaultsmode);
3299 if(o->pmrChan->numtxcodes>0)
3301 for(i=0;i<o->pmrChan->numtxcodes;i++)
3303 printf(" %i = %s\n",i,o->pmrChan->pTxCode[i]);
3307 pd(p->b.rxpolarity);
3308 pd(p->b.txpolarity);
3309 pd(p->b.dcsrxpolarity);
3310 pd(p->b.dcstxpolarity);
3311 pd(p->b.lsdrxpolarity);
3312 pd(p->b.lsdtxpolarity);
3317 pd(p->rxDeEmpEnable);
3318 pd(p->rxCenterSlicerEnable);
3319 pd(p->rxCtcssDecodeEnable);
3320 pd(p->rxDcsDecodeEnable);
3321 pd(p->b.ctcssRxEnable);
3322 pd(p->b.dcsRxEnable);
3323 pd(p->b.lmrRxEnable);
3324 pd(p->b.dstRxEnable);
3328 pd(p->txLimiterEnable);
3329 pd(p->txPreEmpEnable);
3332 if(p->spsTxOutA)pd(p->spsTxOutA->outputGain);
3333 if(p->spsTxOutB)pd(p->spsTxOutB->outputGain);
3342 takes data from a chan_usbradio_pvt struct (e.g. o->)
3343 and configures the xpmr radio layer
3345 static int xpmr_config(struct chan_usbradio_pvt *o)
3347 //ast_log(LOG_NOTICE,"xpmr_config()\n");
3349 TRACEO(1,("xpmr_config()\n"));
3351 if(o->pmrChan==NULL)
3353 ast_log(LOG_ERROR,"pmr channel structure NULL\n");
3357 o->pmrChan->rxCtcss->relax = o->rxctcssrelax;
3358 o->pmrChan->txpower=0;
3362 o->pmrChan->pTxCodeDefault = o->set_txctcssdefault;
3363 o->pmrChan->pRxCodeSrc=o->set_rxctcssfreqs;
3364 o->pmrChan->pTxCodeSrc=o->set_txctcssfreqs;
3366 o->pmrChan->rxfreq=o->set_rxfreq;
3367 o->pmrChan->txfreq=o->set_txfreq;
3368 /* printf(" remoted %s %s --> %s \n",o->pmrChan->txctcssdefault,
3369 o->pmrChan->txctcssfreq,o->pmrChan->rxctcssfreq); */
3373 // set xpmr pointers to source strings
3375 o->pmrChan->pTxCodeDefault = o->txctcssdefault;
3376 o->pmrChan->pRxCodeSrc = o->rxctcssfreqs;
3377 o->pmrChan->pTxCodeSrc = o->txctcssfreqs;
3379 o->pmrChan->rxfreq = o->rxfreq;
3380 o->pmrChan->txfreq = o->txfreq;
3383 code_string_parse(o->pmrChan);
3384 if(o->pmrChan->rxfreq) o->pmrChan->b.reprog=1;
3389 * grab fields from the config file, init the descriptor and open the device.
3391 static struct chan_usbradio_pvt *store_config(struct ast_config *cfg, char *ctg)
3393 struct ast_variable *v;
3394 struct chan_usbradio_pvt *o;
3395 struct ast_config *cfg1;
3399 struct ast_flags zeroflag = {0};
3402 traceusb1((" store_config() ctg == NULL\n"));
3403 o = &usbradio_default;
3406 /* "general" is also the default thing */
3407 if (strcmp(ctg, "general") == 0) {
3408 o = &usbradio_default;
3410 // ast_log(LOG_NOTICE,"ast_calloc for chan_usbradio_pvt of %s\n",ctg);
3411 if (!(o = ast_calloc(1, sizeof(*o))))
3413 *o = usbradio_default;
3414 o->name = ast_strdup(ctg);
3415 if (!usbradio_active)
3416 usbradio_active = o->name;
3419 ast_mutex_init(&o->eepromlock);
3420 strcpy(o->mohinterpret, "default");
3421 /* fill other fields from configuration */
3422 for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
3423 M_START((char *)v->name, (char *)v->value);
3425 /* handle jb conf */
3426 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
3430 M_BOOL("autoanswer", o->autoanswer)
3431 M_BOOL("autohangup", o->autohangup)
3432 M_BOOL("overridecontext", o->overridecontext)
3433 M_STR("context", o->ctx)
3434 M_STR("language", o->language)
3435 M_STR("mohinterpret", o->mohinterpret)
3436 M_STR("extension", o->ext)
3437 M_F("callerid", store_callerid(o, v->value))
3439 M_UINT("frags", o->frags)
3440 M_UINT("queuesize",o->queuesize)
3442 M_UINT("devicenum",o->devicenum)
3444 M_UINT("debug", usbradio_debug)
3445 M_BOOL("rxcpusaver",o->rxcpusaver)
3446 M_BOOL("txcpusaver",o->txcpusaver)
3447 M_BOOL("invertptt",o->invertptt)
3448 M_F("rxdemod",store_rxdemod(o,(char *)v->value))
3449 M_BOOL("txprelim",o->txprelim);
3450 M_F("txmixa",store_txmixa(o,(char *)v->value))
3451 M_F("txmixb",store_txmixb(o,(char *)v->value))
3452 M_F("carrierfrom",store_rxcdtype(o,(char *)v->value))
3453 M_F("rxsdtype",store_rxsdtype(o,(char *)v->value))
3454 M_UINT("rxsqvox",o->rxsqvoxadj)
3455 M_STR("txctcssdefault",o->txctcssdefault)
3456 M_STR("rxctcssfreqs",o->rxctcssfreqs)
3457 M_STR("txctcssfreqs",o->txctcssfreqs)
3458 M_UINT("rxfreq",o->rxfreq)
3459 M_UINT("txfreq",o->txfreq)
3460 M_F("rxgain",store_rxgain(o,(char *)v->value))
3461 M_BOOL("rxboost",o->rxboostset)
3462 M_UINT("rxctcssrelax",o->rxctcssrelax)
3463 M_F("txtoctype",store_txtoctype(o,(char *)v->value))
3464 M_UINT("hdwtype",o->hdwtype)
3465 M_UINT("eeprom",o->wanteeprom)
3466 M_UINT("duplex",o->radioduplex)
3467 M_UINT("txsettletime",o->txsettletime)
3468 M_BOOL("rxpolarity",o->b.rxpolarity)
3469 M_BOOL("txpolarity",o->b.txpolarity)
3470 M_BOOL("dcsrxpolarity",o->b.dcsrxpolarity)
3471 M_BOOL("dcstxpolarity",o->b.dcstxpolarity)
3472 M_BOOL("lsdrxpolarity",o->b.lsdrxpolarity)
3473 M_BOOL("lsdtxpolarity",o->b.lsdtxpolarity)
3474 M_BOOL("loopback",o->b.loopback)
3475 M_BOOL("radioactive",o->b.radioactive)
3476 M_UINT("rptnum",o->rptnum)
3477 M_UINT("idleinterval",o->idleinterval)
3478 M_UINT("turnoffs",o->turnoffs)
3479 M_UINT("tracetype",o->tracetype)
3480 M_UINT("tracelevel",o->tracelevel)
3481 M_UINT("area",o->area)
3482 M_STR("ukey",o->ukey)
3489 if (o == &usbradio_default) /* we are done with the default */
3492 snprintf(fname,sizeof(fname) - 1,config1,o->name);
3494 cfg1 = ast_config_load(fname,zeroflag);
3496 cfg1 = ast_config_load(fname);
3498 o->rxmixerset = 500;
3501 o->rxvoiceadj = 0.5;
3502 o->rxctcssadj = 0.5;
3503 o->txctcssadj = 200;
3504 o->rxsquelchadj = 500;
3507 for (v = ast_variable_browse(cfg1, o->name); v; v = v->next) {
3509 M_START((char *)v->name, (char *)v->value);
3510 M_UINT("rxmixerset", o->rxmixerset)
3511 M_UINT("txmixaset", o->txmixaset)
3512 M_UINT("txmixbset", o->txmixbset)
3513 M_F("rxvoiceadj",store_rxvoiceadj(o,(char *)v->value))
3514 M_F("rxctcssadj",store_rxctcssadj(o,(char *)v->value))
3515 M_UINT("txctcssadj",o->txctcssadj);
3516 M_UINT("rxsquelchadj", o->rxsquelchadj)
3517 M_STR("devstr", o->devstr)
3521 ast_config_destroy(cfg1);
3522 } else ast_log(LOG_WARNING,"File %s not found, using default parameters.\n",fname);
3526 ast_mutex_lock(&o->eepromlock);
3529 ast_mutex_unlock(&o->eepromlock);
3531 ast_mutex_lock(&o->eepromlock);
3533 o->eepromctl = 1; /* request a load */
3534 ast_mutex_unlock(&o->eepromlock);
3536 /* if our specified one exists in the list */
3537 if ((!usb_list_check(o->devstr)) || find_desc_usb(o->devstr))
3541 for(s = usb_device_list; *s; s += strlen(s) + 1)
3543 if (!find_desc_usb(s)) break;
3547 ast_log(LOG_WARNING,"Unable to assign USB device for channel %s\n",o->name);
3550 ast_log(LOG_NOTICE,"Assigned USB device %s to usbradio channel %s\n",s,o->name);
3551 strcpy(o->devstr,s);
3554 i = usb_get_usbdev(o->devstr);
3557 ast_log(LOG_ERROR,"Not able to find alsa USB device\n");
3562 o->micmax = amixer_max(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL);
3563 o->spkrmax = amixer_max(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL);
3564 o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */
3565 o->dsp = ast_dsp_new();
3569 ast_dsp_set_features(o->dsp,DSP_FEATURE_DIGIT_DETECT);
3570 ast_dsp_set_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
3572 ast_dsp_set_features(o->dsp,DSP_FEATURE_DTMF_DETECT);
3573 ast_dsp_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
3577 if(o->pmrChan==NULL)
3581 // ast_log(LOG_NOTICE,"createPmrChannel() %s\n",o->name);
3582 memset(&tChan,0,sizeof(t_pmr_chan));
3584 tChan.pTxCodeDefault = o->txctcssdefault;
3585 tChan.pRxCodeSrc = o->rxctcssfreqs;
3586 tChan.pTxCodeSrc = o->txctcssfreqs;
3588 tChan.rxDemod=o->rxdemod;
3589 tChan.rxCdType=o->rxcdtype;
3590 tChan.rxSqVoxAdj=o->rxsqvoxadj;
3595 tChan.txMixA = o->txmixa;
3596 tChan.txMixB = o->txmixb;
3598 tChan.rxCpuSaver=o->rxcpusaver;
3599 tChan.txCpuSaver=o->txcpusaver;
3601 tChan.b.rxpolarity=o->b.rxpolarity;
3602 tChan.b.txpolarity=o->b.txpolarity;
3604 tChan.b.dcsrxpolarity=o->b.dcsrxpolarity;
3605 tChan.b.dcstxpolarity=o->b.dcstxpolarity;
3607 tChan.b.lsdrxpolarity=o->b.lsdrxpolarity;
3608 tChan.b.lsdtxpolarity=o->b.lsdtxpolarity;
3610 tChan.tracetype=o->tracetype;
3611 tChan.tracelevel=o->tracelevel;
3612 tChan.rptnum=o->rptnum;
3613 tChan.idleinterval=o->idleinterval;
3614 tChan.turnoffs=o->turnoffs;
3619 o->pmrChan=createPmrChannel(&tChan,FRAME_SIZE);
3621 o->pmrChan->radioDuplex=o->radioduplex;
3622 o->pmrChan->b.loopback=0;