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