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