00001
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 #include "asterisk.h"
00042
00043 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 159024 $")
00044
00045 #include <ctype.h>
00046 #include <math.h>
00047 #include <sys/ioctl.h>
00048 #include <fcntl.h>
00049 #include <sys/time.h>
00050 #include <usb.h>
00051 #include <alsa/asoundlib.h>
00052
00053 #define CHAN_USBRADIO 1
00054
00055 #define DEBUG_USBRADIO 0
00056 #define DEBUG_CAPTURES 1
00057
00058 #define DEBUG_CAP_RX_OUT 0
00059 #define DEBUG_CAP_TX_OUT 0
00060
00061 #define DEBUG_FILETEST 0
00062
00063 #define RX_CAP_RAW_FILE "/tmp/rx_cap_in.pcm"
00064 #define RX_CAP_TRACE_FILE "/tmp/rx_trace.pcm"
00065 #define RX_CAP_OUT_FILE "/tmp/rx_cap_out.pcm"
00066
00067 #define TX_CAP_RAW_FILE "/tmp/tx_cap_in.pcm"
00068 #define TX_CAP_TRACE_FILE "/tmp/tx_trace.pcm"
00069 #define TX_CAP_OUT_FILE "/tmp/tx_cap_out.pcm"
00070
00071 #define MIXER_PARAM_MIC_PLAYBACK_SW "Mic Playback Switch"
00072 #define MIXER_PARAM_MIC_PLAYBACK_VOL "Mic Playback Volume"
00073 #define MIXER_PARAM_MIC_CAPTURE_SW "Mic Capture Switch"
00074 #define MIXER_PARAM_MIC_CAPTURE_VOL "Mic Capture Volume"
00075 #define MIXER_PARAM_MIC_BOOST "Auto Gain Control"
00076 #define MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
00077 #define MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
00078
00079 #include "./xpmr/xpmr.h"
00080
00081 #if 0
00082 #define traceusb1(a, ...) ast_debug(4, a __VA_ARGS__)
00083 #else
00084 #define traceusb1(a, ...)
00085 #endif
00086
00087 #if 0
00088 #define traceusb2(a, ...) ast_debug(4, a __VA_ARGS__)
00089 #else
00090 #define traceusb2(a, ...)
00091 #endif
00092
00093 #ifdef __linux
00094 #include <linux/soundcard.h>
00095 #elif defined(__FreeBSD__)
00096 #include <sys/soundcard.h>
00097 #else
00098 #include <soundcard.h>
00099 #endif
00100
00101 #include "asterisk/lock.h"
00102 #include "asterisk/frame.h"
00103 #include "asterisk/callerid.h"
00104 #include "asterisk/channel.h"
00105 #include "asterisk/module.h"
00106 #include "asterisk/pbx.h"
00107 #include "asterisk/config.h"
00108 #include "asterisk/cli.h"
00109 #include "asterisk/utils.h"
00110 #include "asterisk/causes.h"
00111 #include "asterisk/endian.h"
00112 #include "asterisk/stringfields.h"
00113 #include "asterisk/abstract_jb.h"
00114 #include "asterisk/musiconhold.h"
00115 #include "asterisk/dsp.h"
00116
00117 #define C108_VENDOR_ID 0x0d8c
00118 #define C108_PRODUCT_ID 0x000c
00119 #define C108_HID_INTERFACE 3
00120
00121 #define HID_REPORT_GET 0x01
00122 #define HID_REPORT_SET 0x09
00123
00124 #define HID_RT_INPUT 0x01
00125 #define HID_RT_OUTPUT 0x02
00126
00127
00128 static struct ast_jb_conf default_jbconf =
00129 {
00130 .flags = 0,
00131 .max_size = -1,
00132 .resync_threshold = -1,
00133 .impl = "",
00134 };
00135 static struct ast_jb_conf global_jbconf;
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 #define FRAME_SIZE 160
00230 #define QUEUE_SIZE 20
00231
00232 #if defined(__FreeBSD__)
00233 #define FRAGS 0x8
00234 #else
00235 #define FRAGS ( ( (6 * 5) << 16 ) | 0xc )
00236 #endif
00237
00238
00239
00240
00241
00242 #define TEXT_SIZE 256
00243
00244 #if 0
00245 #define TRYOPEN 1
00246 #endif
00247 #define O_CLOSE 0x444
00248
00249 #if defined( __OpenBSD__ ) || defined( __NetBSD__ )
00250 #define DEV_DSP "/dev/audio"
00251 #else
00252 #define DEV_DSP "/dev/dsp"
00253 #endif
00254
00255 #ifndef MIN
00256 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00257 #endif
00258 #ifndef MAX
00259 #define MAX(a,b) ((a) > (b) ? (a) : (b))
00260 #endif
00261
00262 static char *config = "usbradio.conf";
00263 static char *config1 = "usbradio_tune.conf";
00264
00265 static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
00266 static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
00267
00268 static int usbradio_debug;
00269 #if 0
00270 static int usbradio_debug_level = 0;
00271 #endif
00272
00273 enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
00274 enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
00275 enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR};
00276 enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
00277 enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
00278 enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 struct chan_usbradio_pvt {
00290 struct chan_usbradio_pvt *next;
00291
00292 char *name;
00293
00294 int total_blocks;
00295 int sounddev;
00296 enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
00297 i16 cdMethod;
00298 int autoanswer;
00299 int autohangup;
00300 int hookstate;
00301 unsigned int queuesize;
00302 unsigned int frags;
00303
00304 int warned;
00305 #define WARN_used_blocks 1
00306 #define WARN_speed 2
00307 #define WARN_frag 4
00308 int w_errors;
00309 struct timeval lastopen;
00310
00311 int overridecontext;
00312 int mute;
00313
00314
00315
00316
00317 #define BOOST_SCALE (1<<9)
00318 #define BOOST_MAX 40
00319 int boost;
00320 char devicenum;
00321 int spkrmax;
00322 int micmax;
00323
00324 pthread_t sthread;
00325 pthread_t hidthread;
00326
00327 int stophid;
00328 struct ast_channel *owner;
00329 char ext[AST_MAX_EXTENSION];
00330 char ctx[AST_MAX_CONTEXT];
00331 char language[MAX_LANGUAGE];
00332 char cid_name[256];
00333 char cid_num[256];
00334 char mohinterpret[MAX_MUSICCLASS];
00335
00336
00337 char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];
00338 char usbradio_write_buf_1[FRAME_SIZE * 2 * 2 * 6];
00339
00340 int usbradio_write_dst;
00341
00342
00343
00344 char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
00345 char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
00346 int readpos;
00347 struct ast_frame read_f;
00348
00349
00350 char debuglevel;
00351 char radioduplex;
00352
00353 char lastrx;
00354 char rxhidsq;
00355 char rxcarrierdetect;
00356 char rxctcssdecode;
00357
00358 char rxkeytype;
00359 char rxkeyed;
00360
00361 char lasttx;
00362 char txkeyed;
00363 char txchankey;
00364 char txtestkey;
00365
00366 time_t lasthidtime;
00367 struct ast_dsp *dsp;
00368
00369 t_pmr_chan *pmrChan;
00370
00371 char rxcpusaver;
00372 char txcpusaver;
00373
00374 char rxdemod;
00375 float rxgain;
00376 char rxcdtype;
00377 char rxsdtype;
00378 int rxsquelchadj;
00379 char txtoctype;
00380
00381 char txprelim;
00382 float txctcssgain;
00383 char txmixa;
00384 char txmixb;
00385
00386 char invertptt;
00387
00388 char rxctcssrelax;
00389 float rxctcssgain;
00390 float rxctcssfreq;
00391 float txctcssfreq;
00392
00393 int rxmixerset;
00394 int rxboostset;
00395 float rxvoiceadj;
00396 float rxctcssadj;
00397 int txmixaset;
00398 int txmixbset;
00399 int txctcssadj;
00400
00401 int hdwtype;
00402 int hid_gpio_ctl;
00403 int hid_gpio_ctl_loc;
00404 int hid_io_cor;
00405 int hid_io_cor_loc;
00406 int hid_io_ctcss;
00407 int hid_io_ctcss_loc;
00408 int hid_io_ptt;
00409 int hid_gpio_loc;
00410
00411 struct {
00412 unsigned rxcapraw:1;
00413 unsigned txcapraw:1;
00414 unsigned txcap2:1;
00415 unsigned rxcap2:1;
00416 } b;
00417 };
00418
00419
00420 static struct chan_usbradio_pvt usbradio_default = {
00421 .sounddev = -1,
00422 .duplex = M_UNSET,
00423 .autoanswer = 1,
00424 .autohangup = 1,
00425 .queuesize = QUEUE_SIZE,
00426 .frags = FRAGS,
00427 .ext = "s",
00428 .ctx = "default",
00429 .readpos = AST_FRIENDLY_OFFSET,
00430 .lastopen = { 0, 0 },
00431 .boost = BOOST_SCALE,
00432 };
00433
00434
00435
00436 static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s);
00437 static int hidhdwconfig(struct chan_usbradio_pvt *o);
00438 static int set_txctcss_level(struct chan_usbradio_pvt *o);
00439 static void pmrdump(struct chan_usbradio_pvt *o);
00440 static void mult_set(struct chan_usbradio_pvt *o);
00441 static int mult_calc(int value);
00442 static void mixer_write(struct chan_usbradio_pvt *o);
00443 static void tune_rxinput(struct chan_usbradio_pvt *o);
00444 static void tune_rxvoice(struct chan_usbradio_pvt *o);
00445 static void tune_rxctcss(struct chan_usbradio_pvt *o);
00446 static void tune_txoutput(struct chan_usbradio_pvt *o, int value);
00447 static void tune_write(struct chan_usbradio_pvt *o);
00448
00449 static char *usbradio_active;
00450
00451 static int setformat(struct chan_usbradio_pvt *o, int mode);
00452
00453 static struct ast_channel *usbradio_request(const char *type, int format, void *data
00454 , int *cause);
00455 static int usbradio_digit_begin(struct ast_channel *c, char digit);
00456 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration);
00457 static int usbradio_text(struct ast_channel *c, const char *text);
00458 static int usbradio_hangup(struct ast_channel *c);
00459 static int usbradio_answer(struct ast_channel *c);
00460 static struct ast_frame *usbradio_read(struct ast_channel *chan);
00461 static int usbradio_call(struct ast_channel *c, char *dest, int timeout);
00462 static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
00463 static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
00464 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00465
00466 #if DEBUG_FILETEST == 1
00467 static int RxTestIt(struct chan_usbradio_pvt *o);
00468 #endif
00469
00470 static char tdesc[] = "USB (CM108) Radio Channel Driver";
00471
00472 static const struct ast_channel_tech usbradio_tech = {
00473 .type = "Radio",
00474 .description = tdesc,
00475 .capabilities = AST_FORMAT_SLINEAR,
00476 .requester = usbradio_request,
00477 .send_digit_begin = usbradio_digit_begin,
00478 .send_digit_end = usbradio_digit_end,
00479 .send_text = usbradio_text,
00480 .hangup = usbradio_hangup,
00481 .answer = usbradio_answer,
00482 .read = usbradio_read,
00483 .call = usbradio_call,
00484 .write = usbradio_write,
00485 .indicate = usbradio_indicate,
00486 .fixup = usbradio_fixup,
00487 };
00488
00489
00490
00491
00492
00493
00494
00495 static int amixer_max(int devnum,char *param)
00496 {
00497 int rv,type;
00498 char str[15];
00499 snd_hctl_t *hctl;
00500 snd_ctl_elem_id_t *id;
00501 snd_hctl_elem_t *elem;
00502 snd_ctl_elem_info_t *info;
00503
00504 snprintf(str, sizeof(str), "hw:%d", devnum);
00505 if (snd_hctl_open(&hctl, str, 0))
00506 return -1;
00507 snd_hctl_load(hctl);
00508 id = alloca(snd_ctl_elem_id_sizeof());
00509 memset(id, 0, snd_ctl_elem_id_sizeof());
00510 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
00511 snd_ctl_elem_id_set_name(id, param);
00512 elem = snd_hctl_find_elem(hctl, id);
00513 if (!elem) {
00514 snd_hctl_close(hctl);
00515 return -1;
00516 }
00517 info = alloca(snd_ctl_elem_info_sizeof());
00518 memset(info, 0, snd_ctl_elem_info_sizeof());
00519 snd_hctl_elem_info(elem,info);
00520 type = snd_ctl_elem_info_get_type(info);
00521 rv = 0;
00522 switch (type) {
00523 case SND_CTL_ELEM_TYPE_INTEGER:
00524 rv = snd_ctl_elem_info_get_max(info);
00525 break;
00526 case SND_CTL_ELEM_TYPE_BOOLEAN:
00527 rv = 1;
00528 break;
00529 }
00530 snd_hctl_close(hctl);
00531 return(rv);
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 static int setamixer(int devnum, char *param, int v1, int v2)
00541 {
00542 int type;
00543 char str[15];
00544 snd_hctl_t *hctl;
00545 snd_ctl_elem_id_t *id;
00546 snd_ctl_elem_value_t *control;
00547 snd_hctl_elem_t *elem;
00548 snd_ctl_elem_info_t *info;
00549
00550 snprintf(str, sizeof(str), "hw:%d", devnum);
00551 if (snd_hctl_open(&hctl, str, 0))
00552 return -1;
00553 snd_hctl_load(hctl);
00554 id = alloca(snd_ctl_elem_id_sizeof());
00555 memset(id, 0, snd_ctl_elem_id_sizeof());
00556 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
00557 snd_ctl_elem_id_set_name(id, param);
00558 elem = snd_hctl_find_elem(hctl, id);
00559 if (!elem) {
00560 snd_hctl_close(hctl);
00561 return -1;
00562 }
00563 info = alloca(snd_ctl_elem_info_sizeof());
00564 memset(info, 0, snd_ctl_elem_info_sizeof());
00565 snd_hctl_elem_info(elem,info);
00566 type = snd_ctl_elem_info_get_type(info);
00567 control = alloca(snd_ctl_elem_value_sizeof());
00568 memset(control, 0, snd_ctl_elem_value_sizeof());
00569 snd_ctl_elem_value_set_id(control, id);
00570 switch (type) {
00571 case SND_CTL_ELEM_TYPE_INTEGER:
00572 snd_ctl_elem_value_set_integer(control, 0, v1);
00573 if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2);
00574 break;
00575 case SND_CTL_ELEM_TYPE_BOOLEAN:
00576 snd_ctl_elem_value_set_integer(control, 0, (v1 != 0));
00577 break;
00578 }
00579 if (snd_hctl_elem_write(elem, control)) {
00580 snd_hctl_close(hctl);
00581 return(-1);
00582 }
00583 snd_hctl_close(hctl);
00584 return 0;
00585 }
00586
00587 static void hid_set_outputs(struct usb_dev_handle *handle,
00588 unsigned char *outputs)
00589 {
00590 usb_control_msg(handle,
00591 USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
00592 HID_REPORT_SET,
00593 0 + (HID_RT_OUTPUT << 8),
00594 C108_HID_INTERFACE,
00595 (char *)outputs, 4, 5000);
00596 }
00597
00598 static void hid_get_inputs(struct usb_dev_handle *handle,
00599 unsigned char *inputs)
00600 {
00601 usb_control_msg(handle,
00602 USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
00603 HID_REPORT_GET,
00604 0 + (HID_RT_INPUT << 8),
00605 C108_HID_INTERFACE,
00606 (char *)inputs, 4, 5000);
00607 }
00608
00609 static struct usb_device *hid_device_init(void)
00610 {
00611 struct usb_bus *usb_bus;
00612 struct usb_device *dev;
00613
00614 usb_init();
00615 usb_find_busses();
00616 usb_find_devices();
00617 for (usb_bus = usb_busses; usb_bus; usb_bus = usb_bus->next) {
00618 for (dev = usb_bus->devices; dev; dev = dev->next) {
00619 if ((dev->descriptor.idVendor == C108_VENDOR_ID) && (dev->descriptor.idProduct == C108_PRODUCT_ID))
00620 return dev;
00621 }
00622 }
00623 return NULL;
00624 }
00625
00626 static int hidhdwconfig(struct chan_usbradio_pvt *o)
00627 {
00628 if (o->hdwtype == 1) {
00629 o->hid_gpio_ctl = 0x08;
00630 o->hid_gpio_ctl_loc = 2;
00631 o->hid_io_cor = 4;
00632 o->hid_io_cor_loc = 1;
00633 o->hid_io_ctcss = 2;
00634 o->hid_io_ctcss_loc = 1;
00635 o->hid_io_ptt = 8;
00636 o->hid_gpio_loc = 1;
00637 } else if (o->hdwtype == 0) {
00638 o->hid_gpio_ctl = 0x0c;
00639 o->hid_gpio_ctl_loc = 2;
00640 o->hid_io_cor = 2;
00641 o->hid_io_cor_loc = 0;
00642 o->hid_io_ctcss = 2;
00643 o->hid_io_ctcss_loc = 1;
00644 o->hid_io_ptt = 4;
00645 o->hid_gpio_loc = 1;
00646 } else if (o->hdwtype == 3) {
00647 o->hid_gpio_ctl = 0x0c;
00648 o->hid_gpio_ctl_loc = 2;
00649 o->hid_io_cor = 2;
00650 o->hid_io_cor_loc = 0;
00651 o->hid_io_ctcss = 2;
00652 o->hid_io_ctcss_loc = 1;
00653 o->hid_io_ptt = 4;
00654 o->hid_gpio_loc = 1;
00655 }
00656
00657 return 0;
00658 }
00659
00660
00661 static void *hidthread(void *arg)
00662 {
00663 unsigned char buf[4], keyed;
00664 char lastrx, txtmp;
00665 struct usb_device *usb_dev;
00666 struct usb_dev_handle *usb_handle;
00667 struct chan_usbradio_pvt *o = arg;
00668
00669 usb_dev = hid_device_init();
00670 if (usb_dev == NULL) {
00671 ast_log(LOG_ERROR, "USB HID device not found\n");
00672 pthread_exit(NULL);
00673 }
00674 usb_handle = usb_open(usb_dev);
00675 if (usb_handle == NULL) {
00676 ast_log(LOG_ERROR, "Not able to open USB device\n");
00677 pthread_exit(NULL);
00678 }
00679 if (usb_claim_interface(usb_handle, C108_HID_INTERFACE) < 0) {
00680 if (usb_detach_kernel_driver_np(usb_handle, C108_HID_INTERFACE) < 0) {
00681 ast_log(LOG_ERROR, "Not able to detach the USB device\n");
00682 pthread_exit(NULL);
00683 }
00684 if (usb_claim_interface(usb_handle, C108_HID_INTERFACE) < 0) {
00685 ast_log(LOG_ERROR, "Not able to claim the USB device\n");
00686 pthread_exit(NULL);
00687 }
00688 }
00689 memset(buf, 0, sizeof(buf));
00690 buf[2] = o->hid_gpio_ctl;
00691 buf[1] = 0;
00692 hid_set_outputs(usb_handle, buf);
00693 traceusb1("hidthread: Starting normally!!\n");
00694 lastrx = 0;
00695 while (!o->stophid) {
00696 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
00697 hid_get_inputs(usb_handle, buf);
00698 keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
00699 if (keyed != o->rxhidsq) {
00700 if (o->debuglevel)
00701 ast_log(LOG_NOTICE, "chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
00702 o->rxhidsq = keyed;
00703 }
00704
00705
00706 txtmp = 0;
00707 if (o->txkeyed || o->txchankey || o->txtestkey || o->pmrChan->txPttOut)
00708 txtmp = 1;
00709
00710 if (o->lasttx != txtmp) {
00711 o->lasttx = txtmp;
00712 if (o->debuglevel)
00713 ast_log(LOG_NOTICE, "hidthread: tx set to %d\n", txtmp);
00714 buf[o->hid_gpio_loc] = 0;
00715 if (txtmp)
00716 buf[o->hid_gpio_loc] = o->hid_io_ptt;
00717 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
00718 hid_set_outputs(usb_handle, buf);
00719 }
00720
00721 time(&o->lasthidtime);
00722 usleep(50000);
00723 }
00724 buf[o->hid_gpio_loc] = 0;
00725 if (o->invertptt)
00726 buf[o->hid_gpio_loc] = o->hid_io_ptt;
00727 buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
00728 hid_set_outputs(usb_handle, buf);
00729 pthread_exit(0);
00730 }
00731
00732
00733
00734
00735 static struct chan_usbradio_pvt *find_desc(char *dev)
00736 {
00737 struct chan_usbradio_pvt *o = NULL;
00738
00739 if (!dev)
00740 ast_log(LOG_WARNING, "null dev\n");
00741
00742 for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
00743
00744 if (!o)
00745 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
00746
00747 return o;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 #if 0
00760 static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
00761 {
00762 struct chan_usbradio_pvt *o = find_desc(usbradio_active);
00763
00764 if (ext == NULL || ctx == NULL)
00765 return NULL;
00766
00767 *ext = *ctx = NULL;
00768
00769 if (src && *src != '\0')
00770 *ext = ast_strdup(src);
00771
00772 if (*ext == NULL)
00773 return NULL;
00774
00775 if (!o->overridecontext) {
00776
00777 *ctx = strrchr(*ext, '@');
00778 if (*ctx)
00779 *(*ctx)++ = '\0';
00780 }
00781
00782 return *ext;
00783 }
00784 #endif
00785
00786
00787
00788
00789 static int used_blocks(struct chan_usbradio_pvt *o)
00790 {
00791 struct audio_buf_info info;
00792
00793 if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
00794 if (!(o->warned & WARN_used_blocks)) {
00795 ast_log(LOG_WARNING, "Error reading output space\n");
00796 o->warned |= WARN_used_blocks;
00797 }
00798 return 1;
00799 }
00800
00801 if (o->total_blocks == 0) {
00802 ast_debug(4, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
00803 o->total_blocks = info.fragments;
00804 }
00805
00806 return o->total_blocks - info.fragments;
00807 }
00808
00809
00810 static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
00811 {
00812 int res;
00813
00814 if (o->sounddev < 0)
00815 setformat(o, O_RDWR);
00816 if (o->sounddev < 0)
00817 return 0;
00818
00819
00820
00821
00822
00823
00824 res = used_blocks(o);
00825 if (res > o->queuesize) {
00826 if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
00827 ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
00828 return 0;
00829 }
00830 o->w_errors = 0;
00831
00832 return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12);
00833 }
00834
00835
00836
00837
00838
00839
00840 static int setformat(struct chan_usbradio_pvt *o, int mode)
00841 {
00842 int fmt, desired, res, fd;
00843 char device[20];
00844
00845 if (o->sounddev >= 0) {
00846 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
00847 close(o->sounddev);
00848 o->duplex = M_UNSET;
00849 o->sounddev = -1;
00850 }
00851 if (mode == O_CLOSE)
00852 return 0;
00853 if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000)
00854 return -1;
00855 o->lastopen = ast_tvnow();
00856 strcpy(device, "/dev/dsp");
00857 if (o->devicenum)
00858 snprintf(device + strlen("/dev/dsp"), sizeof(device) - strlen("/dev/dsp"), "%d", o->devicenum);
00859 fd = o->sounddev = open(device, mode | O_NONBLOCK);
00860 if (fd < 0) {
00861 ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno));
00862 return -1;
00863 }
00864 if (o->owner)
00865 o->owner->fds[0] = fd;
00866
00867 #if __BYTE_ORDER == __LITTLE_ENDIAN
00868 fmt = AFMT_S16_LE;
00869 #else
00870 fmt = AFMT_S16_BE;
00871 #endif
00872 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
00873 if (res < 0) {
00874 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
00875 return -1;
00876 }
00877 switch (mode) {
00878 case O_RDWR:
00879 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
00880
00881 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
00882 if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
00883 ast_verb(2, "Console is full duplex\n");
00884 o->duplex = M_FULL;
00885 };
00886 break;
00887 case O_WRONLY:
00888 o->duplex = M_WRITE;
00889 break;
00890 case O_RDONLY:
00891 o->duplex = M_READ;
00892 break;
00893 }
00894
00895 fmt = 1;
00896 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
00897 if (res < 0) {
00898 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
00899 return -1;
00900 }
00901 fmt = desired = 48000;
00902 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
00903
00904 if (res < 0) {
00905 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
00906 return -1;
00907 }
00908 if (fmt != desired) {
00909 if (!(o->warned & WARN_speed)) {
00910 ast_log(LOG_WARNING,
00911 "Requested %d Hz, got %d Hz -- sound may be choppy\n",
00912 desired, fmt);
00913 o->warned |= WARN_speed;
00914 }
00915 }
00916
00917
00918
00919
00920 if (o->frags) {
00921 fmt = o->frags;
00922 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
00923 if (res < 0) {
00924 if (!(o->warned & WARN_frag)) {
00925 ast_log(LOG_WARNING,
00926 "Unable to set fragment size -- sound may be choppy\n");
00927 o->warned |= WARN_frag;
00928 }
00929 }
00930 }
00931
00932 res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
00933 res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
00934
00935 return 0;
00936 }
00937
00938
00939
00940
00941 static int usbradio_digit_begin(struct ast_channel *c, char digit)
00942 {
00943 return 0;
00944 }
00945
00946 static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration)
00947 {
00948
00949 ast_verb(0, " << Console Received digit %c of duration %u ms >> \n",
00950 digit, duration);
00951 return 0;
00952 }
00953
00954 static int usbradio_text(struct ast_channel *c, const char *text)
00955 {
00956
00957 ast_verb(0, " << Console Received text %s >> \n", text);
00958 return 0;
00959 }
00960
00961
00962
00963
00964 static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
00965 {
00966 struct chan_usbradio_pvt *o = c->tech_pvt;
00967
00968 time(&o->lasthidtime);
00969 ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
00970 ast_setstate(c, AST_STATE_UP);
00971 return 0;
00972 }
00973
00974
00975
00976
00977 static int usbradio_answer(struct ast_channel *c)
00978 {
00979 ast_setstate(c, AST_STATE_UP);
00980
00981 return 0;
00982 }
00983
00984 static int usbradio_hangup(struct ast_channel *c)
00985 {
00986 struct chan_usbradio_pvt *o = c->tech_pvt;
00987
00988 c->tech_pvt = NULL;
00989 o->owner = NULL;
00990 ast_module_unref(ast_module_info->self);
00991 if (o->hookstate) {
00992 if (o->autoanswer || o->autohangup) {
00993
00994 o->hookstate = 0;
00995 setformat(o, O_CLOSE);
00996 }
00997 }
00998 o->stophid = 1;
00999 pthread_join(o->hidthread, NULL);
01000 return 0;
01001 }
01002
01003
01004
01005 static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
01006 {
01007 int src,datalen;
01008 struct chan_usbradio_pvt *o = c->tech_pvt;
01009
01010 traceusb2("usbradio_write() o->nosound=%d\n", o->nosound);
01011
01012
01013
01014
01015
01016
01017
01018
01019 if (o->txkeyed || o->txtestkey)
01020 o->pmrChan->txPttIn = 1;
01021 else
01022 o->pmrChan->txPttIn = 0;
01023
01024 #if DEBUG_CAPTURES == 1
01025 if (ftxcapraw && o->b.txcapraw) {
01026 i16 i, tbuff[f->datalen];
01027 for (i = 0; i < f->datalen; i += 2) {
01028 tbuff[i] = ((i16 *)(f->data))[i / 2];
01029 tbuff[i + 1] = o->txkeyed * M_Q13;
01030 }
01031 if (fwrite(tbuff, 2, f->datalen, ftxcapraw) != f->datalen) {
01032 ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
01033 }
01034
01035 }
01036 #endif
01037
01038 PmrTx(o->pmrChan,(i16*)f->data,(i16*)o->usbradio_write_buf_1);
01039
01040 #if 0
01041 if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
01042 if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,f->datalen * 2 * 6,ftxoutraw);
01043 #endif
01044
01045 #if DEBUG_CAPTURES == 1
01046 if ((o->b.txcap2 && ftxcaptrace) && (fwrite((o->pmrChan->ptxDebug), 1, FRAME_SIZE * 2 * 16, ftxcaptrace) != FRAME_SIZE * 2 * 16)) {
01047 ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
01048 }
01049 #endif
01050
01051 src = 0;
01052 datalen = f->datalen * 12;
01053 while (src < datalen) {
01054
01055 int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
01056
01057 if (datalen - src >= l) {
01058 memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
01059 soundcard_writeframe(o, (short *) o->usbradio_write_buf);
01060 src += l;
01061 o->usbradio_write_dst = 0;
01062 } else {
01063 l = datalen - src;
01064 memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
01065 src += l;
01066 o->usbradio_write_dst += l;
01067 }
01068 }
01069 return 0;
01070 }
01071
01072 static struct ast_frame *usbradio_read(struct ast_channel *c)
01073 {
01074 int res;
01075 struct chan_usbradio_pvt *o = c->tech_pvt;
01076 struct ast_frame *f = &o->read_f, *f1;
01077 struct ast_frame wf = { AST_FRAME_CONTROL };
01078 time_t now;
01079
01080 traceusb2("usbradio_read()\n");
01081
01082 if (o->lasthidtime) {
01083 time(&now);
01084 if ((now - o->lasthidtime) > 3) {
01085 ast_log(LOG_ERROR, "HID process has died or something!!\n");
01086 return NULL;
01087 }
01088 }
01089 if (o->lastrx && (!o->rxkeyed)) {
01090 o->lastrx = 0;
01091 wf.subclass = AST_CONTROL_RADIO_UNKEY;
01092 ast_queue_frame(o->owner, &wf);
01093 } else if ((!o->lastrx) && (o->rxkeyed)) {
01094 o->lastrx = 1;
01095 wf.subclass = AST_CONTROL_RADIO_KEY;
01096 ast_queue_frame(o->owner, &wf);
01097 }
01098
01099
01100 memset(f, 0, sizeof(struct ast_frame));
01101 f->frametype = AST_FRAME_NULL;
01102 f->src = usbradio_tech.type;
01103
01104 res = read(o->sounddev, o->usbradio_read_buf + o->readpos,
01105 sizeof(o->usbradio_read_buf) - o->readpos);
01106 if (res < 0)
01107 return f;
01108
01109 o->readpos += res;
01110 if (o->readpos < sizeof(o->usbradio_read_buf))
01111 return f;
01112
01113 if (o->mute)
01114 return f;
01115
01116 #if DEBUG_CAPTURES == 1
01117 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)) {
01118 ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
01119 }
01120 #endif
01121
01122 #if 1
01123 PmrRx( o->pmrChan,
01124 (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
01125 (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
01126
01127 #else
01128 static FILE *hInput;
01129 i16 iBuff[FRAME_SIZE * 2 * 6];
01130
01131 o->pmrChan->b.rxCapture = 1;
01132
01133 if(!hInput) {
01134 hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm", "r");
01135 if(!hInput) {
01136 ast_log(LOG_ERROR, " Input Data File Not Found.\n");
01137 return 0;
01138 }
01139 }
01140
01141 if (0 == fread((void *)iBuff, 2, FRAME_SIZE * 2 * 6, hInput))
01142 exit;
01143
01144 PmrRx( o->pmrChan,
01145 (i16 *)iBuff,
01146 (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
01147
01148 #endif
01149
01150 #if 0
01151 if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE, "w");
01152 if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET), 1, FRAME_SIZE * 2, frxoutraw);
01153 #endif
01154
01155 #if DEBUG_CAPTURES == 1
01156 if ((frxcaptrace && o->b.rxcap2) && (fwrite((o->pmrChan->prxDebug), 1, FRAME_SIZE * 2 * 16, frxcaptrace) != FRAME_SIZE * 2 * 16)) {
01157 ast_log(LOG_ERROR, "fwrite() error: %s\n", strerror(errno));
01158 }
01159 #endif
01160
01161 if (o->rxcdtype == CD_HID && (o->pmrChan->rxExtCarrierDetect != o->rxhidsq))
01162 o->pmrChan->rxExtCarrierDetect = o->rxhidsq;
01163 if (o->rxcdtype == CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect == o->rxhidsq))
01164 o->pmrChan->rxExtCarrierDetect = !o->rxhidsq;
01165
01166 if ( (o->rxcdtype == CD_HID && o->rxhidsq) ||
01167 (o->rxcdtype == CD_HID_INVERT && !o->rxhidsq) ||
01168 (o->rxcdtype == CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
01169 (o->rxcdtype == CD_XPMR_VOX && o->pmrChan->rxCarrierDetect) )
01170 res = 1;
01171 else
01172 res = 0;
01173
01174 if (res != o->rxcarrierdetect) {
01175 o->rxcarrierdetect = res;
01176 if (o->debuglevel)
01177 ast_debug(4, "rxcarrierdetect = %d\n", res);
01178 }
01179
01180 if (o->pmrChan->rxCtcss->decode != o->rxctcssdecode) {
01181 if (o->debuglevel)
01182 ast_debug(4, "rxctcssdecode = %d\n", o->pmrChan->rxCtcss->decode);
01183 o->rxctcssdecode = o->pmrChan->rxCtcss->decode;
01184 }
01185
01186 if ( ( o->rxctcssfreq && (o->rxctcssdecode == o->pmrChan->rxCtcssIndex)) ||
01187 ( !o->rxctcssfreq && o->rxcarrierdetect) )
01188 o->rxkeyed = 1;
01189 else
01190 o->rxkeyed = 0;
01191
01192
01193 o->readpos = AST_FRIENDLY_OFFSET;
01194 if (c->_state != AST_STATE_UP)
01195 return f;
01196
01197 f->frametype = AST_FRAME_VOICE;
01198 f->subclass = AST_FORMAT_SLINEAR;
01199 f->samples = FRAME_SIZE;
01200 f->datalen = FRAME_SIZE * 2;
01201 f->data = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET;
01202 if (o->boost != BOOST_SCALE) {
01203 int i, x;
01204 int16_t *p = (int16_t *) f->data;
01205 for (i = 0; i < f->samples; i++) {
01206 x = (p[i] * o->boost) / BOOST_SCALE;
01207 if (x > 32767)
01208 x = 32767;
01209 else if (x < -32768)
01210 x = -32768;
01211 p[i] = x;
01212 }
01213 }
01214
01215 f->offset = AST_FRIENDLY_OFFSET;
01216 if (o->dsp) {
01217 f1 = ast_dsp_process(c, o->dsp, f);
01218 if ((f1->frametype == AST_FRAME_DTMF_END) || (f1->frametype == AST_FRAME_DTMF_BEGIN)) {
01219 if ((f1->subclass == 'm') || (f1->subclass == 'u'))
01220 f1->frametype = AST_FRAME_DTMF_BEGIN;
01221 if (f1->frametype == AST_FRAME_DTMF_END)
01222 ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
01223 return f1;
01224 }
01225 }
01226 return f;
01227 }
01228
01229 static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01230 {
01231 struct chan_usbradio_pvt *o = newchan->tech_pvt;
01232 ast_log(LOG_WARNING,"usbradio_fixup()\n");
01233 o->owner = newchan;
01234 return 0;
01235 }
01236
01237 static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
01238 {
01239 struct chan_usbradio_pvt *o = c->tech_pvt;
01240 int res = 0;
01241
01242 switch (cond) {
01243 case AST_CONTROL_BUSY:
01244 case AST_CONTROL_CONGESTION:
01245 case AST_CONTROL_RINGING:
01246 case -1:
01247 res = -1;
01248 break;
01249 case AST_CONTROL_PROGRESS:
01250 case AST_CONTROL_PROCEEDING:
01251 case AST_CONTROL_VIDUPDATE:
01252 break;
01253 case AST_CONTROL_HOLD:
01254 ast_verb(0, " << Console Has Been Placed on Hold >> \n");
01255 ast_moh_start(c, data, o->mohinterpret);
01256 break;
01257 case AST_CONTROL_UNHOLD:
01258 ast_verb(0, " << Console Has Been Retrieved from Hold >> \n");
01259 ast_moh_stop(c);
01260 break;
01261 case AST_CONTROL_RADIO_KEY:
01262 o->txkeyed = 1;
01263 if (o->debuglevel)
01264 ast_verb(0, " << Radio Transmit On. >> \n");
01265 break;
01266 case AST_CONTROL_RADIO_UNKEY:
01267 o->txkeyed = 0;
01268 if (o->debuglevel)
01269 ast_verb(0, " << Radio Transmit Off. >> \n");
01270 break;
01271 default:
01272 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
01273 return -1;
01274 }
01275
01276 return res;
01277 }
01278
01279
01280
01281
01282 static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state)
01283 {
01284 struct ast_channel *c;
01285 char device[15] = "dsp";
01286
01287 if (o->devicenum)
01288 snprintf(device + 3, sizeof(device) - 3, "%d", o->devicenum);
01289 c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "usbRadio/%s", device);
01290 if (c == NULL)
01291 return NULL;
01292 c->tech = &usbradio_tech;
01293 if (o->sounddev < 0)
01294 setformat(o, O_RDWR);
01295 c->fds[0] = o->sounddev;
01296 c->nativeformats = AST_FORMAT_SLINEAR;
01297 c->readformat = AST_FORMAT_SLINEAR;
01298 c->writeformat = AST_FORMAT_SLINEAR;
01299 c->tech_pvt = o;
01300
01301 if (!ast_strlen_zero(o->language))
01302 ast_string_field_set(c, language, o->language);
01303
01304
01305 c->cid.cid_num = ast_strdup(o->cid_num);
01306 c->cid.cid_ani = ast_strdup(o->cid_num);
01307 c->cid.cid_name = ast_strdup(o->cid_name);
01308 if (!ast_strlen_zero(ext))
01309 c->cid.cid_dnid = ast_strdup(ext);
01310
01311 o->owner = c;
01312 ast_module_ref(ast_module_info->self);
01313 ast_jb_configure(c, &global_jbconf);
01314 if (state != AST_STATE_DOWN) {
01315 if (ast_pbx_start(c)) {
01316 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
01317 ast_hangup(c);
01318 o->owner = c = NULL;
01319
01320
01321 }
01322 }
01323
01324 return c;
01325 }
01326
01327 static struct ast_channel *usbradio_request(const char *type, int format, void *data, int *cause)
01328 {
01329 struct ast_channel *c;
01330 struct chan_usbradio_pvt *o = find_desc(data);
01331
01332 ast_debug(4, "usbradio_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data);
01333 if (o == NULL) {
01334 ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
01335
01336 return NULL;
01337 }
01338 if ((format & AST_FORMAT_SLINEAR) == 0) {
01339 ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format);
01340 return NULL;
01341 }
01342 if (o->owner) {
01343 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the usb channel\n", o->owner);
01344 *cause = AST_CAUSE_BUSY;
01345 return NULL;
01346 }
01347 c = usbradio_new(o, NULL, NULL, AST_STATE_DOWN);
01348 if (c == NULL) {
01349 ast_log(LOG_WARNING, "Unable to create new usb channel\n");
01350 return NULL;
01351 }
01352 return c;
01353 }
01354
01355 static char *handle_cli_radio_key(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01356 {
01357 struct chan_usbradio_pvt *o = NULL;
01358
01359 switch (cmd) {
01360 case CLI_INIT:
01361 e->command = "radio key";
01362 e->usage =
01363 "Usage: radio key\n"
01364 " Simulates COR active.\n";
01365 return NULL;
01366 case CLI_GENERATE:
01367 return NULL;
01368 }
01369
01370 if (a->argc != 2)
01371 return CLI_SHOWUSAGE;
01372
01373 o = find_desc(usbradio_active);
01374 o->txtestkey = 1;
01375
01376 return CLI_SUCCESS;
01377 }
01378
01379 static char *handle_cli_radio_unkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01380 {
01381 struct chan_usbradio_pvt *o = NULL;
01382
01383 switch (cmd) {
01384 case CLI_INIT:
01385 e->command = "radio unkey";
01386 e->usage =
01387 "Usage: radio unkey\n"
01388 " Simulates COR un-active.\n";
01389 return NULL;
01390 case CLI_GENERATE:
01391 return NULL;
01392 }
01393
01394 if (a->argc != 2)
01395 return CLI_SHOWUSAGE;
01396
01397 o = find_desc(usbradio_active);
01398 o->txtestkey = 0;
01399
01400 return CLI_SUCCESS;
01401 }
01402
01403 static char *handle_cli_radio_tune(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01404 {
01405 struct chan_usbradio_pvt *o = NULL;
01406 int i = 0;
01407
01408 switch (cmd) {
01409 case CLI_INIT:
01410 e->command = "radio tune [rxnoise|rxvoice|rxtone|rxsquelch|rxcap|rxtracecap|"
01411 "txvoice|txtone|txcap|txtracecap|auxvoice|nocap|dump|save]";
01412
01413 e->usage =
01414 "Usage: radio tune <function>\n"
01415 " rxnoise\n"
01416 " rxvoice\n"
01417 " rxtone\n"
01418 " rxsquelch [newsetting]\n"
01419 " rxcap\n"
01420 " rxtracecap\n"
01421 " txvoice [newsetting]\n"
01422 " txtone [newsetting]\n"
01423 " txcap\n"
01424 " txtracecap\n"
01425 " auxvoice [newsetting]\n"
01426 " nocap\n"
01427 " dump\n"
01428 " save (settings to tuning file)\n"
01429 "\n"
01430 " All [newsetting]s are values 0-999\n";
01431 return NULL;
01432 case CLI_GENERATE:
01433 return NULL;
01434 }
01435
01436 if ((a->argc < 2) || (a->argc > 4))
01437 return CLI_SHOWUSAGE;
01438
01439 if (a->argc == 2) {
01440 ast_cli(a->fd, "Output A is currently set to %s.\n",
01441 o->txmixa == TX_OUT_COMPOSITE ? "composite" :
01442 o->txmixa == TX_OUT_VOICE ? "voice" :
01443 o->txmixa == TX_OUT_LSD ? "tone" :
01444 o->txmixa == TX_OUT_AUX ? "auxvoice" :
01445 "off");
01446
01447 ast_cli(a->fd, "Output B is currently set to %s.\n",
01448 o->txmixb == TX_OUT_COMPOSITE ? "composite" :
01449 o->txmixb == TX_OUT_VOICE ? "voice" :
01450 o->txmixb == TX_OUT_LSD ? "tone" :
01451 o->txmixb == TX_OUT_AUX ? "auxvoice" :
01452 "off");
01453
01454 ast_cli(a->fd, "Tx Voice Level currently set to %d\n", o->txmixaset);
01455 ast_cli(a->fd, "Tx Tone Level currently set to %d\n", o->txctcssadj);
01456 ast_cli(a->fd, "Rx Squelch currently set to %d\n", o->rxsquelchadj);
01457 return CLI_SHOWUSAGE;
01458 }
01459
01460 o = find_desc(usbradio_active);
01461
01462 if (!strcasecmp(a->argv[2], "rxnoise"))
01463 tune_rxinput(o);
01464 else if (!strcasecmp(a->argv[2], "rxvoice"))
01465 tune_rxvoice(o);
01466 else if (!strcasecmp(a->argv[2], "rxtone"))
01467 tune_rxctcss(o);
01468 else if (!strcasecmp(a->argv[2], "rxsquelch")) {
01469 if (a->argc == 3) {
01470 ast_cli(a->fd, "Current Signal Strength is %d\n", ((32767 - o->pmrChan->rxRssi) * 1000 / 32767));
01471 ast_cli(a->fd, "Current Squelch setting is %d\n", o->rxsquelchadj);
01472 #if 0
01473 ast_cli(a->fd,"Current Raw RSSI is %d\n",o->pmrChan->rxRssi);
01474 ast_cli(a->fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
01475 #endif
01476 } else {
01477 i = atoi(a->argv[3]);
01478 if ((i < 0) || (i > 999))
01479 return CLI_SHOWUSAGE;
01480 ast_cli(a->fd, "Changed Squelch setting to %d\n", i);
01481 o->rxsquelchadj = i;
01482 *(o->pmrChan->prxSquelchAdjust) = ((999 - i) * 32767) / 1000;
01483 }
01484 } else if (!strcasecmp(a->argv[2], "txvoice")) {
01485 i = 0;
01486
01487 if ((o->txmixa != TX_OUT_VOICE) && (o->txmixb != TX_OUT_VOICE) &&
01488 (o->txmixa != TX_OUT_COMPOSITE) && (o->txmixb != TX_OUT_COMPOSITE)) {
01489 ast_log(LOG_ERROR, "No txvoice output configured.\n");
01490 } else if (a->argc == 3) {
01491 if ((o->txmixa == TX_OUT_VOICE) || (o->txmixa == TX_OUT_COMPOSITE))
01492 ast_cli(a->fd, "Current txvoice setting on Channel A is %d\n", o->txmixaset);
01493 else
01494 ast_cli(a->fd, "Current txvoice setting on Channel B is %d\n", o->txmixbset);
01495 } else {
01496 i = atoi(a->argv[3]);
01497 if ((i < 0) || (i > 999))
01498 return CLI_SHOWUSAGE;
01499
01500 if ((o->txmixa == TX_OUT_VOICE) || (o->txmixa == TX_OUT_COMPOSITE)) {
01501 o->txmixaset = i;
01502 ast_cli(a->fd, "Changed txvoice setting on Channel A to %d\n", o->txmixaset);
01503 } else {
01504 o->txmixbset = i;
01505 ast_cli(a->fd, "Changed txvoice setting on Channel B to %d\n", o->txmixbset);
01506 }
01507 mixer_write(o);
01508 mult_set(o);
01509 ast_cli(a->fd, "Changed Tx Voice Output setting to %d\n", i);
01510 }
01511 tune_txoutput(o,i);
01512 } else if (!strcasecmp(a->argv[2], "auxvoice")) {
01513 i = 0;
01514 if ( (o->txmixa != TX_OUT_AUX) && (o->txmixb != TX_OUT_AUX))
01515 ast_log(LOG_WARNING, "No auxvoice output configured.\n");
01516 else if (a->argc == 3) {
01517 if (o->txmixa == TX_OUT_AUX)
01518 ast_cli(a->fd, "Current auxvoice setting on Channel A is %d\n", o->txmixaset);
01519 else
01520 ast_cli(a->fd, "Current auxvoice setting on Channel B is %d\n", o->txmixbset);
01521 } else {
01522 i = atoi(a->argv[3]);
01523 if ((i < 0) || (i > 999))
01524 return CLI_SHOWUSAGE;
01525 if (o->txmixa == TX_OUT_AUX) {
01526 o->txmixbset = i;
01527 ast_cli(a->fd, "Changed auxvoice setting on Channel A to %d\n", o->txmixaset);
01528 } else {
01529 o->txmixbset = i;
01530 ast_cli(a->fd, "Changed auxvoice setting on Channel B to %d\n", o->txmixbset);
01531 }
01532 mixer_write(o);
01533 mult_set(o);
01534 }
01535
01536 } else if (!strcasecmp(a->argv[2], "txtone")) {
01537 if (a->argc == 3)
01538 ast_cli(a->fd, "Current Tx CTCSS modulation setting = %d\n", o->txctcssadj);
01539 else {
01540 i = atoi(a->argv[3]);
01541 if ((i < 0) || (i > 999))
01542 return CLI_SHOWUSAGE;
01543 o->txctcssadj = i;
01544 set_txctcss_level(o);
01545 ast_cli(a->fd, "Changed Tx CTCSS modulation setting to %i\n", i);
01546 }
01547 o->txtestkey = 1;
01548 usleep(5000000);
01549 o->txtestkey = 0;
01550 } else if (!strcasecmp(a->argv[2],"dump"))
01551 pmrdump(o);
01552 else if (!strcasecmp(a->argv[2],"nocap")) {
01553 ast_cli(a->fd, "File capture (trace) was rx=%d tx=%d and now off.\n", o->b.rxcap2, o->b.txcap2);
01554 ast_cli(a->fd, "File capture (raw) was rx=%d tx=%d and now off.\n", o->b.rxcapraw, o->b.txcapraw);
01555 o->b.rxcapraw = o->b.txcapraw = o->b.rxcap2 = o->b.txcap2 = o->pmrChan->b.rxCapture = o->pmrChan->b.txCapture = 0;
01556 if (frxcapraw) {
01557 fclose(frxcapraw);
01558 frxcapraw = NULL;
01559 }
01560 if (frxcaptrace) {
01561 fclose(frxcaptrace);
01562 frxcaptrace = NULL;
01563 }
01564 if (frxoutraw) {
01565 fclose(frxoutraw);
01566 frxoutraw = NULL;
01567 }
01568 if (ftxcapraw) {
01569 fclose(ftxcapraw);
01570 ftxcapraw = NULL;
01571 }
01572 if (ftxcaptrace) {
01573 fclose(ftxcaptrace);
01574 ftxcaptrace = NULL;
01575 }
01576 if (ftxoutraw) {
01577 fclose(ftxoutraw);
01578 ftxoutraw = NULL;
01579 }
01580 } else if (!strcasecmp(a->argv[2], "rxtracecap")) {
01581 if (!frxcaptrace)
01582 frxcaptrace = fopen(RX_CAP_TRACE_FILE, "w");
01583 ast_cli(a->fd, "Trace rx on.\n");
01584 o->b.rxcap2 = o->pmrChan->b.rxCapture = 1;
01585 } else if (!strcasecmp(a->argv[2], "txtracecap")) {
01586 if (!ftxcaptrace)
01587 ftxcaptrace = fopen(TX_CAP_TRACE_FILE, "w");
01588 ast_cli(a->fd, "Trace tx on.\n");
01589 o->b.txcap2 = o->pmrChan->b.txCapture = 1;
01590 } else if (!strcasecmp(a->argv[2], "rxcap")) {
01591 if (!frxcapraw)
01592 frxcapraw = fopen(RX_CAP_RAW_FILE, "w");
01593 ast_cli(a->fd, "cap rx raw on.\n");
01594 o->b.rxcapraw = 1;
01595 } else if (!strcasecmp(a->argv[2], "txcap")) {
01596 if (!ftxcapraw)
01597 ftxcapraw = fopen(TX_CAP_RAW_FILE, "w");
01598 ast_cli(a->fd, "cap tx raw on.\n");
01599 o->b.txcapraw = 1;
01600 } else if (!strcasecmp(a->argv[2], "save")) {
01601 tune_write(o);
01602 ast_cli(a->fd, "Saved radio tuning settings to usbradio_tune.conf\n");
01603 } else
01604 return CLI_SHOWUSAGE;
01605 return CLI_SUCCESS;
01606 }
01607
01608
01609
01610
01611
01612
01613 static int set_txctcss_level(struct chan_usbradio_pvt *o)
01614 {
01615 if (o->txmixa == TX_OUT_LSD) {
01616 o->txmixaset = (151 * o->txctcssadj) / 1000;
01617 mixer_write(o);
01618 mult_set(o);
01619 } else if (o->txmixb == TX_OUT_LSD) {
01620 o->txmixbset = (151 * o->txctcssadj) / 1000;
01621 mixer_write(o);
01622 mult_set(o);
01623 } else {
01624 *o->pmrChan->ptxCtcssAdjust = (o->txctcssadj * M_Q8) / 1000;
01625 }
01626 return 0;
01627 }
01628
01629
01630
01631 static char *handle_cli_radio_set_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01632 {
01633 struct chan_usbradio_pvt *o = NULL;
01634
01635 switch (cmd) {
01636 case CLI_INIT:
01637 e->command = "radio set debug [off]";
01638 e->usage =
01639 "Usage: radio set debug [off]\n"
01640 " Enable/Disable radio debugging.\n";
01641 case CLI_GENERATE:
01642 return NULL;
01643 }
01644 if (a->argc < 3 || a->argc > 4)
01645 return CLI_SHOWUSAGE;
01646 if (a->argc == 4 && strncasecmp(a->argv[3], "off", 3))
01647 return CLI_SHOWUSAGE;
01648
01649 o = find_desc(usbradio_active);
01650
01651 if (a->argc == 3)
01652 o->debuglevel = 1;
01653 else
01654 o->debuglevel = 0;
01655
01656 ast_cli(a->fd, "USB Radio debugging %s.\n", o->debuglevel ? "enabled" : "disabled");
01657
01658 return CLI_SUCCESS;
01659 }
01660
01661 static char *handle_cli_radio_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01662 {
01663 struct chan_usbradio_pvt *o = NULL;
01664
01665 switch (cmd) {
01666 case CLI_INIT:
01667 e->command = "radio set debug {on|off}";
01668 e->usage =
01669 "Usage: radio set debug {on|off}\n"
01670 " Enable/Disable radio debugging.\n";
01671 case CLI_GENERATE:
01672 return NULL;
01673 }
01674
01675 if (a->argc != e->args)
01676 return CLI_SHOWUSAGE;
01677
01678 o = find_desc(usbradio_active);
01679
01680 if (!strncasecmp(a->argv[e->args - 1], "on", 2))
01681 o->debuglevel = 1;
01682 else if (!strncasecmp(a->argv[e->args - 1], "off", 3))
01683 o->debuglevel = 0;
01684 else
01685 return CLI_SHOWUSAGE;
01686
01687 ast_cli(a->fd, "USB Radio debugging %s.\n", o->debuglevel ? "enabled" : "disabled");
01688
01689 return CLI_SUCCESS;
01690 }
01691
01692 static struct ast_cli_entry cli_radio_set_debug_deprecated = AST_CLI_DEFINE(handle_cli_radio_set_debug_deprecated, "Enable/Disable Radio Debugging");
01693 static struct ast_cli_entry cli_usbradio[] = {
01694 AST_CLI_DEFINE(handle_cli_radio_key, "Simulate Rx Signal Present"),
01695 AST_CLI_DEFINE(handle_cli_radio_unkey, "Simulate Rx Signal Lusb"),
01696 AST_CLI_DEFINE(handle_cli_radio_tune, "Radio Tune"),
01697 AST_CLI_DEFINE(handle_cli_radio_set_debug, "Enable/Disable Radio Debugging", .deprecate_cmd = &cli_radio_set_debug_deprecated),
01698 };
01699
01700
01701
01702
01703 #if 0
01704 static void store_callerid(struct chan_usbradio_pvt *o, const char *s)
01705 {
01706 ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
01707 }
01708 #endif
01709
01710 static void store_rxdemod(struct chan_usbradio_pvt *o, const char *s)
01711 {
01712 if (!strcasecmp(s, "no")) {
01713 o->rxdemod = RX_AUDIO_NONE;
01714 } else if (!strcasecmp(s, "speaker")) {
01715 o->rxdemod = RX_AUDIO_SPEAKER;
01716 } else if (!strcasecmp(s, "flat")) {
01717 o->rxdemod = RX_AUDIO_FLAT;
01718 } else {
01719 ast_log(LOG_WARNING, "Unrecognized rxdemod parameter: %s\n", s);
01720 }
01721
01722 ast_debug(4, "set rxdemod = %s\n", s);
01723 }
01724
01725
01726 static void store_txmixa(struct chan_usbradio_pvt *o, const char *s)
01727 {
01728 if (!strcasecmp(s, "no"))
01729 o->txmixa = TX_OUT_OFF;
01730
01731 else if (!strcasecmp(s, "voice"))
01732 o->txmixa = TX_OUT_VOICE;
01733 else if (!strcasecmp(s, "tone"))
01734 o->txmixa = TX_OUT_LSD;
01735 else if (!strcasecmp(s, "composite"))
01736 o->txmixa = TX_OUT_COMPOSITE;
01737 else if (!strcasecmp(s, "auxvoice"))
01738 o->txmixb = TX_OUT_AUX;
01739 else
01740 ast_log(LOG_WARNING, "Unrecognized txmixa parameter: %s\n", s);
01741
01742 ast_debug(4, "set txmixa = %s\n", s);
01743 }
01744
01745 static void store_txmixb(struct chan_usbradio_pvt *o, const char *s)
01746 {
01747 if (!strcasecmp(s, "no"))
01748 o->txmixb = TX_OUT_OFF;
01749 else if (!strcasecmp(s, "voice"))
01750 o->txmixb = TX_OUT_VOICE;
01751 else if (!strcasecmp(s, "tone"))
01752 o->txmixb = TX_OUT_LSD;
01753 else if (!strcasecmp(s, "composite"))
01754 o->txmixb = TX_OUT_COMPOSITE;
01755 else if (!strcasecmp(s, "auxvoice"))
01756 o->txmixb = TX_OUT_AUX;
01757 else
01758 ast_log(LOG_WARNING, "Unrecognized txmixb parameter: %s\n", s);
01759
01760 ast_debug(4, "set txmixb = %s\n", s);
01761 }
01762
01763 static void store_rxcdtype(struct chan_usbradio_pvt *o, const char *s)
01764 {
01765 if (!strcasecmp(s, "no"))
01766 o->rxcdtype = CD_IGNORE;
01767 else if (!strcasecmp(s, "usb"))
01768 o->rxcdtype = CD_HID;
01769 else if (!strcasecmp(s, "dsp"))
01770 o->rxcdtype = CD_XPMR_NOISE;
01771 else if (!strcasecmp(s, "vox"))
01772 o->rxcdtype = CD_XPMR_VOX;
01773 else if (!strcasecmp(s, "usbinvert"))
01774 o->rxcdtype = CD_HID_INVERT;
01775 else
01776 ast_log(LOG_WARNING, "Unrecognized rxcdtype parameter: %s\n", s);
01777
01778 ast_debug(4, "set rxcdtype = %s\n", s);
01779 }
01780
01781 static void store_rxsdtype(struct chan_usbradio_pvt *o, const char *s)
01782 {
01783 if (!strcasecmp(s, "no") || !strcasecmp(s, "SD_IGNORE"))
01784 o->rxsdtype = SD_IGNORE;
01785 else if (!strcasecmp(s, "usb") || !strcasecmp(s, "SD_HID"))
01786 o->rxsdtype = SD_HID;
01787 else if (!strcasecmp(s, "usbinvert") || !strcasecmp(s, "SD_HID_INVERT"))
01788 o->rxsdtype = SD_HID_INVERT;
01789 else if (!strcasecmp(s, "software") || !strcasecmp(s, "SD_XPMR"))
01790 o->rxsdtype = SD_XPMR;
01791 else
01792 ast_log(LOG_WARNING, "Unrecognized rxsdtype parameter: %s\n", s);
01793
01794 ast_debug(4, "set rxsdtype = %s\n", s);
01795 }
01796
01797 static void store_rxgain(struct chan_usbradio_pvt *o, const char *s)
01798 {
01799 float f;
01800 if (sscanf(s, "%f", &f) == 1)
01801 o->rxgain = f;
01802 ast_debug(4, "set rxgain = %f\n", f);
01803 }
01804
01805 static void store_rxvoiceadj(struct chan_usbradio_pvt *o, const char *s)
01806 {
01807 float f;
01808 if (sscanf(s, "%f", &f) == 1)
01809 o->rxvoiceadj = f;
01810 ast_debug(4, "set rxvoiceadj = %f\n", f);
01811 }
01812
01813 static void store_rxctcssadj(struct chan_usbradio_pvt *o, const char *s)
01814 {
01815 float f;
01816 if (sscanf(s, "%f", &f) == 1)
01817 o->rxctcssadj = f;
01818 ast_debug(4, "set rxctcssadj = %f\n", f);
01819 }
01820
01821 static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s)
01822 {
01823 if (!strcasecmp(s, "no") || !strcasecmp(s, "TOC_NONE"))
01824 o->txtoctype = TOC_NONE;
01825 else if (!strcasecmp(s, "phase") || !strcasecmp(s, "TOC_PHASE"))
01826 o->txtoctype = TOC_PHASE;
01827 else if (!strcasecmp(s, "notone") || !strcasecmp(s, "TOC_NOTONE"))
01828 o->txtoctype = TOC_NOTONE;
01829 else
01830 ast_log(LOG_WARNING, "Unrecognized txtoctype parameter: %s\n", s);
01831
01832 ast_debug(4, "set txtoctype = %s\n", s);
01833 }
01834
01835 static void store_rxctcssfreq(struct chan_usbradio_pvt *o, const char *s)
01836 {
01837 float f;
01838 if (sscanf(s, "%f", &f) == 1)
01839 o->rxctcssfreq = f;
01840 ast_debug(4, "set rxctcss = %f\n", f);
01841 }
01842
01843 static void store_txctcssfreq(struct chan_usbradio_pvt *o, const char *s)
01844 {
01845 float f;
01846 if (sscanf(s, "%f", &f) == 1)
01847 o->txctcssfreq = f;
01848 ast_debug(4, "set txctcss = %f\n", f);
01849 }
01850
01851 static void tune_txoutput(struct chan_usbradio_pvt *o, int value)
01852 {
01853 o->txtestkey = 1;
01854 o->pmrChan->txPttIn = 1;
01855
01856 #if 0
01857
01858 o->pmrChan->spsSigGen1->freq = 10000;
01859 o->pmrChan->spsSigGen1->outputGain = (float)(0.22 * M_Q8);
01860 o->pmrChan->b.startSpecialTone = 1;
01861 #endif
01862
01863 TxTestTone(o->pmrChan, 1);
01864
01865 usleep(5000000);
01866
01867 usleep(100000);
01868
01869 TxTestTone(o->pmrChan, 0);
01870
01871 o->pmrChan->txPttIn = 0;
01872 o->txtestkey = 0;
01873 }
01874
01875 static void tune_rxinput(struct chan_usbradio_pvt *o)
01876 {
01877 const int target = 23000;
01878 const int tolerance = 2000;
01879 const int settingmin = 1;
01880 const int settingstart = 2;
01881 const int maxtries = 12;
01882
01883 float settingmax;
01884
01885 int setting = 0, tries = 0, tmpdiscfactor, meas;
01886 int tunetype = 0;
01887
01888 settingmax = o->micmax;
01889
01890 if (o->pmrChan->rxDemod)
01891 tunetype = 1;
01892
01893 setting = settingstart;
01894
01895 while (tries < maxtries) {
01896 setamixer(o->devicenum, MIXER_PARAM_MIC_CAPTURE_VOL, setting, 0);
01897 setamixer(o->devicenum, MIXER_PARAM_MIC_BOOST, o->rxboostset, 0);
01898 usleep(100000);
01899 if (o->rxcdtype == CD_XPMR_VOX || o->rxdemod == RX_AUDIO_SPEAKER) {
01900 ast_debug(4, "Measure Direct Input\n");
01901 o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source;
01902 o->pmrChan->spsMeasure->discfactor = 1000;
01903 o->pmrChan->spsMeasure->enabled = 1;
01904 o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
01905 usleep(400000);
01906 meas = o->pmrChan->spsMeasure->apeak;
01907 o->pmrChan->spsMeasure->enabled = 0;
01908 } else {
01909 ast_debug(4, "Measure HF Noise\n");
01910 tmpdiscfactor = o->pmrChan->spsRx->discfactor;
01911 o->pmrChan->spsRx->discfactor = (i16)1000;
01912 o->pmrChan->spsRx->discounteru = o->pmrChan->spsRx->discounterl = 0;
01913 o->pmrChan->spsRx->amax = o->pmrChan->spsRx->amin = 0;
01914 usleep(200000);
01915 meas = o->pmrChan->rxRssi;
01916 o->pmrChan->spsRx->discfactor = tmpdiscfactor;
01917 o->pmrChan->spsRx->discounteru = o->pmrChan->spsRx->discounterl = 0;
01918 o->pmrChan->spsRx->amax = o->pmrChan->spsRx->amin = 0;
01919 }
01920 if (!meas)
01921 meas++;
01922 ast_log(LOG_NOTICE, "tries=%d, setting=%d, meas=%i\n", tries, setting, meas);
01923
01924 if ( meas < (target - tolerance) || meas > (target + tolerance) || tries < 3)
01925 setting = setting * target / meas;
01926 else if (tries > 4 && meas > (target - tolerance) && meas < (target + tolerance) )
01927 break;
01928
01929 if (setting < settingmin)
01930 setting = settingmin;
01931 else if (setting > settingmax)
01932 setting = settingmax;
01933
01934 tries++;
01935 }
01936 ast_log(LOG_NOTICE, "DONE tries=%d, setting=%d, meas=%i\n", tries,
01937 (setting * 1000) / o->micmax, meas);
01938 if (meas < (target - tolerance) || meas > (target + tolerance))
01939 ast_log(LOG_NOTICE, "ERROR: RX INPUT ADJUST FAILED.\n");
01940 else {
01941 ast_log(LOG_NOTICE, "INFO: RX INPUT ADJUST SUCCESS.\n");
01942 o->rxmixerset = (setting * 1000) / o->micmax;
01943 }
01944 }
01945
01946
01947 static void tune_rxvoice(struct chan_usbradio_pvt *o)
01948 {
01949 const int target = 7200;
01950 const int tolerance = 360;
01951 const float settingmin = 0.1;
01952 const float settingmax = 4;
01953 const float settingstart = 1;
01954 const int maxtries = 12;
01955
01956 float setting;
01957
01958 int tries = 0, meas;
01959
01960 ast_log(LOG_NOTICE, "INFO: RX VOICE ADJUST START.\n");
01961 ast_log(LOG_NOTICE, "target=%d tolerance=%d\n", target, tolerance);
01962
01963 if (!o->pmrChan->spsMeasure)
01964 ast_log(LOG_ERROR, "NO MEASURE BLOCK.\n");
01965
01966 if (!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
01967 ast_log(LOG_ERROR, "NO SOURCE OR MEASURE SETTING.\n");
01968
01969 o->pmrChan->spsMeasure->source = o->pmrChan->spsRxOut->sink;
01970 o->pmrChan->spsMeasure->enabled = 1;
01971 o->pmrChan->spsMeasure->discfactor = 1000;
01972
01973 setting=settingstart;
01974
01975 ast_debug(4, "ERROR: NO MEASURE BLOCK.\n");
01976
01977 while (tries < maxtries) {
01978 *(o->pmrChan->prxVoiceAdjust) = setting * M_Q8;
01979 usleep(10000);
01980 o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
01981 usleep(1000000);
01982 meas = o->pmrChan->spsMeasure->apeak;
01983 ast_log(LOG_NOTICE, "tries=%d, setting=%f, meas=%i\n", tries, setting, meas);
01984
01985 if (meas < (target - tolerance) || meas > (target + tolerance) || tries < 3)
01986 setting = setting * target / meas;
01987 else if (tries > 4 && meas > (target - tolerance) && meas < (target + tolerance))
01988 break;
01989 if (setting < settingmin)
01990 setting = settingmin;
01991 else if (setting > settingmax)
01992 setting = settingmax;
01993
01994 tries++;
01995 }
01996
01997 o->pmrChan->spsMeasure->enabled = 0;
01998
01999 ast_log(LOG_NOTICE, "DONE tries=%d, setting=%f, meas=%f\n", tries, setting, (float)meas);
02000 if (meas < (target - tolerance) || meas > (target + tolerance))
02001 ast_log(LOG_ERROR, "RX VOICE GAIN ADJUST FAILED.\n");
02002 else {
02003 ast_log(LOG_NOTICE, "RX VOICE GAIN ADJUST SUCCESS.\n");
02004 o->rxvoiceadj = setting;
02005 }
02006 }
02007
02008 static void tune_rxctcss(struct chan_usbradio_pvt *o)
02009 {
02010 const int target = 4096;
02011 const int tolerance = 100;
02012 const float settingmin = 0.1;
02013 const float settingmax = 4;
02014 const float settingstart = 1;
02015 const int maxtries = 12;
02016
02017 float setting;
02018 int tries = 0, meas;
02019
02020 ast_log(LOG_NOTICE, "RX CTCSS ADJUST START.\n");
02021 ast_log(LOG_NOTICE, "target=%d tolerance=%d \n", target, tolerance);
02022
02023 o->pmrChan->spsMeasure->source = o->pmrChan->prxCtcssMeasure;
02024 o->pmrChan->spsMeasure->discfactor = 400;
02025 o->pmrChan->spsMeasure->enabled = 1;
02026
02027 setting = settingstart;
02028
02029 while (tries < maxtries) {
02030 *(o->pmrChan->prxCtcssAdjust) = setting * M_Q8;
02031 usleep(10000);
02032 o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
02033 usleep(500000);
02034 meas = o->pmrChan->spsMeasure->apeak;
02035 ast_debug(4, "tries=%d, setting=%f, meas=%i\n", tries, setting, meas);
02036
02037 if (meas < (target - tolerance) || meas > (target + tolerance) || tries < 3)
02038 setting = setting * target / meas;
02039 else if (tries > 4 && meas > (target - tolerance) && meas < (target + tolerance))
02040 break;
02041 if (setting < settingmin)
02042 setting = settingmin;
02043 else if (setting > settingmax)
02044 setting = settingmax;
02045
02046 tries++;
02047 }
02048 o->pmrChan->spsMeasure->enabled = 0;
02049 ast_debug(4, "DONE tries=%d, setting=%f, meas=%f\n", tries, setting, (float)meas);
02050 if (meas < (target - tolerance) || meas > (target + tolerance))
02051 ast_log(LOG_ERROR, "RX CTCSS GAIN ADJUST FAILED.\n");
02052 else {
02053 ast_log(LOG_NOTICE, "RX CTCSS GAIN ADJUST SUCCESS.\n");
02054 o->rxctcssadj = setting;
02055 }
02056 }
02057
02058
02059
02060
02061 static void tune_write(struct chan_usbradio_pvt *o)
02062 {
02063 FILE *fp;
02064
02065 fp = fopen("/etc/asterisk/usbradio_tune.conf", "w");
02066
02067 if (!strcmp(o->name, "dsp"))
02068 fprintf(fp, "[general]\n");
02069 else
02070 fprintf(fp, "[%s]\n", o->name);
02071
02072 fprintf(fp, "; name=%s\n", o->name);
02073 fprintf(fp, "; devicenum=%d\n", o->devicenum);
02074
02075 fprintf(fp, "rxmixerset=%d\n", o->rxmixerset);
02076 fprintf(fp, "rxboostset=%d\n", o->rxboostset);
02077 fprintf(fp, "txmixaset=%d\n", o->txmixaset);
02078 fprintf(fp, "txmixbset=%d\n", o->txmixbset);
02079
02080 fprintf(fp, "rxvoiceadj=%f\n", o->rxvoiceadj);
02081 fprintf(fp, "rxctcssadj=%f\n", o->rxctcssadj);
02082 fprintf(fp, "txctcssadj=%d\n", o->txctcssadj);
02083
02084 fprintf(fp, "rxsquelchadj=%d\n", o->rxsquelchadj);
02085 fclose(fp);
02086 }
02087
02088 static void mixer_write(struct chan_usbradio_pvt *o)
02089 {
02090 setamixer(o->devicenum, MIXER_PARAM_MIC_PLAYBACK_SW, 0, 0);
02091 setamixer(o->devicenum, MIXER_PARAM_MIC_PLAYBACK_VOL, 0, 0);
02092 setamixer(o->devicenum, MIXER_PARAM_SPKR_PLAYBACK_SW, 1, 0);
02093 setamixer(o->devicenum, MIXER_PARAM_SPKR_PLAYBACK_VOL,
02094 o->txmixaset * o->spkrmax / 1000,
02095 o->txmixbset * o->spkrmax / 1000);
02096 setamixer(o->devicenum, MIXER_PARAM_MIC_CAPTURE_VOL,
02097 o->rxmixerset * o->micmax / 1000, 0);
02098 setamixer(o->devicenum, MIXER_PARAM_MIC_BOOST, o->rxboostset, 0);
02099 setamixer(o->devicenum, MIXER_PARAM_MIC_CAPTURE_SW, 1, 0);
02100 }
02101
02102
02103
02104 static void mult_set(struct chan_usbradio_pvt *o)
02105 {
02106
02107 if (o->pmrChan->spsTxOutA) {
02108 o->pmrChan->spsTxOutA->outputGain =
02109 mult_calc((o->txmixaset * 152) / 1000);
02110 }
02111 if (o->pmrChan->spsTxOutB) {
02112 o->pmrChan->spsTxOutB->outputGain =
02113 mult_calc((o->txmixbset * 152) / 1000);
02114 }
02115 }
02116
02117
02118
02119 static int mult_calc(int value)
02120 {
02121 const int multx = M_Q8;
02122 int pot, mult;
02123
02124 pot= ((int)(value / 4) * 4) + 2;
02125 mult = multx - ((multx * (3 - (value % 4))) / (pot + 2));
02126 return mult;
02127 }
02128
02129 #define pd(x) ast_debug(4, #x" = %d\n", x)
02130 #define pp(x) ast_debug(4, #x" = %p\n", x)
02131 #define ps(x) ast_debug(4, #x" = %s\n", x)
02132 #define pf(x) ast_debug(4, #x" = %f\n", x)
02133
02134
02135 static void pmrdump(struct chan_usbradio_pvt *o)
02136 {
02137 t_pmr_chan *p;
02138
02139 p = o->pmrChan;
02140
02141 ast_debug(4, "odump()\n");
02142
02143 pd(o->devicenum);
02144
02145 pd(o->rxdemod);
02146 pd(o->rxcdtype);
02147 pd(o->rxsdtype);
02148 pd(o->txtoctype);
02149
02150 pd(o->rxmixerset);
02151 pf(o->rxvoiceadj);
02152 pf(o->rxctcssadj);
02153 pd(o->rxsquelchadj);
02154
02155 pd(o->txprelim);
02156 pd(o->txmixa);
02157 pd(o->txmixb);
02158
02159 pd(o->txmixaset);
02160 pd(o->txmixbset);
02161
02162 ast_debug(4, "pmrdump()\n");
02163
02164 ast_debug(4, "prxSquelchAdjust=%d\n", *(o->pmrChan->prxSquelchAdjust));
02165
02166 pd(p->rxCarrierPoint);
02167 pd(p->rxCarrierHyst);
02168
02169 pd(p->rxCtcss->relax);
02170 pf(p->rxCtcssFreq);
02171 pd(p->rxCtcssIndex);
02172 pf(p->txCtcssFreq);
02173
02174 pd(p->txMixA);
02175 pd(p->txMixB);
02176
02177 pd(p->rxDeEmpEnable);
02178 pd(p->rxCenterSlicerEnable);
02179 pd(p->rxCtcssDecodeEnable);
02180 pd(p->rxDcsDecodeEnable);
02181
02182 pd(p->txHpfEnable);
02183 pd(p->txLimiterEnable);
02184 pd(p->txPreEmpEnable);
02185 pd(p->txLpfEnable);
02186
02187 if (p->spsTxOutA)
02188 pd(p->spsTxOutA->outputGain);
02189 if (p->spsTxOutB)
02190 pd(p->spsTxOutB->outputGain);
02191
02192 return;
02193 }
02194
02195
02196
02197
02198
02199 static struct chan_usbradio_pvt *store_config(struct ast_config *cfg, char *ctg)
02200 {
02201 struct ast_variable *v;
02202 struct chan_usbradio_pvt *o;
02203 struct ast_config *cfg1;
02204 struct ast_flags config_flags = { 0 };
02205
02206 if (ctg == NULL) {
02207 traceusb1(" store_config() ctg == NULL\n");
02208 o = &usbradio_default;
02209 ctg = "general";
02210 } else {
02211 if (!(o = ast_calloc(1, sizeof(*o)))){
02212 return NULL;
02213 }
02214 *o = usbradio_default;
02215
02216 if (strcmp(ctg, "general") == 0) {
02217 o->name = ast_strdup("dsp");
02218 usbradio_active = o->name;
02219 } else
02220 o->name = ast_strdup(ctg);
02221 }
02222
02223 strcpy(o->mohinterpret, "default");
02224 o->micmax = amixer_max(o->devicenum, MIXER_PARAM_MIC_CAPTURE_VOL);
02225 o->spkrmax = amixer_max(o->devicenum, MIXER_PARAM_SPKR_PLAYBACK_VOL);
02226
02227 for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
02228
02229
02230 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02231 continue;
02232 CV_START(v->name, v->value);
02233
02234 CV_UINT("frags", o->frags);
02235 CV_UINT("queuesize", o->queuesize);
02236 CV_UINT("devicenum", o->devicenum);
02237 CV_UINT("debug", usbradio_debug);
02238 CV_BOOL("rxcpusaver", o->rxcpusaver);
02239 CV_BOOL("txcpusaver", o->txcpusaver);
02240 CV_BOOL("invertptt", o->invertptt);
02241 CV_F("rxdemod", store_rxdemod(o, v->value));
02242 CV_BOOL("txprelim", o->txprelim);;
02243 CV_F("txmixa", store_txmixa(o, v->value));
02244 CV_F("txmixb", store_txmixb(o, v->value));
02245 CV_F("carrierfrom", store_rxcdtype(o, v->value));
02246 CV_F("rxsdtype", store_rxsdtype(o, v->value));
02247 CV_F("rxctcssfreq", store_rxctcssfreq(o, v->value));
02248 CV_F("txctcssfreq", store_txctcssfreq(o, v->value));
02249 CV_F("rxgain", store_rxgain(o, v->value));
02250 CV_BOOL("rxboostset", o->rxboostset);
02251 CV_UINT("rxctcssrelax", o->rxctcssrelax);
02252 CV_F("txtoctype", store_txtoctype(o, v->value));
02253 CV_UINT("hdwtype", o->hdwtype);
02254 CV_UINT("duplex", o->radioduplex);
02255
02256 CV_END;
02257 }
02258
02259 cfg1 = ast_config_load(config1, config_flags);
02260 if (!cfg1) {
02261 o->rxmixerset = 500;
02262 o->txmixaset = 500;
02263 o->txmixbset = 500;
02264 o->rxvoiceadj = 0.5;
02265 o->rxctcssadj = 0.5;
02266 o->txctcssadj = 200;
02267 o->rxsquelchadj = 500;
02268 ast_log(LOG_WARNING, "File %s not found, using default parameters.\n", config1);
02269 } else {
02270 for (v = ast_variable_browse(cfg1, ctg); v; v = v->next) {
02271
02272 CV_START(v->name, v->value);
02273 CV_UINT("rxmixerset", o->rxmixerset);
02274 CV_UINT("txmixaset", o->txmixaset);
02275 CV_UINT("txmixbset", o->txmixbset);
02276 CV_F("rxvoiceadj", store_rxvoiceadj(o, v->value));
02277 CV_F("rxctcssadj", store_rxctcssadj(o, v->value));
02278 CV_UINT("txctcssadj", o->txctcssadj);
02279 CV_UINT("rxsquelchadj", o->rxsquelchadj);
02280 CV_END;
02281 }
02282 ast_config_destroy(cfg1);
02283 }
02284
02285 o->debuglevel = 0;
02286
02287 if (o == &usbradio_default)
02288 return NULL;
02289
02290 o->lastopen = ast_tvnow();
02291 o->dsp = ast_dsp_new();
02292 if (o->dsp) {
02293 ast_dsp_set_features(o->dsp, DSP_FEATURE_DTMF_DETECT);
02294 ast_dsp_digitmode(o->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
02295 }
02296
02297 if (o->rxctcssfreq != 0 && o->rxdemod == RX_AUDIO_SPEAKER)
02298 ast_log(LOG_ERROR, "Incompatable Options o->rxctcssfreq=%f and o->rxdemod=speaker\n", o->rxctcssfreq);
02299
02300 if (o->pmrChan == NULL) {
02301 t_pmr_chan tChan;
02302
02303 memset(&tChan, 0, sizeof(tChan));
02304
02305 tChan.rxDemod = o->rxdemod;
02306 tChan.rxCdType = o->rxcdtype;
02307
02308 tChan.txMod = o->txprelim;
02309
02310 tChan.txMixA = o->txmixa;
02311 tChan.txMixB = o->txmixb;
02312
02313 tChan.rxCpuSaver = o->rxcpusaver;
02314 tChan.txCpuSaver = o->txcpusaver;
02315
02316 tChan.rxCtcssFreq = o->rxctcssfreq;
02317 tChan.txCtcssFreq = o->txctcssfreq;
02318
02319 o->pmrChan = createPmrChannel(&tChan, FRAME_SIZE);
02320
02321 o->pmrChan->radioDuplex = o->radioduplex;
02322
02323 o->pmrChan->rxCpuSaver = o->rxcpusaver;
02324 o->pmrChan->txCpuSaver = o->txcpusaver;
02325
02326 *(o->pmrChan->prxSquelchAdjust) =
02327 ((999 - o->rxsquelchadj) * 32767) / 1000;
02328
02329 o->pmrChan->spsRx->outputGain = o->rxvoiceadj*M_Q8;
02330
02331 o->pmrChan->txTocType = o->txtoctype;
02332
02333 if ((o->txmixa == TX_OUT_LSD) ||
02334 (o->txmixa == TX_OUT_COMPOSITE) ||
02335 (o->txmixb == TX_OUT_LSD) ||
02336 (o->txmixb == TX_OUT_COMPOSITE)) {
02337 *(o->pmrChan->prxCtcssAdjust) = o->rxctcssadj * M_Q8;
02338 set_txctcss_level(o);
02339 }
02340
02341 o->pmrChan->rxCtcss->relax = o->rxctcssrelax;
02342
02343 }
02344
02345 if ((o->txmixa != TX_OUT_VOICE) && (o->txmixb != TX_OUT_VOICE) &&
02346 (o->txmixa != TX_OUT_COMPOSITE) && (o->txmixb != TX_OUT_COMPOSITE))
02347 ast_log(LOG_ERROR, "No txvoice output configured.\n");
02348
02349 if (o->txctcssfreq &&
02350 o->txmixa != TX_OUT_LSD && o->txmixa != TX_OUT_COMPOSITE &&
02351 o->txmixb != TX_OUT_LSD && o->txmixb != TX_OUT_COMPOSITE)
02352 ast_log(LOG_ERROR, "No txtone output configured.\n");
02353
02354 if (o->rxctcssfreq && o->pmrChan->rxCtcssIndex < 0)
02355 ast_log(LOG_ERROR, "Invalid CTCSS Frequency.\n");
02356
02357
02358
02359 mixer_write(o);
02360 mult_set(o);
02361 hidhdwconfig(o);
02362
02363
02364
02365
02366 if (o != &usbradio_default) {
02367 o->next = usbradio_default.next;
02368 usbradio_default.next = o;
02369 }
02370 return o;
02371 }
02372
02373 #if DEBUG_FILETEST == 1
02374
02375
02376
02377 int RxTestIt(struct chan_usbradio_pvt *o)
02378 {
02379 const int numSamples = SAMPLES_PER_BLOCK;
02380 const int numChannels = 16;
02381
02382 i16 sample, i, ii;
02383
02384 i32 txHangTime;
02385
02386 i16 txEnable;
02387
02388 t_pmr_chan tChan;
02389 t_pmr_chan *pChan;
02390
02391 FILE *hInput = NULL, *hOutput = NULL, *hOutputTx = NULL;
02392
02393 i16 iBuff[numSamples * 2 * 6], oBuff[numSamples];
02394
02395 ast_debug(4, "RxTestIt()\n");
02396
02397 pChan = o->pmrChan;
02398 pChan->b.txCapture = 1;
02399 pChan->b.rxCapture = 1;
02400
02401 txEnable = 0;
02402
02403 hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm", "r");
02404 if (!hInput){
02405 ast_debug(4, " RxTestIt() File Not Found.\n");
02406 return 0;
02407 }
02408 hOutput = fopen("/usr/src/xpmr/testdata/rx_debug.pcm", "w");
02409
02410 ast_debug(4, " RxTestIt() Working...\n");
02411
02412 while (!feof(hInput)) {
02413 fread((void *)iBuff, 2, numSamples * 2 * 6, hInput);
02414
02415 if (txHangTime)
02416 txHangTime -= numSamples;
02417 if (txHangTime < 0)
02418 txHangTime = 0;
02419
02420 if (pChan->rxCtcss->decode)
02421 txHangTime = (8000 / 1000 * 2000);
02422
02423 if (pChan->rxCtcss->decode && !txEnable) {
02424 txEnable = 1;
02425
02426 } else if (!pChan->rxCtcss->decode && txEnable) {
02427 txEnable = 0;
02428 }
02429
02430 PmrRx(pChan, iBuff, oBuff);
02431
02432 if (fwrite((void *)pChan->prxDebug, 2, numSamples * numChannels, hOutput) != numSamples * numChannels) {
02433 ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
02434 }
02435 }
02436 pChan->b.txCapture = 0;
02437 pChan->b.rxCapture = 0;
02438
02439 if (hInput)
02440 fclose(hInput);
02441 if (hOutput)
02442 fclose(hOutput);
02443
02444 ast_debug(4, " RxTestIt() Complete.\n");
02445
02446 return 0;
02447 }
02448 #endif
02449
02450 #include "./xpmr/xpmr.c"
02451
02452
02453 static int load_module(void)
02454 {
02455 struct ast_config *cfg = NULL;
02456 char *ctg = NULL;
02457 struct ast_flags config_flags = { 0 };
02458
02459
02460 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02461
02462
02463 if (!(cfg = ast_config_load(config, config_flags))) {
02464 ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
02465 return AST_MODULE_LOAD_DECLINE;
02466 }
02467
02468 do {
02469 store_config(cfg, ctg);
02470 } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL);
02471
02472 ast_config_destroy(cfg);
02473
02474 if (find_desc(usbradio_active) == NULL) {
02475 ast_log(LOG_NOTICE, "Device %s not found\n", usbradio_active);
02476
02477
02478 return AST_MODULE_LOAD_FAILURE;
02479 }
02480
02481 if (ast_channel_register(&usbradio_tech)) {
02482 ast_log(LOG_ERROR, "Unable to register channel type 'usb'\n");
02483 return AST_MODULE_LOAD_FAILURE;
02484 }
02485
02486 ast_cli_register_multiple(cli_usbradio, sizeof(cli_usbradio) / sizeof(struct ast_cli_entry));
02487
02488 return AST_MODULE_LOAD_SUCCESS;
02489 }
02490
02491
02492 static int unload_module(void)
02493 {
02494 struct chan_usbradio_pvt *o;
02495
02496 ast_log(LOG_WARNING, "unload_module() called\n");
02497
02498 ast_channel_unregister(&usbradio_tech);
02499 ast_cli_unregister_multiple(cli_usbradio, sizeof(cli_usbradio) / sizeof(struct ast_cli_entry));
02500
02501 for (o = usbradio_default.next; o; o = o->next) {
02502
02503 ast_log(LOG_WARNING, "destroyPmrChannel() called\n");
02504 if (o->pmrChan)
02505 destroyPmrChannel(o->pmrChan);
02506
02507 #if DEBUG_CAPTURES == 1
02508 if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
02509 if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
02510 if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
02511 if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
02512 if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
02513 if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
02514 #endif
02515
02516 close(o->sounddev);
02517 if (o->dsp)
02518 ast_dsp_free(o->dsp);
02519 if (o->owner)
02520 ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
02521 if (o->owner)
02522 return -1;
02523
02524
02525 }
02526 return 0;
02527 }
02528
02529 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "usb Console Channel Driver");
02530
02531
02532
02533