Sun Oct 16 2011 08:41:37

Asterisk developer's documentation


chan_usbradio.c
Go to the documentation of this file.
00001 #define  NEW_ASTERISK
00002 /*
00003  * Asterisk -- An open source telephony toolkit.
00004  *
00005  * Copyright (C) 1999 - 2005, Digium, Inc.
00006  * Copyright (C) 2007 - 2008, Jim Dixon
00007  *
00008  * Jim Dixon, WB6NIL <jim@lambdatel.com>
00009  * Steve Henke, W9SH  <w9sh@arrl.net>
00010  * Based upon work by Mark Spencer <markster@digium.com> and Luigi Rizzo
00011  *
00012  * See http://www.asterisk.org for more information about
00013  * the Asterisk project. Please do not directly contact
00014  * any of the maintainers of this project for assistance;
00015  * the project provides a web site, mailing lists and IRC
00016  * channels for your use.
00017  *
00018  * This program is free software, distributed under the terms of
00019  * the GNU General Public License Version 2. See the LICENSE file
00020   * at the top of the source tree.
00021  */
00022 
00023 /*! \file
00024  *
00025  * \brief Channel driver for CM108 USB Cards with Radio Interface
00026  *
00027  * \author Jim Dixon  <jim@lambdatel.com>
00028  * \author Steve Henke  <w9sh@arrl.net>
00029  *
00030  * \par See also
00031  * \arg \ref Config_usbradio
00032  *
00033  * \ingroup channel_drivers
00034  */
00035 
00036 /*** MODULEINFO
00037    <depend>oss</depend>
00038    <depend>alsa</depend>
00039    <depend>usb</depend>
00040    <defaultenabled>no</defaultenabled>
00041    <support_level>extended</support_level>
00042  ***/
00043 
00044 /*** MAKEOPTS
00045 <category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes">
00046    <member name="RADIO_RTX" displayname="Build RTX/DTX Radio Programming" touch_on_change="channels/chan_usbradio.c channels/xpmr/xpmr.h">
00047       <defaultenabled>no</defaultenabled>
00048       <depend>chan_usbradio</depend>
00049    </member>
00050    <member name="RADIO_XPMRX" displayname="Build Experimental Radio Protocols" touch_on_change="channels/chan_usbradio.c">
00051       <defaultenabled>no</defaultenabled>
00052       <depend>chan_usbradio</depend>
00053    </member>
00054 </category>
00055  ***/
00056 
00057 // 20070918 1600 EDT sph@xelatec.com changing to rx driven streams
00058 
00059 #include "asterisk.h"
00060 
00061 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00062 
00063 #include <stdio.h>
00064 #include <ctype.h>
00065 #include <math.h>
00066 #include <string.h>
00067 #include <unistd.h>
00068 #ifdef HAVE_SYS_IO_H
00069 #include <sys/io.h>
00070 #endif
00071 #include <sys/ioctl.h>
00072 #include <fcntl.h>
00073 #include <sys/time.h>
00074 #include <stdlib.h>
00075 #include <errno.h>
00076 #include <usb.h>
00077 #include <alsa/asoundlib.h>
00078 
00079 //#define HAVE_XPMRX          1
00080 #ifdef RADIO_XPMRX
00081 #define HAVE_XPMRX            1
00082 #endif
00083 
00084 #define CHAN_USBRADIO           1
00085 #define DEBUG_USBRADIO          0   
00086 #define DEBUG_CAPTURES        1
00087 #define DEBUG_CAP_RX_OUT      0        
00088 #define DEBUG_CAP_TX_OUT       0       
00089 #define DEBUG_FILETEST        0         
00090 
00091 #define RX_CAP_RAW_FILE       "/tmp/rx_cap_in.pcm"
00092 #define RX_CAP_TRACE_FILE     "/tmp/rx_trace.pcm"
00093 #define RX_CAP_OUT_FILE       "/tmp/rx_cap_out.pcm"
00094 
00095 #define TX_CAP_RAW_FILE       "/tmp/tx_cap_in.pcm"
00096 #define TX_CAP_TRACE_FILE     "/tmp/tx_trace.pcm"
00097 #define TX_CAP_OUT_FILE       "/tmp/tx_cap_out.pcm"
00098 
00099 #define  MIXER_PARAM_MIC_PLAYBACK_SW "Mic Playback Switch"
00100 #define MIXER_PARAM_MIC_PLAYBACK_VOL "Mic Playback Volume"
00101 #define  MIXER_PARAM_MIC_CAPTURE_SW "Mic Capture Switch"
00102 #define  MIXER_PARAM_MIC_CAPTURE_VOL "Mic Capture Volume"
00103 #define  MIXER_PARAM_MIC_BOOST "Auto Gain Control"
00104 #define  MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
00105 #define  MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
00106 
00107 #define  DELIMCHR ','
00108 #define  QUOTECHR 34
00109 
00110 #define  READERR_THRESHOLD 50
00111 
00112 #include "./xpmr/xpmr.h"
00113 #ifdef HAVE_XPMRX
00114 #include "./xpmrx/xpmrx.h"
00115 #include "./xpmrx/bitweight.h"
00116 #endif
00117 
00118 #if 0
00119 #define traceusb1(a) {printf a;}
00120 #else
00121 #define traceusb1(a)
00122 #endif
00123 
00124 #if 0
00125 #define traceusb2(a) {printf a;}
00126 #else
00127 #define traceusb2(a)
00128 #endif
00129 
00130 #ifdef __linux
00131 #include <linux/soundcard.h>
00132 #elif defined(__FreeBSD__)
00133 #include <sys/soundcard.h>
00134 #else
00135 #include <soundcard.h>
00136 #endif
00137 
00138 #include "asterisk/lock.h"
00139 #include "asterisk/frame.h"
00140 #include "asterisk/logger.h"
00141 #include "asterisk/callerid.h"
00142 #include "asterisk/channel.h"
00143 #include "asterisk/module.h"
00144 #include "asterisk/options.h"
00145 #include "asterisk/pbx.h"
00146 #include "asterisk/config.h"
00147 #include "asterisk/cli.h"
00148 #include "asterisk/utils.h"
00149 #include "asterisk/causes.h"
00150 #include "asterisk/endian.h"
00151 #include "asterisk/stringfields.h"
00152 #include "asterisk/abstract_jb.h"
00153 #include "asterisk/musiconhold.h"
00154 #include "asterisk/dsp.h"
00155 
00156 #ifndef  NEW_ASTERISK
00157 
00158 /* ringtones we use */
00159 #include "busy.h"
00160 #include "ringtone.h"
00161 #include "ring10.h"
00162 #include "answer.h"
00163 
00164 #endif
00165 
00166 #define C108_VENDOR_ID     0x0d8c
00167 #define C108_PRODUCT_ID    0x000c
00168 #define C108_HID_INTERFACE 3
00169 
00170 #define HID_REPORT_GET     0x01
00171 #define HID_REPORT_SET     0x09
00172 
00173 #define HID_RT_INPUT    0x01
00174 #define HID_RT_OUTPUT      0x02
00175 
00176 #define  EEPROM_START_ADDR 6
00177 #define  EEPROM_END_ADDR      63
00178 #define  EEPROM_PHYSICAL_LEN  64
00179 #define EEPROM_TEST_ADDR   EEPROM_END_ADDR
00180 #define  EEPROM_MAGIC_ADDR 6
00181 #define  EEPROM_MAGIC      34329
00182 #define  EEPROM_CS_ADDR    62
00183 #define  EEPROM_RXMIXERSET 8
00184 #define  EEPROM_TXMIXASET  9
00185 #define  EEPROM_TXMIXBSET  10
00186 #define  EEPROM_RXVOICEADJ 11
00187 #define  EEPROM_RXCTCSSADJ 13
00188 #define  EEPROM_TXCTCSSADJ 15
00189 #define  EEPROM_RXSQUELCHADJ  16
00190 
00191 /*! Global jitterbuffer configuration - by default, jb is disabled
00192  *  \note Values shown here match the defaults shown in usbradio.conf.sample */
00193 static struct ast_jb_conf default_jbconf =
00194 {
00195    .flags = 0,
00196    .max_size = 200,
00197    .resync_threshold = 1000,
00198    .impl = "fixed",
00199    .target_extra = 40,
00200 };
00201 static struct ast_jb_conf global_jbconf;
00202 
00203 /*
00204  * usbradio.conf parameters are
00205 START_CONFIG
00206 
00207 [general]
00208     ; General config options which propigate to all devices, with
00209     ; default values shown. You may have as many devices as the
00210     ; system will allow. You must use one section per device, with
00211     ; [usb] generally (although its up to you) being the first device.
00212     ;
00213     ;
00214     ; debug = 0x0    ; misc debug flags, default is 0
00215 
00216    ; Set the device to use for I/O
00217    ; devicenum = 0
00218    ; Set hardware type here
00219    ; hdwtype=0               ; 0=limey, 1=sph
00220 
00221    ; rxboost=0          ; no rx gain boost
00222    ; rxctcssrelax=1        ; reduce talkoff from radios w/o CTCSS Tx HPF
00223    ; rxctcssfreqs=100.0,123.0      ; list of rx ctcss freq in floating point. must be in table
00224    ; txctcssfreqs=100.0,123.0      ; list tx ctcss freq, any frequency permitted
00225    ; txctcssdefault=100.0      ; default tx ctcss freq, any frequency permitted
00226 
00227    ; carrierfrom=dsp     ;no,usb,usbinvert,dsp,vox
00228    ; ctcssfrom=dsp       ;no,usb,dsp
00229 
00230    ; rxdemod=flat            ; input type from radio: no,speaker,flat
00231    ; txprelim=yes            ; output is pre-emphasised and limited
00232    ; txtoctype=no            ; no,phase,notone
00233 
00234    ; txmixa=composite        ;no,voice,tone,composite,auxvoice
00235    ; txmixb=no               ;no,voice,tone,composite,auxvoice
00236 
00237    ; invertptt=0
00238 
00239     ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
00240     ; jbenable = yes              ; Enables the use of a jitterbuffer on the receiving side of an
00241                                   ; USBRADIO channel. Defaults to "no". An enabled jitterbuffer will
00242                                   ; be used only if the sending side can create and the receiving
00243                                   ; side can not accept jitter. The USBRADIO channel can't accept jitter,
00244                                   ; thus an enabled jitterbuffer on the receive USBRADIO side will always
00245                                   ; be used if the sending side can create jitter.
00246 
00247     ; jbmaxsize = 200             ; Max length of the jitterbuffer in milliseconds.
00248 
00249     ; jbresyncthreshold = 1000    ; Jump in the frame timestamps over which the jitterbuffer is
00250                                   ; resynchronized. Useful to improve the quality of the voice, with
00251                                   ; big jumps in/broken timestamps, usualy sent from exotic devices
00252                                   ; and programs. Defaults to 1000.
00253 
00254     ; jbimpl = fixed              ; Jitterbuffer implementation, used on the receiving side of an USBRADIO
00255                                   ; channel. Two implementations are currenlty available - "fixed"
00256                                   ; (with size always equals to jbmax-size) and "adaptive" (with
00257                                   ; variable size, actually the new jb of IAX2). Defaults to fixed.
00258 
00259     ; jblog = no                  ; Enables jitterbuffer frame logging. Defaults to "no".
00260     ;-----------------------------------------------------------------------------------
00261 
00262 [usb]
00263 
00264 ; First channel unique config
00265 
00266 [usb1]
00267 
00268 ; Second channel config
00269 
00270 END_CONFIG
00271 
00272  */
00273 
00274 /*
00275  * Helper macros to parse config arguments. They will go in a common
00276  * header file if their usage is globally accepted. In the meantime,
00277  * we define them here. Typical usage is as below.
00278  * Remember to open a block right before M_START (as it declares
00279  * some variables) and use the M_* macros WITHOUT A SEMICOLON:
00280  *
00281  * {
00282  *    M_START(v->name, v->value) 
00283  *
00284  *    M_BOOL("dothis", x->flag1)
00285  *    M_STR("name", x->somestring)
00286  *    M_F("bar", some_c_code)
00287  *    M_END(some_final_statement)
00288  *    ... other code in the block
00289  * }
00290  *
00291  * XXX NOTE these macros should NOT be replicated in other parts of asterisk. 
00292  * Likely we will come up with a better way of doing config file parsing.
00293  */
00294 #define M_START(var, val) \
00295         char *__s = var; char *__val = val;
00296 #define M_END(x)   x;
00297 #define M_F(tag, f)        if (!strcasecmp((__s), tag)) { f; } else
00298 #define M_BOOL(tag, dst)   M_F(tag, (dst) = ast_true(__val) )
00299 #define M_UINT(tag, dst)   M_F(tag, (dst) = strtoul(__val, NULL, 0) )
00300 #define M_STR(tag, dst)    M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
00301 
00302 /*
00303  * The following parameters are used in the driver:
00304  *
00305  *  FRAME_SIZE the size of an audio frame, in samples.
00306  *    160 is used almost universally, so you should not change it.
00307  *
00308  *  FRAGS   the argument for the SETFRAGMENT ioctl.
00309  *    Overridden by the 'frags' parameter in usbradio.conf
00310  *
00311  *    Bits 0-7 are the base-2 log of the device's block size,
00312  *    bits 16-31 are the number of blocks in the driver's queue.
00313  *    There are a lot of differences in the way this parameter
00314  *    is supported by different drivers, so you may need to
00315  *    experiment a bit with the value.
00316  *    A good default for linux is 30 blocks of 64 bytes, which
00317  *    results in 6 frames of 320 bytes (160 samples).
00318  *    FreeBSD works decently with blocks of 256 or 512 bytes,
00319  *    leaving the number unspecified.
00320  *    Note that this only refers to the device buffer size,
00321  *    this module will then try to keep the lenght of audio
00322  *    buffered within small constraints.
00323  *
00324  *  QUEUE_SIZE The max number of blocks actually allowed in the device
00325  *    driver's buffer, irrespective of the available number.
00326  *    Overridden by the 'queuesize' parameter in usbradio.conf
00327  *
00328  *    Should be >=2, and at most as large as the hw queue above
00329  *    (otherwise it will never be full).
00330  */
00331 
00332 #define FRAME_SIZE   160
00333 #define  QUEUE_SIZE  2           
00334 
00335 #if defined(__FreeBSD__)
00336 #define  FRAGS 0x8
00337 #else
00338 #define  FRAGS ( ( (6 * 5) << 16 ) | 0xc )
00339 #endif
00340 
00341 /*
00342  * XXX text message sizes are probably 256 chars, but i am
00343  * not sure if there is a suitable definition anywhere.
00344  */
00345 #define TEXT_SIZE 256
00346 
00347 #if 0
00348 #define  TRYOPEN  1           /* try to open on startup */
00349 #endif
00350 #define  O_CLOSE  0x444       /* special 'close' mode for device */
00351 /* Which device to use */
00352 #if defined( __OpenBSD__ ) || defined( __NetBSD__ )
00353 #define DEV_DSP "/dev/audio"
00354 #else
00355 #define DEV_DSP "/dev/dsp"
00356 #endif
00357 
00358 static const char *config = "usbradio.conf"; /* default config file */
00359 #define config1 "usbradio_tune_%s.conf"    /* tune config file */
00360 
00361 static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
00362 static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
00363 
00364 static char *usb_device_list = NULL;
00365 static int usb_device_list_size = 0;
00366 
00367 static int usbradio_debug;
00368 #if 0 //maw asdf sph
00369 static int usbradio_debug_level = 0;
00370 #endif
00371 
00372 enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
00373 enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
00374 enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR};               // no,external,externalinvert,software
00375 enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
00376 enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
00377 enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
00378 
00379 /* DECLARE STRUCTURES */
00380 
00381 /*
00382  * Each sound is made of 'datalen' samples of sound, repeated as needed to
00383  * generate 'samplen' samples of data, then followed by 'silencelen' samples
00384  * of silence. The loop is repeated if 'repeat' is set.
00385  */
00386 struct sound {
00387    int ind;
00388    char *desc;
00389    short *data;
00390    int datalen;
00391    int samplen;
00392    int silencelen;
00393    int repeat;
00394 };
00395 
00396 #ifndef  NEW_ASTERISK
00397 
00398 static struct sound sounds[] = {
00399    { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
00400    { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
00401    { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
00402    { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
00403    { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
00404    { -1, NULL, 0, 0, 0, 0 },  /* end marker */
00405 };
00406 
00407 #endif
00408 
00409 /*
00410  * descriptor for one of our channels.
00411  * There is one used for 'default' values (from the [general] entry in
00412  * the configuration file), and then one instance for each device
00413  * (the default is cloned from [general], others are only created
00414  * if the relevant section exists).
00415  */
00416 struct chan_usbradio_pvt {
00417    struct chan_usbradio_pvt *next;
00418 
00419    char *name;
00420 #ifndef  NEW_ASTERISK
00421    /*
00422     * cursound indicates which in struct sound we play. -1 means nothing,
00423     * any other value is a valid sound, in which case sampsent indicates
00424     * the next sample to send in [0..samplen + silencelen]
00425     * nosound is set to disable the audio data from the channel
00426     * (so we can play the tones etc.).
00427     */
00428    int sndcmd[2];          /* Sound command pipe */
00429    int cursound;           /* index of sound to send */
00430    int sampsent;           /* # of sound samples sent  */
00431    int nosound;            /* set to block audio from the PBX */
00432 #endif
00433 
00434    int pttkick[2];
00435    int total_blocks;       /* total blocks in the output device */
00436    int sounddev;
00437    enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
00438    i16 cdMethod;
00439    int autoanswer;
00440    int autohangup;
00441    int hookstate;
00442    unsigned int queuesize;    /* max fragments in queue */
00443    unsigned int frags;        /* parameter for SETFRAGMENT */
00444 
00445    int warned;             /* various flags used for warnings */
00446 #define WARN_used_blocks   1
00447 #define WARN_speed      2
00448 #define WARN_frag    4
00449    int w_errors;           /* overfull in the write path */
00450    struct timeval lastopen;
00451 
00452    int overridecontext;
00453    int mute;
00454 
00455    /* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
00456     * be representable in 16 bits to avoid overflows.
00457     */
00458 #define  BOOST_SCALE (1<<9)
00459 #define  BOOST_MAX   40       /* slightly less than 7 bits */
00460    int boost;              /* input boost, scaled by BOOST_SCALE */
00461    char devicenum;
00462    char devstr[128];
00463    int spkrmax;
00464    int micmax;
00465 
00466 #ifndef  NEW_ASTERISK
00467    pthread_t sthread;
00468 #endif
00469    pthread_t hidthread;
00470 
00471    int stophid;
00472    FILE *hkickhid;
00473 
00474    struct ast_channel *owner;
00475    char ext[AST_MAX_EXTENSION];
00476    char ctx[AST_MAX_CONTEXT];
00477    char language[MAX_LANGUAGE];
00478    char cid_name[256];        /*XXX */
00479    char cid_num[256];         /*XXX */
00480    char mohinterpret[MAX_MUSICCLASS];
00481 
00482    /* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */
00483    char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];    
00484    char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6];
00485 
00486    int usbradio_write_dst;
00487    /* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
00488     * plus enough room for a full frame
00489     */
00490    char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
00491    char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
00492    int readpos;            /* read position above */
00493    struct ast_frame read_f;   /* returned by usbradio_read */
00494 
00495    char  debuglevel;
00496    char  radioduplex;         // 
00497    char    wanteeprom;
00498 
00499    int   tracetype;
00500    int     tracelevel;
00501    char    area;
00502    char  rptnum;
00503    int     idleinterval;
00504    int      turnoffs;
00505    int   txsettletime;
00506    char    ukey[48];
00507 
00508    char lastrx;
00509    char rxhidsq;
00510    char rxcarrierdetect;      // status from pmr channel
00511    char rxctcssdecode;        // status from pmr channel
00512 
00513    int  rxdcsdecode;
00514    int  rxlsddecode;
00515 
00516    char rxkeytype;
00517    char rxkeyed;           // indicates rx signal present
00518 
00519    char lasttx;
00520    char txkeyed;           // tx key request from upper layers 
00521    char txchankey;
00522    char txtestkey;
00523 
00524    time_t lasthidtime;
00525     struct ast_dsp *dsp;
00526 
00527    t_pmr_chan  *pmrChan;
00528 
00529    char    rxcpusaver;
00530    char    txcpusaver;
00531 
00532    char  rxdemod;
00533    float rxgain;
00534    char  rxcdtype;
00535    char  rxsdtype;
00536    int      rxsquelchadj;   /* this copy needs to be here for initialization */
00537    int     rxsqvoxadj;
00538    char  txtoctype;
00539 
00540    char    txprelim;
00541    float txctcssgain;
00542    char  txmixa;
00543    char  txmixb;
00544 
00545    char  invertptt;
00546 
00547    char  rxctcssrelax;
00548    float rxctcssgain;
00549 
00550    char    txctcssdefault[16];            // for repeater operation
00551    char  rxctcssfreqs[512];            // a string
00552    char    txctcssfreqs[512];
00553 
00554    char  txctcssfreq[32];           // encode now
00555    char  rxctcssfreq[32];           // decode now
00556 
00557    char    numrxctcssfreqs;            // how many
00558    char    numtxctcssfreqs;
00559 
00560    char    *rxctcss[CTCSS_NUM_CODES];     // pointers to strings
00561    char    *txctcss[CTCSS_NUM_CODES];
00562 
00563    int      txfreq;                    // in Hz
00564    int     rxfreq;
00565 
00566    //       start remote operation info
00567    char    set_txctcssdefault[16];           // for remote operation
00568    char  set_txctcssfreq[16];          // encode now
00569    char  set_rxctcssfreq[16];          // decode now
00570 
00571    char    set_numrxctcssfreqs;           // how many
00572    char    set_numtxctcssfreqs;
00573 
00574    char  set_rxctcssfreqs[16];            // a string
00575    char    set_txctcssfreqs[16];
00576 
00577    char    *set_rxctcss;                   // pointers to strings
00578    char    *set_txctcss;
00579 
00580    int      set_txfreq;                   // in Hz
00581    int     set_rxfreq;
00582    //       end remote operation info
00583 
00584    int         rxmixerset;       
00585    int   rxboostset;
00586    float rxvoiceadj;
00587    float rxctcssadj;
00588    int   txmixaset;
00589    int   txmixbset;
00590    int     txctcssadj;
00591 
00592    int      hdwtype;
00593    int      hid_gpio_ctl;     
00594    int      hid_gpio_ctl_loc; 
00595    int      hid_io_cor;       
00596    int      hid_io_cor_loc;   
00597    int      hid_io_ctcss;     
00598    int      hid_io_ctcss_loc;    
00599    int      hid_io_ptt;       
00600    int      hid_gpio_loc;     
00601 
00602    struct {
00603        unsigned rxcapraw:1;
00604       unsigned txcapraw:1;
00605       unsigned txcap2:1;
00606       unsigned rxcap2:1;
00607       unsigned rxplmon:1;
00608       unsigned remoted:1;
00609       unsigned txpolarity:1;
00610       unsigned rxpolarity:1;
00611       unsigned dcstxpolarity:1;
00612       unsigned dcsrxpolarity:1;
00613       unsigned lsdtxpolarity:1;
00614       unsigned lsdrxpolarity:1;
00615       unsigned loopback:1;
00616       unsigned radioactive:1;
00617    }b;
00618    unsigned short eeprom[EEPROM_PHYSICAL_LEN];
00619    char eepromctl;
00620    ast_mutex_t eepromlock;
00621 
00622    struct usb_dev_handle *usb_handle;
00623    int readerrs;
00624 };
00625 
00626 // maw add additional defaults !!!
00627 static struct chan_usbradio_pvt usbradio_default = {
00628 #ifndef  NEW_ASTERISK
00629    .cursound = -1,
00630 #endif
00631    .sounddev = -1,
00632    .duplex = M_UNSET,         /* XXX check this */
00633    .autoanswer = 1,
00634    .autohangup = 1,
00635    .queuesize = QUEUE_SIZE,
00636    .frags = FRAGS,
00637    .ext = "s",
00638    .ctx = "default",
00639    .readpos = AST_FRIENDLY_OFFSET,  /* start here on reads */
00640    .lastopen = { 0, 0 },
00641    .boost = BOOST_SCALE,
00642    .wanteeprom = 1,
00643    .area = 0,
00644    .rptnum = 0,
00645 };
00646 
00647 /* DECLARE FUNCTION PROTOTYPES   */
00648 
00649 static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s);
00650 static int  hidhdwconfig(struct chan_usbradio_pvt *o);
00651 static int set_txctcss_level(struct chan_usbradio_pvt *o);
00652 static void pmrdump(struct chan_usbradio_pvt *o);
00653 static void mult_set(struct chan_usbradio_pvt *o);
00654 static int  mult_calc(int value);
00655 static void mixer_write(struct chan_usbradio_pvt *o);
00656 static void tune_rxinput(int fd, struct chan_usbradio_pvt *o);
00657 static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o);
00658 static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o);
00659 static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd);
00660 static void tune_write(struct chan_usbradio_pvt *o);
00661 
00662 static char *usbradio_active;  /* the active device */
00663 
00664 static int setformat(struct chan_usbradio_pvt *o, int mode);
00665 
00666 static struct ast_channel *usbradio_request(const char *type, format_t format,
00667       const struct ast_channel *requestor,
00668       void *data, int *cause);
00669 static int usbradio_digit_begin(struct ast_channel *c, char digit);
00670 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration);
00671 static int usbradio_text(struct ast_channel *c, const char *text);
00672 static int usbradio_hangup(struct ast_channel *c);
00673 static int usbradio_answer(struct ast_channel *c);
00674 static struct ast_frame *usbradio_read(struct ast_channel *chan);
00675 static int usbradio_call(struct ast_channel *c, char *dest, int timeout);
00676 static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
00677 static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
00678 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00679 static int xpmr_config(struct chan_usbradio_pvt *o);
00680 
00681 #if   DEBUG_FILETEST == 1
00682 static int RxTestIt(struct chan_usbradio_pvt *o);
00683 #endif
00684 
00685 static char tdesc[] = "USB (CM108) Radio Channel Driver";
00686 
00687 static const struct ast_channel_tech usbradio_tech = {
00688    .type = "Radio",
00689    .description = tdesc,
00690    .capabilities = AST_FORMAT_SLINEAR,
00691    .requester = usbradio_request,
00692    .send_digit_begin = usbradio_digit_begin,
00693    .send_digit_end = usbradio_digit_end,
00694    .send_text = usbradio_text,
00695    .hangup = usbradio_hangup,
00696    .answer = usbradio_answer,
00697    .read = usbradio_read,
00698    .call = usbradio_call,
00699    .write = usbradio_write,
00700    .indicate = usbradio_indicate,
00701    .fixup = usbradio_fixup,
00702 };
00703 
00704 /* Call with:  devnum: alsa major device number, param: ascii Formal
00705 Parameter Name, val1, first or only value, val2 second value, or 0 
00706 if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
00707 
00708 Note: must add -lasound to end of linkage */
00709 
00710 static int amixer_max(int devnum,char *param)
00711 {
00712 int   rv,type;
00713 char  str[100];
00714 snd_hctl_t *hctl;
00715 snd_ctl_elem_id_t *id;
00716 snd_hctl_elem_t *elem;
00717 snd_ctl_elem_info_t *info;
00718 
00719    sprintf(str,"hw:%d",devnum);
00720    if (snd_hctl_open(&hctl, str, 0)) return(-1);
00721    snd_hctl_load(hctl);
00722    snd_ctl_elem_id_alloca(&id);
00723    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
00724    snd_ctl_elem_id_set_name(id, param);  
00725    elem = snd_hctl_find_elem(hctl, id);
00726    if (!elem)
00727    {
00728       snd_hctl_close(hctl);
00729       return(-1);
00730    }
00731    snd_ctl_elem_info_alloca(&info);
00732    snd_hctl_elem_info(elem,info);
00733    type = snd_ctl_elem_info_get_type(info);
00734    rv = 0;
00735    switch(type)
00736    {
00737        case SND_CTL_ELEM_TYPE_INTEGER:
00738       rv = snd_ctl_elem_info_get_max(info);
00739       break;
00740        case SND_CTL_ELEM_TYPE_BOOLEAN:
00741       rv = 1;
00742       break;
00743    }
00744    snd_hctl_close(hctl);
00745    return(rv);
00746 }
00747 
00748 /* Call with:  devnum: alsa major device number, param: ascii Formal
00749 Parameter Name, val1, first or only value, val2 second value, or 0 
00750 if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
00751 
00752 Note: must add -lasound to end of linkage */
00753 
00754 static int setamixer(int devnum,char *param, int v1, int v2)
00755 {
00756 int   type;
00757 char  str[100];
00758 snd_hctl_t *hctl;
00759 snd_ctl_elem_id_t *id;
00760 snd_ctl_elem_value_t *control;
00761 snd_hctl_elem_t *elem;
00762 snd_ctl_elem_info_t *info;
00763 
00764    sprintf(str,"hw:%d",devnum);
00765    if (snd_hctl_open(&hctl, str, 0)) return(-1);
00766    snd_hctl_load(hctl);
00767    snd_ctl_elem_id_alloca(&id);
00768    snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
00769    snd_ctl_elem_id_set_name(id, param);  
00770    elem = snd_hctl_find_elem(hctl, id);
00771    if (!elem)
00772    {
00773       snd_hctl_close(hctl);
00774       return(-1);
00775    }
00776    snd_ctl_elem_info_alloca(&info);
00777    snd_hctl_elem_info(elem,info);
00778    type = snd_ctl_elem_info_get_type(info);
00779    snd_ctl_elem_value_alloca(&control);
00780    snd_ctl_elem_value_set_id(control, id);    
00781    switch(type)
00782    {
00783        case SND_CTL_ELEM_TYPE_INTEGER:
00784       snd_ctl_elem_value_set_integer(control, 0, v1);
00785       if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2);
00786       break;
00787        case SND_CTL_ELEM_TYPE_BOOLEAN:
00788       snd_ctl_elem_value_set_integer(control, 0, (v1 != 0));
00789       break;
00790    }
00791    if (snd_hctl_elem_write(elem, control))
00792    {
00793       snd_hctl_close(hctl);
00794       return(-1);
00795    }
00796    snd_hctl_close(hctl);
00797    return(0);
00798 }
00799 
00800 static void hid_set_outputs(struct usb_dev_handle *handle,
00801          unsigned char *outputs)
00802 {
00803    usleep(1500);
00804    usb_control_msg(handle,
00805          USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
00806          HID_REPORT_SET,
00807          0 + (HID_RT_OUTPUT << 8),
00808          C108_HID_INTERFACE,
00809          (char*)outputs, 4, 5000);
00810 }
00811 
00812 static void hid_get_inputs(struct usb_dev_handle *handle,
00813          unsigned char *inputs)
00814 {
00815    usleep(1500);
00816    usb_control_msg(handle,
00817          USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
00818          HID_REPORT_GET,
00819          0 + (HID_RT_INPUT << 8),
00820          C108_HID_INTERFACE,
00821          (char*)inputs, 4, 5000);
00822 }
00823 
00824 static unsigned short read_eeprom(struct usb_dev_handle *handle, int addr)
00825 {
00826    unsigned char buf[4];
00827 
00828    buf[0] = 0x80;
00829    buf[1] = 0;
00830    buf[2] = 0;
00831    buf[3] = 0x80 | (addr & 0x3f);
00832    hid_set_outputs(handle,buf);
00833    memset(buf,0,sizeof(buf));
00834    hid_get_inputs(handle,buf);
00835    return(buf[1] + (buf[2] << 8));
00836 }
00837 
00838 static void write_eeprom(struct usb_dev_handle *handle, int addr, 
00839    unsigned short data)
00840 {
00841 
00842    unsigned char buf[4];
00843 
00844    buf[0] = 0x80;
00845    buf[1] = data & 0xff;
00846    buf[2] = data >> 8;
00847    buf[3] = 0xc0 | (addr & 0x3f);
00848    hid_set_outputs(handle,buf);
00849 }
00850 
00851 static unsigned short get_eeprom(struct usb_dev_handle *handle,
00852    unsigned short *buf)
00853 {
00854 int   i;
00855 unsigned short cs;
00856 
00857    cs = 0xffff;
00858    for(i = EEPROM_START_ADDR; i < EEPROM_END_ADDR; i++)
00859    {
00860       cs += buf[i] = read_eeprom(handle,i);
00861    }
00862    return(cs);
00863 }
00864 
00865 static void put_eeprom(struct usb_dev_handle *handle,unsigned short *buf)
00866 {
00867 int   i;
00868 unsigned short cs;
00869 
00870    cs = 0xffff;
00871    buf[EEPROM_MAGIC_ADDR] = EEPROM_MAGIC;
00872    for(i = EEPROM_START_ADDR; i < EEPROM_CS_ADDR; i++)
00873    {
00874       write_eeprom(handle,i,buf[i]);
00875       cs += buf[i];
00876    }
00877    buf[EEPROM_CS_ADDR] = (65535 - cs) + 1;
00878    write_eeprom(handle,i,buf[EEPROM_CS_ADDR]);
00879 }
00880 
00881 static struct usb_device *hid_device_init(char *desired_device)
00882 {
00883     struct usb_bus *usb_bus;
00884     struct usb_device *dev;
00885     char devstr[200],str[200],desdev[200],*cp;
00886     int i;
00887     FILE *fp;
00888 
00889     usb_init();
00890     usb_find_busses();
00891     usb_find_devices();
00892     for (usb_bus = usb_busses;
00893          usb_bus;
00894          usb_bus = usb_bus->next) {
00895         for (dev = usb_bus->devices;
00896              dev;
00897              dev = dev->next) {
00898             if ((dev->descriptor.idVendor
00899                   == C108_VENDOR_ID) &&
00900                 (dev->descriptor.idProduct
00901                   == C108_PRODUCT_ID))
00902       {
00903                         sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
00904          for(i = 0; i < 32; i++)
00905          {
00906             sprintf(str,"/proc/asound/card%d/usbbus",i);
00907             fp = fopen(str,"r");
00908             if (!fp) continue;
00909             if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
00910             {
00911                fclose(fp);
00912                continue;
00913             }
00914             fclose(fp);
00915             if (desdev[strlen(desdev) - 1] == '\n')
00916                   desdev[strlen(desdev) -1 ] = 0;
00917             if (strcasecmp(desdev,devstr)) continue;
00918             if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
00919             else strcpy(str,"/sys/class/sound/dsp/device");
00920             memset(desdev,0,sizeof(desdev));
00921             if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
00922             {
00923                sprintf(str,"/sys/class/sound/controlC%d/device",i);
00924                memset(desdev,0,sizeof(desdev));
00925                if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
00926             }
00927             cp = strrchr(desdev,'/');
00928             if (cp) *cp = 0; else continue;
00929             cp = strrchr(desdev,'/');
00930             if (!cp) continue;
00931             cp++;
00932             break;
00933          }
00934          if (i >= 32) continue;
00935                         if (!strcmp(cp,desired_device)) return dev;
00936       }
00937 
00938         }
00939     }
00940     return NULL;
00941 }
00942 
00943 static int hid_device_mklist(void)
00944 {
00945     struct usb_bus *usb_bus;
00946     struct usb_device *dev;
00947     char devstr[200],str[200],desdev[200],*cp;
00948     int i;
00949     FILE *fp;
00950 
00951     usb_device_list = ast_malloc(2);
00952     if (!usb_device_list) return -1;
00953     memset(usb_device_list,0,2);
00954 
00955     usb_init();
00956     usb_find_busses();
00957     usb_find_devices();
00958     for (usb_bus = usb_busses;
00959          usb_bus;
00960          usb_bus = usb_bus->next) {
00961         for (dev = usb_bus->devices;
00962              dev;
00963              dev = dev->next) {
00964             if ((dev->descriptor.idVendor
00965                   == C108_VENDOR_ID) &&
00966                 (dev->descriptor.idProduct
00967                   == C108_PRODUCT_ID))
00968       {
00969                         sprintf(devstr,"%s/%s", usb_bus->dirname,dev->filename);
00970          for(i = 0;i < 32; i++)
00971          {
00972             sprintf(str,"/proc/asound/card%d/usbbus",i);
00973             fp = fopen(str,"r");
00974             if (!fp) continue;
00975             if ((!fgets(desdev,sizeof(desdev) - 1,fp)) || (!desdev[0]))
00976             {
00977                fclose(fp);
00978                continue;
00979             }
00980             fclose(fp);
00981             if (desdev[strlen(desdev) - 1] == '\n')
00982                   desdev[strlen(desdev) -1 ] = 0;
00983             if (strcasecmp(desdev,devstr)) continue;
00984             if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
00985             else strcpy(str,"/sys/class/sound/dsp/device");
00986             memset(desdev,0,sizeof(desdev));
00987             if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
00988             {
00989                sprintf(str,"/sys/class/sound/controlC%d/device",i);
00990                memset(desdev,0,sizeof(desdev));
00991                if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
00992             }
00993             cp = strrchr(desdev,'/');
00994             if (cp) *cp = 0; else continue;
00995             cp = strrchr(desdev,'/');
00996             if (!cp) continue;
00997             cp++;
00998             break;
00999          }
01000          if (i >= 32) return -1;
01001          usb_device_list = ast_realloc(usb_device_list,
01002             usb_device_list_size + 2 +
01003                strlen(cp));
01004          if (!usb_device_list) return -1;
01005          usb_device_list_size += strlen(cp) + 2;
01006          i = 0;
01007          while(usb_device_list[i])
01008          {
01009             i += strlen(usb_device_list + i) + 1;
01010          }
01011          strcat(usb_device_list + i,cp);
01012          usb_device_list[strlen(cp) + i + 1] = 0;
01013       }
01014 
01015         }
01016     }
01017     return 0;
01018 }
01019 
01020 /* returns internal formatted string from external one */
01021 static int usb_get_usbdev(char *devstr)
01022 {
01023 int   i;
01024 char  str[200],desdev[200],*cp;
01025 
01026    for(i = 0;i < 32; i++)
01027    {
01028       if (i) sprintf(str,"/sys/class/sound/dsp%d/device",i);
01029       else strcpy(str,"/sys/class/sound/dsp/device");
01030       memset(desdev,0,sizeof(desdev));
01031       if (readlink(str,desdev,sizeof(desdev) - 1) == -1)
01032       {
01033          sprintf(str,"/sys/class/sound/controlC%d/device",i);
01034          memset(desdev,0,sizeof(desdev));
01035          if (readlink(str,desdev,sizeof(desdev) - 1) == -1) continue;
01036       }
01037       cp = strrchr(desdev,'/');
01038       if (cp) *cp = 0; else continue;
01039       cp = strrchr(desdev,'/');
01040       if (!cp) continue;
01041       cp++;
01042       if (!strcasecmp(cp,devstr)) break;
01043    }
01044    if (i >= 32) return -1;
01045    return i;
01046 
01047 }
01048 
01049 static int usb_list_check(char *devstr)
01050 {
01051 
01052 char *s = usb_device_list;
01053 
01054    if (!s) return(0);
01055    while(*s)
01056    {
01057       if (!strcasecmp(s,devstr)) return(1);
01058       s += strlen(s) + 1;
01059    }
01060    return(0);
01061 }
01062 
01063 
01064 static int  hidhdwconfig(struct chan_usbradio_pvt *o)
01065 {
01066    if(o->hdwtype==1)   //sphusb
01067    {
01068       o->hid_gpio_ctl      =  0x08; /* set GPIO4 to output mode */
01069       o->hid_gpio_ctl_loc  =  2;    /* For CTL of GPIO */
01070       o->hid_io_cor     =  4; /* GPIO3 is COR */
01071       o->hid_io_cor_loc =  1; /* GPIO3 is COR */
01072       o->hid_io_ctcss      =  2;    /* GPIO 2 is External CTCSS */
01073       o->hid_io_ctcss_loc =  1;  /* is GPIO 2 */
01074       o->hid_io_ptt     =  8;    /* GPIO 4 is PTT */
01075       o->hid_gpio_loc   =  1;    /* For ALL GPIO */
01076    }
01077    else if(o->hdwtype==0)  //dudeusb
01078    {
01079       o->hid_gpio_ctl      =  0x0c; /* set GPIO 3 & 4 to output mode */
01080       o->hid_gpio_ctl_loc  =  2;    /* For CTL of GPIO */
01081       o->hid_io_cor     =  2; /* VOLD DN is COR */
01082       o->hid_io_cor_loc =  0; /* VOL DN COR */
01083       o->hid_io_ctcss      =  2;    /* GPIO 2 is External CTCSS */
01084       o->hid_io_ctcss_loc =  1;  /* is GPIO 2 */
01085       o->hid_io_ptt     =  4;    /* GPIO 3 is PTT */
01086       o->hid_gpio_loc   =  1;    /* For ALL GPIO */
01087    }
01088    else if(o->hdwtype==3)  // custom version
01089    {
01090       o->hid_gpio_ctl      =  0x0c; /* set GPIO 3 & 4 to output mode */
01091       o->hid_gpio_ctl_loc  =  2;    /* For CTL of GPIO */
01092       o->hid_io_cor     =  2; /* VOLD DN is COR */
01093       o->hid_io_cor_loc =  0; /* VOL DN COR */
01094       o->hid_io_ctcss      =  2;    /* GPIO 2 is External CTCSS */
01095       o->hid_io_ctcss_loc =  1;  /* is GPIO 2 */
01096       o->hid_io_ptt     =  4;    /* GPIO 3 is PTT */
01097       o->hid_gpio_loc   =  1;    /* For ALL GPIO */
01098    }
01099 
01100    return 0;
01101 }
01102 /*
01103 */
01104 static void kickptt(struct chan_usbradio_pvt *o)
01105 {
01106    char c = 0;
01107    //printf("kickptt  %i  %i  %i\n",o->txkeyed,o->txchankey,o->txtestkey);
01108    if (!o) return;
01109    if (!o->pttkick) return;
01110    if (write(o->pttkick[1],&c,1) < 0) {
01111       ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
01112    }
01113 }
01114 /*
01115 */
01116 static void *hidthread(void *arg)
01117 {
01118    unsigned char buf[4],bufsave[4],keyed;
01119    char lastrx, txtmp;
01120    int res;
01121    struct usb_device *usb_dev;
01122    struct usb_dev_handle *usb_handle;
01123    struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
01124    struct pollfd pfd = { .events = POLLIN };
01125 
01126    usb_dev = hid_device_init(o->devstr);
01127    if (usb_dev == NULL) {
01128       ast_log(LOG_ERROR,"USB HID device not found\n");
01129       pthread_exit(NULL);
01130    }
01131    usb_handle = usb_open(usb_dev);
01132    if (usb_handle == NULL) {
01133            ast_log(LOG_ERROR,"Not able to open USB device\n");
01134       pthread_exit(NULL);
01135    }
01136    if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0)
01137    {
01138        if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
01139               ast_log(LOG_ERROR,"Not able to detach the USB device\n");
01140          pthread_exit(NULL);
01141       }
01142       if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0) {
01143               ast_log(LOG_ERROR,"Not able to claim the USB device\n");
01144          pthread_exit(NULL);
01145       }
01146    }
01147    memset(buf,0,sizeof(buf));
01148    buf[2] = o->hid_gpio_ctl;
01149    buf[1] = 0;
01150    hid_set_outputs(usb_handle,buf);
01151    memcpy(bufsave,buf,sizeof(buf));
01152    if (pipe(o->pttkick) == -1)
01153    {
01154        ast_log(LOG_ERROR,"Not able to create pipe\n");
01155       pthread_exit(NULL);
01156    }
01157    traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
01158    lastrx = 0;
01159    // popen 
01160    while (!o->stophid) {
01161       pfd.fd = o->pttkick[0];
01162       pfd.revents = 0;
01163 
01164       res = ast_poll(&pfd, 1, 50);
01165       if (res < 0) {
01166          ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
01167          usleep(10000);
01168          continue;
01169       }
01170       if (pfd.revents & POLLIN) {
01171          char c;
01172 
01173          if (read(o->pttkick[0], &c, 1) < 0) {
01174             ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
01175          }
01176       }
01177       if (o->wanteeprom) {
01178          ast_mutex_lock(&o->eepromlock);
01179          if (o->eepromctl == 1) { /* to read */
01180             /* if CS okay */
01181             if (!get_eeprom(usb_handle, o->eeprom)) {
01182                if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) {
01183                   ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name);
01184                } else {
01185                   o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
01186                   o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
01187                   o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
01188                   memcpy(&o->rxvoiceadj, &o->eeprom[EEPROM_RXVOICEADJ], sizeof(float));
01189                   memcpy(&o->rxctcssadj, &o->eeprom[EEPROM_RXCTCSSADJ], sizeof(float));
01190                   o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
01191                   o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
01192                   ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
01193                }
01194             } else {
01195                ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name);
01196             }
01197             hid_set_outputs(usb_handle,bufsave);
01198          }
01199          if (o->eepromctl == 2) { /* to write */
01200             put_eeprom(usb_handle,o->eeprom);
01201             hid_set_outputs(usb_handle,bufsave);
01202             ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name);
01203          }
01204          o->eepromctl = 0;
01205          ast_mutex_unlock(&o->eepromlock);
01206       }
01207       buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
01208       hid_get_inputs(usb_handle,buf);
01209       keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
01210       if (keyed != o->rxhidsq) {
01211          if (o->debuglevel) {
01212             printf("chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
01213          }
01214          o->rxhidsq=keyed;
01215       }
01216 
01217       /* if change in tx state as controlled by xpmr */
01218       txtmp = o->pmrChan->txPttOut;
01219 
01220       if (o->lasttx != txtmp) {
01221          o->pmrChan->txPttHid = o->lasttx = txtmp;
01222          if (o->debuglevel) {
01223             ast_debug(0, "hidthread: tx set to %d\n", txtmp);
01224          }
01225          buf[o->hid_gpio_loc] = 0;
01226          if (!o->invertptt) {
01227             if (txtmp) {
01228                buf[o->hid_gpio_loc] = o->hid_io_ptt;
01229             }
01230          } else {
01231             if (!txtmp) {
01232                buf[o->hid_gpio_loc] = o->hid_io_ptt;
01233             }
01234          }
01235          buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
01236          memcpy(bufsave, buf, sizeof(buf));
01237          hid_set_outputs(usb_handle, buf);
01238       }
01239       time(&o->lasthidtime);
01240    }
01241    buf[o->hid_gpio_loc] = 0;
01242    if (o->invertptt) {
01243       buf[o->hid_gpio_loc] = o->hid_io_ptt;
01244    }
01245    buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
01246    hid_set_outputs(usb_handle, buf);
01247    pthread_exit(0);
01248 }
01249 
01250 /*
01251  * returns a pointer to the descriptor with the given name
01252  */
01253 static struct chan_usbradio_pvt *find_desc(char *dev)
01254 {
01255    struct chan_usbradio_pvt *o = NULL;
01256 
01257    if (!dev)
01258       ast_log(LOG_WARNING, "null dev\n");
01259 
01260    for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
01261    if (!o)
01262    {
01263       ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
01264    }
01265 
01266    return o;
01267 }
01268 
01269 static struct chan_usbradio_pvt *find_desc_usb(char *devstr)
01270 {
01271    struct chan_usbradio_pvt *o = NULL;
01272 
01273    if (!devstr)
01274       ast_log(LOG_WARNING, "null dev\n");
01275 
01276    for (o = usbradio_default.next; o && devstr && strcmp(o->devstr, devstr) != 0; o = o->next);
01277 
01278    return o;
01279 }
01280 
01281 /*
01282  * split a string in extension-context, returns pointers to malloc'ed
01283  * strings.
01284  * If we do not have 'overridecontext' then the last @ is considered as
01285  * a context separator, and the context is overridden.
01286  * This is usually not very necessary as you can play with the dialplan,
01287  * and it is nice not to need it because you have '@' in SIP addresses.
01288  * Return value is the buffer address.
01289  */
01290 #if   0
01291 static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
01292 {
01293    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
01294 
01295    if (ext == NULL || ctx == NULL)
01296       return NULL;         /* error */
01297 
01298    *ext = *ctx = NULL;
01299 
01300    if (src && *src != '\0')
01301       *ext = ast_strdup(src);
01302 
01303    if (*ext == NULL)
01304       return NULL;
01305 
01306    if (!o->overridecontext) {
01307       /* parse from the right */
01308       *ctx = strrchr(*ext, '@');
01309       if (*ctx)
01310          *(*ctx)++ = '\0';
01311    }
01312 
01313    return *ext;
01314 }
01315 #endif
01316 
01317 /*
01318  * Returns the number of blocks used in the audio output channel
01319  */
01320 static int used_blocks(struct chan_usbradio_pvt *o)
01321 {
01322    struct audio_buf_info info;
01323 
01324    if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
01325       if (!(o->warned & WARN_used_blocks)) {
01326          ast_log(LOG_WARNING, "Error reading output space\n");
01327          o->warned |= WARN_used_blocks;
01328       }
01329       return 1;
01330    }
01331 
01332    if (o->total_blocks == 0) {
01333       if (0)               /* debugging */
01334          ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
01335       o->total_blocks = info.fragments;
01336    }
01337 
01338    return o->total_blocks - info.fragments;
01339 }
01340 
01341 /* Write an exactly FRAME_SIZE sized frame */
01342 static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
01343 {
01344    int res;
01345 
01346    if (o->sounddev < 0)
01347       setformat(o, O_RDWR);
01348    if (o->sounddev < 0)
01349       return 0;            /* not fatal */
01350    //  maw maw sph !!! may or may not be a good thing
01351    //  drop the frame if not transmitting, this keeps from gradually
01352    //  filling the buffer when asterisk clock > usb sound clock
01353    if(!o->pmrChan->txPttIn && !o->pmrChan->txPttOut)
01354    {
01355       //return 0;
01356    }
01357    /*
01358     * Nothing complex to manage the audio device queue.
01359     * If the buffer is full just drop the extra, otherwise write.
01360     * XXX in some cases it might be useful to write anyways after
01361     * a number of failures, to restart the output chain.
01362     */
01363    res = used_blocks(o);
01364    if (res > o->queuesize) {  /* no room to write a block */
01365        // ast_log(LOG_WARNING, "sound device write buffer overflow\n");
01366       if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
01367          ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
01368       return 0;
01369    }
01370    o->w_errors = 0;
01371 
01372    return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12);
01373 }
01374 
01375 #ifndef  NEW_ASTERISK
01376 
01377 /*
01378  * Handler for 'sound writable' events from the sound thread.
01379  * Builds a frame from the high level description of the sounds,
01380  * and passes it to the audio device.
01381  * The actual sound is made of 1 or more sequences of sound samples
01382  * (s->datalen, repeated to make s->samplen samples) followed by
01383  * s->silencelen samples of silence. The position in the sequence is stored
01384  * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen.
01385  * In case we fail to write a frame, don't update o->sampsent.
01386  */
01387 static void send_sound(struct chan_usbradio_pvt *o)
01388 {
01389    short myframe[FRAME_SIZE];
01390    int ofs, l, start;
01391    int l_sampsent = o->sampsent;
01392    struct sound *s;
01393 
01394    if (o->cursound < 0)    /* no sound to send */
01395       return;
01396 
01397    s = &sounds[o->cursound];
01398 
01399    for (ofs = 0; ofs < FRAME_SIZE; ofs += l) {
01400       l = s->samplen - l_sampsent;  /* # of available samples */
01401       if (l > 0) {
01402          start = l_sampsent % s->datalen; /* source offset */
01403          if (l > FRAME_SIZE - ofs)  /* don't overflow the frame */
01404             l = FRAME_SIZE - ofs;
01405          if (l > s->datalen - start)   /* don't overflow the source */
01406             l = s->datalen - start;
01407          memmove(myframe + ofs, s->data + start, l * 2);
01408          if (0)
01409             ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
01410          l_sampsent += l;
01411       } else {          /* end of samples, maybe some silence */
01412          static const short silence[FRAME_SIZE] = { 0, };
01413 
01414          l += s->silencelen;
01415          if (l > 0) {
01416             if (l > FRAME_SIZE - ofs)
01417                l = FRAME_SIZE - ofs;
01418             memmove(myframe + ofs, silence, l * 2);
01419             l_sampsent += l;
01420          } else {       /* silence is over, restart sound if loop */
01421             if (s->repeat == 0) {   /* last block */
01422                o->cursound = -1;
01423                o->nosound = 0;   /* allow audio data */
01424                if (ofs < FRAME_SIZE)   /* pad with silence */
01425                   memmove(myframe + ofs, silence, (FRAME_SIZE - ofs) * 2);
01426             }
01427             l_sampsent = 0;
01428          }
01429       }
01430    }
01431    l = soundcard_writeframe(o, myframe);
01432    if (l > 0)
01433       o->sampsent = l_sampsent;  /* update status */
01434 }
01435 
01436 static void *sound_thread(void *arg)
01437 {
01438    char ign[4096];
01439    struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
01440 
01441    /*
01442     * Just in case, kick the driver by trying to read from it.
01443     * Ignore errors - this read is almost guaranteed to fail.
01444     */
01445    read(o->sounddev, ign, sizeof(ign));
01446    for (;;) {
01447       struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev } };
01448       int res;
01449 
01450       if (o->cursound > -1 && o->sounddev < 0) {
01451          setformat(o, O_RDWR);   /* need the channel, try to reopen */
01452       } else if (o->cursound == -1 && o->owner == NULL) {
01453          setformat(o, O_CLOSE);  /* can close */
01454       }
01455       if (o->sounddev > -1) {
01456          if (!o->owner) {  /* no one owns the audio, so we must drain it */
01457             pfd[1].events = POLLIN;
01458          }
01459          if (o->cursound > -1) {
01460             pfd[1].events |= POLLOUT;
01461          }
01462       }
01463       res = ast_poll(pfd, o->sounddev > -1 ? 2 : 1, -1);
01464       if (res < 1) {
01465          ast_log(LOG_WARNING, "poll failed: %s\n", strerror(errno));
01466          sleep(1);
01467          continue;
01468       }
01469       if (pfd[0].revents & POLLIN) {
01470          /* read which sound to play from the pipe */
01471          int i, what = -1;
01472 
01473          read(o->sndcmd[0], &what, sizeof(what));
01474          for (i = 0; sounds[i].ind != -1; i++) {
01475             if (sounds[i].ind == what) {
01476                o->cursound = i;
01477                o->sampsent = 0;
01478                o->nosound = 1;   /* block audio from pbx */
01479                break;
01480             }
01481          }
01482          if (sounds[i].ind == -1) {
01483             ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
01484          }
01485       }
01486       if (o->sounddev > -1) {
01487          if (pfd[1].revents & POLLIN) { /* read and ignore errors */
01488             read(o->sounddev, ign, sizeof(ign)); 
01489          }
01490          if (pfd[1].revents & POLLOUT) {
01491             send_sound(o);
01492          }
01493       }
01494    }
01495    return NULL;            /* Never reached */
01496 }
01497 
01498 #endif
01499 
01500 /*
01501  * reset and close the device if opened,
01502  * then open and initialize it in the desired mode,
01503  * trigger reads and writes so we can start using it.
01504  */
01505 static int setformat(struct chan_usbradio_pvt *o, int mode)
01506 {
01507    int fmt, desired, res, fd;
01508    char device[100];
01509 
01510    if (o->sounddev >= 0) {
01511       ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
01512       close(o->sounddev);
01513       o->duplex = M_UNSET;
01514       o->sounddev = -1;
01515    }
01516    if (mode == O_CLOSE)    /* we are done */
01517       return 0;
01518    o->lastopen = ast_tvnow();
01519    strcpy(device,"/dev/dsp");
01520    if (o->devicenum)
01521       sprintf(device,"/dev/dsp%d",o->devicenum);
01522    fd = o->sounddev = open(device, mode | O_NONBLOCK);
01523    if (fd < 0) {
01524       ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno));
01525       return -1;
01526    }
01527    if (o->owner)
01528       o->owner->fds[0] = fd;
01529 
01530 #if __BYTE_ORDER == __LITTLE_ENDIAN
01531    fmt = AFMT_S16_LE;
01532 #else
01533    fmt = AFMT_S16_BE;
01534 #endif
01535    res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
01536    if (res < 0) {
01537       ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
01538       return -1;
01539    }
01540    switch (mode) {
01541       case O_RDWR:
01542          res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
01543          /* Check to see if duplex set (FreeBSD Bug) */
01544          res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
01545          if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
01546             if (option_verbose > 1)
01547                ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
01548             o->duplex = M_FULL;
01549          };
01550          break;
01551       case O_WRONLY:
01552          o->duplex = M_WRITE;
01553          break;
01554       case O_RDONLY:
01555          o->duplex = M_READ;
01556          break;
01557    }
01558 
01559    fmt = 1;
01560    res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
01561    if (res < 0) {
01562       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
01563       return -1;
01564    }
01565    fmt = desired = 48000;                    /* 8000 Hz desired */
01566    res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
01567 
01568    if (res < 0) {
01569       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
01570       return -1;
01571    }
01572    if (fmt != desired) {
01573       if (!(o->warned & WARN_speed)) {
01574          ast_log(LOG_WARNING,
01575              "Requested %d Hz, got %d Hz -- sound may be choppy\n",
01576              desired, fmt);
01577          o->warned |= WARN_speed;
01578       }
01579    }
01580    /*
01581     * on Freebsd, SETFRAGMENT does not work very well on some cards.
01582     * Default to use 256 bytes, let the user override
01583     */
01584    if (o->frags) {
01585       fmt = o->frags;
01586       res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
01587       if (res < 0) {
01588          if (!(o->warned & WARN_frag)) {
01589             ast_log(LOG_WARNING,
01590                "Unable to set fragment size -- sound may be choppy\n");
01591             o->warned |= WARN_frag;
01592          }
01593       }
01594    }
01595    /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */
01596    res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
01597    res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
01598    /* it may fail if we are in half duplex, never mind */
01599    return 0;
01600 }
01601 
01602 /*
01603  * some of the standard methods supported by channels.
01604  */
01605 static int usbradio_digit_begin(struct ast_channel *c, char digit)
01606 {
01607    return 0;
01608 }
01609 
01610 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration)
01611 {
01612    /* no better use for received digits than print them */
01613    ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
01614       digit, duration);
01615    return 0;
01616 }
01617 /*
01618    SETFREQ - sets spi programmable xcvr
01619    SETCHAN - sets binary parallel xcvr
01620 */
01621 static int usbradio_text(struct ast_channel *c, const char *text)
01622 {
01623    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
01624    double tx,rx;
01625    char cnt,rxs[16],txs[16],txpl[16],rxpl[16];
01626    char pwr,*cmd;
01627 
01628    cmd = alloca(strlen(text) + 10);
01629 
01630    /* print received messages */
01631    if(o->debuglevel)ast_verbose(" << Console Received usbradio text %s >> \n", text);
01632 
01633    cnt = sscanf(text, "%300s %15s %15s %15s %15s %1c", cmd, rxs, txs, rxpl, txpl, &pwr);
01634 
01635    if (strcmp(cmd,"SETCHAN")==0)
01636     { 
01637       u8 chan;
01638       chan=strtod(rxs,NULL);
01639       ppbinout(chan);
01640         if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETCHAN cmd: %s chan: %i\n",text,chan);
01641         return 0;
01642     }
01643    
01644     if (cnt < 6)
01645     {
01646        ast_log(LOG_ERROR,"Cannot parse usbradio text: %s\n",text);
01647        return 0;
01648     }
01649    else
01650    {
01651       if(o->debuglevel)ast_verbose(" << %s %s %s %s %s %c >> \n", cmd,rxs,txs,rxpl,txpl,pwr);   
01652    }
01653     
01654     if (strcmp(cmd,"SETFREQ")==0)
01655     {
01656         if(o->debuglevel)ast_log(LOG_NOTICE,"parse usbradio SETFREQ cmd: %s\n",text);
01657       tx=strtod(txs,NULL);
01658       rx=strtod(rxs,NULL);
01659       o->set_txfreq = round(tx * (double)1000000);
01660       o->set_rxfreq = round(rx * (double)1000000);
01661       o->pmrChan->txpower = (pwr == 'H');
01662       strcpy(o->set_rxctcssfreqs,rxpl);
01663       strcpy(o->set_txctcssfreqs,txpl);
01664    
01665       o->b.remoted=1;
01666       xpmr_config(o);
01667         return 0;
01668     }
01669    ast_log(LOG_ERROR,"Cannot parse usbradio cmd: %s\n",text);
01670    return 0;
01671 }
01672 
01673 /* Play ringtone 'x' on device 'o' */
01674 static void ring(struct chan_usbradio_pvt *o, int x)
01675 {
01676 #ifndef  NEW_ASTERISK
01677    write(o->sndcmd[1], &x, sizeof(x));
01678 #endif
01679 }
01680 
01681 /*
01682  * handler for incoming calls. Either autoanswer, or start ringing
01683  */
01684 static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
01685 {
01686    struct chan_usbradio_pvt *o = c->tech_pvt;
01687 
01688    o->stophid = 0;
01689    time(&o->lasthidtime);
01690    ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
01691    ast_setstate(c, AST_STATE_UP);
01692    return 0;
01693 }
01694 
01695 /*
01696  * remote side answered the phone
01697  */
01698 static int usbradio_answer(struct ast_channel *c)
01699 {
01700 #ifndef  NEW_ASTERISK
01701    struct chan_usbradio_pvt *o = c->tech_pvt;
01702 #endif
01703 
01704    ast_setstate(c, AST_STATE_UP);
01705 #ifndef  NEW_ASTERISK
01706    o->cursound = -1;
01707    o->nosound = 0;
01708 #endif
01709    return 0;
01710 }
01711 
01712 static int usbradio_hangup(struct ast_channel *c)
01713 {
01714    struct chan_usbradio_pvt *o = c->tech_pvt;
01715 
01716    //ast_log(LOG_NOTICE, "usbradio_hangup()\n");
01717 #ifndef  NEW_ASTERISK
01718    o->cursound = -1;
01719    o->nosound = 0;
01720 #endif
01721    c->tech_pvt = NULL;
01722    o->owner = NULL;
01723    ast_module_unref(ast_module_info->self);
01724    if (o->hookstate) {
01725       if (o->autoanswer || o->autohangup) {
01726          /* Assume auto-hangup too */
01727          o->hookstate = 0;
01728          setformat(o, O_CLOSE);
01729       } else {
01730          /* Make congestion noise */
01731          ring(o, AST_CONTROL_CONGESTION);
01732       }
01733    }
01734    o->stophid = 1;
01735    pthread_join(o->hidthread,NULL);
01736    return 0;
01737 }
01738 
01739 
01740 /* used for data coming from the network */
01741 static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
01742 {
01743    struct chan_usbradio_pvt *o = c->tech_pvt;
01744 
01745    traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound));
01746 
01747 #ifndef  NEW_ASTERISK
01748    /* Immediately return if no sound is enabled */
01749    if (o->nosound)
01750       return 0;
01751    /* Stop any currently playing sound */
01752    o->cursound = -1;
01753 #endif
01754    /*
01755     * we could receive a block which is not a multiple of our
01756     * FRAME_SIZE, so buffer it locally and write to the device
01757     * in FRAME_SIZE chunks.
01758     * Keep the residue stored for future use.
01759     */
01760 
01761    #if DEBUG_CAPTURES == 1 // to write input data to a file   datalen=320
01762    if (ftxcapraw && o->b.txcapraw)
01763    {
01764       i16 i, tbuff[f->datalen];
01765       for(i=0;i<f->datalen;i+=2)
01766       {
01767          tbuff[i]= ((i16*)(f->data.ptr))[i/2];
01768          tbuff[i+1]= o->txkeyed*M_Q13;
01769       }
01770       if (fwrite(tbuff,2,f->datalen,ftxcapraw) != f->datalen) {
01771          ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
01772       }
01773       //fwrite(f->data,1,f->datalen,ftxcapraw);
01774    }
01775    #endif
01776 
01777    // maw just take the data from the network and save it for PmrRx processing
01778 
01779    PmrTx(o->pmrChan,(i16*)f->data.ptr);
01780    
01781    return 0;
01782 }
01783 
01784 static struct ast_frame *usbradio_read(struct ast_channel *c)
01785 {
01786    int res, src, datalen, oldpttout;
01787    int cd,sd;
01788    struct chan_usbradio_pvt *o = c->tech_pvt;
01789    struct ast_frame *f = &o->read_f,*f1;
01790    struct ast_frame wf = { AST_FRAME_CONTROL };
01791    time_t now;
01792 
01793    traceusb2(("usbradio_read()\n"));
01794 
01795    if (o->lasthidtime)
01796    {
01797       time(&now);
01798       if ((now - o->lasthidtime) > 3)
01799       {
01800          ast_log(LOG_ERROR,"HID process has died or something!!\n");
01801          return NULL;
01802       }
01803    }
01804    /* XXX can be simplified returning &ast_null_frame */
01805    /* prepare a NULL frame in case we don't have enough data to return */
01806    memset(f, '\0', sizeof(struct ast_frame));
01807    f->frametype = AST_FRAME_NULL;
01808    f->src = usbradio_tech.type;
01809 
01810    res = read(o->sounddev, o->usbradio_read_buf + o->readpos, 
01811       sizeof(o->usbradio_read_buf) - o->readpos);
01812    if (res < 0)            /* audio data not ready, return a NULL frame */
01813    {
01814       if (errno != EAGAIN) return NULL;
01815       if (o->readerrs++ > READERR_THRESHOLD)
01816       {
01817          ast_log(LOG_ERROR,"Stuck USB read channel [%s], un-sticking it!\n",o->name);
01818          o->readerrs = 0;
01819          return NULL;
01820       }
01821       if (o->readerrs == 1) 
01822          ast_log(LOG_WARNING,"Possibly stuck USB read channel. [%s]\n",o->name);
01823       return f;
01824    }
01825    if (o->readerrs) ast_log(LOG_WARNING,"Nope, USB read channel [%s] wasn't stuck after all.\n",o->name);
01826    o->readerrs = 0;
01827    o->readpos += res;
01828    if (o->readpos < sizeof(o->usbradio_read_buf))  /* not enough samples */
01829       return f;
01830 
01831    if (o->mute)
01832       return f;
01833 
01834    #if DEBUG_CAPTURES == 1
01835    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)) {
01836       ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
01837    }
01838    #endif
01839 
01840    #if 1
01841    if(o->txkeyed||o->txtestkey)
01842    {
01843       if(!o->pmrChan->txPttIn)
01844       {
01845          o->pmrChan->txPttIn=1;
01846          if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
01847       }
01848    }
01849    else if(o->pmrChan->txPttIn)
01850    {
01851       o->pmrChan->txPttIn=0;
01852       if(o->debuglevel) ast_log(LOG_NOTICE,"txPttIn = %i, chan %s\n",o->pmrChan->txPttIn,o->owner->name);
01853    }
01854    oldpttout = o->pmrChan->txPttOut;
01855 
01856    PmrRx(         o->pmrChan, 
01857          (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
01858          (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),
01859          (i16 *)(o->usbradio_write_buf_1));
01860 
01861    if (oldpttout != o->pmrChan->txPttOut)
01862    {
01863       if(o->debuglevel) ast_log(LOG_NOTICE,"txPttOut = %i, chan %s\n",o->pmrChan->txPttOut,o->owner->name);
01864       kickptt(o);
01865    }
01866 
01867    #if 0 // to write 48KS/s stereo tx data to a file
01868    if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
01869    if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,FRAME_SIZE * 2 * 6,ftxoutraw);
01870    #endif
01871 
01872    #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
01873     if ((o->b.txcap2 && ftxcaptrace) && (fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace) != FRAME_SIZE * 2 * 16)) {
01874       ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
01875    }
01876    #endif
01877    
01878    // 160 samples * 2 bytes/sample * 2 chan * 6x oversampling to 48KS/s
01879    datalen = FRAME_SIZE * 24;  
01880    src = 0;             /* read position into f->data */
01881    while (src < datalen) 
01882    {
01883       /* Compute spare room in the buffer */
01884       int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
01885 
01886       if (datalen - src >= l) 
01887       {  
01888          /* enough to fill a frame */
01889          memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
01890          soundcard_writeframe(o, (short *) o->usbradio_write_buf);
01891          src += l;
01892          o->usbradio_write_dst = 0;
01893       } 
01894       else 
01895       {           
01896          /* copy residue */
01897          l = datalen - src;
01898          memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
01899          src += l;         /* but really, we are done */
01900          o->usbradio_write_dst += l;
01901       }
01902    }
01903    #else
01904    static FILE *hInput;
01905    i16 iBuff[FRAME_SIZE*2*6];
01906 
01907    o->pmrChan->b.rxCapture=1;
01908 
01909    if(!hInput)
01910    {
01911       hInput  = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
01912       if(!hInput)
01913       {
01914          printf(" Input Data File Not Found.\n");
01915          return 0;
01916       }
01917    }
01918 
01919    if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit;
01920 
01921    PmrRx(  o->pmrChan, 
01922          (i16 *)iBuff,
01923          (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
01924 
01925    #endif
01926 
01927    #if 0
01928    if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE,"w");
01929     if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw);
01930    #endif
01931 
01932    #if DEBUG_CAPTURES == 1 && XPMR_DEBUG0 == 1
01933     if ((frxcaptrace && o->b.rxcap2 && o->pmrChan->b.radioactive) && (fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace) != FRAME_SIZE * 2 * 16 )) {
01934       ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
01935    }
01936    #endif
01937 
01938    cd = 0;
01939    if(o->rxcdtype==CD_HID && (o->pmrChan->rxExtCarrierDetect!=o->rxhidsq))
01940       o->pmrChan->rxExtCarrierDetect=o->rxhidsq;
01941    
01942    if(o->rxcdtype==CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect==o->rxhidsq))
01943       o->pmrChan->rxExtCarrierDetect=!o->rxhidsq;
01944       
01945    if( (o->rxcdtype==CD_HID        && o->rxhidsq)                  ||
01946       (o->rxcdtype==CD_HID_INVERT && !o->rxhidsq)                 ||
01947       (o->rxcdtype==CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
01948       (o->rxcdtype==CD_XPMR_VOX   && o->pmrChan->rxCarrierDetect)
01949      )
01950    {
01951       if (!o->pmrChan->txPttOut || o->radioduplex)cd=1;  
01952    }
01953    else
01954    {
01955       cd=0;
01956    }
01957 
01958    if(cd!=o->rxcarrierdetect)
01959    {
01960       o->rxcarrierdetect=cd;
01961       if(o->debuglevel) ast_log(LOG_NOTICE,"rxcarrierdetect = %i, chan %s\n",cd,o->owner->name);
01962       // printf("rxcarrierdetect = %i, chan %s\n",res,o->owner->name);
01963    }
01964 
01965    if(o->pmrChan->b.ctcssRxEnable && o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
01966    {
01967       if(o->debuglevel)ast_log(LOG_NOTICE,"rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
01968       // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
01969       o->rxctcssdecode=o->pmrChan->rxCtcss->decode;
01970       strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
01971    }
01972 
01973    #ifndef HAVE_XPMRX
01974    if(  !o->pmrChan->b.ctcssRxEnable ||
01975       ( o->pmrChan->b.ctcssRxEnable && 
01976          o->pmrChan->rxCtcss->decode>CTCSS_NULL && 
01977          o->pmrChan->smode==SMODE_CTCSS )  
01978    )
01979    {
01980       sd=1; 
01981    }
01982    else
01983    {
01984       sd=0;
01985    }
01986    #else
01987    if( (!o->pmrChan->b.ctcssRxEnable && !o->pmrChan->b.dcsRxEnable && !o->pmrChan->b.lmrRxEnable) ||
01988       ( o->pmrChan->b.ctcssRxEnable && 
01989          o->pmrChan->rxCtcss->decode>CTCSS_NULL && 
01990          o->pmrChan->smode==SMODE_CTCSS ) ||
01991       ( o->pmrChan->b.dcsRxEnable && 
01992          o->pmrChan->decDcs->decode > 0 &&
01993          o->pmrChan->smode==SMODE_DCS )
01994    )
01995    {
01996       sd=1; 
01997    }
01998    else
01999    {
02000       sd=0;
02001    }
02002 
02003    if(o->pmrChan->decDcs->decode!=o->rxdcsdecode)
02004    {                                      
02005       if(o->debuglevel)ast_log(LOG_NOTICE,"rxdcsdecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
02006       // printf("rxctcssdecode = %i, chan %s\n",o->pmrChan->rxCtcss->decode,o->owner->name);
02007       o->rxdcsdecode=o->pmrChan->decDcs->decode;
02008       strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
02009    }                                                                      
02010 
02011    if(o->pmrChan->rptnum && (o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed != o->rxlsddecode))
02012    {                       
02013       if(o->debuglevel)ast_log(LOG_NOTICE,"rxLSDecode = %s, chan %s\n",o->pmrChan->rxctcssfreq,o->owner->name);
02014       o->rxlsddecode=o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed;
02015       strcpy(o->rxctcssfreq, o->pmrChan->rxctcssfreq);
02016    }
02017 
02018    if( (o->pmrChan->rptnum>0 && o->pmrChan->smode==SMODE_LSD && o->pmrChan->pLsdCtl->cs[o->pmrChan->rptnum].b.rxkeyed)||
02019        (o->pmrChan->smode==SMODE_DCS && o->pmrChan->decDcs->decode>0) )
02020    {
02021       sd=1;
02022    }
02023    #endif
02024 
02025    if ( cd && sd )
02026    {
02027       //if(!o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
02028       if(!o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 1, chan %s\n", o->owner->name);
02029       o->rxkeyed = 1;
02030    }
02031    else 
02032    {
02033       //if(o->rxkeyed)o->pmrChan->dd.b.doitnow=1;
02034       if(o->rxkeyed && o->debuglevel)ast_log(LOG_NOTICE,"o->rxkeyed = 0, chan %s\n",o->owner->name);
02035       o->rxkeyed = 0;
02036    }
02037 
02038    // provide rx signal detect conditions
02039    if (o->lastrx && (!o->rxkeyed))
02040    {
02041       o->lastrx = 0;
02042       //printf("AST_CONTROL_RADIO_UNKEY\n");
02043       wf.subclass.integer = AST_CONTROL_RADIO_UNKEY;
02044       ast_queue_frame(o->owner, &wf);
02045    }
02046    else if ((!o->lastrx) && (o->rxkeyed))
02047    {
02048       o->lastrx = 1;
02049       //printf("AST_CONTROL_RADIO_KEY\n");
02050       wf.subclass.integer = AST_CONTROL_RADIO_KEY;
02051       if(o->rxctcssdecode)    
02052         {
02053            wf.data.ptr = o->rxctcssfreq;
02054            wf.datalen = strlen(o->rxctcssfreq) + 1;
02055          TRACEO(1,("AST_CONTROL_RADIO_KEY text=%s\n",o->rxctcssfreq));
02056         }
02057       ast_queue_frame(o->owner, &wf);
02058    }
02059 
02060    o->readpos = AST_FRIENDLY_OFFSET;   /* reset read pointer for next frame */
02061    if (c->_state != AST_STATE_UP)   /* drop data if frame is not up */
02062       return f;
02063    /* ok we can build and deliver the frame to the caller */
02064    f->frametype = AST_FRAME_VOICE;
02065    f->subclass.codec = AST_FORMAT_SLINEAR;
02066    f->samples = FRAME_SIZE;
02067    f->datalen = FRAME_SIZE * 2;
02068    f->data.ptr = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET;
02069    if (o->boost != BOOST_SCALE) {   /* scale and clip values */
02070       int i, x;
02071       int16_t *p = (int16_t *) f->data.ptr;
02072       for (i = 0; i < f->samples; i++) {
02073          x = (p[i] * o->boost) / BOOST_SCALE;
02074          if (x > 32767)
02075             x = 32767;
02076          else if (x < -32768)
02077             x = -32768;
02078          p[i] = x;
02079       }
02080    }
02081 
02082    f->offset = AST_FRIENDLY_OFFSET;
02083    if (o->dsp)
02084    {
02085        f1 = ast_dsp_process(c,o->dsp,f);
02086        if ((f1->frametype == AST_FRAME_DTMF_END) ||
02087          (f1->frametype == AST_FRAME_DTMF_BEGIN))
02088        {
02089       if ((f1->subclass.integer == 'm') || (f1->subclass.integer == 'u'))
02090       {
02091          f1->frametype = AST_FRAME_NULL;
02092          f1->subclass.integer = 0;
02093          return(f1);
02094       }
02095       if (f1->frametype == AST_FRAME_DTMF_END)
02096          ast_log(LOG_NOTICE, "Got DTMF char %c\n", f1->subclass.integer);
02097       return(f1);
02098        }
02099    }
02100    return f;
02101 }
02102 
02103 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
02104 {
02105    struct chan_usbradio_pvt *o = newchan->tech_pvt;
02106    ast_log(LOG_WARNING,"usbradio_fixup()\n");
02107    o->owner = newchan;
02108    return 0;
02109 }
02110 
02111 static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
02112 {
02113    struct chan_usbradio_pvt *o = c->tech_pvt;
02114    int res = -1;
02115 
02116    switch (cond) {
02117       case AST_CONTROL_BUSY:
02118       case AST_CONTROL_CONGESTION:
02119       case AST_CONTROL_RINGING:
02120          res = cond;
02121          break;
02122 
02123       case -1:
02124 #ifndef  NEW_ASTERISK
02125          o->cursound = -1;
02126          o->nosound = 0;      /* when cursound is -1 nosound must be 0 */
02127 #endif
02128          return 0;
02129 
02130       case AST_CONTROL_VIDUPDATE:
02131          res = -1;
02132          break;
02133       case AST_CONTROL_HOLD:
02134          ast_verbose(" << Console Has Been Placed on Hold >> \n");
02135          ast_moh_start(c, data, o->mohinterpret);
02136          break;
02137       case AST_CONTROL_UNHOLD:
02138          ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
02139          ast_moh_stop(c);
02140          break;
02141       case AST_CONTROL_PROCEEDING:
02142          ast_verbose(" << Call Proceeding... >> \n");
02143          ast_moh_stop(c);
02144          break;
02145       case AST_CONTROL_PROGRESS:
02146          ast_verbose(" << Call Progress... >> \n");
02147          ast_moh_stop(c);
02148          break;
02149       case AST_CONTROL_RADIO_KEY:
02150          o->txkeyed = 1;
02151          if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_KEY Radio Transmit On. >> \n");
02152          break;
02153       case AST_CONTROL_RADIO_UNKEY:
02154          o->txkeyed = 0;
02155          if(o->debuglevel)ast_verbose(" << AST_CONTROL_RADIO_UNKEY Radio Transmit Off. >> \n");
02156          break;
02157       default:
02158          ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
02159          return -1;
02160    }
02161 
02162    if (res > -1)
02163       ring(o, res);
02164 
02165    return 0;
02166 }
02167 
02168 /*
02169  * allocate a new channel.
02170  */
02171 static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state, const char *linkedid)
02172 {
02173    struct ast_channel *c;
02174 
02175    c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Radio/%s", o->name);
02176    if (c == NULL)
02177       return NULL;
02178    c->tech = &usbradio_tech;
02179    if (o->sounddev < 0)
02180       setformat(o, O_RDWR);
02181    c->fds[0] = o->sounddev;   /* -1 if device closed, override later */
02182    c->nativeformats = AST_FORMAT_SLINEAR;
02183    c->readformat = AST_FORMAT_SLINEAR;
02184    c->writeformat = AST_FORMAT_SLINEAR;
02185    c->tech_pvt = o;
02186 
02187    if (!ast_strlen_zero(o->language))
02188       ast_string_field_set(c, language, o->language);
02189    /* Don't use ast_set_callerid() here because it will
02190     * generate a needless NewCallerID event */
02191    if (!ast_strlen_zero(o->cid_num)) {
02192       c->caller.ani.number.valid = 1;
02193       c->caller.ani.number.str = ast_strdup(o->cid_num);
02194    }
02195    if (!ast_strlen_zero(ext)) {
02196       c->dialed.number.str = ast_strdup(ext);
02197    }
02198 
02199    o->owner = c;
02200    ast_module_ref(ast_module_info->self);
02201    ast_jb_configure(c, &global_jbconf);
02202    if (state != AST_STATE_DOWN) {
02203       if (ast_pbx_start(c)) {
02204          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
02205          ast_hangup(c);
02206          o->owner = c = NULL;
02207          /* XXX what about the channel itself ? */
02208          /* XXX what about usecnt ? */
02209       }
02210    }
02211 
02212    return c;
02213 }
02214 /*
02215 */
02216 static struct ast_channel *usbradio_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
02217 {
02218    struct ast_channel *c;
02219    struct chan_usbradio_pvt *o = find_desc(data);
02220 
02221    TRACEO(1,("usbradio_request()\n"));
02222 
02223    if (0)
02224    {
02225       ast_log(LOG_WARNING, "usbradio_request type <%s> data 0x%p <%s>\n", type, data, (char *) data);
02226    }
02227    if (o == NULL) {
02228       ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
02229       /* XXX we could default to 'dsp' perhaps ? */
02230       return NULL;
02231    }
02232    if ((format & AST_FORMAT_SLINEAR) == 0) {
02233       ast_log(LOG_NOTICE, "Format 0x%" PRIx64 " unsupported\n", format);
02234       return NULL;
02235    }
02236    if (o->owner) {
02237       ast_log(LOG_NOTICE, "Already have a call (chan %p) on the usb channel\n", o->owner);
02238       *cause = AST_CAUSE_BUSY;
02239       return NULL;
02240    }
02241    c = usbradio_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
02242    if (c == NULL) {
02243       ast_log(LOG_WARNING, "Unable to create new usb channel\n");
02244       return NULL;
02245    }
02246       
02247    o->b.remoted=0;
02248    xpmr_config(o);
02249 
02250    return c;
02251 }
02252 /*
02253 */
02254 static int console_key(int fd, int argc, char *argv[])
02255 {
02256    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
02257 
02258    if (argc != 2)
02259       return RESULT_SHOWUSAGE; 
02260    o->txtestkey = 1;
02261    return RESULT_SUCCESS;
02262 }
02263 /*
02264 */
02265 static int console_unkey(int fd, int argc, char *argv[])
02266 {
02267    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
02268 
02269    if (argc != 2)
02270       return RESULT_SHOWUSAGE;
02271    o->txtestkey = 0;
02272    return RESULT_SUCCESS;
02273 }
02274 
02275 static int radio_tune(int fd, int argc, char *argv[])
02276 {
02277    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
02278    int i=0;
02279 
02280    if ((argc < 2) || (argc > 4))
02281       return RESULT_SHOWUSAGE; 
02282 
02283    if (argc == 2) /* just show stuff */
02284    {
02285       ast_cli(fd,"Active radio interface is [%s]\n",usbradio_active);
02286       ast_cli(fd,"Output A is currently set to ");
02287       if(o->txmixa==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
02288       else if (o->txmixa==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
02289       else if (o->txmixa==TX_OUT_LSD)ast_cli(fd,"tone.\n");
02290       else if (o->txmixa==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
02291       else ast_cli(fd,"off.\n");
02292 
02293       ast_cli(fd,"Output B is currently set to ");
02294       if(o->txmixb==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
02295       else if (o->txmixb==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
02296       else if (o->txmixb==TX_OUT_LSD)ast_cli(fd,"tone.\n");
02297       else if (o->txmixb==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
02298       else ast_cli(fd,"off.\n");
02299 
02300       ast_cli(fd,"Tx Voice Level currently set to %d\n",o->txmixaset);
02301       ast_cli(fd,"Tx Tone Level currently set to %d\n",o->txctcssadj);
02302       ast_cli(fd,"Rx Squelch currently set to %d\n",o->rxsquelchadj);
02303       ast_cli(fd,"Device String is %s\n",o->devstr);
02304       return RESULT_SHOWUSAGE;
02305    }
02306 
02307    o->pmrChan->b.tuning=1;
02308 
02309    if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(fd,o);
02310    else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(fd,o);
02311    else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(fd,o);
02312    else if (!strcasecmp(argv[2],"rxsquelch"))
02313    {
02314       if (argc == 3)
02315       {
02316           ast_cli(fd,"Current Signal Strength is %d\n",((32767-o->pmrChan->rxRssi)*1000/32767));
02317           ast_cli(fd,"Current Squelch setting is %d\n",o->rxsquelchadj);
02318          //ast_cli(fd,"Current Raw RSSI        is %d\n",o->pmrChan->rxRssi);
02319           //ast_cli(fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
02320       } else {
02321          i = atoi(argv[3]);
02322          if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
02323          ast_cli(fd,"Changed Squelch setting to %d\n",i);
02324          o->rxsquelchadj = i;
02325          *(o->pmrChan->prxSquelchAdjust)= ((999 - i) * 32767) / 1000;
02326       }
02327    }
02328    else if (!strcasecmp(argv[2],"txvoice")) {
02329       i = 0;
02330 
02331       if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
02332          (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
02333         )
02334       {
02335          ast_log(LOG_ERROR,"No txvoice output configured.\n");
02336       }
02337       else if (argc == 3)
02338       {
02339          if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
02340             ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
02341          else
02342             ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
02343       }
02344       else
02345       {
02346          i = atoi(argv[3]);
02347          if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
02348 
02349          if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
02350          {
02351             o->txmixaset=i;
02352             ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
02353          }
02354          else
02355          {
02356             o->txmixbset=i;   
02357             ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
02358          }
02359          mixer_write(o);
02360          mult_set(o);
02361          ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
02362       }
02363       o->pmrChan->b.txCtcssInhibit=1;
02364       tune_txoutput(o,i,fd);
02365       o->pmrChan->b.txCtcssInhibit=0;
02366    }
02367    else if (!strcasecmp(argv[2],"txall")) {
02368       i = 0;
02369 
02370       if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
02371          (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
02372         )
02373       {
02374          ast_log(LOG_ERROR,"No txvoice output configured.\n");
02375       }
02376       else if (argc == 3)
02377       {
02378          if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
02379             ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
02380          else
02381             ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
02382       }
02383       else
02384       {
02385          i = atoi(argv[3]);
02386          if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
02387 
02388          if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
02389          {
02390             o->txmixaset=i;
02391             ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
02392          }
02393          else
02394          {
02395             o->txmixbset=i;   
02396             ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
02397          }
02398          mixer_write(o);
02399          mult_set(o);
02400          ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
02401       }
02402       tune_txoutput(o,i,fd);
02403    }
02404    else if (!strcasecmp(argv[2],"auxvoice")) {
02405       i = 0;
02406       if( (o->txmixa!=TX_OUT_AUX) && (o->txmixb!=TX_OUT_AUX))
02407       {
02408          ast_log(LOG_WARNING,"No auxvoice output configured.\n");
02409       }
02410       else if (argc == 3)
02411       {
02412          if(o->txmixa==TX_OUT_AUX)
02413             ast_cli(fd,"Current auxvoice setting on Channel A is %d\n",o->txmixaset);
02414          else
02415             ast_cli(fd,"Current auxvoice setting on Channel B is %d\n",o->txmixbset);
02416       }
02417       else
02418       {
02419          i = atoi(argv[3]);
02420          if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
02421          if(o->txmixa==TX_OUT_AUX)
02422          {
02423             o->txmixbset=i;
02424             ast_cli(fd,"Changed auxvoice setting on Channel A to %d\n",o->txmixaset);
02425          }
02426          else
02427          {
02428             o->txmixbset=i;
02429             ast_cli(fd,"Changed auxvoice setting on Channel B to %d\n",o->txmixbset);
02430          }
02431          mixer_write(o);
02432          mult_set(o);
02433       }
02434       //tune_auxoutput(o,i);
02435    }
02436    else if (!strcasecmp(argv[2],"txtone"))
02437    {
02438       if (argc == 3)
02439          ast_cli(fd,"Current Tx CTCSS modulation setting = %d\n",o->txctcssadj);
02440       else
02441       {
02442          i = atoi(argv[3]);
02443          if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
02444          o->txctcssadj = i;
02445          set_txctcss_level(o);
02446          ast_cli(fd,"Changed Tx CTCSS modulation setting to %i\n",i);
02447       }
02448       o->txtestkey=1;
02449       usleep(5000000);
02450       o->txtestkey=0;
02451    }
02452    else if (!strcasecmp(argv[2],"dump")) pmrdump(o);
02453    else if (!strcasecmp(argv[2],"nocap"))    
02454    {
02455       ast_cli(fd,"File capture (trace) was rx=%d tx=%d and now off.\n",o->b.rxcap2,o->b.txcap2);
02456       ast_cli(fd,"File capture (raw)   was rx=%d tx=%d and now off.\n",o->b.rxcapraw,o->b.txcapraw);
02457       o->b.rxcapraw=o->b.txcapraw=o->b.rxcap2=o->b.txcap2=o->pmrChan->b.rxCapture=o->pmrChan->b.txCapture=0;
02458       if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
02459       if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
02460       if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
02461       if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
02462       if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
02463       if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
02464    }
02465    else if (!strcasecmp(argv[2],"rxtracecap")) 
02466    {
02467       if (!frxcaptrace) frxcaptrace= fopen(RX_CAP_TRACE_FILE,"w");
02468       ast_cli(fd,"Trace rx on.\n");
02469       o->b.rxcap2=o->pmrChan->b.rxCapture=1;
02470    }
02471    else if (!strcasecmp(argv[2],"txtracecap")) 
02472    {
02473       if (!ftxcaptrace) ftxcaptrace= fopen(TX_CAP_TRACE_FILE,"w");
02474       ast_cli(fd,"Trace tx on.\n");
02475       o->b.txcap2=o->pmrChan->b.txCapture=1;
02476    }
02477    else if (!strcasecmp(argv[2],"rxcap")) 
02478    {
02479       if (!frxcapraw) frxcapraw = fopen(RX_CAP_RAW_FILE,"w");
02480       ast_cli(fd,"cap rx raw on.\n");
02481       o->b.rxcapraw=1;
02482    }
02483    else if (!strcasecmp(argv[2],"txcap")) 
02484    {
02485       if (!ftxcapraw) ftxcapraw = fopen(TX_CAP_RAW_FILE,"w");
02486       ast_cli(fd,"cap tx raw on.\n");
02487       o->b.txcapraw=1;
02488    }
02489    else if (!strcasecmp(argv[2],"save"))
02490    {
02491       tune_write(o);
02492       ast_cli(fd,"Saved radio tuning settings to usbradio_tune_%s.conf\n",o->name);
02493    }
02494    else if (!strcasecmp(argv[2],"load"))
02495    {
02496       ast_mutex_lock(&o->eepromlock);
02497       while(o->eepromctl)
02498       {
02499          ast_mutex_unlock(&o->eepromlock);
02500          usleep(10000);
02501          ast_mutex_lock(&o->eepromlock);
02502       }
02503       o->eepromctl = 1;  /* request a load */
02504       ast_mutex_unlock(&o->eepromlock);
02505 
02506       ast_cli(fd,"Requesting loading of tuning settings from EEPROM for channel %s\n",o->name);
02507    }
02508    else
02509    {
02510       o->pmrChan->b.tuning=0;
02511       return RESULT_SHOWUSAGE;
02512    }
02513    o->pmrChan->b.tuning=0;
02514    return RESULT_SUCCESS;
02515 }
02516 
02517 /*
02518    set transmit ctcss modulation level
02519    adjust mixer output or internal gain depending on output type
02520    setting range is 0.0 to 0.9
02521 */
02522 static int set_txctcss_level(struct chan_usbradio_pvt *o)
02523 {                      
02524    if (o->txmixa == TX_OUT_LSD)
02525    {
02526 //    o->txmixaset=(151*o->txctcssadj) / 1000;
02527       o->txmixaset=o->txctcssadj;
02528       mixer_write(o);
02529       mult_set(o);
02530    }
02531    else if (o->txmixb == TX_OUT_LSD)
02532    {
02533 //    o->txmixbset=(151*o->txctcssadj) / 1000;
02534       o->txmixbset=o->txctcssadj;
02535       mixer_write(o);
02536       mult_set(o);
02537    }
02538    else
02539    {
02540       *o->pmrChan->ptxCtcssAdjust=(o->txctcssadj * M_Q8) / 1000;
02541    }
02542    return 0;
02543 }
02544 /*
02545    CLI debugging on and off
02546 */
02547 static int radio_set_debug(int fd, int argc, char *argv[])
02548 {
02549    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
02550 
02551    o->debuglevel=1;
02552    ast_cli(fd,"usbradio debug on.\n");
02553    return RESULT_SUCCESS;
02554 }
02555 
02556 static int radio_set_debug_off(int fd, int argc, char *argv[])
02557 {
02558    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
02559 
02560    o->debuglevel=0;
02561    ast_cli(fd,"usbradio debug off.\n");
02562    return RESULT_SUCCESS;
02563 }
02564 
02565 static int radio_active(int fd, int argc, char *argv[])
02566 {
02567         if (argc == 2)
02568                 ast_cli(fd, "active (command) USB Radio device is [%s]\n", usbradio_active);
02569         else if (argc != 3)
02570                 return RESULT_SHOWUSAGE;
02571         else {
02572                 struct chan_usbradio_pvt *o;
02573                 if (strcmp(argv[2], "show") == 0) {
02574                         for (o = usbradio_default.next; o; o = o->next)
02575                                 ast_cli(fd, "device [%s] exists\n", o->name);
02576                         return RESULT_SUCCESS;
02577                 }
02578                 o = find_desc(argv[2]);
02579                 if (o == NULL)
02580                         ast_cli(fd, "No device [%s] exists\n", argv[2]);
02581                 else
02582             {
02583                struct chan_usbradio_pvt *ao;
02584                for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
02585                     usbradio_active = o->name;
02586                 o->pmrChan->b.radioactive=1;
02587             }
02588         }
02589         return RESULT_SUCCESS;
02590 }
02591 /*
02592    CLI debugging on and off
02593 */
02594 static int radio_set_xpmr_debug(int fd, int argc, char *argv[])
02595 {
02596    struct chan_usbradio_pvt *o = find_desc(usbradio_active);
02597 
02598    if (argc == 4)
02599    {
02600       int i;
02601       i = atoi(argv[3]);
02602       if ((i >= 0) && (i <= 100))
02603       { 
02604          o->pmrChan->tracelevel=i;
02605       }
02606     }
02607    // add ability to set it for a number of frames after which it reverts
02608    ast_cli(fd,"usbradio xdebug on tracelevel %i\n",o->pmrChan->tracelevel);
02609 
02610    return RESULT_SUCCESS;
02611 }
02612 
02613 
02614 static char key_usage[] =
02615    "Usage: radio key\n"
02616    "       Simulates COR active.\n";
02617 
02618 static char unkey_usage[] =
02619    "Usage: radio unkey\n"
02620    "       Simulates COR un-active.\n";
02621 
02622 static char active_usage[] =
02623         "Usage: radio active [device-name]\n"
02624         "       If used without a parameter, displays which device is the current\n"
02625         "one being commanded.  If a device is specified, the commanded radio device is changed\n"
02626         "to the device specified.\n";
02627 /*
02628 radio tune 6 3000    measured tx value
02629 */
02630 static char radio_tune_usage[] =
02631    "Usage: radio tune <function>\n"
02632    "       rxnoise\n"
02633    "       rxvoice\n"
02634    "       rxtone\n"
02635    "       rxsquelch [newsetting]\n"
02636    "       txvoice [newsetting]\n"
02637    "       txtone [newsetting]\n"
02638    "       auxvoice [newsetting]\n"
02639    "       save (settings to tuning file)\n"
02640    "       load (tuning settings from EEPROM)\n"
02641    "\n       All [newsetting]'s are values 0-999\n\n";
02642                  
02643 #ifndef  NEW_ASTERISK
02644 
02645 static struct ast_cli_entry cli_usbradio[] = {
02646    { { "radio", "key", NULL },
02647    console_key, "Simulate Rx Signal Present",
02648    key_usage, NULL, NULL},
02649 
02650    { { "radio", "unkey", NULL },
02651    console_unkey, "Simulate Rx Signal Lusb",
02652    unkey_usage, NULL, NULL },
02653 
02654    { { "radio", "tune", NULL },
02655    radio_tune, "Radio Tune",
02656    radio_tune_usage, NULL, NULL },
02657 
02658    { { "radio", "set", "debug", NULL },
02659    radio_set_debug, "Radio Debug",
02660    radio_tune_usage, NULL, NULL },
02661 
02662    { { "radio", "set", "debug", "off", NULL },
02663    radio_set_debug_off, "Radio Debug",
02664    radio_tune_usage, NULL, NULL },
02665 
02666    { { "radio", "active", NULL },
02667    radio_active, "Change commanded device",
02668    active_usage, NULL, NULL },
02669 
02670     { { "radio", "set", "xdebug", NULL },
02671    radio_set_xpmr_debug, "Radio set xpmr debug level",
02672    active_usage, NULL, NULL },
02673 
02674 };
02675 #endif
02676 
02677 /*
02678  * store the callerid components
02679  */
02680 #if 0
02681 static void store_callerid(struct chan_usbradio_pvt *o, char *s)
02682 {
02683    ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
02684 }
02685 #endif
02686 
02687 static void store_rxdemod(struct chan_usbradio_pvt *o, const char *s)
02688 {
02689    if (!strcasecmp(s,"no")){
02690       o->rxdemod = RX_AUDIO_NONE;
02691    }
02692    else if (!strcasecmp(s,"speaker")){
02693       o->rxdemod = RX_AUDIO_SPEAKER;
02694    }
02695    else if (!strcasecmp(s,"flat")){
02696          o->rxdemod = RX_AUDIO_FLAT;
02697    }  
02698    else {
02699       ast_log(LOG_WARNING,"Unrecognized rxdemod parameter: %s\n",s);
02700    }
02701 
02702    //ast_log(LOG_WARNING, "set rxdemod = %s\n", s);
02703 }
02704 
02705                   
02706 static void store_txmixa(struct chan_usbradio_pvt *o, const char *s)
02707 {
02708    if (!strcasecmp(s,"no")){
02709       o->txmixa = TX_OUT_OFF;
02710    }
02711    else if (!strcasecmp(s,"voice")){
02712       o->txmixa = TX_OUT_VOICE;
02713    }
02714    else if (!strcasecmp(s,"tone")){
02715          o->txmixa = TX_OUT_LSD;
02716    }  
02717    else if (!strcasecmp(s,"composite")){
02718       o->txmixa = TX_OUT_COMPOSITE;
02719    }  
02720    else if (!strcasecmp(s,"auxvoice")){
02721       o->txmixa = TX_OUT_AUX;
02722    }  
02723    else {
02724       ast_log(LOG_WARNING,"Unrecognized txmixa parameter: %s\n",s);
02725    }
02726 
02727    //ast_log(LOG_WARNING, "set txmixa = %s\n", s);
02728 }
02729 
02730 static void store_txmixb(struct chan_usbradio_pvt *o, const char *s)
02731 {
02732    if (!strcasecmp(s,"no")){
02733       o->txmixb = TX_OUT_OFF;
02734    }
02735    else if (!strcasecmp(s,"voice")){
02736       o->txmixb = TX_OUT_VOICE;
02737    }
02738    else if (!strcasecmp(s,"tone")){
02739          o->txmixb = TX_OUT_LSD;
02740    }  
02741    else if (!strcasecmp(s,"composite")){
02742       o->txmixb = TX_OUT_COMPOSITE;
02743    }  
02744    else if (!strcasecmp(s,"auxvoice")){
02745       o->txmixb = TX_OUT_AUX;
02746    }  
02747    else {
02748       ast_log(LOG_WARNING,"Unrecognized txmixb parameter: %s\n",s);
02749    }
02750 
02751    //ast_log(LOG_WARNING, "set txmixb = %s\n", s);
02752 }
02753 /*
02754 */
02755 static void store_rxcdtype(struct chan_usbradio_pvt *o, const char *s)
02756 {
02757    if (!strcasecmp(s,"no")){
02758       o->rxcdtype = CD_IGNORE;
02759    }
02760    else if (!strcasecmp(s,"usb")){
02761       o->rxcdtype = CD_HID;
02762    }
02763    else if (!strcasecmp(s,"dsp")){
02764       o->rxcdtype = CD_XPMR_NOISE;
02765    }  
02766    else if (!strcasecmp(s,"vox")){
02767       o->rxcdtype = CD_XPMR_VOX;
02768    }  
02769    else if (!strcasecmp(s,"usbinvert")){
02770       o->rxcdtype = CD_HID_INVERT;
02771    }  
02772    else {
02773       ast_log(LOG_WARNING,"Unrecognized rxcdtype parameter: %s\n",s);
02774    }
02775 
02776    //ast_log(LOG_WARNING, "set rxcdtype = %s\n", s);
02777 }
02778 /*
02779 */
02780 static void store_rxsdtype(struct chan_usbradio_pvt *o, const char *s)
02781 {
02782    if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){
02783       o->rxsdtype = SD_IGNORE;
02784    }
02785    else if (!strcasecmp(s,"usb") || !strcasecmp(s,"SD_HID")){
02786       o->rxsdtype = SD_HID;
02787    }
02788    else if (!strcasecmp(s,"usbinvert") || !strcasecmp(s,"SD_HID_INVERT")){
02789       o->rxsdtype = SD_HID_INVERT;
02790    }  
02791    else if (!strcasecmp(s,"software") || !strcasecmp(s,"SD_XPMR")){
02792       o->rxsdtype = SD_XPMR;
02793    }  
02794    else {
02795       ast_log(LOG_WARNING,"Unrecognized rxsdtype parameter: %s\n",s);
02796    }
02797 
02798    //ast_log(LOG_WARNING, "set rxsdtype = %s\n", s);
02799 }
02800 /*
02801 */
02802 static void store_rxgain(struct chan_usbradio_pvt *o, const char *s)
02803 {
02804    float f;
02805    sscanf(s, "%30f", &f); 
02806    o->rxgain = f;
02807    //ast_log(LOG_WARNING, "set rxgain = %f\n", f);
02808 }
02809 /*
02810 */
02811 static void store_rxvoiceadj(struct chan_usbradio_pvt *o, const char *s)
02812 {
02813    float f;
02814    sscanf(s, "%30f", &f);
02815    o->rxvoiceadj = f;
02816    //ast_log(LOG_WARNING, "set rxvoiceadj = %f\n", f);
02817 }
02818 /*
02819 */
02820 static void store_rxctcssadj(struct chan_usbradio_pvt *o, const char *s)
02821 {
02822    float f;
02823    sscanf(s, "%30f", &f);
02824    o->rxctcssadj = f;
02825    //ast_log(LOG_WARNING, "set rxctcssadj = %f\n", f);
02826 }
02827 /*
02828 */
02829 static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s)
02830 {
02831    if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){
02832       o->txtoctype = TOC_NONE;
02833    }
02834    else if (!strcasecmp(s,"phase") || !strcasecmp(s,"TOC_PHASE")){
02835       o->txtoctype = TOC_PHASE;
02836    }
02837    else if (!strcasecmp(s,"notone") || !strcasecmp(s,"TOC_NOTONE")){
02838       o->txtoctype = TOC_NOTONE;
02839    }  
02840    else {
02841       ast_log(LOG_WARNING,"Unrecognized txtoctype parameter: %s\n",s);
02842    }
02843 }
02844 /*
02845 */
02846 static void tune_txoutput(struct chan_usbradio_pvt *o, int value, int fd)
02847 {
02848    o->txtestkey=1;
02849    o->pmrChan->txPttIn=1;
02850    TxTestTone(o->pmrChan, 1);   // generate 1KHz tone at 7200 peak
02851    if (fd > 0) ast_cli(fd,"Tone output starting on channel %s...\n",o->name);
02852    usleep(5000000);
02853    TxTestTone(o->pmrChan, 0);
02854    if (fd > 0) ast_cli(fd,"Tone output ending on channel %s...\n",o->name);
02855    o->pmrChan->txPttIn=0;
02856    o->txtestkey=0;
02857 }
02858 /*
02859 */
02860 static void tune_rxinput(int fd, struct chan_usbradio_pvt *o)
02861 {
02862    const int target=23000;
02863    const int tolerance=2000;
02864    const int settingmin=1;
02865    const int settingstart=2;
02866    const int maxtries=12;
02867 
02868    float settingmax;
02869    
02870    int setting=0, tries=0, tmpdiscfactor, meas;
02871    int tunetype=0;
02872 
02873    settingmax = o->micmax;
02874 
02875    if(o->pmrChan->rxDemod)tunetype=1;
02876    o->pmrChan->b.tuning=1;
02877 
02878    setting = settingstart;
02879 
02880     ast_cli(fd,"tune rxnoise maxtries=%i, target=%i, tolerance=%i\n",maxtries,target,tolerance);
02881 
02882    while(tries<maxtries)
02883    {
02884       setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,setting,0);
02885       setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
02886        
02887       usleep(100000);
02888       if(o->rxcdtype!=CD_XPMR_NOISE || o->rxdemod==RX_AUDIO_SPEAKER) 
02889       {
02890          // printf("Measure Direct Input\n");
02891          o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source;
02892          o->pmrChan->spsMeasure->discfactor=2000;
02893          o->pmrChan->spsMeasure->enabled=1;
02894          o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
02895          usleep(400000);   
02896          meas=o->pmrChan->spsMeasure->apeak;
02897          o->pmrChan->spsMeasure->enabled=0;  
02898       }
02899       else
02900       {
02901          // printf("Measure HF Noise\n");
02902          tmpdiscfactor=o->pmrChan->spsRx->discfactor;
02903          o->pmrChan->spsRx->discfactor=(i16)2000;
02904          o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
02905          o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
02906          usleep(200000);
02907          meas=o->pmrChan->rxRssi;
02908          o->pmrChan->spsRx->discfactor=tmpdiscfactor;
02909          o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
02910          o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
02911       }
02912         if(!meas)meas++;
02913       ast_cli(fd,"tries=%i, setting=%i, meas=%i\n",tries,setting,meas);
02914 
02915       if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
02916          setting=setting*target/meas;
02917       }
02918       else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
02919       {
02920          break;
02921       }
02922 
02923       if(setting<settingmin)setting=settingmin;
02924       else if(setting>settingmax)setting=settingmax;
02925 
02926       tries++;
02927    }
02928    ast_cli(fd,"DONE tries=%i, setting=%i, meas=%i\n",tries,
02929       (setting * 1000) / o->micmax,meas);
02930    if( meas<(target-tolerance) || meas>(target+tolerance) ){
02931       ast_cli(fd,"ERROR: RX INPUT ADJUST FAILED.\n");
02932    }else{
02933       ast_cli(fd,"INFO: RX INPUT ADJUST SUCCESS.\n"); 
02934       o->rxmixerset=(setting * 1000) / o->micmax;
02935    }
02936    o->pmrChan->b.tuning=0;
02937 }
02938 /*
02939 */
02940 static void tune_rxvoice(int fd, struct chan_usbradio_pvt *o)
02941 {
02942    const int target=7200;           // peak
02943    const int tolerance=360;            // peak to peak
02944    const float settingmin=0.1;
02945    const float settingmax=4;
02946    const float settingstart=1;
02947    const int maxtries=12;
02948 
02949    float setting;
02950 
02951    int tries=0, meas;
02952 
02953    ast_cli(fd,"INFO: RX VOICE ADJUST START.\n");   
02954    ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
02955 
02956    o->pmrChan->b.tuning=1;
02957    if(!o->pmrChan->spsMeasure)
02958       ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
02959 
02960    if(!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
02961       ast_cli(fd,"ERROR: NO SOURCE OR MEASURE SETTING.\n");
02962 
02963    o->pmrChan->spsMeasure->source=o->pmrChan->spsRxOut->sink;
02964    o->pmrChan->spsMeasure->enabled=1;
02965    o->pmrChan->spsMeasure->discfactor=1000;
02966    
02967    setting=settingstart;
02968 
02969    // ast_cli(fd,"ERROR: NO MEASURE BLOCK.\n");
02970 
02971    while(tries<maxtries)
02972    {
02973       *(o->pmrChan->prxVoiceAdjust)=setting*M_Q8;
02974       usleep(10000);
02975       o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
02976       usleep(1000000);
02977       meas = o->pmrChan->spsMeasure->apeak;
02978       ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
02979 
02980       if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
02981          setting=setting*target/meas;
02982       }
02983       else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
02984       {
02985          break;
02986       }
02987       if(setting<settingmin)setting=settingmin;
02988       else if(setting>settingmax)setting=settingmax;
02989 
02990       tries++;
02991    }
02992 
02993    o->pmrChan->spsMeasure->enabled=0;
02994 
02995    ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
02996    if( meas<(target-tolerance) || meas>(target+tolerance) ){
02997       ast_cli(fd,"ERROR: RX VOICE GAIN ADJUST FAILED.\n");
02998    }else{
02999       ast_cli(fd,"INFO: RX VOICE GAIN ADJUST SUCCESS.\n");
03000       o->rxvoiceadj=setting;
03001    }
03002    o->pmrChan->b.tuning=0;
03003 }
03004 /*
03005 */
03006 static void tune_rxctcss(int fd, struct chan_usbradio_pvt *o)
03007 {
03008    const int target=2400;      // was 4096 pre 20080205
03009    const int tolerance=100;
03010    const float settingmin=0.1;
03011    const float settingmax=8;
03012    const float settingstart=1;
03013    const int maxtries=12;
03014 
03015    float setting;
03016    int tries=0, meas;
03017 
03018    ast_cli(fd,"INFO: RX CTCSS ADJUST START.\n");   
03019    ast_cli(fd,"target=%i tolerance=%i \n",target,tolerance);
03020 
03021    o->pmrChan->b.tuning=1;
03022    o->pmrChan->spsMeasure->source=o->pmrChan->prxCtcssMeasure;
03023    o->pmrChan->spsMeasure->discfactor=400;
03024    o->pmrChan->spsMeasure->enabled=1;
03025 
03026    setting=settingstart;
03027 
03028    while(tries<maxtries)
03029    {
03030       *(o->pmrChan->prxCtcssAdjust)=setting*M_Q8;
03031       usleep(10000);
03032       o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
03033       usleep(500000);
03034       meas = o->pmrChan->spsMeasure->apeak;
03035       ast_cli(fd,"tries=%i, setting=%f, meas=%i\n",tries,setting,meas);
03036 
03037       if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
03038          setting=setting*target/meas;
03039       }
03040       else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
03041       {
03042          break;
03043       }
03044       if(setting<settingmin)setting=settingmin;
03045       else if(setting>settingmax)setting=settingmax;
03046 
03047       tries++;
03048    }
03049    o->pmrChan->spsMeasure->enabled=0;
03050    ast_cli(fd,"DONE tries=%i, setting=%f, meas=%f\n",tries,setting,(float)meas);
03051    if( meas<(target-tolerance) || meas>(target+tolerance) ){
03052       ast_cli(fd,"ERROR: RX CTCSS GAIN ADJUST FAILED.\n");
03053    }else{
03054       ast_cli(fd,"INFO: RX CTCSS GAIN ADJUST SUCCESS.\n");
03055       o->rxctcssadj=setting;
03056    }
03057    o->pmrChan->b.tuning=0;
03058 }
03059 /*
03060    after radio tune is performed data is serialized here 
03061 */
03062 static void tune_write(struct chan_usbradio_pvt *o)
03063 {
03064    FILE *fp;
03065    char fname[200];
03066 
03067    snprintf(fname,sizeof(fname) - 1,"/etc/asterisk/usbradio_tune_%s.conf",o->name);
03068    fp = fopen(fname,"w");
03069 
03070    fprintf(fp,"[%s]\n",o->name);
03071 
03072    fprintf(fp,"; name=%s\n",o->name);
03073    fprintf(fp,"; devicenum=%i\n",o->devicenum);
03074    fprintf(fp,"devstr=%s\n",o->devstr);
03075    fprintf(fp,"rxmixerset=%i\n",o->rxmixerset);
03076    fprintf(fp,"txmixaset=%i\n",o->txmixaset);
03077    fprintf(fp,"txmixbset=%i\n",o->txmixbset);
03078    fprintf(fp,"rxvoiceadj=%f\n",o->rxvoiceadj);
03079    fprintf(fp,"rxctcssadj=%f\n",o->rxctcssadj);
03080    fprintf(fp,"txctcssadj=%i\n",o->txctcssadj);
03081    fprintf(fp,"rxsquelchadj=%i\n",o->rxsquelchadj);
03082    fclose(fp);
03083 
03084    if(o->wanteeprom)
03085    {
03086       ast_mutex_lock(&o->eepromlock);
03087       while(o->eepromctl)
03088       {
03089          ast_mutex_unlock(&o->eepromlock);
03090          usleep(10000);
03091          ast_mutex_lock(&o->eepromlock);
03092       }
03093       o->eeprom[EEPROM_RXMIXERSET] = o->rxmixerset;
03094       o->eeprom[EEPROM_TXMIXASET] = o->txmixaset;
03095       o->eeprom[EEPROM_TXMIXBSET] = o->txmixbset;
03096       memcpy(&o->eeprom[EEPROM_RXVOICEADJ],&o->rxvoiceadj,sizeof(float));
03097       memcpy(&o->eeprom[EEPROM_RXCTCSSADJ],&o->rxctcssadj,sizeof(float));
03098       o->eeprom[EEPROM_TXCTCSSADJ] = o->txctcssadj;
03099       o->eeprom[EEPROM_RXSQUELCHADJ] = o->rxsquelchadj;
03100       o->eepromctl = 2;  /* request a write */
03101       ast_mutex_unlock(&o->eepromlock);
03102    }
03103 }
03104 //
03105 static void mixer_write(struct chan_usbradio_pvt *o)
03106 {
03107    setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_SW,0,0);
03108    setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_VOL,0,0);
03109    setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_SW,1,0);
03110    setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL,
03111       o->txmixaset * o->spkrmax / 1000,
03112       o->txmixbset * o->spkrmax / 1000);
03113    setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,
03114       o->rxmixerset * o->micmax / 1000,0);
03115    setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
03116    setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_SW,1,0);
03117 }
03118 /*
03119    adjust dsp multiplier to add resolution to tx level adjustment
03120 */
03121 static void mult_set(struct chan_usbradio_pvt *o)
03122 {
03123 
03124    if(o->pmrChan->spsTxOutA) {
03125       o->pmrChan->spsTxOutA->outputGain = 
03126          mult_calc((o->txmixaset * 152) / 1000);
03127    }
03128    if(o->pmrChan->spsTxOutB){
03129       o->pmrChan->spsTxOutB->outputGain = 
03130          mult_calc((o->txmixbset * 152) / 1000);
03131    }
03132 }
03133 //
03134 // input 0 - 151 outputs are pot and multiplier
03135 //
03136 static int mult_calc(int value)
03137 {
03138    const int multx=M_Q8;
03139    int pot,mult;
03140 
03141    pot=((int)(value/4)*4)+2;
03142    mult = multx-( ( multx * (3-(value%4)) ) / (pot+2) );
03143    return(mult);
03144 }
03145 
03146 #define pd(x) {printf(#x" = %d\n",x);}
03147 #define pp(x) {printf(#x" = %p\n",x);}
03148 #define ps(x) {printf(#x" = %s\n",x);}
03149 #define pf(x) {printf(#x" = %f\n",x);}
03150 
03151 
03152 #if 0
03153 /*
03154    do hid output if only requirement is ptt out
03155    this give fastest performance with least overhead
03156    where gpio inputs are not required.
03157 */
03158 
03159 static int usbhider(struct chan_usbradio_pvt *o, int opt)
03160 {
03161    unsigned char buf[4];
03162    char lastrx, txtmp;
03163 
03164    if(opt)
03165    {
03166       struct usb_device *usb_dev;
03167 
03168       usb_dev = hid_device_init(o->devstr);
03169       if (usb_dev == NULL) {
03170          ast_log(LOG_ERROR,"USB HID device not found\n");
03171          return -1;
03172       }
03173       o->usb_handle = usb_open(usb_dev);
03174       if (o->usb_handle == NULL) {
03175           ast_log(LOG_ERROR,"Not able to open USB device\n");
03176          return -1;
03177       }
03178       if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0)
03179       {
03180           if (usb_detach_kernel_driver_np(o->usb_handle,C108_HID_INTERFACE) < 0) {
03181              ast_log(LOG_ERROR,"Not able to detach the USB device\n");
03182             return -1;
03183          }
03184          if (usb_claim_interface(o->usb_handle,C108_HID_INTERFACE) < 0) {
03185             ast_log(LOG_ERROR,"Not able to claim the USB device\n");
03186             return -1;
03187          }
03188       }
03189    
03190       memset(buf,0,sizeof(buf));
03191       buf[2] = o->hid_gpio_ctl;
03192       buf[1] = 0;
03193       hid_set_outputs(o->usb_handle,buf);
03194       memcpy(bufsave,buf,sizeof(buf));
03195     
03196       buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
03197       o->lasttx=0;
03198    }
03199 
03200    /* if change in tx state as controlled by xpmr */
03201    txtmp=o->pmrChan->txPttOut;
03202          
03203    if (o->lasttx != txtmp)
03204    {
03205       o->pmrChan->txPttHid=o->lasttx = txtmp;
03206       if(o->debuglevel)printf("usbhid: tx set to %d\n",txtmp);
03207       buf[o->hid_gpio_loc] = 0;
03208       if (!o->invertptt)
03209       {
03210          if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
03211       }
03212       else
03213       {
03214          if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
03215       }
03216       buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
03217       hid_set_outputs(o->usb_handle,buf);
03218    }
03219 
03220    return(0);
03221 }
03222 #endif
03223 /*
03224 */
03225 static void pmrdump(struct chan_usbradio_pvt *o)
03226 {
03227    t_pmr_chan *p;
03228    int i;
03229 
03230    p=o->pmrChan;
03231 
03232    printf("\nodump()\n");
03233 
03234    pd(o->devicenum);
03235    ps(o->devstr);
03236 
03237    pd(o->micmax);
03238    pd(o->spkrmax);
03239 
03240    pd(o->rxdemod);
03241    pd(o->rxcdtype);
03242    pd(o->rxsdtype);
03243    pd(o->txtoctype);
03244 
03245    pd(o->rxmixerset);
03246    pd(o->rxboostset);
03247 
03248    pf(o->rxvoiceadj);
03249    pf(o->rxctcssadj);
03250    pd(o->rxsquelchadj);
03251 
03252    ps(o->txctcssdefault);
03253    ps(o->txctcssfreq);
03254 
03255    pd(o->numrxctcssfreqs);
03256    if(o->numrxctcssfreqs>0)
03257    {
03258       for(i=0;i<o->numrxctcssfreqs;i++)
03259       {
03260          printf(" %i =  %s  %s\n",i,o->rxctcss[i],o->txctcss[i]); 
03261       }
03262    }
03263 
03264    pd(o->b.rxpolarity);
03265    pd(o->b.txpolarity);
03266 
03267    pd(o->txprelim);
03268    pd(o->txmixa);
03269    pd(o->txmixb);
03270    
03271    pd(o->txmixaset);
03272    pd(o->txmixbset);
03273    
03274    printf("\npmrdump()\n");
03275  
03276    pd(p->devicenum);
03277 
03278    printf("prxSquelchAdjust=%i\n",*(o->pmrChan->prxSquelchAdjust));
03279 
03280    pd(p->rxCarrierPoint);
03281    pd(p->rxCarrierHyst);
03282 
03283    pd(*p->prxVoiceAdjust);
03284    pd(*p->prxCtcssAdjust);
03285 
03286    pd(p->rxfreq);
03287    pd(p->txfreq);
03288 
03289    pd(p->rxCtcss->relax);
03290    //pf(p->rxCtcssFreq);   
03291    pd(p->numrxcodes);
03292    if(o->pmrChan->numrxcodes>0)
03293    {
03294       for(i=0;i<o->pmrChan->numrxcodes;i++)
03295       {
03296          printf(" %i = %s\n",i,o->pmrChan->pRxCode[i]); 
03297       }
03298    }
03299 
03300    pd(p->txTocType);
03301    ps(p->pTxCodeDefault);
03302    pd(p->txcodedefaultsmode);
03303    pd(p->numtxcodes);
03304    if(o->pmrChan->numtxcodes>0)
03305    {
03306       for(i=0;i<o->pmrChan->numtxcodes;i++)
03307       {                                       
03308          printf(" %i = %s\n",i,o->pmrChan->pTxCode[i]); 
03309       }
03310    }
03311 
03312    pd(p->b.rxpolarity);
03313    pd(p->b.txpolarity);
03314    pd(p->b.dcsrxpolarity);
03315    pd(p->b.dcstxpolarity);
03316    pd(p->b.lsdrxpolarity);
03317    pd(p->b.lsdtxpolarity);
03318 
03319    pd(p->txMixA);
03320    pd(p->txMixB);
03321     
03322    pd(p->rxDeEmpEnable);
03323    pd(p->rxCenterSlicerEnable);
03324    pd(p->rxCtcssDecodeEnable);
03325    pd(p->rxDcsDecodeEnable);
03326    pd(p->b.ctcssRxEnable);
03327    pd(p->b.dcsRxEnable);
03328    pd(p->b.lmrRxEnable);
03329    pd(p->b.dstRxEnable);
03330    pd(p->smode);
03331 
03332    pd(p->txHpfEnable);
03333    pd(p->txLimiterEnable);
03334    pd(p->txPreEmpEnable);
03335    pd(p->txLpfEnable);
03336 
03337    if(p->spsTxOutA)pd(p->spsTxOutA->outputGain);
03338    if(p->spsTxOutB)pd(p->spsTxOutB->outputGain);
03339    pd(p->txPttIn);
03340    pd(p->txPttOut);
03341 
03342    pd(p->tracetype);
03343 
03344    return;
03345 }
03346 /*
03347    takes data from a chan_usbradio_pvt struct (e.g. o->)
03348    and configures the xpmr radio layer
03349 */
03350 static int xpmr_config(struct chan_usbradio_pvt *o)
03351 {
03352    //ast_log(LOG_NOTICE,"xpmr_config()\n");
03353 
03354    TRACEO(1,("xpmr_config()\n"));
03355 
03356    if(o->pmrChan==NULL)
03357    {
03358       ast_log(LOG_ERROR,"pmr channel structure NULL\n");
03359       return 1;
03360    }
03361 
03362    o->pmrChan->rxCtcss->relax = o->rxctcssrelax;
03363    o->pmrChan->txpower=0;
03364 
03365    if(o->b.remoted)
03366    {
03367       o->pmrChan->pTxCodeDefault = o->set_txctcssdefault;
03368       o->pmrChan->pRxCodeSrc=o->set_rxctcssfreqs;
03369       o->pmrChan->pTxCodeSrc=o->set_txctcssfreqs;
03370 
03371       o->pmrChan->rxfreq=o->set_rxfreq;
03372       o->pmrChan->txfreq=o->set_txfreq;
03373       /* printf(" remoted %s %s --> %s \n",o->pmrChan->txctcssdefault,
03374          o->pmrChan->txctcssfreq,o->pmrChan->rxctcssfreq); */
03375    }
03376    else
03377    {
03378       // set xpmr pointers to source strings
03379 
03380       o->pmrChan->pTxCodeDefault = o->txctcssdefault;
03381       o->pmrChan->pRxCodeSrc     = o->rxctcssfreqs;
03382       o->pmrChan->pTxCodeSrc     = o->txctcssfreqs;
03383    
03384       o->pmrChan->rxfreq = o->rxfreq;
03385       o->pmrChan->txfreq = o->txfreq;
03386    }
03387    
03388    code_string_parse(o->pmrChan);
03389    if(o->pmrChan->rxfreq) o->pmrChan->b.reprog=1;
03390 
03391    return 0;
03392 }
03393 /*
03394  * grab fields from the config file, init the descriptor and open the device.
03395  */
03396 static struct chan_usbradio_pvt *store_config(struct ast_config *cfg, char *ctg)
03397 {
03398    struct ast_variable *v;
03399    struct chan_usbradio_pvt *o;
03400    struct ast_config *cfg1;
03401    int i;
03402    char fname[200];
03403 #ifdef   NEW_ASTERISK
03404    struct ast_flags zeroflag = {0};
03405 #endif
03406    if (ctg == NULL) {
03407       traceusb1((" store_config() ctg == NULL\n"));
03408       o = &usbradio_default;
03409       ctg = "general";
03410    } else {
03411       /* "general" is also the default thing */
03412       if (strcmp(ctg, "general") == 0) {
03413          o = &usbradio_default;
03414       } else {
03415           // ast_log(LOG_NOTICE,"ast_calloc for chan_usbradio_pvt of %s\n",ctg);
03416          if (!(o = ast_calloc(1, sizeof(*o))))
03417             return NULL;
03418          *o = usbradio_default;
03419          o->name = ast_strdup(ctg);
03420          if (!usbradio_active) 
03421             usbradio_active = o->name;
03422       }
03423    }
03424    ast_mutex_init(&o->eepromlock);
03425    strcpy(o->mohinterpret, "default");
03426    /* fill other fields from configuration */
03427    for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
03428       M_START((char *)v->name, (char *)v->value);
03429 
03430       /* handle jb conf */
03431       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
03432          continue;
03433 
03434 #if   0
03435          M_BOOL("autoanswer", o->autoanswer)
03436          M_BOOL("autohangup", o->autohangup)
03437          M_BOOL("overridecontext", o->overridecontext)
03438          M_STR("context", o->ctx)
03439          M_STR("language", o->language)
03440          M_STR("mohinterpret", o->mohinterpret)
03441          M_STR("extension", o->ext)
03442          M_F("callerid", store_callerid(o, v->value))
03443 #endif
03444          M_UINT("frags", o->frags)
03445          M_UINT("queuesize",o->queuesize)
03446 #if 0
03447          M_UINT("devicenum",o->devicenum)
03448 #endif
03449          M_UINT("debug", usbradio_debug)
03450          M_BOOL("rxcpusaver",o->rxcpusaver)
03451          M_BOOL("txcpusaver",o->txcpusaver)
03452          M_BOOL("invertptt",o->invertptt)
03453          M_F("rxdemod",store_rxdemod(o,(char *)v->value))
03454          M_BOOL("txprelim",o->txprelim);
03455          M_F("txmixa",store_txmixa(o,(char *)v->value))
03456          M_F("txmixb",store_txmixb(o,(char *)v->value))
03457          M_F("carrierfrom",store_rxcdtype(o,(char *)v->value))
03458          M_F("rxsdtype",store_rxsdtype(o,(char *)v->value))
03459           M_UINT("rxsqvox",o->rxsqvoxadj)
03460          M_STR("txctcssdefault",o->txctcssdefault)
03461          M_STR("rxctcssfreqs",o->rxctcssfreqs)
03462          M_STR("txctcssfreqs",o->txctcssfreqs)
03463          M_UINT("rxfreq",o->rxfreq)
03464          M_UINT("txfreq",o->txfreq)
03465          M_F("rxgain",store_rxgain(o,(char *)v->value))
03466          M_BOOL("rxboost",o->rxboostset)
03467          M_UINT("rxctcssrelax",o->rxctcssrelax)
03468          M_F("txtoctype",store_txtoctype(o,(char *)v->value))
03469          M_UINT("hdwtype",o->hdwtype)
03470          M_UINT("eeprom",o->wanteeprom)
03471          M_UINT("duplex",o->radioduplex)
03472          M_UINT("txsettletime",o->txsettletime)
03473          M_BOOL("rxpolarity",o->b.rxpolarity)
03474          M_BOOL("txpolarity",o->b.txpolarity)
03475          M_BOOL("dcsrxpolarity",o->b.dcsrxpolarity)
03476          M_BOOL("dcstxpolarity",o->b.dcstxpolarity)
03477          M_BOOL("lsdrxpolarity",o->b.lsdrxpolarity)
03478          M_BOOL("lsdtxpolarity",o->b.lsdtxpolarity)
03479          M_BOOL("loopback",o->b.loopback)
03480          M_BOOL("radioactive",o->b.radioactive)
03481          M_UINT("rptnum",o->rptnum)
03482          M_UINT("idleinterval",o->idleinterval)
03483          M_UINT("turnoffs",o->turnoffs)
03484          M_UINT("tracetype",o->tracetype)
03485          M_UINT("tracelevel",o->tracelevel)
03486          M_UINT("area",o->area)
03487          M_STR("ukey",o->ukey)
03488          M_END(;
03489          );
03490    }
03491 
03492    o->debuglevel=0;
03493 
03494    if (o == &usbradio_default)      /* we are done with the default */
03495       return NULL;
03496 
03497    snprintf(fname,sizeof(fname) - 1,config1,o->name);
03498 #ifdef   NEW_ASTERISK
03499    cfg1 = ast_config_load(fname,zeroflag);
03500 #else
03501    cfg1 = ast_config_load(fname);
03502 #endif
03503    o->rxmixerset = 500;
03504    o->txmixaset = 500;
03505    o->txmixbset = 500;
03506    o->rxvoiceadj = 0.5;
03507    o->rxctcssadj = 0.5;
03508    o->txctcssadj = 200;
03509    o->rxsquelchadj = 500;
03510    o->devstr[0] = 0;
03511    if (cfg1 && cfg1 != CONFIG_STATUS_FILEINVALID) {
03512       for (v = ast_variable_browse(cfg1, o->name); v; v = v->next) {
03513    
03514          M_START((char *)v->name, (char *)v->value);
03515          M_UINT("rxmixerset", o->rxmixerset)
03516          M_UINT("txmixaset", o->txmixaset)
03517          M_UINT("txmixbset", o->txmixbset)
03518          M_F("rxvoiceadj",store_rxvoiceadj(o,(char *)v->value))
03519          M_F("rxctcssadj",store_rxctcssadj(o,(char *)v->value))
03520          M_UINT("txctcssadj",o->txctcssadj);
03521          M_UINT("rxsquelchadj", o->rxsquelchadj)
03522          M_STR("devstr", o->devstr)
03523          M_END(;
03524          );
03525       }
03526       ast_config_destroy(cfg1);
03527    } else ast_log(LOG_WARNING,"File %s not found, using default parameters.\n",fname);
03528 
03529    if(o->wanteeprom)
03530    {
03531       ast_mutex_lock(&o->eepromlock);
03532       while(o->eepromctl)
03533       {
03534          ast_mutex_unlock(&o->eepromlock);
03535          usleep(10000);
03536          ast_mutex_lock(&o->eepromlock);
03537       }
03538       o->eepromctl = 1;  /* request a load */
03539       ast_mutex_unlock(&o->eepromlock);
03540    }
03541    /* if our specified one exists in the list */
03542    if ((!usb_list_check(o->devstr)) || find_desc_usb(o->devstr))
03543    {
03544       char *s;
03545 
03546       for(s = usb_device_list; *s; s += strlen(s) + 1)
03547       {
03548          if (!find_desc_usb(s)) break;
03549       }
03550       if (!*s)
03551       {
03552          ast_log(LOG_WARNING,"Unable to assign USB device for channel %s\n",o->name);
03553          goto error;
03554       }
03555       ast_log(LOG_NOTICE,"Assigned USB device %s to usbradio channel %s\n",s,o->name);
03556       strcpy(o->devstr,s);
03557    }
03558 
03559    i = usb_get_usbdev(o->devstr);
03560    if (i < 0)
03561    {
03562            ast_log(LOG_ERROR,"Not able to find alsa USB device\n");
03563       goto error;
03564    }
03565    o->devicenum = i;
03566 
03567    o->micmax = amixer_max(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL);
03568    o->spkrmax = amixer_max(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL);
03569    o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */
03570    o->dsp = ast_dsp_new();
03571    if (o->dsp)
03572    {
03573 #ifdef   NEW_ASTERISK
03574      ast_dsp_set_features(o->dsp,DSP_FEATURE_DIGIT_DETECT);
03575      ast_dsp_set_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
03576 #else
03577      ast_dsp_set_features(o->dsp,DSP_FEATURE_DTMF_DETECT);
03578      ast_dsp_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
03579 #endif
03580    }
03581 
03582    if(o->pmrChan==NULL)
03583    {
03584       t_pmr_chan tChan;
03585 
03586       // ast_log(LOG_NOTICE,"createPmrChannel() %s\n",o->name);
03587       memset(&tChan,0,sizeof(t_pmr_chan));
03588 
03589       tChan.pTxCodeDefault = o->txctcssdefault;
03590       tChan.pRxCodeSrc     = o->rxctcssfreqs;
03591       tChan.pTxCodeSrc     = o->txctcssfreqs;
03592 
03593       tChan.rxDemod=o->rxdemod;
03594       tChan.rxCdType=o->rxcdtype;
03595       tChan.rxSqVoxAdj=o->rxsqvoxadj;
03596 
03597       if (o->txprelim) 
03598          tChan.txMod = 2;
03599 
03600       tChan.txMixA = o->txmixa;
03601       tChan.txMixB = o->txmixb;
03602 
03603       tChan.rxCpuSaver=o->rxcpusaver;
03604       tChan.txCpuSaver=o->txcpusaver;
03605 
03606       tChan.b.rxpolarity=o->b.rxpolarity;
03607       tChan.b.txpolarity=o->b.txpolarity;
03608 
03609       tChan.b.dcsrxpolarity=o->b.dcsrxpolarity;
03610       tChan.b.dcstxpolarity=o->b.dcstxpolarity;
03611 
03612       tChan.b.lsdrxpolarity=o->b.lsdrxpolarity;
03613       tChan.b.lsdtxpolarity=o->b.lsdtxpolarity;
03614 
03615       tChan.tracetype=o->tracetype;
03616       tChan.tracelevel=o->tracelevel;
03617       tChan.rptnum=o->rptnum;
03618       tChan.idleinterval=o->idleinterval;
03619       tChan.turnoffs=o->turnoffs;
03620       tChan.area=o->area;
03621       tChan.ukey=o->ukey;
03622       tChan.name=o->name;
03623 
03624       o->pmrChan=createPmrChannel(&tChan,FRAME_SIZE);
03625                             
03626       o->pmrChan->radioDuplex=o->radioduplex;
03627       o->pmrChan->b.loopback=0; 
03628       o->pmrChan->txsettletime=o->txsettletime;
03629       o->pmrChan->rxCpuSaver=o->rxcpusaver;
03630       o->pmrChan->txCpuSaver=o->txcpusaver;
03631 
03632       *(o->pmrChan->prxSquelchAdjust) = 
03633          ((999 - o->rxsquelchadj) * 32767) / 1000;
03634 
03635       *(o->pmrChan->prxVoiceAdjust)=o->rxvoiceadj*M_Q8;
03636       *(o->pmrChan->prxCtcssAdjust)=o->rxctcssadj*M_Q8;
03637       o->pmrChan->rxCtcss->relax=o->rxctcssrelax;
03638       o->pmrChan->txTocType = o->txtoctype;
03639 
03640         if (    (o->txmixa == TX_OUT_LSD) ||
03641                 (o->txmixa == TX_OUT_COMPOSITE) ||
03642                 (o->txmixb == TX_OUT_LSD) ||
03643                 (o->txmixb == TX_OUT_COMPOSITE))
03644         {
03645                 set_txctcss_level(o);
03646         }
03647 
03648       if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
03649          (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
03650         )
03651       {
03652          ast_log(LOG_ERROR,"No txvoice output configured.\n");
03653       }
03654    
03655       if( o->txctcssfreq[0] && 
03656           o->txmixa!=TX_OUT_LSD && o->txmixa!=TX_OUT_COMPOSITE  &&
03657          o->txmixb!=TX_OUT_LSD && o->txmixb!=TX_OUT_COMPOSITE
03658         )
03659       {
03660          ast_log(LOG_ERROR,"No txtone output configured.\n");
03661       }
03662       
03663       if(o->b.radioactive)
03664       {
03665           // 20080328 sphenke asdf maw !!!
03666           // this diagnostic option was working but now appears broken
03667          // it's not required for operation so I'll fix it later.
03668          //struct chan_usbradio_pvt *ao;
03669          //for (ao = usbradio_default.next; ao && ao->name ; ao = ao->next)ao->pmrChan->b.radioactive=0;
03670          usbradio_active = o->name;
03671          // o->pmrChan->b.radioactive=1;
03672          //o->b.radioactive=0;
03673          //o->pmrChan->b.radioactive=0;
03674          ast_log(LOG_NOTICE,"radio active set to [%s]\n",o->name);
03675       }
03676    }
03677 
03678    xpmr_config(o);
03679 
03680    TRACEO(1,("store_config() 120\n"));
03681    mixer_write(o);
03682    TRACEO(1,("store_config() 130\n"));
03683    mult_set(o);    
03684    TRACEO(1,("store_config() 140\n"));
03685    hidhdwconfig(o);
03686 
03687    TRACEO(1,("store_config() 200\n"));
03688 
03689 #ifndef  NEW_ASTERISK
03690    if (pipe(o->sndcmd) != 0) {
03691       ast_log(LOG_ERROR, "Unable to create pipe\n");
03692       goto error;
03693    }
03694 
03695    ast_pthread_create_background(&o->sthread, NULL, sound_thread, o);
03696 #endif
03697 
03698    /* link into list of devices */
03699    if (o != &usbradio_default) {
03700       o->next = usbradio_default.next;
03701       usbradio_default.next = o;
03702    }
03703    TRACEO(1,("store_config() complete\n"));
03704    return o;
03705   
03706   error:
03707    if (o != &usbradio_default)
03708       free(o);
03709    return NULL;
03710 }
03711 
03712 
03713 #if   DEBUG_FILETEST == 1
03714 /*
03715    Test It on a File
03716 */
03717 int RxTestIt(struct chan_usbradio_pvt *o)
03718 {
03719    const int numSamples = SAMPLES_PER_BLOCK;
03720    const int numChannels = 16;
03721 
03722    i16 sample,i,ii;
03723    
03724    i32 txHangTime;
03725 
03726    i16 txEnable;
03727 
03728    t_pmr_chan  tChan;
03729    t_pmr_chan *pChan;
03730 
03731    FILE *hInput=NULL, *hOutput=NULL, *hOutputTx=NULL;
03732  
03733    i16 iBuff[numSamples*2*6], oBuff[numSamples];
03734               
03735    printf("RxTestIt()\n");
03736 
03737    pChan=o->pmrChan;
03738    pChan->b.txCapture=1;
03739    pChan->b.rxCapture=1;
03740 
03741    txEnable = 0;
03742 
03743    hInput  = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
03744    if(!hInput){
03745       printf(" RxTestIt() File Not Found.\n");
03746       return 0;
03747    }
03748    hOutput = fopen("/usr/src/xpmr/testdata/rx_debug.pcm","w");
03749 
03750    printf(" RxTestIt() Working...\n");
03751             
03752    while(!feof(hInput))
03753    {
03754       fread((void *)iBuff,2,numSamples*2*6,hInput);
03755        
03756       if(txHangTime)txHangTime-=numSamples;
03757       if(txHangTime<0)txHangTime=0;
03758       
03759       if(pChan->rxCtcss->decode)txHangTime=(8000/1000*2000);
03760 
03761       if(pChan->rxCtcss->decode && !txEnable)
03762       {
03763          txEnable=1;
03764          //pChan->inputBlanking=(8000/1000*200);
03765       }
03766       else if(!pChan->rxCtcss->decode && txEnable)
03767       {
03768          txEnable=0; 
03769       }
03770 
03771       PmrRx(pChan,iBuff,oBuff);
03772 
03773       if (fwrite((void *)pChan->prxDebug,2,numSamples*numChannels,hOutput) != numSamples * numChannels) {
03774          ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
03775       }
03776    }
03777    pChan->b.txCapture=0;
03778    pChan->b.rxCapture=0;
03779 
03780    if(hInput)fclose(hInput);
03781    if(hOutput)fclose(hOutput);
03782 
03783    printf(" RxTestIt() Complete.\n");
03784 
03785    return 0;
03786 }
03787 #endif
03788 
03789 #ifdef   NEW_ASTERISK
03790 
03791 static char *res2cli(int r)
03792 
03793 {
03794    switch (r)
03795    {
03796        case RESULT_SUCCESS:
03797       return(CLI_SUCCESS);
03798        case RESULT_SHOWUSAGE:
03799       return(CLI_SHOWUSAGE);
03800        default:
03801       return(CLI_FAILURE);
03802    }
03803 }
03804 
03805 static char *handle_console_key(struct ast_cli_entry *e,
03806    int cmd, struct ast_cli_args *a)
03807 {
03808    char *argv[] = { "radio", "key", NULL };
03809 
03810         switch (cmd) {
03811         case CLI_INIT:
03812                 e->command = "radio key";
03813                 e->usage = key_usage;
03814                 return NULL;
03815         case CLI_GENERATE:
03816                 return NULL;
03817    }
03818    return res2cli(console_key(a->fd, 2, argv));
03819 }
03820 
03821 static char *handle_console_unkey(struct ast_cli_entry *e,
03822    int cmd, struct ast_cli_args *a)
03823 {
03824    char *argv[] = { "radio", "unkey", NULL };
03825         switch (cmd) {
03826         case CLI_INIT:
03827                 e->command = "radio unkey";
03828                 e->usage = unkey_usage;
03829                 return NULL;
03830         case CLI_GENERATE:
03831                 return NULL;
03832    }
03833    return res2cli(console_unkey(a->fd, 2, argv));
03834 }
03835 
03836 static char *handle_radio_tune(struct ast_cli_entry *e,
03837    int cmd, struct ast_cli_args *a)
03838 {
03839    char *argv[5] = { "radio", "tune", a->argc > 2 ? (char *) a->argv[2] : NULL, a->argc > 3 ? (char *) a->argv[3] : NULL };
03840         switch (cmd) {
03841         case CLI_INIT:
03842                 e->command = "radio tune";
03843                 e->usage = radio_tune_usage;
03844                 return NULL;
03845         case CLI_GENERATE:
03846                 return NULL;
03847    }
03848    return res2cli(radio_tune(a->fd, a->argc, argv));
03849 }
03850 
03851 static char *handle_radio_debug(struct ast_cli_entry *e,
03852    int cmd, struct ast_cli_args *a)
03853 {
03854         switch (cmd) {
03855         case CLI_INIT:
03856                 e->command = "radio debug";
03857                 e->usage = radio_tune_usage;
03858                 return NULL;
03859         case CLI_GENERATE:
03860                 return NULL;
03861    }
03862    return res2cli(radio_set_debug(a->fd, a->argc, NULL /* ignored */));
03863 }
03864 
03865 static char *handle_radio_debug_off(struct ast_cli_entry *e,
03866    int cmd, struct ast_cli_args *a)
03867 {
03868         switch (cmd) {
03869         case CLI_INIT:
03870                 e->command = "radio debug off";
03871                 e->usage = radio_tune_usage;
03872                 return NULL;
03873         case CLI_GENERATE:
03874                 return NULL;
03875    }
03876    return res2cli(radio_set_debug_off(a->fd, a->argc, NULL /* ignored */));
03877 }
03878 
03879 static char *handle_radio_active(struct ast_cli_entry *e,
03880    int cmd, struct ast_cli_args *a)
03881 {
03882    char *argv[4] = { "radio", "active", a->argc > 2 ? (char *) a->argv[2] : NULL, };
03883         switch (cmd) {
03884         case CLI_INIT:
03885                 e->command = "radio active";
03886                 e->usage = active_usage;
03887                 return NULL;
03888         case CLI_GENERATE:
03889                 return NULL;
03890    }
03891    return res2cli(radio_active(a->fd, a->argc, argv));
03892 }
03893 
03894 static char *handle_set_xdebug(struct ast_cli_entry *e,
03895    int cmd, struct ast_cli_args *a)
03896 {
03897    char *argv[5] = { "radio", "set", "xdebug", a->argc == 4 ? (char *) a->argv[3] : NULL, };
03898         switch (cmd) {
03899         case CLI_INIT:
03900                 e->command = "radio set xdebug";
03901                 e->usage = active_usage;
03902                 return NULL;
03903         case CLI_GENERATE:
03904                 return NULL;
03905    }
03906    return res2cli(radio_set_xpmr_debug(a->fd, a->argc, argv));
03907 }
03908 
03909 
03910 static struct ast_cli_entry cli_usbradio[] = {
03911    AST_CLI_DEFINE(handle_console_key,"Simulate Rx Signal Present"),
03912    AST_CLI_DEFINE(handle_console_unkey,"Simulate Rx Signal Loss"),
03913    AST_CLI_DEFINE(handle_radio_tune,"Radio Tune"),
03914    AST_CLI_DEFINE(handle_radio_debug,"Radio Debug On"),
03915    AST_CLI_DEFINE(handle_radio_debug_off,"Radio Debug Off"),
03916    AST_CLI_DEFINE(handle_radio_active,"Change commanded device"),
03917    AST_CLI_DEFINE(handle_set_xdebug,"Radio set xpmr debug level")
03918 };
03919 
03920 #endif
03921 
03922 #include "./xpmr/xpmr.c"
03923 #ifdef HAVE_XPMRX
03924 #include "./xpmrx/xpmrx.c"
03925 #endif
03926 
03927 /*
03928 */
03929 static int load_module(void)
03930 {
03931    struct ast_config *cfg = NULL;
03932    char *ctg = NULL;
03933 #ifdef   NEW_ASTERISK
03934    struct ast_flags zeroflag = {0};
03935 #endif
03936 
03937    if (hid_device_mklist()) {
03938       ast_log(LOG_NOTICE, "Unable to make hid list\n");
03939       return AST_MODULE_LOAD_DECLINE;
03940    }
03941 
03942    usb_list_check("");
03943 
03944    usbradio_active = NULL;
03945 
03946    /* Copy the default jb config over global_jbconf */
03947    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
03948 
03949    /* load config file */
03950 #ifdef   NEW_ASTERISK
03951    if (!(cfg = ast_config_load(config,zeroflag)) || cfg == CONFIG_STATUS_FILEINVALID) {
03952 #else
03953    if (!(cfg = ast_config_load(config))) || cfg == CONFIG_STATUS_FILEINVALID {
03954 #endif
03955       ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
03956       return AST_MODULE_LOAD_DECLINE;
03957    }
03958 
03959    do {
03960       store_config(cfg, ctg);
03961    } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL);
03962 
03963    ast_config_destroy(cfg);
03964 
03965    if (find_desc(usbradio_active) == NULL) {
03966       ast_log(LOG_NOTICE, "radio active device %s not found\n", usbradio_active);
03967       /* XXX we could default to 'dsp' perhaps ? */
03968       /* XXX should cleanup allocated memory etc. */
03969       return AST_MODULE_LOAD_DECLINE;
03970    }
03971 
03972    if (ast_channel_register(&usbradio_tech)) {
03973       ast_log(LOG_ERROR, "Unable to register channel type 'usb'\n");
03974       return AST_MODULE_LOAD_DECLINE;
03975    }
03976 
03977    ast_cli_register_multiple(cli_usbradio, ARRAY_LEN(cli_usbradio));
03978 
03979    return AST_MODULE_LOAD_SUCCESS;
03980 }
03981 /*
03982 */
03983 static int unload_module(void)
03984 {
03985    struct chan_usbradio_pvt *o;
03986 
03987    ast_log(LOG_WARNING, "unload_module() called\n");
03988 
03989    ast_channel_unregister(&usbradio_tech);
03990    ast_cli_unregister_multiple(cli_usbradio, ARRAY_LEN(cli_usbradio));
03991 
03992    for (o = usbradio_default.next; o; o = o->next) {
03993 
03994       ast_log(LOG_WARNING, "destroyPmrChannel() called\n");
03995       if(o->pmrChan)destroyPmrChannel(o->pmrChan);
03996       
03997       #if DEBUG_CAPTURES == 1
03998       if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
03999       if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
04000       if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
04001       if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
04002       if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
04003       if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
04004       #endif
04005 
04006       close(o->sounddev);
04007 #ifndef  NEW_ASTERISK
04008       if (o->sndcmd[0] > 0) {
04009          close(o->sndcmd[0]);
04010          close(o->sndcmd[1]);
04011       }
04012 #endif
04013       if (o->dsp) ast_dsp_free(o->dsp);
04014       if (o->owner)
04015          ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
04016       if (o->owner)        /* XXX how ??? */
04017          return -1;
04018       /* XXX what about the thread ? */
04019       /* XXX what about the memory allocated ? */
04020    }
04021    return 0;
04022 }
04023 
04024 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "usb Console Channel Driver");
04025 
04026 /* end of file */
04027 
04028