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