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