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
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #define RECONNECT_KLUDGE
00102
00103
00104
00105 #define MAXDTMF 32
00106 #define DTMF_TIMEOUT 3
00107
00108 #define DISC_TIME 10000
00109 #define MAX_RETRIES 5
00110
00111 #define REDUNDANT_TX_TIME 2000
00112
00113 #define RETRY_TIMER_MS 5000
00114
00115 #define MAXREMSTR 15
00116
00117 #define NODES "nodes"
00118 #define MEMORY "memory"
00119 #define FUNCTIONS "functions"
00120 #define TELEMETRY "telemetry"
00121 #define MORSE "morse"
00122 #define FUNCCHAR '*'
00123 #define ENDCHAR '#'
00124
00125 #define DEFAULT_IOBASE 0x378
00126
00127 #define MAXCONNECTTIME 5000
00128
00129 #define MAXNODESTR 300
00130
00131 #define ACTIONSIZE 32
00132
00133 #define TELEPARAMSIZE 256
00134
00135 #define REM_SCANTIME 100
00136
00137
00138 enum {REM_OFF,REM_MONITOR,REM_TX};
00139
00140 enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
00141 CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME,
00142 STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH};
00143
00144 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
00145
00146 enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
00147
00148 enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_DOKEY};
00149
00150 enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
00151
00152 enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
00153
00154 enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
00155
00156 enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
00157
00158 #include "asterisk.h"
00159
00160 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00161
00162 #include <signal.h>
00163 #include <stdio.h>
00164 #include <unistd.h>
00165 #include <string.h>
00166 #include <stdlib.h>
00167 #include <search.h>
00168 #include <sys/types.h>
00169 #include <sys/stat.h>
00170 #include <errno.h>
00171 #include <dirent.h>
00172 #include <ctype.h>
00173 #include <sys/stat.h>
00174 #include <sys/time.h>
00175 #include <sys/file.h>
00176 #include <sys/ioctl.h>
00177 #include <sys/io.h>
00178 #include <math.h>
00179 #include <tonezone.h>
00180 #include <linux/zaptel.h>
00181 #include <netinet/in.h>
00182 #include <arpa/inet.h>
00183
00184 #include "asterisk/utils.h"
00185 #include "asterisk/lock.h"
00186 #include "asterisk/file.h"
00187 #include "asterisk/logger.h"
00188 #include "asterisk/channel.h"
00189 #include "asterisk/callerid.h"
00190 #include "asterisk/pbx.h"
00191 #include "asterisk/module.h"
00192 #include "asterisk/translate.h"
00193 #include "asterisk/features.h"
00194 #include "asterisk/options.h"
00195 #include "asterisk/cli.h"
00196 #include "asterisk/config.h"
00197 #include "asterisk/say.h"
00198 #include "asterisk/localtime.h"
00199
00200 static char *tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005";
00201
00202 static char *app = "Rpt";
00203
00204 static char *synopsis = "Radio Repeater/Remote Base Control System";
00205
00206 static char *descrip =
00207 " Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
00208 "\n"
00209 " Not specifying an option puts it in normal endpoint mode (where source\n"
00210 " IP and nodename are verified).\n"
00211 "\n"
00212 " Options are as follows:\n"
00213 "\n"
00214 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
00215 " this if you have checked security already (like with an IAX2\n"
00216 " user/password or something).\n"
00217 "\n"
00218 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
00219 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
00220 " specified by the 'announce-string') is played on radio system.\n"
00221 " Users of radio system can access autopatch, dial specified\n"
00222 " code, and pick up call. Announce-string is list of names of\n"
00223 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
00224 " or \"NODE\" to substitute node number.\n"
00225 "\n"
00226 " P - Phone Control mode. This allows a regular phone user to have\n"
00227 " full control and audio access to the radio system. For the\n"
00228 " user to have DTMF control, the 'phone_functions' parameter\n"
00229 " must be specified for the node in 'rpt.conf'. An additional\n"
00230 " function (cop,6) must be listed so that PTT control is available.\n"
00231 "\n"
00232 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
00233 " have full control and audio access to the radio system. In this\n"
00234 " mode, the PTT is activated for the entire length of the call.\n"
00235 " For the user to have DTMF control (not generally recomended in\n"
00236 " this mode), the 'dphone_functions' parameter must be specified\n"
00237 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
00238 " available to the phone user.\n"
00239 "\n";
00240
00241 static int debug = 0;
00242 static int nrpts = 0;
00243
00244 char *discstr = "!!DISCONNECT!!";
00245 static char *remote_rig_ft897="ft897";
00246 static char *remote_rig_rbi="rbi";
00247
00248 struct ast_config *cfg;
00249
00250 STANDARD_LOCAL_USER;
00251 LOCAL_USER_DECL;
00252
00253 #define MSWAIT 200
00254 #define HANGTIME 5000
00255 #define TOTIME 180000
00256 #define IDTIME 300000
00257 #define MAXRPTS 20
00258 #define POLITEID 30000
00259 #define FUNCTDELAY 1500
00260
00261 static pthread_t rpt_master_thread;
00262
00263 struct rpt;
00264
00265 struct rpt_link
00266 {
00267 struct rpt_link *next;
00268 struct rpt_link *prev;
00269 char mode;
00270 char isremote;
00271 char phonemode;
00272 char name[MAXNODESTR];
00273 char lasttx;
00274 char lastrx;
00275 char connected;
00276 char hasconnected;
00277 char outbound;
00278 char disced;
00279 char killme;
00280 long elaptime;
00281 long disctime;
00282 long retrytimer;
00283 long retxtimer;
00284 int retries;
00285 struct ast_channel *chan;
00286 struct ast_channel *pchan;
00287 } ;
00288
00289 struct rpt_tele
00290 {
00291 struct rpt_tele *next;
00292 struct rpt_tele *prev;
00293 struct rpt *rpt;
00294 struct ast_channel *chan;
00295 int mode;
00296 struct rpt_link mylink;
00297 char param[TELEPARAMSIZE];
00298 pthread_t threadid;
00299 } ;
00300
00301 struct function_table_tag
00302 {
00303 char action[ACTIONSIZE];
00304 int (*function)(struct rpt *myrpt, char *param, char *digitbuf,
00305 int command_source, struct rpt_link *mylink);
00306 } ;
00307
00308
00309
00310 struct morse_bits
00311 {
00312 int len;
00313 int ddcomb;
00314 } ;
00315
00316 struct telem_defaults
00317 {
00318 char name[20];
00319 char value[80];
00320 } ;
00321
00322
00323 static struct rpt
00324 {
00325 char *name;
00326 ast_mutex_t lock;
00327 char *rxchanname;
00328 char *txchanname;
00329 char *ourcontext;
00330 char *ourcallerid;
00331 char *acctcode;
00332 char *ident;
00333 char *tonezone;
00334 char *functions;
00335 char *link_functions;
00336 char *phone_functions;
00337 char *dphone_functions;
00338 char *nodes;
00339 struct rpt_link links;
00340 int hangtime;
00341 int totime;
00342 int idtime;
00343 int unkeytocttimer;
00344 char keyed;
00345 char exttx;
00346 char localtx;
00347 char remoterx;
00348 char remotetx;
00349 char remoteon;
00350 char simple;
00351 char *remote;
00352 char tounkeyed;
00353 char tonotify;
00354 char enable;
00355 char dtmfbuf[MAXDTMF];
00356 char rem_dtmfbuf[MAXDTMF];
00357 char cmdnode[50];
00358 struct ast_channel *rxchannel,*txchannel;
00359 struct ast_channel *pchannel,*txpchannel, *remchannel;
00360 struct rpt_tele tele;
00361 pthread_t rpt_call_thread,rpt_thread;
00362 time_t rem_dtmf_time,dtmf_time_rem;
00363 int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer;
00364 int mustid;
00365 int politeid;
00366 int dtmfidx,rem_dtmfidx;
00367 long retxtimer;
00368 char mydtmf;
00369 int iobase;
00370 char exten[AST_MAX_EXTENSION];
00371 char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
00372 char offset;
00373 char powerlevel;
00374 char txplon;
00375 char rxplon;
00376 char remmode;
00377 char tunerequest;
00378 char hfscanmode;
00379 int hfscanstatus;
00380 char lastlinknode[MAXNODESTR];
00381 char funcchar;
00382 char endchar;
00383 char stopgen;
00384 int phone_longestfunc;
00385 int dphone_longestfunc;
00386 int link_longestfunc;
00387 int longestfunc;
00388 int longestnode;
00389 int threadrestarts;
00390 time_t disgorgetime;
00391 time_t lastthreadrestarttime;
00392 char nobusyout;
00393 } rpt_vars[MAXRPTS];
00394
00395
00396
00397
00398
00399
00400 static int rpt_do_debug(int fd, int argc, char *argv[]);
00401
00402 static char debug_usage[] =
00403 "Usage: rpt debug level {0-7}\n"
00404 " Enables debug messages in app_rpt\n";
00405
00406 static struct ast_cli_entry cli_debug =
00407 { { "rpt", "debug", "level" }, rpt_do_debug, "Enable app_rpt debugging", debug_usage };
00408
00409
00410
00411
00412
00413
00414
00415
00416 static struct telem_defaults tele_defs[] = {
00417 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
00418 {"ct2","|t(660,880,150,3072)"},
00419 {"ct3","|t(440,0,150,3072)"},
00420 {"ct4","|t(550,0,150,3072)"},
00421 {"ct5","|t(660,0,150,3072)"},
00422 {"ct6","|t(880,0,150,3072)"},
00423 {"ct7","|t(660,440,150,3072)"},
00424 {"ct8","|t(700,1100,150,3072)"},
00425 {"remotemon","|t(1600,0,75,2048)"},
00426 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
00427 {"cmdmode","|t(900,904,200,2048)"},
00428 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
00429 } ;
00430
00431
00432
00433
00434
00435 static int setrbi(struct rpt *myrpt);
00436
00437
00438
00439
00440
00441
00442
00443 static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00444 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00445 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00446 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00447 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00448 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
00449
00450
00451
00452
00453 static struct function_table_tag function_table[] = {
00454 {"cop", function_cop},
00455 {"autopatchup", function_autopatchup},
00456 {"autopatchdn", function_autopatchdn},
00457 {"ilink", function_ilink},
00458 {"status", function_status},
00459 {"remote", function_remote}
00460 } ;
00461
00462 static int myatoi(char *str)
00463 {
00464 int ret;
00465
00466 if (str == NULL) return -1;
00467
00468 if (sscanf(str,"%i",&ret) != 1) return -1;
00469 return ret;
00470 }
00471
00472
00473
00474
00475
00476 static int rpt_do_debug(int fd, int argc, char *argv[])
00477 {
00478 int newlevel;
00479
00480 if (argc != 4)
00481 return RESULT_SHOWUSAGE;
00482 newlevel = myatoi(argv[3]);
00483 if((newlevel < 0) || (newlevel > 7))
00484 return RESULT_SHOWUSAGE;
00485 if(newlevel)
00486 ast_cli(fd, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug, newlevel);
00487 else
00488 ast_cli(fd, "app_rpt Debugging disabled\n");
00489
00490 debug = newlevel;
00491 return RESULT_SUCCESS;
00492 }
00493
00494
00495
00496 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
00497 {
00498 int res;
00499
00500 if ((res = ast_tonepair_start(chan, f1, f2, duration, amplitude)))
00501 return res;
00502
00503 while(chan->generatordata) {
00504 if (ast_safe_sleep(chan,1)) return -1;
00505 }
00506
00507 return 0;
00508 }
00509
00510 static int play_tone(struct ast_channel *chan, int freq, int duration, int amplitude)
00511 {
00512 return play_tone_pair(chan, freq, 0, duration, amplitude);
00513 }
00514
00515 static int play_silence(struct ast_channel *chan, int duration)
00516 {
00517 return play_tone_pair(chan, 0, 0, duration, 0);
00518 }
00519
00520
00521 static int send_morse(struct ast_channel *chan, char *string, int speed, int freq, int amplitude)
00522 {
00523
00524 static struct morse_bits mbits[] = {
00525 {0, 0},
00526 {0, 0},
00527 {6, 18},
00528 {0, 0},
00529 {7, 72},
00530 {0, 0},
00531 {0, 0},
00532 {6, 30},
00533 {5, 13},
00534 {6, 29},
00535 {0, 0},
00536 {5, 10},
00537 {6, 51},
00538 {6, 33},
00539 {6, 42},
00540 {5, 9},
00541 {5, 31},
00542 {5, 30},
00543 {5, 28},
00544 {5, 24},
00545 {5, 16},
00546 {5, 0},
00547 {5, 1},
00548 {5, 3},
00549 {5, 7},
00550 {5, 15},
00551 {6, 7},
00552 {6, 21},
00553 {0, 0},
00554 {5, 33},
00555 {0, 0},
00556 {6, 12},
00557 {0, 0},
00558 {2, 2},
00559 {4, 1},
00560 {4, 5},
00561 {3, 1},
00562 {1, 0},
00563 {4, 4},
00564 {3, 3},
00565 {4, 0},
00566 {2, 0},
00567 {4, 14},
00568 {3, 5},
00569 {4, 2},
00570 {2, 3},
00571 {2, 1},
00572 {3, 7},
00573 {4, 6},
00574 {4, 11},
00575 {3, 2},
00576 {3, 0},
00577 {1, 1},
00578 {3, 4},
00579 {4, 8},
00580 {3, 6},
00581 {4, 9},
00582 {4, 13},
00583 {4, 3}
00584 };
00585
00586
00587 int dottime;
00588 int dashtime;
00589 int intralettertime;
00590 int interlettertime;
00591 int interwordtime;
00592 int len, ddcomb;
00593 int res;
00594 int c;
00595 int i;
00596 int flags;
00597
00598 res = 0;
00599
00600
00601
00602 dottime = 900/speed;
00603
00604
00605
00606 dashtime = 3 * dottime;
00607 intralettertime = dottime;
00608 interlettertime = dottime * 4 ;
00609 interwordtime = dottime * 7;
00610
00611 for(;(*string) && (!res); string++){
00612
00613 c = *string;
00614
00615
00616
00617 if((c >= 'a') && (c <= 'z'))
00618 c -= 0x20;
00619
00620
00621
00622 if(c > 'Z')
00623 continue;
00624
00625
00626
00627 if(c == ' '){
00628 if(!res)
00629 res = play_silence(chan, interwordtime);
00630 continue;
00631 }
00632
00633
00634
00635 c -= 0x20;
00636
00637
00638
00639 len = mbits[c].len;
00640 ddcomb = mbits[c].ddcomb;
00641
00642
00643
00644 for(; len ; len--){
00645 if(!res)
00646 res = play_tone(chan, freq, (ddcomb & 1) ? dashtime : dottime, amplitude);
00647 if(!res)
00648 res = play_silence(chan, intralettertime);
00649 ddcomb >>= 1;
00650 }
00651
00652
00653
00654 if(!res)
00655 res = play_silence(chan, interlettertime - intralettertime);
00656 }
00657
00658
00659
00660 if (!res)
00661 res = ast_waitstream(chan, "");
00662 ast_stopstream(chan);
00663
00664
00665
00666
00667
00668 for(i = 0; i < 20 ; i++){
00669 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
00670 res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
00671 if(flags & ZT_IOMUX_WRITEEMPTY)
00672 break;
00673 if( ast_safe_sleep(chan, 50)){
00674 res = -1;
00675 break;
00676 }
00677 }
00678
00679
00680 return res;
00681 }
00682
00683 static int send_tone_telemetry(struct ast_channel *chan, char *tonestring)
00684 {
00685 char *stringp;
00686 char *tonesubset;
00687 int f1,f2;
00688 int duration;
00689 int amplitude;
00690 int res;
00691 int i;
00692 int flags;
00693
00694 res = 0;
00695
00696 stringp = ast_strdupa(tonestring);
00697
00698 for(;tonestring;){
00699 tonesubset = strsep(&stringp,")");
00700 if(!tonesubset)
00701 break;
00702 if(sscanf(tonesubset,"(%d,%d,%d,%d", &f1, &f2, &duration, &litude) != 4)
00703 break;
00704 res = play_tone_pair(chan, f1, f2, duration, amplitude);
00705 if(res)
00706 break;
00707 }
00708 if(!res)
00709 res = play_tone_pair(chan, 0, 0, 100, 0);
00710
00711 if (!res)
00712 res = ast_waitstream(chan, "");
00713 ast_stopstream(chan);
00714
00715
00716
00717
00718
00719 for(i = 0; i < 20 ; i++){
00720 flags = ZT_IOMUX_WRITEEMPTY | ZT_IOMUX_NOWAIT;
00721 res = ioctl(chan->fds[0], ZT_IOMUX, &flags);
00722 if(flags & ZT_IOMUX_WRITEEMPTY)
00723 break;
00724 if( ast_safe_sleep(chan, 50)){
00725 res = -1;
00726 break;
00727 }
00728 }
00729
00730 return res;
00731
00732 }
00733
00734
00735 static int sayfile(struct ast_channel *mychannel,char *fname)
00736 {
00737 int res;
00738
00739 res = ast_streamfile(mychannel, fname, mychannel->language);
00740 if (!res)
00741 res = ast_waitstream(mychannel, "");
00742 else
00743 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00744 ast_stopstream(mychannel);
00745 return res;
00746 }
00747
00748 static int saycharstr(struct ast_channel *mychannel,char *str)
00749 {
00750 int res;
00751
00752 res = ast_say_character_str(mychannel,str,NULL,mychannel->language);
00753 if (!res)
00754 res = ast_waitstream(mychannel, "");
00755 else
00756 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00757 ast_stopstream(mychannel);
00758 return res;
00759 }
00760
00761 static int saynum(struct ast_channel *mychannel, int num)
00762 {
00763 int res;
00764 res = ast_say_number(mychannel, num, NULL, mychannel->language, NULL);
00765 if(!res)
00766 res = ast_waitstream(mychannel, "");
00767 else
00768 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
00769 ast_stopstream(mychannel);
00770 return res;
00771 }
00772
00773
00774
00775
00776 static int retrieve_astcfgint(char *category, char *name, int min, int max, int defl)
00777 {
00778 char *var;
00779 int ret;
00780
00781 var = ast_variable_retrieve(cfg, category, name);
00782 if(var){
00783 ret = myatoi(var);
00784 if(ret < min)
00785 ret = min;
00786 if(ret > max)
00787 ret = max;
00788 }
00789 else
00790 ret = defl;
00791 return ret;
00792 }
00793
00794 static int telem_any(struct ast_channel *chan, char *entry)
00795 {
00796 int res;
00797 char c;
00798
00799 static int morsespeed;
00800 static int morsefreq;
00801 static int morseampl;
00802 static int morseidfreq = 0;
00803 static int morseidampl;
00804 static char mcat[] = MORSE;
00805
00806 res = 0;
00807
00808 if(!morseidfreq){
00809 morsespeed = retrieve_astcfgint( mcat, "speed", 5, 20, 20);
00810 morsefreq = retrieve_astcfgint( mcat, "frequency", 300, 3000, 800);
00811 morseampl = retrieve_astcfgint( mcat, "amplitude", 200, 8192, 4096);
00812 morseidampl = retrieve_astcfgint( mcat, "idamplitude", 200, 8192, 2048);
00813 morseidfreq = retrieve_astcfgint( mcat, "idfrequency", 300, 3000, 330);
00814 }
00815
00816
00817
00818 if(entry[0] == '|'){
00819 c = entry[1];
00820 if((c >= 'a')&&(c <= 'z'))
00821 c -= 0x20;
00822
00823 switch(c){
00824 case 'I':
00825 res = send_morse(chan, entry + 2, morsespeed, morseidfreq, morseidampl);
00826 break;
00827
00828 case 'M':
00829 res = send_morse(chan, entry + 2, morsespeed, morsefreq, morseampl);
00830 break;
00831
00832 case 'T':
00833 res = send_tone_telemetry(chan, entry + 2);
00834 break;
00835 default:
00836 res = -1;
00837 }
00838 }
00839 else
00840 res = sayfile(chan, entry);
00841 return res;
00842 }
00843
00844
00845
00846
00847
00848
00849
00850 static int telem_lookup(struct ast_channel *chan, char *node, char *name)
00851 {
00852
00853 int res;
00854 int i;
00855 char *entry;
00856 char *telemetry;
00857 char *telemetry_save;
00858
00859 res = 0;
00860 telemetry_save = NULL;
00861 entry = NULL;
00862
00863
00864
00865
00866 telemetry = ast_variable_retrieve(cfg, node, TELEMETRY);
00867 if(telemetry){
00868 telemetry_save = ast_strdupa(telemetry);
00869 if(!telemetry_save){
00870 ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
00871 return res;
00872 }
00873 entry = ast_variable_retrieve(cfg, telemetry_save, name);
00874 }
00875
00876
00877
00878 if(!entry){
00879
00880 for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
00881 if(!strcasecmp(tele_defs[i].name, name))
00882 entry = tele_defs[i].value;
00883 }
00884 }
00885 if(entry)
00886 telem_any(chan, entry);
00887 else{
00888 ast_log(LOG_WARNING, "Telemetry name not found: %s\n", name);
00889 res = -1;
00890 }
00891 return res;
00892 }
00893
00894
00895
00896
00897
00898 static int get_wait_interval(struct rpt *myrpt, int type)
00899 {
00900 int interval;
00901 char *wait_times;
00902 char *wait_times_save;
00903
00904 wait_times_save = NULL;
00905 wait_times = ast_variable_retrieve(cfg, myrpt->name, "wait_times");
00906
00907 if(wait_times){
00908 wait_times_save = ast_strdupa(wait_times);
00909 if(!wait_times_save){
00910 ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
00911 wait_times = NULL;
00912 }
00913 }
00914
00915 switch(type){
00916 case DLY_TELEM:
00917 if(wait_times)
00918 interval = retrieve_astcfgint(wait_times_save, "telemwait", 500, 5000, 1000);
00919 else
00920 interval = 1000;
00921 break;
00922
00923 case DLY_ID:
00924 if(wait_times)
00925 interval = retrieve_astcfgint(wait_times_save, "idwait",250,5000,500);
00926 else
00927 interval = 500;
00928 break;
00929
00930 case DLY_UNKEY:
00931 if(wait_times)
00932 interval = retrieve_astcfgint(wait_times_save, "unkeywait",500,5000,1000);
00933 else
00934 interval = 1000;
00935 break;
00936
00937 case DLY_CALLTERM:
00938 if(wait_times)
00939 interval = retrieve_astcfgint(wait_times_save, "calltermwait",500,5000,1500);
00940 else
00941 interval = 1500;
00942 break;
00943
00944 default:
00945 return 0;
00946 }
00947 return interval;
00948 }
00949
00950
00951
00952
00953
00954
00955
00956 static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
00957 {
00958 int interval;
00959 if((interval = get_wait_interval(myrpt, type)))
00960 ast_safe_sleep(chan,interval);
00961 return;
00962 }
00963
00964
00965 static void *rpt_tele_thread(void *this)
00966 {
00967 ZT_CONFINFO ci;
00968 int res = 0,haslink,hastx,hasremote,imdone = 0, unkeys_queued, x;
00969 struct rpt_tele *mytele = (struct rpt_tele *)this;
00970 struct rpt_tele *tlist;
00971 struct rpt *myrpt;
00972 struct rpt_link *l,*m,linkbase;
00973 struct ast_channel *mychannel;
00974 int vmajor, vminor;
00975 char *p,*ct,*ct_copy,*ident, *nodename;
00976 time_t t;
00977 struct tm localtm;
00978
00979
00980
00981 myrpt = mytele->rpt;
00982
00983
00984 ast_mutex_lock(&myrpt->lock);
00985 nodename = ast_strdupa(myrpt->name);
00986 ident = ast_strdupa(myrpt->ident);
00987 ast_mutex_unlock(&myrpt->lock);
00988
00989
00990
00991 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
00992 if (!mychannel)
00993 {
00994 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
00995 ast_mutex_lock(&myrpt->lock);
00996 remque((struct qelem *)mytele);
00997 ast_mutex_unlock(&myrpt->lock);
00998 free(mytele);
00999 pthread_exit(NULL);
01000 }
01001 ast_mutex_lock(&myrpt->lock);
01002 mytele->chan = mychannel;
01003 ast_mutex_unlock(&myrpt->lock);
01004
01005
01006 ci.chan = 0;
01007
01008
01009 ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY)) ?
01010 myrpt->txconf : myrpt->conf);
01011 ci.confmode = ZT_CONF_CONFANN;
01012
01013 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01014 {
01015 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01016 ast_mutex_lock(&myrpt->lock);
01017 remque((struct qelem *)mytele);
01018 ast_mutex_unlock(&myrpt->lock);
01019 free(mytele);
01020 ast_hangup(mychannel);
01021 pthread_exit(NULL);
01022 }
01023 ast_stopstream(mychannel);
01024 switch(mytele->mode)
01025 {
01026 case ID:
01027 case ID1:
01028
01029 wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
01030 res = telem_any(mychannel, ident);
01031 imdone=1;
01032
01033 break;
01034
01035
01036 case IDTALKOVER:
01037 p = ast_variable_retrieve(cfg, nodename, "idtalkover");
01038 if(p)
01039 res = telem_any(mychannel, p);
01040 imdone=1;
01041 break;
01042
01043 case PROC:
01044
01045 wait_interval(myrpt, DLY_TELEM, mychannel);
01046 res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
01047 break;
01048 case TERM:
01049
01050 wait_interval(myrpt, DLY_CALLTERM, mychannel);
01051 res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
01052 break;
01053 case COMPLETE:
01054
01055 wait_interval(myrpt, DLY_TELEM, mychannel);
01056 res = telem_lookup(mychannel, myrpt->name, "functcomplete");
01057 break;
01058 case UNKEY:
01059
01060
01061
01062
01063
01064 x = get_wait_interval(myrpt, DLY_UNKEY);
01065 ast_mutex_lock(&myrpt->lock);
01066 myrpt->unkeytocttimer = x;
01067 ast_mutex_unlock(&myrpt->lock);
01068
01069
01070
01071
01072
01073 tlist = myrpt->tele.next;
01074 unkeys_queued = 0;
01075 if (tlist != &myrpt->tele)
01076 {
01077 ast_mutex_lock(&myrpt->lock);
01078 while(tlist != &myrpt->tele){
01079 if (tlist->mode == UNKEY) unkeys_queued++;
01080 tlist = tlist->next;
01081 }
01082 ast_mutex_unlock(&myrpt->lock);
01083 }
01084 if( unkeys_queued > 1){
01085 imdone = 1;
01086 break;
01087 }
01088
01089
01090
01091
01092 while(myrpt->unkeytocttimer)
01093 {
01094 int ctint;
01095 if(myrpt->unkeytocttimer > 100)
01096 ctint = 100;
01097 else
01098 ctint = myrpt->unkeytocttimer;
01099 ast_safe_sleep(mychannel, ctint);
01100 ast_mutex_lock(&myrpt->lock);
01101 if(myrpt->unkeytocttimer < ctint)
01102 myrpt->unkeytocttimer = 0;
01103 else
01104 myrpt->unkeytocttimer -= ctint;
01105 ast_mutex_unlock(&myrpt->lock);
01106 }
01107
01108
01109
01110
01111
01112
01113 if(myrpt->keyed){
01114 imdone = 1;
01115 break;
01116 }
01117
01118 haslink = 0;
01119 hastx = 0;
01120 hasremote = 0;
01121 l = myrpt->links.next;
01122 if (l != &myrpt->links)
01123 {
01124 ast_mutex_lock(&myrpt->lock);
01125 while(l != &myrpt->links)
01126 {
01127 if (l->name[0] == '0')
01128 {
01129 l = l->next;
01130 continue;
01131 }
01132 haslink = 1;
01133 if (l->mode) {
01134 hastx++;
01135 if (l->isremote) hasremote++;
01136 }
01137 l = l->next;
01138 }
01139 ast_mutex_unlock(&myrpt->lock);
01140 }
01141 if (haslink)
01142 {
01143
01144 res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
01145 if(res)
01146 ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
01147
01148
01149
01150 if (myrpt->cmdnode[0])
01151 {
01152 ast_safe_sleep(mychannel,200);
01153 res = telem_lookup(mychannel, myrpt->name, "cmdmode");
01154 if(res)
01155 ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
01156 ast_stopstream(mychannel);
01157 }
01158 }
01159 else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){
01160 ct_copy = ast_strdupa(ct);
01161 res = telem_lookup(mychannel, myrpt->name, ct_copy);
01162 if(res)
01163 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
01164 }
01165
01166 if (hasremote && (!myrpt->cmdnode[0]))
01167 {
01168
01169 ci.chan = 0;
01170 ci.confno = myrpt->conf;
01171 ci.confmode = ZT_CONF_CONFANN;
01172
01173 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01174 {
01175 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01176 ast_mutex_lock(&myrpt->lock);
01177 remque((struct qelem *)mytele);
01178 ast_mutex_unlock(&myrpt->lock);
01179 free(mytele);
01180 ast_hangup(mychannel);
01181 pthread_exit(NULL);
01182 }
01183 if((ct = ast_variable_retrieve(cfg, nodename, "remotect"))){
01184 ast_safe_sleep(mychannel,200);
01185 ct_copy = ast_strdupa(ct);
01186 res = telem_lookup(mychannel, myrpt->name, ct_copy);
01187 if(res)
01188 ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
01189 }
01190 }
01191 imdone = 1;
01192 break;
01193 case REMDISC:
01194
01195 wait_interval(myrpt, DLY_TELEM, mychannel);
01196 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01197 if (!res)
01198 res = ast_waitstream(mychannel, "");
01199 else
01200 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01201 ast_stopstream(mychannel);
01202 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01203 res = ast_streamfile(mychannel, ((mytele->mylink.connected) ?
01204 "rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
01205 break;
01206 case REMALREADY:
01207
01208 wait_interval(myrpt, DLY_TELEM, mychannel);
01209 res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
01210 break;
01211 case REMNOTFOUND:
01212
01213 wait_interval(myrpt, DLY_TELEM, mychannel);
01214 res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
01215 break;
01216 case REMGO:
01217
01218 wait_interval(myrpt, DLY_TELEM, mychannel);
01219 res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
01220 break;
01221 case CONNECTED:
01222
01223 wait_interval(myrpt, DLY_TELEM, mychannel);
01224 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01225 if (!res)
01226 res = ast_waitstream(mychannel, "");
01227 else
01228 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01229 ast_stopstream(mychannel);
01230 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01231 res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
01232 break;
01233 case CONNFAIL:
01234 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01235 if (!res)
01236 res = ast_waitstream(mychannel, "");
01237 else
01238 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01239 ast_stopstream(mychannel);
01240 ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
01241 res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
01242 break;
01243 case STATUS:
01244
01245 wait_interval(myrpt, DLY_TELEM, mychannel);
01246 hastx = 0;
01247 linkbase.next = &linkbase;
01248 linkbase.prev = &linkbase;
01249 ast_mutex_lock(&myrpt->lock);
01250
01251 l = myrpt->links.next;
01252 while(l != &myrpt->links)
01253 {
01254 if (l->name[0] == '0')
01255 {
01256 l = l->next;
01257 continue;
01258 }
01259 m = malloc(sizeof(struct rpt_link));
01260 if (!m)
01261 {
01262 ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
01263 ast_mutex_lock(&myrpt->lock);
01264 remque((struct qelem *)mytele);
01265 ast_mutex_unlock(&myrpt->lock);
01266 free(mytele);
01267 ast_hangup(mychannel);
01268 pthread_exit(NULL);
01269 }
01270 memcpy(m,l,sizeof(struct rpt_link));
01271 m->next = m->prev = NULL;
01272 insque((struct qelem *)m,(struct qelem *)linkbase.next);
01273 l = l->next;
01274 }
01275 ast_mutex_unlock(&myrpt->lock);
01276 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01277 if (!res)
01278 res = ast_waitstream(mychannel, "");
01279 else
01280 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01281 ast_stopstream(mychannel);
01282 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
01283 if (!res)
01284 res = ast_waitstream(mychannel, "");
01285 else
01286 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01287 ast_stopstream(mychannel);
01288 if (myrpt->callmode)
01289 {
01290 hastx = 1;
01291 res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
01292 if (!res)
01293 res = ast_waitstream(mychannel, "");
01294 else
01295 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01296 ast_stopstream(mychannel);
01297 }
01298 l = linkbase.next;
01299 while(l != &linkbase)
01300 {
01301 hastx = 1;
01302 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01303 if (!res)
01304 res = ast_waitstream(mychannel, "");
01305 else
01306 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01307 ast_stopstream(mychannel);
01308 ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
01309 if (!res)
01310 res = ast_waitstream(mychannel, "");
01311 else
01312 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01313 ast_stopstream(mychannel);
01314 res = ast_streamfile(mychannel, ((l->mode) ?
01315 "rpt/tranceive" : "rpt/monitor"), mychannel->language);
01316 if (!res)
01317 res = ast_waitstream(mychannel, "");
01318 else
01319 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01320 ast_stopstream(mychannel);
01321 l = l->next;
01322 }
01323 if (!hastx)
01324 {
01325 res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
01326 if (!res)
01327 res = ast_waitstream(mychannel, "");
01328 else
01329 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01330 ast_stopstream(mychannel);
01331 }
01332
01333 l = linkbase.next;
01334 while(l != &linkbase)
01335 {
01336 m = l;
01337 l = l->next;
01338 remque((struct qelem *)m);
01339 free(m);
01340 }
01341 imdone = 1;
01342 break;
01343 case TIMEOUT:
01344 res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
01345 if (!res)
01346 res = ast_waitstream(mychannel, "");
01347 else
01348 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01349 ast_stopstream(mychannel);
01350 ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
01351 res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
01352 break;
01353
01354 case STATS_TIME:
01355 wait_interval(myrpt, DLY_TELEM, mychannel);
01356 t = time(NULL);
01357 localtime_r(&t, &localtm);
01358
01359 if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
01360 p = "rpt/goodmorning";
01361 else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
01362 p = "rpt/goodafternoon";
01363 else
01364 p = "rpt/goodevening";
01365 if (sayfile(mychannel,p) == -1)
01366 {
01367 imdone = 1;
01368 break;
01369 }
01370
01371 if (sayfile(mychannel,"rpt/thetimeis") == -1)
01372 {
01373 imdone = 1;
01374 break;
01375 }
01376
01377 res = ast_say_time(mychannel, t, "", mychannel->language);
01378 if (!res)
01379 res = ast_waitstream(mychannel, "");
01380 ast_stopstream(mychannel);
01381 imdone = 1;
01382 break;
01383 case STATS_VERSION:
01384 p = strstr(tdesc, "version");
01385 if(!p)
01386 break;
01387 if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
01388 break;
01389 wait_interval(myrpt, DLY_TELEM, mychannel);
01390
01391 if (sayfile(mychannel,"rpt/version") == -1)
01392 {
01393 imdone = 1;
01394 break;
01395 }
01396 if(!res)
01397 ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
01398 if (!res)
01399 res = ast_waitstream(mychannel, "");
01400 ast_stopstream(mychannel);
01401 if (saycharstr(mychannel,".") == -1)
01402 {
01403 imdone = 1;
01404 break;
01405 }
01406 if(!res)
01407 ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
01408 if (!res){
01409 res = ast_waitstream(mychannel, "");
01410 ast_stopstream(mychannel);
01411 }
01412 else
01413 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01414 imdone = 1;
01415 break;
01416 case ARB_ALPHA:
01417 wait_interval(myrpt, DLY_TELEM, mychannel);
01418 if(mytele->param)
01419 saycharstr(mychannel, mytele->param);
01420 imdone = 1;
01421 break;
01422 case REV_PATCH:
01423 wait_interval(myrpt, DLY_TELEM, mychannel);
01424 if(mytele->param) {
01425
01426
01427 char *tpl_working, *tpl_current;
01428 char *tmp[100], *myparm;
01429 int looptemp=0,i=0, dres = 0;
01430
01431
01432 tpl_working = strdupa(mytele->param);
01433 myparm = strsep(&tpl_working,",");
01434 tpl_current=strsep(&tpl_working, ":");
01435
01436 while(tpl_current && looptemp < sizeof(tmp)) {
01437 tmp[looptemp]=tpl_current;
01438 looptemp++;
01439 tpl_current=strsep(&tpl_working,":");
01440 }
01441
01442 for(i=0; i<looptemp; i++) {
01443 if(!strcmp(tmp[i], "PARKED")) {
01444 ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
01445 } else if(!strcmp(tmp[i], "NODE")) {
01446 ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
01447 } else {
01448 dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
01449 if(!dres) {
01450 dres = ast_waitstream(mychannel, "");
01451 } else {
01452 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
01453 dres = 0;
01454 }
01455 }
01456 }
01457 }
01458 imdone = 1;
01459 break;
01460 case TEST_TONE:
01461 imdone = 1;
01462 myrpt->stopgen = 0;
01463 if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
01464 break;
01465 while(mychannel->generatordata && (!myrpt->stopgen)) {
01466 if (ast_safe_sleep(mychannel,1)) break;
01467 imdone = 1;
01468 }
01469 break;
01470 default:
01471 break;
01472 }
01473 myrpt->stopgen = 0;
01474 if (!imdone)
01475 {
01476 if (!res)
01477 res = ast_waitstream(mychannel, "");
01478 else {
01479 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
01480 res = 0;
01481 }
01482 }
01483 ast_stopstream(mychannel);
01484 ast_mutex_lock(&myrpt->lock);
01485 remque((struct qelem *)mytele);
01486 ast_mutex_unlock(&myrpt->lock);
01487 free(mytele);
01488 ast_hangup(mychannel);
01489 pthread_exit(NULL);
01490 }
01491
01492 static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
01493 {
01494 struct rpt_tele *tele;
01495 struct rpt_link *mylink = (struct rpt_link *) data;
01496 pthread_attr_t attr;
01497
01498 tele = malloc(sizeof(struct rpt_tele));
01499 if (!tele)
01500 {
01501 ast_log(LOG_WARNING, "Unable to allocate memory\n");
01502 pthread_exit(NULL);
01503 return;
01504 }
01505
01506 memset((char *)tele,0,sizeof(struct rpt_tele));
01507 tele->rpt = myrpt;
01508 tele->mode = mode;
01509 ast_mutex_lock(&myrpt->lock);
01510 if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)){
01511 memset(&tele->mylink,0,sizeof(struct rpt_link));
01512 if (mylink){
01513 memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
01514 }
01515 }
01516 else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
01517 strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
01518 tele->param[TELEPARAMSIZE - 1] = 0;
01519 }
01520 insque((struct qelem *)tele,(struct qelem *)myrpt->tele.next);
01521 ast_mutex_unlock(&myrpt->lock);
01522 pthread_attr_init(&attr);
01523 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01524 ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
01525 return;
01526 }
01527
01528 static void *rpt_call(void *this)
01529 {
01530 ZT_CONFINFO ci;
01531 struct rpt *myrpt = (struct rpt *)this;
01532 int res;
01533 struct ast_frame wf;
01534 int stopped,congstarted;
01535 struct ast_channel *mychannel,*genchannel;
01536
01537 myrpt->mydtmf = 0;
01538
01539 mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01540 if (!mychannel)
01541 {
01542 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01543 pthread_exit(NULL);
01544 }
01545 ci.chan = 0;
01546 ci.confno = myrpt->conf;
01547 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
01548 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01549
01550 if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
01551 {
01552 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01553 ast_hangup(mychannel);
01554 myrpt->callmode = 0;
01555 pthread_exit(NULL);
01556 }
01557
01558 genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01559 if (!genchannel)
01560 {
01561 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01562 ast_hangup(mychannel);
01563 pthread_exit(NULL);
01564 }
01565 ci.chan = 0;
01566 ci.confno = myrpt->conf;
01567 ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
01568 | ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
01569
01570 if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
01571 {
01572 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01573 ast_hangup(mychannel);
01574 ast_hangup(genchannel);
01575 myrpt->callmode = 0;
01576 pthread_exit(NULL);
01577 }
01578 if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
01579 {
01580 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
01581 ast_hangup(mychannel);
01582 ast_hangup(genchannel);
01583 myrpt->callmode = 0;
01584 pthread_exit(NULL);
01585 }
01586 if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
01587 {
01588 ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
01589 ast_hangup(mychannel);
01590 ast_hangup(genchannel);
01591 myrpt->callmode = 0;
01592 pthread_exit(NULL);
01593 }
01594
01595 if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
01596 {
01597 ast_log(LOG_WARNING, "Cannot start dialtone\n");
01598 ast_hangup(mychannel);
01599 ast_hangup(genchannel);
01600 myrpt->callmode = 0;
01601 pthread_exit(NULL);
01602 }
01603 stopped = 0;
01604 congstarted = 0;
01605 while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
01606 {
01607
01608 if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
01609 {
01610 stopped = 1;
01611
01612 tone_zone_play_tone(mychannel->fds[0],-1);
01613 }
01614 if ((myrpt->callmode == 4) && (!congstarted))
01615 {
01616 congstarted = 1;
01617
01618 tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
01619 }
01620 res = ast_safe_sleep(mychannel, MSWAIT);
01621 if (res < 0)
01622 {
01623 ast_hangup(mychannel);
01624 ast_hangup(genchannel);
01625 ast_mutex_lock(&myrpt->lock);
01626 myrpt->callmode = 0;
01627 ast_mutex_unlock(&myrpt->lock);
01628 pthread_exit(NULL);
01629 }
01630 }
01631
01632 tone_zone_play_tone(mychannel->fds[0],-1);
01633
01634 if (!myrpt->callmode)
01635 {
01636 ast_hangup(mychannel);
01637 ast_hangup(genchannel);
01638 ast_mutex_lock(&myrpt->lock);
01639 myrpt->callmode = 0;
01640 ast_mutex_unlock(&myrpt->lock);
01641 pthread_exit(NULL);
01642 }
01643
01644 if (myrpt->ourcallerid && *myrpt->ourcallerid){
01645 char *name, *loc, *instr;
01646 instr = strdup(myrpt->ourcallerid);
01647 if(instr){
01648 ast_callerid_parse(instr, &name, &loc);
01649 if(loc){
01650 if(mychannel->cid.cid_num)
01651 free(mychannel->cid.cid_num);
01652 mychannel->cid.cid_num = strdup(loc);
01653 }
01654 if(name){
01655 if(mychannel->cid.cid_name)
01656 free(mychannel->cid.cid_name);
01657 mychannel->cid.cid_name = strdup(name);
01658 }
01659 free(instr);
01660 }
01661 }
01662
01663 strncpy(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
01664 strncpy(mychannel->context, myrpt->ourcontext, sizeof(mychannel->context) - 1);
01665 if (myrpt->acctcode)
01666 strncpy(mychannel->accountcode, myrpt->acctcode, sizeof(mychannel->accountcode) - 1);
01667 mychannel->priority = 1;
01668 ast_channel_undefer_dtmf(mychannel);
01669 if (ast_pbx_start(mychannel) < 0)
01670 {
01671 ast_log(LOG_WARNING, "Unable to start PBX!!\n");
01672 ast_hangup(mychannel);
01673 ast_hangup(genchannel);
01674 ast_mutex_lock(&myrpt->lock);
01675 myrpt->callmode = 0;
01676 ast_mutex_unlock(&myrpt->lock);
01677 pthread_exit(NULL);
01678 }
01679 usleep(10000);
01680 ast_mutex_lock(&myrpt->lock);
01681 myrpt->callmode = 3;
01682 while(myrpt->callmode)
01683 {
01684 if ((!mychannel->pbx) && (myrpt->callmode != 4))
01685 {
01686 myrpt->callmode = 4;
01687 ast_mutex_unlock(&myrpt->lock);
01688
01689 tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
01690 ast_mutex_lock(&myrpt->lock);
01691 }
01692 if (myrpt->mydtmf)
01693 {
01694 wf.frametype = AST_FRAME_DTMF;
01695 wf.subclass = myrpt->mydtmf;
01696 wf.offset = 0;
01697 wf.mallocd = 0;
01698 wf.data = NULL;
01699 wf.datalen = 0;
01700 wf.samples = 0;
01701 ast_mutex_unlock(&myrpt->lock);
01702 ast_write(genchannel,&wf);
01703 ast_mutex_lock(&myrpt->lock);
01704 myrpt->mydtmf = 0;
01705 }
01706 ast_mutex_unlock(&myrpt->lock);
01707 usleep(MSWAIT * 1000);
01708 ast_mutex_lock(&myrpt->lock);
01709 }
01710 ast_mutex_unlock(&myrpt->lock);
01711 tone_zone_play_tone(genchannel->fds[0],-1);
01712 if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
01713 ast_hangup(genchannel);
01714 ast_mutex_lock(&myrpt->lock);
01715 myrpt->callmode = 0;
01716 ast_mutex_unlock(&myrpt->lock);
01717 pthread_exit(NULL);
01718 }
01719
01720 static void send_link_dtmf(struct rpt *myrpt,char c)
01721 {
01722 char str[300];
01723 struct ast_frame wf;
01724 struct rpt_link *l;
01725
01726 snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
01727 wf.frametype = AST_FRAME_TEXT;
01728 wf.subclass = 0;
01729 wf.offset = 0;
01730 wf.mallocd = 1;
01731 wf.datalen = strlen(str) + 1;
01732 wf.samples = 0;
01733 l = myrpt->links.next;
01734
01735 while(l != &myrpt->links)
01736 {
01737 if (l->name[0] == '0')
01738 {
01739 l = l->next;
01740 continue;
01741 }
01742
01743 if (!strcmp(l->name,myrpt->cmdnode))
01744 {
01745 wf.data = strdup(str);
01746 if (l->chan) ast_write(l->chan,&wf);
01747 return;
01748 }
01749 l = l->next;
01750 }
01751 l = myrpt->links.next;
01752
01753 while(l != &myrpt->links)
01754 {
01755 wf.data = strdup(str);
01756 if (l->chan) ast_write(l->chan,&wf);
01757 l = l->next;
01758 }
01759 return;
01760 }
01761
01762
01763
01764
01765
01766 static int function_ilink(struct rpt *myrpt, char *param, char *digits, int command_source, struct rpt_link *mylink)
01767 {
01768
01769 char *val, *s, *s1, *s2, *tele;
01770 char tmp[300], deststr[300] = "",modechange = 0;
01771 char digitbuf[MAXNODESTR];
01772 struct rpt_link *l;
01773 ZT_CONFINFO ci;
01774
01775 if(!param)
01776 return DC_ERROR;
01777
01778
01779 if (!myrpt->enable)
01780 return DC_ERROR;
01781
01782 strncpy(digitbuf,digits,MAXNODESTR - 1);
01783
01784 if(debug)
01785 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
01786
01787 switch(myatoi(param)){
01788 case 1:
01789 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01790 strcpy(digitbuf,myrpt->lastlinknode);
01791 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01792 if (!val){
01793 if(strlen(digitbuf) >= myrpt->longestnode)
01794 return DC_ERROR;
01795 break;
01796 }
01797 strncpy(tmp,val,sizeof(tmp) - 1);
01798 s = tmp;
01799 s1 = strsep(&s,",");
01800 s2 = strsep(&s,",");
01801 ast_mutex_lock(&myrpt->lock);
01802 l = myrpt->links.next;
01803
01804 while(l != &myrpt->links){
01805 if (l->name[0] == '0')
01806 {
01807 l = l->next;
01808 continue;
01809 }
01810
01811 if (!strcmp(l->name, digitbuf))
01812 break;
01813 l = l->next;
01814 }
01815 if (l != &myrpt->links){
01816 struct ast_frame wf;
01817
01818 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01819 l->retries = MAX_RETRIES + 1;
01820 l->disced = 1;
01821 ast_mutex_unlock(&myrpt->lock);
01822 wf.frametype = AST_FRAME_TEXT;
01823 wf.subclass = 0;
01824 wf.offset = 0;
01825 wf.mallocd = 1;
01826 wf.datalen = strlen(discstr) + 1;
01827 wf.samples = 0;
01828 wf.data = strdup(discstr);
01829 if (l->chan)
01830 {
01831 ast_write(l->chan,&wf);
01832 if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
01833 ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
01834 }
01835 rpt_telemetry(myrpt, COMPLETE, NULL);
01836 return DC_COMPLETE;
01837 }
01838 ast_mutex_unlock(&myrpt->lock);
01839 return DC_COMPLETE;
01840 case 2:
01841 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01842 strcpy(digitbuf,myrpt->lastlinknode);
01843 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01844 if (!val){
01845 if(strlen(digitbuf) >= myrpt->longestnode)
01846 return DC_ERROR;
01847 break;
01848 }
01849 strncpy(tmp,val,sizeof(tmp) - 1);
01850 s = tmp;
01851 s1 = strsep(&s,",");
01852 s2 = strsep(&s,",");
01853 ast_mutex_lock(&myrpt->lock);
01854 l = myrpt->links.next;
01855
01856 while(l != &myrpt->links){
01857 if (l->name[0] == '0')
01858 {
01859 l = l->next;
01860 continue;
01861 }
01862
01863 if (!strcmp(l->name, digitbuf))
01864 break;
01865 l = l->next;
01866 }
01867
01868 if (l != &myrpt->links)
01869 {
01870
01871 if ((!l->mode) || (!l->chan)) {
01872 ast_mutex_unlock(&myrpt->lock);
01873 rpt_telemetry(myrpt,REMALREADY,NULL);
01874 return DC_COMPLETE;
01875
01876 }
01877 ast_mutex_unlock(&myrpt->lock);
01878 if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
01879 l->retries = MAX_RETRIES + 1;
01880 l->disced = 2;
01881 modechange = 1;
01882 } else
01883 ast_mutex_unlock(&myrpt->lock);
01884 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01885
01886 l = malloc(sizeof(struct rpt_link));
01887 if (!l){
01888 ast_log(LOG_WARNING, "Unable to malloc\n");
01889 return DC_ERROR;
01890 }
01891
01892 memset((char *)l,0,sizeof(struct rpt_link));
01893 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
01894 tele = strchr(deststr,'/');
01895 if (!tele){
01896 fprintf(stderr,"link2:Dial number (%s) must be in format tech/number\n",deststr);
01897 return DC_ERROR;
01898 }
01899 *tele++ = 0;
01900 l->isremote = (s && ast_true(s));
01901 strncpy(l->name, digitbuf, MAXNODESTR - 1);
01902 l->chan = ast_request(deststr,AST_FORMAT_SLINEAR,tele,NULL);
01903 if (modechange) l->connected = 1;
01904 if (l->chan){
01905 ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
01906 ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
01907 l->chan->whentohangup = 0;
01908 l->chan->appl = "Apprpt";
01909 l->chan->data = "(Remote Rx)";
01910 if (option_verbose > 2)
01911 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
01912 deststr,tele,l->chan->name);
01913 if(l->chan->cid.cid_num)
01914 free(l->chan->cid.cid_num);
01915 l->chan->cid.cid_num = strdup(myrpt->name);
01916 ast_call(l->chan,tele,0);
01917 }
01918 else
01919 {
01920 rpt_telemetry(myrpt,CONNFAIL,l);
01921 free(l);
01922 if (option_verbose > 2)
01923 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
01924 deststr,tele,l->chan->name);
01925 return DC_ERROR;
01926 }
01927
01928 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
01929 if (!l->pchan){
01930 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
01931 ast_hangup(l->chan);
01932 free(l);
01933 return DC_ERROR;
01934 }
01935 ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
01936 ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
01937
01938 ci.chan = 0;
01939 ci.confno = myrpt->conf;
01940 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
01941
01942 if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
01943 {
01944 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
01945 ast_hangup(l->chan);
01946 ast_hangup(l->pchan);
01947 free(l);
01948 return DC_ERROR;
01949 }
01950 ast_mutex_lock(&myrpt->lock);
01951
01952 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
01953 ast_mutex_unlock(&myrpt->lock);
01954 rpt_telemetry(myrpt,COMPLETE,NULL);
01955 return DC_COMPLETE;
01956 case 3:
01957 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
01958 strcpy(digitbuf,myrpt->lastlinknode);
01959 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
01960 if (!val){
01961 if(strlen(digitbuf) >= myrpt->longestnode)
01962 return DC_ERROR;
01963 break;
01964 }
01965 strncpy(tmp,val,sizeof(tmp) - 1);
01966 s = tmp;
01967 s1 = strsep(&s,",");
01968 s2 = strsep(&s,",");
01969 ast_mutex_lock(&myrpt->lock);
01970 l = myrpt->links.next;
01971
01972 while(l != &myrpt->links){
01973 if (l->name[0] == '0')
01974 {
01975 l = l->next;
01976 continue;
01977 }
01978
01979 if (!strcmp(l->name, digitbuf))
01980 break;
01981 l = l->next;
01982 }
01983
01984 if (l != &myrpt->links){
01985
01986 if ((l->mode) || (!l->chan)) {
01987 ast_mutex_unlock(&myrpt->lock);
01988 rpt_telemetry(myrpt, REMALREADY, NULL);
01989 return DC_COMPLETE;
01990 }
01991 ast_mutex_unlock(&myrpt->lock);
01992 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
01993 l->retries = MAX_RETRIES + 1;
01994 l->disced = 2;
01995 modechange = 1;
01996 } else
01997 ast_mutex_unlock(&myrpt->lock);
01998 strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
01999
02000 l = malloc(sizeof(struct rpt_link));
02001 if (!l){
02002 ast_log(LOG_WARNING, "Unable to malloc\n");
02003 return(DC_ERROR);
02004 }
02005
02006 memset((char *)l,0,sizeof(struct rpt_link));
02007 l->mode = 1;
02008 l->outbound = 1;
02009 strncpy(l->name, digitbuf, MAXNODESTR - 1);
02010 l->isremote = (s && ast_true(s));
02011 if (modechange) l->connected = 1;
02012 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
02013 tele = strchr(deststr, '/');
02014 if (!tele){
02015 fprintf(stderr,"link3:Dial number (%s) must be in format tech/number\n",deststr);
02016 free(l);
02017 return DC_ERROR;
02018 }
02019 *tele++ = 0;
02020 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
02021 if (l->chan){
02022 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
02023 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
02024 l->chan->whentohangup = 0;
02025 l->chan->appl = "Apprpt";
02026 l->chan->data = "(Remote Rx)";
02027 if (option_verbose > 2)
02028 ast_verbose(VERBOSE_PREFIX_3 "rpt (remote) initiating call to %s/%s on %s\n",
02029 deststr, tele, l->chan->name);
02030 if(l->chan->cid.cid_num)
02031 free(l->chan->cid.cid_num);
02032 l->chan->cid.cid_num = strdup(myrpt->name);
02033 ast_call(l->chan,tele,999);
02034 }
02035 else{
02036 rpt_telemetry(myrpt,CONNFAIL,l);
02037 free(l);
02038 if (option_verbose > 2)
02039 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
02040 deststr,tele,l->chan->name);
02041 return DC_ERROR;
02042 }
02043
02044 l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
02045 if (!l->pchan){
02046 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
02047 ast_hangup(l->chan);
02048 free(l);
02049 return DC_ERROR;
02050 }
02051 ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
02052 ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
02053
02054 ci.chan = 0;
02055 ci.confno = myrpt->conf;
02056 ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
02057
02058 if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1)
02059 {
02060 ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
02061 ast_hangup(l->chan);
02062 ast_hangup(l->pchan);
02063 free(l);
02064 return DC_ERROR;
02065 }
02066 ast_mutex_lock(&myrpt->lock);
02067
02068 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
02069 ast_mutex_unlock(&myrpt->lock);
02070 rpt_telemetry(myrpt,COMPLETE,NULL);
02071 return DC_COMPLETE;
02072 case 4:
02073
02074
02075 if (((command_source != SOURCE_RPT) && (command_source != SOURCE_PHONE) && (command_source != SOURCE_DPHONE)) || (myrpt->links.next == &myrpt->links))
02076 return DC_COMPLETE;
02077
02078
02079 if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
02080
02081 rpt_telemetry(myrpt, REMALREADY, NULL);
02082 return DC_COMPLETE;
02083 }
02084 if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
02085 strcpy(digitbuf,myrpt->lastlinknode);
02086
02087 val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
02088 if (!val){
02089 if(strlen(digitbuf) >= myrpt->longestnode)
02090 return DC_ERROR;
02091 break;
02092
02093 }
02094 ast_mutex_lock(&myrpt->lock);
02095 strcpy(myrpt->lastlinknode,digitbuf);
02096 strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
02097 ast_mutex_unlock(&myrpt->lock);
02098 rpt_telemetry(myrpt, REMGO, NULL);
02099 return DC_COMPLETE;
02100
02101 case 5:
02102 rpt_telemetry(myrpt, STATUS, NULL);
02103 return DC_COMPLETE;
02104
02105
02106 case 6:
02107 l = myrpt->links.next;
02108
02109 while(l != &myrpt->links){
02110 if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
02111 l = l->next;
02112 }
02113 rpt_telemetry(myrpt, COMPLETE, NULL);
02114 break;
02115
02116 default:
02117 return DC_ERROR;
02118
02119 }
02120
02121 return DC_INDETERMINATE;
02122 }
02123
02124
02125
02126
02127
02128 static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02129 {
02130 pthread_attr_t attr;
02131
02132
02133 if (!myrpt->enable)
02134 return DC_ERROR;
02135
02136 if(debug)
02137 printf("@@@@ Autopatch up\n");
02138
02139 ast_mutex_lock(&myrpt->lock);
02140
02141
02142
02143 if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
02144 myrpt->mydtmf = myrpt->funcchar;
02145 }
02146 if (myrpt->callmode){
02147 ast_mutex_unlock(&myrpt->lock);
02148 return DC_COMPLETE;
02149 }
02150 myrpt->callmode = 1;
02151 myrpt->cidx = 0;
02152 myrpt->exten[myrpt->cidx] = 0;
02153 ast_mutex_unlock(&myrpt->lock);
02154 pthread_attr_init(&attr);
02155 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02156 ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
02157 return DC_COMPLETE;
02158 }
02159
02160
02161
02162
02163
02164 static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02165 {
02166 if (!myrpt->enable)
02167 return DC_ERROR;
02168
02169 if(debug)
02170 printf("@@@@ Autopatch down\n");
02171
02172 ast_mutex_lock(&myrpt->lock);
02173
02174 if (!myrpt->callmode){
02175 ast_mutex_unlock(&myrpt->lock);
02176 return DC_COMPLETE;
02177 }
02178
02179 myrpt->callmode = 0;
02180 ast_mutex_unlock(&myrpt->lock);
02181 rpt_telemetry(myrpt, TERM, NULL);
02182 return DC_COMPLETE;
02183 }
02184
02185
02186
02187
02188
02189 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02190 {
02191
02192 if(!param)
02193 return DC_ERROR;
02194
02195
02196 if (!myrpt->enable)
02197 return DC_ERROR;
02198
02199 if(debug)
02200 printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
02201
02202 switch(myatoi(param)){
02203 case 1:
02204 rpt_telemetry(myrpt, ID1, NULL);
02205 return DC_COMPLETE;
02206 case 2:
02207 rpt_telemetry(myrpt, STATS_TIME, NULL);
02208 return DC_COMPLETE;
02209 case 3:
02210 rpt_telemetry(myrpt, STATS_VERSION, NULL);
02211 default:
02212 return DC_ERROR;
02213 }
02214 return DC_INDETERMINATE;
02215 }
02216
02217
02218
02219
02220
02221 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
02222 {
02223 if(!param)
02224 return DC_ERROR;
02225
02226 switch(myatoi(param)){
02227 case 1:
02228 system("killall -9 asterisk");
02229 return DC_COMPLETE;
02230
02231 case 2:
02232 myrpt->enable = 1;
02233 rpt_telemetry(myrpt, ARB_ALPHA, (void *) "RPTENA");
02234 return DC_COMPLETE;
02235
02236 case 3:
02237 myrpt->enable = 0;
02238 return DC_COMPLETE;
02239
02240 case 4:
02241 rpt_telemetry(myrpt, TEST_TONE, NULL);
02242 return DC_COMPLETE;
02243
02244 case 5:
02245 myrpt->disgorgetime = time(NULL) + 10;
02246 return DC_COMPLETE;
02247
02248 case 6:
02249 if (command_source != SOURCE_PHONE) return DC_INDETERMINATE;
02250 return DC_DOKEY;
02251
02252 }
02253 return DC_INDETERMINATE;
02254 }
02255
02256
02257
02258
02259
02260 static int collect_function_digits(struct rpt *myrpt, char *digits,
02261 int command_source, struct rpt_link *mylink)
02262 {
02263 int i;
02264 char *stringp,*action,*param,*functiondigits;
02265 char function_table_name[30] = "";
02266 char workstring[80];
02267
02268 struct ast_variable *vp;
02269
02270 if(debug)
02271 printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
02272
02273 if (command_source == SOURCE_DPHONE) {
02274 if (!myrpt->dphone_functions) return DC_INDETERMINATE;
02275 strncpy(function_table_name, myrpt->dphone_functions, sizeof(function_table_name) - 1);
02276 }
02277 else if (command_source == SOURCE_PHONE) {
02278 if (!myrpt->phone_functions) return DC_INDETERMINATE;
02279 strncpy(function_table_name, myrpt->phone_functions, sizeof(function_table_name) - 1);
02280 }
02281 else if (command_source == SOURCE_LNK)
02282 strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1);
02283 else
02284 strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1);
02285 vp = ast_variable_browse(cfg, function_table_name);
02286 while(vp) {
02287 if(!strncasecmp(vp->name, digits, strlen(vp->name)))
02288 break;
02289 vp = vp->next;
02290 }
02291 if(!vp) {
02292 int n;
02293
02294 n = myrpt->longestfunc;
02295 if (command_source == SOURCE_LNK) n = myrpt->link_longestfunc;
02296 else
02297 if (command_source == SOURCE_PHONE) n = myrpt->phone_longestfunc;
02298 else
02299 if (command_source == SOURCE_DPHONE) n = myrpt->dphone_longestfunc;
02300
02301 if(strlen(digits) >= n)
02302 return DC_ERROR;
02303 else
02304 return DC_INDETERMINATE;
02305 }
02306
02307 strncpy(workstring, vp->value, sizeof(workstring) - 1 );
02308 stringp = workstring;
02309 action = strsep(&stringp, ",");
02310 param = stringp;
02311 if(debug)
02312 printf("@@@@ action: %s, param = %s\n",action, (param) ? param : "(null)");
02313
02314 for(i = 0 ; i < (sizeof(function_table)/sizeof(struct function_table_tag)); i++){
02315 if(!strncasecmp(action, function_table[i].action, strlen(action)))
02316 break;
02317 }
02318 if(debug)
02319 printf("@@@@ table index i = %d\n",i);
02320 if(i == (sizeof(function_table)/sizeof(struct function_table_tag))){
02321
02322 return DC_ERROR;
02323 }
02324 if(function_table[i].function == NULL){
02325
02326 if(debug)
02327 printf("@@@@ NULL for action: %s\n",action);
02328 return DC_ERROR;
02329 }
02330 functiondigits = digits + strlen(vp->name);
02331 return (*function_table[i].function)(myrpt, param, functiondigits, command_source, mylink);
02332 }
02333
02334
02335 static void handle_link_data(struct rpt *myrpt, struct rpt_link *mylink,
02336 char *str)
02337 {
02338 char tmp[300],cmd[300] = "",dest[300],src[300],c;
02339 int seq, res;
02340 struct rpt_link *l;
02341 struct ast_frame wf;
02342
02343 wf.frametype = AST_FRAME_TEXT;
02344 wf.subclass = 0;
02345 wf.offset = 0;
02346 wf.mallocd = 1;
02347 wf.datalen = strlen(str) + 1;
02348 wf.samples = 0;
02349
02350 strncpy(tmp,str,sizeof(tmp) - 1);
02351
02352 if (!strcmp(tmp,discstr))
02353 {
02354 mylink->disced = 1;
02355 mylink->retries = MAX_RETRIES + 1;
02356 ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
02357 return;
02358 }
02359 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
02360 {
02361 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
02362 return;
02363 }
02364 if (strcmp(cmd,"D"))
02365 {
02366 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
02367 return;
02368 }
02369
02370 if (dest[0] == '0')
02371 {
02372 strcpy(dest,myrpt->name);
02373 }
02374
02375
02376 if (strcmp(dest,myrpt->name))
02377 {
02378 l = myrpt->links.next;
02379
02380 while(l != &myrpt->links)
02381 {
02382 if (l->name[0] == '0')
02383 {
02384 l = l->next;
02385 continue;
02386 }
02387
02388 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
02389 {
02390 l = l->next;
02391 continue;
02392 }
02393
02394 if (!strcmp(l->name,dest))
02395 {
02396
02397 if (strcmp(l->name,src)) {
02398 wf.data = strdup(str);
02399 if (l->chan) ast_write(l->chan,&wf);
02400 }
02401 return;
02402 }
02403 l = l->next;
02404 }
02405 l = myrpt->links.next;
02406
02407 while(l != &myrpt->links)
02408 {
02409 if (l->name[0] == '0')
02410 {
02411 l = l->next;
02412 continue;
02413 }
02414
02415 if ((l == mylink) || (!strcmp(l->name,mylink->name)))
02416 {
02417 l = l->next;
02418 continue;
02419 }
02420
02421 if (strcmp(l->name,src)) {
02422 wf.data = strdup(str);
02423 if (l->chan) ast_write(l->chan,&wf);
02424 }
02425 l = l->next;
02426 }
02427 return;
02428 }
02429 ast_mutex_lock(&myrpt->lock);
02430 if (c == myrpt->endchar) myrpt->stopgen = 1;
02431 if (myrpt->callmode == 1)
02432 {
02433 myrpt->exten[myrpt->cidx++] = c;
02434 myrpt->exten[myrpt->cidx] = 0;
02435
02436 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02437 {
02438 myrpt->callmode = 2;
02439 rpt_telemetry(myrpt,PROC,NULL);
02440 }
02441
02442 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02443 {
02444
02445 myrpt->callmode = 4;
02446 }
02447 }
02448 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
02449 {
02450 myrpt->mydtmf = c;
02451 }
02452 if (c == myrpt->funcchar)
02453 {
02454 myrpt->rem_dtmfidx = 0;
02455 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02456 time(&myrpt->rem_dtmf_time);
02457 ast_mutex_unlock(&myrpt->lock);
02458 return;
02459 }
02460 else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
02461 {
02462 time(&myrpt->rem_dtmf_time);
02463 if (myrpt->rem_dtmfidx < MAXDTMF)
02464 {
02465 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
02466 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02467
02468 ast_mutex_unlock(&myrpt->lock);
02469 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
02470 res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
02471 ast_mutex_lock(&myrpt->lock);
02472
02473 switch(res){
02474
02475 case DC_INDETERMINATE:
02476 break;
02477
02478 case DC_REQ_FLUSH:
02479 myrpt->rem_dtmfidx = 0;
02480 myrpt->rem_dtmfbuf[0] = 0;
02481 break;
02482
02483
02484 case DC_COMPLETE:
02485 myrpt->rem_dtmfbuf[0] = 0;
02486 myrpt->rem_dtmfidx = -1;
02487 myrpt->rem_dtmf_time = 0;
02488 break;
02489
02490 case DC_ERROR:
02491 default:
02492 myrpt->rem_dtmfbuf[0] = 0;
02493 myrpt->rem_dtmfidx = -1;
02494 myrpt->rem_dtmf_time = 0;
02495 break;
02496 }
02497 }
02498
02499 }
02500 ast_mutex_unlock(&myrpt->lock);
02501 return;
02502 }
02503
02504 static void handle_link_phone_dtmf(struct rpt *myrpt, struct rpt_link *mylink,
02505 char c)
02506 {
02507
02508 char cmd[300];
02509 int res;
02510
02511 ast_mutex_lock(&myrpt->lock);
02512 if (c == myrpt->endchar)
02513 {
02514 if (mylink->lastrx)
02515 {
02516 mylink->lastrx = 0;
02517 ast_mutex_unlock(&myrpt->lock);
02518 return;
02519 }
02520 myrpt->stopgen = 1;
02521 if (myrpt->cmdnode[0])
02522 {
02523 myrpt->cmdnode[0] = 0;
02524 myrpt->dtmfidx = -1;
02525 myrpt->dtmfbuf[0] = 0;
02526 ast_mutex_unlock(&myrpt->lock);
02527 rpt_telemetry(myrpt,COMPLETE,NULL);
02528 ast_mutex_unlock(&myrpt->lock);
02529 return;
02530 }
02531 }
02532 if (myrpt->cmdnode[0])
02533 {
02534 ast_mutex_unlock(&myrpt->lock);
02535 send_link_dtmf(myrpt,c);
02536 return;
02537 }
02538 if (myrpt->callmode == 1)
02539 {
02540 myrpt->exten[myrpt->cidx++] = c;
02541 myrpt->exten[myrpt->cidx] = 0;
02542
02543 if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02544 {
02545 myrpt->callmode = 2;
02546 rpt_telemetry(myrpt,PROC,NULL);
02547 }
02548
02549 if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
02550 {
02551
02552 myrpt->callmode = 4;
02553 }
02554 }
02555 if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
02556 {
02557 myrpt->mydtmf = c;
02558 }
02559 if (c == myrpt->funcchar)
02560 {
02561 myrpt->rem_dtmfidx = 0;
02562 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02563 time(&myrpt->rem_dtmf_time);
02564 ast_mutex_unlock(&myrpt->lock);
02565 return;
02566 }
02567 else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
02568 {
02569 time(&myrpt->rem_dtmf_time);
02570 if (myrpt->rem_dtmfidx < MAXDTMF)
02571 {
02572 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
02573 myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
02574
02575 ast_mutex_unlock(&myrpt->lock);
02576 strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
02577 res = collect_function_digits(myrpt, cmd,
02578 ((mylink->phonemode == 2) ? SOURCE_DPHONE : SOURCE_PHONE), mylink);
02579 ast_mutex_lock(&myrpt->lock);
02580
02581 switch(res){
02582
02583 case DC_INDETERMINATE:
02584 break;
02585
02586 case DC_DOKEY:
02587 mylink->lastrx = 1;
02588 break;
02589
02590 case DC_REQ_FLUSH:
02591 myrpt->rem_dtmfidx = 0;
02592 myrpt->rem_dtmfbuf[0] = 0;
02593 break;
02594
02595
02596 case DC_COMPLETE:
02597 myrpt->rem_dtmfbuf[0] = 0;
02598 myrpt->rem_dtmfidx = -1;
02599 myrpt->rem_dtmf_time = 0;
02600 break;
02601
02602 case DC_ERROR:
02603 default:
02604 myrpt->rem_dtmfbuf[0] = 0;
02605 myrpt->rem_dtmfidx = -1;
02606 myrpt->rem_dtmf_time = 0;
02607 break;
02608 }
02609 }
02610
02611 }
02612 ast_mutex_unlock(&myrpt->lock);
02613 return;
02614 }
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647 static int rbi_mhztoband(char *str)
02648 {
02649 int i;
02650
02651 i = atoi(str) / 10;
02652 switch(i)
02653 {
02654 case 2:
02655 return 10;
02656 case 5:
02657 return 11;
02658 case 14:
02659 return 2;
02660 case 22:
02661 return 3;
02662 case 44:
02663 return 4;
02664 case 124:
02665 return 0;
02666 case 125:
02667 return 1;
02668 case 126:
02669 return 8;
02670 case 127:
02671 return 5;
02672 case 128:
02673 return 6;
02674 case 129:
02675 return 7;
02676 default:
02677 break;
02678 }
02679 return -1;
02680 }
02681
02682
02683 static int rbi_pltocode(char *str)
02684 {
02685 int i;
02686 char *s;
02687
02688 s = strchr(str,'.');
02689 i = 0;
02690 if (s) i = atoi(s + 1);
02691 i += atoi(str) * 10;
02692 switch(i)
02693 {
02694 case 670:
02695 return 0;
02696 case 719:
02697 return 1;
02698 case 744:
02699 return 2;
02700 case 770:
02701 return 3;
02702 case 797:
02703 return 4;
02704 case 825:
02705 return 5;
02706 case 854:
02707 return 6;
02708 case 885:
02709 return 7;
02710 case 915:
02711 return 8;
02712 case 948:
02713 return 9;
02714 case 974:
02715 return 10;
02716 case 1000:
02717 return 11;
02718 case 1035:
02719 return 12;
02720 case 1072:
02721 return 13;
02722 case 1109:
02723 return 14;
02724 case 1148:
02725 return 15;
02726 case 1188:
02727 return 16;
02728 case 1230:
02729 return 17;
02730 case 1273:
02731 return 18;
02732 case 1318:
02733 return 19;
02734 case 1365:
02735 return 20;
02736 case 1413:
02737 return 21;
02738 case 1462:
02739 return 22;
02740 case 1514:
02741 return 23;
02742 case 1567:
02743 return 24;
02744 case 1622:
02745 return 25;
02746 case 1679:
02747 return 26;
02748 case 1738:
02749 return 27;
02750 case 1799:
02751 return 28;
02752 case 1862:
02753 return 29;
02754 case 1928:
02755 return 30;
02756 case 2035:
02757 return 31;
02758 case 2107:
02759 return 32;
02760 case 2181:
02761 return 33;
02762 case 2257:
02763 return 34;
02764 case 2336:
02765 return 35;
02766 case 2418:
02767 return 36;
02768 case 2503:
02769 return 37;
02770 }
02771 return -1;
02772 }
02773
02774
02775
02776
02777
02778 static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
02779 {
02780 int i,j;
02781 unsigned char od,d;
02782 static volatile long long delayvar;
02783
02784 for(i = 0 ; i < 5 ; i++){
02785 od = *data++;
02786 for(j = 0 ; j < 8 ; j++){
02787 d = od & 1;
02788 outb(d,myrpt->iobase);
02789
02790 for(delayvar = 1; delayvar < 15000; delayvar++);
02791 od >>= 1;
02792 outb(d | 2,myrpt->iobase);
02793
02794 for(delayvar = 1; delayvar < 30000; delayvar++);
02795 outb(d,myrpt->iobase);
02796
02797 for(delayvar = 1; delayvar < 10000; delayvar++);
02798 }
02799 }
02800
02801 for(delayvar = 1; delayvar < 50000; delayvar++);
02802 }
02803
02804 static void rbi_out(struct rpt *myrpt,unsigned char *data)
02805 {
02806 struct zt_radio_param r;
02807
02808 memset(&r,0,sizeof(struct zt_radio_param));
02809 r.radpar = ZT_RADPAR_REMMODE;
02810 r.data = ZT_RADPAR_REM_RBI1;
02811
02812 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
02813 {
02814 rbi_out_parallel(myrpt,data);
02815 return;
02816 }
02817 r.radpar = ZT_RADPAR_REMCOMMAND;
02818 memcpy(&r.data,data,5);
02819 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
02820 {
02821 ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name);
02822 return;
02823 }
02824 }
02825
02826 static int serial_remote_io(struct rpt *myrpt, char *txbuf, int txbytes, char *rxbuf,
02827 int rxmaxbytes, int asciiflag)
02828 {
02829 int i;
02830 struct zt_radio_param prm;
02831
02832 if(debug){
02833 printf("String output was: ");
02834 for(i = 0; i < txbytes; i++)
02835 printf("%02X ", (unsigned char ) txbuf[i]);
02836 printf("\n");
02837 }
02838
02839 prm.radpar = ZT_RADPAR_REMMODE;
02840 if (asciiflag) prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
02841 else prm.data = ZT_RADPAR_REM_SERIAL;
02842 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
02843 prm.radpar = ZT_RADPAR_REMCOMMAND;
02844 prm.data = rxmaxbytes;
02845 memcpy(prm.buf,txbuf,txbytes);
02846 prm.index = txbytes;
02847 if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
02848 if (rxbuf)
02849 {
02850 *rxbuf = 0;
02851 memcpy(rxbuf,prm.buf,prm.index);
02852 }
02853 return(prm.index);
02854 }
02855
02856 static int setrbi(struct rpt *myrpt)
02857 {
02858 char tmp[MAXREMSTR] = "",rbicmd[5],*s;
02859 int band,txoffset = 0,txpower = 0,txpl;
02860
02861
02862 if (!myrpt->remote) return(0);
02863
02864 if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
02865 strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
02866 s = strchr(tmp,'.');
02867
02868
02869 if (s == NULL){
02870 if(debug)
02871 printf("@@@@ Frequency needs a decimal\n");
02872 return -1;
02873 }
02874
02875 *s++ = 0;
02876 if (strlen(tmp) < 2){
02877 if(debug)
02878 printf("@@@@ Bad MHz digits: %s\n", tmp);
02879 return -1;
02880 }
02881
02882 if (strlen(s) < 3){
02883 if(debug)
02884 printf("@@@@ Bad KHz digits: %s\n", s);
02885 return -1;
02886 }
02887
02888 if ((s[2] != '0') && (s[2] != '5')){
02889 if(debug)
02890 printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
02891 return -1;
02892 }
02893
02894 band = rbi_mhztoband(tmp);
02895 if (band == -1){
02896 if(debug)
02897 printf("@@@@ Bad Band: %s\n", tmp);
02898 return -1;
02899 }
02900
02901 txpl = rbi_pltocode(myrpt->txpl);
02902
02903 if (txpl == -1){
02904 if(debug)
02905 printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
02906 return -1;
02907 }
02908
02909
02910 switch(myrpt->offset)
02911 {
02912 case REM_MINUS:
02913 txoffset = 0;
02914 break;
02915 case REM_PLUS:
02916 txoffset = 0x10;
02917 break;
02918 case REM_SIMPLEX:
02919 txoffset = 0x20;
02920 break;
02921 }
02922 switch(myrpt->powerlevel)
02923 {
02924 case REM_LOWPWR:
02925 txpower = 0;
02926 break;
02927 case REM_MEDPWR:
02928 txpower = 0x20;
02929 break;
02930 case REM_HIPWR:
02931 txpower = 0x10;
02932 break;
02933 }
02934 rbicmd[0] = 0;
02935 rbicmd[1] = band | txpower | 0xc0;
02936 rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
02937 if (s[2] == '5') rbicmd[2] |= 0x40;
02938 rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
02939 rbicmd[4] = txpl;
02940 if (myrpt->txplon) rbicmd[4] |= 0x40;
02941 if (myrpt->rxplon) rbicmd[4] |= 0x80;
02942 rbi_out(myrpt,rbicmd);
02943 return 0;
02944 }
02945
02946
02947
02948
02949
02950 static int check_freq_rbi(int m, int d, int *defmode)
02951 {
02952 int dflmd = REM_MODE_FM;
02953
02954 if(m == 50){
02955 if(d < 10100)
02956 return -1;
02957 }
02958 else if((m >= 51) && ( m < 54)){
02959 ;
02960 }
02961 else if(m == 144){
02962 if(d < 10100)
02963 return -1;
02964 }
02965 else if((m >= 145) && (m < 148)){
02966 ;
02967 }
02968 else if((m >= 222) && (m < 225)){
02969 ;
02970 }
02971 else if((m >= 430) && (m < 450)){
02972 ;
02973 }
02974 else if((m >= 1240) && (m < 1300)){
02975 ;
02976 }
02977 else
02978 return -1;
02979
02980 if(defmode)
02981 *defmode = dflmd;
02982
02983
02984 return 0;
02985 }
02986
02987
02988
02989
02990
02991 static int split_freq(char *mhz, char *decimals, char *freq)
02992 {
02993 char freq_copy[MAXREMSTR];
02994 char *decp;
02995
02996 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
02997 if(decp){
02998 *decp++ = 0;
02999 strncpy(mhz, freq_copy, MAXREMSTR);
03000 strcpy(decimals, "00000");
03001 strncpy(decimals, decp, strlen(decp));
03002 decimals[5] = 0;
03003 return 0;
03004 }
03005 else
03006 return -1;
03007
03008 }
03009
03010
03011
03012
03013
03014 static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
03015 {
03016 char freq_copy[MAXREMSTR];
03017 char *decp;
03018
03019 decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
03020 if(decp){
03021 *decp++ = 0;
03022 strncpy(hertz, freq_copy, MAXREMSTR);
03023 strncpy(decimal, decp, strlen(decp));
03024 decimal[strlen(decp)] = '\0';
03025 return 0;
03026 }
03027 else
03028 return -1;
03029 }
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041 static int check_freq_ft897(int m, int d, int *defmode)
03042 {
03043 int dflmd = REM_MODE_FM;
03044
03045 if(m == 1){
03046 dflmd = REM_MODE_LSB;
03047 if(d < 80001)
03048 return -1;
03049 }
03050 else if(m == 3){
03051 dflmd = REM_MODE_LSB;
03052 if(d < 75001)
03053 return -1;
03054 }
03055 else if(m == 7){
03056 dflmd = REM_MODE_LSB;
03057 if((d < 15001) || (d > 29999))
03058 return -1;
03059 }
03060 else if(m == 14){
03061 dflmd = REM_MODE_USB;
03062 if((d < 15001) || (d > 34999))
03063 return -1;
03064 }
03065 else if(m == 18){
03066 dflmd = REM_MODE_USB;
03067 if((d < 11001) || (d > 16797))
03068 return -1;
03069 }
03070 else if(m == 21){
03071 dflmd = REM_MODE_USB;
03072 if((d < 20001) || (d > 44999))
03073 return -1;
03074 }
03075 else if(m == 24){
03076 dflmd = REM_MODE_USB;
03077 if((d < 93001) || (d > 98999))
03078 return -1;
03079 }
03080 else if(m == 28){
03081 dflmd = REM_MODE_USB;
03082 if(d < 30001)
03083 return -1;
03084 }
03085 else if(m == 29){
03086 if(d >= 51000)
03087 dflmd = REM_MODE_FM;
03088 else
03089 dflmd = REM_MODE_USB;
03090 if(d > 69999)
03091 return -1;
03092 }
03093 else if(m == 50){
03094 if(d < 10100)
03095 return -1;
03096 if(d >= 30000)
03097 dflmd = REM_MODE_FM;
03098 else
03099 dflmd = REM_MODE_USB;
03100
03101 }
03102 else if((m >= 51) && ( m < 54)){
03103 dflmd = REM_MODE_FM;
03104 }
03105 else if(m == 144){
03106 if(d < 10100)
03107 return -1;
03108 if(d >= 30000)
03109 dflmd = REM_MODE_FM;
03110 else
03111 dflmd = REM_MODE_USB;
03112 }
03113 else if((m >= 145) && (m < 148)){
03114 dflmd = REM_MODE_FM;
03115 }
03116 else if((m >= 430) && (m < 450)){
03117 if(m < 438)
03118 dflmd = REM_MODE_USB;
03119 else
03120 dflmd = REM_MODE_FM;
03121 ;
03122 }
03123 else
03124 return -1;
03125
03126 if(defmode)
03127 *defmode = dflmd;
03128
03129 return 0;
03130 }
03131
03132
03133
03134
03135
03136 static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
03137 {
03138 char mhz[MAXREMSTR];
03139 char decimals[MAXREMSTR];
03140 unsigned char cmdstr[5];
03141 int fd,m,d;
03142
03143 fd = 0;
03144 if(debug)
03145 printf("New frequency: %s\n",newfreq);
03146
03147 if(split_freq(mhz, decimals, newfreq))
03148 return -1;
03149
03150 m = atoi(mhz);
03151 d = atoi(decimals);
03152
03153
03154
03155 cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);
03156 cmdstr[1] = ((m % 10) << 4) + (d / 10000);
03157 cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);
03158 cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);
03159 cmdstr[4] = 0x01;
03160
03161 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03162
03163 }
03164
03165
03166
03167 static int simple_command_ft897(struct rpt *myrpt, char command)
03168 {
03169 unsigned char cmdstr[5];
03170
03171 memset(cmdstr, 0, 5);
03172
03173 cmdstr[4] = command;
03174
03175 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03176
03177 }
03178
03179
03180
03181 static int set_offset_ft897(struct rpt *myrpt, char offset)
03182 {
03183 unsigned char cmdstr[5];
03184
03185 memset(cmdstr, 0, 5);
03186
03187 switch(offset){
03188 case REM_SIMPLEX:
03189 cmdstr[0] = 0x89;
03190 break;
03191
03192 case REM_MINUS:
03193 cmdstr[0] = 0x09;
03194 break;
03195
03196 case REM_PLUS:
03197 cmdstr[0] = 0x49;
03198 break;
03199
03200 default:
03201 return -1;
03202 }
03203
03204 cmdstr[4] = 0x09;
03205
03206 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03207 }
03208
03209
03210
03211 static int set_mode_ft897(struct rpt *myrpt, char newmode)
03212 {
03213 unsigned char cmdstr[5];
03214
03215 memset(cmdstr, 0, 5);
03216
03217 switch(newmode){
03218 case REM_MODE_FM:
03219 cmdstr[0] = 0x08;
03220 break;
03221
03222 case REM_MODE_USB:
03223 cmdstr[0] = 0x01;
03224 break;
03225
03226 case REM_MODE_LSB:
03227 cmdstr[0] = 0x00;
03228 break;
03229
03230 case REM_MODE_AM:
03231 cmdstr[0] = 0x04;
03232 break;
03233
03234 default:
03235 return -1;
03236 }
03237 cmdstr[4] = 0x07;
03238
03239 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03240 }
03241
03242
03243
03244 static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
03245 {
03246 unsigned char cmdstr[5];
03247
03248 memset(cmdstr, 0, 5);
03249
03250 if(rxplon && txplon)
03251 cmdstr[0] = 0x2A;
03252 else if (!rxplon && txplon)
03253 cmdstr[0] = 0x4A;
03254 else if (rxplon && !txplon)
03255 cmdstr[0] = 0x3A;
03256 else
03257 cmdstr[0] = 0x8A;
03258
03259 cmdstr[4] = 0x0A;
03260
03261 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03262 }
03263
03264
03265
03266
03267 static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
03268 {
03269 unsigned char cmdstr[5];
03270 char hertz[MAXREMSTR],decimal[MAXREMSTR];
03271 int h,d;
03272
03273 memset(cmdstr, 0, 5);
03274
03275 if(split_ctcss_freq(hertz, decimal, txtone))
03276 return -1;
03277
03278 h = atoi(hertz);
03279 d = atoi(decimal);
03280
03281 cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
03282 cmdstr[1] = ((h % 10) << 4) + (d % 10);
03283
03284 if(rxtone){
03285
03286 if(split_ctcss_freq(hertz, decimal, rxtone))
03287 return -1;
03288
03289 h = atoi(hertz);
03290 d = atoi(decimal);
03291
03292 cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
03293 cmdstr[3] = ((h % 10) << 4) + (d % 10);
03294 }
03295 cmdstr[4] = 0x0B;
03296
03297 return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
03298 }
03299
03300
03301
03302 static int set_ft897(struct rpt *myrpt)
03303 {
03304 int res;
03305
03306 if(debug)
03307 printf("@@@@ lock on\n");
03308
03309 res = simple_command_ft897(myrpt, 0x00);
03310
03311 if(debug)
03312 printf("@@@@ ptt off\n");
03313
03314 if(!res)
03315 res = simple_command_ft897(myrpt, 0x88);
03316
03317 if(debug)
03318 printf("Modulation mode\n");
03319
03320 if(!res)
03321 res = set_mode_ft897(myrpt, myrpt->remmode);
03322
03323 if(debug)
03324 printf("Split off\n");
03325
03326 if(!res)
03327 simple_command_ft897(myrpt, 0x82);
03328
03329 if(debug)
03330 printf("Frequency\n");
03331
03332 if(!res)
03333 res = set_freq_ft897(myrpt, myrpt->freq);
03334 if((myrpt->remmode == REM_MODE_FM)){
03335 if(debug)
03336 printf("Offset\n");
03337 if(!res)
03338 res = set_offset_ft897(myrpt, myrpt->offset);
03339 if((!res)&&(myrpt->rxplon || myrpt->txplon)){
03340 if(debug)
03341 printf("CTCSS tone freqs.\n");
03342 res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl);
03343 }
03344 if(!res){
03345 if(debug)
03346 printf("CTCSS mode\n");
03347 res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon);
03348 }
03349 }
03350 if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
03351 if(debug)
03352 printf("Clarifier off\n");
03353 simple_command_ft897(myrpt, 0x85);
03354 }
03355 return res;
03356 }
03357
03358 static int closerem_ft897(struct rpt *myrpt)
03359 {
03360 simple_command_ft897(myrpt, 0x88);
03361 return 0;
03362 }
03363
03364
03365
03366
03367
03368
03369
03370 static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
03371 {
03372 int m,d;
03373 char mhz[MAXREMSTR], decimals[MAXREMSTR];
03374
03375 if(debug)
03376 printf("Before bump: %s\n", myrpt->freq);
03377
03378 if(split_freq(mhz, decimals, myrpt->freq))
03379 return -1;
03380
03381 m = atoi(mhz);
03382 d = atoi(decimals);
03383
03384 d += (interval / 10);
03385 if(d < 0){
03386 m--;
03387 d += 100000;
03388 }
03389 else if(d >= 100000){
03390 m++;
03391 d -= 100000;
03392 }
03393
03394 if(check_freq_ft897(m, d, NULL)){
03395 if(debug)
03396 printf("Bump freq invalid\n");
03397 return -1;
03398 }
03399
03400 snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
03401
03402 if(debug)
03403 printf("After bump: %s\n", myrpt->freq);
03404
03405 return set_freq_ft897(myrpt, myrpt->freq);
03406 }
03407
03408
03409
03410
03411
03412
03413
03414 static int setrem(struct rpt *myrpt)
03415 {
03416 if(!strcmp(myrpt->remote, remote_rig_ft897))
03417 return set_ft897(myrpt);
03418 else if(!strcmp(myrpt->remote, remote_rig_rbi))
03419 return setrbi(myrpt);
03420 else
03421 return -1;
03422 }
03423
03424 static int closerem(struct rpt *myrpt)
03425 {
03426 if(!strcmp(myrpt->remote, remote_rig_ft897))
03427 return closerem_ft897(myrpt);
03428 else
03429 return 0;
03430 }
03431
03432
03433
03434
03435
03436 static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
03437 {
03438 if(!strcmp(myrpt->remote, remote_rig_ft897))
03439 return check_freq_ft897(m, d, defmode);
03440 else if(!strcmp(myrpt->remote, remote_rig_rbi))
03441 return check_freq_rbi(m, d, defmode);
03442 else
03443 return -1;
03444 }
03445
03446
03447
03448
03449
03450 static int multimode_capable(struct rpt *myrpt)
03451 {
03452 if(!strcmp(myrpt->remote, remote_rig_ft897))
03453 return 1;
03454 return 0;
03455 }
03456
03457
03458
03459
03460
03461 static int multimode_bump_freq(struct rpt *myrpt, int interval)
03462 {
03463 if(!strcmp(myrpt->remote, remote_rig_ft897))
03464 return multimode_bump_freq_ft897(myrpt, interval);
03465 else
03466 return -1;
03467 }
03468
03469
03470
03471
03472
03473
03474 static void stop_scan(struct rpt *myrpt, int flag)
03475 {
03476 myrpt->hfscanmode = 0;
03477 myrpt->hfscanstatus = ((flag) ? -2 : -1);
03478 }
03479
03480
03481
03482
03483
03484
03485 static int service_scan(struct rpt *myrpt)
03486 {
03487 int res, interval;
03488 char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
03489
03490 switch(myrpt->hfscanmode){
03491
03492 case HF_SCAN_DOWN_SLOW:
03493 interval = -10;
03494 break;
03495
03496 case HF_SCAN_DOWN_QUICK:
03497 interval = -50;
03498 break;
03499
03500 case HF_SCAN_DOWN_FAST:
03501 interval = -200;
03502 break;
03503
03504 case HF_SCAN_UP_SLOW:
03505 interval = 10;
03506 break;
03507
03508 case HF_SCAN_UP_QUICK:
03509 interval = 50;
03510 break;
03511
03512 case HF_SCAN_UP_FAST:
03513 interval = 200;
03514 break;
03515
03516 default:
03517 myrpt->hfscanmode = 0;
03518 return -1;
03519 }
03520
03521 res = split_freq(mhz, decimals, myrpt->freq);
03522
03523 if(!res){
03524 k100 =decimals[0];
03525 k10 = decimals[1];
03526 res = multimode_bump_freq(myrpt, interval);
03527 }
03528
03529 if(!res)
03530 res = split_freq(mhz, decimals, myrpt->freq);
03531
03532
03533 if(res){
03534 stop_scan(myrpt,1);
03535 return -1;
03536 }
03537
03538
03539 if(k10 != decimals[1]){
03540 int myhund = (interval < 0) ? k100 : decimals[0];
03541 int myten = (interval < 0) ? k10 : decimals[1];
03542 myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
03543 }
03544 return res;
03545
03546 }
03547
03548
03549 static int rmt_telem_start(struct rpt *myrpt, struct ast_channel *chan, int delay)
03550 {
03551 myrpt->remotetx = 0;
03552 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
03553 if (!myrpt->remoterx)
03554 ast_indicate(chan,AST_CONTROL_RADIO_KEY);
03555 if (ast_safe_sleep(chan, delay) == -1)
03556 return -1;
03557 return 0;
03558 }
03559
03560
03561 static int rmt_telem_finish(struct rpt *myrpt, struct ast_channel *chan)
03562 {
03563
03564 struct zt_params par;
03565
03566 if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
03567 {
03568 return -1;
03569
03570 }
03571 if (!par.rxisoffhook)
03572 {
03573 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
03574 myrpt->remoterx = 0;
03575 }
03576 else
03577 {
03578 myrpt->remoterx = 1;
03579 }
03580 return 0;
03581 }
03582
03583
03584 static int rmt_sayfile(struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
03585 {
03586 int res;
03587
03588 res = rmt_telem_start(myrpt, chan, delay);
03589
03590 if(!res)
03591 res = sayfile(chan, filename);
03592
03593 if(!res)
03594 res = rmt_telem_finish(myrpt, chan);
03595 return res;
03596 }
03597
03598 static int rmt_saycharstr(struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
03599 {
03600 int res;
03601
03602 res = rmt_telem_start(myrpt, chan, delay);
03603
03604 if(!res)
03605 res = saycharstr(chan, charstr);
03606
03607 if(!res)
03608 res = rmt_telem_finish(myrpt, chan);
03609 return res;
03610 }
03611
03612
03613
03614
03615
03616
03617
03618 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
03619 {
03620 char *s,*s1,*s2,*val;
03621 int i,j,ht,k,l,ls2,m,d,res,offset,offsave, modesave, defmode;
03622 char multimode = 0;
03623 char oc;
03624 char tmp[20], freq[20] = "", savestr[20] = "";
03625 char mhz[MAXREMSTR], decimals[MAXREMSTR];
03626 struct ast_channel *mychannel;
03627
03628 if((!param) || (command_source == SOURCE_RPT) || (command_source == SOURCE_LNK))
03629 return DC_ERROR;
03630
03631 multimode = multimode_capable(myrpt);
03632
03633 mychannel = myrpt->remchannel;
03634
03635
03636 switch(myatoi(param)){
03637
03638 case 1:
03639 if(strlen(digitbuf) < 2)
03640 break;
03641
03642 for(i = 0 ; i < 2 ; i++){
03643 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03644 return DC_ERROR;
03645 }
03646
03647 val = ast_variable_retrieve(cfg, MEMORY, digitbuf);
03648 if (!val){
03649 if (ast_safe_sleep(mychannel,1000) == -1)
03650 return DC_ERROR;
03651 sayfile(mychannel,"rpt/memory_notfound");
03652 return DC_COMPLETE;
03653 }
03654 strncpy(tmp,val,sizeof(tmp) - 1);
03655 s = strchr(tmp,',');
03656 if (!s)
03657 return DC_ERROR;
03658 *s++ = 0;
03659 s1 = strchr(s,',');
03660 if (!s1)
03661 return DC_ERROR;
03662 *s1++ = 0;
03663 strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
03664 strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
03665 strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
03666 myrpt->remmode = REM_MODE_FM;
03667 myrpt->offset = REM_SIMPLEX;
03668 myrpt->powerlevel = REM_MEDPWR;
03669 myrpt->txplon = myrpt->rxplon = 0;
03670 while(*s1)
03671 {
03672 switch(*s1++){
03673 case 'A':
03674 case 'a':
03675 strcpy(myrpt->rxpl, "100.0");
03676 strcpy(myrpt->txpl, "100.0");
03677 myrpt->remmode = REM_MODE_AM;
03678 break;
03679
03680 case 'B':
03681 case 'b':
03682 strcpy(myrpt->rxpl, "100.0");
03683 strcpy(myrpt->txpl, "100.0");
03684 myrpt->remmode = REM_MODE_LSB;
03685 break;
03686
03687 case 'F':
03688 myrpt->remmode = REM_MODE_FM;
03689 break;
03690
03691 case 'L':
03692 case 'l':
03693 myrpt->powerlevel = REM_LOWPWR;
03694 break;
03695 case 'H':
03696 case 'h':
03697 myrpt->powerlevel = REM_HIPWR;
03698 break;
03699
03700 case 'M':
03701 case 'm':
03702 myrpt->powerlevel = REM_MEDPWR;
03703 break;
03704
03705 case '-':
03706 myrpt->offset = REM_MINUS;
03707 break;
03708
03709 case '+':
03710 myrpt->offset = REM_PLUS;
03711 break;
03712
03713 case 'S':
03714 case 's':
03715 myrpt->offset = REM_SIMPLEX;
03716 break;
03717
03718 case 'T':
03719 case 't':
03720 myrpt->txplon = 1;
03721 break;
03722
03723 case 'R':
03724 case 'r':
03725 myrpt->rxplon = 1;
03726 break;
03727
03728 case 'U':
03729 case 'u':
03730 strcpy(myrpt->rxpl, "100.0");
03731 strcpy(myrpt->txpl, "100.0");
03732 myrpt->remmode = REM_MODE_USB;
03733 break;
03734 }
03735 }
03736
03737
03738 if (setrem(myrpt) == -1)
03739 return DC_ERROR;
03740
03741
03742 return DC_COMPLETE;
03743
03744 case 2:
03745
03746
03747 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
03748 if(digitbuf[i] == '*'){
03749 j++;
03750 continue;
03751 }
03752 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03753 goto invalid_freq;
03754 else{
03755 if(j == 0)
03756 l++;
03757 if(j == 1)
03758 k++;
03759 }
03760 }
03761
03762 i = strlen(digitbuf) - 1;
03763 if(multimode){
03764 if((j > 2) || (l > 3) || (k > 6))
03765 goto invalid_freq;
03766 }
03767 else{
03768 if((j > 2) || (l > 4) || (k > 3))
03769 goto invalid_freq;
03770 }
03771
03772
03773
03774 if(j < 2)
03775 break;
03776
03777
03778
03779 strncpy(tmp, digitbuf ,sizeof(tmp) - 1);
03780
03781 s = tmp;
03782 s1 = strsep(&s, "*");
03783 s2 = strsep(&s,"*");
03784 ls2 = strlen(s2);
03785
03786 switch(ls2){
03787 case 1:
03788 ht = 0;
03789 k = 100 * atoi(s2);
03790 break;
03791
03792 case 2:
03793 ht = 0;
03794 k = 10 * atoi(s2);
03795 break;
03796
03797 case 3:
03798 if(!multimode){
03799 if((s2[2] != '0')&&(s2[2] != '5'))
03800 goto invalid_freq;
03801 }
03802 ht = 0;
03803 k = atoi(s2);
03804 break;
03805 case 4:
03806 k = atoi(s2)/10;
03807 ht = 10 * (atoi(s2+(ls2-1)));
03808 break;
03809
03810 case 5:
03811 k = atoi(s2)/100;
03812 ht = (atoi(s2+(ls2-2)));
03813 break;
03814
03815 default:
03816 goto invalid_freq;
03817 }
03818
03819
03820
03821 snprintf(freq, sizeof(freq), "%s.%03d%02d",s1, k, ht);
03822
03823 if(debug)
03824 printf("New frequency: %s\n", freq);
03825
03826 split_freq(mhz, decimals, freq);
03827 m = atoi(mhz);
03828 d = atoi(decimals);
03829
03830 if(check_freq(myrpt, m, d, &defmode))
03831 goto invalid_freq;
03832
03833
03834 if((defmode == REM_MODE_FM) && (digitbuf[i] == '*'))
03835 break;
03836
03837
03838 offset = REM_SIMPLEX;
03839
03840 if(defmode == REM_MODE_FM){
03841 oc = *s;
03842
03843 if (oc){
03844 switch(oc){
03845 case '1':
03846 offset = REM_MINUS;
03847 break;
03848
03849 case '2':
03850 offset = REM_SIMPLEX;
03851 break;
03852
03853 case '3':
03854 offset = REM_PLUS;
03855 break;
03856
03857 default:
03858 goto invalid_freq;
03859 }
03860 }
03861 }
03862 offsave = myrpt->offset;
03863 modesave = myrpt->remmode;
03864 strncpy(savestr, myrpt->freq, sizeof(savestr) - 1);
03865 strncpy(myrpt->freq, freq, sizeof(myrpt->freq) - 1);
03866 myrpt->offset = offset;
03867 myrpt->remmode = defmode;
03868
03869 if (setrem(myrpt) == -1){
03870 myrpt->offset = offsave;
03871 myrpt->remmode = modesave;
03872 strncpy(myrpt->freq, savestr, sizeof(myrpt->freq) - 1);
03873 goto invalid_freq;
03874 }
03875
03876 return DC_COMPLETE;
03877
03878
03879 invalid_freq:
03880
03881 rmt_sayfile(myrpt, mychannel, 1000, "rpt/invalid-freq");
03882
03883 return DC_ERROR;
03884
03885 case 3:
03886
03887 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
03888 if(digitbuf[i] == '*'){
03889 j++;
03890 continue;
03891 }
03892 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03893 return DC_ERROR;
03894 else{
03895 if(j)
03896 l++;
03897 else
03898 k++;
03899 }
03900 }
03901 if((j > 1) || (k > 3) || (l > 1))
03902 return DC_ERROR;
03903 i = strlen(digitbuf) - 1;
03904 if((j != 1) || (k < 2)|| (l != 1))
03905 break;
03906 if(debug)
03907 printf("PL digits entered %s\n", digitbuf);
03908
03909 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
03910
03911 s = strchr(tmp,'*');
03912 if(s)
03913 *s = '.';
03914 strncpy(savestr, myrpt->rxpl, sizeof(savestr) - 1);
03915 strncpy(myrpt->rxpl, tmp, sizeof(myrpt->rxpl) - 1);
03916
03917 if (setrem(myrpt) == -1){
03918 strncpy(myrpt->rxpl, savestr, sizeof(myrpt->rxpl) - 1);
03919 return DC_ERROR;
03920 }
03921
03922
03923 return DC_COMPLETE;
03924
03925 case 4:
03926
03927 for(i = 0, j = 0, k = 0, l = 0 ; digitbuf[i] ; i++){
03928 if(digitbuf[i] == '*'){
03929 j++;
03930 continue;
03931 }
03932 if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
03933 return DC_ERROR;
03934 else{
03935 if(j)
03936 l++;
03937 else
03938 k++;
03939 }
03940 }
03941 if((j > 1) || (k > 3) || (l > 1))
03942 return DC_ERROR;
03943 i = strlen(digitbuf) - 1;
03944 if((j != 1) || (k < 2)|| (l != 1))
03945 break;
03946 if(debug)
03947 printf("PL digits entered %s\n", digitbuf);
03948
03949 strncpy(tmp, digitbuf, sizeof(tmp) - 1);
03950
03951 s = strchr(tmp,'*');
03952 if(s)
03953 *s = '.';
03954 strncpy(savestr, myrpt->txpl, sizeof(savestr) - 1);
03955 strncpy(myrpt->txpl, tmp, sizeof(myrpt->txpl) - 1);
03956
03957 if (setrem(myrpt) == -1){
03958 strncpy(myrpt->txpl, savestr, sizeof(myrpt->txpl) - 1);
03959 return DC_ERROR;
03960 }
03961
03962
03963 return DC_COMPLETE;
03964
03965
03966 case 6:
03967 if(strlen(digitbuf) < 1)
03968 break;
03969
03970 if(!multimode)
03971 return DC_ERROR;
03972
03973 switch(*digitbuf){
03974 case '1':
03975 split_freq(mhz, decimals, myrpt->freq);
03976 m=atoi(mhz);
03977 if(m < 29)
03978 return DC_ERROR;
03979 myrpt->remmode = REM_MODE_FM;
03980 res = rmt_saycharstr(myrpt, mychannel, 1000,"FM");
03981 break;
03982
03983 case '2':
03984 myrpt->remmode = REM_MODE_USB;
03985 res = rmt_saycharstr(myrpt, mychannel, 1000,"USB");
03986 break;
03987
03988 case '3':
03989 myrpt->remmode = REM_MODE_LSB;
03990 res = rmt_saycharstr(myrpt, mychannel, 1000,"LSB");
03991 break;
03992
03993 case '4':
03994 myrpt->remmode = REM_MODE_AM;
03995 res = rmt_saycharstr(myrpt, mychannel, 1000,"AM");
03996 break;
03997
03998 default:
03999 return DC_ERROR;
04000 }
04001 if(res)
04002 return DC_ERROR;
04003
04004 if(setrem(myrpt))
04005 return DC_ERROR;
04006 return DC_COMPLETE;
04007
04008 case 100:
04009 case 101:
04010 case 102:
04011 case 103:
04012 case 104:
04013 case 105:
04014 case 106:
04015 res = rmt_telem_start(myrpt, mychannel, 1000);
04016 switch(myatoi(param)){
04017 case 100:
04018 myrpt->rxplon = 0;
04019 if(!res)
04020 res = sayfile(mychannel, "rpt/rxpl");
04021 if(!res)
04022 sayfile(mychannel, "rpt/off");
04023 break;
04024
04025 case 101:
04026 myrpt->rxplon = 1;
04027 if(!res)
04028 res = sayfile(mychannel, "rpt/rxpl");
04029 if(!res)
04030 sayfile(mychannel, "rpt/on");
04031 break;
04032
04033
04034 case 102:
04035 myrpt->txplon = 0;
04036 if(!res)
04037 res = sayfile(mychannel, "rpt/txpl");
04038 if(!res)
04039 sayfile(mychannel, "rpt/off");
04040 break;
04041
04042 case 103:
04043 myrpt->txplon = 1;
04044 if(!res)
04045 res = sayfile(mychannel, "rpt/txpl");
04046 if(!res)
04047 sayfile(mychannel, "rpt/on");
04048 break;
04049
04050 case 104:
04051 myrpt->powerlevel = REM_LOWPWR;
04052 if(!res)
04053 res = sayfile(mychannel, "rpt/lopwr");
04054 break;
04055
04056 case 105:
04057 myrpt->powerlevel = REM_MEDPWR;
04058 if(!res)
04059 res = sayfile(mychannel, "rpt/medpwr");
04060 break;
04061
04062 case 106:
04063 myrpt->powerlevel = REM_HIPWR;
04064 if(!res)
04065 res = sayfile(mychannel, "rpt/hipwr");
04066 break;
04067
04068 default:
04069 if(!res)
04070 rmt_telem_finish(myrpt, mychannel);
04071 return DC_ERROR;
04072 }
04073 if(!res)
04074 res = rmt_telem_finish(myrpt, mychannel);
04075 if(res)
04076 return DC_ERROR;
04077
04078 if (setrem(myrpt) == -1)
04079 return DC_ERROR;
04080 return DC_COMPLETE;
04081
04082 case 107:
04083 multimode_bump_freq(myrpt, -20);
04084 return DC_COMPLETE;
04085
04086 case 108:
04087 multimode_bump_freq(myrpt, -100);
04088 return DC_COMPLETE;
04089
04090 case 109:
04091 multimode_bump_freq(myrpt, -500);
04092 return DC_COMPLETE;
04093
04094 case 110:
04095 multimode_bump_freq(myrpt, 20);
04096 return DC_COMPLETE;
04097
04098 case 111:
04099 multimode_bump_freq(myrpt, 100);
04100 return DC_COMPLETE;
04101
04102 case 112:
04103 multimode_bump_freq(myrpt, 500);
04104 return DC_COMPLETE;
04105
04106
04107 case 113:
04108 case 114:
04109 case 115:
04110 case 116:
04111 case 117:
04112 case 118:
04113 myrpt->remotetx = 0;
04114 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04115 if (!myrpt->remoterx)
04116 ast_indicate(mychannel,AST_CONTROL_RADIO_KEY);
04117 if (ast_safe_sleep(mychannel,1000) == -1)
04118 return DC_ERROR;
04119
04120 switch(myatoi(param)){
04121
04122 case 113:
04123 res = sayfile(mychannel,"rpt/down");
04124 if(!res)
04125 res = sayfile(mychannel, "rpt/slow");
04126 if(!res){
04127 myrpt->scantimer = REM_SCANTIME;
04128 myrpt->hfscanmode = HF_SCAN_DOWN_SLOW;
04129 }
04130 break;
04131
04132 case 114:
04133 res = sayfile(mychannel,"rpt/down");
04134 if(!res)
04135 res = sayfile(mychannel, "rpt/quick");
04136 if(!res){
04137 myrpt->scantimer = REM_SCANTIME;
04138 myrpt->hfscanmode = HF_SCAN_DOWN_QUICK;
04139 }
04140 break;
04141
04142 case 115:
04143 res = sayfile(mychannel,"rpt/down");
04144 if(!res)
04145 res = sayfile(mychannel, "rpt/fast");
04146 if(!res){
04147 myrpt->scantimer = REM_SCANTIME;
04148 myrpt->hfscanmode = HF_SCAN_DOWN_FAST;
04149 }
04150 break;
04151
04152 case 116:
04153 res = sayfile(mychannel,"rpt/up");
04154 if(!res)
04155 res = sayfile(mychannel, "rpt/slow");
04156 if(!res){
04157 myrpt->scantimer = REM_SCANTIME;
04158 myrpt->hfscanmode = HF_SCAN_UP_SLOW;
04159 }
04160 break;
04161
04162 case 117:
04163 res = sayfile(mychannel,"rpt/up");
04164 if(!res)
04165 res = sayfile(mychannel, "rpt/quick");
04166 if(!res){
04167 myrpt->scantimer = REM_SCANTIME;
04168 myrpt->hfscanmode = HF_SCAN_UP_QUICK;
04169 }
04170 break;
04171
04172 case 118:
04173 res = sayfile(mychannel,"rpt/up");
04174 if(!res)
04175 res = sayfile(mychannel, "rpt/fast");
04176 if(!res){
04177 myrpt->scantimer = REM_SCANTIME;
04178 myrpt->hfscanmode = HF_SCAN_UP_FAST;
04179 }
04180 break;
04181 }
04182 rmt_telem_finish(myrpt,mychannel);
04183 return DC_COMPLETE;
04184
04185
04186 case 119:
04187 myrpt->tunerequest = 1;
04188 return DC_COMPLETE;
04189
04190 case 5:
04191 case 140:
04192 res = rmt_telem_start(myrpt, mychannel, 1000);
04193
04194 res = sayfile(mychannel,"rpt/node");
04195 if(!res)
04196 res = saycharstr(mychannel, myrpt->name);
04197 if(!res)
04198 res = sayfile(mychannel,"rpt/frequency");
04199 if(!res)
04200 res = split_freq(mhz, decimals, myrpt->freq);
04201 if(!res){
04202 m = atoi(mhz);
04203 if(m < 100)
04204 res = saynum(mychannel, m);
04205 else
04206 res = saycharstr(mychannel, mhz);
04207 }
04208 if(!res)
04209 res = sayfile(mychannel, "letters/dot");
04210 if(!res)
04211 res = saycharstr(mychannel, decimals);
04212
04213 if(res){
04214 rmt_telem_finish(myrpt,mychannel);
04215 return DC_ERROR;
04216 }
04217 if(myrpt->remmode == REM_MODE_FM){
04218 switch(myrpt->offset){
04219
04220 case REM_MINUS:
04221 res = sayfile(mychannel,"rpt/minus");
04222 break;
04223
04224 case REM_SIMPLEX:
04225 res = sayfile(mychannel,"rpt/simplex");
04226 break;
04227
04228 case REM_PLUS:
04229 res = sayfile(mychannel,"rpt/plus");
04230 break;
04231
04232 default:
04233 return DC_ERROR;
04234
04235 }
04236 }
04237 else{
04238 switch(myrpt->remmode){
04239
04240 case REM_MODE_USB:
04241 res = saycharstr(mychannel, "USB");
04242 break;
04243
04244 case REM_MODE_LSB:
04245 res = saycharstr(mychannel, "LSB");
04246 break;
04247
04248 case REM_MODE_AM:
04249 res = saycharstr(mychannel, "AM");
04250 break;
04251
04252
04253 default:
04254 return DC_ERROR;
04255 }
04256 }
04257
04258 if (res == -1){
04259 rmt_telem_finish(myrpt,mychannel);
04260 return DC_ERROR;
04261 }
04262
04263 if(myatoi(param) == 140){
04264 if(!res)
04265 res = rmt_telem_finish(myrpt, mychannel);
04266 if(res)
04267 return DC_ERROR;
04268 return DC_COMPLETE;
04269 }
04270
04271 switch(myrpt->powerlevel){
04272
04273 case REM_LOWPWR:
04274 res = sayfile(mychannel,"rpt/lopwr") ;
04275 break;
04276
04277 case REM_MEDPWR:
04278 res = sayfile(mychannel,"rpt/medpwr");
04279 break;
04280 case REM_HIPWR:
04281 res = sayfile(mychannel,"rpt/hipwr");
04282 break;
04283 }
04284 if (res || (sayfile(mychannel,"rpt/rxpl") == -1) ||
04285 (sayfile(mychannel,"rpt/frequency") == -1) ||
04286 (saycharstr(mychannel,myrpt->rxpl) == -1) ||
04287 (sayfile(mychannel,"rpt/txpl") == -1) ||
04288 (sayfile(mychannel,"rpt/frequency") == -1) ||
04289 (saycharstr(mychannel,myrpt->txpl) == -1) ||
04290 (sayfile(mychannel,"rpt/txpl") == -1) ||
04291 (sayfile(mychannel,((myrpt->txplon) ? "rpt/on" : "rpt/off")) == -1) ||
04292 (sayfile(mychannel,"rpt/rxpl") == -1) ||
04293 (sayfile(mychannel,((myrpt->rxplon) ? "rpt/on" : "rpt/off")) == -1))
04294 {
04295 rmt_telem_finish(myrpt,mychannel);
04296 return DC_ERROR;
04297 }
04298 if(!res)
04299 res = rmt_telem_finish(myrpt,mychannel);
04300 if(res)
04301 return DC_ERROR;
04302
04303 return DC_COMPLETE;
04304 default:
04305 return DC_ERROR;
04306 }
04307
04308 return DC_INDETERMINATE;
04309 }
04310
04311 static int handle_remote_dtmf_digit(struct rpt *myrpt,char c, char *keyed, int phonemode)
04312 {
04313 time_t now;
04314 int ret,res = 0,src;
04315
04316
04317 if(myrpt->hfscanmode){
04318 stop_scan(myrpt,0);
04319 return 0;
04320 }
04321
04322 time(&now);
04323
04324 if ((myrpt->dtmf_time_rem + DTMF_TIMEOUT) < now)
04325 {
04326 myrpt->dtmfidx = -1;
04327 myrpt->dtmfbuf[0] = 0;
04328 myrpt->dtmf_time_rem = 0;
04329 }
04330
04331 if (myrpt->dtmfidx == -1)
04332 {
04333
04334 if (c != myrpt->funcchar) return 0;
04335 myrpt->dtmfidx = 0;
04336 myrpt->dtmfbuf[0] = 0;
04337 myrpt->dtmf_time_rem = now;
04338 return 0;
04339 }
04340
04341 if (myrpt->dtmfidx >= MAXDTMF)
04342 {
04343 myrpt->dtmfidx = 0;
04344 myrpt->dtmfbuf[0] = 0;
04345 myrpt->dtmf_time_rem = now;
04346 }
04347 if (c == myrpt->funcchar)
04348 {
04349
04350 if ((myrpt->dtmfidx < 1) ||
04351 (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->funcchar))
04352 {
04353 myrpt->dtmfidx = 0;
04354 myrpt->dtmfbuf[0] = 0;
04355 myrpt->dtmf_time_rem = now;
04356 return 0;
04357 }
04358 }
04359 myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
04360 myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
04361 myrpt->dtmf_time_rem = now;
04362
04363
04364 src = SOURCE_RMT;
04365 if (phonemode > 1) src = SOURCE_DPHONE;
04366 else if (phonemode) src = SOURCE_PHONE;
04367 ret = collect_function_digits(myrpt, myrpt->dtmfbuf, src, NULL);
04368
04369 switch(ret){
04370
04371 case DC_INDETERMINATE:
04372 res = 0;
04373 break;
04374
04375 case DC_DOKEY:
04376 if (keyed) *keyed = 1;
04377 res = 0;
04378 break;
04379
04380 case DC_REQ_FLUSH:
04381 myrpt->dtmfidx = 0;
04382 myrpt->dtmfbuf[0] = 0;
04383 res = 0;
04384 break;
04385
04386
04387 case DC_COMPLETE:
04388 myrpt->dtmfbuf[0] = 0;
04389 myrpt->dtmfidx = -1;
04390 myrpt->dtmf_time_rem = 0;
04391 res = 1;
04392 break;
04393
04394 case DC_ERROR:
04395 default:
04396 myrpt->dtmfbuf[0] = 0;
04397 myrpt->dtmfidx = -1;
04398 myrpt->dtmf_time_rem = 0;
04399 res = 0;
04400 break;
04401 }
04402
04403 return res;
04404 }
04405
04406 static int handle_remote_data(struct rpt *myrpt, char *str)
04407 {
04408 char tmp[300],cmd[300],dest[300],src[300],c;
04409 int seq,res;
04410
04411
04412 strncpy(tmp,str,sizeof(tmp) - 1);
04413 if (!strcmp(tmp,discstr)) return 0;
04414 if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
04415 {
04416 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
04417 return 0;
04418 }
04419 if (strcmp(cmd,"D"))
04420 {
04421 ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
04422 return 0;
04423 }
04424
04425 if (strcmp(dest,myrpt->name)) return 0;
04426 res = handle_remote_dtmf_digit(myrpt,c, NULL, 0);
04427 if (res != 1)
04428 return res;
04429 myrpt->remotetx = 0;
04430 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04431 if (!myrpt->remoterx)
04432 {
04433 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
04434 }
04435 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
04436 res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
04437 rmt_telem_finish(myrpt,myrpt->remchannel);
04438 return res;
04439 }
04440
04441 static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int phonemode)
04442 {
04443 int res;
04444
04445
04446 if (keyed && *keyed && (c == myrpt->endchar))
04447 {
04448 *keyed = 0;
04449 return DC_INDETERMINATE;
04450 }
04451
04452 res = handle_remote_dtmf_digit(myrpt,c,keyed, phonemode);
04453 if (res != 1)
04454 return res;
04455 myrpt->remotetx = 0;
04456 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04457 if (!myrpt->remoterx)
04458 {
04459 ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
04460 }
04461 if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
04462 res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
04463 rmt_telem_finish(myrpt,myrpt->remchannel);
04464 return res;
04465 }
04466
04467 static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
04468 {
04469 char *val, *s, *s1, *s2, *tele;
04470 char tmp[300], deststr[300] = "";
04471
04472 val = ast_variable_retrieve(cfg, myrpt->nodes, l->name);
04473 if (!val)
04474 {
04475 fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
04476 return -1;
04477 }
04478
04479 ast_mutex_lock(&myrpt->lock);
04480
04481 remque((struct qelem *) l);
04482 ast_mutex_unlock(&myrpt->lock);
04483 strncpy(tmp,val,sizeof(tmp) - 1);
04484 s = tmp;
04485 s1 = strsep(&s,",");
04486 s2 = strsep(&s,",");
04487 snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
04488 tele = strchr(deststr, '/');
04489 if (!tele) {
04490 fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
04491 return -1;
04492 }
04493 *tele++ = 0;
04494 l->elaptime = 0;
04495 l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
04496 if (l->chan){
04497 ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
04498 ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
04499 l->chan->whentohangup = 0;
04500 l->chan->appl = "Apprpt";
04501 l->chan->data = "(Remote Rx)";
04502 if (option_verbose > 2)
04503 ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
04504 deststr, tele, l->chan->name);
04505 if(l->chan->cid.cid_num)
04506 free(l->chan->cid.cid_num);
04507 l->chan->cid.cid_num = strdup(myrpt->name);
04508 ast_call(l->chan,tele,999);
04509
04510 }
04511 else
04512 {
04513 if (option_verbose > 2)
04514 ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
04515 deststr,tele,l->chan->name);
04516 return -1;
04517 }
04518 ast_mutex_lock(&myrpt->lock);
04519
04520 insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
04521 ast_mutex_unlock(&myrpt->lock);
04522 ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
04523 return 0;
04524 }
04525
04526
04527 static void *rpt(void *this)
04528 {
04529 struct rpt *myrpt = (struct rpt *)this;
04530 char *tele,*idtalkover;
04531 int ms = MSWAIT,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res;
04532 struct ast_channel *who;
04533 ZT_CONFINFO ci;
04534 time_t dtmf_time,t;
04535 struct rpt_link *l,*m;
04536 struct rpt_tele *telem;
04537 pthread_attr_t attr;
04538 char tmpstr[300];
04539 char cmd[MAXDTMF+1] = "";
04540
04541
04542 ast_mutex_lock(&myrpt->lock);
04543 strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
04544 tele = strchr(tmpstr,'/');
04545 if (!tele)
04546 {
04547 fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
04548 ast_mutex_unlock(&myrpt->lock);
04549 myrpt->rpt_thread = AST_PTHREADT_STOP;
04550 pthread_exit(NULL);
04551 }
04552 *tele++ = 0;
04553 myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
04554 if (myrpt->rxchannel)
04555 {
04556 if (myrpt->rxchannel->_state == AST_STATE_BUSY)
04557 {
04558 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
04559 ast_mutex_unlock(&myrpt->lock);
04560 ast_hangup(myrpt->rxchannel);
04561 myrpt->rpt_thread = AST_PTHREADT_STOP;
04562 pthread_exit(NULL);
04563 }
04564 ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
04565 ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
04566 myrpt->rxchannel->whentohangup = 0;
04567 myrpt->rxchannel->appl = "Apprpt";
04568 myrpt->rxchannel->data = "(Repeater Rx)";
04569 if (option_verbose > 2)
04570 ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
04571 tmpstr,tele,myrpt->rxchannel->name);
04572 ast_call(myrpt->rxchannel,tele,999);
04573 if (myrpt->rxchannel->_state != AST_STATE_UP)
04574 {
04575 ast_mutex_unlock(&myrpt->lock);
04576 ast_hangup(myrpt->rxchannel);
04577 myrpt->rpt_thread = AST_PTHREADT_STOP;
04578 pthread_exit(NULL);
04579 }
04580 }
04581 else
04582 {
04583 fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
04584 ast_mutex_unlock(&myrpt->lock);
04585 myrpt->rpt_thread = AST_PTHREADT_STOP;
04586 pthread_exit(NULL);
04587 }
04588 if (myrpt->txchanname)
04589 {
04590 strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
04591 tele = strchr(tmpstr,'/');
04592 if (!tele)
04593 {
04594 fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
04595 ast_mutex_unlock(&myrpt->lock);
04596 ast_hangup(myrpt->rxchannel);
04597 myrpt->rpt_thread = AST_PTHREADT_STOP;
04598 pthread_exit(NULL);
04599 }
04600 *tele++ = 0;
04601 myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele,NULL);
04602 if (myrpt->txchannel)
04603 {
04604 if (myrpt->txchannel->_state == AST_STATE_BUSY)
04605 {
04606 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
04607 ast_mutex_unlock(&myrpt->lock);
04608 ast_hangup(myrpt->txchannel);
04609 ast_hangup(myrpt->rxchannel);
04610 myrpt->rpt_thread = AST_PTHREADT_STOP;
04611 pthread_exit(NULL);
04612 }
04613 ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
04614 ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
04615 myrpt->txchannel->whentohangup = 0;
04616 myrpt->txchannel->appl = "Apprpt";
04617 myrpt->txchannel->data = "(Repeater Tx)";
04618 if (option_verbose > 2)
04619 ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
04620 tmpstr,tele,myrpt->txchannel->name);
04621 ast_call(myrpt->txchannel,tele,999);
04622 if (myrpt->rxchannel->_state != AST_STATE_UP)
04623 {
04624 ast_mutex_unlock(&myrpt->lock);
04625 ast_hangup(myrpt->rxchannel);
04626 ast_hangup(myrpt->txchannel);
04627 myrpt->rpt_thread = AST_PTHREADT_STOP;
04628 pthread_exit(NULL);
04629 }
04630 }
04631 else
04632 {
04633 fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
04634 ast_mutex_unlock(&myrpt->lock);
04635 ast_hangup(myrpt->rxchannel);
04636 myrpt->rpt_thread = AST_PTHREADT_STOP;
04637 pthread_exit(NULL);
04638 }
04639 }
04640 else
04641 {
04642 myrpt->txchannel = myrpt->rxchannel;
04643 }
04644 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
04645 ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
04646
04647 myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
04648 if (!myrpt->pchannel)
04649 {
04650 fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
04651 ast_mutex_unlock(&myrpt->lock);
04652 if (myrpt->txchannel != myrpt->rxchannel)
04653 ast_hangup(myrpt->txchannel);
04654 ast_hangup(myrpt->rxchannel);
04655 myrpt->rpt_thread = AST_PTHREADT_STOP;
04656 pthread_exit(NULL);
04657 }
04658