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