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