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