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