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