Merged revisions 291758 via svnmerge from
[asterisk/asterisk.git] / channels / chan_usbradio.c
1 #define NEW_ASTERISK
2 /*
3  * Asterisk -- An open source telephony toolkit.
4  *
5  * Copyright (C) 1999 - 2005, Digium, Inc.
6  * Copyright (C) 2007 - 2008, Jim Dixon
7  *
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
11  *
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.
17  *
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.
21  */
22
23 /*! \file
24  *
25  * \brief Channel driver for CM108 USB Cards with Radio Interface
26  *
27  * \author Jim Dixon  <jim@lambdatel.com>
28  * \author Steve Henke  <w9sh@arrl.net>
29  *
30  * \par See also
31  * \arg \ref Config_usbradio
32  *
33  * \ingroup channel_drivers
34  */
35
36 /*** MODULEINFO
37         <depend>oss</depend>
38         <depend>alsa</depend>
39         <depend>usb</depend>
40         <defaultenabled>no</defaultenabled>
41  ***/
42
43 /*** MAKEOPTS
44 <category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes">
45         <member name="RADIO_RTX" displayname="Build RTX/DTX Radio Programming" touch_on_change="channels/chan_usbradio.c channels/xpmr/xpmr.h">
46                 <defaultenabled>no</defaultenabled>
47                 <depend>chan_usbradio</depend>
48         </member>
49         <member name="RADIO_XPMRX" displayname="Build Experimental Radio Protocols" touch_on_change="channels/chan_usbradio.c">
50                 <defaultenabled>no</defaultenabled>
51                 <depend>chan_usbradio</depend>
52         </member>
53 </category>
54  ***/
55
56 // 20070918 1600 EDT sph@xelatec.com changing to rx driven streams
57
58 #include "asterisk.h"
59
60 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
61
62 #include <stdio.h>
63 #include <ctype.h>
64 #include <math.h>
65 #include <string.h>
66 #include <unistd.h>
67 #ifdef HAVE_SYS_IO_H
68 #include <sys/io.h>
69 #endif
70 #include <sys/ioctl.h>
71 #include <fcntl.h>
72 #include <sys/time.h>
73 #include <stdlib.h>
74 #include <errno.h>
75 #include <usb.h>
76 #include <alsa/asoundlib.h>
77
78 //#define HAVE_XPMRX                            1
79 #ifdef RADIO_XPMRX
80 #define HAVE_XPMRX                              1
81 #endif
82
83 #define CHAN_USBRADIO           1
84 #define DEBUG_USBRADIO          0       
85 #define DEBUG_CAPTURES                  1
86 #define DEBUG_CAP_RX_OUT                0               
87 #define DEBUG_CAP_TX_OUT            0                   
88 #define DEBUG_FILETEST                  0                        
89
90 #define RX_CAP_RAW_FILE                 "/tmp/rx_cap_in.pcm"
91 #define RX_CAP_TRACE_FILE               "/tmp/rx_trace.pcm"
92 #define RX_CAP_OUT_FILE                 "/tmp/rx_cap_out.pcm"
93
94 #define TX_CAP_RAW_FILE                 "/tmp/tx_cap_in.pcm"
95 #define TX_CAP_TRACE_FILE               "/tmp/tx_trace.pcm"
96 #define TX_CAP_OUT_FILE                 "/tmp/tx_cap_out.pcm"
97
98 #define MIXER_PARAM_MIC_PLAYBACK_SW "Mic Playback Switch"
99 #define MIXER_PARAM_MIC_PLAYBACK_VOL "Mic Playback Volume"
100 #define MIXER_PARAM_MIC_CAPTURE_SW "Mic Capture Switch"
101 #define MIXER_PARAM_MIC_CAPTURE_VOL "Mic Capture Volume"
102 #define MIXER_PARAM_MIC_BOOST "Auto Gain Control"
103 #define MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
104 #define MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
105
106 #define DELIMCHR ','
107 #define QUOTECHR 34
108
109 #define READERR_THRESHOLD 50
110
111 #include "./xpmr/xpmr.h"
112 #ifdef HAVE_XPMRX
113 #include "./xpmrx/xpmrx.h"
114 #include "./xpmrx/bitweight.h"
115 #endif
116
117 #if 0
118 #define traceusb1(a) {printf a;}
119 #else
120 #define traceusb1(a)
121 #endif
122
123 #if 0
124 #define traceusb2(a) {printf a;}
125 #else
126 #define traceusb2(a)
127 #endif
128
129 #ifdef __linux
130 #include <linux/soundcard.h>
131 #elif defined(__FreeBSD__)
132 #include <sys/soundcard.h>
133 #else
134 #include <soundcard.h>
135 #endif
136
137 #include "asterisk/lock.h"
138 #include "asterisk/frame.h"
139 #include "asterisk/logger.h"
140 #include "asterisk/callerid.h"
141 #include "asterisk/channel.h"
142 #include "asterisk/module.h"
143 #include "asterisk/options.h"
144 #include "asterisk/pbx.h"
145 #include "asterisk/config.h"
146 #include "asterisk/cli.h"
147 #include "asterisk/utils.h"
148 #include "asterisk/causes.h"
149 #include "asterisk/endian.h"
150 #include "asterisk/stringfields.h"
151 #include "asterisk/abstract_jb.h"
152 #include "asterisk/musiconhold.h"
153 #include "asterisk/dsp.h"
154
155 #ifndef NEW_ASTERISK
156
157 /* ringtones we use */
158 #include "busy.h"
159 #include "ringtone.h"
160 #include "ring10.h"
161 #include "answer.h"
162
163 #endif
164
165 #define C108_VENDOR_ID          0x0d8c
166 #define C108_PRODUCT_ID         0x000c
167 #define C108_HID_INTERFACE      3
168
169 #define HID_REPORT_GET          0x01
170 #define HID_REPORT_SET          0x09
171
172 #define HID_RT_INPUT            0x01
173 #define HID_RT_OUTPUT           0x02
174
175 #define EEPROM_START_ADDR       6
176 #define EEPROM_END_ADDR         63
177 #define EEPROM_PHYSICAL_LEN     64
178 #define EEPROM_TEST_ADDR        EEPROM_END_ADDR
179 #define EEPROM_MAGIC_ADDR       6
180 #define EEPROM_MAGIC            34329
181 #define EEPROM_CS_ADDR          62
182 #define EEPROM_RXMIXERSET       8
183 #define EEPROM_TXMIXASET        9
184 #define EEPROM_TXMIXBSET        10
185 #define EEPROM_RXVOICEADJ       11
186 #define EEPROM_RXCTCSSADJ       13
187 #define EEPROM_TXCTCSSADJ       15
188 #define EEPROM_RXSQUELCHADJ     16
189
190 /*! Global jitterbuffer configuration - by default, jb is disabled */
191 static struct ast_jb_conf default_jbconf =
192 {
193         .flags = 0,
194         .max_size = -1,
195         .resync_threshold = -1,
196         .impl = "",
197         .target_extra = -1,
198 };
199 static struct ast_jb_conf global_jbconf;
200
201 /*
202  * usbradio.conf parameters are
203 START_CONFIG
204
205 [general]
206     ; General config options which propigate to all devices, with
207     ; default values shown. You may have as many devices as the
208     ; system will allow. You must use one section per device, with
209     ; [usb] generally (although its up to you) being the first device.
210     ;
211     ;
212     ; debug = 0x0               ; misc debug flags, default is 0
213
214         ; Set the device to use for I/O
215         ; devicenum = 0
216         ; Set hardware type here
217         ; hdwtype=0               ; 0=limey, 1=sph
218
219         ; rxboost=0          ; no rx gain boost
220         ; rxctcssrelax=1        ; reduce talkoff from radios w/o CTCSS Tx HPF
221         ; rxctcssfreqs=100.0,123.0      ; list of rx ctcss freq in floating point. must be in table
222         ; txctcssfreqs=100.0,123.0      ; list tx ctcss freq, any frequency permitted
223         ; txctcssdefault=100.0      ; default tx ctcss freq, any frequency permitted
224
225         ; carrierfrom=dsp     ;no,usb,usbinvert,dsp,vox
226         ; ctcssfrom=dsp       ;no,usb,dsp
227
228         ; rxdemod=flat            ; input type from radio: no,speaker,flat
229         ; txprelim=yes            ; output is pre-emphasised and limited
230         ; txtoctype=no            ; no,phase,notone
231
232         ; txmixa=composite        ;no,voice,tone,composite,auxvoice
233         ; txmixb=no               ;no,voice,tone,composite,auxvoice
234
235         ; invertptt=0
236
237     ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
238     ; jbenable = yes              ; Enables the use of a jitterbuffer on the receiving side of an
239                                   ; USBRADIO channel. Defaults to "no". An enabled jitterbuffer will
240                                   ; be used only if the sending side can create and the receiving
241                                   ; side can not accept jitter. The USBRADIO channel can't accept jitter,
242                                   ; thus an enabled jitterbuffer on the receive USBRADIO side will always
243                                   ; be used if the sending side can create jitter.
244
245     ; jbmaxsize = 200             ; Max length of the jitterbuffer in milliseconds.
246
247     ; jbresyncthreshold = 1000    ; Jump in the frame timestamps over which the jitterbuffer is
248                                   ; resynchronized. Useful to improve the quality of the voice, with
249                                   ; big jumps in/broken timestamps, usualy sent from exotic devices
250                                   ; and programs. Defaults to 1000.
251
252     ; jbimpl = fixed              ; Jitterbuffer implementation, used on the receiving side of an USBRADIO
253                                   ; channel. Two implementations are currenlty available - "fixed"
254                                   ; (with size always equals to jbmax-size) and "adaptive" (with
255                                   ; variable size, actually the new jb of IAX2). Defaults to fixed.
256
257     ; jblog = no                  ; Enables jitterbuffer frame logging. Defaults to "no".
258     ;-----------------------------------------------------------------------------------
259
260 [usb]
261
262 ; First channel unique config
263
264 [usb1]
265
266 ; Second channel config
267
268 END_CONFIG
269
270  */
271
272 /*
273  * Helper macros to parse config arguments. They will go in a common
274  * header file if their usage is globally accepted. In the meantime,
275  * we define them here. Typical usage is as below.
276  * Remember to open a block right before M_START (as it declares
277  * some variables) and use the M_* macros WITHOUT A SEMICOLON:
278  *
279  *      {
280  *              M_START(v->name, v->value) 
281  *
282  *              M_BOOL("dothis", x->flag1)
283  *              M_STR("name", x->somestring)
284  *              M_F("bar", some_c_code)
285  *              M_END(some_final_statement)
286  *              ... other code in the block
287  *      }
288  *
289  * XXX NOTE these macros should NOT be replicated in other parts of asterisk. 
290  * Likely we will come up with a better way of doing config file parsing.
291  */
292 #define M_START(var, val) \
293         char *__s = var; char *__val = val;
294 #define M_END(x)   x;
295 #define M_F(tag, f)                     if (!strcasecmp((__s), tag)) { f; } else
296 #define M_BOOL(tag, dst)        M_F(tag, (dst) = ast_true(__val) )
297 #define M_UINT(tag, dst)        M_F(tag, (dst) = strtoul(__val, NULL, 0) )
298 #define M_STR(tag, dst)         M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
299
300 /*
301  * The following parameters are used in the driver:
302  *
303  *  FRAME_SIZE  the size of an audio frame, in samples.
304  *              160 is used almost universally, so you should not change it.
305  *
306  *  FRAGS       the argument for the SETFRAGMENT ioctl.
307  *              Overridden by the 'frags' parameter in usbradio.conf
308  *
309  *              Bits 0-7 are the base-2 log of the device's block size,
310  *              bits 16-31 are the number of blocks in the driver's queue.
311  *              There are a lot of differences in the way this parameter
312  *              is supported by different drivers, so you may need to
313  *              experiment a bit with the value.
314  *              A good default for linux is 30 blocks of 64 bytes, which
315  *              results in 6 frames of 320 bytes (160 samples).
316  *              FreeBSD works decently with blocks of 256 or 512 bytes,
317  *              leaving the number unspecified.
318  *              Note that this only refers to the device buffer size,
319  *              this module will then try to keep the lenght of audio
320  *              buffered within small constraints.
321  *
322  *  QUEUE_SIZE  The max number of blocks actually allowed in the device
323  *              driver's buffer, irrespective of the available number.
324  *              Overridden by the 'queuesize' parameter in usbradio.conf
325  *
326  *              Should be >=2, and at most as large as the hw queue above
327  *              (otherwise it will never be full).
328  */
329
330 #define FRAME_SIZE      160
331 #define QUEUE_SIZE      2                               
332
333 #if defined(__FreeBSD__)
334 #define FRAGS   0x8
335 #else
336 #define FRAGS   ( ( (6 * 5) << 16 ) | 0xc )
337 #endif
338
339 /*
340  * XXX text message sizes are probably 256 chars, but i am
341  * not sure if there is a suitable definition anywhere.
342  */
343 #define TEXT_SIZE       256
344
345 #if 0
346 #define TRYOPEN 1                               /* try to open on startup */
347 #endif
348 #define O_CLOSE 0x444                   /* special 'close' mode for device */
349 /* Which device to use */
350 #if defined( __OpenBSD__ ) || defined( __NetBSD__ )
351 #define DEV_DSP "/dev/audio"
352 #else
353 #define DEV_DSP "/dev/dsp"
354 #endif
355
356 static const char *config = "usbradio.conf";    /* default config file */
357 #define config1 "usbradio_tune_%s.conf"    /* tune config file */
358
359 static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
360 static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
361
362 static char *usb_device_list = NULL;
363 static int usb_device_list_size = 0;
364
365 static int usbradio_debug;
366 #if 0 //maw asdf sph
367 static int usbradio_debug_level = 0;
368 #endif
369
370 enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
371 enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
372 enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR};                                   // no,external,externalinvert,software
373 enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
374 enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
375 enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
376
377 /*      DECLARE STRUCTURES */
378
379 /*
380  * Each sound is made of 'datalen' samples of sound, repeated as needed to
381  * generate 'samplen' samples of data, then followed by 'silencelen' samples
382  * of silence. The loop is repeated if 'repeat' is set.
383  */
384 struct sound {
385         int ind;
386         char *desc;
387         short *data;
388         int datalen;
389         int samplen;
390         int silencelen;
391         int repeat;
392 };
393
394 #ifndef NEW_ASTERISK
395
396 static struct sound sounds[] = {
397         { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
398         { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
399         { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
400         { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
401         { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
402         { -1, NULL, 0, 0, 0, 0 },       /* end marker */
403 };
404
405 #endif
406
407 /*
408  * descriptor for one of our channels.
409  * There is one used for 'default' values (from the [general] entry in
410  * the configuration file), and then one instance for each device
411  * (the default is cloned from [general], others are only created
412  * if the relevant section exists).
413  */
414 struct chan_usbradio_pvt {
415         struct chan_usbradio_pvt *next;
416
417         char *name;
418 #ifndef NEW_ASTERISK
419         /*
420          * cursound indicates which in struct sound we play. -1 means nothing,
421          * any other value is a valid sound, in which case sampsent indicates
422          * the next sample to send in [0..samplen + silencelen]
423          * nosound is set to disable the audio data from the channel
424          * (so we can play the tones etc.).
425          */
426         int sndcmd[2];                          /* Sound command pipe */
427         int cursound;                           /* index of sound to send */
428         int sampsent;                           /* # of sound samples sent  */
429         int nosound;                            /* set to block audio from the PBX */
430 #endif
431
432         int pttkick[2];
433         int total_blocks;                       /* total blocks in the output device */
434         int sounddev;
435         enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
436         i16 cdMethod;
437         int autoanswer;
438         int autohangup;
439         int hookstate;
440         unsigned int queuesize;         /* max fragments in queue */
441         unsigned int frags;                     /* parameter for SETFRAGMENT */
442
443         int warned;                                     /* various flags used for warnings */
444 #define WARN_used_blocks        1
445 #define WARN_speed              2
446 #define WARN_frag               4
447         int w_errors;                           /* overfull in the write path */
448         struct timeval lastopen;
449
450         int overridecontext;
451         int mute;
452
453         /* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
454          * be representable in 16 bits to avoid overflows.
455          */
456 #define BOOST_SCALE     (1<<9)
457 #define BOOST_MAX       40                      /* slightly less than 7 bits */
458         int boost;                                      /* input boost, scaled by BOOST_SCALE */
459         char devicenum;
460         char devstr[128];
461         int spkrmax;
462         int micmax;
463
464 #ifndef NEW_ASTERISK
465         pthread_t sthread;
466 #endif
467         pthread_t hidthread;
468
469         int stophid;
470         FILE *hkickhid;
471
472         struct ast_channel *owner;
473         char ext[AST_MAX_EXTENSION];
474         char ctx[AST_MAX_CONTEXT];
475         char language[MAX_LANGUAGE];
476         char cid_name[256];                     /*XXX */
477         char cid_num[256];                      /*XXX */
478         char mohinterpret[MAX_MUSICCLASS];
479
480         /* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */
481         char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];    
482         char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6];
483
484         int usbradio_write_dst;
485         /* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
486          * plus enough room for a full frame
487          */
488         char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
489         char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
490         int readpos;                            /* read position above */
491         struct ast_frame read_f;        /* returned by usbradio_read */
492
493         char    debuglevel;
494         char    radioduplex;                    // 
495         char    wanteeprom;
496
497         int     tracetype;
498         int     tracelevel;
499         char    area;
500         char    rptnum;
501         int     idleinterval;
502         int             turnoffs;
503         int     txsettletime;
504         char    ukey[48];
505
506         char lastrx;
507         char rxhidsq;
508         char rxcarrierdetect;           // status from pmr channel
509         char rxctcssdecode;                     // status from pmr channel
510
511         int  rxdcsdecode;
512         int  rxlsddecode;
513
514         char rxkeytype;
515         char rxkeyed;                           // indicates rx signal present
516
517         char lasttx;
518         char txkeyed;                           // tx key request from upper layers 
519         char txchankey;
520         char txtestkey;
521
522         time_t lasthidtime;
523     struct ast_dsp *dsp;
524
525         t_pmr_chan      *pmrChan;
526
527         char    rxcpusaver;
528         char    txcpusaver;
529
530         char    rxdemod;
531         float   rxgain;
532         char    rxcdtype;
533         char    rxsdtype;
534         int             rxsquelchadj;   /* this copy needs to be here for initialization */
535         int     rxsqvoxadj;
536         char    txtoctype;
537
538         char    txprelim;
539         float   txctcssgain;
540         char    txmixa;
541         char    txmixb;
542
543         char    invertptt;
544
545         char    rxctcssrelax;
546         float   rxctcssgain;
547
548         char    txctcssdefault[16];                             // for repeater operation
549         char    rxctcssfreqs[512];                              // a string
550         char    txctcssfreqs[512];
551
552         char    txctcssfreq[32];                                // encode now
553         char    rxctcssfreq[32];                                // decode now
554
555         char    numrxctcssfreqs;                                // how many
556         char    numtxctcssfreqs;
557
558         char    *rxctcss[CTCSS_NUM_CODES];              // pointers to strings
559         char    *txctcss[CTCSS_NUM_CODES];
560
561         int     txfreq;                                                 // in Hz
562         int     rxfreq;
563
564         //              start remote operation info
565         char    set_txctcssdefault[16];                         // for remote operation
566         char    set_txctcssfreq[16];                            // encode now
567         char    set_rxctcssfreq[16];                            // decode now
568
569         char    set_numrxctcssfreqs;                            // how many
570         char    set_numtxctcssfreqs;
571
572         char    set_rxctcssfreqs[16];                           // a string
573         char    set_txctcssfreqs[16];
574
575         char    *set_rxctcss;                                       // pointers to strings
576         char    *set_txctcss;
577
578         int     set_txfreq;                                                     // in Hz
579         int     set_rxfreq;
580         //              end remote operation info
581
582         int             rxmixerset;             
583         int     rxboostset;
584         float   rxvoiceadj;
585         float   rxctcssadj;
586         int     txmixaset;
587         int     txmixbset;
588         int     txctcssadj;
589
590         int     hdwtype;
591         int             hid_gpio_ctl;           
592         int             hid_gpio_ctl_loc;       
593         int             hid_io_cor;             
594         int             hid_io_cor_loc;         
595         int             hid_io_ctcss;           
596         int             hid_io_ctcss_loc;       
597         int             hid_io_ptt;             
598         int             hid_gpio_loc;           
599
600         struct {
601             unsigned rxcapraw:1;
602                 unsigned txcapraw:1;
603                 unsigned txcap2:1;
604                 unsigned rxcap2:1;
605                 unsigned rxplmon:1;
606                 unsigned remoted:1;
607                 unsigned txpolarity:1;
608                 unsigned rxpolarity:1;
609                 unsigned dcstxpolarity:1;
610                 unsigned dcsrxpolarity:1;
611                 unsigned lsdtxpolarity:1;
612                 unsigned lsdrxpolarity:1;
613                 unsigned loopback:1;
614                 unsigned radioactive:1;
615         }b;
616         unsigned short eeprom[EEPROM_PHYSICAL_LEN];
617         char eepromctl;
618         ast_mutex_t eepromlock;
619
620         struct usb_dev_handle *usb_handle;
621         int readerrs;
622 };
623
624 // maw add additional defaults !!!
625 static struct chan_usbradio_pvt usbradio_default = {
626 #ifndef NEW_ASTERISK
627         .cursound = -1,
628 #endif
629         .sounddev = -1,
630         .duplex = M_UNSET,                      /* XXX check this */
631         .autoanswer = 1,
632         .autohangup = 1,
633         .queuesize = QUEUE_SIZE,
634         .frags = FRAGS,
635         .ext = "s",
636         .ctx = "default",
637         .readpos = AST_FRIENDLY_OFFSET, /* start here on reads */
638         .lastopen = { 0, 0 },
639         .boost = BOOST_SCALE,
640         .wanteeprom = 1,
641         .area = 0,
642         .rptnum = 0,
643 };
644
645 /*      DECLARE FUNCTION PROTOTYPES     */
646
647 static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s);
648 static int      hidhdwconfig(struct chan_usbradio_pvt *o);
649 static int set_txctcss_level(struct chan_usbradio_pvt *o);
650 static void pmrdump(struct chan_usbradio_pvt *o);
651 static void mult_set(struct chan_usbradio_pvt *o);
652 static int  mult_calc(int value);
653 static void mixer_write(struct chan_usbradio_pvt *o);
654 static void tune_rxinput(int fd, struct chan_usbradio_pvt *o);
655 static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o);
656 static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o);
657 static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd);
658 static void tune_write(struct chan_usbradio_pvt *o);
659
660 static char *usbradio_active;    /* the active device */
661
662 static int setformat(struct chan_usbradio_pvt *o, int mode);
663
664 static struct ast_channel *usbradio_request(const char *type, format_t format,
665                 const struct ast_channel *requestor,
666                 void *data, int *cause);
667 static int usbradio_digit_begin(struct ast_channel *c, char digit);
668 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration);
669 static int usbradio_text(struct ast_channel *c, const char *text);
670 static int usbradio_hangup(struct ast_channel *c);
671 static int usbradio_answer(struct ast_channel *c);
672 static struct ast_frame *usbradio_read(struct ast_channel *chan);
673 static int usbradio_call(struct ast_channel *c, char *dest, int timeout);
674 static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
675 static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
676 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
677 static int xpmr_config(struct chan_usbradio_pvt *o);
678
679 #if     DEBUG_FILETEST == 1
680 static int RxTestIt(struct chan_usbradio_pvt *o);
681 #endif
682
683 static char tdesc[] = "USB (CM108) Radio Channel Driver";
684
685 static const struct ast_channel_tech usbradio_tech = {
686         .type = "Radio",
687         .description = tdesc,
688         .capabilities = AST_FORMAT_SLINEAR,
689         .requester = usbradio_request,
690         .send_digit_begin = usbradio_digit_begin,
691         .send_digit_end = usbradio_digit_end,
692         .send_text = usbradio_text,
693         .hangup = usbradio_hangup,
694         .answer = usbradio_answer,
695         .read = usbradio_read,
696         .call = usbradio_call,
697         .write = usbradio_write,
698         .indicate = usbradio_indicate,
699         .fixup = usbradio_fixup,
700 };
701
702 /* Call with:  devnum: alsa major device number, param: ascii Formal
703 Parameter Name, val1, first or only value, val2 second value, or 0 
704 if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
705
706 Note: must add -lasound to end of linkage */
707
708 static int amixer_max(int devnum,char *param)
709 {
710 int     rv,type;
711 char    str[100];
712 snd_hctl_t *hctl;
713 snd_ctl_elem_id_t *id;
714 snd_hctl_elem_t *elem;
715 snd_ctl_elem_info_t *info;
716
717         sprintf(str,"hw:%d",devnum);
718         if (snd_hctl_open(&hctl, str, 0)) return(-1);
719         snd_hctl_load(hctl);
720         snd_ctl_elem_id_alloca(&id);
721         snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
722         snd_ctl_elem_id_set_name(id, param);  
723         elem = snd_hctl_find_elem(hctl, id);
724         if (!elem)
725         {
726                 snd_hctl_close(hctl);
727                 return(-1);
728         }
729         snd_ctl_elem_info_alloca(&info);
730         snd_hctl_elem_info(elem,info);
731         type = snd_ctl_elem_info_get_type(info);
732         rv = 0;
733         switch(type)
734         {
735             case SND_CTL_ELEM_TYPE_INTEGER:
736                 rv = snd_ctl_elem_info_get_max(info);
737                 break;
738             case SND_CTL_ELEM_TYPE_BOOLEAN:
739                 rv = 1;
740                 break;
741         }
742         snd_hctl_close(hctl);
743         return(rv);
744 }
745
746 /* Call with:  devnum: alsa major device number, param: ascii Formal
747 Parameter Name, val1, first or only value, val2 second value, or 0 
748 if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
749
750 Note: must add -lasound to end of linkage */
751
752 static int setamixer(int devnum,char *param, int v1, int v2)
753 {
754 int     type;
755 char    str[100];
756 snd_hctl_t *hctl;
757 snd_ctl_elem_id_t *id;
758 snd_ctl_elem_value_t *control;
759 snd_hctl_elem_t *elem;
760 snd_ctl_elem_info_t *info;
761
762         sprintf(str,"hw:%d",devnum);
763         if (snd_hctl_open(&hctl, str, 0)) return(-1);
764         snd_hctl_load(hctl);
765         snd_ctl_elem_id_alloca(&id);
766         snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
767         snd_ctl_elem_id_set_name(id, param);  
768         elem = snd_hctl_find_elem(hctl, id);
769         if (!elem)
770         {
771                 snd_hctl_close(hctl);
772                 return(-1);
773         }
774         snd_ctl_elem_info_alloca(&info);
775         snd_hctl_elem_info(elem,info);
776         type = snd_ctl_elem_info_get_type(info);
777         snd_ctl_elem_value_alloca(&control);
778         snd_ctl_elem_value_set_id(control, id);    
779         switch(type)
780         {
781             case SND_CTL_ELEM_TYPE_INTEGER:
782                 snd_ctl_elem_value_set_integer(control, 0, v1);
783                 if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2);
784                 break;
785             case SND_CTL_ELEM_TYPE_BOOLEAN:
786                 snd_ctl_elem_value_set_integer(control, 0, (v1 != 0));
787                 break;
788         }
789         if (snd_hctl_elem_write(elem, control))
790         {
791                 snd_hctl_close(hctl);
792                 return(-1);
793         }
794         snd_hctl_close(hctl);
795         return(0);
796 }
797
798 static void hid_set_outputs(struct usb_dev_handle *handle,
799          unsigned char *outputs)
800 {
801         usleep(1500);
802         usb_control_msg(handle,
803               USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
804               HID_REPORT_SET,
805               0 + (HID_RT_OUTPUT << 8),
806               C108_HID_INTERFACE,
807               (char*)outputs, 4, 5000);
808 }
809
810 static void hid_get_inputs(struct usb_dev_handle *handle,
811          unsigned char *inputs)
812 {
813         usleep(1500);
814         usb_control_msg(handle,
815               USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
816               HID_REPORT_GET,
817               0 + (HID_RT_INPUT << 8),
818               C108_HID_INTERFACE,
819               (char*)inputs, 4, 5000);
820 }
821
822 static unsigned short read_eeprom(struct usb_dev_handle *handle, int addr)
823 {
824         unsigned char buf[4];
825
826         buf[0] = 0x80;
827         buf[1] = 0;
828         buf[2] = 0;
829         buf[3] = 0x80 | (addr & 0x3f);
830         hid_set_outputs(handle,buf);
831         memset(buf,0,sizeof(buf));
832         hid_get_inputs(handle,buf);
833         return(buf[1] + (buf[2] << 8));
834 }
835
836 static void write_eeprom(struct usb_dev_handle *handle, int addr, 
837    unsigned short data)
838 {
839
840         unsigned char buf[4];
841
842         buf[0] = 0x80;
843         buf[1] = data & 0xff;
844         buf[2] = data >> 8;
845         buf[3] = 0xc0 | (addr & 0x3f);
846         hid_set_outputs(handle,buf);
847 }
848
849 static unsigned short get_eeprom(struct usb_dev_handle *handle,
850         unsigned short *buf)
851 {
852 int     i;
853 unsigned short cs;
854
855         cs = 0xffff;
856         for(i = EEPROM_START_ADDR; i < EEPROM_END_ADDR; i++)
857         {
858                 cs += buf[i] = read_eeprom(handle,i);
859         }
860         return(cs);
861 }
862
863 static void put_eeprom(struct usb_dev_handle *handle,unsigned short *buf)
864 {
865 int     i;
866 unsigned short cs;
867
868         cs = 0xffff;
869         buf[EEPROM_MAGIC_ADDR] = EEPROM_MAGIC;
870         for(i = EEPROM_START_ADDR; i < EEPROM_CS_ADDR; i++)
871         {
872                 write_eeprom(handle,i,buf[i]);
873                 cs += buf[i];
874         }
875         buf[EEPROM_CS_ADDR] = (65535 - cs) + 1;
876         write_eeprom(handle,i,buf[EEPROM_CS_ADDR]);
877 }
878
879 static struct usb_device *hid_device_init(char *desired_device)
880 {
881     struct usb_bus *usb_bus;
882     struct usb_device *dev;
883     char devstr[200],str[200],desdev[200],*cp;
884     int i;
885     FILE *fp;
886
887     usb_init();
888     usb_find_busses();
889     usb_find_devices();
890     for (usb_bus = usb_busses;
891          usb_bus;
892          usb_bus = usb_bus->next) {
893         for (dev = usb_bus->devices;
894              dev;
895              dev = dev->next) {
896             if ((dev->descriptor.idVendor
897                   == C108_VENDOR_ID) &&
898                 (dev->descriptor.idProduct
899                   == C108_PRODUCT_ID))
900                 {
901                         sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
902                         for(i = 0; i < 32; i++)
903                         {
904                                 sprintf(str,"/proc/asound/card%d/usbbus",i);
905                                 fp = fopen(str,"r");
906                                 if (!fp) continue;
907                                 if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
908                                 {
909                                         fclose(fp);
910                                         continue;
911                                 }
912                                 fclose(fp);
913                                 if (desdev[strlen(desdev) - 1] == '\n')
914                                         desdev[strlen(desdev) -1 ] = 0;
915                                 if (strcasecmp(desdev,devstr)) continue;
916                                 if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
917                                 else strcpy(str,"/sys/class/sound/dsp/device");
918                                 memset(desdev,0,sizeof(desdev));
919                                 if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
920                                 {
921                                         sprintf(str,"/sys/class/sound/controlC%d/device",i);
922                                         memset(desdev,0,sizeof(desdev));
923                                         if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
924                                 }
925                                 cp = strrchr(desdev,'/');
926                                 if (cp) *cp = 0; else continue;
927                                 cp = strrchr(desdev,'/');
928                                 if (!cp) continue;
929                                 cp++;
930                                 break;
931                         }
932                         if (i >= 32) continue;
933                         if (!strcmp(cp,desired_device)) return dev;
934                 }
935
936         }
937     }
938     return NULL;
939 }
940
941 static int hid_device_mklist(void)
942 {
943     struct usb_bus *usb_bus;
944     struct usb_device *dev;
945     char devstr[200],str[200],desdev[200],*cp;
946     int i;
947     FILE *fp;
948
949     usb_device_list = ast_malloc(2);
950     if (!usb_device_list) return -1;
951     memset(usb_device_list,0,2);
952
953     usb_init();
954     usb_find_busses();
955     usb_find_devices();
956     for (usb_bus = usb_busses;
957          usb_bus;
958          usb_bus = usb_bus->next) {
959         for (dev = usb_bus->devices;
960              dev;
961              dev = dev->next) {
962             if ((dev->descriptor.idVendor
963                   == C108_VENDOR_ID) &&
964                 (dev->descriptor.idProduct
965                   == C108_PRODUCT_ID))
966                 {
967                         sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
968                         for(i = 0;i < 32; i++)
969                         {
970                                 sprintf(str,"/proc/asound/card%d/usbbus",i);
971                                 fp = fopen(str,"r");
972                                 if (!fp) continue;
973                                 if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
974                                 {
975                                         fclose(fp);
976                                         continue;
977                                 }
978                                 fclose(fp);
979                                 if (desdev[strlen(desdev) - 1] == '\n')
980                                         desdev[strlen(desdev) -1 ] = 0;
981                                 if (strcasecmp(desdev,devstr)) continue;
982                                 if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
983                                 else strcpy(str,"/sys/class/sound/dsp/device");
984                                 memset(desdev,0,sizeof(desdev));
985                                 if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
986                                 {
987                                         sprintf(str,"/sys/class/sound/controlC%d/device",i);
988                                         memset(desdev,0,sizeof(desdev));
989                                         if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
990                                 }
991                                 cp = strrchr(desdev,'/');
992                                 if (cp) *cp = 0; else continue;
993                                 cp = strrchr(desdev,'/');
994                                 if (!cp) continue;
995                                 cp++;
996                                 break;
997                         }
998                         if (i >= 32) return -1;
999                         usb_device_list = ast_realloc(usb_device_list,
1000                                 usb_device_list_size + 2 +
1001                                         strlen(cp));
1002                         if (!usb_device_list) return -1;
1003                         usb_device_list_size += strlen(cp) + 2;
1004                         i = 0;
1005                         while(usb_device_list[i])
1006                         {
1007                                 i += strlen(usb_device_list + i) + 1;
1008                         }
1009                         strcat(usb_device_list + i,cp);
1010                         usb_device_list[strlen(cp) + i + 1] = 0;
1011                 }
1012
1013         }
1014     }
1015     return 0;
1016 }
1017
1018 /* returns internal formatted string from external one */
1019 static int usb_get_usbdev(char *devstr)
1020 {
1021 int     i;
1022 char    str[200],desdev[200],*cp;
1023
1024         for(i = 0;i < 32; i++)
1025         {
1026                 if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
1027                 else strcpy(str,"/sys/class/sound/dsp/device");
1028                 memset(desdev,0,sizeof(desdev));
1029                 if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
1030                 {
1031                         sprintf(str,"/sys/class/sound/controlC%d/device",i);
1032                         memset(desdev,0,sizeof(desdev));
1033                         if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
1034                 }
1035                 cp = strrchr(desdev,'/');
1036                 if (cp) *cp = 0; else continue;
1037                 cp = strrchr(desdev,'/');
1038                 if (!cp) continue;
1039                 cp++;
1040                 if (!strcasecmp(cp,devstr)) break;
1041         }
1042         if (i >= 32) return -1;
1043         return i;
1044
1045 }
1046
1047 static int usb_list_check(char *devstr)
1048 {
1049
1050 char *s = usb_device_list;
1051
1052         if (!s) return(0);
1053         while(*s)
1054         {
1055                 if (!strcasecmp(s,devstr)) return(1);
1056                 s += strlen(s) + 1;
1057         }
1058         return(0);
1059 }
1060
1061
1062 static int      hidhdwconfig(struct chan_usbradio_pvt *o)
1063 {
1064         if(o->hdwtype==1)         //sphusb
1065         {
1066                 o->hid_gpio_ctl         =  0x08;        /* set GPIO4 to output mode */
1067                 o->hid_gpio_ctl_loc     =  2;   /* For CTL of GPIO */
1068                 o->hid_io_cor           =  4;   /* GPIO3 is COR */
1069                 o->hid_io_cor_loc       =  1;   /* GPIO3 is COR */
1070                 o->hid_io_ctcss         =  2;   /* GPIO 2 is External CTCSS */
1071                 o->hid_io_ctcss_loc =  1;       /* is GPIO 2 */
1072                 o->hid_io_ptt           =  8;   /* GPIO 4 is PTT */
1073                 o->hid_gpio_loc         =  1;   /* For ALL GPIO */
1074         }
1075         else if(o->hdwtype==0)  //dudeusb
1076         {
1077                 o->hid_gpio_ctl         =  0x0c;        /* set GPIO 3 & 4 to output mode */
1078                 o->hid_gpio_ctl_loc     =  2;   /* For CTL of GPIO */
1079                 o->hid_io_cor           =  2;   /* VOLD DN is COR */
1080                 o->hid_io_cor_loc       =  0;   /* VOL DN COR */
1081                 o->hid_io_ctcss         =  2;   /* GPIO 2 is External CTCSS */
1082                 o->hid_io_ctcss_loc =  1;       /* is GPIO 2 */
1083                 o->hid_io_ptt           =  4;   /* GPIO 3 is PTT */
1084                 o->hid_gpio_loc         =  1;   /* For ALL GPIO */
1085         }
1086         else if(o->hdwtype==3)  // custom version
1087         {
1088                 o->hid_gpio_ctl         =  0x0c;        /* set GPIO 3 & 4 to output mode */
1089                 o->hid_gpio_ctl_loc     =  2;   /* For CTL of GPIO */
1090                 o->hid_io_cor           =  2;   /* VOLD DN is COR */
1091                 o->hid_io_cor_loc       =  0;   /* VOL DN COR */
1092                 o->hid_io_ctcss         =  2;   /* GPIO 2 is External CTCSS */
1093                 o->hid_io_ctcss_loc =  1;       /* is GPIO 2 */
1094                 o->hid_io_ptt           =  4;   /* GPIO 3 is PTT */
1095                 o->hid_gpio_loc         =  1;   /* For ALL GPIO */
1096         }
1097
1098         return 0;
1099 }
1100 /*
1101 */
1102 static void kickptt(struct chan_usbradio_pvt *o)
1103 {
1104         char c = 0;
1105         //printf("kickptt  %i  %i  %i\n",o->txkeyed,o->txchankey,o->txtestkey);
1106         if (!o) return;
1107         if (!o->pttkick) return;
1108         if (write(o->pttkick[1],&c,1) < 0) {
1109                 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
1110         }
1111 }
1112 /*
1113 */
1114 static void *hidthread(void *arg)
1115 {
1116         unsigned char buf[4],bufsave[4],keyed;
1117         char lastrx, txtmp;
1118         int res;
1119         struct usb_device *usb_dev;
1120         struct usb_dev_handle *usb_handle;
1121         struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
1122         struct pollfd pfd = { .events = POLLIN };
1123
1124         usb_dev = hid_device_init(o->devstr);
1125         if (usb_dev == NULL) {
1126                 ast_log(LOG_ERROR,"USB HID device not found\n");
1127                 pthread_exit(NULL);
1128         }
1129         usb_handle = usb_open(usb_dev);
1130         if (usb_handle == NULL) {
1131                 ast_log(LOG_ERROR,"Not able to open USB device\n");
1132                 pthread_exit(NULL);
1133         }
1134         if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0)
1135         {
1136             if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
1137                         ast_log(LOG_ERROR,"Not able to detach the USB device\n");
1138                         pthread_exit(NULL);
1139                 }
1140                 if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0) {
1141                         ast_log(LOG_ERROR,"Not able to claim the USB device\n");
1142                         pthread_exit(NULL);
1143                 }
1144         }
1145         memset(buf,0,sizeof(buf));
1146         buf[2] = o->hid_gpio_ctl;
1147         buf[1] = 0;
1148         hid_set_outputs(usb_handle,buf);
1149         memcpy(bufsave,buf,sizeof(buf));
1150         if (pipe(o->pttkick) == -1)
1151         {
1152             ast_log(LOG_ERROR,"Not able to create pipe\n");
1153                 pthread_exit(NULL);
1154         }
1155         traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
1156         lastrx = 0;
1157         // popen 
1158         while (!o->stophid) {
1159                 pfd.fd = o->pttkick[0];
1160                 pfd.revents = 0;
1161
1162                 res = ast_poll(&pfd, 1, 50);
1163                 if (res < 0) {
1164                         ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
1165                         usleep(10000);
1166                         continue;
1167                 }
1168                 if (pfd.revents & POLLIN) {
1169                         char c;
1170
1171                         if (read(o->pttkick[0], &c, 1) < 0) {
1172                                 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
1173                         }
1174                 }
1175                 if (o->wanteeprom) {
1176                         ast_mutex_lock(&o->eepromlock);
1177                         if (o->eepromctl == 1) { /* to read */
1178                                 /* if CS okay */
1179                                 if (!get_eeprom(usb_handle, o->eeprom)) {
1180                                         if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) {
1181                                                 ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name);
1182                                         } else {
1183                                                 o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
1184                                                 o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
1185                                                 o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
1186                                                 memcpy(&o->rxvoiceadj, &o->eeprom[EEPROM_RXVOICEADJ], sizeof(float));
1187                                                 memcpy(&o->rxctcssadj, &o->eeprom[EEPROM_RXCTCSSADJ], sizeof(float));
1188                                                 o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
1189                                                 o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
1190                                                 ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
1191                                         }
1192                                 } else {
1193                                         ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name);
1194                                 }
1195                                 hid_set_outputs(usb_handle,bufsave);
1196                         }
1197                         if (o->eepromctl == 2) { /* to write */
1198                                 put_eeprom(usb_handle,o->eeprom);
1199                                 hid_set_outputs(usb_handle,bufsave);
1200                                 ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name);
1201                         }
1202                         o->eepromctl = 0;
1203                         ast_mutex_unlock(&o->eepromlock);
1204                 }
1205                 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
1206                 hid_get_inputs(usb_handle,buf);
1207                 keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
1208                 if (keyed != o->rxhidsq) {
1209                         if (o->debuglevel) {
1210                                 printf("chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
1211                         }
1212                         o->rxhidsq=keyed;
1213                 }
1214
1215                 /* if change in tx state as controlled by xpmr */
1216                 txtmp = o->pmrChan->txPttOut;
1217
1218                 if (o->lasttx != txtmp) {
1219                         o->pmrChan->txPttHid = o->lasttx = txtmp;
1220                         if (o->debuglevel) {
1221                                 ast_debug(0, "hidthread: tx set to %d\n", txtmp);
1222                         }
1223                         buf[o->hid_gpio_loc] = 0;
1224                         if (!o->invertptt) {
1225                                 if (txtmp) {
1226                                         buf[o->hid_gpio_loc] = o->hid_io_ptt;
1227                                 }
1228                         } else {
1229                                 if (!txtmp) {
1230                                         buf[o->hid_gpio_loc] = o->hid_io_ptt;
1231                                 }
1232                         }
1233                         buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
1234                         memcpy(bufsave, buf, sizeof(buf));
1235                         hid_set_outputs(usb_handle, buf);
1236                 }
1237                 time(&o->lasthidtime);
1238         }
1239         buf[o->hid_gpio_loc] = 0;
1240         if (o->invertptt) {
1241                 buf[o->hid_gpio_loc] = o->hid_io_ptt;
1242         }
1243         buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
1244         hid_set_outputs(usb_handle, buf);
1245         pthread_exit(0);
1246 }
1247
1248 /*
1249  * returns a pointer to the descriptor with the given name
1250  */
1251 static struct chan_usbradio_pvt *find_desc(char *dev)
1252 {
1253         struct chan_usbradio_pvt *o = NULL;
1254
1255         if (!dev)
1256                 ast_log(LOG_WARNING, "null dev\n");
1257
1258         for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
1259         if (!o)
1260         {
1261                 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
1262         }
1263
1264         return o;
1265 }
1266
1267 static struct chan_usbradio_pvt *find_desc_usb(char *devstr)
1268 {
1269         struct chan_usbradio_pvt *o = NULL;
1270
1271         if (!devstr)
1272                 ast_log(LOG_WARNING, "null dev\n");
1273
1274         for (o = usbradio_default.next; o && devstr && strcmp(o->devstr, devstr) != 0; o = o->next);
1275
1276         return o;
1277 }
1278
1279 /*
1280  * split a string in extension-context, returns pointers to malloc'ed
1281  * strings.
1282  * If we do not have 'overridecontext' then the last @ is considered as
1283  * a context separator, and the context is overridden.
1284  * This is usually not very necessary as you can play with the dialplan,
1285  * and it is nice not to need it because you have '@' in SIP addresses.
1286  * Return value is the buffer address.
1287  */
1288 #if     0
1289 static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
1290 {
1291         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
1292
1293         if (ext == NULL || ctx == NULL)
1294                 return NULL;                    /* error */
1295
1296         *ext = *ctx = NULL;
1297
1298         if (src && *src != '\0')
1299                 *ext = ast_strdup(src);
1300
1301         if (*ext == NULL)
1302                 return NULL;
1303
1304         if (!o->overridecontext) {
1305                 /* parse from the right */
1306                 *ctx = strrchr(*ext, '@');
1307                 if (*ctx)
1308                         *(*ctx)++ = '\0';
1309         }
1310
1311         return *ext;
1312 }
1313 #endif
1314
1315 /*
1316  * Returns the number of blocks used in the audio output channel
1317  */
1318 static int used_blocks(struct chan_usbradio_pvt *o)
1319 {
1320         struct audio_buf_info info;
1321
1322         if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
1323                 if (!(o->warned & WARN_used_blocks)) {
1324                         ast_log(LOG_WARNING, "Error reading output space\n");
1325                         o->warned |= WARN_used_blocks;
1326                 }
1327                 return 1;
1328         }
1329
1330         if (o->total_blocks == 0) {
1331                 if (0)                                  /* debugging */
1332                         ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
1333                 o->total_blocks = info.fragments;
1334         }
1335
1336         return o->total_blocks - info.fragments;
1337 }
1338
1339 /* Write an exactly FRAME_SIZE sized frame */
1340 static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
1341 {
1342         int res;
1343
1344         if (o->sounddev < 0)
1345                 setformat(o, O_RDWR);
1346         if (o->sounddev < 0)
1347                 return 0;                               /* not fatal */
1348         //  maw maw sph !!! may or may not be a good thing
1349         //  drop the frame if not transmitting, this keeps from gradually
1350         //  filling the buffer when asterisk clock > usb sound clock
1351         if(!o->pmrChan->txPttIn && !o->pmrChan->txPttOut)
1352         {
1353                 //return 0;
1354         }
1355         /*
1356          * Nothing complex to manage the audio device queue.
1357          * If the buffer is full just drop the extra, otherwise write.
1358          * XXX in some cases it might be useful to write anyways after
1359          * a number of failures, to restart the output chain.
1360          */
1361         res = used_blocks(o);
1362         if (res > o->queuesize) {       /* no room to write a block */
1363             // ast_log(LOG_WARNING, "sound device write buffer overflow\n");
1364                 if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
1365                         ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
1366                 return 0;
1367         }
1368         o->w_errors = 0;
1369
1370         return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12);
1371 }
1372
1373 #ifndef NEW_ASTERISK
1374
1375 /*
1376  * Handler for 'sound writable' events from the sound thread.
1377  * Builds a frame from the high level description of the sounds,
1378  * and passes it to the audio device.
1379  * The actual sound is made of 1 or more sequences of sound samples
1380  * (s->datalen, repeated to make s->samplen samples) followed by
1381  * s->silencelen samples of silence. The position in the sequence is stored
1382  * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen.
1383  * In case we fail to write a frame, don't update o->sampsent.
1384  */
1385 static void send_sound(struct chan_usbradio_pvt *o)
1386 {
1387         short myframe[FRAME_SIZE];
1388         int ofs, l, start;
1389         int l_sampsent = o->sampsent;
1390         struct sound *s;
1391
1392         if (o->cursound < 0)            /* no sound to send */
1393                 return;
1394
1395         s = &sounds[o->cursound];
1396
1397         for (ofs = 0; ofs < FRAME_SIZE; ofs += l) {
1398                 l = s->samplen - l_sampsent;    /* # of available samples */
1399                 if (l > 0) {
1400                         start = l_sampsent % s->datalen;        /* source offset */
1401                         if (l > FRAME_SIZE - ofs)       /* don't overflow the frame */
1402                                 l = FRAME_SIZE - ofs;
1403                         if (l > s->datalen - start)     /* don't overflow the source */
1404                                 l = s->datalen - start;
1405                         memmove(myframe + ofs, s->data + start, l * 2);
1406                         if (0)
1407                                 ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
1408                         l_sampsent += l;
1409                 } else {                                /* end of samples, maybe some silence */
1410                         static const short silence[FRAME_SIZE] = { 0, };
1411
1412                         l += s->silencelen;
1413                         if (l > 0) {
1414                                 if (l > FRAME_SIZE - ofs)
1415                                         l = FRAME_SIZE - ofs;
1416                                 memmove(myframe + ofs, silence, l * 2);
1417                                 l_sampsent += l;
1418                         } else {                        /* silence is over, restart sound if loop */
1419                                 if (s->repeat == 0) {   /* last block */
1420                                         o->cursound = -1;
1421                                         o->nosound = 0; /* allow audio data */
1422                                         if (ofs < FRAME_SIZE)   /* pad with silence */
1423                                                 memmove(myframe + ofs, silence, (FRAME_SIZE - ofs) * 2);
1424                                 }
1425                                 l_sampsent = 0;
1426                         }
1427                 }
1428         }
1429         l = soundcard_writeframe(o, myframe);
1430         if (l > 0)
1431                 o->sampsent = l_sampsent;       /* update status */
1432 }
1433
1434 static void *sound_thread(void *arg)
1435 {
1436         char ign[4096];
1437         struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
1438
1439         /*
1440          * Just in case, kick the driver by trying to read from it.
1441          * Ignore errors - this read is almost guaranteed to fail.
1442          */
1443         read(o->sounddev, ign, sizeof(ign));
1444         for (;;) {
1445                 struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev } };
1446                 int res;
1447
1448                 if (o->cursound > -1 && o->sounddev < 0) {
1449                         setformat(o, O_RDWR);   /* need the channel, try to reopen */
1450                 } else if (o->cursound == -1 && o->owner == NULL) {
1451                         setformat(o, O_CLOSE);  /* can close */
1452                 }
1453                 if (o->sounddev > -1) {
1454                         if (!o->owner) {        /* no one owns the audio, so we must drain it */
1455                                 pfd[1].events = POLLIN;
1456                         }
1457                         if (o->cursound > -1) {
1458                                 pfd[1].events |= POLLOUT;
1459                         }
1460                 }
1461                 res = ast_poll(pfd, o->sounddev > -1 ? 2 : 1, -1);
1462                 if (res < 1) {
1463                         ast_log(LOG_WARNING, "poll failed: %s\n", strerror(errno));
1464                         sleep(1);
1465                         continue;
1466                 }
1467                 if (pfd[0].revents & POLLIN) {
1468                         /* read which sound to play from the pipe */
1469                         int i, what = -1;
1470
1471                         read(o->sndcmd[0], &what, sizeof(what));
1472                         for (i = 0; sounds[i].ind != -1; i++) {
1473                                 if (sounds[i].ind == what) {
1474                                         o->cursound = i;
1475                                         o->sampsent = 0;
1476                                         o->nosound = 1; /* block audio from pbx */
1477                                         break;
1478                                 }
1479                         }
1480                         if (sounds[i].ind == -1) {
1481                                 ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
1482                         }
1483                 }
1484                 if (o->sounddev > -1) {
1485                         if (pfd[1].revents & POLLIN) { /* read and ignore errors */
1486                                 read(o->sounddev, ign, sizeof(ign)); 
1487                         }
1488                         if (pfd[1].revents & POLLOUT) {
1489                                 send_sound(o);
1490                         }
1491                 }
1492         }
1493         return NULL;                            /* Never reached */
1494 }
1495
1496 #endif
1497
1498 /*
1499  * reset and close the device if opened,
1500  * then open and initialize it in the desired mode,
1501  * trigger reads and writes so we can start using it.
1502  */
1503 static int setformat(struct chan_usbradio_pvt *o, int mode)
1504 {
1505         int fmt, desired, res, fd;
1506         char device[100];
1507
1508         if (o->sounddev >= 0) {
1509                 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
1510                 close(o->sounddev);
1511                 o->duplex = M_UNSET;
1512                 o->sounddev = -1;
1513         }
1514         if (mode == O_CLOSE)            /* we are done */
1515                 return 0;
1516         o->lastopen = ast_tvnow();
1517         strcpy(device,"/dev/dsp");
1518         if (o->devicenum)
1519                 sprintf(device,"/dev/dsp%d",o->devicenum);
1520         fd = o->sounddev = open(device, mode | O_NONBLOCK);
1521         if (fd < 0) {
1522                 ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno));
1523                 return -1;
1524         }
1525         if (o->owner)
1526                 o->owner->fds[0] = fd;
1527
1528 #if __BYTE_ORDER == __LITTLE_ENDIAN
1529         fmt = AFMT_S16_LE;
1530 #else
1531         fmt = AFMT_S16_BE;
1532 #endif
1533         res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
1534         if (res < 0) {
1535                 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
1536                 return -1;
1537         }
1538         switch (mode) {
1539                 case O_RDWR:
1540                         res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
1541                         /* Check to see if duplex set (FreeBSD Bug) */
1542                         res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
1543                         if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
1544                                 if (option_verbose > 1)
1545                                         ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
1546                                 o->duplex = M_FULL;
1547                         };
1548                         break;
1549                 case O_WRONLY:
1550                         o->duplex = M_WRITE;
1551                         break;
1552                 case O_RDONLY:
1553                         o->duplex = M_READ;
1554                         break;
1555         }
1556
1557         fmt = 1;
1558         res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
1559         if (res < 0) {
1560                 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
1561                 return -1;
1562         }
1563         fmt = desired = 48000;                                                  /* 8000 Hz desired */
1564         res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
1565
1566         if (res < 0) {
1567                 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
1568                 return -1;
1569         }
1570         if (fmt != desired) {
1571                 if (!(o->warned & WARN_speed)) {
1572                         ast_log(LOG_WARNING,
1573                             "Requested %d Hz, got %d Hz -- sound may be choppy\n",
1574                             desired, fmt);
1575                         o->warned |= WARN_speed;
1576                 }
1577         }
1578         /*
1579          * on Freebsd, SETFRAGMENT does not work very well on some cards.
1580          * Default to use 256 bytes, let the user override
1581          */
1582         if (o->frags) {
1583                 fmt = o->frags;
1584                 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
1585                 if (res < 0) {
1586                         if (!(o->warned & WARN_frag)) {
1587                                 ast_log(LOG_WARNING,
1588                                         "Unable to set fragment size -- sound may be choppy\n");
1589                                 o->warned |= WARN_frag;
1590                         }
1591                 }
1592         }
1593         /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */
1594         res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
1595         res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
1596         /* it may fail if we are in half duplex, never mind */
1597         return 0;
1598 }
1599
1600 /*
1601  * some of the standard methods supported by channels.
1602  */
1603 static int usbradio_digit_begin(struct ast_channel *c, char digit)
1604 {
1605         return 0;
1606 }
1607
1608 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration)
1609 {
1610         /* no better use for received digits than print them */
1611         ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
1612                 digit, duration);
1613         return 0;
1614 }
1615 /*
1616         SETFREQ - sets spi programmable xcvr
1617         SETCHAN - sets binary parallel xcvr
1618 */
1619 static int usbradio_text(struct ast_channel *c, const char *text)
1620 {
1621         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
1622         double tx,rx;
1623         char cnt,rxs[16],txs[16],txpl[16],rxpl[16];
1624         char pwr,*cmd;
1625
1626         cmd = alloca(strlen(text) + 10);
1627
1628         /* print received messages */
1629         if(o->debuglevel)ast_verbose(" << Console Received usbradio text %s >> \n", text);
1630
1631         cnt = sscanf(text, "%300s %15s %15s %15s %15s %1c", cmd, rxs, txs, rxpl, txpl, &pwr);
1632
1633         if (strcmp(cmd,"SETCHAN")==0)
1634     { 
1635                 u8 chan;
1636                 chan=strtod(rxs,NULL);
1637                 ppbinout(chan);
1638         if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETCHAN cmd: %s chan: %i\n",text,chan);
1639         return 0;
1640     }
1641         
1642     if (cnt < 6)
1643     {
1644             ast_log(LOG_ERROR,"Cannot parse usbradio text: %s\n",text);
1645             return 0;
1646     }
1647         else
1648         {
1649                 if(o->debuglevel)ast_verbose(" << %s %s %s %s %s %c >> \n", cmd,rxs,txs,rxpl,txpl,pwr); 
1650         }
1651     
1652     if (strcmp(cmd,"SETFREQ")==0)
1653     {
1654         if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETFREQ cmd: %s\n",text);
1655                 tx=strtod(txs,NULL);
1656                 rx=strtod(rxs,NULL);
1657                 o->set_txfreq = round(tx * (double)1000000);
1658                 o->set_rxfreq = round(rx * (double)1000000);
1659                 o->pmrChan->txpower = (pwr == 'H');
1660                 strcpy(o->set_rxctcssfreqs,rxpl);
1661                 strcpy(o->set_txctcssfreqs,txpl);
1662         
1663                 o->b.remoted=1;
1664                 xpmr_config(o);
1665         return 0;
1666     }
1667         ast_log(LOG_ERROR,"Cannot parse usbradio cmd: %s\n",text);
1668         return 0;
1669 }
1670
1671 /* Play ringtone 'x' on device 'o' */
1672 static void ring(struct chan_usbradio_pvt *o, int x)
1673 {
1674 #ifndef NEW_ASTERISK
1675         write(o->sndcmd[1], &x, sizeof(x));
1676 #endif
1677 }
1678
1679 /*
1680  * handler for incoming calls. Either autoanswer, or start ringing
1681  */
1682 static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
1683 {
1684         struct chan_usbradio_pvt *o = c->tech_pvt;
1685
1686         o->stophid = 0;
1687         time(&o->lasthidtime);
1688         ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
1689         ast_setstate(c, AST_STATE_UP);
1690         return 0;
1691 }
1692
1693 /*
1694  * remote side answered the phone
1695  */
1696 static int usbradio_answer(struct ast_channel *c)
1697 {
1698 #ifndef NEW_ASTERISK
1699         struct chan_usbradio_pvt *o = c->tech_pvt;
1700 #endif
1701
1702         ast_setstate(c, AST_STATE_UP);
1703 #ifndef NEW_ASTERISK
1704         o->cursound = -1;
1705         o->nosound = 0;
1706 #endif
1707         return 0;
1708 }
1709
1710 static int usbradio_hangup(struct ast_channel *c)
1711 {
1712         struct chan_usbradio_pvt *o = c->tech_pvt;
1713
1714         //ast_log(LOG_NOTICE, "usbradio_hangup()\n");
1715 #ifndef NEW_ASTERISK
1716         o->cursound = -1;
1717         o->nosound = 0;
1718 #endif
1719         c->tech_pvt = NULL;
1720         o->owner = NULL;
1721         ast_module_unref(ast_module_info->self);
1722         if (o->hookstate) {
1723                 if (o->autoanswer || o->autohangup) {
1724                         /* Assume auto-hangup too */
1725                         o->hookstate = 0;
1726                         setformat(o, O_CLOSE);
1727                 } else {
1728                         /* Make congestion noise */
1729                         ring(o, AST_CONTROL_CONGESTION);
1730                 }
1731         }
1732         o->stophid = 1;
1733         pthread_join(o->hidthread,NULL);
1734         return 0;
1735 }
1736
1737
1738 /* used for data coming from the network */
1739 static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
1740 {
1741         struct chan_usbradio_pvt *o = c->tech_pvt;
1742
1743         traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound));
1744
1745 #ifndef NEW_ASTERISK
1746         /* Immediately return if no sound is enabled */
1747         if (o->nosound)
1748                 return 0;
1749         /* Stop any currently playing sound */
1750         o->cursound = -1;
1751 #endif
1752         /*
1753          * we could receive a block which is not a multiple of our
1754          * FRAME_SIZE, so buffer it locally and write to the device
1755          * in FRAME_SIZE chunks.
1756          * Keep the residue stored for future use.
1757          */
1758
1759         #if DEBUG_CAPTURES == 1 // to write input data to a file   datalen=320
1760         if (ftxcapraw && o->b.txcapraw)
1761         {
1762                 i16 i, tbuff[f->datalen];
1763                 for(i=0;i<f->datalen;i+=2)
1764                 {
1765                         tbuff[i]= ((i16*)(f->data.ptr))[i/2];
1766                         tbuff[i+1]= o->txkeyed*M_Q13;
1767                 }
1768                 if (fwrite(tbuff,2,f->datalen,ftxcapraw) != f->datalen) {
1769                         ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
1770                 }
1771                 //fwrite(f->data,1,f->datalen,ftxcapraw);
1772         }
1773         #endif
1774
1775         // maw just take the data from the network and save it for PmrRx processing
1776
1777         PmrTx(o->pmrChan,(i16*)f->data.ptr);
1778         
1779         return 0;
1780 }
1781
1782 static struct ast_frame *usbradio_read(struct ast_channel *c)
1783 {
1784         int res, src, datalen, oldpttout;
1785         int cd,sd;
1786         struct chan_usbradio_pvt *o = c->tech_pvt;
1787         struct ast_frame *f = &o->read_f,*f1;
1788         struct ast_frame wf = { AST_FRAME_CONTROL };
1789         time_t now;
1790
1791         traceusb2(("usbradio_read()\n"));
1792
1793         if (o->lasthidtime)
1794         {
1795                 time(&now);
1796                 if ((now - o->lasthidtime) > 3)
1797                 {
1798                         ast_log(LOG_ERROR,"HID process has died or something!!\n");
1799                         return NULL;
1800                 }
1801         }
1802         /* XXX can be simplified returning &ast_null_frame */
1803         /* prepare a NULL frame in case we don't have enough data to return */
1804         memset(f, '\0', sizeof(struct ast_frame));
1805         f->frametype = AST_FRAME_NULL;
1806         f->src = usbradio_tech.type;
1807
1808         res = read(o->sounddev, o->usbradio_read_buf + o->readpos, 
1809                 sizeof(o->usbradio_read_buf) - o->readpos);
1810         if (res < 0)                            /* audio data not ready, return a NULL frame */
1811         {
1812                 if (errno != EAGAIN) return NULL;
1813                 if (o->readerrs++ > READERR_THRESHOLD)
1814                 {
1815                         ast_log(LOG_ERROR,"Stuck USB read channel [%s], un-sticking it!\n",o->name);
1816                         o->readerrs = 0;
1817                         return NULL;
1818                 }
1819                 if (o->readerrs == 1) 
1820                         ast_log(LOG_WARNING,"Possibly stuck USB read channel. [%s]\n",o->name);
1821                 return f;
1822         }
1823         if (o->readerrs) ast_log(LOG_WARNING,"Nope, USB read channel [%s] wasn't stuck after all.\n",o->name);
1824         o->readerrs = 0;
1825         o->readpos += res;
1826         if (o->readpos < sizeof(o->usbradio_read_buf))  /* not enough samples */
1827                 return f;
1828
1829         if (o->mute)
1830                 return f;
1831
1832         #if DEBUG_CAPTURES == 1
1833         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)) {
1834                 ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
1835         }
1836         #endif
1837
1838         #if 1
1839         if(o->txkeyed||o->txtestkey)
1840         {
1841                 if(!o->pmrChan->txPttIn)
1842                 {
1843                         o->pmrChan->txPttIn=1;
1844                         if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
1845                 }
1846         }
1847         else if(o->pmrChan->txPttIn)
1848         {
1849                 o->pmrChan->txPttIn=0;
1850                 if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
1851         }
1852         oldpttout = o->pmrChan->txPttOut;
1853
1854         PmrRx(         o->pmrChan, 
1855                    (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
1856                    (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),
1857                    (i16 *)(o->usbradio_write_buf_1));
1858
1859         if (oldpttout != o->pmrChan->txPttOut)
1860         {
1861                 if(o->debuglevel) ast_log(LOG_NOTICE,"txPttOut = %i, chan %s\n",o->pmrChan->txPttOut,o->owner->name);
1862                 kickptt(o);
1863         }
1864
1865         #if 0   // to write 48KS/s stereo tx data to a file
1866         if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
1867         if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,FRAME_SIZE * 2 * 6,ftxoutraw);
1868         #endif
1869
1870         #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
1871     if ((o->b.txcap2 && ftxcaptrace) && (fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace) != FRAME_SIZE * 2 * 16)) {
1872            ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
1873         }
1874         #endif
1875         
1876         // 160 samples * 2 bytes/sample * 2 chan * 6x oversampling to 48KS/s
1877         datalen = FRAME_SIZE * 24;  
1878         src = 0;                                        /* read position into f->data */
1879         while (src < datalen) 
1880         {
1881                 /* Compute spare room in the buffer */
1882                 int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
1883
1884                 if (datalen - src >= l) 
1885                 {       
1886                         /* enough to fill a frame */
1887                         memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
1888                         soundcard_writeframe(o, (short *) o->usbradio_write_buf);
1889                         src += l;
1890                         o->usbradio_write_dst = 0;
1891                 } 
1892                 else 
1893                 {                               
1894                         /* copy residue */
1895                         l = datalen - src;
1896                         memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
1897                         src += l;                       /* but really, we are done */
1898                         o->usbradio_write_dst += l;
1899                 }
1900         }
1901         #else
1902         static FILE *hInput;
1903         i16 iBuff[FRAME_SIZE*2*6];
1904
1905         o->pmrChan->b.rxCapture=1;
1906
1907         if(!hInput)
1908         {
1909                 hInput  = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
1910                 if(!hInput)
1911                 {
1912                         printf(" Input Data File Not Found.\n");
1913                         return 0;
1914                 }
1915         }
1916
1917         if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit;
1918
1919         PmrRx(  o->pmrChan, 
1920                    (i16 *)iBuff,
1921                    (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
1922
1923         #endif
1924
1925         #if 0
1926         if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE,"w");
1927     if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw);
1928         #endif
1929
1930         #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
1931     if ((frxcaptrace && o->b.rxcap2 && o->pmrChan->b.radioactive) && (fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace) != FRAME_SIZE * 2 * 16 )) {
1932                 ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
1933         }
1934         #endif
1935
1936         cd = 0;
1937         if(o->rxcdtype==CD_HID && (o->pmrChan->rxExtCarrierDetect!=o->rxhidsq))
1938                 o->pmrChan->rxExtCarrierDetect=o->rxhidsq;
1939         
1940         if(o->rxcdtype==CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect==o->rxhidsq))
1941                 o->pmrChan->rxExtCarrierDetect=!o->rxhidsq;
1942                 
1943         if( (o->rxcdtype==CD_HID        && o->rxhidsq)                  ||
1944                 (o->rxcdtype==CD_HID_INVERT && !o->rxhidsq)                 ||
1945                 (o->rxcdtype==CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
1946                 (o->rxcdtype==CD_XPMR_VOX   && o->pmrChan->rxCarrierDetect)
1947           )
1948         {
1949                 if (!o->pmrChan->txPttOut || o->radioduplex)cd=1;       
1950         }
1951         else
1952         {
1953                 cd=0;
1954         }
1955
1956         if(cd!=o->rxcarrierdetect)
1957         {
1958                 o->rxcarrierdetect=cd;
1959                 if(o->debuglevel) ast_log(LOG_NOTICE,"rxcarrierdetect = %i, chan %s\n",cd,o->owner->name);
1960                 // printf("rxcarrierdetect = %i, chan %s\n",res,o->owner->name);
1961         }
1962
1963         if(o->pmrChan->b.ctcssRxEnable && o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
1964         {
1965                 if(o->debuglevel)ast_log(LOG_NOTICE,"rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
1966                 // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
1967                 o->rxctcssdecode=o->pmrChan->rxCtcss->decode;
1968                 strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
1969         }
1970
1971         #ifndef HAVE_XPMRX
1972         if(  !o->pmrChan->b.ctcssRxEnable ||
1973                 ( o->pmrChan->b.ctcssRxEnable && 
1974               o->pmrChan->rxCtcss->decode>CTCSS_NULL && 
1975               o->pmrChan->smode==SMODE_CTCSS )  
1976         )
1977         {
1978                 sd=1;   
1979         }
1980         else
1981         {
1982                 sd=0;
1983         }
1984         #else
1985         if( (!o->pmrChan->b.ctcssRxEnable && !o->pmrChan->b.dcsRxEnable && !o->pmrChan->b.lmrRxEnable) ||
1986                 ( o->pmrChan->b.ctcssRxEnable && 
1987               o->pmrChan->rxCtcss->decode>CTCSS_NULL && 
1988               o->pmrChan->smode==SMODE_CTCSS ) ||
1989                 ( o->pmrChan->b.dcsRxEnable && 
1990               o->pmrChan->decDcs->decode > 0 &&
1991               o->pmrChan->smode==SMODE_DCS )
1992         )
1993         {
1994                 sd=1;   
1995         }
1996         else
1997         {
1998                 sd=0;
1999         }
2000
2001         if(o->pmrChan->decDcs->decode!=o->rxdcsdecode)
2002         {                                                                                                       
2003                 if(o->debuglevel)ast_log(LOG_NOTICE,"rxdcsdecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
2004                 // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
2005                 o->rxdcsdecode=o->pmrChan->decDcs->decode;
2006                 strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
2007         }                                                                                                                                                                                         
2008
2009         if(o->pmrChan->rptnum && (o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed != o->rxlsddecode))
2010         {                                                               
2011                 if(o->debuglevel)ast_log(LOG_NOTICE,"rxLSDecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
2012                 o->rxlsddecode=o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed;
2013                 strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
2014         }
2015
2016         if( (o->pmrChan->rptnum>0 && o->pmrChan->smode==SMODE_LSD && o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed)||
2017             (o->pmrChan->smode==SMODE_DCS && o->pmrChan->decDcs->decode>0) )
2018         {
2019                 sd=1;
2020         }
2021         #endif
2022
2023         if ( cd && sd )
2024         {
2025                 //if(!o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
2026                 if(!o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 1, chan %s\n", o->owner->name);
2027                 o->rxkeyed = 1;
2028         }
2029         else 
2030         {
2031                 //if(o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
2032                 if(o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 0, chan %s\n",o->owner->name);
2033                 o->rxkeyed = 0;
2034         }
2035
2036         // provide rx signal detect conditions
2037         if (o->lastrx && (!o->rxkeyed))
2038         {
2039                 o->lastrx = 0;
2040                 //printf("AST_CONTROL_RADIO_UNKEY\n");
2041                 wf.subclass.integer = AST_CONTROL_RADIO_UNKEY;
2042                 ast_queue_frame(o->owner, &wf);
2043         }
2044         else if ((!o->lastrx) && (o->rxkeyed))
2045         {
2046                 o->lastrx = 1;
2047                 //printf("AST_CONTROL_RADIO_KEY\n");
2048                 wf.subclass.integer = AST_CONTROL_RADIO_KEY;
2049                 if(o->rxctcssdecode)    
2050         {
2051                 wf.data.ptr = o->rxctcssfreq;
2052                 wf.datalen = strlen(o->rxctcssfreq) + 1;
2053                         TRACEO(1,("AST_CONTROL_RADIO_KEY text=%s\n",o->rxctcssfreq));
2054         }
2055                 ast_queue_frame(o->owner, &wf);
2056         }
2057
2058         o->readpos = AST_FRIENDLY_OFFSET;       /* reset read pointer for next frame */
2059         if (c->_state != AST_STATE_UP)  /* drop data if frame is not up */
2060                 return f;
2061         /* ok we can build and deliver the frame to the caller */
2062         f->frametype = AST_FRAME_VOICE;
2063         f->subclass.codec = AST_FORMAT_SLINEAR;
2064         f->samples = FRAME_SIZE;
2065         f->datalen = FRAME_SIZE * 2;
2066         f->data.ptr = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET;
2067         if (o->boost != BOOST_SCALE) {  /* scale and clip values */
2068                 int i, x;
2069                 int16_t *p = (int16_t *) f->data.ptr;
2070                 for (i = 0; i < f->samples; i++) {
2071                         x = (p[i] * o->boost) / BOOST_SCALE;
2072                         if (x > 32767)
2073                                 x = 32767;
2074                         else if (x < -32768)
2075                                 x = -32768;
2076                         p[i] = x;
2077                 }
2078         }
2079
2080         f->offset = AST_FRIENDLY_OFFSET;
2081         if (o->dsp)
2082         {
2083             f1 = ast_dsp_process(c,o->dsp,f);
2084             if ((f1->frametype == AST_FRAME_DTMF_END) ||
2085               (f1->frametype == AST_FRAME_DTMF_BEGIN))
2086             {
2087                 if ((f1->subclass.integer == 'm') || (f1->subclass.integer == 'u'))
2088                 {
2089                         f1->frametype = AST_FRAME_NULL;
2090                         f1->subclass.integer = 0;
2091                         return(f1);
2092                 }
2093                 if (f1->frametype == AST_FRAME_DTMF_END)
2094                         ast_log(LOG_NOTICE, "Got DTMF char %c\n", f1->subclass.integer);
2095                 return(f1);
2096             }
2097         }
2098         return f;
2099 }
2100
2101 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
2102 {
2103         struct chan_usbradio_pvt *o = newchan->tech_pvt;
2104         ast_log(LOG_WARNING,"usbradio_fixup()\n");
2105         o->owner = newchan;
2106         return 0;
2107 }
2108
2109 static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
2110 {
2111         struct chan_usbradio_pvt *o = c->tech_pvt;
2112         int res = -1;
2113
2114         switch (cond) {
2115                 case AST_CONTROL_BUSY:
2116                 case AST_CONTROL_CONGESTION:
2117                 case AST_CONTROL_RINGING:
2118                         res = cond;
2119                         break;
2120
2121                 case -1:
2122 #ifndef NEW_ASTERISK
2123                         o->cursound = -1;
2124                         o->nosound = 0;         /* when cursound is -1 nosound must be 0 */
2125 #endif
2126                         return 0;
2127
2128                 case AST_CONTROL_VIDUPDATE:
2129                         res = -1;
2130                         break;
2131                 case AST_CONTROL_HOLD:
2132                         ast_verbose(" << Console Has Been Placed on Hold >> \n");
2133                         ast_moh_start(c, data, o->mohinterpret);
2134                         break;
2135                 case AST_CONTROL_UNHOLD:
2136                         ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
2137                         ast_moh_stop(c);
2138                         break;
2139                 case AST_CONTROL_PROCEEDING:
2140                         ast_verbose(" << Call Proceeding... >> \n");
2141                         ast_moh_stop(c);
2142                         break;
2143                 case AST_CONTROL_PROGRESS:
2144                         ast_verbose(" << Call Progress... >> \n");
2145                         ast_moh_stop(c);
2146                         break;
2147                 case AST_CONTROL_RADIO_KEY:
2148                         o->txkeyed = 1;
2149                         if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_KEY Radio Transmit On. >> \n");
2150                         break;
2151                 case AST_CONTROL_RADIO_UNKEY:
2152                         o->txkeyed = 0;
2153                         if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_UNKEY Radio Transmit Off. >> \n");
2154                         break;
2155                 default:
2156                         ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
2157                         return -1;
2158         }
2159
2160         if (res > -1)
2161                 ring(o, res);
2162
2163         return 0;
2164 }
2165
2166 /*
2167  * allocate a new channel.
2168  */
2169 static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state, const char *linkedid)
2170 {
2171         struct ast_channel *c;
2172
2173         c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Radio/%s", o->name);
2174         if (c == NULL)
2175                 return NULL;
2176         c->tech = &usbradio_tech;
2177         if (o->sounddev < 0)
2178                 setformat(o, O_RDWR);
2179         c->fds[0] = o->sounddev;        /* -1 if device closed, override later */
2180         c->nativeformats = AST_FORMAT_SLINEAR;
2181         c->readformat = AST_FORMAT_SLINEAR;
2182         c->writeformat = AST_FORMAT_SLINEAR;
2183         c->tech_pvt = o;
2184
2185         if (!ast_strlen_zero(o->language))
2186                 ast_string_field_set(c, language, o->language);
2187         /* Don't use ast_set_callerid() here because it will
2188          * generate a needless NewCallerID event */
2189         if (!ast_strlen_zero(o->cid_num)) {
2190                 c->caller.ani.number.valid = 1;
2191                 c->caller.ani.number.str = ast_strdup(o->cid_num);
2192         }
2193         if (!ast_strlen_zero(ext)) {
2194                 c->dialed.number.str = ast_strdup(ext);
2195         }
2196
2197         o->owner = c;
2198         ast_module_ref(ast_module_info->self);
2199         ast_jb_configure(c, &global_jbconf);
2200         if (state != AST_STATE_DOWN) {
2201                 if (ast_pbx_start(c)) {
2202                         ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
2203                         ast_hangup(c);
2204                         o->owner = c = NULL;
2205                         /* XXX what about the channel itself ? */
2206                         /* XXX what about usecnt ? */
2207                 }
2208         }
2209
2210         return c;
2211 }
2212 /*
2213 */
2214 static struct ast_channel *usbradio_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
2215 {
2216         struct ast_channel *c;
2217         struct chan_usbradio_pvt *o = find_desc(data);
2218
2219         TRACEO(1,("usbradio_request()\n"));
2220
2221         if (0)
2222         {
2223                 ast_log(LOG_WARNING, "usbradio_request type <%s> data 0x%p <%s>\n", type, data, (char *) data);
2224         }
2225         if (o == NULL) {
2226                 ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
2227                 /* XXX we could default to 'dsp' perhaps ? */
2228                 return NULL;
2229         }
2230         if ((format & AST_FORMAT_SLINEAR) == 0) {
2231                 ast_log(LOG_NOTICE, "Format 0x%" PRIx64 " unsupported\n", format);
2232                 return NULL;
2233         }
2234         if (o->owner) {
2235                 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the usb channel\n", o->owner);
2236                 *cause = AST_CAUSE_BUSY;
2237                 return NULL;
2238         }
2239         c = usbradio_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
2240         if (c == NULL) {
2241                 ast_log(LOG_WARNING, "Unable to create new usb channel\n");
2242                 return NULL;
2243         }
2244                 
2245         o->b.remoted=0;
2246         xpmr_config(o);
2247
2248         return c;
2249 }
2250 /*
2251 */
2252 static int console_key(int fd, int argc, char *argv[])
2253 {
2254         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2255
2256         if (argc != 2)
2257                 return RESULT_SHOWUSAGE; 
2258         o->txtestkey = 1;
2259         return RESULT_SUCCESS;
2260 }
2261 /*
2262 */
2263 static int console_unkey(int fd, int argc, char *argv[])
2264 {
2265         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2266
2267         if (argc != 2)
2268                 return RESULT_SHOWUSAGE;
2269         o->txtestkey = 0;
2270         return RESULT_SUCCESS;
2271 }
2272
2273 static int radio_tune(int fd, int argc, char *argv[])
2274 {
2275         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2276         int i=0;
2277
2278         if ((argc < 2) || (argc > 4))
2279                 return RESULT_SHOWUSAGE; 
2280
2281         if (argc == 2) /* just show stuff */
2282         {
2283                 ast_cli(fd,"Active radio interface is [%s]\n",usbradio_active);
2284                 ast_cli(fd,"Output A is currently set to ");
2285                 if(o->txmixa==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
2286                 else if (o->txmixa==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
2287                 else if (o->txmixa==TX_OUT_LSD)ast_cli(fd,"tone.\n");
2288                 else if (o->txmixa==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
2289                 else ast_cli(fd,"off.\n");
2290
2291                 ast_cli(fd,"Output B is currently set to ");
2292                 if(o->txmixb==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
2293                 else if (o->txmixb==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
2294                 else if (o->txmixb==TX_OUT_LSD)ast_cli(fd,"tone.\n");
2295                 else if (o->txmixb==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
2296                 else ast_cli(fd,"off.\n");
2297
2298                 ast_cli(fd,"Tx Voice Level currently set to %d\n",o->txmixaset);
2299                 ast_cli(fd,"Tx Tone Level currently set to %d\n",o->txctcssadj);
2300                 ast_cli(fd,"Rx Squelch currently set to %d\n",o->rxsquelchadj);
2301                 ast_cli(fd,"Device String is %s\n",o->devstr);
2302                 return RESULT_SHOWUSAGE;
2303         }
2304
2305         o->pmrChan->b.tuning=1;
2306
2307         if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(fd,o);
2308         else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(fd,o);
2309         else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(fd,o);
2310         else if (!strcasecmp(argv[2],"rxsquelch"))
2311         {
2312                 if (argc == 3)
2313                 {
2314                     ast_cli(fd,"Current Signal Strength is %d\n",((32767-o->pmrChan->rxRssi)*1000/32767));
2315                     ast_cli(fd,"Current Squelch setting is %d\n",o->rxsquelchadj);
2316                         //ast_cli(fd,"Current Raw RSSI        is %d\n",o->pmrChan->rxRssi);
2317                     //ast_cli(fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
2318                 } else {
2319                         i = atoi(argv[3]);
2320                         if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2321                         ast_cli(fd,"Changed Squelch setting to %d\n",i);
2322                         o->rxsquelchadj = i;
2323                         *(o->pmrChan->prxSquelchAdjust)= ((999 - i) * 32767) / 1000;
2324                 }
2325         }
2326         else if (!strcasecmp(argv[2],"txvoice")) {
2327                 i = 0;
2328
2329                 if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
2330                         (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
2331                   )
2332                 {
2333                         ast_log(LOG_ERROR,"No txvoice output configured.\n");
2334                 }
2335                 else if (argc == 3)
2336                 {
2337                         if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2338                                 ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
2339                         else
2340                                 ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
2341                 }
2342                 else
2343                 {
2344                         i = atoi(argv[3]);
2345                         if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2346
2347                         if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2348                         {
2349                                 o->txmixaset=i;
2350                                 ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
2351                         }
2352                         else
2353                         {
2354                                 o->txmixbset=i;   
2355                                 ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
2356                         }
2357                         mixer_write(o);
2358                         mult_set(o);
2359                         ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
2360                 }
2361                 o->pmrChan->b.txCtcssInhibit=1;
2362                 tune_txoutput(o,i,fd);
2363                 o->pmrChan->b.txCtcssInhibit=0;
2364         }
2365         else if (!strcasecmp(argv[2],"txall")) {
2366                 i = 0;
2367
2368                 if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
2369                         (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
2370                   )
2371                 {
2372                         ast_log(LOG_ERROR,"No txvoice output configured.\n");
2373                 }
2374                 else if (argc == 3)
2375                 {
2376                         if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2377                                 ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
2378                         else
2379                                 ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
2380                 }
2381                 else
2382                 {
2383                         i = atoi(argv[3]);
2384                         if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2385
2386                         if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
2387                         {
2388                                 o->txmixaset=i;
2389                                 ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
2390                         }
2391                         else
2392                         {
2393                                 o->txmixbset=i;   
2394                                 ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
2395                         }
2396                         mixer_write(o);
2397                         mult_set(o);
2398                         ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
2399                 }
2400                 tune_txoutput(o,i,fd);
2401         }
2402         else if (!strcasecmp(argv[2],"auxvoice")) {
2403                 i = 0;
2404                 if( (o->txmixa!=TX_OUT_AUX) && (o->txmixb!=TX_OUT_AUX))
2405                 {
2406                         ast_log(LOG_WARNING,"No auxvoice output configured.\n");
2407                 }
2408                 else if (argc == 3)
2409                 {
2410                         if(o->txmixa==TX_OUT_AUX)
2411                                 ast_cli(fd,"Current auxvoice setting on Channel A is %d\n",o->txmixaset);
2412                         else
2413                                 ast_cli(fd,"Current auxvoice setting on Channel B is %d\n",o->txmixbset);
2414                 }
2415                 else
2416                 {
2417                         i = atoi(argv[3]);
2418                         if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2419                         if(o->txmixa==TX_OUT_AUX)
2420                         {
2421                                 o->txmixbset=i;
2422                                 ast_cli(fd,"Changed auxvoice setting on Channel A to %d\n",o->txmixaset);
2423                         }
2424                         else
2425                         {
2426                                 o->txmixbset=i;
2427                                 ast_cli(fd,"Changed auxvoice setting on Channel B to %d\n",o->txmixbset);
2428                         }
2429                         mixer_write(o);
2430                         mult_set(o);
2431                 }
2432                 //tune_auxoutput(o,i);
2433         }
2434         else if (!strcasecmp(argv[2],"txtone"))
2435         {
2436                 if (argc == 3)
2437                         ast_cli(fd,"Current Tx CTCSS modulation setting = %d\n",o->txctcssadj);
2438                 else
2439                 {
2440                         i = atoi(argv[3]);
2441                         if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
2442                         o->txctcssadj = i;
2443                         set_txctcss_level(o);
2444                         ast_cli(fd,"Changed Tx CTCSS modulation setting to %i\n",i);
2445                 }
2446                 o->txtestkey=1;
2447                 usleep(5000000);
2448                 o->txtestkey=0;
2449         }
2450         else if (!strcasecmp(argv[2],"dump")) pmrdump(o);
2451         else if (!strcasecmp(argv[2],"nocap"))  
2452         {
2453                 ast_cli(fd,"File capture (trace) was rx=%d tx=%d and now off.\n",o->b.rxcap2,o->b.txcap2);
2454                 ast_cli(fd,"File capture (raw)   was rx=%d tx=%d and now off.\n",o->b.rxcapraw,o->b.txcapraw);
2455                 o->b.rxcapraw=o->b.txcapraw=o->b.rxcap2=o->b.txcap2=o->pmrChan->b.rxCapture=o->pmrChan->b.txCapture=0;
2456                 if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
2457                 if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
2458                 if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
2459                 if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
2460                 if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
2461                 if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
2462         }
2463         else if (!strcasecmp(argv[2],"rxtracecap")) 
2464         {
2465                 if (!frxcaptrace) frxcaptrace= fopen(RX_CAP_TRACE_FILE,"w");
2466                 ast_cli(fd,"Trace rx on.\n");
2467                 o->b.rxcap2=o->pmrChan->b.rxCapture=1;
2468         }
2469         else if (!strcasecmp(argv[2],"txtracecap")) 
2470         {
2471                 if (!ftxcaptrace) ftxcaptrace= fopen(TX_CAP_TRACE_FILE,"w");
2472                 ast_cli(fd,"Trace tx on.\n");
2473                 o->b.txcap2=o->pmrChan->b.txCapture=1;
2474         }
2475         else if (!strcasecmp(argv[2],"rxcap")) 
2476         {
2477                 if (!frxcapraw) frxcapraw = fopen(RX_CAP_RAW_FILE,"w");
2478                 ast_cli(fd,"cap rx raw on.\n");
2479                 o->b.rxcapraw=1;
2480         }
2481         else if (!strcasecmp(argv[2],"txcap")) 
2482         {
2483                 if (!ftxcapraw) ftxcapraw = fopen(TX_CAP_RAW_FILE,"w");
2484                 ast_cli(fd,"cap tx raw on.\n");
2485                 o->b.txcapraw=1;
2486         }
2487         else if (!strcasecmp(argv[2],"save"))
2488         {
2489                 tune_write(o);
2490                 ast_cli(fd,"Saved radio tuning settings to usbradio_tune_%s.conf\n",o->name);
2491         }
2492         else if (!strcasecmp(argv[2],"load"))
2493         {
2494                 ast_mutex_lock(&o->eepromlock);
2495                 while(o->eepromctl)
2496                 {
2497                         ast_mutex_unlock(&o->eepromlock);
2498                         usleep(10000);
2499                         ast_mutex_lock(&o->eepromlock);
2500                 }
2501                 o->eepromctl = 1;  /* request a load */
2502                 ast_mutex_unlock(&o->eepromlock);
2503
2504                 ast_cli(fd,"Requesting loading of tuning settings from EEPROM for channel %s\n",o->name);
2505         }
2506         else
2507         {
2508                 o->pmrChan->b.tuning=0;
2509                 return RESULT_SHOWUSAGE;
2510         }
2511         o->pmrChan->b.tuning=0;
2512         return RESULT_SUCCESS;
2513 }
2514
2515 /*
2516         set transmit ctcss modulation level
2517         adjust mixer output or internal gain depending on output type
2518         setting range is 0.0 to 0.9
2519 */
2520 static int set_txctcss_level(struct chan_usbradio_pvt *o)
2521 {                                                         
2522         if (o->txmixa == TX_OUT_LSD)
2523         {
2524 //              o->txmixaset=(151*o->txctcssadj) / 1000;
2525                 o->txmixaset=o->txctcssadj;
2526                 mixer_write(o);
2527                 mult_set(o);
2528         }
2529         else if (o->txmixb == TX_OUT_LSD)
2530         {
2531 //              o->txmixbset=(151*o->txctcssadj) / 1000;
2532                 o->txmixbset=o->txctcssadj;
2533                 mixer_write(o);
2534                 mult_set(o);
2535         }
2536         else
2537         {
2538                 *o->pmrChan->ptxCtcssAdjust=(o->txctcssadj * M_Q8) / 1000;
2539         }
2540         return 0;
2541 }
2542 /*
2543         CLI debugging on and off
2544 */
2545 static int radio_set_debug(int fd, int argc, char *argv[])
2546 {
2547         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2548
2549         o->debuglevel=1;
2550         ast_cli(fd,"usbradio debug on.\n");
2551         return RESULT_SUCCESS;
2552 }
2553
2554 static int radio_set_debug_off(int fd, int argc, char *argv[])
2555 {
2556         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2557
2558         o->debuglevel=0;
2559         ast_cli(fd,"usbradio debug off.\n");
2560         return RESULT_SUCCESS;
2561 }
2562
2563 static int radio_active(int fd, int argc, char *argv[])
2564 {
2565         if (argc == 2)
2566                 ast_cli(fd, "active (command) USB Radio device is [%s]\n", usbradio_active);
2567         else if (argc != 3)
2568                 return RESULT_SHOWUSAGE;
2569         else {
2570                 struct chan_usbradio_pvt *o;
2571                 if (strcmp(argv[2], "show") == 0) {
2572                         for (o = usbradio_default.next; o; o = o->next)
2573                                 ast_cli(fd, "device [%s] exists\n", o->name);
2574                         return RESULT_SUCCESS;
2575                 }
2576                 o = find_desc(argv[2]);
2577                 if (o == NULL)
2578                         ast_cli(fd, "No device [%s] exists\n", argv[2]);
2579                 else
2580                                 {
2581                                         struct chan_usbradio_pvt *ao;
2582                                         for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
2583                     usbradio_active = o->name;
2584                                     o->pmrChan->b.radioactive=1;
2585                                 }
2586         }
2587         return RESULT_SUCCESS;
2588 }
2589 /*
2590         CLI debugging on and off
2591 */
2592 static int radio_set_xpmr_debug(int fd, int argc, char *argv[])
2593 {
2594         struct chan_usbradio_pvt *o = find_desc(usbradio_active);
2595
2596         if (argc == 4)
2597         {
2598                 int i;
2599                 i = atoi(argv[3]);
2600                 if ((i >= 0) && (i <= 100))
2601                 { 
2602                         o->pmrChan->tracelevel=i;
2603                 }
2604     }
2605         // add ability to set it for a number of frames after which it reverts
2606         ast_cli(fd,"usbradio xdebug on tracelevel %i\n",o->pmrChan->tracelevel);
2607
2608         return RESULT_SUCCESS;
2609 }
2610
2611
2612 static char key_usage[] =
2613         "Usage: radio key\n"
2614         "       Simulates COR active.\n";
2615
2616 static char unkey_usage[] =
2617         "Usage: radio unkey\n"
2618         "       Simulates COR un-active.\n";
2619
2620 static char active_usage[] =
2621         "Usage: radio active [device-name]\n"
2622         "       If used without a parameter, displays which device is the current\n"
2623         "one being commanded.  If a device is specified, the commanded radio device is changed\n"
2624         "to the device specified.\n";
2625 /*
2626 radio tune 6 3000               measured tx value
2627 */
2628 static char radio_tune_usage[] =
2629         "Usage: radio tune <function>\n"
2630         "       rxnoise\n"
2631         "       rxvoice\n"
2632         "       rxtone\n"
2633         "       rxsquelch [newsetting]\n"
2634         "       txvoice [newsetting]\n"
2635         "       txtone [newsetting]\n"
2636         "       auxvoice [newsetting]\n"
2637         "       save (settings to tuning file)\n"
2638         "       load (tuning settings from EEPROM)\n"
2639         "\n       All [newsetting]'s are values 0-999\n\n";
2640                                           
2641 #ifndef NEW_ASTERISK
2642
2643 static struct ast_cli_entry cli_usbradio[] = {
2644         { { "radio", "key", NULL },
2645         console_key, "Simulate Rx Signal Present",
2646         key_usage, NULL, NULL},
2647
2648         { { "radio", "unkey", NULL },
2649         console_unkey, "Simulate Rx Signal Lusb",
2650         unkey_usage, NULL, NULL },
2651
2652         { { "radio", "tune", NULL },
2653         radio_tune, "Radio Tune",
2654         radio_tune_usage, NULL, NULL },
2655
2656         { { "radio", "set", "debug", NULL },
2657         radio_set_debug, "Radio Debug",
2658         radio_tune_usage, NULL, NULL },
2659
2660         { { "radio", "set", "debug", "off", NULL },
2661         radio_set_debug_off, "Radio Debug",
2662         radio_tune_usage, NULL, NULL },
2663
2664         { { "radio", "active", NULL },
2665         radio_active, "Change commanded device",
2666         active_usage, NULL, NULL },
2667
2668     { { "radio", "set", "xdebug", NULL },
2669         radio_set_xpmr_debug, "Radio set xpmr debug level",
2670         active_usage, NULL, NULL },
2671
2672 };
2673 #endif
2674
2675 /*
2676  * store the callerid components
2677  */
2678 #if 0
2679 static void store_callerid(struct chan_usbradio_pvt *o, char *s)
2680 {
2681         ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
2682 }
2683 #endif
2684
2685 static void store_rxdemod(struct chan_usbradio_pvt *o, const char *s)
2686 {
2687         if (!strcasecmp(s,"no")){
2688                 o->rxdemod = RX_AUDIO_NONE;
2689         }
2690         else if (!strcasecmp(s,"speaker")){
2691                 o->rxdemod = RX_AUDIO_SPEAKER;
2692         }
2693         else if (!strcasecmp(s,"flat")){
2694                         o->rxdemod = RX_AUDIO_FLAT;
2695         }       
2696         else {
2697                 ast_log(LOG_WARNING,"Unrecognized rxdemod parameter: %s\n",s);
2698         }
2699
2700         //ast_log(LOG_WARNING, "set rxdemod = %s\n", s);
2701 }
2702
2703                                            
2704 static void store_txmixa(struct chan_usbradio_pvt *o, const char *s)
2705 {
2706         if (!strcasecmp(s,"no")){
2707                 o->txmixa = TX_OUT_OFF;
2708         }
2709         else if (!strcasecmp(s,"voice")){
2710                 o->txmixa = TX_OUT_VOICE;
2711         }
2712         else if (!strcasecmp(s,"tone")){
2713                         o->txmixa = TX_OUT_LSD;
2714         }       
2715         else if (!strcasecmp(s,"composite")){
2716                 o->txmixa = TX_OUT_COMPOSITE;
2717         }       
2718         else if (!strcasecmp(s,"auxvoice")){
2719                 o->txmixa = TX_OUT_AUX;
2720         }       
2721         else {
2722                 ast_log(LOG_WARNING,"Unrecognized txmixa parameter: %s\n",s);
2723         }
2724
2725         //ast_log(LOG_WARNING, "set txmixa = %s\n", s);
2726 }
2727
2728 static void store_txmixb(struct chan_usbradio_pvt *o, const char *s)
2729 {
2730         if (!strcasecmp(s,"no")){
2731                 o->txmixb = TX_OUT_OFF;
2732         }
2733         else if (!strcasecmp(s,"voice")){
2734                 o->txmixb = TX_OUT_VOICE;
2735         }
2736         else if (!strcasecmp(s,"tone")){
2737                         o->txmixb = TX_OUT_LSD;
2738         }       
2739         else if (!strcasecmp(s,"composite")){
2740                 o->txmixb = TX_OUT_COMPOSITE;
2741         }       
2742         else if (!strcasecmp(s,"auxvoice")){
2743                 o->txmixb = TX_OUT_AUX;
2744         }       
2745         else {
2746                 ast_log(LOG_WARNING,"Unrecognized txmixb parameter: %s\n",s);
2747         }
2748
2749         //ast_log(LOG_WARNING, "set txmixb = %s\n", s);
2750 }
2751 /*
2752 */
2753 static void store_rxcdtype(struct chan_usbradio_pvt *o, const char *s)
2754 {
2755         if (!strcasecmp(s,"no")){
2756                 o->rxcdtype = CD_IGNORE;
2757         }
2758         else if (!strcasecmp(s,"usb")){
2759                 o->rxcdtype = CD_HID;
2760         }
2761         else if (!strcasecmp(s,"dsp")){
2762                 o->rxcdtype = CD_XPMR_NOISE;
2763         }       
2764         else if (!strcasecmp(s,"vox")){
2765                 o->rxcdtype = CD_XPMR_VOX;
2766         }       
2767         else if (!strcasecmp(s,"usbinvert")){
2768                 o->rxcdtype = CD_HID_INVERT;
2769         }       
2770         else {
2771                 ast_log(LOG_WARNING,"Unrecognized rxcdtype parameter: %s\n",s);
2772         }
2773
2774         //ast_log(LOG_WARNING, "set rxcdtype = %s\n", s);
2775 }
2776 /*
2777 */
2778 static void store_rxsdtype(struct chan_usbradio_pvt *o, const char *s)
2779 {
2780         if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){
2781                 o->rxsdtype = SD_IGNORE;
2782         }
2783         else if (!strcasecmp(s,"usb") || !strcasecmp(s,"SD_HID")){
2784                 o->rxsdtype = SD_HID;
2785         }
2786         else if (!strcasecmp(s,"usbinvert") || !strcasecmp(s,"SD_HID_INVERT")){
2787                 o->rxsdtype = SD_HID_INVERT;
2788         }       
2789         else if (!strcasecmp(s,"software") || !strcasecmp(s,"SD_XPMR")){
2790                 o->rxsdtype = SD_XPMR;
2791         }       
2792         else {
2793                 ast_log(LOG_WARNING,"Unrecognized rxsdtype parameter: %s\n",s);
2794         }
2795
2796         //ast_log(LOG_WARNING, "set rxsdtype = %s\n", s);
2797 }
2798 /*
2799 */
2800 static void store_rxgain(struct chan_usbradio_pvt *o, const char *s)
2801 {
2802         float f;
2803         sscanf(s, "%30f", &f); 
2804         o->rxgain = f;
2805         //ast_log(LOG_WARNING, "set rxgain = %f\n", f);
2806 }
2807 /*
2808 */
2809 static void store_rxvoiceadj(struct chan_usbradio_pvt *o, const char *s)
2810 {
2811         float f;
2812         sscanf(s, "%30f", &f);
2813         o->rxvoiceadj = f;
2814         //ast_log(LOG_WARNING, "set rxvoiceadj = %f\n", f);
2815 }
2816 /*
2817 */
2818 static void store_rxctcssadj(struct chan_usbradio_pvt *o, const char *s)
2819 {
2820         float f;
2821         sscanf(s, "%30f", &f);
2822         o->rxctcssadj = f;
2823         //ast_log(LOG_WARNING, "set rxctcssadj = %f\n", f);
2824 }
2825 /*
2826 */
2827 static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s)
2828 {
2829         if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){
2830                 o->txtoctype = TOC_NONE;
2831         }
2832         else if (!strcasecmp(s,"phase") || !strcasecmp(s,"TOC_PHASE")){
2833                 o->txtoctype = TOC_PHASE;
2834         }
2835         else if (!strcasecmp(s,"notone") || !strcasecmp(s,"TOC_NOTONE")){
2836                 o->txtoctype = TOC_NOTONE;
2837         }       
2838         else {
2839                 ast_log(LOG_WARNING,"Unrecognized txtoctype parameter: %s\n",s);
2840         }
2841 }
2842 /*
2843 */
2844 static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd)
2845 {
2846         o->txtestkey=1;
2847         o->pmrChan->txPttIn=1;
2848         TxTestTone(o->pmrChan, 1);        // generate 1KHz tone at 7200 peak
2849         if (fd > 0) ast_cli(fd,"Tone output starting on channel %s...\n",o->name);
2850         usleep(5000000);
2851         TxTestTone(o->pmrChan, 0);
2852         if (fd > 0) ast_cli(fd,"Tone output ending on channel %s...\n",o->name);
2853         o->pmrChan->txPttIn=0;
2854         o->txtestkey=0;
2855 }
2856 /*
2857 */
2858 static void tune_rxinput(int fd, struct chan_usbradio_pvt *o)
2859 {
2860         const int target=23000;
2861         const int tolerance=2000;
2862         const int settingmin=1;
2863         const int settingstart=2;
2864         const int maxtries=12;
2865
2866         float settingmax;
2867         
2868         int setting=0, tries=0, tmpdiscfactor, meas;
2869         int tunetype=0;
2870
2871         settingmax = o->micmax;
2872
2873         if(o->pmrChan->rxDemod)tunetype=1;
2874         o->pmrChan->b.tuning=1;
2875
2876         setting = settingstart;
2877
2878     ast_cli(fd,"tune rxnoise maxtries=%i, target=%i, tolerance=%i\n",maxtries,target,tolerance);
2879
2880         while(tries<maxtries)
2881         {
2882                 setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,setting,0);
2883                 setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
2884        
2885                 usleep(100000);
2886                 if(o->rxcdtype!=CD_XPMR_NOISE || o->rxdemod==RX_AUDIO_SPEAKER) 
2887                 {
2888                         // printf("Measure Direct Input\n");
2889                         o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source;
2890                         o->pmrChan->spsMeasure->discfactor=2000;
2891                         o->pmrChan->spsMeasure->enabled=1;
2892                         o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
2893                         usleep(400000); 
2894                         meas=o->pmrChan->spsMeasure->apeak;
2895                         o->pmrChan->spsMeasure->enabled=0;      
2896                 }
2897                 else
2898                 {
2899                         // printf("Measure HF Noise\n");
2900                         tmpdiscfactor=o->pmrChan->spsRx->discfactor;
2901                         o->pmrChan->spsRx->discfactor=(i16)2000;
2902                         o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
2903                         o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
2904                         usleep(200000);
2905                         meas=o->pmrChan->rxRssi;
2906                         o->pmrChan->spsRx->discfactor=tmpdiscfactor;
2907                         o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
2908                         o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
2909                 }
2910         if(!meas)meas++;
2911                 ast_cli(fd,"tries=%i, setting=%i, meas=%i\n",tries,setting,meas);
2912
2913                 if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
2914                         setting=setting*target/meas;
2915                 }
2916                 else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
2917                 {
2918                         break;
2919                 }
2920
2921                 if(setting<settingmin)setting=settingmin;
2922                 else if(setting>settingmax)setting=settingmax;
2923
2924                 tries++;
2925         }
2926         ast_cli(fd,"DONE tries=%i, setting=%i, meas=%i\n",tries,
2927                 (setting * 1000) / o->micmax,meas);
2928         if( meas<(target-tolerance) || meas>(target+tolerance) ){
2929                 ast_cli(fd,"ERROR: RX INPUT ADJUST FAILED.\n");
2930         }else{
2931                 ast_cli(fd,"INFO: RX INPUT ADJUST SUCCESS.\n"); 
2932                 o->rxmixerset=(setting * 1000) / o->micmax;
2933         }
2934         o->pmrChan->b.tuning=0;
2935 }
2936 /*
2937 */
2938 static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o)
2939 {
2940         const int target=7200;                          // peak
2941         const int tolerance=360;                        // peak to peak
2942         const float settingmin=0.1;
2943         const float settingmax=4;
2944         const float settingstart=1;
2945         const int maxtries=12;
2946
2947         float setting;
2948
2949         int tries=0, meas;
2950
2951         ast_cli(fd,"INFO: RX VOICE ADJUST START.\n");   
2952         ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
2953
2954         o->pmrChan->b.tuning=1;
2955         if(!o->pmrChan->spsMeasure)
2956                 ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
2957
2958         if(!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
2959                 ast_cli(fd,"ERROR: NO SOURCE OR MEASURE SETTING.\n");
2960
2961         o->pmrChan->spsMeasure->source=o->pmrChan->spsRxOut->sink;
2962         o->pmrChan->spsMeasure->enabled=1;
2963         o->pmrChan->spsMeasure->discfactor=1000;
2964         
2965         setting=settingstart;
2966
2967         // ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
2968
2969         while(tries<maxtries)
2970         {
2971                 *(o->pmrChan->prxVoiceAdjust)=setting*M_Q8;
2972                 usleep(10000);
2973         o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
2974                 usleep(1000000);
2975                 meas = o->pmrChan->spsMeasure->apeak;
2976                 ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
2977
2978                 if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
2979                         setting=setting*target/meas;
2980                 }
2981                 else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
2982                 {
2983                         break;
2984                 }
2985                 if(setting<settingmin)setting=settingmin;
2986                 else if(setting>settingmax)setting=settingmax;
2987
2988                 tries++;
2989         }
2990
2991         o->pmrChan->spsMeasure->enabled=0;
2992
2993         ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
2994         if( meas<(target-tolerance) || meas>(target+tolerance) ){
2995                 ast_cli(fd,"ERROR: RX VOICE GAIN ADJUST FAILED.\n");
2996         }else{
2997                 ast_cli(fd,"INFO: RX VOICE GAIN ADJUST SUCCESS.\n");
2998                 o->rxvoiceadj=setting;
2999         }
3000         o->pmrChan->b.tuning=0;
3001 }
3002 /*
3003 */
3004 static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o)
3005 {
3006         const int target=2400;           // was 4096 pre 20080205
3007         const int tolerance=100;
3008         const float settingmin=0.1;
3009         const float settingmax=8;
3010         const float settingstart=1;
3011         const int maxtries=12;
3012
3013         float setting;
3014         int tries=0, meas;
3015
3016         ast_cli(fd,"INFO: RX CTCSS ADJUST START.\n");   
3017         ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
3018
3019         o->pmrChan->b.tuning=1;
3020         o->pmrChan->spsMeasure->source=o->pmrChan->prxCtcssMeasure;
3021         o->pmrChan->spsMeasure->discfactor=400;
3022         o->pmrChan->spsMeasure->enabled=1;
3023
3024         setting=settingstart;
3025
3026         while(tries<maxtries)
3027         {
3028                 *(o->pmrChan->prxCtcssAdjust)=setting*M_Q8;
3029                 usleep(10000);
3030         o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
3031                 usleep(500000);
3032                 meas = o->pmrChan->spsMeasure->apeak;
3033                 ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
3034
3035                 if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
3036                         setting=setting*target/meas;
3037                 }
3038                 else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
3039                 {
3040                         break;
3041                 }
3042                 if(setting<settingmin)setting=settingmin;
3043                 else if(setting>settingmax)setting=settingmax;
3044
3045                 tries++;
3046         }
3047         o->pmrChan->spsMeasure->enabled=0;
3048         ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
3049         if( meas<(target-tolerance) || meas>(target+tolerance) ){
3050                 ast_cli(fd,"ERROR: RX CTCSS GAIN ADJUST FAILED.\n");
3051         }else{
3052                 ast_cli(fd,"INFO: RX CTCSS GAIN ADJUST SUCCESS.\n");
3053                 o->rxctcssadj=setting;
3054         }
3055         o->pmrChan->b.tuning=0;
3056 }
3057 /*
3058         after radio tune is performed data is serialized here 
3059 */
3060 static void tune_write(struct chan_usbradio_pvt *o)
3061 {
3062         FILE *fp;
3063         char fname[200];
3064
3065         snprintf(fname,sizeof(fname) - 1,"/etc/asterisk/usbradio_tune_%s.conf",o->name);
3066         fp = fopen(fname,"w");
3067
3068         fprintf(fp,"[%s]\n",o->name);
3069
3070         fprintf(fp,"; name=%s\n",o->name);
3071         fprintf(fp,"; devicenum=%i\n",o->devicenum);
3072         fprintf(fp,"devstr=%s\n",o->devstr);
3073         fprintf(fp,"rxmixerset=%i\n",o->rxmixerset);
3074         fprintf(fp,"txmixaset=%i\n",o->txmixaset);
3075         fprintf(fp,"txmixbset=%i\n",o->txmixbset);
3076         fprintf(fp,"rxvoiceadj=%f\n",o->rxvoiceadj);
3077         fprintf(fp,"rxctcssadj=%f\n",o->rxctcssadj);
3078         fprintf(fp,"txctcssadj=%i\n",o->txctcssadj);
3079         fprintf(fp,"rxsquelchadj=%i\n",o->rxsquelchadj);
3080         fclose(fp);
3081
3082         if(o->wanteeprom)
3083         {
3084                 ast_mutex_lock(&o->eepromlock);
3085                 while(o->eepromctl)
3086                 {
3087                         ast_mutex_unlock(&o->eepromlock);
3088                         usleep(10000);
3089                         ast_mutex_lock(&o->eepromlock);
3090                 }
3091                 o->eeprom[EEPROM_RXMIXERSET] = o->rxmixerset;
3092                 o->eeprom[EEPROM_TXMIXASET] = o->txmixaset;
3093                 o->eeprom[EEPROM_TXMIXBSET] = o->txmixbset;
3094                 memcpy(&o->eeprom[EEPROM_RXVOICEADJ],&o->rxvoiceadj,sizeof(float));
3095                 memcpy(&o->eeprom[EEPROM_RXCTCSSADJ],&o->rxctcssadj,sizeof(float));
3096                 o->eeprom[EEPROM_TXCTCSSADJ] = o->txctcssadj;
3097                 o->eeprom[EEPROM_RXSQUELCHADJ] = o->rxsquelchadj;
3098                 o->eepromctl = 2;  /* request a write */
3099                 ast_mutex_unlock(&o->eepromlock);
3100         }
3101 }
3102 //
3103 static void mixer_write(struct chan_usbradio_pvt *o)
3104 {
3105         setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_SW,0,0);
3106         setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_VOL,0,0);
3107         setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_SW,1,0);
3108         setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL,
3109                 o->txmixaset * o->spkrmax / 1000,
3110                 o->txmixbset * o->spkrmax / 1000);
3111         setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,
3112                 o->rxmixerset * o->micmax / 1000,0);
3113         setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
3114         setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_SW,1,0);
3115 }
3116 /*
3117         adjust dsp multiplier to add resolution to tx level adjustment
3118 */
3119 static void mult_set(struct chan_usbradio_pvt *o)
3120 {
3121
3122         if(o->pmrChan->spsTxOutA) {
3123                 o->pmrChan->spsTxOutA->outputGain = 
3124                         mult_calc((o->txmixaset * 152) / 1000);
3125         }
3126         if(o->pmrChan->spsTxOutB){
3127                 o->pmrChan->spsTxOutB->outputGain = 
3128                         mult_calc((o->txmixbset * 152) / 1000);
3129         }
3130 }
3131 //
3132 // input 0 - 151 outputs are pot and multiplier
3133 //
3134 static int mult_calc(int value)