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