2 /* #define OLD_ASTERISK */
4 * Asterisk -- An open source telephony toolkit.
6 * Copyright (C) 2002-2008, Jim Dixon, WB6NIL
8 * Jim Dixon, WB6NIL <jim@lambdatel.com>
9 * Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
11 * See http://www.asterisk.org for more information about
12 * the Asterisk project. Please do not directly contact
13 * any of the maintainers of this project for assistance;
14 * the project provides a web site, mailing lists and IRC
15 * channels for your use.
17 * This program is free software, distributed under the terms of
18 * the GNU General Public License Version 2. See the LICENSE file
19 * at the top of the source tree.
23 * \brief Radio Repeater / Remote Base program
24 * version 0.115 5/12/08 2055 EDT
26 * \author Jim Dixon, WB6NIL <jim@lambdatel.com>
28 * \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
29 * \note Steven Henke, W9SH, <w9sh@arrl.net> added a few features here and there.
31 * See http://www.zapatatelephony.org/app_rpt.html
34 * Repeater / Remote Functions:
35 * "Simple" Mode: * - autopatch access, # - autopatch hangup
37 * See the function list in rpt.conf (autopatchup, autopatchdn)
38 * autopatchup can optionally take comma delimited setting=value pairs:
41 * context=string : Override default context with "string"
42 * dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second)
43 * farenddisconnect=1 : Automatically disconnect when called party hangs up
44 * noct=1 : Don't send repeater courtesy tone during autopatch calls
45 * quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up
48 * Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1
50 * To send an asterisk (*) while dialing or talking on phone,
51 * use the autopatch acess code.
56 * 1 - Force ID (global)
57 * 2 - Give Time of Day (global)
58 * 3 - Give software Version (global)
59 * 11 - Force ID (local only)
60 * 12 - Give Time of Day (local only)
62 * cop (control operator) cmds:
64 * 1 - System warm boot
67 * 4 - Test Tone On/Off
68 * 5 - Dump System Variables on Console (debug)
69 * 6 - PTT (phone mode only)
70 * 7 - Time out timer enable
71 * 8 - Time out timer disable
72 * 9 - Autopatch enable
73 * 10 - Autopatch disable
76 * 13 - Query System State
77 * 14 - Change System State
78 * 15 - Scheduler Enable
79 * 16 - Scheduler Disable
80 * 17 - User functions (time, id, etc) enable
81 * 18 - User functions (time, id, etc) disable
82 * 19 - Select alternate hang timer
83 * 20 - Select standard hang timer
84 * 21 - Enable Parrot Mode
85 * 22 - Disable Parrot Mode
86 * 23 - Birdbath (Current Parrot Cleanup/Flush)
87 * 24 - Flush all telemetry
88 * 25 - Query last node un-keyed
89 * 26 - Query all nodes keyed/unkeyed
90 * 30 - Recall Memory Setting in Attached Xcvr
91 * 31 - Channel Selector for Parallel Programmed Xcvr
92 * 32 - Touchtone pad test: command + Digit string + # to playback all digits pressed
96 * 1 - Disconnect specified link
97 * 2 - Connect specified link -- monitor only
98 * 3 - Connect specified link -- tranceive
99 * 4 - Enter command mode on specified link
101 * 6 - Disconnect all links
102 * 11 - Disconnect a previously permanently connected link
103 * 12 - Permanently connect specified link -- monitor only
104 * 13 - Permanently connect specified link -- tranceive
105 * 15 - Full system status (all nodes)
106 * 16 - Reconnect links disconnected with "disconnect all links"
107 * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
111 * 1 - Recall Memory MM (*000-*099) (Gets memory from rpt.conf)
112 * 2 - Set VFO MMMMM*KKK*O (Mhz digits, Khz digits, Offset)
113 * 3 - Set Rx PL Tone HHH*D*
114 * 4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
115 * 5 - Link Status (long)
116 * 6 - Set operating mode M (FM, USB, LSB, AM, etc)
117 * 100 - RX PL off (Default)
119 * 102 - TX PL Off (Default)
124 * 107 - Bump Down 20 Hz
125 * 108 - Bump Down 100 Hz
126 * 109 - Bump Down 500 Hz
127 * 110 - Bump Up 20 Hz
128 * 111 - Bump Up 100 Hz
129 * 112 - Bump Up 500 Hz
130 * 113 - Scan Down Slow
131 * 114 - Scan Down Medium
132 * 115 - Scan Down Fast
134 * 117 - Scan Up Medium
136 * 119 - Transmit allowing auto-tune
137 * 140 - Link Status (brief)
138 * 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
141 * specify the name of the file to be played (for example, 25=rpt/foo)
144 * 'duplex' modes: (defaults to duplex=2)
146 * 0 - Only remote links key Tx and no main repeat audio.
147 * 1 - Everything other then main Rx keys Tx, no main repeat audio.
149 * 3 - Normal except no main repeat audio.
150 * 4 - Normal except no main repeat audio during autopatch only
155 <depend>dahdi</depend>
156 <depend>tonezone</depend>
157 <defaultenabled>no</defaultenabled>
160 /* Un-comment the following to include support for MDC-1200 digital tone
161 signalling protocol (using KA6SQG's GPL'ed implementation) */
162 /* #include "mdc_decode.c" */
164 /* Un-comment the following to include support for notch filters in the
165 rx audio stream (using Tony Fisher's mknotch (mkfilter) implementation) */
166 /* #include "rpt_notch.c" */
168 /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
171 #define ast_free free
172 #define ast_malloc malloc
173 #define ast_strdup strdup
178 #define MAXMACRO 2048
179 #define MAXLINKLIST 512
180 #define LINKLISTTIME 10000
181 #define LINKLISTSHORTTIME 200
182 #define LINKPOSTTIME 30000
183 #define LINKPOSTSHORTTIME 200
184 #define KEYPOSTTIME 30000
185 #define KEYPOSTSHORTTIME 200
186 #define MACROTIME 100
187 #define MACROPTIME 500
188 #define DTMF_TIMEOUT 3
189 #define KENWOOD_RETRIES 5
192 #define TOPKEYMAXSTR 30
194 #define AUTHTELLTIME 7000
195 #define AUTHTXTIME 1000
196 #define AUTHLOGOUTTIME 25000
199 #define MAXFILTERS 10
202 #define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
203 #define MAX_RETRIES 5
204 #define MAX_RETRIES_PERM 1000000000
206 #define REDUNDANT_TX_TIME 2000
208 #define RETRY_TIMER_MS 5000
210 #define PATCH_DIALPLAN_TIMEOUT 1500
213 #define START_DELAY 10
215 #define START_DELAY 2
218 #define RPT_LOCKOUT_SECS 10
220 #define MAXPEERSTR 31
226 #define MONITOR_DISK_BLOCKS_PER_MINUTE 38
228 #define DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
229 #define DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
230 #define DEFAULT_REMOTE_TIMEOUT (60 * 60)
231 #define DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
232 #define DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
234 #define NODES "nodes"
235 #define EXTNODES "extnodes"
236 #define MEMORY "memory"
237 #define MACRO "macro"
238 #define FUNCTIONS "functions"
239 #define TELEMETRY "telemetry"
240 #define MORSE "morse"
241 #define TONEMACRO "tonemacro"
244 #define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
245 #define NODENAMES "rpt/nodenames"
246 #define PARROTFILE "/tmp/parrot_%s_%u"
248 #define PARROTTIME 1000
250 #define DEFAULT_IOBASE 0x378
252 #define DEFAULT_CIV_ADDR 0x58
254 #define MAXCONNECTTIME 5000
256 #define MAXNODESTR 300
258 #define MAXNODELEN 16
260 #define MAXIDENTLEN 32
262 #define MAXPATCHCONTEXT 100
264 #define ACTIONSIZE 32
266 #define TELEPARAMSIZE 256
268 #define REM_SCANTIME 100
270 #define DTMF_LOCAL_TIME 250
271 #define DTMF_LOCAL_STARTTIME 500
273 #define IC706_PL_MEMORY_OFFSET 50
275 #define VOX_ON_DEBOUNCE_COUNT 3
276 #define VOX_OFF_DEBOUNCE_COUNT 20
277 #define VOX_MAX_THRESHOLD 10000.0
278 #define VOX_MIN_THRESHOLD 3000.0
279 #define VOX_TIMEOUT_MS 5000
280 #define VOX_RECOVER_MS 500
281 #define SIMPLEX_PATCH_DELAY 25
282 #define SIMPLEX_PHONE_DELAY 25
284 #define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
286 #define ALLOW_LOCAL_CHANNELS
288 enum {REM_OFF
,REM_MONITOR
,REM_TX
};
290 enum{ID
,PROC
,TERM
,COMPLETE
,UNKEY
,REMDISC
,REMALREADY
,REMNOTFOUND
,REMGO
,
291 CONNECTED
,CONNFAIL
,STATUS
,TIMEOUT
,ID1
, STATS_TIME
, PLAYBACK
,
292 STATS_VERSION
, IDTALKOVER
, ARB_ALPHA
, TEST_TONE
, REV_PATCH
,
293 TAILMSG
, MACRO_NOTFOUND
, MACRO_BUSY
, LASTNODEKEY
, FULLSTATUS
,
294 MEMNOTFOUND
, INVFREQ
, REMMODE
, REMLOGIN
, REMXXX
, REMSHORTSTATUS
,
295 REMLONGSTATUS
, LOGINREQ
, SCAN
, SCANSTAT
, TUNE
, SETREMOTE
, TOPKEY
,
296 TIMEOUT_WARNING
, ACT_TIMEOUT_WARNING
, LINKUNKEY
, UNAUTHTX
, PARROT
,
300 enum {REM_SIMPLEX
,REM_MINUS
,REM_PLUS
};
302 enum {REM_LOWPWR
,REM_MEDPWR
,REM_HIPWR
};
304 enum {DC_INDETERMINATE
, DC_REQ_FLUSH
, DC_ERROR
, DC_COMPLETE
, DC_COMPLETEQUIET
, DC_DOKEY
};
306 enum {SOURCE_RPT
, SOURCE_LNK
, SOURCE_RMT
, SOURCE_PHONE
, SOURCE_DPHONE
, SOURCE_ALT
};
308 enum {DLY_TELEM
, DLY_ID
, DLY_UNKEY
, DLY_CALLTERM
, DLY_COMP
, DLY_LINKUNKEY
, DLY_PARROT
};
310 enum {REM_MODE_FM
,REM_MODE_USB
,REM_MODE_LSB
,REM_MODE_AM
};
312 enum {HF_SCAN_OFF
,HF_SCAN_DOWN_SLOW
,HF_SCAN_DOWN_QUICK
,
313 HF_SCAN_DOWN_FAST
,HF_SCAN_UP_SLOW
,HF_SCAN_UP_QUICK
,HF_SCAN_UP_FAST
};
315 #include "asterisk.h"
317 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
325 #include <sys/types.h>
326 #include <sys/stat.h>
330 #include <sys/stat.h>
331 #include <sys/time.h>
332 #include <sys/file.h>
333 #include <sys/ioctl.h>
337 #include <dahdi/user.h>
338 #include <dahdi/tonezone.h>
339 #include <netinet/in.h>
340 #include <arpa/inet.h>
342 #include "asterisk/utils.h"
343 #include "asterisk/lock.h"
344 #include "asterisk/file.h"
345 #include "asterisk/logger.h"
346 #include "asterisk/channel.h"
347 #include "asterisk/callerid.h"
348 #include "asterisk/pbx.h"
349 #include "asterisk/module.h"
350 #include "asterisk/translate.h"
351 #include "asterisk/features.h"
352 #include "asterisk/options.h"
353 #include "asterisk/cli.h"
354 #include "asterisk/config.h"
355 #include "asterisk/say.h"
356 #include "asterisk/localtime.h"
357 #include "asterisk/cdr.h"
358 #include "asterisk/options.h"
359 #include "asterisk/manager.h"
363 struct ast_flags config_flags
= { CONFIG_FLAG_WITHCOMMENTS
};
367 /* Start a tone-list going */
368 int ast_playtones_start(struct ast_channel
*chan
, int vol
, const char* tonelist
, int interruptible
);
369 /*! Stop the tones from playing */
370 void ast_playtones_stop(struct ast_channel
*chan
);
372 static char *tdesc
= "Radio Repeater / Remote Base version 0.115 5/12/2008";
374 static char *app
= "Rpt";
376 static char *synopsis
= "Radio Repeater/Remote Base Control System";
378 static char *descrip
=
379 " Rpt(nodename[|options][|M][|*]): \n"
380 " Radio Remote Link or Remote Base Link Endpoint Process.\n"
382 " Not specifying an option puts it in normal endpoint mode (where source\n"
383 " IP and nodename are verified).\n"
385 " Options are as follows:\n"
387 " X - Normal endpoint mode WITHOUT security check. Only specify\n"
388 " this if you have checked security already (like with an IAX2\n"
389 " user/password or something).\n"
391 " Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
392 " Reverse Autopatch. Caller is put on hold, and announcement (as\n"
393 " specified by the 'announce-string') is played on radio system.\n"
394 " Users of radio system can access autopatch, dial specified\n"
395 " code, and pick up call. Announce-string is list of names of\n"
396 " recordings, or \"PARKED\" to substitute code for un-parking,\n"
397 " or \"NODE\" to substitute node number.\n"
399 " P - Phone Control mode. This allows a regular phone user to have\n"
400 " full control and audio access to the radio system. For the\n"
401 " user to have DTMF control, the 'phone_functions' parameter\n"
402 " must be specified for the node in 'rpt.conf'. An additional\n"
403 " function (cop,6) must be listed so that PTT control is available.\n"
405 " D - Dumb Phone Control mode. This allows a regular phone user to\n"
406 " have full control and audio access to the radio system. In this\n"
407 " mode, the PTT is activated for the entire length of the call.\n"
408 " For the user to have DTMF control (not generally recomended in\n"
409 " this mode), the 'dphone_functions' parameter must be specified\n"
410 " for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
411 " available to the phone user.\n"
413 " S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
414 " audio-only access to the radio system. In this mode, the\n"
415 " transmitter is toggled on and off when the phone user presses the\n"
416 " funcchar (*) key on the telephone set. In addition, the transmitter\n"
417 " will turn off if the endchar (#) key is pressed. When a user first\n"
418 " calls in, the transmitter will be off, and the user can listen for\n"
419 " radio traffic. When the user wants to transmit, they press the *\n"
420 " key, start talking, then press the * key again or the # key to turn\n"
421 " the transmitter off. No other functions can be executed by the\n"
422 " user on the phone when this mode is selected. Note: If your\n"
423 " radio system is full-duplex, we recommend using either P or D\n"
424 " modes as they provide more flexibility.\n"
426 " q - Query Status. Sets channel variables and returns + 101 in plan.\n"
428 " M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
430 " * - Alt Macro to execute (e.g. *7 for status)\n"
434 static int debug
= 0; /* Set this >0 for extra debug output */
435 static int nrpts
= 0;
437 static char remdtmfstr
[] = "0123456789*#ABCD";
439 enum {TOP_TOP
,TOP_WON
,WON_BEFREAD
,BEFREAD_AFTERREAD
};
441 int max_chan_stat
[] = {22000,1000,22000,100,22000,2000,22000};
450 unsigned long largest
;
451 struct timeval largest_time
;
454 char *discstr
= "!!DISCONNECT!!";
455 char *newkeystr
= "!NEWKEY!";
456 static char *remote_rig_ft897
="ft897";
457 static char *remote_rig_rbi
="rbi";
458 static char *remote_rig_kenwood
="kenwood";
459 static char *remote_rig_tm271
="tm271";
460 static char *remote_rig_ic706
="ic706";
461 static char *remote_rig_rtx150
="rtx150";
462 static char *remote_rig_rtx450
="rtx450";
463 static char *remote_rig_ppp16
="ppp16"; // parallel port programmable 16 channels
465 #define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
466 #define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
474 #define HANGTIME 5000
475 #define TOTIME 180000
476 #define IDTIME 300000
478 #define MAX_STAT_LINKS 32
479 #define POLITEID 30000
480 #define FUNCTDELAY 1500
483 #define MAXXLATTIME 3
485 #define MAX_SYSSTATES 10
497 #define mymax(x,y) ((x > y) ? x : y)
498 #define mymin(x,y) ((x < y) ? x : y)
502 char node
[TOPKEYMAXSTR
];
509 char funccharseq
[MAXXLAT
];
510 char endcharseq
[MAXXLAT
];
511 char passchars
[MAXXLAT
];
517 static time_t starttime
= 0;
519 static pthread_t rpt_master_thread
;
525 struct rpt_link
*next
;
526 struct rpt_link
*prev
;
527 char mode
; /* 1 if in tx mode */
530 char phonevox
; /* vox the phone */
531 char name
[MAXNODESTR
]; /* identifier (routing) string */
552 long long connecttime
;
553 struct ast_channel
*chan
;
554 struct ast_channel
*pchan
;
555 char linklist
[MAXLINKLIST
];
556 time_t linklistreceived
;
559 int linkunkeytocttimer
;
560 struct timeval lastlinktv
;
561 struct ast_frame
*lastf1
,*lastf2
;
562 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
569 AST_LIST_HEAD(, ast_frame
) rxq
;
571 AST_LIST_HEAD_NOLOCK(, ast_frame
) rxq
;
577 struct rpt_lstat
*next
;
578 struct rpt_lstat
*prev
;
579 char peer
[MAXPEERSTR
];
580 char name
[MAXNODESTR
];
585 long long connecttime
;
586 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
591 struct rpt_tele
*next
;
592 struct rpt_tele
*prev
;
594 struct ast_channel
*chan
;
596 struct rpt_link mylink
;
597 char param
[TELEPARAMSIZE
];
603 struct function_table_tag
605 char action
[ACTIONSIZE
];
606 int (*function
)(struct rpt
*myrpt
, char *param
, char *digitbuf
,
607 int command_source
, struct rpt_link
*mylink
);
610 /* Used to store the morse code patterns */
618 struct telem_defaults
630 char autopatchdisable
;
631 char schedulerdisable
;
636 /* rpt cmd support */
638 #define CMD_STATE_IDLE 0
639 #define CMD_STATE_BUSY 1
640 #define CMD_STATE_READY 2
641 #define CMD_STATE_EXECUTING 3
643 struct rpt_cmd_struct
648 char digits
[MAXDTMF
];
656 ast_mutex_t statpost_lock
;
657 struct ast_config
*cfg
;
659 char xlink
; // cross link state of a share repeater/remote radio
660 unsigned int statpost_seqno
;
667 struct rpt_chan_stat chan_stat
[NRPTSTAT
];
678 char *link_functions
;
679 char *phone_functions
;
680 char *dphone_functions
;
690 int tailsquashedtime
;
693 char *tailmessages
[500];
706 char propagate_phonedtmf
;
708 unsigned char civaddr
;
709 struct rpt_xlat inxlat
;
710 struct rpt_xlat outxlat
;
714 char *skedstanzaname
;
715 char *txlimitsstanzaname
;
717 int remoteinacttimeout
;
719 int remotetimeoutwarning
;
720 int remotetimeoutwarningfreq
;
722 struct sysstate s
[MAX_SYSSTATES
];
729 int simplexpatchdelay
;
730 int simplexphonedelay
;
731 char *statpost_program
;
734 struct rpt_link links
;
736 time_t lastkeyedtime
;
737 time_t lasttxkeyedtime
;
748 char dtmfbuf
[MAXDTMF
];
749 char macrobuf
[MAXMACRO
];
750 char rem_dtmfbuf
[MAXDTMF
];
751 char lastdtmfcommand
[MAXDTMF
];
753 char nowchan
; // channel now
754 char waschan
; // channel selected initially or by command
755 char bargechan
; // barge in channel
756 char macropatch
; // autopatch via tonemacro state
759 unsigned int parrotcnt
;
760 struct ast_channel
*rxchannel
,*txchannel
, *monchannel
, *parrotchannel
;
761 struct ast_channel
*pchannel
,*txpchannel
, *dahdirxchannel
, *dahditxchannel
;
762 struct ast_channel
*voxchannel
;
763 struct ast_frame
*lastf1
,*lastf2
;
764 struct rpt_tele tele
;
765 struct timeval lasttv
,curtv
;
766 pthread_t rpt_call_thread
,rpt_thread
;
767 time_t dtmf_time
,rem_dtmf_time
,dtmf_time_rem
;
769 int tailtimer
,totimer
,idtimer
,txconf
,conf
,callmode
,cidx
,scantimer
,tmsgtimer
,skedtimer
;
773 int dtmfidx
,rem_dtmfidx
;
774 int dailytxtime
,dailykerchunks
,totalkerchunks
,dailykeyups
,totalkeyups
,timeouts
;
775 int totalexecdcommands
, dailyexecdcommands
;
778 long long totaltxtime
;
780 char exten
[AST_MAX_EXTENSION
];
781 char freq
[MAXREMSTR
],rxpl
[MAXREMSTR
],txpl
[MAXREMSTR
];
791 char lastlinknode
[MAXNODESTR
];
792 char savednodes
[MAXNODESTR
];
794 char patchfarenddisconnect
;
797 char patchcontext
[MAXPATCHCONTEXT
];
800 int phone_longestfunc
;
802 int dphone_longestfunc
;
803 int link_longestfunc
;
809 time_t lastthreadrestarttime
;
811 char lastnodewhichkeyedusup
[MAXNODESTR
];
812 int dtmf_local_timer
;
813 char dtmf_local_str
[100];
814 struct ast_filestream
*monstream
,*parrotstream
;
820 time_t start_time
,last_activity_time
;
822 struct rpt_tele
*active_telem
;
823 struct rpt_topkey topkey
[TOPKEYN
];
836 AST_LIST_HEAD(, ast_frame
) txq
;
838 AST_LIST_HEAD_NOLOCK(, ast_frame
) txq
;
855 } filters
[MAXFILTERS
];
857 #ifdef _MDC_DECODE_H_
859 unsigned short lastunit
;
861 struct rpt_cmd_struct cmdAction
;
865 struct nodelog
*next
;
866 struct nodelog
*prev
;
868 char archivedir
[MAXNODESTR
];
869 char str
[MAXNODESTR
* 2];
872 static int service_scan(struct rpt
*myrpt
);
873 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
);
874 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
);
875 static int simple_command_ft897(struct rpt
*myrpt
, char command
);
876 static int setrem(struct rpt
*myrpt
);
877 static int setrtx_check(struct rpt
*myrpt
);
878 static int channel_revert(struct rpt
*myrpt
);
879 static int channel_steer(struct rpt
*myrpt
, char *data
);
881 AST_MUTEX_DEFINE_STATIC(nodeloglock
);
883 AST_MUTEX_DEFINE_STATIC(nodelookuplock
);
885 #ifdef APP_RPT_LOCK_DEBUG
887 #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
889 #define MAXLOCKTHREAD 100
891 #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
892 #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
900 } lockthreads
[MAXLOCKTHREAD
];
908 struct lockthread lockthread
;
911 int lock_ring_index
= 0;
913 AST_MUTEX_DEFINE_STATIC(locklock
);
915 static struct lockthread
*get_lockthread(pthread_t id
)
919 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
921 if (lockthreads
[i
].id
== id
) return(&lockthreads
[i
]);
926 static struct lockthread
*put_lockthread(pthread_t id
)
930 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
932 if (lockthreads
[i
].id
== id
)
933 return(&lockthreads
[i
]);
935 for(i
= 0; i
< MAXLOCKTHREAD
; i
++)
937 if (!lockthreads
[i
].id
)
939 lockthreads
[i
].lockcount
= 0;
940 lockthreads
[i
].lastlock
= 0;
941 lockthreads
[i
].lastunlock
= 0;
942 lockthreads
[i
].id
= id
;
943 return(&lockthreads
[i
]);
950 static void rpt_mutex_spew(void)
952 struct by_lightning lock_ring_copy
[32];
953 int lock_ring_index_copy
;
957 struct timeval lasttv
;
959 ast_mutex_lock(&locklock
);
960 memcpy(&lock_ring_copy
, &lock_ring
, sizeof(lock_ring_copy
));
961 lock_ring_index_copy
= lock_ring_index
;
962 ast_mutex_unlock(&locklock
);
964 lasttv
.tv_sec
= lasttv
.tv_usec
= 0;
965 for(i
= 0 ; i
< 32 ; i
++)
967 j
= (i
+ lock_ring_index_copy
) % 32;
968 strftime(a
,sizeof(a
) - 1,"%m/%d/%Y %H:%M:%S",
969 localtime(&lock_ring_copy
[j
].tv
.tv_sec
));
973 diff
= (lock_ring_copy
[j
].tv
.tv_sec
- lasttv
.tv_sec
)
975 diff
+= (lock_ring_copy
[j
].tv
.tv_usec
- lasttv
.tv_usec
);
977 lasttv
.tv_sec
= lock_ring_copy
[j
].tv
.tv_sec
;
978 lasttv
.tv_usec
= lock_ring_copy
[j
].tv
.tv_usec
;
979 if (!lock_ring_copy
[j
].tv
.tv_sec
) continue;
980 if (lock_ring_copy
[j
].line
< 0)
982 ast_log(LOG_NOTICE
,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
983 i
- 31,-lock_ring_copy
[j
].line
,lock_ring_copy
[j
].rpt
->name
,(int) lock_ring_copy
[j
].lockthread
.id
,diff
,a
,(int)lock_ring_copy
[j
].tv
.tv_usec
);
987 ast_log(LOG_NOTICE
,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
988 i
- 31,lock_ring_copy
[j
].line
,lock_ring_copy
[j
].rpt
->name
,(int) lock_ring_copy
[j
].lockthread
.id
,diff
,a
,(int)lock_ring_copy
[j
].tv
.tv_usec
);
994 static void _rpt_mutex_lock(ast_mutex_t
*lockp
, struct rpt
*myrpt
, int line
)
996 struct lockthread
*t
;
1000 ast_mutex_lock(&locklock
);
1001 t
= put_lockthread(id
);
1004 ast_mutex_unlock(&locklock
);
1009 int lastline
= t
->lastlock
;
1010 ast_mutex_unlock(&locklock
);
1011 ast_log(LOG_NOTICE
,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line
,myrpt
->name
,(int) t
->id
,lastline
);
1017 gettimeofday(&lock_ring
[lock_ring_index
].tv
, NULL
);
1018 lock_ring
[lock_ring_index
].rpt
= myrpt
;
1019 memcpy(&lock_ring
[lock_ring_index
].lockthread
,t
,sizeof(struct lockthread
));
1020 lock_ring
[lock_ring_index
++].line
= line
;
1021 if(lock_ring_index
== 32)
1022 lock_ring_index
= 0;
1023 ast_mutex_unlock(&locklock
);
1024 ast_mutex_lock(lockp
);
1028 static void _rpt_mutex_unlock(ast_mutex_t
*lockp
, struct rpt
*myrpt
, int line
)
1030 struct lockthread
*t
;
1033 id
= pthread_self();
1034 ast_mutex_lock(&locklock
);
1035 t
= put_lockthread(id
);
1038 ast_mutex_unlock(&locklock
);
1043 int lastline
= t
->lastunlock
;
1044 ast_mutex_unlock(&locklock
);
1045 ast_log(LOG_NOTICE
,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line
,myrpt
->name
,(int) t
->id
,lastline
);
1049 t
->lastunlock
= line
;
1051 gettimeofday(&lock_ring
[lock_ring_index
].tv
, NULL
);
1052 lock_ring
[lock_ring_index
].rpt
= myrpt
;
1053 memcpy(&lock_ring
[lock_ring_index
].lockthread
,t
,sizeof(struct lockthread
));
1054 lock_ring
[lock_ring_index
++].line
= -line
;
1055 if(lock_ring_index
== 32)
1056 lock_ring_index
= 0;
1057 ast_mutex_unlock(&locklock
);
1058 ast_mutex_unlock(lockp
);
1061 #else /* APP_RPT_LOCK_DEBUG */
1063 #define rpt_mutex_lock(x) ast_mutex_lock(x)
1064 #define rpt_mutex_unlock(x) ast_mutex_unlock(x)
1066 #endif /* APP_RPT_LOCK_DEBUG */
1069 * Return 1 if rig is multimode capable
1072 static int multimode_capable(struct rpt
*myrpt
)
1074 if(!strcmp(myrpt
->remoterig
, remote_rig_ft897
))
1076 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
1081 static void voxinit_rpt(struct rpt
*myrpt
,char enable
)
1084 myrpt
->vox
.speech_energy
= 0.0;
1085 myrpt
->vox
.noise_energy
= 0.0;
1086 myrpt
->vox
.enacount
= 0;
1087 myrpt
->vox
.voxena
= 0;
1088 if (!enable
) myrpt
->vox
.voxena
= -1;
1089 myrpt
->vox
.lastvox
= 0;
1090 myrpt
->vox
.ondebcnt
= VOX_ON_DEBOUNCE_COUNT
;
1091 myrpt
->vox
.offdebcnt
= VOX_OFF_DEBOUNCE_COUNT
;
1093 myrpt
->voxtotimer
= 0;
1094 myrpt
->voxtostate
= 0;
1097 static void voxinit_link(struct rpt_link
*mylink
,char enable
)
1100 mylink
->vox
.speech_energy
= 0.0;
1101 mylink
->vox
.noise_energy
= 0.0;
1102 mylink
->vox
.enacount
= 0;
1103 mylink
->vox
.voxena
= 0;
1104 if (!enable
) mylink
->vox
.voxena
= -1;
1105 mylink
->vox
.lastvox
= 0;
1106 mylink
->vox
.ondebcnt
= VOX_ON_DEBOUNCE_COUNT
;
1107 mylink
->vox
.offdebcnt
= VOX_OFF_DEBOUNCE_COUNT
;
1109 mylink
->voxtotimer
= 0;
1110 mylink
->voxtostate
= 0;
1113 static int dovox(struct vox
*v
,short *buf
,int bs
)
1117 float esquare
= 0.0;
1119 float threshold
= 0.0;
1121 if (v
->voxena
< 0) return(v
->lastvox
);
1122 for(i
= 0; i
< bs
; i
++)
1124 esquare
+= (float) buf
[i
] * (float) buf
[i
];
1126 energy
= sqrt(esquare
);
1128 if (energy
>= v
->speech_energy
)
1129 v
->speech_energy
+= (energy
- v
->speech_energy
) / 4;
1131 v
->speech_energy
+= (energy
- v
->speech_energy
) / 64;
1133 if (energy
>= v
->noise_energy
)
1134 v
->noise_energy
+= (energy
- v
->noise_energy
) / 64;
1136 v
->noise_energy
+= (energy
- v
->noise_energy
) / 4;
1138 if (v
->voxena
) threshold
= v
->speech_energy
/ 8;
1141 threshold
= mymax(v
->speech_energy
/ 16,v
->noise_energy
* 2);
1142 threshold
= mymin(threshold
,VOX_MAX_THRESHOLD
);
1144 threshold
= mymax(threshold
,VOX_MIN_THRESHOLD
);
1145 if (energy
> threshold
)
1147 if (v
->voxena
) v
->noise_energy
*= 0.75;
1149 } else v
->voxena
= 0;
1150 if (v
->lastvox
!= v
->voxena
)
1152 if (v
->enacount
++ >= ((v
->lastvox
) ? v
->offdebcnt
: v
->ondebcnt
))
1154 v
->lastvox
= v
->voxena
;
1157 } else v
->enacount
= 0;
1169 static int rpt_do_debug(int fd
, int argc
, char *argv
[]);
1170 static int rpt_do_dump(int fd
, int argc
, char *argv
[]);
1171 static int rpt_do_stats(int fd
, int argc
, char *argv
[]);
1172 static int rpt_do_lstats(int fd
, int argc
, char *argv
[]);
1173 static int rpt_do_nodes(int fd
, int argc
, char *argv
[]);
1174 static int rpt_do_local_nodes(int fd
, int argc
, char *argv
[]);
1175 static int rpt_do_reload(int fd
, int argc
, char *argv
[]);
1176 static int rpt_do_restart(int fd
, int argc
, char *argv
[]);
1177 static int rpt_do_fun(int fd
, int argc
, char *argv
[]);
1178 static int rpt_do_fun1(int fd
, int argc
, char *argv
[]);
1179 static int rpt_do_cmd(int fd
, int argc
, char *argv
[]);
1181 static char debug_usage
[] =
1182 "Usage: rpt debug level {0-7}\n"
1183 " Enables debug messages in app_rpt\n";
1185 static char dump_usage
[] =
1186 "Usage: rpt dump <nodename>\n"
1187 " Dumps struct debug info to log\n";
1189 static char dump_stats
[] =
1190 "Usage: rpt stats <nodename>\n"
1191 " Dumps node statistics to console\n";
1193 static char dump_lstats
[] =
1194 "Usage: rpt lstats <nodename>\n"
1195 " Dumps link statistics to console\n";
1197 static char dump_nodes
[] =
1198 "Usage: rpt nodes <nodename>\n"
1199 " Dumps a list of directly and indirectly connected nodes to the console\n";
1201 static char usage_local_nodes
[] =
1202 "Usage: rpt localnodes\n"
1203 " Dumps a list of the locally configured node numbers to the console.\n";
1205 static char reload_usage
[] =
1206 "Usage: rpt reload\n"
1207 " Reloads app_rpt running config parameters\n";
1209 static char restart_usage
[] =
1210 "Usage: rpt restart\n"
1211 " Restarts app_rpt\n";
1213 static char fun_usage
[] =
1214 "Usage: rpt fun <nodename> <command>\n"
1215 " Send a DTMF function to a node\n";
1217 static char cmd_usage
[] =
1218 "Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
1219 " Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
1221 #ifndef NEW_ASTERISK
1223 static struct ast_cli_entry cli_debug
=
1224 { { "rpt", "debug", "level" }, rpt_do_debug
,
1225 "Enable app_rpt debugging", debug_usage
};
1227 static struct ast_cli_entry cli_dump
=
1228 { { "rpt", "dump" }, rpt_do_dump
,
1229 "Dump app_rpt structs for debugging", dump_usage
};
1231 static struct ast_cli_entry cli_stats
=
1232 { { "rpt", "stats" }, rpt_do_stats
,
1233 "Dump node statistics", dump_stats
};
1235 static struct ast_cli_entry cli_nodes
=
1236 { { "rpt", "nodes" }, rpt_do_nodes
,
1237 "Dump node list", dump_nodes
};
1239 static struct ast_cli_entry cli_local_nodes
=
1240 { { "rpt", "localnodes" }, rpt_do_local_nodes
,
1241 "Dump list of local node numbers", usage_local_nodes
};
1243 static struct ast_cli_entry cli_lstats
=
1244 { { "rpt", "lstats" }, rpt_do_lstats
,
1245 "Dump link statistics", dump_lstats
};
1247 static struct ast_cli_entry cli_reload
=
1248 { { "rpt", "reload" }, rpt_do_reload
,
1249 "Reload app_rpt config", reload_usage
};
1251 static struct ast_cli_entry cli_restart
=
1252 { { "rpt", "restart" }, rpt_do_restart
,
1253 "Restart app_rpt", restart_usage
};
1255 static struct ast_cli_entry cli_fun
=
1256 { { "rpt", "fun" }, rpt_do_fun
,
1257 "Execute a DTMF function", fun_usage
};
1259 static struct ast_cli_entry cli_fun1
=
1260 { { "rpt", "fun1" }, rpt_do_fun1
,
1261 "Execute a DTMF function", fun_usage
};
1263 static struct ast_cli_entry cli_cmd
=
1264 { { "rpt", "cmd" }, rpt_do_cmd
,
1265 "Execute a DTMF function", cmd_usage
};
1270 * Telemetry defaults
1274 static struct telem_defaults tele_defs
[] = {
1275 {"ct1","|t(350,0,100,3072)(500,0,100,3072)(660,0,100,3072)"},
1276 {"ct2","|t(660,880,150,3072)"},
1277 {"ct3","|t(440,0,150,3072)"},
1278 {"ct4","|t(550,0,150,3072)"},
1279 {"ct5","|t(660,0,150,3072)"},
1280 {"ct6","|t(880,0,150,3072)"},
1281 {"ct7","|t(660,440,150,3072)"},
1282 {"ct8","|t(700,1100,150,3072)"},
1283 {"remotemon","|t(1600,0,75,2048)"},
1284 {"remotetx","|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048)"},
1285 {"cmdmode","|t(900,904,200,2048)"},
1286 {"functcomplete","|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)"}
1290 * Forward decl's - these suppress compiler warnings when funcs coded further down the file than thier invokation
1293 static int setrbi(struct rpt
*myrpt
);
1294 static int set_ft897(struct rpt
*myrpt
);
1295 static int set_ic706(struct rpt
*myrpt
);
1296 static int setkenwood(struct rpt
*myrpt
);
1297 static int set_tm271(struct rpt
*myrpt
);
1298 static int setrbi_check(struct rpt
*myrpt
);
1303 * Define function protos for function table here
1306 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1307 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1308 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1309 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1310 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1311 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1312 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1313 static int function_playback(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
);
1318 static struct function_table_tag function_table
[] = {
1319 {"cop", function_cop
},
1320 {"autopatchup", function_autopatchup
},
1321 {"autopatchdn", function_autopatchdn
},
1322 {"ilink", function_ilink
},
1323 {"status", function_status
},
1324 {"remote", function_remote
},
1325 {"macro", function_macro
},
1326 {"playback", function_playback
}
1329 static long diskavail(struct rpt
*myrpt
)
1331 struct statfs statfsbuf
;
1333 if (!myrpt
->p
.archivedir
) return(0);
1334 if (statfs(myrpt
->p
.archivedir
,&statfsbuf
) == -1)
1336 ast_log(LOG_WARNING
,"Cannot get filesystem size for %s node %s\n",
1337 myrpt
->p
.archivedir
,myrpt
->name
);
1340 return(statfsbuf
.f_bavail
);
1343 static void flush_telem(struct rpt
*myrpt
)
1345 struct rpt_tele
*telem
;
1347 ast_log(LOG_NOTICE
, "flush_telem()!!");
1348 rpt_mutex_lock(&myrpt
->lock
);
1349 telem
= myrpt
->tele
.next
;
1350 while(telem
!= &myrpt
->tele
)
1352 if (telem
->mode
!= SETREMOTE
) ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
1353 telem
= telem
->next
;
1355 rpt_mutex_unlock(&myrpt
->lock
);
1358 return via error priority
1360 static int priority_jump(struct rpt
*myrpt
, struct ast_channel
*chan
)
1364 // if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
1365 if (ast_goto_if_exists(chan
, chan
->context
, chan
->exten
, chan
->priority
+ 101) == 0){
1374 static int linkcount(struct rpt
*myrpt
)
1377 char *reverse_patch_state
;
1380 reverse_patch_state
= "DOWN";
1382 l
= myrpt
->links
.next
;
1383 while(l
&& (l
!= &myrpt
->links
)){
1384 if(numoflinks
>= MAX_STAT_LINKS
){
1385 ast_log(LOG_WARNING
,
1386 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS
);
1389 //if (l->name[0] == '0'){ /* Skip '0' nodes */
1390 // reverse_patch_state = "UP";
1398 ast_log(LOG_NOTICE
, "numoflinks=%i\n",numoflinks
);
1402 * Retrieve a memory channel
1403 * Return 0 if sucessful,
1404 * -1 if channel not found,
1407 static int retreive_memory(struct rpt
*myrpt
, char *memory
)
1409 char tmp
[30], *s
, *s1
, *val
;
1411 if (debug
)ast_log(LOG_NOTICE
, "memory=%s block=%s\n",memory
,myrpt
->p
.memory
);
1413 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.memory
, memory
);
1417 strncpy(tmp
,val
,sizeof(tmp
) - 1);
1418 tmp
[sizeof(tmp
)-1] = 0;
1420 s
= strchr(tmp
,',');
1428 strncpy(myrpt
->freq
, tmp
, sizeof(myrpt
->freq
) - 1);
1429 strncpy(myrpt
->rxpl
, s
, sizeof(myrpt
->rxpl
) - 1);
1430 strncpy(myrpt
->txpl
, s
, sizeof(myrpt
->rxpl
) - 1);
1431 myrpt
->remmode
= REM_MODE_FM
;
1432 myrpt
->offset
= REM_SIMPLEX
;
1433 myrpt
->powerlevel
= REM_MEDPWR
;
1434 myrpt
->txplon
= myrpt
->rxplon
= 0;
1439 strcpy(myrpt
->rxpl
, "100.0");
1440 strcpy(myrpt
->txpl
, "100.0");
1441 myrpt
->remmode
= REM_MODE_AM
;
1445 strcpy(myrpt
->rxpl
, "100.0");
1446 strcpy(myrpt
->txpl
, "100.0");
1447 myrpt
->remmode
= REM_MODE_LSB
;
1450 myrpt
->remmode
= REM_MODE_FM
;
1454 myrpt
->powerlevel
= REM_LOWPWR
;
1458 myrpt
->powerlevel
= REM_HIPWR
;
1463 myrpt
->powerlevel
= REM_MEDPWR
;
1467 myrpt
->offset
= REM_MINUS
;
1471 myrpt
->offset
= REM_PLUS
;
1476 myrpt
->offset
= REM_SIMPLEX
;
1491 strcpy(myrpt
->rxpl
, "100.0");
1492 strcpy(myrpt
->txpl
, "100.0");
1493 myrpt
->remmode
= REM_MODE_USB
;
1504 static void birdbath(struct rpt
*myrpt
)
1506 struct rpt_tele
*telem
;
1508 ast_log(LOG_NOTICE
, "birdbath!!");
1509 rpt_mutex_lock(&myrpt
->lock
);
1510 telem
= myrpt
->tele
.next
;
1511 while(telem
!= &myrpt
->tele
)
1513 if (telem
->mode
== PARROT
) ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
1514 telem
= telem
->next
;
1516 rpt_mutex_unlock(&myrpt
->lock
);
1519 static void do_dtmf_phone(struct rpt
*myrpt
, struct rpt_link
*mylink
, char c
)
1523 l
= myrpt
->links
.next
;
1524 /* go thru all the links */
1525 while(l
!= &myrpt
->links
)
1532 /* dont send to self */
1533 if (mylink
&& (l
== mylink
))
1539 if (l
->chan
) ast_senddigit(l
->chan
,c
,0);
1541 if (l
->chan
) ast_senddigit(l
->chan
,c
);
1548 /* node logging function */
1549 static void donodelog(struct rpt
*myrpt
,char *str
)
1551 struct nodelog
*nodep
;
1554 if (!myrpt
->p
.archivedir
) return;
1555 nodep
= (struct nodelog
*)ast_malloc(sizeof(struct nodelog
));
1558 ast_log(LOG_ERROR
,"Cannot get memory for node log");
1561 time(&nodep
->timestamp
);
1562 strncpy(nodep
->archivedir
,myrpt
->p
.archivedir
,
1563 sizeof(nodep
->archivedir
) - 1);
1564 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d%H%M%S",
1565 localtime(&nodep
->timestamp
));
1566 snprintf(nodep
->str
,sizeof(nodep
->str
) - 1,"%s %s,%s\n",
1567 myrpt
->name
,datestr
,str
);
1568 ast_mutex_lock(&nodeloglock
);
1569 insque((struct qelem
*) nodep
, (struct qelem
*) nodelog
.prev
);
1570 ast_mutex_unlock(&nodeloglock
);
1573 /* must be called locked */
1574 static void do_dtmf_local(struct rpt
*myrpt
, char c
)
1578 static const char* dtmf_tones
[] = {
1579 "!941+1336/200,!0/200", /* 0 */
1580 "!697+1209/200,!0/200", /* 1 */
1581 "!697+1336/200,!0/200", /* 2 */
1582 "!697+1477/200,!0/200", /* 3 */
1583 "!770+1209/200,!0/200", /* 4 */
1584 "!770+1336/200,!0/200", /* 5 */
1585 "!770+1477/200,!0/200", /* 6 */
1586 "!852+1209/200,!0/200", /* 7 */
1587 "!852+1336/200,!0/200", /* 8 */
1588 "!852+1477/200,!0/200", /* 9 */
1589 "!697+1633/200,!0/200", /* A */
1590 "!770+1633/200,!0/200", /* B */
1591 "!852+1633/200,!0/200", /* C */
1592 "!941+1633/200,!0/200", /* D */
1593 "!941+1209/200,!0/200", /* * */
1594 "!941+1477/200,!0/200" }; /* # */
1599 snprintf(myrpt
->dtmf_local_str
+ strlen(myrpt
->dtmf_local_str
),sizeof(myrpt
->dtmf_local_str
) - 1,"%c",c
);
1600 if (!myrpt
->dtmf_local_timer
)
1601 myrpt
->dtmf_local_timer
= DTMF_LOCAL_STARTTIME
;
1604 if (myrpt
->dtmf_local_timer
== 1)
1607 ast_log(LOG_NOTICE
,"time out dtmf_local_timer=%i\n",myrpt
->dtmf_local_timer
);
1609 /* if anything in the string */
1610 if (myrpt
->dtmf_local_str
[0])
1612 digit
= myrpt
->dtmf_local_str
[0];
1613 myrpt
->dtmf_local_str
[0] = 0;
1614 for(i
= 1; myrpt
->dtmf_local_str
[i
]; i
++)
1616 myrpt
->dtmf_local_str
[i
- 1] =
1617 myrpt
->dtmf_local_str
[i
];
1619 myrpt
->dtmf_local_str
[i
- 1] = 0;
1620 myrpt
->dtmf_local_timer
= DTMF_LOCAL_TIME
;
1621 rpt_mutex_unlock(&myrpt
->lock
);
1622 if (digit
>= '0' && digit
<='9')
1623 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[digit
-'0'], 0);
1624 else if (digit
>= 'A' && digit
<= 'D')
1625 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[digit
-'A'+10], 0);
1626 else if (digit
== '*')
1627 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[14], 0);
1628 else if (digit
== '#')
1629 ast_playtones_start(myrpt
->txchannel
, 0, dtmf_tones
[15], 0);
1632 ast_log(LOG_DEBUG
, "Unable to generate DTMF tone '%c' for '%s'\n", digit
, myrpt
->txchannel
->name
);
1634 rpt_mutex_lock(&myrpt
->lock
);
1638 myrpt
->dtmf_local_timer
= 0;
1643 static int setdtr(int fd
, int enable
)
1645 struct termios mode
;
1647 if (fd
< 0) return -1;
1648 if (tcgetattr(fd
, &mode
)) {
1649 ast_log(LOG_WARNING
, "Unable to get serial parameters for dtr: %s\n", strerror(errno
));
1654 cfsetspeed(&mode
, B9600
);
1658 cfsetspeed(&mode
, B0
);
1661 if (tcsetattr(fd
, TCSADRAIN
, &mode
)) {
1662 ast_log(LOG_WARNING
, "Unable to set serial parameters for dtr: %s\n", strerror(errno
));
1665 if (enable
) usleep(100000);
1669 static int openserial(struct rpt
*myrpt
,char *fname
)
1671 struct termios mode
;
1674 fd
= open(fname
,O_RDWR
);
1677 ast_log(LOG_WARNING
,"Cannot open serial port %s\n",fname
);
1680 memset(&mode
, 0, sizeof(mode
));
1681 if (tcgetattr(fd
, &mode
)) {
1682 ast_log(LOG_WARNING
, "Unable to get serial parameters on %s: %s\n", fname
, strerror(errno
));
1688 mode
.c_iflag
&= ~(IGNBRK
|BRKINT
|PARMRK
|ISTRIP
1689 |INLCR
|IGNCR
|ICRNL
|IXON
);
1690 mode
.c_lflag
&= ~(ECHO
|ECHONL
|ICANON
|ISIG
|IEXTEN
);
1691 mode
.c_cflag
&= ~(CSIZE
|PARENB
|CRTSCTS
);
1692 mode
.c_cflag
|= CS8
;
1693 mode
.c_cc
[VTIME
] = 3;
1694 mode
.c_cc
[VMIN
] = 1;
1697 cfsetispeed(&mode
, B9600
);
1698 cfsetospeed(&mode
, B9600
);
1699 if (tcsetattr(fd
, TCSANOW
, &mode
))
1700 ast_log(LOG_WARNING
, "Unable to set serial parameters on %s: %s\n", fname
, strerror(errno
));
1701 if(!strcmp(myrpt
->remoterig
, remote_rig_kenwood
)) setdtr(fd
,0);
1703 if (debug
)ast_log(LOG_NOTICE
,"Opened serial port %s\n",fname
);
1707 static void mdc1200_notify(struct rpt
*myrpt
,char *fromnode
, unsigned int unit
)
1711 ast_verbose("Got MDC-1200 ID %04X from local system (%s)\n",
1716 ast_verbose("Got MDC-1200 ID %04X from node %s (%s)\n",
1717 unit
,fromnode
,myrpt
->name
);
1721 #ifdef _MDC_DECODE_H_
1723 static void mdc1200_send(struct rpt
*myrpt
, unsigned int unit
)
1726 struct ast_frame wf
;
1730 sprintf(str
,"I %s %04X",myrpt
->name
,unit
);
1732 wf
.frametype
= AST_FRAME_TEXT
;
1736 wf
.datalen
= strlen(str
) + 1;
1740 l
= myrpt
->links
.next
;
1741 /* otherwise, send it to all of em */
1742 while(l
!= &myrpt
->links
)
1744 if (l
->name
[0] == '0')
1750 if (l
->chan
) ast_write(l
->chan
,&wf
);
1758 static char func_xlat(struct rpt
*myrpt
,char c
,struct rpt_xlat
*xlat
)
1765 /* if too much time, reset the skate machine */
1766 if ((now
- xlat
->lastone
) > MAXXLATTIME
)
1768 xlat
->funcindex
= xlat
->endindex
= 0;
1770 if (xlat
->funccharseq
[0] && (c
== xlat
->funccharseq
[xlat
->funcindex
++]))
1772 time(&xlat
->lastone
);
1774 if (!xlat
->funccharseq
[xlat
->funcindex
])
1776 xlat
->funcindex
= xlat
->endindex
= 0;
1777 return(myrpt
->p
.funcchar
);
1779 } else xlat
->funcindex
= 0;
1780 if (xlat
->endcharseq
[0] && (c
== xlat
->endcharseq
[xlat
->endindex
++]))
1782 time(&xlat
->lastone
);
1784 if (!xlat
->endcharseq
[xlat
->endindex
])
1786 xlat
->funcindex
= xlat
->endindex
= 0;
1787 return(myrpt
->p
.endchar
);
1789 } else xlat
->endindex
= 0;
1790 /* if in middle of decode seq, send nothing back */
1791 if (gotone
) return(0);
1792 /* if no pass chars specified, return em all */
1793 if (!xlat
->passchars
[0]) return(c
);
1794 /* if a "pass char", pass it */
1795 if (strchr(xlat
->passchars
,c
)) return(c
);
1800 * Return a pointer to the first non-whitespace character
1803 static char *eatwhite(char *s
)
1805 while((*s
== ' ') || (*s
== 0x09)){ /* get rid of any leading white space */
1814 * Break up a delimited string into a table of substrings
1816 * str - delimited string ( will be modified )
1817 * strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
1818 * limit- maximum number of substrings to process
1823 static int finddelim(char *str
, char *strp
[], int limit
)
1835 for(l
= 0; *str
&& (l
< limit
) ; str
++)
1837 if (*str
== QUOTECHR
)
1846 strp
[i
- 1] = str
+ 1;
1850 if ((*str
== DELIMCHR
) && (!inquo
))
1854 strp
[i
++] = str
+ 1;
1862 send asterisk frame text message on the current tx channel
1864 static int send_usb_txt(struct rpt
*myrpt
, char *txt
)
1866 struct ast_frame wf
;
1868 if (debug
)ast_log(LOG_NOTICE
, "send_usb_txt %s\n",txt
);
1869 wf
.frametype
= AST_FRAME_TEXT
;
1873 wf
.datalen
= strlen(txt
) + 1;
1876 ast_write(myrpt
->txchannel
,&wf
);
1879 /* must be called locked */
1880 static void __mklinklist(struct rpt
*myrpt
, struct rpt_link
*mylink
, char *buf
)
1886 buf
[0] = 0; /* clear output buffer */
1887 if (myrpt
->remote
) return;
1888 /* go thru all links */
1889 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
1891 /* if is not a real link, ignore it */
1892 if (l
->name
[0] == '0') continue;
1893 /* dont count our stuff */
1894 if (l
== mylink
) continue;
1895 if (mylink
&& (!strcmp(l
->name
,mylink
->name
))) continue;
1896 /* figure out mode to report */
1897 mode
= 'T'; /* use Tranceive by default */
1898 if (!l
->mode
) mode
= 'R'; /* indicate RX for our mode */
1899 if (!l
->thisconnected
) mode
= 'C'; /* indicate connecting */
1900 spos
= strlen(buf
); /* current buf size (b4 we add our stuff) */
1906 /* add nodes into buffer */
1909 snprintf(buf
+ spos
,MAXLINKLIST
- spos
,
1910 "%c%s,%s",mode
,l
->name
,l
->linklist
);
1912 else /* if no nodes, add this node into buffer */
1914 snprintf(buf
+ spos
,MAXLINKLIST
- spos
,
1915 "%c%s",mode
,l
->name
);
1917 /* if we are in tranceive mode, let all modes stand */
1918 if (mode
== 'T') continue;
1919 /* downgrade everyone on this node if appropriate */
1920 for(i
= spos
; buf
[i
]; i
++)
1922 if (buf
[i
] == 'T') buf
[i
] = mode
;
1923 if ((buf
[i
] == 'R') && (mode
== 'C')) buf
[i
] = mode
;
1929 /* must be called locked */
1930 static void __kickshort(struct rpt
*myrpt
)
1934 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
1936 /* if is not a real link, ignore it */
1937 if (l
->name
[0] == '0') continue;
1938 l
->linklisttimer
= LINKLISTSHORTTIME
;
1940 myrpt
->linkposttimer
= LINKPOSTSHORTTIME
;
1944 static void statpost(struct rpt
*myrpt
,char *pairs
)
1952 if (!myrpt
->p
.statpost_url
) return;
1953 str
= ast_malloc(strlen(pairs
) + strlen(myrpt
->p
.statpost_url
) + 200);
1954 astr
= ast_strdup(myrpt
->p
.statpost_program
);
1955 if ((!str
) || (!astr
)) return;
1956 n
= finddelim(astr
,astrs
,100);
1958 ast_mutex_lock(&myrpt
->statpost_lock
);
1959 seq
= ++myrpt
->statpost_seqno
;
1960 ast_mutex_unlock(&myrpt
->statpost_lock
);
1964 sprintf(str
,"%s?node=%s&time=%u&seqno=%u",myrpt
->p
.statpost_url
,
1965 myrpt
->name
,(unsigned int) now
,seq
);
1966 if (pairs
) sprintf(str
+ strlen(str
),"&%s",pairs
);
1967 if (!(pid
= fork()))
1969 execv(astrs
[0],astrs
);
1970 ast_log(LOG_ERROR
, "exec of %s failed.\n", astrs
[0]);
1979 static char *node_lookup(struct rpt
*myrpt
,char *digitbuf
)
1985 static time_t last
= 0;
1986 static struct ast_config
*ourcfg
= NULL
;
1987 struct ast_variable
*vp
;
1989 /* try to look it up locally first */
1990 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.nodes
, digitbuf
);
1991 if (val
) return(val
);
1992 ast_mutex_lock(&nodelookuplock
);
1993 /* if file does not exist */
1994 if (stat(myrpt
->p
.extnodefile
,&mystat
) == -1)
1996 if (ourcfg
) ast_config_destroy(ourcfg
);
1998 ast_mutex_unlock(&nodelookuplock
);
2001 /* if we need to reload */
2002 if (mystat
.st_mtime
> last
)
2004 if (ourcfg
) ast_config_destroy(ourcfg
);
2006 ourcfg
= ast_config_load(myrpt
->p
.extnodefile
,config_flags
);
2008 ourcfg
= ast_config_load(myrpt
->p
.extnodefile
);
2010 /* if file not there, just bail */
2013 ast_mutex_unlock(&nodelookuplock
);
2016 /* reset "last" time */
2017 last
= mystat
.st_mtime
;
2019 /* determine longest node length again */
2021 vp
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.nodes
);
2023 j
= strlen(vp
->name
);
2024 if (j
> longestnode
)
2029 vp
= ast_variable_browse(ourcfg
, myrpt
->p
.extnodes
);
2031 j
= strlen(vp
->name
);
2032 if (j
> longestnode
)
2037 myrpt
->longestnode
= longestnode
;
2041 val
= (char *) ast_variable_retrieve(ourcfg
, myrpt
->p
.extnodes
, digitbuf
);
2042 ast_mutex_unlock(&nodelookuplock
);
2047 * Match a keyword in a list, and return index of string plus 1 if there was a match,* else return 0.
2048 * If param is passed in non-null, then it will be set to the first character past the match
2051 static int matchkeyword(char *string
, char **param
, char *keywords
[])
2054 for( i
= 0 ; keywords
[i
] ; i
++){
2055 ls
= strlen(keywords
[i
]);
2060 if(!strncmp(string
, keywords
[i
], ls
)){
2062 *param
= string
+ ls
;
2071 * Skip characters in string which are in charlist, and return a pointer to the
2072 * first non-matching character
2075 static char *skipchars(char *string
, char *charlist
)
2079 for(i
= 0; charlist
[i
] ; i
++){
2080 if(*string
== charlist
[i
]){
2093 static int myatoi(char *str
)
2097 if (str
== NULL
) return -1;
2098 /* leave this %i alone, non-base-10 input is useful here */
2099 if (sscanf(str
,"%i",&ret
) != 1) return -1;
2103 static int mycompar(const void *a
, const void *b
)
2105 char **x
= (char **) a
;
2106 char **y
= (char **) b
;
2109 if ((**x
< '0') || (**x
> '9')) xoff
= 1; else xoff
= 0;
2110 if ((**y
< '0') || (**y
> '9')) yoff
= 1; else yoff
= 0;
2111 return(strcmp((*x
) + xoff
,(*y
) + yoff
));
2114 static int topcompar(const void *a
, const void *b
)
2116 struct rpt_topkey
*x
= (struct rpt_topkey
*) a
;
2117 struct rpt_topkey
*y
= (struct rpt_topkey
*) b
;
2119 return(x
->timesince
- y
->timesince
);
2124 /* rpt filter routine */
2125 static void rpt_filter(struct rpt
*myrpt
, volatile short *buf
, int len
)
2128 struct rptfilter
*f
;
2130 for(i
= 0; i
< len
; i
++)
2132 for(j
= 0; j
< MAXFILTERS
; j
++)
2134 f
= &myrpt
->filters
[j
];
2135 if (!*f
->desc
) continue;
2136 f
->x0
= f
->x1
; f
->x1
= f
->x2
;
2137 f
->x2
= ((float)buf
[i
]) / f
->gain
;
2138 f
->y0
= f
->y1
; f
->y1
= f
->y2
;
2139 f
->y2
= (f
->x0
+ f
->x2
) + f
->const0
* f
->x1
2140 + (f
->const1
* f
->y0
) + (f
->const2
* f
->y1
);
2141 buf
[i
] = (short)f
->y2
;
2150 Get the time for the machine's time zone
2151 Note: Asterisk requires a copy of localtime
2152 in the /etc directory for this to work properly.
2153 If /etc/localtime is not present, you will get
2154 GMT time! This is especially important on systems
2155 running embedded linux distributions as they don't usually
2156 have support for locales.
2158 If OLD_ASTERISK is defined, then the older localtime_r
2159 function will be used. The /etc/localtime file is not
2160 required in this case. This provides backward compatibility
2161 with Asterisk 1.2 systems.
2166 static void rpt_localtime( time_t * t
, struct ast_tm
*lt
)
2172 ast_localtime(&tv
, lt
, NULL
);
2177 static void rpt_localtime( time_t * t
, struct tm
*lt
)
2182 ast_localtime(t
, lt
, NULL
);
2188 /* Retrieve an int from a config file */
2190 static int retrieve_astcfgint(struct rpt
*myrpt
,char *category
, char *name
, int min
, int max
, int defl
)
2194 char include_zero
= 0;
2196 if(min
< 0){ /* If min is negative, this means include 0 as a valid entry */
2201 var
= (char *) ast_variable_retrieve(myrpt
->cfg
, category
, name
);
2204 if(include_zero
&& !ret
)
2217 static void load_rpt_vars(int n
,int init
)
2220 int i
,j
,longestnode
;
2221 struct ast_variable
*vp
;
2222 struct ast_config
*cfg
;
2225 static char *cs_keywords
[] = {"rptena","rptdis","apena","apdis","lnkena","lnkdis","totena","totdis","skena","skdis",
2226 "ufena","ufdis","atena","atdis",NULL
};
2228 if (option_verbose
> 2)
2229 ast_verbose(VERBOSE_PREFIX_3
"%s config for repeater %s\n",
2230 (init
) ? "Loading initial" : "Re-Loading",rpt_vars
[n
].name
);
2231 ast_mutex_lock(&rpt_vars
[n
].lock
);
2232 if (rpt_vars
[n
].cfg
) ast_config_destroy(rpt_vars
[n
].cfg
);
2234 cfg
= ast_config_load("rpt.conf",config_flags
);
2236 cfg
= ast_config_load("rpt.conf");
2239 ast_mutex_unlock(&rpt_vars
[n
].lock
);
2240 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
2243 rpt_vars
[n
].cfg
= cfg
;
2244 this = rpt_vars
[n
].name
;
2245 memset(&rpt_vars
[n
].p
,0,sizeof(rpt_vars
[n
].p
));
2249 int savearea
= (char *)&rpt_vars
[n
].p
- (char *)&rpt_vars
[n
];
2251 cp
= (char *) &rpt_vars
[n
].p
;
2252 memset(cp
+ sizeof(rpt_vars
[n
].p
),0,
2253 sizeof(rpt_vars
[n
]) - (sizeof(rpt_vars
[n
].p
) + savearea
));
2254 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
2255 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
2256 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
2257 rpt_vars
[n
].tailmessagen
= 0;
2260 /* zot out filters stuff */
2261 memset(&rpt_vars
[n
].filters
,0,sizeof(rpt_vars
[n
].filters
));
2263 val
= (char *) ast_variable_retrieve(cfg
,this,"context");
2264 if (val
) rpt_vars
[n
].p
.ourcontext
= val
;
2265 else rpt_vars
[n
].p
.ourcontext
= this;
2266 val
= (char *) ast_variable_retrieve(cfg
,this,"callerid");
2267 if (val
) rpt_vars
[n
].p
.ourcallerid
= val
;
2268 val
= (char *) ast_variable_retrieve(cfg
,this,"accountcode");
2269 if (val
) rpt_vars
[n
].p
.acctcode
= val
;
2270 val
= (char *) ast_variable_retrieve(cfg
,this,"idrecording");
2271 if (val
) rpt_vars
[n
].p
.ident
= val
;
2272 val
= (char *) ast_variable_retrieve(cfg
,this,"hangtime");
2273 if (val
) rpt_vars
[n
].p
.hangtime
= atoi(val
);
2274 else rpt_vars
[n
].p
.hangtime
= HANGTIME
;
2275 val
= (char *) ast_variable_retrieve(cfg
,this,"althangtime");
2276 if (val
) rpt_vars
[n
].p
.althangtime
= atoi(val
);
2277 else rpt_vars
[n
].p
.althangtime
= HANGTIME
;
2278 val
= (char *) ast_variable_retrieve(cfg
,this,"totime");
2279 if (val
) rpt_vars
[n
].p
.totime
= atoi(val
);
2280 else rpt_vars
[n
].p
.totime
= TOTIME
;
2281 val
= (char *) ast_variable_retrieve(cfg
,this,"voxtimeout");
2282 if (val
) rpt_vars
[n
].p
.voxtimeout_ms
= atoi(val
);
2283 else rpt_vars
[n
].p
.voxtimeout_ms
= VOX_TIMEOUT_MS
;
2284 val
= (char *) ast_variable_retrieve(cfg
,this,"voxrecover");
2285 if (val
) rpt_vars
[n
].p
.voxrecover_ms
= atoi(val
);
2286 else rpt_vars
[n
].p
.voxrecover_ms
= VOX_RECOVER_MS
;
2287 val
= (char *) ast_variable_retrieve(cfg
,this,"simplexpatchdelay");
2288 if (val
) rpt_vars
[n
].p
.simplexpatchdelay
= atoi(val
);
2289 else rpt_vars
[n
].p
.simplexpatchdelay
= SIMPLEX_PATCH_DELAY
;
2290 val
= (char *) ast_variable_retrieve(cfg
,this,"simplexphonedelay");
2291 if (val
) rpt_vars
[n
].p
.simplexphonedelay
= atoi(val
);
2292 else rpt_vars
[n
].p
.simplexphonedelay
= SIMPLEX_PHONE_DELAY
;
2293 val
= (char *) ast_variable_retrieve(cfg
,this,"statpost_program");
2294 if (val
) rpt_vars
[n
].p
.statpost_program
= val
;
2295 else rpt_vars
[n
].p
.statpost_program
= STATPOST_PROGRAM
;
2296 rpt_vars
[n
].p
.statpost_url
=
2297 (char *) ast_variable_retrieve(cfg
,this,"statpost_url");
2298 rpt_vars
[n
].p
.tailmessagetime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailmessagetime", 0, 2400000, 0);
2299 rpt_vars
[n
].p
.tailsquashedtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "tailsquashedtime", 0, 2400000, 0);
2300 rpt_vars
[n
].p
.duplex
= retrieve_astcfgint(&rpt_vars
[n
],this,"duplex",0,4,2);
2301 rpt_vars
[n
].p
.idtime
= retrieve_astcfgint(&rpt_vars
[n
],this, "idtime", -60000, 2400000, IDTIME
); /* Enforce a min max including zero */
2302 rpt_vars
[n
].p
.politeid
= retrieve_astcfgint(&rpt_vars
[n
],this, "politeid", 30000, 300000, POLITEID
); /* Enforce a min max */
2303 val
= (char *) ast_variable_retrieve(cfg
,this,"tonezone");
2304 if (val
) rpt_vars
[n
].p
.tonezone
= val
;
2305 rpt_vars
[n
].p
.tailmessages
[0] = 0;
2306 rpt_vars
[n
].p
.tailmessagemax
= 0;
2307 val
= (char *) ast_variable_retrieve(cfg
,this,"tailmessagelist");
2308 if (val
) rpt_vars
[n
].p
.tailmessagemax
= finddelim(val
, rpt_vars
[n
].p
.tailmessages
, 500);
2309 val
= (char *) ast_variable_retrieve(cfg
,this,"memory");
2310 if (!val
) val
= MEMORY
;
2311 rpt_vars
[n
].p
.memory
= val
;
2312 val
= (char *) ast_variable_retrieve(cfg
,this,"macro");
2313 if (!val
) val
= MACRO
;
2314 rpt_vars
[n
].p
.macro
= val
;
2315 val
= (char *) ast_variable_retrieve(cfg
,this,"tonemacro");
2316 if (!val
) val
= TONEMACRO
;
2317 rpt_vars
[n
].p
.tonemacro
= val
;
2318 val
= (char *) ast_variable_retrieve(cfg
,this,"startup_macro");
2319 if (val
) rpt_vars
[n
].p
.startupmacro
= val
;
2320 val
= (char *) ast_variable_retrieve(cfg
,this,"iobase");
2321 /* do not use atoi() here, we need to be able to have
2322 the input specified in hex or decimal so we use
2324 if ((!val
) || (sscanf(val
,"%i",&rpt_vars
[n
].p
.iobase
) != 1))
2325 rpt_vars
[n
].p
.iobase
= DEFAULT_IOBASE
;
2326 val
= (char *) ast_variable_retrieve(cfg
,this,"ioport");
2327 rpt_vars
[n
].p
.ioport
= val
;
2328 val
= (char *) ast_variable_retrieve(cfg
,this,"functions");
2332 rpt_vars
[n
].p
.simple
= 1;
2334 rpt_vars
[n
].p
.functions
= val
;
2335 val
= (char *) ast_variable_retrieve(cfg
,this,"link_functions");
2336 if (val
) rpt_vars
[n
].p
.link_functions
= val
;
2338 rpt_vars
[n
].p
.link_functions
= rpt_vars
[n
].p
.functions
;
2339 val
= (char *) ast_variable_retrieve(cfg
,this,"phone_functions");
2340 if (val
) rpt_vars
[n
].p
.phone_functions
= val
;
2341 val
= (char *) ast_variable_retrieve(cfg
,this,"dphone_functions");
2342 if (val
) rpt_vars
[n
].p
.dphone_functions
= val
;
2343 val
= (char *) ast_variable_retrieve(cfg
,this,"alt_functions");
2344 if (val
) rpt_vars
[n
].p
.alt_functions
= val
;
2345 val
= (char *) ast_variable_retrieve(cfg
,this,"funcchar");
2346 if (!val
) rpt_vars
[n
].p
.funcchar
= FUNCCHAR
; else
2347 rpt_vars
[n
].p
.funcchar
= *val
;
2348 val
= (char *) ast_variable_retrieve(cfg
,this,"endchar");
2349 if (!val
) rpt_vars
[n
].p
.endchar
= ENDCHAR
; else
2350 rpt_vars
[n
].p
.endchar
= *val
;
2351 val
= (char *) ast_variable_retrieve(cfg
,this,"nobusyout");
2352 if (val
) rpt_vars
[n
].p
.nobusyout
= ast_true(val
);
2353 val
= (char *) ast_variable_retrieve(cfg
,this,"notelemtx");
2354 if (val
) rpt_vars
[n
].p
.notelemtx
= ast_true(val
);
2355 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_dtmf");
2356 if (val
) rpt_vars
[n
].p
.propagate_dtmf
= ast_true(val
);
2357 val
= (char *) ast_variable_retrieve(cfg
,this,"propagate_phonedtmf");
2358 if (val
) rpt_vars
[n
].p
.propagate_phonedtmf
= ast_true(val
);
2359 val
= (char *) ast_variable_retrieve(cfg
,this,"linktolink");
2360 if (val
) rpt_vars
[n
].p
.linktolink
= ast_true(val
);
2361 val
= (char *) ast_variable_retrieve(cfg
,this,"nodes");
2362 if (!val
) val
= NODES
;
2363 rpt_vars
[n
].p
.nodes
= val
;
2364 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodes");
2365 if (!val
) val
= EXTNODES
;
2366 rpt_vars
[n
].p
.extnodes
= val
;
2367 val
= (char *) ast_variable_retrieve(cfg
,this,"extnodefile");
2368 if (!val
) val
= EXTNODEFILE
;
2369 rpt_vars
[n
].p
.extnodefile
= val
;
2370 val
= (char *) ast_variable_retrieve(cfg
,this,"archivedir");
2371 if (val
) rpt_vars
[n
].p
.archivedir
= val
;
2372 val
= (char *) ast_variable_retrieve(cfg
,this,"authlevel");
2373 if (val
) rpt_vars
[n
].p
.authlevel
= atoi(val
);
2374 else rpt_vars
[n
].p
.authlevel
= 0;
2375 val
= (char *) ast_variable_retrieve(cfg
,this,"parrot");
2376 if (val
) rpt_vars
[n
].p
.parrotmode
= ast_true(val
) * 2;
2377 else rpt_vars
[n
].p
.parrotmode
= 0;
2378 val
= (char *) ast_variable_retrieve(cfg
,this,"parrottime");
2379 if (val
) rpt_vars
[n
].p
.parrottime
= atoi(val
);
2380 else rpt_vars
[n
].p
.parrottime
= PARROTTIME
;
2381 val
= (char *) ast_variable_retrieve(cfg
,this,"rptnode");
2382 rpt_vars
[n
].p
.rptnode
= val
;
2383 val
= (char *) ast_variable_retrieve(cfg
,this,"mars");
2384 if (val
) rpt_vars
[n
].p
.remote_mars
= atoi(val
);
2385 else rpt_vars
[n
].p
.remote_mars
= 0;
2386 val
= (char *) ast_variable_retrieve(cfg
,this,"monminblocks");
2387 if (val
) rpt_vars
[n
].p
.monminblocks
= atol(val
);
2388 else rpt_vars
[n
].p
.monminblocks
= DEFAULT_MONITOR_MIN_DISK_BLOCKS
;
2389 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_inact_timeout");
2390 if (val
) rpt_vars
[n
].p
.remoteinacttimeout
= atoi(val
);
2391 else rpt_vars
[n
].p
.remoteinacttimeout
= DEFAULT_REMOTE_INACT_TIMEOUT
;
2392 val
= (char *) ast_variable_retrieve(cfg
,this,"civaddr");
2393 if (val
) rpt_vars
[n
].p
.civaddr
= atoi(val
);
2394 else rpt_vars
[n
].p
.civaddr
= DEFAULT_CIV_ADDR
;
2395 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout");
2396 if (val
) rpt_vars
[n
].p
.remotetimeout
= atoi(val
);
2397 else rpt_vars
[n
].p
.remotetimeout
= DEFAULT_REMOTE_TIMEOUT
;
2398 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning");
2399 if (val
) rpt_vars
[n
].p
.remotetimeoutwarning
= atoi(val
);
2400 else rpt_vars
[n
].p
.remotetimeoutwarning
= DEFAULT_REMOTE_TIMEOUT_WARNING
;
2401 val
= (char *) ast_variable_retrieve(cfg
,this,"remote_timeout_warning_freq");
2402 if (val
) rpt_vars
[n
].p
.remotetimeoutwarningfreq
= atoi(val
);
2403 else rpt_vars
[n
].p
.remotetimeoutwarningfreq
= DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ
;
2405 val
= (char *) ast_variable_retrieve(cfg
,this,"rxnotch");
2407 i
= finddelim(val
,strs
,MAXFILTERS
* 2);
2408 i
&= ~1; /* force an even number, rounded down */
2409 if (i
>= 2) for(j
= 0; j
< i
; j
+= 2)
2411 rpt_mknotch(atof(strs
[j
]),atof(strs
[j
+ 1]),
2412 &rpt_vars
[n
].filters
[j
>> 1].gain
,
2413 &rpt_vars
[n
].filters
[j
>> 1].const0
,
2414 &rpt_vars
[n
].filters
[j
>> 1].const1
,
2415 &rpt_vars
[n
].filters
[j
>> 1].const2
);
2416 sprintf(rpt_vars
[n
].filters
[j
>> 1].desc
,"%s Hz, BW = %s",
2417 strs
[j
],strs
[j
+ 1]);
2422 val
= (char *) ast_variable_retrieve(cfg
,this,"inxlat");
2424 memset(&rpt_vars
[n
].p
.inxlat
,0,sizeof(struct rpt_xlat
));
2425 i
= finddelim(val
,strs
,3);
2426 if (i
) strncpy(rpt_vars
[n
].p
.inxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
2427 if (i
> 1) strncpy(rpt_vars
[n
].p
.inxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
2428 if (i
> 2) strncpy(rpt_vars
[n
].p
.inxlat
.passchars
,strs
[2],MAXXLAT
- 1);
2430 val
= (char *) ast_variable_retrieve(cfg
,this,"outxlat");
2432 memset(&rpt_vars
[n
].p
.outxlat
,0,sizeof(struct rpt_xlat
));
2433 i
= finddelim(val
,strs
,3);
2434 if (i
) strncpy(rpt_vars
[n
].p
.outxlat
.funccharseq
,strs
[0],MAXXLAT
- 1);
2435 if (i
> 1) strncpy(rpt_vars
[n
].p
.outxlat
.endcharseq
,strs
[1],MAXXLAT
- 1);
2436 if (i
> 2) strncpy(rpt_vars
[n
].p
.outxlat
.passchars
,strs
[2],MAXXLAT
- 1);
2438 /* retreive the stanza name for the control states if there is one */
2439 val
= (char *) ast_variable_retrieve(cfg
,this,"controlstates");
2440 rpt_vars
[n
].p
.csstanzaname
= val
;
2442 /* retreive the stanza name for the scheduler if there is one */
2443 val
= (char *) ast_variable_retrieve(cfg
,this,"scheduler");
2444 rpt_vars
[n
].p
.skedstanzaname
= val
;
2446 /* retreive the stanza name for the txlimits */
2447 val
= (char *) ast_variable_retrieve(cfg
,this,"txlimits");
2448 rpt_vars
[n
].p
.txlimitsstanzaname
= val
;
2452 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.nodes
);
2455 j
= strlen(vp
->name
);
2456 if (j
> longestnode
)
2461 rpt_vars
[n
].longestnode
= longestnode
;
2464 * For this repeater, Determine the length of the longest function
2466 rpt_vars
[n
].longestfunc
= 0;
2467 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.functions
);
2469 j
= strlen(vp
->name
);
2470 if (j
> rpt_vars
[n
].longestfunc
)
2471 rpt_vars
[n
].longestfunc
= j
;
2475 * For this repeater, Determine the length of the longest function
2477 rpt_vars
[n
].link_longestfunc
= 0;
2478 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.link_functions
);
2480 j
= strlen(vp
->name
);
2481 if (j
> rpt_vars
[n
].link_longestfunc
)
2482 rpt_vars
[n
].link_longestfunc
= j
;
2485 rpt_vars
[n
].phone_longestfunc
= 0;
2486 if (rpt_vars
[n
].p
.phone_functions
)
2488 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.phone_functions
);
2490 j
= strlen(vp
->name
);
2491 if (j
> rpt_vars
[n
].phone_longestfunc
)
2492 rpt_vars
[n
].phone_longestfunc
= j
;
2496 rpt_vars
[n
].dphone_longestfunc
= 0;
2497 if (rpt_vars
[n
].p
.dphone_functions
)
2499 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.dphone_functions
);
2501 j
= strlen(vp
->name
);
2502 if (j
> rpt_vars
[n
].dphone_longestfunc
)
2503 rpt_vars
[n
].dphone_longestfunc
= j
;
2507 rpt_vars
[n
].alt_longestfunc
= 0;
2508 if (rpt_vars
[n
].p
.alt_functions
)
2510 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.alt_functions
);
2512 j
= strlen(vp
->name
);
2513 if (j
> rpt_vars
[n
].alt_longestfunc
)
2514 rpt_vars
[n
].alt_longestfunc
= j
;
2518 rpt_vars
[n
].macro_longest
= 1;
2519 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.macro
);
2521 j
= strlen(vp
->name
);
2522 if (j
> rpt_vars
[n
].macro_longest
)
2523 rpt_vars
[n
].macro_longest
= j
;
2527 /* Browse for control states */
2528 if(rpt_vars
[n
].p
.csstanzaname
)
2529 vp
= ast_variable_browse(cfg
, rpt_vars
[n
].p
.csstanzaname
);
2532 for( i
= 0 ; vp
&& (i
< MAX_SYSSTATES
) ; i
++){ /* Iterate over the number of control state lines in the stanza */
2533 int k
,nukw
,statenum
;
2534 statenum
=atoi(vp
->name
);
2535 strncpy(s1
, vp
->value
, 255);
2537 nukw
= finddelim(s1
,strs
,32);
2539 for (k
= 0 ; k
< nukw
; k
++){ /* for each user specified keyword */
2540 for(j
= 0 ; cs_keywords
[j
] != NULL
; j
++){ /* try to match to one in our internal table */
2541 if(!strcmp(strs
[k
],cs_keywords
[j
])){
2543 case 0: /* rptena */
2544 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 0;
2546 case 1: /* rptdis */
2547 rpt_vars
[n
].p
.s
[statenum
].txdisable
= 1;
2551 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 0;
2555 rpt_vars
[n
].p
.s
[statenum
].autopatchdisable
= 1;
2558 case 4: /* lnkena */
2559 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 0;
2562 case 5: /* lnkdis */
2563 rpt_vars
[n
].p
.s
[statenum
].linkfundisable
= 1;
2566 case 6: /* totena */
2567 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 0;
2570 case 7: /* totdis */
2571 rpt_vars
[n
].p
.s
[statenum
].totdisable
= 1;
2575 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 0;
2579 rpt_vars
[n
].p
.s
[statenum
].schedulerdisable
= 1;
2582 case 10: /* ufena */
2583 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 0;
2586 case 11: /* ufdis */
2587 rpt_vars
[n
].p
.s
[statenum
].userfundisable
= 1;
2590 case 12: /* atena */
2591 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 1;
2594 case 13: /* atdis */
2595 rpt_vars
[n
].p
.s
[statenum
].alternatetail
= 0;
2599 ast_log(LOG_WARNING
,
2600 "Unhandled control state keyword %s", cs_keywords
[i
]);
2608 ast_mutex_unlock(&rpt_vars
[n
].lock
);
2612 * Enable or disable debug output at a given level at the console
2615 static int rpt_do_debug(int fd
, int argc
, char *argv
[])
2620 return RESULT_SHOWUSAGE
;
2621 newlevel
= myatoi(argv
[3]);
2622 if((newlevel
< 0) || (newlevel
> 7))
2623 return RESULT_SHOWUSAGE
;
2625 ast_cli(fd
, "app_rpt Debugging enabled, previous level: %d, new level: %d\n", debug
, newlevel
);
2627 ast_cli(fd
, "app_rpt Debugging disabled\n");
2630 return RESULT_SUCCESS
;
2634 * Dump rpt struct debugging onto console
2637 static int rpt_do_dump(int fd
, int argc
, char *argv
[])
2642 return RESULT_SHOWUSAGE
;
2644 for(i
= 0; i
< nrpts
; i
++)
2646 if (!strcmp(argv
[2],rpt_vars
[i
].name
))
2648 rpt_vars
[i
].disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
2649 ast_cli(fd
, "app_rpt struct dump requested for node %s\n",argv
[2]);
2650 return RESULT_SUCCESS
;
2653 return RESULT_FAILURE
;
2657 * Dump statistics onto console
2660 static int rpt_do_stats(int fd
, int argc
, char *argv
[])
2663 int dailytxtime
, dailykerchunks
;
2665 int totalkerchunks
, dailykeyups
, totalkeyups
, timeouts
;
2666 int totalexecdcommands
, dailyexecdcommands
, hours
, minutes
, seconds
;
2668 long long totaltxtime
;
2670 char *listoflinks
[MAX_STAT_LINKS
];
2671 char *lastdtmfcommand
,*parrot_ena
;
2672 char *tot_state
, *ider_state
, *patch_state
;
2673 char *reverse_patch_state
, *sys_ena
, *tot_ena
, *link_ena
, *patch_ena
;
2674 char *sch_ena
, *input_signal
, *called_number
, *user_funs
, *tail_type
;
2677 static char *not_applicable
= "N/A";
2680 return RESULT_SHOWUSAGE
;
2682 tot_state
= ider_state
=
2683 patch_state
= reverse_patch_state
=
2684 input_signal
= not_applicable
;
2685 called_number
= lastdtmfcommand
= NULL
;
2688 for(i
= 0; i
< nrpts
; i
++)
2690 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2691 /* Make a copy of all stat variables while locked */
2692 myrpt
= &rpt_vars
[i
];
2693 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2694 uptime
= (int)(now
- starttime
);
2695 dailytxtime
= myrpt
->dailytxtime
;
2696 totaltxtime
= myrpt
->totaltxtime
;
2697 dailykeyups
= myrpt
->dailykeyups
;
2698 totalkeyups
= myrpt
->totalkeyups
;
2699 dailykerchunks
= myrpt
->dailykerchunks
;
2700 totalkerchunks
= myrpt
->totalkerchunks
;
2701 dailyexecdcommands
= myrpt
->dailyexecdcommands
;
2702 totalexecdcommands
= myrpt
->totalexecdcommands
;
2703 timeouts
= myrpt
->timeouts
;
2705 /* Traverse the list of connected nodes */
2706 reverse_patch_state
= "DOWN";
2708 l
= myrpt
->links
.next
;
2709 while(l
&& (l
!= &myrpt
->links
)){
2710 if(numoflinks
>= MAX_STAT_LINKS
){
2712 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS
);
2715 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2716 reverse_patch_state
= "UP";
2720 listoflinks
[numoflinks
] = ast_strdup(l
->name
);
2721 if(listoflinks
[numoflinks
] == NULL
){
2731 input_signal
= "YES";
2733 input_signal
= "NO";
2735 if(myrpt
->p
.parrotmode
)
2736 parrot_ena
= "ENABLED";
2738 parrot_ena
= "DISABLED";
2740 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
)
2741 sys_ena
= "DISABLED";
2743 sys_ena
= "ENABLED";
2745 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
)
2746 tot_ena
= "DISABLED";
2748 tot_ena
= "ENABLED";
2750 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
2751 link_ena
= "DISABLED";
2753 link_ena
= "ENABLED";
2755 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
2756 patch_ena
= "DISABLED";
2758 patch_ena
= "ENABLED";
2760 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
)
2761 sch_ena
= "DISABLED";
2763 sch_ena
= "ENABLED";
2765 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
)
2766 user_funs
= "DISABLED";
2768 user_funs
= "ENABLED";
2770 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
)
2771 tail_type
= "ALTERNATE";
2773 tail_type
= "STANDARD";
2776 tot_state
= "TIMED OUT!";
2777 else if(myrpt
->totimer
!= myrpt
->p
.totime
)
2778 tot_state
= "ARMED";
2780 tot_state
= "RESET";
2783 ider_state
= "QUEUED IN TAIL";
2784 else if(myrpt
->mustid
)
2785 ider_state
= "QUEUED FOR CLEANUP";
2787 ider_state
= "CLEAN";
2789 switch(myrpt
->callmode
){
2791 patch_state
= "DIALING";
2794 patch_state
= "CONNECTING";
2801 patch_state
= "CALL FAILED";
2805 patch_state
= "DOWN";
2808 if(strlen(myrpt
->exten
)){
2809 called_number
= ast_strdup(myrpt
->exten
);
2812 if(strlen(myrpt
->lastdtmfcommand
)){
2813 lastdtmfcommand
= ast_strdup(myrpt
->lastdtmfcommand
);
2815 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2817 ast_cli(fd
, "************************ NODE %s STATISTICS *************************\n\n", myrpt
->name
);
2818 ast_cli(fd
, "Selected system state............................: %d\n", myrpt
->p
.sysstate_cur
);
2819 ast_cli(fd
, "Signal on input..................................: %s\n", input_signal
);
2820 ast_cli(fd
, "System...........................................: %s\n", sys_ena
);
2821 ast_cli(fd
, "Parrot Mode......................................: %s\n", parrot_ena
);
2822 ast_cli(fd
, "Scheduler........................................: %s\n", sch_ena
);
2823 ast_cli(fd
, "Tail Time........................................: %s\n", tail_type
);
2824 ast_cli(fd
, "Time out timer...................................: %s\n", tot_ena
);
2825 ast_cli(fd
, "Time out timer state.............................: %s\n", tot_state
);
2826 ast_cli(fd
, "Time outs since system initialization............: %d\n", timeouts
);
2827 ast_cli(fd
, "Identifier state.................................: %s\n", ider_state
);
2828 ast_cli(fd
, "Kerchunks today..................................: %d\n", dailykerchunks
);
2829 ast_cli(fd
, "Kerchunks since system initialization............: %d\n", totalkerchunks
);
2830 ast_cli(fd
, "Keyups today.....................................: %d\n", dailykeyups
);
2831 ast_cli(fd
, "Keyups since system initialization...............: %d\n", totalkeyups
);
2832 ast_cli(fd
, "DTMF commands today..............................: %d\n", dailyexecdcommands
);
2833 ast_cli(fd
, "DTMF commands since system initialization........: %d\n", totalexecdcommands
);
2834 ast_cli(fd
, "Last DTMF command executed.......................: %s\n",
2835 (lastdtmfcommand
&& strlen(lastdtmfcommand
)) ? lastdtmfcommand
: not_applicable
);
2836 hours
= dailytxtime
/3600000;
2837 dailytxtime
%= 3600000;
2838 minutes
= dailytxtime
/60000;
2839 dailytxtime
%= 60000;
2840 seconds
= dailytxtime
/1000;
2841 dailytxtime
%= 1000;
2843 ast_cli(fd
, "TX time today....................................: %02d:%02d:%02d.%d\n",
2844 hours
, minutes
, seconds
, dailytxtime
);
2846 hours
= (int) totaltxtime
/3600000;
2847 totaltxtime
%= 3600000;
2848 minutes
= (int) totaltxtime
/60000;
2849 totaltxtime
%= 60000;
2850 seconds
= (int) totaltxtime
/1000;
2851 totaltxtime
%= 1000;
2853 ast_cli(fd
, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
2854 hours
, minutes
, seconds
, (int) totaltxtime
);
2856 hours
= uptime
/3600;
2858 minutes
= uptime
/60;
2861 ast_cli(fd
, "Uptime...........................................: %02d:%02d:%02d\n",
2862 hours
, minutes
, uptime
);
2864 ast_cli(fd
, "Nodes currently connected to us..................: ");
2866 ast_cli(fd
,"<NONE>");
2869 for(j
= 0 ;j
< numoflinks
; j
++){
2870 ast_cli(fd
, "%s", listoflinks
[j
]);
2876 if((numoflinks
- 1) - j
> 0)
2883 ast_cli(fd
, "Autopatch........................................: %s\n", patch_ena
);
2884 ast_cli(fd
, "Autopatch state..................................: %s\n", patch_state
);
2885 ast_cli(fd
, "Autopatch called number..........................: %s\n",
2886 (called_number
&& strlen(called_number
)) ? called_number
: not_applicable
);
2887 ast_cli(fd
, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state
);
2888 ast_cli(fd
, "User linking commands............................: %s\n", link_ena
);
2889 ast_cli(fd
, "User functions...................................: %s\n\n", user_funs
);
2891 for(j
= 0; j
< numoflinks
; j
++){ /* ast_free() all link names */
2892 ast_free(listoflinks
[j
]);
2895 ast_free(called_number
);
2897 if(lastdtmfcommand
){
2898 ast_free(lastdtmfcommand
);
2900 return RESULT_SUCCESS
;
2903 return RESULT_FAILURE
;
2907 * Link stats function
2910 static int rpt_do_lstats(int fd
, int argc
, char *argv
[])
2916 struct rpt_lstat
*s
,*t
;
2917 struct rpt_lstat s_head
;
2919 return RESULT_SHOWUSAGE
;
2922 s_head
.next
= &s_head
;
2923 s_head
.prev
= &s_head
;
2925 for(i
= 0; i
< nrpts
; i
++)
2927 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
2928 /* Make a copy of all stat variables while locked */
2929 myrpt
= &rpt_vars
[i
];
2930 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
2931 /* Traverse the list of connected nodes */
2933 l
= myrpt
->links
.next
;
2934 while(l
&& (l
!= &myrpt
->links
)){
2935 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
2939 if((s
= (struct rpt_lstat
*) ast_malloc(sizeof(struct rpt_lstat
))) == NULL
){
2940 ast_log(LOG_ERROR
, "Malloc failed in rpt_do_lstats\n");
2941 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2942 return RESULT_FAILURE
;
2944 memset(s
, 0, sizeof(struct rpt_lstat
));
2945 strncpy(s
->name
, l
->name
, MAXREMSTR
- 1);
2946 if (l
->chan
) pbx_substitute_variables_helper(l
->chan
, "${IAXPEER(CURRENTCHANNEL)}", s
->peer
, MAXPEERSTR
- 1);
2947 else strcpy(s
->peer
,"(none)");
2949 s
->outbound
= l
->outbound
;
2950 s
->reconnects
= l
->reconnects
;
2951 s
->connecttime
= l
->connecttime
;
2952 s
->thisconnected
= l
->thisconnected
;
2953 memcpy(s
->chan_stat
,l
->chan_stat
,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2954 insque((struct qelem
*) s
, (struct qelem
*) s_head
.next
);
2955 memset(l
->chan_stat
,0,NRPTSTAT
* sizeof(struct rpt_chan_stat
));
2958 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
2959 ast_cli(fd
, "NODE PEER RECONNECTS DIRECTION CONNECT TIME CONNECT STATE\n");
2960 ast_cli(fd
, "---- ---- ---------- --------- ------------ -------------\n");
2962 for(s
= s_head
.next
; s
!= &s_head
; s
= s
->next
){
2963 int hours
, minutes
, seconds
;
2964 long long connecttime
= s
->connecttime
;
2966 hours
= (int) connecttime
/3600000;
2967 connecttime
%= 3600000;
2968 minutes
= (int) connecttime
/60000;
2969 connecttime
%= 60000;
2970 seconds
= (int) connecttime
/1000;
2971 connecttime
%= 1000;
2972 snprintf(conntime
, 20, "%02d:%02d:%02d.%d",
2973 hours
, minutes
, seconds
, (int) connecttime
);
2975 if(s
->thisconnected
)
2976 connstate
= "ESTABLISHED";
2978 connstate
= "CONNECTING";
2979 ast_cli(fd
, "%-10s%-20s%-12d%-11s%-20s%-20s\n",
2980 s
->name
, s
->peer
, s
->reconnects
, (s
->outbound
)? "OUT":"IN", conntime
, connstate
);
2982 /* destroy our local link queue */
2984 while(s
!= &s_head
){
2987 remque((struct qelem
*)t
);
2990 return RESULT_SUCCESS
;
2993 return RESULT_FAILURE
;
2997 * List all nodes connected, directly or indirectly
3000 static int rpt_do_nodes(int fd
, int argc
, char *argv
[])
3004 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
3007 return RESULT_SHOWUSAGE
;
3009 for(i
= 0; i
< nrpts
; i
++)
3011 if (!strcmp(argv
[2],rpt_vars
[i
].name
)){
3012 /* Make a copy of all stat variables while locked */
3013 myrpt
= &rpt_vars
[i
];
3014 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
3015 __mklinklist(myrpt
,NULL
,lbuf
);
3016 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
3018 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
3020 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
3022 ast_cli(fd
, "************************* CONNECTED NODES *************************\n\n");
3026 ast_cli(fd
,"<NONE>");
3030 ast_cli(fd
, "%s", strs
[j
]);
3040 return RESULT_SUCCESS
;
3043 return RESULT_FAILURE
;
3047 * List all locally configured nodes
3050 static int rpt_do_local_nodes(int fd
, int argc
, char *argv
[])
3054 ast_cli(fd
, "\nNode\n----\n");
3055 for (i
=0; i
< nrpts
; i
++)
3057 ast_cli(fd
, "%s\n", rpt_vars
[i
].name
);
3060 return RESULT_SUCCESS
;
3068 static int rpt_do_reload(int fd
, int argc
, char *argv
[])
3072 if (argc
> 2) return RESULT_SHOWUSAGE
;
3074 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
3076 return RESULT_FAILURE
;
3083 static int rpt_do_restart(int fd
, int argc
, char *argv
[])
3087 if (argc
> 2) return RESULT_SHOWUSAGE
;
3088 for(i
= 0; i
< nrpts
; i
++)
3090 if (rpt_vars
[i
].rxchannel
) ast_softhangup(rpt_vars
[i
].rxchannel
,AST_SOFTHANGUP_DEV
);
3092 return RESULT_FAILURE
;
3097 * send an app_rpt DTMF function from the CLI
3100 static int rpt_do_fun(int fd
, int argc
, char *argv
[])
3104 if (argc
!= 4) return RESULT_SHOWUSAGE
;
3106 for(i
= 0; i
< nrpts
; i
++){
3107 if(!strcmp(argv
[2], rpt_vars
[i
].name
)){
3108 struct rpt
*myrpt
= &rpt_vars
[i
];
3109 rpt_mutex_lock(&myrpt
->lock
);
3110 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(argv
[3])){
3111 rpt_mutex_unlock(&myrpt
->lock
);
3115 myrpt
->macrotimer
= MACROTIME
;
3116 strncat(myrpt
->macrobuf
,argv
[3],MAXMACRO
- 1);
3118 rpt_mutex_unlock(&myrpt
->lock
);
3122 ast_cli(fd
, "Function decoder busy");
3124 return RESULT_FAILURE
;
3127 the convention is that macros in the data from the rpt() application
3128 are all at the end of the data, separated by the | and start with a *
3129 when put into the macro buffer, the characters have their high bit
3130 set so the macro processor knows they came from the application data
3131 and to use the alt-functions table.
3134 static int rpt_push_alt_macro(struct rpt
*myrpt
, char *sptr
)
3138 rpt_mutex_lock(&myrpt
->lock
);
3139 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(sptr
)){
3140 rpt_mutex_unlock(&myrpt
->lock
);
3145 if (debug
)ast_log(LOG_NOTICE
, "rpt_push_alt_macro %s\n",sptr
);
3146 myrpt
->macrotimer
= MACROTIME
;
3147 for(x
= 0; *(sptr
+ x
); x
++)
3148 myrpt
->macrobuf
[x
] = *(sptr
+ x
) | 0x80;
3151 rpt_mutex_unlock(&myrpt
->lock
);
3153 if(busy
)ast_log(LOG_WARNING
, "Function decoder busy on app_rpt command macro.\n");
3158 allows us to test rpt() application data commands
3160 static int rpt_do_fun1(int fd
, int argc
, char *argv
[])
3164 if (argc
!= 4) return RESULT_SHOWUSAGE
;
3166 for(i
= 0; i
< nrpts
; i
++){
3167 if(!strcmp(argv
[2], rpt_vars
[i
].name
)){
3168 struct rpt
*myrpt
= &rpt_vars
[i
];
3169 rpt_push_alt_macro(myrpt
,argv
[3]);
3172 return RESULT_FAILURE
;
3175 * send an app_rpt **command** from the CLI
3178 static int rpt_do_cmd(int fd
, int argc
, char *argv
[])
3182 int maxActions
= sizeof(function_table
)/sizeof(struct function_table_tag
);
3185 int thisAction
= -1;
3186 struct rpt
*myrpt
= NULL
;
3187 if (argc
!= 6) return RESULT_SHOWUSAGE
;
3189 for(i
= 0; i
< nrpts
; i
++)
3191 if(!strcmp(argv
[2], rpt_vars
[i
].name
))
3194 myrpt
= &rpt_vars
[i
];
3196 } /* if !strcmp... */
3201 ast_cli(fd
, "Unknown node number %s.\n", argv
[2]);
3202 return RESULT_FAILURE
;
3203 } /* if thisRpt < 0 */
3205 /* Look up the action */
3206 l
= strlen(argv
[3]);
3207 for(i
= 0 ; i
< maxActions
; i
++)
3209 if(!strncasecmp(argv
[3], function_table
[i
].action
, l
))
3213 } /* if !strncasecmp... */
3218 ast_cli(fd
, "Unknown action name %s.\n", argv
[3]);
3219 return RESULT_FAILURE
;
3220 } /* if thisAction < 0 */
3222 /* at this point, it looks like all the arguments make sense... */
3224 rpt_mutex_lock(&myrpt
->lock
);
3226 if (rpt_vars
[thisRpt
].cmdAction
.state
== CMD_STATE_IDLE
)
3228 rpt_vars
[thisRpt
].cmdAction
.state
= CMD_STATE_BUSY
;
3229 rpt_vars
[thisRpt
].cmdAction
.functionNumber
= thisAction
;
3230 strncpy(rpt_vars
[thisRpt
].cmdAction
.param
, argv
[4], MAXDTMF
);
3231 strncpy(rpt_vars
[thisRpt
].cmdAction
.digits
, argv
[5], MAXDTMF
);
3232 rpt_vars
[thisRpt
].cmdAction
.command_source
= SOURCE_RPT
;
3233 rpt_vars
[thisRpt
].cmdAction
.state
= CMD_STATE_READY
;
3234 } /* if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE */
3238 } /* if (rpt_vars[thisRpt].cmdAction.state == CMD_STATE_IDLE */
3239 rpt_mutex_unlock(&myrpt
->lock
);
3241 return (busy
? RESULT_FAILURE
: RESULT_SUCCESS
);
3242 } /* rpt_do_cmd() */
3244 static int play_tone_pair(struct ast_channel
*chan
, int f1
, int f2
, int duration
, int amplitude
)
3248 if ((res
= ast_tonepair_start(chan
, f1
, f2
, duration
, amplitude
)))
3251 while(chan
->generatordata
) {
3252 if (ast_safe_sleep(chan
,1)) return -1;
3258 static int play_tone(struct ast_channel
*chan
, int freq
, int duration
, int amplitude
)
3260 return play_tone_pair(chan
, freq
, 0, duration
, amplitude
);
3263 static int play_silence(struct ast_channel
*chan
, int duration
)
3265 return play_tone_pair(chan
, 0, 0, duration
, 0);
3270 static char *res2cli(int r
)
3275 case RESULT_SUCCESS
:
3276 return(CLI_SUCCESS
);
3277 case RESULT_SHOWUSAGE
:
3278 return(CLI_SHOWUSAGE
);
3280 return(CLI_FAILURE
);
3284 static char *handle_cli_debug(struct ast_cli_entry
*e
,
3285 int cmd
, struct ast_cli_args
*a
)
3289 e
->command
= "rpt debug level";
3290 e
->usage
= debug_usage
;
3295 return res2cli(rpt_do_debug(a
->fd
,a
->argc
,a
->argv
));
3298 static char *handle_cli_dump(struct ast_cli_entry
*e
,
3299 int cmd
, struct ast_cli_args
*a
)
3303 e
->command
= "rpt dump level";
3304 e
->usage
= dump_usage
;
3309 return res2cli(rpt_do_dump(a
->fd
,a
->argc
,a
->argv
));
3313 static char *handle_cli_stats(struct ast_cli_entry
*e
,
3314 int cmd
, struct ast_cli_args
*a
)
3318 e
->command
= "rpt stats";
3319 e
->usage
= dump_stats
;
3324 return res2cli(rpt_do_stats(a
->fd
,a
->argc
,a
->argv
));
3327 static char *handle_cli_nodes(struct ast_cli_entry
*e
,
3328 int cmd
, struct ast_cli_args
*a
)
3332 e
->command
= "rpt nodes";
3333 e
->usage
= dump_nodes
;
3338 return res2cli(rpt_do_nodes(a
->fd
,a
->argc
,a
->argv
));
3341 static char *handle_cli_local_nodes(struct ast_cli_entry
*e
,
3342 int cmd
, struct ast_cli_args
*a
)
3346 e
->command
= "rpt localnodes";
3347 e
->usage
= usage_local_nodes
;
3352 return res2cli(rpt_do_local_nodes(a
->fd
,a
->argc
,a
->argv
));
3355 static char *handle_cli_lstats(struct ast_cli_entry
*e
,
3356 int cmd
, struct ast_cli_args
*a
)
3360 e
->command
= "rpt lstats";
3361 e
->usage
= dump_lstats
;
3366 return res2cli(rpt_do_lstats(a
->fd
,a
->argc
,a
->argv
));
3369 static char *handle_cli_reload(struct ast_cli_entry
*e
,
3370 int cmd
, struct ast_cli_args
*a
)
3374 e
->command
= "rpt reload";
3375 e
->usage
= reload_usage
;
3380 return res2cli(rpt_do_reload(a
->fd
,a
->argc
,a
->argv
));
3383 static char *handle_cli_restart(struct ast_cli_entry
*e
,
3384 int cmd
, struct ast_cli_args
*a
)
3388 e
->command
= "rpt restart";
3389 e
->usage
= restart_usage
;
3394 return res2cli(rpt_do_restart(a
->fd
,a
->argc
,a
->argv
));
3397 static char *handle_cli_fun(struct ast_cli_entry
*e
,
3398 int cmd
, struct ast_cli_args
*a
)
3402 e
->command
= "rpt fun";
3403 e
->usage
= fun_usage
;
3408 return res2cli(rpt_do_fun(a
->fd
,a
->argc
,a
->argv
));
3411 static char *handle_cli_fun1(struct ast_cli_entry
*e
,
3412 int cmd
, struct ast_cli_args
*a
)
3416 e
->command
= "rpt fun1";
3417 e
->usage
= fun_usage
;
3422 return res2cli(rpt_do_fun1(a
->fd
,a
->argc
,a
->argv
));
3425 static char *handle_cli_cmd(struct ast_cli_entry
*e
,
3426 int cmd
, struct ast_cli_args
*a
)
3430 e
->command
= "rpt cmd";
3431 e
->usage
= cmd_usage
;
3436 return res2cli(rpt_do_cmd(a
->fd
,a
->argc
,a
->argv
));
3439 static struct ast_cli_entry rpt_cli
[] = {
3440 AST_CLI_DEFINE(handle_cli_debug
,"Enable app_rpt debugging"),
3441 AST_CLI_DEFINE(handle_cli_dump
,"Dump app_rpt structs for debugging"),
3442 AST_CLI_DEFINE(handle_cli_stats
,"Dump node statistics"),
3443 AST_CLI_DEFINE(handle_cli_nodes
,"Dump node list"),
3444 AST_CLI_DEFINE(handle_cli_local_nodes
, "Dump list of local node numbers"),
3445 AST_CLI_DEFINE(handle_cli_lstats
,"Dump link statistics"),
3446 AST_CLI_DEFINE(handle_cli_reload
,"Reload app_rpt config"),
3447 AST_CLI_DEFINE(handle_cli_restart
,"Restart app_rpt"),
3448 AST_CLI_DEFINE(handle_cli_fun
,"Execute a DTMF function"),
3449 AST_CLI_DEFINE(handle_cli_fun1
,"Execute a DTMF function"),
3450 AST_CLI_DEFINE(handle_cli_cmd
,"Execute a DTMF function")
3455 static int send_morse(struct ast_channel
*chan
, char *string
, int speed
, int freq
, int amplitude
)
3458 static struct morse_bits mbits
[] = {
3523 int intralettertime
;
3524 int interlettertime
;
3534 /* Approximate the dot time from the speed arg. */
3536 dottime
= 900/speed
;
3538 /* Establish timing releationships */
3540 dashtime
= 3 * dottime
;
3541 intralettertime
= dottime
;
3542 interlettertime
= dottime
* 4 ;
3543 interwordtime
= dottime
* 7;
3545 for(;(*string
) && (!res
); string
++){
3549 /* Convert lower case to upper case */
3551 if((c
>= 'a') && (c
<= 'z'))
3554 /* Can't deal with any char code greater than Z, skip it */
3559 /* If space char, wait the inter word time */
3563 res
= play_silence(chan
, interwordtime
);
3567 /* Subtract out control char offset to match our table */
3571 /* Get the character data */
3574 ddcomb
= mbits
[c
].ddcomb
;
3576 /* Send the character */
3580 res
= play_tone(chan
, freq
, (ddcomb
& 1) ? dashtime
: dottime
, amplitude
);
3582 res
= play_silence(chan
, intralettertime
);
3586 /* Wait the interletter time */
3589 res
= play_silence(chan
, interlettertime
- intralettertime
);
3592 /* Wait for all the frames to be sent */
3595 res
= ast_waitstream(chan
, "");
3596 ast_stopstream(chan
);
3599 * Wait for the DAHDI driver to physically write the tone blocks to the hardware
3602 for(i
= 0; i
< 20 ; i
++){
3603 flags
= DAHDI_IOMUX_WRITEEMPTY
| DAHDI_IOMUX_NOWAIT
;
3604 res
= ioctl(chan
->fds
[0], DAHDI_IOMUX
, &flags
);
3605 if(flags
& DAHDI_IOMUX_WRITEEMPTY
)
3607 if( ast_safe_sleep(chan
, 50)){
3617 static int send_tone_telemetry(struct ast_channel
*chan
, char *tonestring
)
3633 p
= stringp
= ast_strdup(tonestring
);
3636 tonesubset
= strsep(&stringp
,")");
3639 if(sscanf(tonesubset
,"(%d,%d,%d,%d", &f1
, &f2
, &duration
, &litude
) != 4)
3641 res
= play_tone_pair(chan
, f1
, f2
, duration
, amplitude
);
3648 res
= play_tone_pair(chan
, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
3651 res
= ast_waitstream(chan
, "");
3653 ast_stopstream(chan
);
3656 * Wait for the DAHDI driver to physically write the tone blocks to the hardware
3659 for(i
= 0; i
< 20 ; i
++){
3660 flags
= DAHDI_IOMUX_WRITEEMPTY
| DAHDI_IOMUX_NOWAIT
;
3661 res
= ioctl(chan
->fds
[0], DAHDI_IOMUX
, &flags
);
3662 if(flags
& DAHDI_IOMUX_WRITEEMPTY
)
3664 if( ast_safe_sleep(chan
, 50)){
3674 static int sayfile(struct ast_channel
*mychannel
,char *fname
)
3678 res
= ast_streamfile(mychannel
, fname
, mychannel
->language
);
3680 res
= ast_waitstream(mychannel
, "");
3682 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3683 ast_stopstream(mychannel
);
3687 static int saycharstr(struct ast_channel
*mychannel
,char *str
)
3691 res
= ast_say_character_str(mychannel
,str
,NULL
,mychannel
->language
);
3693 res
= ast_waitstream(mychannel
, "");
3695 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3696 ast_stopstream(mychannel
);
3700 static int saynum(struct ast_channel
*mychannel
, int num
)
3703 res
= ast_say_number(mychannel
, num
, NULL
, mychannel
->language
, NULL
);
3705 res
= ast_waitstream(mychannel
, "");
3707 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
3708 ast_stopstream(mychannel
);
3712 /* say a node and nodename. Try to look in dir referred to by nodenames in
3713 config, and see if there's a custom node file to play, and if so, play it */
3715 static int saynode(struct rpt
*myrpt
, struct ast_channel
*mychannel
, char *name
)
3718 char *val
,fname
[300];
3720 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "nodenames");
3721 if (!val
) val
= NODENAMES
;
3722 snprintf(fname
,sizeof(fname
) - 1,"%s/%s",val
,name
);
3723 if (ast_fileexists(fname
,NULL
,mychannel
->language
) > 0)
3724 return(sayfile(mychannel
,fname
));
3725 res
= sayfile(mychannel
,"rpt/node");
3727 res
= ast_say_character_str(mychannel
,name
,NULL
,mychannel
->language
);
3731 static int telem_any(struct rpt
*myrpt
,struct ast_channel
*chan
, char *entry
)
3736 static int morsespeed
;
3737 static int morsefreq
;
3738 static int morseampl
;
3739 static int morseidfreq
= 0;
3740 static int morseidampl
;
3741 static char mcat
[] = MORSE
;
3745 if(!morseidfreq
){ /* Get the morse parameters if not already loaded */
3746 morsespeed
= retrieve_astcfgint(myrpt
, mcat
, "speed", 5, 20, 20);
3747 morsefreq
= retrieve_astcfgint(myrpt
, mcat
, "frequency", 300, 3000, 800);
3748 morseampl
= retrieve_astcfgint(myrpt
, mcat
, "amplitude", 200, 8192, 4096);
3749 morseidampl
= retrieve_astcfgint(myrpt
, mcat
, "idamplitude", 200, 8192, 2048);
3750 morseidfreq
= retrieve_astcfgint(myrpt
, mcat
, "idfrequency", 300, 3000, 330);
3753 /* Is it a file, or a tone sequence? */
3755 if(entry
[0] == '|'){
3757 if((c
>= 'a')&&(c
<= 'z'))
3761 case 'I': /* Morse ID */
3762 res
= send_morse(chan
, entry
+ 2, morsespeed
, morseidfreq
, morseidampl
);
3765 case 'M': /* Morse Message */
3766 res
= send_morse(chan
, entry
+ 2, morsespeed
, morsefreq
, morseampl
);
3769 case 'T': /* Tone sequence */
3770 res
= send_tone_telemetry(chan
, entry
+ 2);
3777 res
= sayfile(chan
, entry
); /* File */
3782 * This function looks up a telemetry name in the config file, and does a telemetry response as configured.
3784 * 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
3787 static int telem_lookup(struct rpt
*myrpt
,struct ast_channel
*chan
, char *node
, char *name
)
3794 char *telemetry_save
;
3797 telemetry_save
= NULL
;
3800 /* Retrieve the section name for telemetry from the node section */
3801 telemetry
= (char *) ast_variable_retrieve(myrpt
->cfg
, node
, TELEMETRY
);
3803 telemetry_save
= ast_strdup(telemetry
);
3804 if(!telemetry_save
){
3805 ast_log(LOG_WARNING
,"ast_strdup() failed in telem_lookup()\n");
3808 entry
= (char *) ast_variable_retrieve(myrpt
->cfg
, telemetry_save
, name
);
3811 /* Try to look up the telemetry name */
3814 /* Telemetry name wasn't found in the config file, use the default */
3815 for(i
= 0; i
< sizeof(tele_defs
)/sizeof(struct telem_defaults
) ; i
++){
3816 if(!strcasecmp(tele_defs
[i
].name
, name
))
3817 entry
= tele_defs
[i
].value
;
3822 if (chan
) telem_any(myrpt
,chan
, entry
);
3828 ast_free(telemetry_save
);
3833 * Retrieve a wait interval
3836 static int get_wait_interval(struct rpt
*myrpt
, int type
)
3840 char *wait_times_save
;
3842 wait_times_save
= NULL
;
3843 wait_times
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "wait_times");
3846 wait_times_save
= ast_strdup(wait_times
);
3847 if(!wait_times_save
)
3855 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "telemwait", 500, 5000, 1000);
3862 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "idwait",250,5000,500);
3869 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "unkeywait",50,5000,1000);
3876 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "linkunkeywait",500,5000,1000);
3883 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "calltermwait",500,5000,1500);
3890 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "compwait",500,5000,200);
3897 interval
= retrieve_astcfgint(myrpt
,wait_times_save
, "parrotwait",500,5000,200);
3907 ast_free(wait_times_save
);
3913 * Wait a configurable interval of time
3915 static void wait_interval(struct rpt
*myrpt
, int type
, struct ast_channel
*chan
)
3918 interval
= get_wait_interval(myrpt
, type
);
3920 ast_log(LOG_NOTICE
,"Delay interval = %d\n", interval
);
3922 ast_safe_sleep(chan
,interval
);
3924 ast_log(LOG_NOTICE
,"Delay complete\n");
3928 static int split_freq(char *mhz
, char *decimals
, char *freq
);
3930 static void *rpt_tele_thread(void *this)
3932 DAHDI_CONFINFO ci
; /* conference info */
3933 int res
= 0,haslink
,hastx
,hasremote
,imdone
= 0, unkeys_queued
, x
;
3934 struct rpt_tele
*mytele
= (struct rpt_tele
*)this;
3935 struct rpt_tele
*tlist
;
3937 struct rpt_link
*l
,*l1
,linkbase
;
3938 struct ast_channel
*mychannel
;
3939 int id_malloc
, vmajor
, vminor
, m
;
3940 char *p
,*ct
,*ct_copy
,*ident
, *nodename
,*cp
;
3943 struct ast_tm localtm
;
3947 char lbuf
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
3949 char mhz
[MAXREMSTR
];
3950 char decimals
[MAXREMSTR
];
3952 struct dahdi_params par
;
3955 /* get a pointer to myrpt */
3956 myrpt
= mytele
->rpt
;
3958 /* Snag copies of a few key myrpt variables */
3959 rpt_mutex_lock(&myrpt
->lock
);
3960 nodename
= ast_strdup(myrpt
->name
);
3963 fprintf(stderr
,"rpt:Sorry unable strdup nodename\n");
3964 rpt_mutex_lock(&myrpt
->lock
);
3965 remque((struct qelem
*)mytele
);
3966 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3967 rpt_mutex_unlock(&myrpt
->lock
);
3972 if (myrpt
->p
.ident
){
3973 ident
= ast_strdup(myrpt
->p
.ident
);
3976 fprintf(stderr
,"rpt:Sorry unable strdup ident\n");
3977 rpt_mutex_lock(&myrpt
->lock
);
3978 remque((struct qelem
*)mytele
);
3979 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",
3980 __LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
3981 rpt_mutex_unlock(&myrpt
->lock
);
3995 rpt_mutex_unlock(&myrpt
->lock
);
3999 /* allocate a pseudo-channel thru asterisk */
4000 mychannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
4003 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
4004 rpt_mutex_lock(&myrpt
->lock
);
4005 remque((struct qelem
*)mytele
);
4006 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
4007 rpt_mutex_unlock(&myrpt
->lock
);
4014 #ifdef AST_CDR_FLAG_POST_DISABLED
4016 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
4018 rpt_mutex_lock(&myrpt
->lock
);
4019 mytele
->chan
= mychannel
;
4020 rpt_mutex_unlock(&myrpt
->lock
);
4022 while((mytele
->mode
!= SETREMOTE
) && (mytele
->mode
!= UNKEY
) &&
4023 (mytele
->mode
!= LINKUNKEY
))
4025 rpt_mutex_lock(&myrpt
->lock
);
4026 if (!myrpt
->active_telem
)
4028 myrpt
->active_telem
= mytele
;
4029 rpt_mutex_unlock(&myrpt
->lock
);
4032 rpt_mutex_unlock(&myrpt
->lock
);
4036 /* make a conference for the tx */
4038 /* If the telemetry is only intended for a local audience, */
4039 /* only connect the ID audio to the local tx conference so */
4040 /* linked systems can't hear it */
4041 ci
.confno
= (((mytele
->mode
== ID
) || (mytele
->mode
== IDTALKOVER
) || (mytele
->mode
== UNKEY
) ||
4042 (mytele
->mode
== TAILMSG
) || (mytele
->mode
== LINKUNKEY
) || (mytele
->mode
== TIMEOUT
) ||
4043 (mytele
->mode
== PARROT
) || (mytele
->mode
== STATS_TIME_LOCAL
)) ?
4044 myrpt
->txconf
: myrpt
->conf
);
4045 ci
.confmode
= DAHDI_CONF_CONFANN
;
4046 /* first put the channel on the conference in announce mode */
4047 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4049 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4050 rpt_mutex_lock(&myrpt
->lock
);
4051 myrpt
->active_telem
= NULL
;
4052 remque((struct qelem
*)mytele
);
4053 rpt_mutex_unlock(&myrpt
->lock
);
4054 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
4059 ast_hangup(mychannel
);
4062 ast_stopstream(mychannel
);
4063 switch(mytele
->mode
)
4068 wait_interval(myrpt
, (mytele
->mode
== ID
) ? DLY_ID
: DLY_TELEM
,mychannel
);
4069 res
= telem_any(myrpt
,mychannel
, ident
);
4074 res
= ast_streamfile(mychannel
, myrpt
->p
.tailmessages
[myrpt
->tailmessagen
], mychannel
->language
);
4078 p
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "idtalkover");
4080 res
= telem_any(myrpt
,mychannel
, p
);
4085 /* wait a little bit longer */
4086 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4087 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchup");
4088 if(res
< 0){ /* Then default message */
4089 res
= ast_streamfile(mychannel
, "rpt/callproceeding", mychannel
->language
);
4093 /* wait a little bit longer */
4094 wait_interval(myrpt
, DLY_CALLTERM
, mychannel
);
4095 res
= telem_lookup(myrpt
, mychannel
, myrpt
->name
, "patchdown");
4096 if(res
< 0){ /* Then default message */
4097 res
= ast_streamfile(mychannel
, "rpt/callterminated", mychannel
->language
);
4101 /* wait a little bit */
4102 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4103 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
4105 case MACRO_NOTFOUND
:
4106 /* wait a little bit */
4107 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4108 res
= ast_streamfile(mychannel
, "rpt/macro_notfound", mychannel
->language
);
4111 /* wait a little bit */
4112 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4113 res
= ast_streamfile(mychannel
, "rpt/macro_busy", mychannel
->language
);
4116 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
4122 * Reset the Unkey to CT timer
4125 x
= get_wait_interval(myrpt
, DLY_UNKEY
);
4126 rpt_mutex_lock(&myrpt
->lock
);
4127 myrpt
->unkeytocttimer
= x
; /* Must be protected as it is changed below */
4128 rpt_mutex_unlock(&myrpt
->lock
);
4131 * If there's one already queued, don't do another
4134 tlist
= myrpt
->tele
.next
;
4136 if (tlist
!= &myrpt
->tele
)
4138 rpt_mutex_lock(&myrpt
->lock
);
4139 while(tlist
!= &myrpt
->tele
){
4140 if (tlist
->mode
== UNKEY
) unkeys_queued
++;
4141 tlist
= tlist
->next
;
4143 rpt_mutex_unlock(&myrpt
->lock
);
4145 if( unkeys_queued
> 1){
4150 /* Wait for the telemetry timer to expire */
4151 /* Periodically check the timer since it can be re-initialized above */
4152 while(myrpt
->unkeytocttimer
)
4155 if(myrpt
->unkeytocttimer
> 100)
4158 ctint
= myrpt
->unkeytocttimer
;
4159 ast_safe_sleep(mychannel
, ctint
);
4160 rpt_mutex_lock(&myrpt
->lock
);
4161 if(myrpt
->unkeytocttimer
< ctint
)
4162 myrpt
->unkeytocttimer
= 0;
4164 myrpt
->unkeytocttimer
-= ctint
;
4165 rpt_mutex_unlock(&myrpt
->lock
);
4169 * Now, the carrier on the rptr rx should be gone.
4170 * If it re-appeared, then forget about sending the CT
4177 rpt_mutex_lock(&myrpt
->lock
); /* Update the kerchunk counters */
4178 myrpt
->dailykerchunks
++;
4179 myrpt
->totalkerchunks
++;
4180 rpt_mutex_unlock(&myrpt
->lock
);
4185 l
= myrpt
->links
.next
;
4186 if (l
!= &myrpt
->links
)
4188 rpt_mutex_lock(&myrpt
->lock
);
4189 while(l
!= &myrpt
->links
)
4191 if (l
->name
[0] == '0')
4199 if (l
->isremote
) hasremote
++;
4203 rpt_mutex_unlock(&myrpt
->lock
);
4208 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, (!hastx
) ? "remotemon" : "remotetx");
4210 ast_log(LOG_WARNING
, "telem_lookup:remotexx failed on %s\n", mychannel
->name
);
4213 /* if in remote cmd mode, indicate it */
4214 if (myrpt
->cmdnode
[0])
4216 ast_safe_sleep(mychannel
,200);
4217 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "cmdmode");
4219 ast_log(LOG_WARNING
, "telem_lookup:cmdmode failed on %s\n", mychannel
->name
);
4220 ast_stopstream(mychannel
);
4223 else if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "unlinkedct"))){ /* Unlinked Courtesy Tone */
4224 ct_copy
= ast_strdup(ct
);
4227 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
4233 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
4235 if (hasremote
&& (!myrpt
->cmdnode
[0]))
4237 /* set for all to hear */
4239 ci
.confno
= myrpt
->conf
;
4240 ci
.confmode
= DAHDI_CONF_CONFANN
;
4241 /* first put the channel on the conference in announce mode */
4242 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4244 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4245 rpt_mutex_lock(&myrpt
->lock
);
4246 myrpt
->active_telem
= NULL
;
4247 remque((struct qelem
*)mytele
);
4248 rpt_mutex_unlock(&myrpt
->lock
);
4249 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
4254 ast_hangup(mychannel
);
4257 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "remotect"))){ /* Unlinked Courtesy Tone */
4258 ast_safe_sleep(mychannel
,200);
4259 ct_copy
= ast_strdup(ct
);
4262 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
4269 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
4272 #if defined(_MDC_DECODE_H_) && defined(MDC_SAY_WHEN_DOING_CT)
4273 if (myrpt
->lastunit
)
4277 ast_safe_sleep(mychannel
,200);
4278 /* set for all to hear */
4280 ci
.confno
= myrpt
->txconf
;
4281 ci
.confmode
= DAHDI_CONF_CONFANN
;
4282 /* first put the channel on the conference in announce mode */
4283 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
4285 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
4286 rpt_mutex_lock(&myrpt
->lock
);
4287 myrpt
->active_telem
= NULL
;
4288 remque((struct qelem
*)mytele
);
4289 rpt_mutex_unlock(&myrpt
->lock
);
4290 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
4295 ast_hangup(mychannel
);
4298 sprintf(mystr
,"%04x",myrpt
->lastunit
);
4299 myrpt
->lastunit
= 0;
4300 ast_say_character_str(mychannel
,mystr
,NULL
,mychannel
->language
);
4307 if(myrpt
->patchnoct
&& myrpt
->callmode
){ /* If no CT during patch configured, then don't send one */
4313 * Reset the Unkey to CT timer
4316 x
= get_wait_interval(myrpt
, DLY_LINKUNKEY
);
4317 mytele
->mylink
.linkunkeytocttimer
= x
; /* Must be protected as it is changed below */
4320 * If there's one already queued, don't do another
4323 tlist
= myrpt
->tele
.next
;
4325 if (tlist
!= &myrpt
->tele
)
4327 rpt_mutex_lock(&myrpt
->lock
);
4328 while(tlist
!= &myrpt
->tele
){
4329 if (tlist
->mode
== LINKUNKEY
) unkeys_queued
++;
4330 tlist
= tlist
->next
;
4332 rpt_mutex_unlock(&myrpt
->lock
);
4334 if( unkeys_queued
> 1){
4339 /* Wait for the telemetry timer to expire */
4340 /* Periodically check the timer since it can be re-initialized above */
4341 while(mytele
->mylink
.linkunkeytocttimer
)
4344 if(mytele
->mylink
.linkunkeytocttimer
> 100)
4347 ctint
= mytele
->mylink
.linkunkeytocttimer
;
4348 ast_safe_sleep(mychannel
, ctint
);
4349 rpt_mutex_lock(&myrpt
->lock
);
4350 if(mytele
->mylink
.linkunkeytocttimer
< ctint
)
4351 mytele
->mylink
.linkunkeytocttimer
= 0;
4353 mytele
->mylink
.linkunkeytocttimer
-= ctint
;
4354 rpt_mutex_unlock(&myrpt
->lock
);
4357 if((ct
= (char *) ast_variable_retrieve(myrpt
->cfg
, nodename
, "linkunkeyct"))){ /* Unlinked Courtesy Tone */
4358 ct_copy
= ast_strdup(ct
);
4360 res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, ct_copy
);
4366 ast_log(LOG_WARNING
, "telem_lookup:ctx failed on %s\n", mychannel
->name
);
4371 /* wait a little bit */
4372 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4373 l
= myrpt
->links
.next
;
4375 /* dont report if a link for this one still on system */
4376 if (l
!= &myrpt
->links
)
4378 rpt_mutex_lock(&myrpt
->lock
);
4379 while(l
!= &myrpt
->links
)
4381 if (l
->name
[0] == '0')
4386 if (!strcmp(l
->name
,mytele
->mylink
.name
))
4393 rpt_mutex_unlock(&myrpt
->lock
);
4400 res
= saynode(myrpt
,mychannel
,mytele
->mylink
.name
);
4402 res
= ast_streamfile(mychannel
, ((mytele
->mylink
.hasconnected
) ?
4403 "rpt/remote_disc" : "rpt/remote_busy"), mychannel
->language
);
4406 /* wait a little bit */
4407 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4408 res
= ast_streamfile(mychannel
, "rpt/remote_already", mychannel
->language
);
4411 /* wait a little bit */
4412 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4413 res
= ast_streamfile(mychannel
, "rpt/remote_notfound", mychannel
->language
);
4416 /* wait a little bit */
4417 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4418 res
= ast_streamfile(mychannel
, "rpt/remote_go", mychannel
->language
);
4421 /* wait a little bit */
4422 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4423 res
= saynode(myrpt
,mychannel
,mytele
->mylink
.name
);
4425 res
= ast_streamfile(mychannel
, "rpt/connected", mychannel
->language
);
4427 res
= ast_waitstream(mychannel
, "");
4429 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4430 ast_stopstream(mychannel
);
4431 res
= ast_streamfile(mychannel
, "digits/2", mychannel
->language
);
4433 res
= ast_waitstream(mychannel
, "");
4435 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4436 ast_stopstream(mychannel
);
4437 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
4441 res
= saynode(myrpt
,mychannel
,mytele
->mylink
.name
);
4443 res
= ast_streamfile(mychannel
, "rpt/connection_failed", mychannel
->language
);
4446 /* wait a little bit */
4447 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4448 res
= ast_streamfile(mychannel
, "rpt/memory_notfound", mychannel
->language
);
4451 /* wait a little bit */
4452 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4453 res
= ast_streamfile(mychannel
, mytele
->param
, mychannel
->language
);
4456 /* wait a little bit */
4457 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4458 for(i
= 0; i
< TOPKEYN
; i
++)
4460 if (!myrpt
->topkey
[i
].node
[0]) continue;
4461 if ((!myrpt
->topkeylong
) && (myrpt
->topkey
[i
].keyed
)) continue;
4462 res
= saynode(myrpt
, mychannel
, myrpt
->topkey
[i
].node
);
4463 if (!res
) res
= sayfile(mychannel
,(myrpt
->topkey
[i
].keyed
) ?
4464 "rpt/keyedfor" : "rpt/unkeyedfor");
4465 if (!res
) res
= saynum(mychannel
,
4466 myrpt
->topkey
[i
].timesince
);
4467 if (!res
) res
= sayfile(mychannel
,"rpt/seconds");
4468 if (!myrpt
->topkeylong
) break;
4473 ast_mutex_lock(&myrpt
->remlock
);
4475 if(!strcmp(myrpt
->remoterig
, remote_rig_ft897
))
4477 res
= set_ft897(myrpt
);
4479 else if(!strcmp(myrpt
->remoterig
, remote_rig_tm271
))
4481 res
= set_tm271(myrpt
);
4483 else if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
4485 res
= set_ic706(myrpt
);
4487 else if(!strcmp(myrpt
->remoterig
, remote_rig_rbi
)||!strcmp(myrpt
->remoterig
, remote_rig_ppp16
))
4489 if (ioperm(myrpt
->p
.iobase
,1,1) == -1)
4491 rpt_mutex_unlock(&myrpt
->lock
);
4492 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
4495 else res
= setrbi(myrpt
);
4497 else if(!strcmp(myrpt
->remoterig
, remote_rig_kenwood
))
4499 if (myrpt
->iofd
>= 0) setdtr(myrpt
->iofd
,1);
4500 res
= setkenwood(myrpt
);
4501 if (myrpt
->iofd
>= 0) setdtr(myrpt
->iofd
,0);
4502 if (ast_safe_sleep(mychannel
,200) == -1)
4504 ast_mutex_unlock(&myrpt
->remlock
);
4508 if (myrpt
->iofd
< 0)
4510 i
= DAHDI_FLUSH_EVENT
;
4511 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_FLUSH
,&i
) == -1)
4513 ast_mutex_unlock(&myrpt
->remlock
);
4514 ast_log(LOG_ERROR
,"Cant flush events");
4518 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_GET_PARAMS
,&par
) == -1)
4520 ast_mutex_unlock(&myrpt
->remlock
);
4521 ast_log(LOG_ERROR
,"Cant get params");
4526 (par
.rxisoffhook
|| (myrpt
->tele
.next
!= &myrpt
->tele
));
4530 ast_mutex_unlock(&myrpt
->remlock
);
4536 /* fall thru to invalid freq */
4538 /* wait a little bit */
4539 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4540 res
= ast_streamfile(mychannel
, "rpt/invalid-freq", mychannel
->language
);
4544 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4545 switch(myrpt
->remmode
)
4548 saycharstr(mychannel
,"FM");
4551 saycharstr(mychannel
,"USB");
4554 saycharstr(mychannel
,"LSB");
4557 saycharstr(mychannel
,"AM");
4560 wait_interval(myrpt
, DLY_COMP
, mychannel
);
4561 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
4564 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4565 sayfile(mychannel
,"rpt/login");
4566 saycharstr(mychannel
,myrpt
->name
);
4569 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4570 saycharstr(mychannel
,myrpt
->loginuser
);
4571 saynode(myrpt
,mychannel
,myrpt
->name
);
4572 wait_interval(myrpt
, DLY_COMP
, mychannel
);
4573 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
4576 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4578 switch(mytele
->submode
)
4580 case 100: /* RX PL Off */
4581 sayfile(mychannel
, "rpt/rxpl");
4582 sayfile(mychannel
, "rpt/off");
4584 case 101: /* RX PL On */
4585 sayfile(mychannel
, "rpt/rxpl");
4586 sayfile(mychannel
, "rpt/on");
4588 case 102: /* TX PL Off */
4589 sayfile(mychannel
, "rpt/txpl");
4590 sayfile(mychannel
, "rpt/off");
4592 case 103: /* TX PL On */
4593 sayfile(mychannel
, "rpt/txpl");
4594 sayfile(mychannel
, "rpt/on");
4596 case 104: /* Low Power */
4597 sayfile(mychannel
, "rpt/lopwr");
4599 case 105: /* Medium Power */
4600 sayfile(mychannel
, "rpt/medpwr");
4602 case 106: /* Hi Power */
4603 sayfile(mychannel
, "rpt/hipwr");
4605 case 113: /* Scan down slow */
4606 sayfile(mychannel
,"rpt/down");
4607 sayfile(mychannel
, "rpt/slow");
4609 case 114: /* Scan down quick */
4610 sayfile(mychannel
,"rpt/down");
4611 sayfile(mychannel
, "rpt/quick");
4613 case 115: /* Scan down fast */
4614 sayfile(mychannel
,"rpt/down");
4615 sayfile(mychannel
, "rpt/fast");
4617 case 116: /* Scan up slow */
4618 sayfile(mychannel
,"rpt/up");
4619 sayfile(mychannel
, "rpt/slow");
4621 case 117: /* Scan up quick */
4622 sayfile(mychannel
,"rpt/up");
4623 sayfile(mychannel
, "rpt/quick");
4625 case 118: /* Scan up fast */
4626 sayfile(mychannel
,"rpt/up");
4627 sayfile(mychannel
, "rpt/fast");
4632 wait_interval(myrpt
, DLY_COMP
, mychannel
);
4633 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
4636 ast_mutex_lock(&myrpt
->remlock
);
4637 if (myrpt
->hfscanstop
)
4639 myrpt
->hfscanstatus
= 0;
4640 myrpt
->hfscanmode
= 0;
4641 myrpt
->hfscanstop
= 0;
4642 mytele
->mode
= SCANSTAT
;
4643 ast_mutex_unlock(&myrpt
->remlock
);
4644 if (ast_safe_sleep(mychannel
,1000) == -1) break;
4645 sayfile(mychannel
, "rpt/stop");
4649 if (myrpt
->hfscanstatus
> -2) service_scan(myrpt
);
4650 i
= myrpt
->hfscanstatus
;
4651 myrpt
->hfscanstatus
= 0;
4652 if (i
) mytele
->mode
= SCANSTAT
;
4653 ast_mutex_unlock(&myrpt
->remlock
);
4654 if (i
< 0) sayfile(mychannel
, "rpt/stop");
4655 else if (i
> 0) saynum(mychannel
,i
);
4659 ast_mutex_lock(&myrpt
->remlock
);
4660 if (!strcmp(myrpt
->remoterig
,remote_rig_ic706
))
4662 set_mode_ic706(myrpt
, REM_MODE_AM
);
4663 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
4664 ast_safe_sleep(mychannel
,500);
4665 set_mode_ic706(myrpt
, myrpt
->remmode
);
4666 myrpt
->tunerequest
= 0;
4667 ast_mutex_unlock(&myrpt
->remlock
);
4671 set_mode_ft897(myrpt
, REM_MODE_AM
);
4672 simple_command_ft897(myrpt
, 8);
4673 if(play_tone(mychannel
, 800, 6000, 8192) == -1) break;
4674 simple_command_ft897(myrpt
, 0x88);
4675 ast_safe_sleep(mychannel
,500);
4676 set_mode_ft897(myrpt
, myrpt
->remmode
);
4677 myrpt
->tunerequest
= 0;
4678 ast_mutex_unlock(&myrpt
->remlock
);
4681 case REMSHORTSTATUS
:
4683 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4684 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
4686 res
= sayfile(mychannel
,"rpt/frequency");
4688 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
4689 if (!multimode_capable(myrpt
)) decimals
[3] = 0;
4693 res
= saynum(mychannel
, m
);
4695 res
= saycharstr(mychannel
, mhz
);
4698 res
= sayfile(mychannel
, "letters/dot");
4700 res
= saycharstr(mychannel
, decimals
);
4703 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
4704 switch(myrpt
->offset
){
4707 res
= sayfile(mychannel
,"rpt/minus");
4711 res
= sayfile(mychannel
,"rpt/simplex");
4715 res
= sayfile(mychannel
,"rpt/plus");
4722 else{ /* Must be USB, LSB, or AM */
4723 switch(myrpt
->remmode
){
4726 res
= saycharstr(mychannel
, "USB");
4730 res
= saycharstr(mychannel
, "LSB");
4734 res
= saycharstr(mychannel
, "AM");
4743 if (res
== -1) break;
4745 if(mytele
->mode
== REMSHORTSTATUS
){ /* Short status? */
4746 wait_interval(myrpt
, DLY_COMP
, mychannel
);
4747 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
4751 if (strcmp(myrpt
->remoterig
,remote_rig_ic706
))
4753 switch(myrpt
->powerlevel
){
4756 res
= sayfile(mychannel
,"rpt/lopwr") ;
4759 res
= sayfile(mychannel
,"rpt/medpwr");
4762 res
= sayfile(mychannel
,"rpt/hipwr");
4767 rbimode
= ((!strncmp(myrpt
->remoterig
,remote_rig_rbi
,3))
4768 || (!strncmp(myrpt
->remoterig
,remote_rig_ic706
,3)));
4769 if (res
|| (sayfile(mychannel
,"rpt/rxpl") == -1)) break;
4770 if (rbimode
&& (sayfile(mychannel
,"rpt/txpl") == -1)) break;
4771 if ((sayfile(mychannel
,"rpt/frequency") == -1) ||
4772 (saycharstr(mychannel
,myrpt
->rxpl
) == -1)) break;
4773 if ((!rbimode
) && ((sayfile(mychannel
,"rpt/txpl") == -1) ||
4774 (sayfile(mychannel
,"rpt/frequency") == -1) ||
4775 (saycharstr(mychannel
,myrpt
->txpl
) == -1))) break;
4776 if(myrpt
->remmode
== REM_MODE_FM
){ /* Mode FM? */
4777 if ((sayfile(mychannel
,"rpt/rxpl") == -1) ||
4778 (sayfile(mychannel
,((myrpt
->rxplon
) ? "rpt/on" : "rpt/off")) == -1) ||
4779 (sayfile(mychannel
,"rpt/txpl") == -1) ||
4780 (sayfile(mychannel
,((myrpt
->txplon
) ? "rpt/on" : "rpt/off")) == -1))
4785 wait_interval(myrpt
, DLY_COMP
, mychannel
);
4786 if (!res
) res
= telem_lookup(myrpt
,mychannel
, myrpt
->name
, "functcomplete");
4789 /* wait a little bit */
4790 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4792 linkbase
.next
= &linkbase
;
4793 linkbase
.prev
= &linkbase
;
4794 rpt_mutex_lock(&myrpt
->lock
);
4795 /* make our own list of links */
4796 l
= myrpt
->links
.next
;
4797 while(l
!= &myrpt
->links
)
4799 if (l
->name
[0] == '0')
4804 l1
= ast_malloc(sizeof(struct rpt_link
));
4807 ast_log(LOG_WARNING
, "Cannot alloc memory on %s\n", mychannel
->name
);
4808 remque((struct qelem
*)mytele
);
4809 myrpt
->active_telem
= NULL
;
4810 rpt_mutex_unlock(&myrpt
->lock
);
4811 ast_log(LOG_NOTICE
,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__
, mytele
->mode
); /*@@@@@@@@@@@*/
4816 ast_hangup(mychannel
);
4819 memcpy(l1
,l
,sizeof(struct rpt_link
));
4820 l1
->next
= l1
->prev
= NULL
;
4821 insque((struct qelem
*)l1
,(struct qelem
*)linkbase
.next
);
4824 rpt_mutex_unlock(&myrpt
->lock
);
4825 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
4826 if (myrpt
->callmode
)
4829 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
4831 res
= ast_waitstream(mychannel
, "");
4833 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4834 ast_stopstream(mychannel
);
4837 while(l
!= &linkbase
)
4842 res
= saynode(myrpt
,mychannel
,l
->name
);
4843 s
= "rpt/tranceive";
4844 if (!l
->mode
) s
= "rpt/monitor";
4845 if (!l
->thisconnected
) s
= "rpt/connecting";
4846 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
4848 res
= ast_waitstream(mychannel
, "");
4850 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4851 ast_stopstream(mychannel
);
4856 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
4858 res
= ast_waitstream(mychannel
, "");
4860 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4861 ast_stopstream(mychannel
);
4863 /* destroy our local link queue */
4865 while(l
!= &linkbase
)
4869 remque((struct qelem
*)l1
);
4875 rpt_mutex_lock(&myrpt
->lock
);
4876 /* get all the nodes */
4877 __mklinklist(myrpt
,NULL
,lbuf
);
4878 rpt_mutex_unlock(&myrpt
->lock
);
4880 ns
= finddelim(lbuf
,strs
,MAXLINKLIST
);
4882 if (ns
) qsort((void *)strs
,ns
,sizeof(char *),mycompar
);
4883 /* wait a little bit */
4884 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4886 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
4887 if (myrpt
->callmode
)
4890 res
= ast_streamfile(mychannel
, "rpt/autopatch_on", mychannel
->language
);
4892 res
= ast_waitstream(mychannel
, "");
4894 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4895 ast_stopstream(mychannel
);
4897 /* go thru all the nodes in list */
4898 for(i
= 0; i
< ns
; i
++)
4902 /* if a mode spec at first, handle it */
4903 if ((*strs
[i
] < '0') || (*strs
[i
] > '9'))
4910 res
= saynode(myrpt
,mychannel
,strs
[i
]);
4911 s
= "rpt/tranceive";
4912 if (mode
== 'R') s
= "rpt/monitor";
4913 if (mode
== 'C') s
= "rpt/connecting";
4914 res
= ast_streamfile(mychannel
, s
, mychannel
->language
);
4916 res
= ast_waitstream(mychannel
, "");
4918 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4919 ast_stopstream(mychannel
);
4923 res
= ast_streamfile(mychannel
, "rpt/repeat_only", mychannel
->language
);
4925 res
= ast_waitstream(mychannel
, "");
4927 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4928 ast_stopstream(mychannel
);
4933 case LASTNODEKEY
: /* Identify last node which keyed us up */
4934 rpt_mutex_lock(&myrpt
->lock
);
4935 if(myrpt
->lastnodewhichkeyedusup
){
4936 p
= ast_strdup(myrpt
->lastnodewhichkeyedusup
); /* Make a local copy of the node name */
4938 ast_log(LOG_WARNING
, "ast_strdup failed in telemetery LASTNODEKEY");
4945 rpt_mutex_unlock(&myrpt
->lock
);
4947 imdone
= 1; /* no node previously keyed us up, or the node which did has been disconnected */
4950 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4951 res
= saynode(myrpt
,mychannel
,p
);
4956 case UNAUTHTX
: /* Say unauthorized transmit frequency */
4957 wait_interval(myrpt
, DLY_TELEM
, mychannel
);
4958 res
= ast_streamfile(mychannel
, "rpt/unauthtx", mychannel
->language
);
4960 res
= ast_waitstream(mychannel
, "");
4962 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4963 ast_stopstream(mychannel
);
4967 case PARROT
: /* Repeat stuff */
4969 sprintf(mystr
,PARROTFILE
,myrpt
->name
,mytele
->parrot
);
4970 if (ast_fileexists(mystr
,NULL
,mychannel
->language
) <= 0)
4973 myrpt
->parrotstate
= 0;
4976 wait_interval(myrpt
, DLY_PARROT
, mychannel
);
4977 sprintf(mystr
,PARROTFILE
,myrpt
->name
,mytele
->parrot
);
4978 res
= ast_streamfile(mychannel
, mystr
, mychannel
->language
);
4980 res
= ast_waitstream(mychannel
, "");
4982 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
4983 ast_stopstream(mychannel
);
4984 sprintf(mystr
,PARROTFILE
,myrpt
->name
,mytele
->parrot
);
4985 strcat(mystr
,".wav");
4988 myrpt
->parrotstate
= 0;
4992 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
4994 res
= ast_streamfile(mychannel
, "rpt/timeout", mychannel
->language
);
4997 case TIMEOUT_WARNING
:
4999 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
5001 res
= ast_streamfile(mychannel
, "rpt/timeout-warning", mychannel
->language
);
5003 res
= ast_waitstream(mychannel
, "");
5005 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
5006 ast_stopstream(mychannel
);
5007 if(!res
) /* Say number of seconds */
5008 ast_say_number(mychannel
, myrpt
->p
.remotetimeout
-
5009 (t
- myrpt
->last_activity_time
),
5010 "", mychannel
->language
, (char *) NULL
);
5012 res
= ast_waitstream(mychannel
, "");
5013 ast_stopstream(mychannel
);
5014 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
5017 case ACT_TIMEOUT_WARNING
:
5019 res
= saynode(myrpt
,mychannel
,myrpt
->name
);
5021 res
= ast_streamfile(mychannel
, "rpt/act-timeout-warning", mychannel
->language
);
5023 res
= ast_waitstream(mychannel
, "");
5025 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
5026 ast_stopstream(mychannel
);
5027 if(!res
) /* Say number of seconds */
5028 ast_say_number(mychannel
, myrpt
->p
.remoteinacttimeout
-
5029 (t
- myrpt
->last_activity_time
),
5030 "", mychannel
->language
, (char *) NULL
);
5032 res
= ast_waitstream(mychannel
, "");
5033 ast_stopstream(mychannel
);
5034 res
= ast_streamfile(mychannel
, "queue-seconds", mychannel
->language
);
5038 case STATS_TIME_LOCAL
:
5039 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
5041 rpt_localtime(&t
, &localtm
);
5042 /* Say the phase of the day is before the time */
5043 if((localtm
.tm_hour
>= 0) && (localtm
.tm_hour
< 12))
5044 p
= "rpt/goodmorning";
5045 else if((localtm
.tm_hour
>= 12) && (localtm
.tm_hour
< 18))
5046 p
= "rpt/goodafternoon";
5048 p
= "rpt/goodevening";
5049 if (sayfile(mychannel
,p
) == -1)
5054 /* Say the time is ... */
5055 if (sayfile(mychannel
,"rpt/thetimeis") == -1)
5061 res
= ast_say_time(mychannel
, t
, "", mychannel
->language
);
5063 res
= ast_waitstream(mychannel
, "");
5064 ast_stopstream(mychannel
);
5068 p
= strstr(tdesc
, "version");
5071 if(sscanf(p
, "version %d.%d", &vmajor
, &vminor
) != 2)
5073 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
5075 if (sayfile(mychannel
,"rpt/version") == -1)
5080 if(!res
) /* Say "X" */
5081 ast_say_number(mychannel
, vmajor
, "", mychannel
->language
, (char *) NULL
);
5083 res
= ast_waitstream(mychannel
, "");
5084 ast_stopstream(mychannel
);
5085 if (saycharstr(mychannel
,".") == -1)
5090 if(!res
) /* Say "Y" */
5091 ast_say_number(mychannel
, vminor
, "", mychannel
->language
, (char *) NULL
);
5093 res
= ast_waitstream(mychannel
, "");
5094 ast_stopstream(mychannel
);
5097 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
5101 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
5103 saycharstr(mychannel
, mytele
->param
);
5107 wait_interval(myrpt
, DLY_TELEM
, mychannel
); /* Wait a little bit */
5110 /* Parts of this section taken from app_parkandannounce */
5111 char *tpl_working
, *tpl_current
;
5112 char *tmp
[100], *myparm
;
5113 int looptemp
=0,i
=0, dres
= 0;
5116 tpl_working
= ast_strdup(mytele
->param
);
5117 myparm
= strsep(&tpl_working
,",");
5118 tpl_current
=strsep(&tpl_working
, ":");
5120 while(tpl_current
&& looptemp
< sizeof(tmp
)) {
5121 tmp
[looptemp
]=tpl_current
;
5123 tpl_current
=strsep(&tpl_working
,":");
5126 for(i
=0; i
<looptemp
; i
++) {
5127 if(!strcmp(tmp
[i
], "PARKED")) {
5128 ast_say_digits(mychannel
, atoi(myparm
), "", mychannel
->language
);
5129 } else if(!strcmp(tmp
[i
], "NODE")) {
5130 ast_say_digits(mychannel
, atoi(myrpt
->name
), "", mychannel
->language
);
5132 dres
= ast_streamfile(mychannel
, tmp
[i
], mychannel
->language
);
5134 dres
= ast_waitstream(mychannel
, "");
5136 ast_log(LOG_WARNING
, "ast_streamfile of %s failed on %s\n", tmp
[i
], mychannel
->name
);
5141 ast_free(tpl_working
);
5147 if (myrpt
->stopgen
) break;
5148 myrpt
->stopgen
= -1;
5149 if ((res
= ast_tonepair_start(mychannel
, 1004.0, 0, 99999999, 7200.0)))
5154 while(mychannel
->generatordata
&& (myrpt
->stopgen
<= 0)) {
5155 if (ast_safe_sleep(mychannel
,1)) break;
5166 res
= ast_waitstream(mychannel
, "");
5168 ast_log(LOG_WARNING
, "ast_streamfile failed on %s\n", mychannel
->name
);
5172 ast_stopstream(mychannel
);
5173 rpt_mutex_lock(&myrpt
->lock
);
5174 if (mytele
->mode
== TAILMSG
)
5178 myrpt
->tailmessagen
++;
5179 if(myrpt
->tailmessagen
>= myrpt
->p
.tailmessagemax
) myrpt
->tailmessagen
= 0;
5183 myrpt
->tmsgtimer
= myrpt
->p
.tailsquashedtime
;
5186 remque((struct qelem
*)mytele
);
5187 myrpt
->active_telem
= NULL
;
5188 rpt_mutex_unlock(&myrpt
->lock
);
5193 ast_hangup(mychannel
);
5194 #ifdef APP_RPT_LOCK_DEBUG
5196 struct lockthread
*t
;
5199 ast_mutex_lock(&locklock
);
5200 t
= get_lockthread(pthread_self());
5201 if (t
) memset(t
,0,sizeof(struct lockthread
));
5202 ast_mutex_unlock(&locklock
);
5208 static void rpt_telemetry(struct rpt
*myrpt
,int mode
, void *data
)
5210 struct rpt_tele
*tele
;
5211 struct rpt_link
*mylink
= NULL
;
5213 pthread_attr_t attr
;
5217 ast_log(LOG_NOTICE
,"mode=%i data=%s\n",mode
, (char *)data
);
5222 /* if any of the following are defined, go ahead and do it,
5223 otherwise, dont bother */
5224 v1
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
,
5226 v2
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
,
5228 if (telem_lookup(myrpt
,NULL
, myrpt
->name
, "remotemon") &&
5229 telem_lookup(myrpt
,NULL
, myrpt
->name
, "remotetx") &&
5230 telem_lookup(myrpt
,NULL
, myrpt
->name
, "cmdmode") &&
5231 (!(v1
&& telem_lookup(myrpt
,NULL
, myrpt
->name
, v1
))) &&
5232 (!(v2
&& telem_lookup(myrpt
,NULL
, myrpt
->name
, v2
)))) return;
5235 if (!ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "linkunkeyct"))
5241 tele
= ast_malloc(sizeof(struct rpt_tele
));
5244 ast_log(LOG_WARNING
, "Unable to allocate memory\n");
5249 memset((char *)tele
,0,sizeof(struct rpt_tele
));
5252 if (mode
== PARROT
) tele
->parrot
= (unsigned int) data
;
5253 else mylink
= (struct rpt_link
*) data
;
5254 rpt_mutex_lock(&myrpt
->lock
);
5255 if((mode
== CONNFAIL
) || (mode
== REMDISC
) || (mode
== CONNECTED
) ||
5256 (mode
== LINKUNKEY
)){
5257 memset(&tele
->mylink
,0,sizeof(struct rpt_link
));
5259 memcpy(&tele
->mylink
,mylink
,sizeof(struct rpt_link
));
5262 else if ((mode
== ARB_ALPHA
) || (mode
== REV_PATCH
) || (mode
== PLAYBACK
)) {
5263 strncpy(tele
->param
, (char *) data
, TELEPARAMSIZE
- 1);
5264 tele
->param
[TELEPARAMSIZE
- 1] = 0;
5266 if (mode
== REMXXX
) tele
->submode
= (int) data
;
5267 insque((struct qelem
*)tele
, (struct qelem
*)myrpt
->tele
.next
);
5268 rpt_mutex_unlock(&myrpt
->lock
);
5269 pthread_attr_init(&attr
);
5270 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
5271 res
= ast_pthread_create(&tele
->threadid
,&attr
,rpt_tele_thread
,(void *) tele
);
5273 rpt_mutex_lock(&myrpt
->lock
);
5274 remque((struct qlem
*) tele
); /* We don't like stuck transmitters, remove it from the queue */
5275 rpt_mutex_unlock(&myrpt
->lock
);
5276 ast_log(LOG_WARNING
, "Could not create telemetry thread: %s",strerror(res
));
5281 static void *rpt_call(void *this)
5283 DAHDI_CONFINFO ci
; /* conference info */
5284 struct rpt
*myrpt
= (struct rpt
*)this;
5286 int stopped
,congstarted
,dialtimer
,lastcidx
,aborted
;
5287 struct ast_channel
*mychannel
,*genchannel
;
5290 /* allocate a pseudo-channel thru asterisk */
5291 mychannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
5294 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
5297 #ifdef AST_CDR_FLAG_POST_DISABLED
5299 ast_set_flag(mychannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
5302 ci
.confno
= myrpt
->conf
; /* use the pseudo conference */
5304 ci
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
5305 | DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
5307 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
;
5308 /* first put the channel on the conference */
5309 if (ioctl(mychannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
5311 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
5312 ast_hangup(mychannel
);
5313 myrpt
->callmode
= 0;
5316 /* allocate a pseudo-channel thru asterisk */
5317 genchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
5320 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
5321 ast_hangup(mychannel
);
5324 #ifdef AST_CDR_FLAG_POST_DISABLED
5325 if (genchannel
->cdr
)
5326 ast_set_flag(genchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
5329 ci
.confno
= myrpt
->conf
;
5330 ci
.confmode
= DAHDI_CONF_REALANDPSEUDO
| DAHDI_CONF_TALKER
| DAHDI_CONF_LISTENER
5331 | DAHDI_CONF_PSEUDO_TALKER
| DAHDI_CONF_PSEUDO_LISTENER
;
5332 /* first put the channel on the conference */
5333 if (ioctl(genchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
5335 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
5336 ast_hangup(mychannel
);
5337 ast_hangup(genchannel
);
5338 myrpt
->callmode
= 0;
5341 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(mychannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
5343 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
5344 ast_hangup(mychannel
);
5345 ast_hangup(genchannel
);
5346 myrpt
->callmode
= 0;
5349 if (myrpt
->p
.tonezone
&& (tone_zone_set_zone(genchannel
->fds
[0],myrpt
->p
.tonezone
) == -1))
5351 ast_log(LOG_WARNING
, "Unable to set tone zone %s\n",myrpt
->p
.tonezone
);
5352 ast_hangup(mychannel
);
5353 ast_hangup(genchannel
);
5354 myrpt
->callmode
= 0;
5357 /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
5358 if ((!myrpt
->patchquiet
) && (tone_zone_play_tone(genchannel
->fds
[0],DAHDI_TONE_DIALTONE
) < 0))
5360 ast_log(LOG_WARNING
, "Cannot start dialtone\n");
5361 ast_hangup(mychannel
);
5362 ast_hangup(genchannel
);
5363 myrpt
->callmode
= 0;
5370 myrpt
->calldigittimer
= 0;
5373 while ((myrpt
->callmode
== 1) || (myrpt
->callmode
== 4))
5375 if((myrpt
->patchdialtime
)&&(myrpt
->callmode
== 1)&&(myrpt
->cidx
!= lastcidx
)){
5377 lastcidx
= myrpt
->cidx
;
5380 if((myrpt
->patchdialtime
)&&(dialtimer
>= myrpt
->patchdialtime
)){
5382 ast_log(LOG_NOTICE
, "dialtimer %i > patchdialtime %i\n", dialtimer
,myrpt
->patchdialtime
);
5383 rpt_mutex_lock(&myrpt
->lock
);
5385 myrpt
->callmode
= 0;
5386 rpt_mutex_unlock(&myrpt
->lock
);
5390 if ((!myrpt
->patchquiet
) && (!stopped
) && (myrpt
->callmode
== 1) && (myrpt
->cidx
> 0))
5393 /* stop dial tone */
5394 tone_zone_play_tone(genchannel
->fds
[0],-1);
5396 if (myrpt
->callmode
== 1)
5398 if(myrpt
->calldigittimer
> PATCH_DIALPLAN_TIMEOUT
)
5400 myrpt
->callmode
= 2;
5403 /* bump timer if active */
5404 if (myrpt
->calldigittimer
)
5405 myrpt
->calldigittimer
+= MSWAIT
;
5407 if (myrpt
->callmode
== 4)
5411 /* start congestion tone */
5412 tone_zone_play_tone(genchannel
->fds
[0],DAHDI_TONE_CONGESTION
);
5415 res
= ast_safe_sleep(mychannel
, MSWAIT
);
5419 ast_log(LOG_NOTICE
, "ast_safe_sleep=%i\n", res
);
5420 ast_hangup(mychannel
);
5421 ast_hangup(genchannel
);
5422 rpt_mutex_lock(&myrpt
->lock
);
5423 myrpt
->callmode
= 0;
5424 rpt_mutex_unlock(&myrpt
->lock
);
5427 dialtimer
+= MSWAIT
;
5429 /* stop any tone generation */
5430 tone_zone_play_tone(genchannel
->fds
[0],-1);
5432 if (!myrpt
->callmode
)
5435 ast_log(LOG_NOTICE
, "callmode==0\n");
5436 ast_hangup(mychannel
);
5437 ast_hangup(genchannel
);
5438 rpt_mutex_lock(&myrpt
->lock
);
5439 myrpt
->callmode
= 0;
5440 myrpt
->macropatch
=0;
5441 channel_revert(myrpt
);
5442 rpt_mutex_unlock(&myrpt
->lock
);
5443 if((!myrpt
->patchquiet
) && aborted
)
5444 rpt_telemetry(myrpt
, TERM
, NULL
);
5448 if (myrpt
->p
.ourcallerid
&& *myrpt
->p
.ourcallerid
){
5449 char *name
, *loc
, *instr
;
5450 instr
= ast_strdup(myrpt
->p
.ourcallerid
);
5452 ast_callerid_parse(instr
, &name
, &loc
);
5454 if(mychannel
->cid
.cid_num
)
5455 ast_free(mychannel
->cid
.cid_num
);
5456 mychannel
->cid
.cid_num
= ast_strdup(loc
);
5459 if(mychannel
->cid
.cid_name
)
5460 ast_free(mychannel
->cid
.cid_name
);
5461 mychannel
->cid
.cid_name
= ast_strdup(name
);
5467 ast_copy_string(mychannel
->exten
, myrpt
->exten
, sizeof(mychannel
->exten
) - 1);
5468 ast_copy_string(mychannel
->context
, myrpt
->patchcontext
, sizeof(mychannel
->context
) - 1);
5470 if (myrpt
->p
.acctcode
)
5471 ast_cdr_setaccount(mychannel
,myrpt
->p
.acctcode
);
5472 mychannel
->priority
= 1;
5473 ast_channel_undefer_dtmf(mychannel
);
5474 if (ast_pbx_start(mychannel
) < 0)
5476 ast_log(LOG_WARNING
, "Unable to start PBX!!\n");
5477 ast_hangup(mychannel
);
5478 ast_hangup(genchannel
);
5479 rpt_mutex_lock(&myrpt
->lock
);
5480 myrpt
->callmode
= 0;
5481 rpt_mutex_unlock(&myrpt
->lock
);
5485 rpt_mutex_lock(&myrpt
->lock
);
5486 myrpt
->callmode
= 3;
5487 /* set appropriate conference for the pseudo */
5489 ci
.confno
= myrpt
->conf
;
5490 ci
.confmode
= (myrpt
->p
.duplex
== 2) ? DAHDI_CONF_CONFANNMON
:
5491 (DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
);
5492 /* first put the channel on the conference in announce mode */
5493 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
5495 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
5496 ast_hangup(mychannel
);
5497 ast_hangup(genchannel
);
5498 myrpt
->callmode
= 0;
5501 /* get its channel number */
5502 if (ioctl(mychannel
->fds
[0],DAHDI_CHANNO
,&res
) == -1)
5504 ast_log(LOG_WARNING
, "Unable to get autopatch channel number\n");
5505 ast_hangup(mychannel
);
5506 myrpt
->callmode
= 0;
5511 ci
.confmode
= DAHDI_CONF_MONITOR
;
5512 /* put vox channel monitoring on the channel */
5513 if (ioctl(myrpt
->voxchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
5515 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
5516 ast_hangup(mychannel
);
5517 myrpt
->callmode
= 0;
5520 while(myrpt
->callmode
)
5522 if ((!mychannel
->pbx
) && (myrpt
->callmode
!= 4))
5524 /* If patch is setup for far end disconnect */
5525 if(myrpt
->patchfarenddisconnect
|| (myrpt
->p
.duplex
< 2)){
5526 if(debug
)ast_log(LOG_NOTICE
,"callmode=%i, patchfarenddisconnect=%i, duplex=%i\n",\
5527 myrpt
->callmode
,myrpt
->patchfarenddisconnect
,myrpt
->p
.duplex
);
5528 myrpt
->callmode
= 0;
5529 myrpt
->macropatch
=0;
5530 if(!myrpt
->patchquiet
){
5531 rpt_mutex_unlock(&myrpt
->lock
);
5532 rpt_telemetry(myrpt
, TERM
, NULL
);
5533 rpt_mutex_lock(&myrpt
->lock
);
5536 else{ /* Send congestion until patch is downed by command */
5537 myrpt
->callmode
= 4;
5538 rpt_mutex_unlock(&myrpt
->lock
);
5539 /* start congestion tone */
5540 tone_zone_play_tone(genchannel
->fds
[0],DAHDI_TONE_CONGESTION
);
5541 rpt_mutex_lock(&myrpt
->lock
);
5546 struct ast_frame wf
= {AST_FRAME_DTMF
, } ;
5547 wf
.subclass
= myrpt
->mydtmf
;
5548 rpt_mutex_unlock(&myrpt
->lock
);
5549 ast_queue_frame(mychannel
,&wf
);
5551 ast_senddigit(genchannel
,myrpt
->mydtmf
,0);
5553 ast_senddigit(genchannel
,myrpt
->mydtmf
);
5555 rpt_mutex_lock(&myrpt
->lock
);
5558 rpt_mutex_unlock(&myrpt
->lock
);
5559 usleep(MSWAIT
* 1000);
5560 rpt_mutex_lock(&myrpt
->lock
);
5563 ast_log(LOG_NOTICE
, "exit channel loop\n");
5564 rpt_mutex_unlock(&myrpt
->lock
);
5565 tone_zone_play_tone(genchannel
->fds
[0],-1);
5566 if (mychannel
->pbx
) ast_softhangup(mychannel
,AST_SOFTHANGUP_DEV
);
5567 ast_hangup(genchannel
);
5568 rpt_mutex_lock(&myrpt
->lock
);
5569 myrpt
->callmode
= 0;
5570 myrpt
->macropatch
=0;
5571 channel_revert(myrpt
);
5572 rpt_mutex_unlock(&myrpt
->lock
);
5573 /* set appropriate conference for the pseudo */
5575 ci
.confno
= myrpt
->conf
;
5576 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? DAHDI_CONF_CONFANNMON
:
5577 (DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
);
5578 /* first put the channel on the conference in announce mode */
5579 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
5581 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
5586 static void send_link_dtmf(struct rpt
*myrpt
,char c
)
5589 struct ast_frame wf
;
5592 snprintf(str
, sizeof(str
), "D %s %s %d %c", myrpt
->cmdnode
, myrpt
->name
, ++(myrpt
->dtmfidx
), c
);
5593 wf
.frametype
= AST_FRAME_TEXT
;
5597 wf
.datalen
= strlen(str
) + 1;
5599 l
= myrpt
->links
.next
;
5600 /* first, see if our dude is there */
5601 while(l
!= &myrpt
->links
)
5603 if (l
->name
[0] == '0')
5608 /* if we found it, write it and were done */
5609 if (!strcmp(l
->name
,myrpt
->cmdnode
))
5612 if (l
->chan
) ast_write(l
->chan
,&wf
);
5617 l
= myrpt
->links
.next
;
5618 /* if not, give it to everyone */
5619 while(l
!= &myrpt
->links
)
5622 if (l
->chan
) ast_write(l
->chan
,&wf
);
5628 static void send_link_keyquery(struct rpt
*myrpt
)
5631 struct ast_frame wf
;
5634 rpt_mutex_lock(&myrpt
->lock
);
5635 memset(myrpt
->topkey
,0,sizeof(myrpt
->topkey
));
5636 myrpt
->topkeystate
= 1;
5637 time(&myrpt
->topkeytime
);
5638 rpt_mutex_unlock(&myrpt
->lock
);
5639 snprintf(str
, sizeof(str
), "K? * %s 0 0", myrpt
->name
);
5640 wf
.frametype
= AST_FRAME_TEXT
;
5644 wf
.datalen
= strlen(str
) + 1;
5646 l
= myrpt
->links
.next
;
5647 /* give it to everyone */
5648 while(l
!= &myrpt
->links
)
5651 if (l
->chan
) ast_write(l
->chan
,&wf
);
5657 /* send newkey request */
5659 static void send_newkey(struct ast_channel
*chan
)
5662 /* ast_safe_sleep(chan,10); */
5663 ast_sendtext(chan
,newkeystr
);
5672 * -2: Attempt to connect to self
5676 * 2: Already connected to this node
5679 static int connect_link(struct rpt
*myrpt
, char* node
, int mode
, int perma
)
5681 char *val
, *s
, *s1
, *s2
, *tele
;
5682 char lstr
[MAXLINKLIST
],*strs
[MAXLINKLIST
];
5683 char tmp
[300], deststr
[300] = "",modechange
= 0;
5688 DAHDI_CONFINFO ci
; /* conference info */
5690 val
= node_lookup(myrpt
,node
);
5692 if(strlen(node
) >= myrpt
->longestnode
)
5693 return -1; /* No such node */
5694 return 1; /* No match yet */
5697 if(!strcmp(myrpt
->name
,node
)) /* Do not allow connections to self */
5701 ast_log(LOG_NOTICE
,"Connect attempt to node %s\n", node
);
5702 ast_log(LOG_NOTICE
,"Mode: %s\n",(mode
)?"Transceive":"Monitor");
5703 ast_log(LOG_NOTICE
,"Connection type: %s\n",(perma
)?"Permalink":"Normal");
5706 strncpy(tmp
,val
,sizeof(tmp
) - 1);
5708 s1
= strsep(&s
,",");
5709 if (!strchr(s1
,':') && strchr(s1
,'/') && strncasecmp(s1
, "local/", 6))
5711 sy
= strchr(s1
,'/');
5713 sprintf(sx
,"%s:4569/%s",s1
,sy
+ 1);
5716 s2
= strsep(&s
,",");
5717 rpt_mutex_lock(&myrpt
->lock
);
5718 l
= myrpt
->links
.next
;
5719 /* try to find this one in queue */
5720 while(l
!= &myrpt
->links
){
5721 if (l
->name
[0] == '0')
5726 /* if found matching string */
5727 if (!strcmp(l
->name
, node
))
5732 if (l
!= &myrpt
->links
){
5733 /* if already in this mode, just ignore */
5734 if ((l
->mode
) || (!l
->chan
)) {
5735 rpt_mutex_unlock(&myrpt
->lock
);
5736 return 2; /* Already linked */
5738 reconnects
= l
->reconnects
;
5739 rpt_mutex_unlock(&myrpt
->lock
);
5740 if (l
->chan
) ast_softhangup(l
->chan
, AST_SOFTHANGUP_DEV
);
5741 l
->retries
= l
->max_retries
+ 1;
5746 __mklinklist(myrpt
,NULL
,lstr
);
5747 rpt_mutex_unlock(&myrpt
->lock
);
5748 n
= finddelim(lstr
,strs
,MAXLINKLIST
);
5749 for(i
= 0; i
< n
; i
++)
5751 if ((*strs
[i
] < '0') ||
5752 (*strs
[i
] > '9')) strs
[i
]++;
5753 if (!strcmp(strs
[i
],node
))
5755 return 2; /* Already linked */
5759 strncpy(myrpt
->lastlinknode
,node
,MAXNODESTR
- 1);
5760 /* establish call */
5761 l
= ast_malloc(sizeof(struct rpt_link
));
5764 ast_log(LOG_WARNING
, "Unable to malloc\n");
5767 /* zero the silly thing */
5768 memset((char *)l
,0,sizeof(struct rpt_link
));
5771 l
->thisconnected
= 0;
5773 strncpy(l
->name
, node
, MAXNODESTR
- 1);
5774 l
->isremote
= (s
&& ast_true(s
));
5775 if (modechange
) l
->connected
= 1;
5776 l
->hasconnected
= l
->perma
= perma
;
5777 #ifdef ALLOW_LOCAL_CHANNELS
5778 if ((strncasecmp(s1
,"iax2/", 5) == 0) || (strncasecmp(s1
, "local/", 6) == 0))
5779 strncpy(deststr
, s1
, sizeof(deststr
));
5781 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
5783 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
5785 tele
= strchr(deststr
, '/');
5787 ast_log(LOG_WARNING
,"link3:Dial number (%s) must be in format tech/number\n",deststr
);
5792 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
5794 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
5795 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
5796 #ifdef AST_CDR_FLAG_POST_DISABLED
5798 ast_set_flag(l
->chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
5800 #ifndef NEW_ASTERISK
5801 l
->chan
->whentohangup
= 0;
5803 l
->chan
->appl
= "Apprpt";
5804 l
->chan
->data
= "(Remote Rx)";
5806 ast_log(LOG_NOTICE
, "rpt (remote) initiating call to %s/%s on %s\n",
5807 deststr
, tele
, l
->chan
->name
);
5808 if(l
->chan
->cid
.cid_num
)
5809 ast_free(l
->chan
->cid
.cid_num
);
5810 l
->chan
->cid
.cid_num
= ast_strdup(myrpt
->name
);
5811 ast_call(l
->chan
,tele
,999);
5815 ast_log(LOG_NOTICE
, "Unable to place call to %s/%s on %s\n",
5816 deststr
,tele
,l
->chan
->name
);
5817 if (myrpt
->p
.archivedir
)
5820 sprintf(str
,"LINKFAIL,%s",l
->name
);
5821 donodelog(myrpt
,str
);
5826 /* allocate a pseudo-channel thru asterisk */
5827 l
->pchan
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
5829 ast_log(LOG_WARNING
,"rpt connect: Sorry unable to obtain pseudo channel\n");
5830 ast_hangup(l
->chan
);
5834 ast_set_read_format(l
->pchan
, AST_FORMAT_SLINEAR
);
5835 ast_set_write_format(l
->pchan
, AST_FORMAT_SLINEAR
);
5836 #ifdef AST_CDR_FLAG_POST_DISABLED
5838 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
5840 /* make a conference for the tx */
5842 ci
.confno
= myrpt
->conf
;
5843 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
;
5844 /* first put the channel on the conference in proper mode */
5845 if (ioctl(l
->pchan
->fds
[0], DAHDI_SETCONF
, &ci
) == -1)
5847 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
5848 ast_hangup(l
->chan
);
5849 ast_hangup(l
->pchan
);
5853 rpt_mutex_lock(&myrpt
->lock
);
5854 l
->reconnects
= reconnects
;
5855 /* insert at end of queue */
5856 l
->max_retries
= MAX_RETRIES
;
5858 l
->max_retries
= MAX_RETRIES_PERM
;
5859 if (l
->isremote
) l
->retries
= l
->max_retries
+ 1;
5860 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
5862 rpt_mutex_unlock(&myrpt
->lock
);
5863 if (!l
->phonemode
) send_newkey(l
->chan
);
5870 * Internet linking function
5873 static int function_ilink(struct rpt
*myrpt
, char *param
, char *digits
, int command_source
, struct rpt_link
*mylink
)
5876 char *val
, *s
, *s1
, *s2
;
5878 char digitbuf
[MAXNODESTR
],*strs
[MAXLINKLIST
];
5888 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
5891 strncpy(digitbuf
,digits
,MAXNODESTR
- 1);
5894 printf("@@@@ ilink param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
5896 switch(myatoi(param
)){
5897 case 11: /* Perm Link off */
5898 case 1: /* Link off */
5899 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
5900 strcpy(digitbuf
,myrpt
->lastlinknode
);
5901 val
= node_lookup(myrpt
,digitbuf
);
5903 if(strlen(digitbuf
) >= myrpt
->longestnode
)
5907 strncpy(tmp
,val
,sizeof(tmp
) - 1);
5909 s1
= strsep(&s
,",");
5910 if (!strchr(s1
,':') && strchr(s1
,'/') && strncasecmp(s1
, "local/", 6))
5912 sy
= strchr(s1
,'/');
5914 sprintf(sx
,"%s:4569/%s",s1
,sy
+ 1);
5917 s2
= strsep(&s
,",");
5918 rpt_mutex_lock(&myrpt
->lock
);
5919 l
= myrpt
->links
.next
;
5920 /* try to find this one in queue */
5921 while(l
!= &myrpt
->links
){
5922 if (l
->name
[0] == '0')
5927 /* if found matching string */
5928 if (!strcmp(l
->name
, digitbuf
))
5932 if (l
!= &myrpt
->links
){ /* if found */
5933 struct ast_frame wf
;
5935 /* must use perm command on perm link */
5936 if ((myatoi(param
) < 10) &&
5937 (l
->max_retries
> MAX_RETRIES
))
5939 rpt_mutex_unlock(&myrpt
->lock
);
5942 strncpy(myrpt
->lastlinknode
,digitbuf
,MAXNODESTR
- 1);
5943 l
->retries
= l
->max_retries
+ 1;
5945 rpt_mutex_unlock(&myrpt
->lock
);
5946 wf
.frametype
= AST_FRAME_TEXT
;
5950 wf
.datalen
= strlen(discstr
) + 1;
5952 wf
.data
.ptr
= discstr
;
5955 ast_write(l
->chan
,&wf
);
5956 if (ast_safe_sleep(l
->chan
,250) == -1) return DC_ERROR
;
5957 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
5959 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
5962 rpt_mutex_unlock(&myrpt
->lock
);
5964 case 2: /* Link Monitor */
5965 case 3: /* Link transceive */
5966 case 12: /* Link Monitor permanent */
5967 case 13: /* Link transceive permanent */
5968 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
5969 strcpy(digitbuf
,myrpt
->lastlinknode
);
5970 /* Attempt connection */
5971 perma
= (atoi(param
) > 10) ? 1 : 0;
5972 mode
= (atoi(param
) & 1) ? 1 : 0;
5973 r
= connect_link(myrpt
, digitbuf
, mode
, perma
);
5975 case -2: /* Attempt to connect to self */
5976 return DC_COMPLETE
; /* Silent error */
5979 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
5986 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
5990 rpt_telemetry(myrpt
, CONNFAIL
, NULL
);
5995 case 4: /* Enter Command Mode */
5997 /* if doesnt allow link cmd, or no links active, return */
5998 if (((command_source
!= SOURCE_RPT
) &&
5999 (command_source
!= SOURCE_PHONE
) &&
6000 (command_source
!= SOURCE_ALT
) &&
6001 (command_source
!= SOURCE_DPHONE
)) ||
6002 (myrpt
->links
.next
== &myrpt
->links
))
6005 /* if already in cmd mode, or selected self, fughetabahtit */
6006 if ((myrpt
->cmdnode
[0]) || (!strcmp(myrpt
->name
, digitbuf
))){
6008 rpt_telemetry(myrpt
, REMALREADY
, NULL
);
6011 if ((digitbuf
[0] == '0') && (myrpt
->lastlinknode
[0]))
6012 strcpy(digitbuf
,myrpt
->lastlinknode
);
6013 /* node must at least exist in list */
6014 val
= node_lookup(myrpt
,digitbuf
);
6016 if(strlen(digitbuf
) >= myrpt
->longestnode
)
6021 rpt_mutex_lock(&myrpt
->lock
);
6022 strcpy(myrpt
->lastlinknode
,digitbuf
);
6023 strncpy(myrpt
->cmdnode
, digitbuf
, sizeof(myrpt
->cmdnode
) - 1);
6024 rpt_mutex_unlock(&myrpt
->lock
);
6025 rpt_telemetry(myrpt
, REMGO
, NULL
);
6028 case 5: /* Status */
6029 rpt_telemetry(myrpt
, STATUS
, NULL
);
6032 case 15: /* Full Status */
6033 rpt_telemetry(myrpt
, FULLSTATUS
, NULL
);
6037 case 6: /* All Links Off, including permalinks */
6038 rpt_mutex_lock(&myrpt
->lock
);
6039 myrpt
->savednodes
[0] = 0;
6040 l
= myrpt
->links
.next
;
6041 /* loop through all links */
6042 while(l
!= &myrpt
->links
){
6043 struct ast_frame wf
;
6044 if (l
->name
[0] == '0') /* Skip any IAXRPT monitoring */
6049 /* Make a string of disconnected nodes for possible restoration */
6050 sprintf(tmp
,"%c%c%s",(l
->mode
) ? 'X' : 'M',(l
->perma
) ? 'P':'T',l
->name
);
6051 if(strlen(tmp
) + strlen(myrpt
->savednodes
) + 1 < MAXNODESTR
){
6052 if(myrpt
->savednodes
[0])
6053 strcat(myrpt
->savednodes
, ",");
6054 strcat(myrpt
->savednodes
, tmp
);
6056 l
->retries
= l
->max_retries
+ 1;
6057 l
->disced
= 2; /* Silently disconnect */
6058 rpt_mutex_unlock(&myrpt
->lock
);
6059 /* ast_log(LOG_NOTICE,"dumping link %s\n",l->name); */
6061 wf
.frametype
= AST_FRAME_TEXT
;
6065 wf
.datalen
= strlen(discstr
) + 1;
6067 wf
.data
.ptr
= discstr
;
6070 ast_write(l
->chan
,&wf
);
6071 ast_safe_sleep(l
->chan
,250); /* It's dead already, why check the return value? */
6072 ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
6074 rpt_mutex_lock(&myrpt
->lock
);
6077 rpt_mutex_unlock(&myrpt
->lock
);
6079 ast_log(LOG_NOTICE
,"Nodes disconnected: %s\n",myrpt
->savednodes
);
6080 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
6083 case 7: /* Identify last node which keyed us up */
6084 rpt_telemetry(myrpt
, LASTNODEKEY
, NULL
);
6088 #ifdef _MDC_DECODE_H_
6090 myrpt
->lastunit
= 0xd00d;
6091 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
6092 mdc1200_send(myrpt
,myrpt
->lastunit
);
6096 case 16: /* Restore links disconnected with "disconnect all links" command */
6097 strcpy(tmp
, myrpt
->savednodes
); /* Make a copy */
6098 finddelim(tmp
, strs
, MAXLINKLIST
); /* convert into substrings */
6099 for(i
= 0; tmp
[0] && strs
[i
] != NULL
&& i
< MAXLINKLIST
; i
++){
6101 mode
= (s1
[0] == 'X') ? 1 : 0;
6102 perma
= (s1
[1] == 'P') ? 1 : 0;
6103 connect_link(myrpt
, s1
+ 2, mode
, perma
); /* Try to reconnect */
6105 rpt_telemetry(myrpt
, COMPLETE
, NULL
);
6124 if (((myrpt
->p
.propagate_dtmf
) &&
6125 (command_source
== SOURCE_LNK
)) ||
6126 ((myrpt
->p
.propagate_phonedtmf
) &&
6127 ((command_source
== SOURCE_PHONE
) ||
6128 (command_source
== SOURCE_ALT
) ||
6129 (command_source
== SOURCE_DPHONE
))))
6130 do_dtmf_local(myrpt
,
6131 remdtmfstr
[myatoi(param
) - 200]);
6137 return DC_INDETERMINATE
;
6144 static int function_autopatchup(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
6146 pthread_attr_t attr
;
6147 int i
, index
, paramlength
;
6150 char *paramlist
[20];
6152 static char *keywords
[] = {
6161 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
6165 printf("@@@@ Autopatch up\n");
6167 if(!myrpt
->callmode
){
6169 myrpt
->patchnoct
= 0;
6170 myrpt
->patchdialtime
= 0;
6171 myrpt
->patchfarenddisconnect
= 0;
6172 myrpt
->patchquiet
= 0;
6173 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
6176 /* Process parameter list */
6177 lparam
= ast_strdup(param
);
6179 ast_log(LOG_ERROR
,"App_rpt out of memory on line %d\n",__LINE__
);
6182 paramlength
= finddelim(lparam
, paramlist
, 20);
6183 for(i
= 0; i
< paramlength
; i
++){
6184 index
= matchkeyword(paramlist
[i
], &value
, keywords
);
6186 value
= skipchars(value
, "= ");
6189 case 1: /* context */
6190 strncpy(myrpt
->patchcontext
, value
, MAXPATCHCONTEXT
- 1) ;
6193 case 2: /* dialtime */
6194 myrpt
->patchdialtime
= atoi(value
);
6197 case 3: /* farenddisconnect */
6198 myrpt
->patchfarenddisconnect
= atoi(value
);
6202 myrpt
->patchnoct
= atoi(value
);
6206 myrpt
->patchquiet
= atoi(value
);
6217 rpt_mutex_lock(&myrpt
->lock
);
6219 /* if on call, force * into current audio stream */
6221 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3)){
6222 myrpt
->mydtmf
= myrpt
->p
.endchar
;
6224 if (myrpt
->callmode
){
6225 rpt_mutex_unlock(&myrpt
->lock
);
6228 myrpt
->callmode
= 1;
6230 myrpt
->exten
[myrpt
->cidx
] = 0;
6231 rpt_mutex_unlock(&myrpt
->lock
);
6232 pthread_attr_init(&attr
);
6233 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
6234 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *) myrpt
);
6242 static int function_autopatchdn(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
6244 if (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
|| myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
6248 printf("@@@@ Autopatch down\n");
6250 rpt_mutex_lock(&myrpt
->lock
);
6252 myrpt
->macropatch
=0;
6254 if (!myrpt
->callmode
){
6255 rpt_mutex_unlock(&myrpt
->lock
);
6259 myrpt
->callmode
= 0;
6260 channel_revert(myrpt
);
6261 rpt_mutex_unlock(&myrpt
->lock
);
6262 rpt_telemetry(myrpt
, TERM
, NULL
);
6270 static int function_status(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
6276 if ((myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
) || (myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
))
6280 printf("@@@@ status param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
6282 switch(myatoi(param
)){
6283 case 1: /* System ID */
6284 rpt_telemetry(myrpt
, ID1
, NULL
);
6286 case 2: /* System Time */
6287 rpt_telemetry(myrpt
, STATS_TIME
, NULL
);
6289 case 3: /* app_rpt.c version */
6290 rpt_telemetry(myrpt
, STATS_VERSION
, NULL
);
6292 case 11: /* System ID (local only)*/
6293 rpt_telemetry(myrpt
, ID
, NULL
);
6295 case 12: /* System Time (local only)*/
6296 rpt_telemetry(myrpt
, STATS_TIME_LOCAL
, NULL
);
6301 return DC_INDETERMINATE
;
6304 * Macro-oni (without Salami)
6306 static int function_macro(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
6314 printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
6316 if(strlen(digitbuf
) < 1) /* needs 1 digit */
6317 return DC_INDETERMINATE
;
6319 for(i
= 0 ; i
< digitbuf
[i
] ; i
++) {
6320 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
6324 if (*digitbuf
== '0') val
= myrpt
->p
.startupmacro
;
6325 else val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, digitbuf
);
6326 /* param was 1 for local buf */
6328 if (strlen(digitbuf
) < myrpt
->macro_longest
)
6329 return DC_INDETERMINATE
;
6330 rpt_telemetry(myrpt
, MACRO_NOTFOUND
, NULL
);
6333 rpt_mutex_lock(&myrpt
->lock
);
6334 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
))
6336 rpt_mutex_unlock(&myrpt
->lock
);
6337 rpt_telemetry(myrpt
, MACRO_BUSY
, NULL
);
6340 myrpt
->macrotimer
= MACROTIME
;
6341 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- 1);
6342 rpt_mutex_unlock(&myrpt
->lock
);
6347 * Playback a recording
6350 static int function_playback(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
6357 printf("@@@@ playback param = %s, digitbuf = %s\n", (param
)? param
: "(null)", digitbuf
);
6359 if (ast_fileexists(param
,NULL
,myrpt
->rxchannel
->language
) <= 0)
6362 rpt_telemetry(myrpt
,PLAYBACK
,param
);
6367 * COP - Control operator
6370 static int function_cop(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
6379 switch(myatoi(param
)){
6380 case 1: /* System reset */
6381 system("killall -9 asterisk");
6385 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 0;
6386 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "RPTENA");
6390 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
= 1;
6393 case 4: /* test tone on */
6394 if (myrpt
->stopgen
< 0)
6401 rpt_telemetry(myrpt
, TEST_TONE
, NULL
);
6405 case 5: /* Disgorge variables to log for debug purposes */
6406 myrpt
->disgorgetime
= time(NULL
) + 10; /* Do it 10 seconds later */
6409 case 6: /* Simulate COR being activated (phone only) */
6410 if (command_source
!= SOURCE_PHONE
) return DC_INDETERMINATE
;
6414 case 7: /* Time out timer enable */
6415 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 0;
6416 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTENA");
6419 case 8: /* Time out timer disable */
6420 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
= 1;
6421 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "TOTDIS");
6424 case 9: /* Autopatch enable */
6425 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 0;
6426 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APENA");
6429 case 10: /* Autopatch disable */
6430 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
= 1;
6431 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "APDIS");
6434 case 11: /* Link Enable */
6435 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 0;
6436 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKENA");
6439 case 12: /* Link Disable */
6440 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
= 1;
6441 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "LNKDIS");
6444 case 13: /* Query System State */
6445 string
[0] = string
[1] = 'S';
6446 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
6448 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
6451 case 14: /* Change System State */
6452 if(strlen(digitbuf
) == 0)
6454 if((digitbuf
[0] < '0') || (digitbuf
[0] > '9'))
6456 myrpt
->p
.sysstate_cur
= digitbuf
[0] - '0';
6457 string
[0] = string
[1] = 'S';
6458 string
[2] = myrpt
->p
.sysstate_cur
+ '0';
6460 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) string
);
6463 case 15: /* Scheduler Enable */
6464 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 0;
6465 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKENA");
6468 case 16: /* Scheduler Disable */
6469 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
= 1;
6470 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "SKDIS");
6473 case 17: /* User functions Enable */
6474 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 0;
6475 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFENA");
6478 case 18: /* User Functions Disable */
6479 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
= 1;
6480 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "UFDIS");
6483 case 19: /* Alternate Tail Enable */
6484 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 1;
6485 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATENA");
6488 case 20: /* Alternate Tail Disable */
6489 myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
= 0;
6490 rpt_telemetry(myrpt
, ARB_ALPHA
, (void *) "ATDIS");
6493 case 21: /* Parrot Mode Disable */
6495 if (myrpt
->p
.parrotmode
< 2)
6497 myrpt
->p
.parrotmode
= 0;
6498 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
6503 case 22: /* Parrot Mode Enable */
6505 if (myrpt
->p
.parrotmode
< 2)
6507 myrpt
->p
.parrotmode
= 1;
6508 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
6512 case 23: /* flush parrot in progress */
6514 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
6516 case 24: /* flush all telemetry */
6518 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
6520 case 25: /* request keying info (brief) */
6521 send_link_keyquery(myrpt
);
6522 myrpt
->topkeylong
= 0;
6523 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
6525 case 26: /* request keying info (full) */
6526 send_link_keyquery(myrpt
);
6527 myrpt
->topkeylong
= 1;
6528 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
6531 case 30: /* recall memory location on programmable radio */
6533 if(strlen(digitbuf
) < 2) /* needs 2 digits */
6536 for(i
= 0 ; i
< 2 ; i
++){
6537 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
6541 r
= retreive_memory(myrpt
, digitbuf
);
6543 rpt_telemetry(myrpt
,MEMNOTFOUND
,NULL
);
6549 if (setrem(myrpt
) == -1) return DC_ERROR
;
6553 /* set channel. note that it's going to change channel
6554 then confirm on the new channel! */
6555 if(strlen(digitbuf
) < 2) /* needs 2 digits */
6558 for(i
= 0 ; i
< 2 ; i
++){
6559 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
6562 channel_steer(myrpt
,digitbuf
);
6565 case 32: /* Touch Tone Pad Test */
6566 i
= strlen(digitbuf
);
6569 ast_log(LOG_NOTICE
,"Padtest entered");
6570 myrpt
->inpadtest
= 1;
6574 ast_log(LOG_NOTICE
,"Padtest len= %d digits=%s",i
,digitbuf
);
6575 if(digitbuf
[i
-1] != myrpt
->p
.endchar
)
6577 rpt_telemetry(myrpt
, ARB_ALPHA
, digitbuf
);
6578 myrpt
->inpadtest
= 0;
6580 ast_log(LOG_NOTICE
,"Padtest exited");
6584 return DC_INDETERMINATE
;
6587 * Collect digits one by one until something matches
6589 static int collect_function_digits(struct rpt
*myrpt
, char *digits
,
6590 int command_source
, struct rpt_link
*mylink
)
6593 char *stringp
,*action
,*param
,*functiondigits
;
6594 char function_table_name
[30] = "";
6595 char workstring
[200];
6597 struct ast_variable
*vp
;
6599 if (debug
> 6) ast_log(LOG_NOTICE
,"digits=%s source=%d\n",digits
, command_source
);
6602 // printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
6604 if (command_source
== SOURCE_DPHONE
) {
6605 if (!myrpt
->p
.dphone_functions
) return DC_INDETERMINATE
;
6606 strncpy(function_table_name
, myrpt
->p
.dphone_functions
, sizeof(function_table_name
) - 1);
6608 else if (command_source
== SOURCE_ALT
) {
6609 if (!myrpt
->p
.alt_functions
) return DC_INDETERMINATE
;
6610 strncpy(function_table_name
, myrpt
->p
.alt_functions
, sizeof(function_table_name
) - 1);
6612 else if (command_source
== SOURCE_PHONE
) {
6613 if (!myrpt
->p
.phone_functions
) return DC_INDETERMINATE
;
6614 strncpy(function_table_name
, myrpt
->p
.phone_functions
, sizeof(function_table_name
) - 1);
6616 else if (command_source
== SOURCE_LNK
)
6617 strncpy(function_table_name
, myrpt
->p
.link_functions
, sizeof(function_table_name
) - 1);
6619 strncpy(function_table_name
, myrpt
->p
.functions
, sizeof(function_table_name
) - 1);
6620 /* find context for function table in rpt.conf file */
6621 vp
= ast_variable_browse(myrpt
->cfg
, function_table_name
);
6623 if(!strncasecmp(vp
->name
, digits
, strlen(vp
->name
)))
6627 /* if function context not found */
6631 n
= myrpt
->longestfunc
;
6632 if (command_source
== SOURCE_LNK
) n
= myrpt
->link_longestfunc
;
6634 if (command_source
== SOURCE_PHONE
) n
= myrpt
->phone_longestfunc
;
6636 if (command_source
== SOURCE_ALT
) n
= myrpt
->alt_longestfunc
;
6638 if (command_source
== SOURCE_DPHONE
) n
= myrpt
->dphone_longestfunc
;
6640 if(strlen(digits
) >= n
)
6643 return DC_INDETERMINATE
;
6645 /* Found a match, retrieve value part and parse */
6646 strncpy(workstring
, vp
->value
, sizeof(workstring
) - 1 );
6647 stringp
= workstring
;
6648 action
= strsep(&stringp
, ",");
6651 printf("@@@@ action: %s, param = %s\n",action
, (param
) ? param
: "(null)");
6652 /* Look up the action */
6653 for(i
= 0 ; i
< (sizeof(function_table
)/sizeof(struct function_table_tag
)); i
++){
6654 if(!strncasecmp(action
, function_table
[i
].action
, strlen(action
)))
6658 printf("@@@@ table index i = %d\n",i
);
6659 if(i
== (sizeof(function_table
)/sizeof(struct function_table_tag
))){
6660 /* Error, action not in table */
6663 if(function_table
[i
].function
== NULL
){
6664 /* Error, function undefined */
6666 printf("@@@@ NULL for action: %s\n",action
);
6669 functiondigits
= digits
+ strlen(vp
->name
);
6670 rv
=(*function_table
[i
].function
)(myrpt
, param
, functiondigits
, command_source
, mylink
);
6671 if (debug
> 6) ast_log(LOG_NOTICE
,"rv=%i\n",rv
);
6676 static void handle_link_data(struct rpt
*myrpt
, struct rpt_link
*mylink
,
6679 char tmp
[512],tmp1
[512],cmd
[300] = "",dest
[300],src
[300],c
;
6682 struct ast_frame wf
;
6684 wf
.frametype
= AST_FRAME_TEXT
;
6688 wf
.datalen
= strlen(str
) + 1;
6690 /* put string in our buffer */
6691 strncpy(tmp
,str
,sizeof(tmp
) - 1);
6693 if (!strcmp(tmp
,discstr
))
6696 mylink
->retries
= mylink
->max_retries
+ 1;
6697 ast_softhangup(mylink
->chan
,AST_SOFTHANGUP_DEV
);
6700 if (!strcmp(tmp
,newkeystr
))
6707 rpt_mutex_lock(&myrpt
->lock
);
6708 strcpy(mylink
->linklist
,tmp
+ 2);
6709 time(&mylink
->linklistreceived
);
6710 rpt_mutex_unlock(&myrpt
->lock
);
6711 if (debug
> 6) ast_log(LOG_NOTICE
,"@@@@ node %s recieved node list %s from node %s\n",
6712 myrpt
->name
,tmp
,mylink
->name
);
6717 if (sscanf(tmp
,"%s %s %s %d %d",cmd
,dest
,src
,&seq
,&ts
) != 5)
6719 ast_log(LOG_WARNING
, "Unable to parse keying string %s\n",str
);
6724 strcpy(dest
,myrpt
->name
);
6726 /* if not for me, redistribute to all links */
6727 if (strcmp(dest
,myrpt
->name
))
6729 l
= myrpt
->links
.next
;
6730 /* see if this is one in list */
6731 while(l
!= &myrpt
->links
)
6733 if (l
->name
[0] == '0')
6738 /* dont send back from where it came */
6739 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
6744 /* if it is, send it and we're done */
6745 if (!strcmp(l
->name
,dest
))
6747 /* send, but not to src */
6748 if (strcmp(l
->name
,src
)) {
6750 if (l
->chan
) ast_write(l
->chan
,&wf
);
6757 /* if not for me, or is broadcast, redistribute to all links */
6758 if ((strcmp(dest
,myrpt
->name
)) || (dest
[0] == '*'))
6760 l
= myrpt
->links
.next
;
6761 /* otherwise, send it to all of em */
6762 while(l
!= &myrpt
->links
)
6764 if (l
->name
[0] == '0')
6769 /* dont send back from where it came */
6770 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
6775 /* send, but not to src */
6776 if (strcmp(l
->name
,src
)) {
6778 if (l
->chan
) ast_write(l
->chan
,&wf
);
6783 /* if not for me, end here */
6784 if (strcmp(dest
,myrpt
->name
) && (dest
[0] != '*')) return;
6791 if (myrpt
->lastkeyedtime
)
6793 n
= (int)(now
- myrpt
->lastkeyedtime
);
6795 sprintf(tmp1
,"K %s %s %d %d",src
,myrpt
->name
,myrpt
->keyed
,n
);
6797 wf
.datalen
= strlen(tmp1
) + 1;
6798 if (mylink
->chan
) ast_write(mylink
->chan
,&wf
);
6801 if (myrpt
->topkeystate
!= 1) return;
6802 rpt_mutex_lock(&myrpt
->lock
);
6803 for(i
= 0; i
< TOPKEYN
; i
++)
6805 if (!strcmp(myrpt
->topkey
[i
].node
,src
)) break;
6809 for(i
= 0; i
< TOPKEYN
; i
++)
6811 if (!myrpt
->topkey
[i
].node
[0]) break;
6816 strncpy(myrpt
->topkey
[i
].node
,src
,TOPKEYMAXSTR
- 1);
6817 myrpt
->topkey
[i
].timesince
= ts
;
6818 myrpt
->topkey
[i
].keyed
= seq
;
6820 rpt_mutex_unlock(&myrpt
->lock
);
6825 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
6827 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
6830 mdc1200_notify(myrpt
,src
,seq
);
6835 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
6837 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
6840 if (strcmp(cmd
,"D"))
6842 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
6848 strcpy(dest
,myrpt
->name
);
6851 /* if not for me, redistribute to all links */
6852 if (strcmp(dest
,myrpt
->name
))
6854 l
= myrpt
->links
.next
;
6855 /* see if this is one in list */
6856 while(l
!= &myrpt
->links
)
6858 if (l
->name
[0] == '0')
6863 /* dont send back from where it came */
6864 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
6869 /* if it is, send it and we're done */
6870 if (!strcmp(l
->name
,dest
))
6872 /* send, but not to src */
6873 if (strcmp(l
->name
,src
)) {
6875 if (l
->chan
) ast_write(l
->chan
,&wf
);
6881 l
= myrpt
->links
.next
;
6882 /* otherwise, send it to all of em */
6883 while(l
!= &myrpt
->links
)
6885 if (l
->name
[0] == '0')
6890 /* dont send back from where it came */
6891 if ((l
== mylink
) || (!strcmp(l
->name
,mylink
->name
)))
6896 /* send, but not to src */
6897 if (strcmp(l
->name
,src
)) {
6899 if (l
->chan
) ast_write(l
->chan
,&wf
);
6905 if (myrpt
->p
.archivedir
)
6909 sprintf(str
,"DTMF,%s,%c",mylink
->name
,c
);
6910 donodelog(myrpt
,str
);
6912 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
6914 rpt_mutex_lock(&myrpt
->lock
);
6915 if (c
== myrpt
->p
.endchar
) myrpt
->stopgen
= 1;
6916 if (myrpt
->callmode
== 1)
6918 myrpt
->exten
[myrpt
->cidx
++] = c
;
6919 myrpt
->exten
[myrpt
->cidx
] = 0;
6920 /* if this exists */
6921 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
6923 /* if this really it, end now */
6924 if (!ast_matchmore_extension(myrpt
->pchannel
,myrpt
->patchcontext
,
6925 myrpt
->exten
,1,NULL
))
6927 myrpt
->callmode
= 2;
6928 if(!myrpt
->patchquiet
)
6930 rpt_mutex_unlock(&myrpt
->lock
);
6931 rpt_telemetry(myrpt
,PROC
,NULL
);
6932 rpt_mutex_lock(&myrpt
->lock
);
6935 else /* othewise, reset timer */
6937 myrpt
->calldigittimer
= 1;
6940 /* if can continue, do so */
6941 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
6943 /* call has failed, inform user */
6944 myrpt
->callmode
= 4;
6947 if ((!myrpt
->inpadtest
) &&(c
== myrpt
->p
.funcchar
))
6949 myrpt
->rem_dtmfidx
= 0;
6950 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
6951 time(&myrpt
->rem_dtmf_time
);
6952 rpt_mutex_unlock(&myrpt
->lock
);
6955 else if (myrpt
->rem_dtmfidx
< 0)
6957 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
6961 if (myrpt
->p
.propagate_dtmf
) do_dtmf_local(myrpt
,c
);
6962 if (myrpt
->p
.propagate_phonedtmf
) do_dtmf_phone(myrpt
,mylink
,c
);
6963 rpt_mutex_unlock(&myrpt
->lock
);
6966 else if (((myrpt
->inpadtest
) || (c
!= myrpt
->p
.endchar
)) && (myrpt
->rem_dtmfidx
>= 0))
6968 time(&myrpt
->rem_dtmf_time
);
6969 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
6971 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
6972 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
6974 rpt_mutex_unlock(&myrpt
->lock
);
6975 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
6976 res
= collect_function_digits(myrpt
, cmd
, SOURCE_LNK
, mylink
);
6977 rpt_mutex_lock(&myrpt
->lock
);
6981 case DC_INDETERMINATE
:
6985 myrpt
->rem_dtmfidx
= 0;
6986 myrpt
->rem_dtmfbuf
[0] = 0;
6991 case DC_COMPLETEQUIET
:
6992 myrpt
->totalexecdcommands
++;
6993 myrpt
->dailyexecdcommands
++;
6994 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
6995 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
6996 myrpt
->rem_dtmfbuf
[0] = 0;
6997 myrpt
->rem_dtmfidx
= -1;
6998 myrpt
->rem_dtmf_time
= 0;
7003 myrpt
->rem_dtmfbuf
[0] = 0;
7004 myrpt
->rem_dtmfidx
= -1;
7005 myrpt
->rem_dtmf_time
= 0;
7011 rpt_mutex_unlock(&myrpt
->lock
);
7015 static void handle_link_phone_dtmf(struct rpt
*myrpt
, struct rpt_link
*mylink
,
7022 if (myrpt
->p
.archivedir
)
7026 sprintf(str
,"DTMF(P),%s,%c",mylink
->name
,c
);
7027 donodelog(myrpt
,str
);
7029 rpt_mutex_lock(&myrpt
->lock
);
7031 if (mylink
->phonemode
== 3) /*If in simplex dumb phone mode */
7033 if(c
== myrpt
->p
.endchar
) /* If end char */
7035 mylink
->lastrealrx
= 0; /* Keying state = off */
7036 rpt_mutex_unlock(&myrpt
->lock
);
7040 if(c
== myrpt
->p
.funcchar
) /* If lead-in char */
7042 mylink
->lastrealrx
= !mylink
->lastrealrx
; /* Toggle keying state */
7043 rpt_mutex_unlock(&myrpt
->lock
);
7049 if (c
== myrpt
->p
.endchar
)
7053 mylink
->lastrealrx
= 0;
7054 rpt_mutex_unlock(&myrpt
->lock
);
7058 if (myrpt
->cmdnode
[0])
7060 myrpt
->cmdnode
[0] = 0;
7061 myrpt
->dtmfidx
= -1;
7062 myrpt
->dtmfbuf
[0] = 0;
7063 rpt_mutex_unlock(&myrpt
->lock
);
7064 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
7069 if (myrpt
->cmdnode
[0])
7071 rpt_mutex_unlock(&myrpt
->lock
);
7072 send_link_dtmf(myrpt
,c
);
7075 if (myrpt
->callmode
== 1)
7077 myrpt
->exten
[myrpt
->cidx
++] = c
;
7078 myrpt
->exten
[myrpt
->cidx
] = 0;
7079 /* if this exists */
7080 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
7082 /* if this really it, end now */
7083 if (!ast_matchmore_extension(myrpt
->pchannel
,myrpt
->patchcontext
,
7084 myrpt
->exten
,1,NULL
))
7086 myrpt
->callmode
= 2;
7087 if(!myrpt
->patchquiet
)
7089 rpt_mutex_unlock(&myrpt
->lock
);
7090 rpt_telemetry(myrpt
,PROC
,NULL
);
7091 rpt_mutex_lock(&myrpt
->lock
);
7094 else /* othewise, reset timer */
7096 myrpt
->calldigittimer
= 1;
7099 /* if can continue, do so */
7100 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
7102 /* call has failed, inform user */
7103 myrpt
->callmode
= 4;
7106 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
7110 if ((!myrpt
->inpadtest
) && (c
== myrpt
->p
.funcchar
))
7112 myrpt
->rem_dtmfidx
= 0;
7113 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
7114 time(&myrpt
->rem_dtmf_time
);
7115 rpt_mutex_unlock(&myrpt
->lock
);
7118 else if (((myrpt
->inpadtest
) || (c
!= myrpt
->p
.endchar
)) && (myrpt
->rem_dtmfidx
>= 0))
7120 time(&myrpt
->rem_dtmf_time
);
7121 if (myrpt
->rem_dtmfidx
< MAXDTMF
)
7123 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
++] = c
;
7124 myrpt
->rem_dtmfbuf
[myrpt
->rem_dtmfidx
] = 0;
7126 rpt_mutex_unlock(&myrpt
->lock
);
7127 strncpy(cmd
, myrpt
->rem_dtmfbuf
, sizeof(cmd
) - 1);
7128 switch(mylink
->phonemode
)
7131 res
= collect_function_digits(myrpt
, cmd
,
7132 SOURCE_PHONE
, mylink
);
7135 res
= collect_function_digits(myrpt
, cmd
,
7136 SOURCE_DPHONE
,mylink
);
7139 res
= collect_function_digits(myrpt
, cmd
,
7143 res
= collect_function_digits(myrpt
, cmd
,
7144 SOURCE_LNK
, mylink
);
7148 rpt_mutex_lock(&myrpt
->lock
);
7152 case DC_INDETERMINATE
:
7156 mylink
->lastrealrx
= 1;
7160 myrpt
->rem_dtmfidx
= 0;
7161 myrpt
->rem_dtmfbuf
[0] = 0;
7166 case DC_COMPLETEQUIET
:
7167 myrpt
->totalexecdcommands
++;
7168 myrpt
->dailyexecdcommands
++;
7169 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
7170 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
7171 myrpt
->rem_dtmfbuf
[0] = 0;
7172 myrpt
->rem_dtmfidx
= -1;
7173 myrpt
->rem_dtmf_time
= 0;
7178 myrpt
->rem_dtmfbuf
[0] = 0;
7179 myrpt
->rem_dtmfidx
= -1;
7180 myrpt
->rem_dtmf_time
= 0;
7186 rpt_mutex_unlock(&myrpt
->lock
);
7190 /* Doug Hall RBI-1 serial data definitions:
7192 * Byte 0: Expansion external outputs
7194 * Bits 0-3 are BAND as follows:
7195 * Bits 4-5 are POWER bits as follows:
7199 * Bits 6-7 are always set
7201 * Bits 0-3 MHZ in BCD format
7202 * Bits 4-5 are offset as follows:
7206 * 03 - minus minus (whatever that is)
7207 * Bit 6 is the 0/5 KHZ bit
7208 * Bit 7 is always set
7210 * Bits 0-3 are 10 KHZ in BCD format
7211 * Bits 4-7 are 100 KHZ in BCD format
7212 * Byte 4: PL Tone code and encode/decode enable bits
7213 * Bits 0-5 are PL tone code (comspec binary codes)
7214 * Bit 6 is encode enable/disable
7215 * Bit 7 is decode enable/disable
7218 /* take the frequency from the 10 mhz digits (and up) and convert it
7221 static int rbi_mhztoband(char *str
)
7225 i
= atoi(str
) / 10; /* get the 10's of mhz */
7256 /* take a PL frequency and turn it into a code */
7257 static int rbi_pltocode(char *str
)
7262 s
= strchr(str
,'.');
7264 if (s
) i
= atoi(s
+ 1);
7265 i
+= atoi(str
) * 10;
7349 * Shift out a formatted serial bit stream
7352 static void rbi_out_parallel(struct rpt
*myrpt
,unsigned char *data
)
7357 static volatile long long delayvar
;
7359 for(i
= 0 ; i
< 5 ; i
++){
7361 for(j
= 0 ; j
< 8 ; j
++){
7363 outb(d
,myrpt
->p
.iobase
);
7365 for(delayvar
= 1; delayvar
< 15000; delayvar
++);
7367 outb(d
| 2,myrpt
->p
.iobase
);
7369 for(delayvar
= 1; delayvar
< 30000; delayvar
++);
7370 outb(d
,myrpt
->p
.iobase
);
7372 for(delayvar
= 1; delayvar
< 10000; delayvar
++);
7376 for(delayvar
= 1; delayvar
< 50000; delayvar
++);
7380 static void rbi_out(struct rpt
*myrpt
,unsigned char *data
)
7382 struct dahdi_radio_param r
;
7384 memset(&r
,0,sizeof(struct dahdi_radio_param
));
7385 r
.radpar
= DAHDI_RADPAR_REMMODE
;
7386 r
.data
= DAHDI_RADPAR_REM_RBI1
;
7387 /* if setparam ioctl fails, its probably not a pciradio card */
7388 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&r
) == -1)
7390 rbi_out_parallel(myrpt
,data
);
7393 r
.radpar
= DAHDI_RADPAR_REMCOMMAND
;
7394 memcpy(&r
.data
,data
,5);
7395 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&r
) == -1)
7397 ast_log(LOG_WARNING
,"Cannot send RBI command for channel %s\n",myrpt
->dahdirxchannel
->name
);
7402 static int serial_remote_io(struct rpt
*myrpt
, unsigned char *txbuf
, int txbytes
,
7403 unsigned char *rxbuf
, int rxmaxbytes
, int asciiflag
)
7405 int i
,j
,index
,oldmode
,olddata
;
7406 struct dahdi_radio_param prm
;
7410 ast_log(LOG_NOTICE
, "ioport=%s iofd=0x%x\n",myrpt
->p
.ioport
,myrpt
->iofd
);
7411 printf("String output was:\n");
7412 for(i
= 0; i
< txbytes
; i
++)
7413 printf("%02X ", (unsigned char ) txbuf
[i
]);
7417 if (myrpt
->iofd
>= 0) /* if to do out a serial port */
7419 if (write(myrpt
->iofd
,txbuf
,txbytes
) != txbytes
)
7423 if ((!rxmaxbytes
) || (rxbuf
== NULL
))
7427 memset(rxbuf
,0,rxmaxbytes
);
7428 for(i
= 0; i
< rxmaxbytes
; i
++)
7430 j
= read(myrpt
->iofd
,&c
,1);
7439 if (c
== '\r') break;
7443 printf("String returned was:\n");
7444 for(j
= 0; j
< i
; j
++)
7445 printf("%02X ", (unsigned char ) rxbuf
[j
]);
7451 /* if not a DAHDI channel, cant use pciradio stuff */
7452 if (myrpt
->rxchannel
!= myrpt
->dahdirxchannel
) return -1;
7454 prm
.radpar
= DAHDI_RADPAR_UIOMODE
;
7455 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_GETPARAM
,&prm
) == -1) return -1;
7457 prm
.radpar
= DAHDI_RADPAR_UIODATA
;
7458 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_GETPARAM
,&prm
) == -1) return -1;
7460 prm
.radpar
= DAHDI_RADPAR_REMMODE
;
7461 if (asciiflag
& 1) prm
.data
= DAHDI_RADPAR_REM_SERIAL_ASCII
;
7462 else prm
.data
= DAHDI_RADPAR_REM_SERIAL
;
7463 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
7467 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1) return -1;
7470 prm
.radpar
= DAHDI_RADPAR_REMCOMMAND
;
7471 prm
.data
= rxmaxbytes
;
7472 memcpy(prm
.buf
,txbuf
,txbytes
);
7473 prm
.index
= txbytes
;
7474 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
7478 memcpy(rxbuf
,prm
.buf
,prm
.index
);
7481 prm
.radpar
= DAHDI_RADPAR_REMMODE
;
7482 prm
.data
= DAHDI_RADPAR_REM_NONE
;
7483 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
7487 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1) return -1;
7489 prm
.radpar
= DAHDI_RADPAR_UIOMODE
;
7491 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
7492 prm
.radpar
= DAHDI_RADPAR_UIODATA
;
7494 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&prm
) == -1) return -1;
7498 static int civ_cmd(struct rpt
*myrpt
,unsigned char *cmd
, int cmdlen
)
7500 unsigned char rxbuf
[100];
7503 rv
= serial_remote_io(myrpt
,cmd
,cmdlen
,rxbuf
,cmdlen
+ 6,0);
7504 if (rv
== -1) return(-1);
7505 if (rv
!= (cmdlen
+ 6)) return(1);
7506 for(i
= 0; i
< 6; i
++)
7507 if (rxbuf
[i
] != cmd
[i
]) return(1);
7508 if (rxbuf
[cmdlen
] != 0xfe) return(1);
7509 if (rxbuf
[cmdlen
+ 1] != 0xfe) return(1);
7510 if (rxbuf
[cmdlen
+ 4] != 0xfb) return(1);
7511 if (rxbuf
[cmdlen
+ 5] != 0xfd) return(1);
7515 static int sendkenwood(struct rpt
*myrpt
,char *txstr
, char *rxstr
)
7519 ast_log(LOG_NOTICE
,"Sent to kenwood: %s\n",txstr
);
7520 if (debug
) printf("Send to kenwood: %s\n",txstr
);
7521 i
= serial_remote_io(myrpt
, (unsigned char *)txstr
, strlen(txstr
),
7522 (unsigned char *)rxstr
,RAD_SERIAL_BUFLEN
- 1,3);
7523 if (i
< 0) return -1;
7524 if ((i
> 0) && (rxstr
[i
- 1] == '\r'))
7526 if (debug
) printf("Got from kenwood: %s\n",rxstr
);
7527 ast_log(LOG_NOTICE
,"Got from kenwood: %s\n",rxstr
);
7531 /* take a PL frequency and turn it into a code */
7532 static int kenwood_pltocode(char *str
)
7537 s
= strchr(str
,'.');
7539 if (s
) i
= atoi(s
+ 1);
7540 i
+= atoi(str
) * 10;
7623 static int sendrxkenwood(struct rpt
*myrpt
, char *txstr
, char *rxstr
,
7628 for(i
= 0;i
< KENWOOD_RETRIES
;i
++)
7630 j
= sendkenwood(myrpt
,txstr
,rxstr
);
7631 if (j
< 0) return(j
);
7632 if (j
== 0) continue;
7633 if (!strncmp(rxstr
,cmpstr
,strlen(cmpstr
))) return(0);
7638 static int setkenwood(struct rpt
*myrpt
)
7640 char rxstr
[RAD_SERIAL_BUFLEN
],txstr
[RAD_SERIAL_BUFLEN
],freq
[20];
7641 char mhz
[MAXREMSTR
],offset
[20],band
,decimals
[MAXREMSTR
],band1
,band2
;
7644 int offsets
[] = {0,2,1};
7645 int powers
[] = {2,1,0};
7647 if (sendrxkenwood(myrpt
,"VMC 0,0\r",rxstr
,"VMC") < 0) return -1;
7648 split_freq(mhz
, decimals
, myrpt
->freq
);
7649 if (atoi(mhz
) > 400)
7654 strcpy(offset
,"005000000");
7661 strcpy(offset
,"000600000");
7663 strcpy(freq
,"000000");
7664 strncpy(freq
,decimals
,strlen(decimals
));
7665 myrxpl
= myrpt
->rxplon
;
7666 if (IS_XPMR(myrpt
)) myrxpl
= 0;
7667 sprintf(txstr
,"VW %c,%05d%s,0,%d,0,%d,%d,,%02d,,%02d,%s\r",
7668 band
,atoi(mhz
),freq
,offsets
[(int)myrpt
->offset
],
7669 (myrpt
->txplon
!= 0),myrxpl
,
7670 kenwood_pltocode(myrpt
->txpl
),kenwood_pltocode(myrpt
->rxpl
),
7672 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"VW") < 0) return -1;
7673 sprintf(txstr
,"RBN %c\r",band2
);
7674 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"RBN") < 0) return -1;
7675 sprintf(txstr
,"PC %c,%d\r",band1
,powers
[(int)myrpt
->powerlevel
]);
7676 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"PC") < 0) return -1;
7680 static int set_tm271(struct rpt
*myrpt
)
7682 char rxstr
[RAD_SERIAL_BUFLEN
],txstr
[RAD_SERIAL_BUFLEN
],freq
[20];
7683 char mhz
[MAXREMSTR
],decimals
[MAXREMSTR
];
7685 int offsets
[] = {0,2,1};
7686 int powers
[] = {2,1,0};
7688 split_freq(mhz
, decimals
, myrpt
->freq
);
7689 strcpy(freq
,"000000");
7690 strncpy(freq
,decimals
,strlen(decimals
));
7692 sprintf(txstr
,"VF %04d%s,4,%d,0,%d,0,0,%d,%d,000,00600000,0,0\r",
7693 atoi(mhz
),freq
,offsets
[(int)myrpt
->offset
],
7694 (myrpt
->txplon
!= 0),kenwood_pltocode(myrpt
->txpl
),
7695 kenwood_pltocode(myrpt
->rxpl
));
7697 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"VF") < 0) return -1;
7698 if (sendrxkenwood(myrpt
,"VM 0\r",rxstr
,"VM") < 0) return -1;
7699 sprintf(txstr
,"PC %d\r",powers
[(int)myrpt
->powerlevel
]);
7700 if (sendrxkenwood(myrpt
,txstr
,rxstr
,"PC") < 0) return -1;
7704 static int setrbi(struct rpt
*myrpt
)
7706 char tmp
[MAXREMSTR
] = "",*s
;
7707 unsigned char rbicmd
[5];
7708 int band
,txoffset
= 0,txpower
= 0,rxpl
;
7710 /* must be a remote system */
7711 if (!myrpt
->remoterig
) return(0);
7712 if (!myrpt
->remoterig
[0]) return(0);
7713 /* must have rbi hardware */
7714 if (strncmp(myrpt
->remoterig
,remote_rig_rbi
,3)) return(0);
7715 if (setrbi_check(myrpt
) == -1) return(-1);
7716 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
7717 s
= strchr(tmp
,'.');
7718 /* if no decimal, is invalid */
7722 printf("@@@@ Frequency needs a decimal\n");
7727 if (strlen(tmp
) < 2){
7729 printf("@@@@ Bad MHz digits: %s\n", tmp
);
7735 printf("@@@@ Bad KHz digits: %s\n", s
);
7739 if ((s
[2] != '0') && (s
[2] != '5')){
7741 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
7745 band
= rbi_mhztoband(tmp
);
7748 printf("@@@@ Bad Band: %s\n", tmp
);
7752 rxpl
= rbi_pltocode(myrpt
->rxpl
);
7756 printf("@@@@ Bad TX PL: %s\n", myrpt
->rxpl
);
7761 switch(myrpt
->offset
)
7773 switch(myrpt
->powerlevel
)
7786 rbicmd
[1] = band
| txpower
| 0xc0;
7787 rbicmd
[2] = (*(s
- 2) - '0') | txoffset
| 0x80;
7788 if (s
[2] == '5') rbicmd
[2] |= 0x40;
7789 rbicmd
[3] = ((*s
- '0') << 4) + (s
[1] - '0');
7791 if (myrpt
->txplon
) rbicmd
[4] |= 0x40;
7792 if (myrpt
->rxplon
) rbicmd
[4] |= 0x80;
7793 rbi_out(myrpt
,rbicmd
);
7797 static int setrtx(struct rpt
*myrpt
)
7799 char tmp
[MAXREMSTR
] = "",*s
,rigstr
[200],pwr
,res
= 0;
7800 int band
,txoffset
= 0,txpower
= 0,rxpl
,txpl
;
7804 /* must be a remote system */
7805 if (!myrpt
->remoterig
) return(0);
7806 if (!myrpt
->remoterig
[0]) return(0);
7807 /* must have rtx hardware */
7808 if (!ISRIG_RTX(myrpt
->remoterig
)) return(0);
7809 /* must be a usbradio interface type */
7810 if (!IS_XPMR(myrpt
)) return(0);
7811 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
7812 s
= strchr(tmp
,'.');
7813 /* if no decimal, is invalid */
7815 if(debug
)printf("setrtx() %s %s\n",myrpt
->name
,myrpt
->remoterig
);
7819 printf("@@@@ Frequency needs a decimal\n");
7823 if (strlen(tmp
) < 2){
7825 printf("@@@@ Bad MHz digits: %s\n", tmp
);
7831 printf("@@@@ Bad KHz digits: %s\n", s
);
7835 if ((s
[2] != '0') && (s
[2] != '5')){
7837 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
7841 band
= rbi_mhztoband(tmp
);
7844 printf("@@@@ Bad Band: %s\n", tmp
);
7848 rxpl
= rbi_pltocode(myrpt
->rxpl
);
7852 printf("@@@@ Bad RX PL: %s\n", myrpt
->rxpl
);
7856 txpl
= rbi_pltocode(myrpt
->txpl
);
7860 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
7864 switch(myrpt
->offset
)
7876 switch(myrpt
->powerlevel
)
7889 res
= setrtx_check(myrpt
);
7890 if (res
< 0) return res
;
7892 if (myrpt
->offset
== REM_MINUS
) ofac
= -1.0;
7893 if (myrpt
->offset
== REM_PLUS
) ofac
= 1.0;
7895 if (!strcmp(myrpt
->remoterig
,remote_rig_rtx450
))
7896 txfreq
= atof(myrpt
->freq
) + (ofac
* 5.0);
7898 txfreq
= atof(myrpt
->freq
) + (ofac
* 0.6);
7901 if (myrpt
->powerlevel
== REM_HIPWR
) pwr
= 'H';
7904 sprintf(rigstr
,"SETFREQ %s %f %s %s %c",myrpt
->freq
,txfreq
,
7905 (myrpt
->rxplon
) ? myrpt
->rxpl
: "0.0",
7906 (myrpt
->txplon
) ? myrpt
->txpl
: "0.0",pwr
);
7907 send_usb_txt(myrpt
,rigstr
);
7908 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
7915 sets current signaling code for xpmr routines
7916 under development for new radios.
7918 static int setxpmr(struct rpt
*myrpt
)
7923 /* must be a remote system */
7924 if (!myrpt
->remoterig
) return(0);
7925 if (!myrpt
->remoterig
[0]) return(0);
7926 /* must not have rtx hardware */
7927 if (ISRIG_RTX(myrpt
->remoterig
)) return(0);
7928 /* must be a usbradio interface type */
7929 if (!IS_XPMR(myrpt
)) return(0);
7931 if(debug
)printf("setxpmr() %s %s\n",myrpt
->name
,myrpt
->remoterig
);
7933 rxpl
= rbi_pltocode(myrpt
->rxpl
);
7937 printf("@@@@ Bad RX PL: %s\n", myrpt
->rxpl
);
7941 txpl
= rbi_pltocode(myrpt
->txpl
);
7944 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
7947 sprintf(rigstr
,"SETFREQ 0.0 0.0 %s %s L",
7948 (myrpt
->rxplon
) ? myrpt
->rxpl
: "0.0",
7949 (myrpt
->txplon
) ? myrpt
->txpl
: "0.0");
7950 send_usb_txt(myrpt
,rigstr
);
7955 static int setrbi_check(struct rpt
*myrpt
)
7957 char tmp
[MAXREMSTR
] = "",*s
;
7960 /* must be a remote system */
7961 if (!myrpt
->remote
) return(0);
7962 /* must have rbi hardware */
7963 if (strncmp(myrpt
->remoterig
,remote_rig_rbi
,3)) return(0);
7964 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
7965 s
= strchr(tmp
,'.');
7966 /* if no decimal, is invalid */
7970 printf("@@@@ Frequency needs a decimal\n");
7975 if (strlen(tmp
) < 2){
7977 printf("@@@@ Bad MHz digits: %s\n", tmp
);
7983 printf("@@@@ Bad KHz digits: %s\n", s
);
7987 if ((s
[2] != '0') && (s
[2] != '5')){
7989 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
7993 band
= rbi_mhztoband(tmp
);
7996 printf("@@@@ Bad Band: %s\n", tmp
);
8000 txpl
= rbi_pltocode(myrpt
->txpl
);
8004 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
8010 static int setrtx_check(struct rpt
*myrpt
)
8012 char tmp
[MAXREMSTR
] = "",*s
;
8015 /* must be a remote system */
8016 if (!myrpt
->remote
) return(0);
8017 /* must have rbi hardware */
8018 if (strncmp(myrpt
->remoterig
,remote_rig_rbi
,3)) return(0);
8019 strncpy(tmp
, myrpt
->freq
, sizeof(tmp
) - 1);
8020 s
= strchr(tmp
,'.');
8021 /* if no decimal, is invalid */
8025 printf("@@@@ Frequency needs a decimal\n");
8030 if (strlen(tmp
) < 2){
8032 printf("@@@@ Bad MHz digits: %s\n", tmp
);
8038 printf("@@@@ Bad KHz digits: %s\n", s
);
8042 if ((s
[2] != '0') && (s
[2] != '5')){
8044 printf("@@@@ KHz must end in 0 or 5: %c\n", s
[2]);
8048 band
= rbi_mhztoband(tmp
);
8051 printf("@@@@ Bad Band: %s\n", tmp
);
8055 txpl
= rbi_pltocode(myrpt
->txpl
);
8059 printf("@@@@ Bad TX PL: %s\n", myrpt
->txpl
);
8063 rxpl
= rbi_pltocode(myrpt
->rxpl
);
8067 printf("@@@@ Bad RX PL: %s\n", myrpt
->rxpl
);
8073 static int check_freq_kenwood(int m
, int d
, int *defmode
)
8075 int dflmd
= REM_MODE_FM
;
8077 if (m
== 144){ /* 2 meters */
8081 else if((m
>= 145) && (m
< 148)){
8084 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
8098 static int check_freq_tm271(int m
, int d
, int *defmode
)
8100 int dflmd
= REM_MODE_FM
;
8102 if (m
== 144){ /* 2 meters */
8106 else if((m
>= 145) && (m
< 148)){
8119 /* Check for valid rbi frequency */
8120 /* Hard coded limits now, configurable later, maybe? */
8122 static int check_freq_rbi(int m
, int d
, int *defmode
)
8124 int dflmd
= REM_MODE_FM
;
8126 if(m
== 50){ /* 6 meters */
8130 else if((m
>= 51) && ( m
< 54)){
8133 else if(m
== 144){ /* 2 meters */
8137 else if((m
>= 145) && (m
< 148)){
8140 else if((m
>= 222) && (m
< 225)){ /* 1.25 meters */
8143 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
8146 else if((m
>= 1240) && (m
< 1300)){ /* 23 centimeters */
8159 /* Check for valid rtx frequency */
8160 /* Hard coded limits now, configurable later, maybe? */
8162 static int check_freq_rtx(int m
, int d
, int *defmode
, struct rpt
*myrpt
)
8164 int dflmd
= REM_MODE_FM
;
8166 if (!strcmp(myrpt
->remoterig
,remote_rig_rtx150
))
8169 if(m
== 144){ /* 2 meters */
8173 else if((m
>= 145) && (m
< 148)){
8181 if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
8195 * Convert decimals of frequency to int
8198 static int decimals2int(char *fraction
)
8201 char len
= strlen(fraction
);
8202 int multiplier
= 100000;
8207 for( i
= 0 ; i
< len
; i
++, multiplier
/= 10)
8208 res
+= (fraction
[i
] - '0') * multiplier
;
8214 * Split frequency into mhz and decimals
8217 static int split_freq(char *mhz
, char *decimals
, char *freq
)
8219 char freq_copy
[MAXREMSTR
];
8222 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
8225 strncpy(mhz
, freq_copy
, MAXREMSTR
);
8226 strcpy(decimals
, "00000");
8227 strncpy(decimals
, decp
, strlen(decp
));
8237 * Split ctcss frequency into hertz and decimal
8240 static int split_ctcss_freq(char *hertz
, char *decimal
, char *freq
)
8242 char freq_copy
[MAXREMSTR
];
8245 decp
= strchr(strncpy(freq_copy
, freq
, MAXREMSTR
),'.');
8248 strncpy(hertz
, freq_copy
, MAXREMSTR
);
8249 strncpy(decimal
, decp
, strlen(decp
));
8250 decimal
[strlen(decp
)] = '\0';
8260 * FT-897 I/O handlers
8263 /* Check to see that the frequency is valid */
8264 /* Hard coded limits now, configurable later, maybe? */
8267 static int check_freq_ft897(int m
, int d
, int *defmode
)
8269 int dflmd
= REM_MODE_FM
;
8271 if(m
== 1){ /* 160 meters */
8272 dflmd
= REM_MODE_LSB
;
8276 else if(m
== 3){ /* 80 meters */
8277 dflmd
= REM_MODE_LSB
;
8281 else if(m
== 7){ /* 40 meters */
8282 dflmd
= REM_MODE_LSB
;
8286 else if(m
== 14){ /* 20 meters */
8287 dflmd
= REM_MODE_USB
;
8291 else if(m
== 18){ /* 17 meters */
8292 dflmd
= REM_MODE_USB
;
8293 if((d
< 6800) || (d
> 16800))
8296 else if(m
== 21){ /* 15 meters */
8297 dflmd
= REM_MODE_USB
;
8298 if((d
< 20000) || (d
> 45000))
8301 else if(m
== 24){ /* 12 meters */
8302 dflmd
= REM_MODE_USB
;
8303 if((d
< 89000) || (d
> 99000))
8306 else if(m
== 28){ /* 10 meters */
8307 dflmd
= REM_MODE_USB
;
8311 dflmd
= REM_MODE_FM
;
8313 dflmd
= REM_MODE_USB
;
8317 else if(m
== 50){ /* 6 meters */
8319 dflmd
= REM_MODE_FM
;
8321 dflmd
= REM_MODE_USB
;
8324 else if((m
>= 51) && ( m
< 54)){
8325 dflmd
= REM_MODE_FM
;
8327 else if(m
== 144){ /* 2 meters */
8329 dflmd
= REM_MODE_FM
;
8331 dflmd
= REM_MODE_USB
;
8333 else if((m
>= 145) && (m
< 148)){
8334 dflmd
= REM_MODE_FM
;
8336 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
8338 dflmd
= REM_MODE_USB
;
8340 dflmd
= REM_MODE_FM
;
8353 * Set a new frequency for the FT897
8356 static int set_freq_ft897(struct rpt
*myrpt
, char *newfreq
)
8358 unsigned char cmdstr
[5];
8360 char mhz
[MAXREMSTR
];
8361 char decimals
[MAXREMSTR
];
8365 printf("New frequency: %s\n",newfreq
);
8367 if(split_freq(mhz
, decimals
, newfreq
))
8373 /* The FT-897 likes packed BCD frequencies */
8375 cmdstr
[0] = ((m
/ 100) << 4) + ((m
% 100)/10); /* 100MHz 10Mhz */
8376 cmdstr
[1] = ((m
% 10) << 4) + (d
/ 10000); /* 1MHz 100KHz */
8377 cmdstr
[2] = (((d
% 10000)/1000) << 4) + ((d
% 1000)/ 100); /* 10KHz 1KHz */
8378 cmdstr
[3] = (((d
% 100)/10) << 4) + (d
% 10); /* 100Hz 10Hz */
8379 cmdstr
[4] = 0x01; /* command */
8381 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
8385 /* ft-897 simple commands */
8387 static int simple_command_ft897(struct rpt
*myrpt
, char command
)
8389 unsigned char cmdstr
[5];
8391 memset(cmdstr
, 0, 5);
8393 cmdstr
[4] = command
;
8395 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
8401 static int set_offset_ft897(struct rpt
*myrpt
, char offset
)
8403 unsigned char cmdstr
[5];
8405 memset(cmdstr
, 0, 5);
8426 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
8431 static int set_mode_ft897(struct rpt
*myrpt
, char newmode
)
8433 unsigned char cmdstr
[5];
8435 memset(cmdstr
, 0, 5);
8459 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
8462 /* Set tone encode and decode modes */
8464 static int set_ctcss_mode_ft897(struct rpt
*myrpt
, char txplon
, char rxplon
)
8466 unsigned char cmdstr
[5];
8468 memset(cmdstr
, 0, 5);
8470 if(rxplon
&& txplon
)
8471 cmdstr
[0] = 0x2A; /* Encode and Decode */
8472 else if (!rxplon
&& txplon
)
8473 cmdstr
[0] = 0x4A; /* Encode only */
8474 else if (rxplon
&& !txplon
)
8475 cmdstr
[0] = 0x3A; /* Encode only */
8477 cmdstr
[0] = 0x8A; /* OFF */
8481 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
8485 /* Set transmit and receive ctcss tone frequencies */
8487 static int set_ctcss_freq_ft897(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
8489 unsigned char cmdstr
[5];
8490 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
8493 memset(cmdstr
, 0, 5);
8495 if(split_ctcss_freq(hertz
, decimal
, txtone
))
8501 cmdstr
[0] = ((h
/ 100) << 4) + (h
% 100)/ 10;
8502 cmdstr
[1] = ((h
% 10) << 4) + (d
% 10);
8506 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
8512 cmdstr
[2] = ((h
/ 100) << 4) + (h
% 100)/ 10;
8513 cmdstr
[3] = ((h
% 10) << 4) + (d
% 10);
8517 return serial_remote_io(myrpt
, cmdstr
, 5, NULL
, 0, 0);
8522 static int set_ft897(struct rpt
*myrpt
)
8527 printf("@@@@ lock on\n");
8529 res
= simple_command_ft897(myrpt
, 0x00); /* LOCK on */
8532 printf("@@@@ ptt off\n");
8535 res
= simple_command_ft897(myrpt
, 0x88); /* PTT off */
8538 printf("Modulation mode\n");
8541 res
= set_mode_ft897(myrpt
, myrpt
->remmode
); /* Modulation mode */
8544 printf("Split off\n");
8547 simple_command_ft897(myrpt
, 0x82); /* Split off */
8550 printf("Frequency\n");
8553 res
= set_freq_ft897(myrpt
, myrpt
->freq
); /* Frequency */
8554 if((myrpt
->remmode
== REM_MODE_FM
)){
8558 res
= set_offset_ft897(myrpt
, myrpt
->offset
); /* Offset if FM */
8559 if((!res
)&&(myrpt
->rxplon
|| myrpt
->txplon
)){
8561 printf("CTCSS tone freqs.\n");
8562 res
= set_ctcss_freq_ft897(myrpt
, myrpt
->txpl
, myrpt
->rxpl
); /* CTCSS freqs if CTCSS is enabled */
8566 printf("CTCSS mode\n");
8567 res
= set_ctcss_mode_ft897(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
8570 if((myrpt
->remmode
== REM_MODE_USB
)||(myrpt
->remmode
== REM_MODE_LSB
)){
8572 printf("Clarifier off\n");
8573 simple_command_ft897(myrpt
, 0x85); /* Clarifier off if LSB or USB */
8578 static int closerem_ft897(struct rpt
*myrpt
)
8580 simple_command_ft897(myrpt
, 0x88); /* PTT off */
8585 * Bump frequency up or down by a small amount
8586 * Return 0 if the new frequnecy is valid, or -1 if invalid
8587 * Interval is in Hz, resolution is 10Hz
8590 static int multimode_bump_freq_ft897(struct rpt
*myrpt
, int interval
)
8593 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
8596 printf("Before bump: %s\n", myrpt
->freq
);
8598 if(split_freq(mhz
, decimals
, myrpt
->freq
))
8604 d
+= (interval
/ 10); /* 10Hz resolution */
8609 else if(d
>= 100000){
8614 if(check_freq_ft897(m
, d
, NULL
)){
8616 printf("Bump freq invalid\n");
8620 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
8623 printf("After bump: %s\n", myrpt
->freq
);
8625 return set_freq_ft897(myrpt
, myrpt
->freq
);
8631 * IC-706 I/O handlers
8634 /* Check to see that the frequency is valid */
8635 /* returns 0 if frequency is valid */
8637 static int check_freq_ic706(int m
, int d
, int *defmode
, char mars
)
8639 int dflmd
= REM_MODE_FM
;
8643 ast_log(LOG_NOTICE
,"(%i,%i,%i,%i)\n",m
,d
,*defmode
,mars
);
8645 /* first test for standard amateur radio bands */
8647 if(m
== 1){ /* 160 meters */
8648 dflmd
= REM_MODE_LSB
;
8651 else if(m
== 3){ /* 80 meters */
8652 dflmd
= REM_MODE_LSB
;
8655 else if(m
== 7){ /* 40 meters */
8656 dflmd
= REM_MODE_LSB
;
8659 else if(m
== 14){ /* 20 meters */
8660 dflmd
= REM_MODE_USB
;
8663 else if(m
== 18){ /* 17 meters */
8664 dflmd
= REM_MODE_USB
;
8665 if((d
< 6800) || (d
> 16800))rv
=-1;
8667 else if(m
== 21){ /* 15 meters */
8668 dflmd
= REM_MODE_USB
;
8669 if((d
< 20000) || (d
> 45000))rv
=-1;
8671 else if(m
== 24){ /* 12 meters */
8672 dflmd
= REM_MODE_USB
;
8673 if((d
< 89000) || (d
> 99000))rv
=-1;
8675 else if(m
== 28){ /* 10 meters */
8676 dflmd
= REM_MODE_USB
;
8680 dflmd
= REM_MODE_FM
;
8682 dflmd
= REM_MODE_USB
;
8685 else if(m
== 50){ /* 6 meters */
8687 dflmd
= REM_MODE_FM
;
8689 dflmd
= REM_MODE_USB
;
8691 else if((m
>= 51) && ( m
< 54)){
8692 dflmd
= REM_MODE_FM
;
8694 else if(m
== 144){ /* 2 meters */
8696 dflmd
= REM_MODE_FM
;
8698 dflmd
= REM_MODE_USB
;
8700 else if((m
>= 145) && (m
< 148)){
8701 dflmd
= REM_MODE_FM
;
8703 else if((m
>= 430) && (m
< 450)){ /* 70 centimeters */
8705 dflmd
= REM_MODE_USB
;
8707 dflmd
= REM_MODE_FM
;
8710 /* check expanded coverage */
8712 if((m
>= 450) && (m
< 470)){ /* LMR */
8713 dflmd
= REM_MODE_FM
;
8716 else if((m
>= 148) && (m
< 174)){ /* LMR */
8717 dflmd
= REM_MODE_FM
;
8720 else if((m
>= 138) && (m
< 144)){ /* VHF-AM AIRCRAFT */
8721 dflmd
= REM_MODE_AM
;
8724 else if((m
>= 108) && (m
< 138)){ /* VHF-AM AIRCRAFT */
8725 dflmd
= REM_MODE_AM
;
8728 else if( (m
==0 && d
>=55000) || (m
==1 && d
<=75000) ){ /* AM BCB*/
8729 dflmd
= REM_MODE_AM
;
8732 else if( (m
== 1 && d
>75000) || (m
>1 && m
<30) ){ /* HF SWL*/
8733 dflmd
= REM_MODE_AM
;
8742 ast_log(LOG_NOTICE
,"(%i,%i,%i,%i) returning %i\n",m
,d
,*defmode
,mars
,rv
);
8747 /* take a PL frequency and turn it into a code */
8748 static int ic706_pltocode(char *str
)
8754 s
= strchr(str
,'.');
8756 if (s
) i
= atoi(s
+ 1);
8757 i
+= atoi(str
) * 10;
8862 ast_log(LOG_NOTICE
,"%i rv=%i\n",i
, rv
);
8867 /* ic-706 simple commands */
8869 static int simple_command_ic706(struct rpt
*myrpt
, char command
, char subcommand
)
8871 unsigned char cmdstr
[10];
8873 cmdstr
[0] = cmdstr
[1] = 0xfe;
8874 cmdstr
[2] = myrpt
->p
.civaddr
;
8876 cmdstr
[4] = command
;
8877 cmdstr
[5] = subcommand
;
8880 return(civ_cmd(myrpt
,cmdstr
,7));
8884 * Set a new frequency for the ic706
8887 static int set_freq_ic706(struct rpt
*myrpt
, char *newfreq
)
8889 unsigned char cmdstr
[20];
8890 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
8895 ast_log(LOG_NOTICE
,"newfreq:%s\n",newfreq
);
8897 if(split_freq(mhz
, decimals
, newfreq
))
8903 /* The ic-706 likes packed BCD frequencies */
8905 cmdstr
[0] = cmdstr
[1] = 0xfe;
8906 cmdstr
[2] = myrpt
->p
.civaddr
;
8909 cmdstr
[5] = ((d
% 10) << 4);
8910 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
8911 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
8912 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
8913 cmdstr
[9] = (m
/ 100);
8916 return(civ_cmd(myrpt
,cmdstr
,11));
8921 static int set_offset_ic706(struct rpt
*myrpt
, char offset
)
8926 ast_log(LOG_NOTICE
,"offset=%i\n",offset
);
8945 return simple_command_ic706(myrpt
,0x0f,c
);
8951 static int set_mode_ic706(struct rpt
*myrpt
, char newmode
)
8956 ast_log(LOG_NOTICE
,"newmode=%i\n",newmode
);
8978 return simple_command_ic706(myrpt
,6,c
);
8981 /* Set tone encode and decode modes */
8983 static int set_ctcss_mode_ic706(struct rpt
*myrpt
, char txplon
, char rxplon
)
8985 unsigned char cmdstr
[10];
8989 ast_log(LOG_NOTICE
,"txplon=%i rxplon=%i \n",txplon
,rxplon
);
8991 cmdstr
[0] = cmdstr
[1] = 0xfe;
8992 cmdstr
[2] = myrpt
->p
.civaddr
;
8996 cmdstr
[6] = (txplon
!= 0);
8999 rv
= civ_cmd(myrpt
,cmdstr
,8);
9002 cmdstr
[0] = cmdstr
[1] = 0xfe;
9003 cmdstr
[2] = myrpt
->p
.civaddr
;
9007 cmdstr
[6] = (rxplon
!= 0);
9010 return(civ_cmd(myrpt
,cmdstr
,8));
9014 /* Set transmit and receive ctcss tone frequencies */
9016 static int set_ctcss_freq_ic706(struct rpt
*myrpt
, char *txtone
, char *rxtone
)
9018 unsigned char cmdstr
[10];
9019 char hertz
[MAXREMSTR
],decimal
[MAXREMSTR
];
9022 memset(cmdstr
, 0, 5);
9025 ast_log(LOG_NOTICE
,"txtone=%s rxtone=%s \n",txtone
,rxtone
);
9027 if(split_ctcss_freq(hertz
, decimal
, txtone
))
9033 cmdstr
[0] = cmdstr
[1] = 0xfe;
9034 cmdstr
[2] = myrpt
->p
.civaddr
;
9038 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
9039 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
9042 rv
= civ_cmd(myrpt
,cmdstr
,9);
9045 if (!rxtone
) return(0);
9047 if(split_ctcss_freq(hertz
, decimal
, rxtone
))
9053 cmdstr
[0] = cmdstr
[1] = 0xfe;
9054 cmdstr
[2] = myrpt
->p
.civaddr
;
9058 cmdstr
[6] = ((h
/ 100) << 4) + (h
% 100)/ 10;
9059 cmdstr
[7] = ((h
% 10) << 4) + (d
% 10);
9061 return(civ_cmd(myrpt
,cmdstr
,9));
9065 static int vfo_ic706(struct rpt
*myrpt
)
9067 unsigned char cmdstr
[10];
9069 cmdstr
[0] = cmdstr
[1] = 0xfe;
9070 cmdstr
[2] = myrpt
->p
.civaddr
;
9075 return(civ_cmd(myrpt
,cmdstr
,6));
9078 static int mem2vfo_ic706(struct rpt
*myrpt
)
9080 unsigned char cmdstr
[10];
9082 cmdstr
[0] = cmdstr
[1] = 0xfe;
9083 cmdstr
[2] = myrpt
->p
.civaddr
;
9088 return(civ_cmd(myrpt
,cmdstr
,6));
9091 static int select_mem_ic706(struct rpt
*myrpt
, int slot
)
9093 unsigned char cmdstr
[10];
9095 cmdstr
[0] = cmdstr
[1] = 0xfe;
9096 cmdstr
[2] = myrpt
->p
.civaddr
;
9100 cmdstr
[6] = ((slot
/ 10) << 4) + (slot
% 10);
9103 return(civ_cmd(myrpt
,cmdstr
,8));
9106 static int set_ic706(struct rpt
*myrpt
)
9110 if(debug
)ast_log(LOG_NOTICE
, "Set to VFO A iobase=%i\n",myrpt
->p
.iobase
);
9113 res
= simple_command_ic706(myrpt
,7,0);
9115 if((myrpt
->remmode
== REM_MODE_FM
))
9117 i
= ic706_pltocode(myrpt
->rxpl
);
9118 if (i
== -1) return -1;
9120 printf("Select memory number\n");
9122 res
= select_mem_ic706(myrpt
,i
+ IC706_PL_MEMORY_OFFSET
);
9124 printf("Transfer memory to VFO\n");
9126 res
= mem2vfo_ic706(myrpt
);
9130 printf("Set to VFO\n");
9133 res
= vfo_ic706(myrpt
);
9136 printf("Modulation mode\n");
9139 res
= set_mode_ic706(myrpt
, myrpt
->remmode
); /* Modulation mode */
9142 printf("Split off\n");
9145 simple_command_ic706(myrpt
, 0x82,0); /* Split off */
9148 printf("Frequency\n");
9151 res
= set_freq_ic706(myrpt
, myrpt
->freq
); /* Frequency */
9152 if((myrpt
->remmode
== REM_MODE_FM
)){
9156 res
= set_offset_ic706(myrpt
, myrpt
->offset
); /* Offset if FM */
9159 printf("CTCSS mode\n");
9160 res
= set_ctcss_mode_ic706(myrpt
, myrpt
->txplon
, myrpt
->rxplon
); /* CTCSS mode */
9167 * Bump frequency up or down by a small amount
9168 * Return 0 if the new frequnecy is valid, or -1 if invalid
9169 * Interval is in Hz, resolution is 10Hz
9172 static int multimode_bump_freq_ic706(struct rpt
*myrpt
, int interval
)
9175 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
9176 unsigned char cmdstr
[20];
9179 printf("Before bump: %s\n", myrpt
->freq
);
9181 if(split_freq(mhz
, decimals
, myrpt
->freq
))
9187 d
+= (interval
/ 10); /* 10Hz resolution */
9192 else if(d
>= 100000){
9197 if(check_freq_ic706(m
, d
, NULL
,myrpt
->p
.remote_mars
)){
9199 printf("Bump freq invalid\n");
9203 snprintf(myrpt
->freq
, MAXREMSTR
, "%d.%05d", m
, d
);
9206 printf("After bump: %s\n", myrpt
->freq
);
9208 /* The ic-706 likes packed BCD frequencies */
9210 cmdstr
[0] = cmdstr
[1] = 0xfe;
9211 cmdstr
[2] = myrpt
->p
.civaddr
;
9214 cmdstr
[5] = ((d
% 10) << 4);
9215 cmdstr
[6] = (((d
% 1000)/ 100) << 4) + ((d
% 100)/10);
9216 cmdstr
[7] = ((d
/ 10000) << 4) + ((d
% 10000)/1000);
9217 cmdstr
[8] = (((m
% 100)/10) << 4) + (m
% 10);
9218 cmdstr
[9] = (m
/ 100);
9221 return(serial_remote_io(myrpt
,cmdstr
,11,NULL
,0,0));
9227 * Dispatch to correct I/O handler
9229 static int setrem(struct rpt
*myrpt
)
9232 char *offsets
[] = {"SIMPLEX","MINUS","PLUS"};
9233 char *powerlevels
[] = {"LOW","MEDIUM","HIGH"};
9234 char *modes
[] = {"FM","USB","LSB","AM"};
9238 printf("FREQ,%s,%s,%s,%s,%s,%s,%d,%d\n",myrpt
->freq
,
9239 modes
[(int)myrpt
->remmode
],
9240 myrpt
->txpl
,myrpt
->rxpl
,offsets
[(int)myrpt
->offset
],
9241 powerlevels
[(int)myrpt
->powerlevel
],myrpt
->txplon
,
9244 if (myrpt
->p
.archivedir
)
9246 sprintf(str
,"FREQ,%s,%s,%s,%s,%s,%s,%d,%d",myrpt
->freq
,
9247 modes
[(int)myrpt
->remmode
],
9248 myrpt
->txpl
,myrpt
->rxpl
,offsets
[(int)myrpt
->offset
],
9249 powerlevels
[(int)myrpt
->powerlevel
],myrpt
->txplon
,
9251 donodelog(myrpt
,str
);
9253 if(!strcmp(myrpt
->remoterig
, remote_rig_ft897
))
9255 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
9258 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
9260 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
9263 if(!strcmp(myrpt
->remoterig
, remote_rig_tm271
))
9265 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
9268 else if(!strcmp(myrpt
->remoterig
, remote_rig_rbi
))
9270 res
= setrbi_check(myrpt
);
9273 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
9277 else if(ISRIG_RTX(myrpt
->remoterig
))
9282 else if(!strcmp(myrpt
->remoterig
, remote_rig_kenwood
)) {
9283 rpt_telemetry(myrpt
,SETREMOTE
,NULL
);
9289 if (res
< 0) ast_log(LOG_ERROR
,"Unable to send remote command on node %s\n",myrpt
->name
);
9294 static int closerem(struct rpt
*myrpt
)
9296 if(!strcmp(myrpt
->remoterig
, remote_rig_ft897
))
9297 return closerem_ft897(myrpt
);
9303 * Dispatch to correct RX frequency checker
9306 static int check_freq(struct rpt
*myrpt
, int m
, int d
, int *defmode
)
9308 if(!strcmp(myrpt
->remoterig
, remote_rig_ft897
))
9309 return check_freq_ft897(m
, d
, defmode
);
9310 else if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
9311 return check_freq_ic706(m
, d
, defmode
,myrpt
->p
.remote_mars
);
9312 else if(!strcmp(myrpt
->remoterig
, remote_rig_rbi
))
9313 return check_freq_rbi(m
, d
, defmode
);
9314 else if(!strcmp(myrpt
->remoterig
, remote_rig_kenwood
))
9315 return check_freq_kenwood(m
, d
, defmode
);
9316 else if(!strcmp(myrpt
->remoterig
, remote_rig_tm271
))
9317 return check_freq_tm271(m
, d
, defmode
);
9318 else if(ISRIG_RTX(myrpt
->remoterig
))
9319 return check_freq_rtx(m
, d
, defmode
, myrpt
);
9325 * Check TX frequency before transmitting
9326 rv=1 if tx frequency in ok.
9329 static char check_tx_freq(struct rpt
*myrpt
)
9332 int radio_mhz
, radio_decimals
, ulimit_mhz
, ulimit_decimals
, llimit_mhz
, llimit_decimals
;
9333 char radio_mhz_char
[MAXREMSTR
];
9334 char radio_decimals_char
[MAXREMSTR
];
9335 char limit_mhz_char
[MAXREMSTR
];
9336 char limit_decimals_char
[MAXREMSTR
];
9338 char *limit_ranges
[40];
9339 struct ast_variable
*limitlist
;
9342 ast_log(LOG_NOTICE
, "myrpt->freq = %s\n", myrpt
->freq
);
9345 /* Must have user logged in and tx_limits defined */
9347 if(!myrpt
->p
.txlimitsstanzaname
|| !myrpt
->loginuser
[0] || !myrpt
->loginlevel
[0]){
9349 ast_log(LOG_NOTICE
, "No tx band table defined, or no user logged in. rv=1\n");
9352 return 1; /* Assume it's ok otherwise */
9355 /* Retrieve the band table for the loginlevel */
9356 limitlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.txlimitsstanzaname
);
9359 ast_log(LOG_WARNING
, "No entries in %s band table stanza. rv=0\n", myrpt
->p
.txlimitsstanzaname
);
9364 split_freq(radio_mhz_char
, radio_decimals_char
, myrpt
->freq
);
9365 radio_mhz
= atoi(radio_mhz_char
);
9366 radio_decimals
= decimals2int(radio_decimals_char
);
9369 ast_log(LOG_NOTICE
, "Login User = %s, login level = %s\n", myrpt
->loginuser
, myrpt
->loginlevel
);
9372 /* Find our entry */
9374 for(;limitlist
; limitlist
=limitlist
->next
){
9375 if(!strcmp(limitlist
->name
, myrpt
->loginlevel
))
9380 ast_log(LOG_WARNING
, "Can't find %s entry in band table stanza %s. rv=0\n", myrpt
->loginlevel
, myrpt
->p
.txlimitsstanzaname
);
9386 ast_log(LOG_NOTICE
, "Auth: %s = %s\n", limitlist
->name
, limitlist
->value
);
9389 /* Parse the limits */
9391 strncpy(limits
, limitlist
->value
, 256);
9393 finddelim(limits
, limit_ranges
, 40);
9394 for(i
= 0; i
< 40 && limit_ranges
[i
] ; i
++){
9397 strncpy(range
, limit_ranges
[i
], 40);
9400 ast_log(LOG_NOTICE
, "Check %s within %s\n", myrpt
->freq
, range
);
9402 r
= strchr(range
, '-');
9404 ast_log(LOG_WARNING
, "Malformed range in %s tx band table entry. rv=0\n", limitlist
->name
);
9409 s
= eatwhite(range
);
9411 split_freq(limit_mhz_char
, limit_decimals_char
, s
);
9412 llimit_mhz
= atoi(limit_mhz_char
);
9413 llimit_decimals
= decimals2int(limit_decimals_char
);
9414 split_freq(limit_mhz_char
, limit_decimals_char
, r
);
9415 ulimit_mhz
= atoi(limit_mhz_char
);
9416 ulimit_decimals
= decimals2int(limit_decimals_char
);
9418 if((radio_mhz
>= llimit_mhz
) && (radio_mhz
<= ulimit_mhz
)){
9419 if(radio_mhz
== llimit_mhz
){ /* CASE 1: TX freq is in llimit mhz portion of band */
9420 if(radio_decimals
>= llimit_decimals
){ /* Cannot be below llimit decimals */
9421 if(llimit_mhz
== ulimit_mhz
){ /* If bandwidth < 1Mhz, check ulimit decimals */
9422 if(radio_decimals
<= ulimit_decimals
){
9428 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 1\n");
9438 else{ /* Is below llimit decimals */
9440 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 2\n");
9445 else if(radio_mhz
== ulimit_mhz
){ /* CASE 2: TX freq not in llimit mhz portion of band */
9446 if(radio_decimals
<= ulimit_decimals
){
9448 ast_log(LOG_NOTICE
, "radio_decimals <= ulimit_decimals\n");
9452 else{ /* Is above ulimit decimals */
9454 ast_log(LOG_NOTICE
, "Invalid TX frequency, debug msg 3\n");
9459 else /* CASE 3: TX freq within a multi-Mhz band and ok */
9461 ast_log(LOG_NOTICE
, "Valid TX freq within a multi-Mhz band and ok.\n");
9467 ast_log(LOG_NOTICE
, "rv=%i\n",rv
);
9474 * Dispatch to correct frequency bumping function
9477 static int multimode_bump_freq(struct rpt
*myrpt
, int interval
)
9479 if(!strcmp(myrpt
->remoterig
, remote_rig_ft897
))
9480 return multimode_bump_freq_ft897(myrpt
, interval
);
9481 else if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
9482 return multimode_bump_freq_ic706(myrpt
, interval
);
9489 * Queue announcment that scan has been stopped
9492 static void stop_scan(struct rpt
*myrpt
)
9494 myrpt
->hfscanstop
= 1;
9495 rpt_telemetry(myrpt
,SCAN
,0);
9499 * This is called periodically when in scan mode
9503 static int service_scan(struct rpt
*myrpt
)
9506 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
], k10
=0i
, k100
=0;
9508 switch(myrpt
->hfscanmode
){
9510 case HF_SCAN_DOWN_SLOW
:
9511 interval
= -10; /* 100Hz /sec */
9514 case HF_SCAN_DOWN_QUICK
:
9515 interval
= -50; /* 500Hz /sec */
9518 case HF_SCAN_DOWN_FAST
:
9519 interval
= -200; /* 2KHz /sec */
9522 case HF_SCAN_UP_SLOW
:
9523 interval
= 10; /* 100Hz /sec */
9526 case HF_SCAN_UP_QUICK
:
9527 interval
= 50; /* 500 Hz/sec */
9530 case HF_SCAN_UP_FAST
:
9531 interval
= 200; /* 2KHz /sec */
9535 myrpt
->hfscanmode
= 0; /* Huh? */
9539 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
9544 res
= multimode_bump_freq(myrpt
, interval
);
9548 res
= split_freq(mhz
, decimals
, myrpt
->freq
);
9552 myrpt
->hfscanmode
= 0;
9553 myrpt
->hfscanstatus
= -2;
9557 /* Announce 10KHz boundaries */
9558 if(k10
!= decimals
[1]){
9559 int myhund
= (interval
< 0) ? k100
: decimals
[0];
9560 int myten
= (interval
< 0) ? k10
: decimals
[1];
9561 myrpt
->hfscanstatus
= (myten
== '0') ? (myhund
- '0') * 100 : (myten
- '0') * 10;
9562 } else myrpt
->hfscanstatus
= 0;
9567 retrieve memory setting and set radio
9569 static int get_mem_set(struct rpt
*myrpt
, char *digitbuf
)
9572 if(debug
)ast_log(LOG_NOTICE
," digitbuf=%s\n", digitbuf
);
9573 res
= retreive_memory(myrpt
, digitbuf
);
9574 if(!res
)res
=setrem(myrpt
);
9575 if(debug
)ast_log(LOG_NOTICE
," freq=%s res=%i\n", myrpt
->freq
, res
);
9579 steer the radio selected channel to either one programmed into the radio
9580 or if the radio is VFO agile, to an rpt.conf memory location.
9582 static int channel_steer(struct rpt
*myrpt
, char *data
)
9586 if(debug
)ast_log(LOG_NOTICE
,"remoterig=%s, data=%s\n",myrpt
->remoterig
,data
);
9587 if (!myrpt
->remoterig
) return(0);
9594 myrpt
->nowchan
=strtod(data
,NULL
);
9595 if(!strcmp(myrpt
->remoterig
, remote_rig_ppp16
))
9598 sprintf(string
,"SETCHAN %d ",myrpt
->nowchan
);
9599 send_usb_txt(myrpt
,string
);
9603 if(get_mem_set(myrpt
, data
))res
=-1;
9606 if(debug
)ast_log(LOG_NOTICE
,"nowchan=%i res=%i\n",myrpt
->nowchan
, res
);
9611 static int channel_revert(struct rpt
*myrpt
)
9614 if(debug
)ast_log(LOG_NOTICE
,"remoterig=%s, nowchan=%02d, waschan=%02d\n",myrpt
->remoterig
,myrpt
->nowchan
,myrpt
->waschan
);
9615 if (!myrpt
->remoterig
) return(0);
9616 if(myrpt
->nowchan
!=myrpt
->waschan
)
9619 if(debug
)ast_log(LOG_NOTICE
,"reverting.\n");
9620 sprintf(data
,"%02d",myrpt
->waschan
);
9621 myrpt
->nowchan
=myrpt
->waschan
;
9622 channel_steer(myrpt
,data
);
9628 * Remote base function
9631 static int function_remote(struct rpt
*myrpt
, char *param
, char *digitbuf
, int command_source
, struct rpt_link
*mylink
)
9634 int i
,j
,p
,r
,ht
,k
,l
,ls2
,m
,d
,offset
,offsave
, modesave
, defmode
;
9636 char oc
,*cp
,*cp1
,*cp2
;
9637 char tmp
[20], freq
[20] = "", savestr
[20] = "";
9638 char mhz
[MAXREMSTR
], decimals
[MAXREMSTR
];
9641 ast_log(LOG_NOTICE
,"%s param=%s digitbuf=%s source=%i\n",myrpt
->name
,param
,digitbuf
,command_source
);
9644 if((!param
) || (command_source
== SOURCE_RPT
) || (command_source
== SOURCE_LNK
))
9649 if ((p
!= 99) && (p
!= 5) && (p
!= 140) && myrpt
->p
.authlevel
&&
9650 (!myrpt
->loginlevel
[0])) return DC_ERROR
;
9651 multimode
= multimode_capable(myrpt
);
9655 case 1: /* retrieve memory */
9656 if(strlen(digitbuf
) < 2) /* needs 2 digits */
9659 for(i
= 0 ; i
< 2 ; i
++){
9660 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
9663 r
=get_mem_set(myrpt
, digitbuf
);
9665 rpt_telemetry(myrpt
,MEMNOTFOUND
,NULL
);
9673 case 2: /* set freq and offset */
9676 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for M+*K+*O or M+*H+* depending on mode */
9677 if(digitbuf
[i
] == '*'){
9681 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
9685 l
++; /* # of digits before first * */
9687 k
++; /* # of digits after first * */
9691 i
= strlen(digitbuf
) - 1;
9693 if((j
> 2) || (l
> 3) || (k
> 6))
9694 goto invalid_freq
; /* &^@#! */
9697 if((j
> 2) || (l
> 4) || (k
> 3))
9698 goto invalid_freq
; /* &^@#! */
9701 /* Wait for M+*K+* */
9704 break; /* Not yet */
9706 /* We have a frequency */
9708 strncpy(tmp
, digitbuf
,sizeof(tmp
) - 1);
9711 s1
= strsep(&s
, "*"); /* Pick off MHz */
9712 s2
= strsep(&s
,"*"); /* Pick off KHz and Hz */
9715 switch(ls2
){ /* Allow partial entry of khz and hz digits for laziness support */
9728 if((s2
[2] != '0')&&(s2
[2] != '5'))
9736 ht
= 10 * (atoi(s2
+(ls2
-1)));
9741 ht
= (atoi(s2
+(ls2
-2)));
9748 /* Check frequency for validity and establish a default mode */
9750 snprintf(freq
, sizeof(freq
), "%s.%03d%02d",s1
, k
, ht
);
9753 ast_log(LOG_NOTICE
, "New frequency: %s\n", freq
);
9755 split_freq(mhz
, decimals
, freq
);
9759 if(check_freq(myrpt
, m
, d
, &defmode
)) /* Check to see if frequency entered is legit */
9763 if((defmode
== REM_MODE_FM
) && (digitbuf
[i
] == '*')) /* If FM, user must enter and additional offset digit */
9764 break; /* Not yet */
9767 offset
= REM_SIMPLEX
; /* Assume simplex */
9769 if(defmode
== REM_MODE_FM
){
9770 oc
= *s
; /* Pick off offset */
9779 offset
= REM_SIMPLEX
;
9791 offsave
= myrpt
->offset
;
9792 modesave
= myrpt
->remmode
;
9793 strncpy(savestr
, myrpt
->freq
, sizeof(savestr
) - 1);
9794 strncpy(myrpt
->freq
, freq
, sizeof(myrpt
->freq
) - 1);
9795 myrpt
->offset
= offset
;
9796 myrpt
->remmode
= defmode
;
9798 if (setrem(myrpt
) == -1){
9799 myrpt
->offset
= offsave
;
9800 myrpt
->remmode
= modesave
;
9801 strncpy(myrpt
->freq
, savestr
, sizeof(myrpt
->freq
) - 1);
9808 rpt_telemetry(myrpt
,INVFREQ
,NULL
);
9811 case 3: /* set rx PL tone */
9812 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
9813 if(digitbuf
[i
] == '*'){
9817 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
9826 if((j
> 1) || (k
> 3) || (l
> 1))
9827 return DC_ERROR
; /* &$@^! */
9828 i
= strlen(digitbuf
) - 1;
9829 if((j
!= 1) || (k
< 2)|| (l
!= 1))
9830 break; /* Not yet */
9832 printf("PL digits entered %s\n", digitbuf
);
9834 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
9835 /* see if we have at least 1 */
9836 s
= strchr(tmp
,'*');
9839 strncpy(savestr
, myrpt
->rxpl
, sizeof(savestr
) - 1);
9840 strncpy(myrpt
->rxpl
, tmp
, sizeof(myrpt
->rxpl
) - 1);
9841 if(!strcmp(myrpt
->remoterig
, remote_rig_rbi
))
9843 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
9845 if (setrem(myrpt
) == -1){
9846 strncpy(myrpt
->rxpl
, savestr
, sizeof(myrpt
->rxpl
) - 1);
9851 case 4: /* set tx PL tone */
9852 /* cant set tx tone on RBI (rx tone does both) */
9853 if(!strcmp(myrpt
->remoterig
, remote_rig_rbi
))
9855 /* eventually for the ic706 instead of just throwing the exception
9856 we can check if we are in encode only mode and allow the tx
9857 ctcss code to be changed. but at least the warning message is
9860 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
9863 ast_log(LOG_WARNING
,"Setting IC706 Tx CTCSS Code Not Supported. Set Rx Code for both.\n");
9866 for(i
= 0, j
= 0, k
= 0, l
= 0 ; digitbuf
[i
] ; i
++){ /* look for N+*N */
9867 if(digitbuf
[i
] == '*'){
9871 if((digitbuf
[i
] < '0') || (digitbuf
[i
] > '9'))
9880 if((j
> 1) || (k
> 3) || (l
> 1))
9881 return DC_ERROR
; /* &$@^! */
9882 i
= strlen(digitbuf
) - 1;
9883 if((j
!= 1) || (k
< 2)|| (l
!= 1))
9884 break; /* Not yet */
9886 printf("PL digits entered %s\n", digitbuf
);
9888 strncpy(tmp
, digitbuf
, sizeof(tmp
) - 1);
9889 /* see if we have at least 1 */
9890 s
= strchr(tmp
,'*');
9893 strncpy(savestr
, myrpt
->txpl
, sizeof(savestr
) - 1);
9894 strncpy(myrpt
->txpl
, tmp
, sizeof(myrpt
->txpl
) - 1);
9896 if (setrem(myrpt
) == -1){
9897 strncpy(myrpt
->txpl
, savestr
, sizeof(myrpt
->txpl
) - 1);
9903 case 6: /* MODE (FM,USB,LSB,AM) */
9904 if(strlen(digitbuf
) < 1)
9908 return DC_ERROR
; /* Multimode radios only */
9912 split_freq(mhz
, decimals
, myrpt
->freq
);
9914 if(m
< 29) /* No FM allowed below 29MHz! */
9916 myrpt
->remmode
= REM_MODE_FM
;
9918 rpt_telemetry(myrpt
,REMMODE
,NULL
);
9922 myrpt
->remmode
= REM_MODE_USB
;
9923 rpt_telemetry(myrpt
,REMMODE
,NULL
);
9927 myrpt
->remmode
= REM_MODE_LSB
;
9928 rpt_telemetry(myrpt
,REMMODE
,NULL
);
9932 myrpt
->remmode
= REM_MODE_AM
;
9933 rpt_telemetry(myrpt
,REMMODE
,NULL
);
9942 return DC_COMPLETEQUIET
;
9944 /* cant log in when logged in */
9945 if (myrpt
->loginlevel
[0])
9947 *myrpt
->loginuser
= 0;
9948 myrpt
->loginlevel
[0] = 0;
9949 cp
= ast_strdup(param
);
9950 cp1
= strchr(cp
,',');
9951 ast_mutex_lock(&myrpt
->lock
);
9955 cp2
= strchr(cp1
+ 1,',');
9959 strncpy(myrpt
->loginlevel
,cp2
+ 1,
9960 sizeof(myrpt
->loginlevel
) - 1);
9962 strncpy(myrpt
->loginuser
,cp1
+ 1,sizeof(myrpt
->loginuser
));
9963 ast_mutex_unlock(&myrpt
->lock
);
9964 if (myrpt
->p
.archivedir
)
9968 sprintf(str
,"LOGIN,%s,%s",
9969 myrpt
->loginuser
,myrpt
->loginlevel
);
9970 donodelog(myrpt
,str
);
9973 printf("loginuser %s level %s\n",myrpt
->loginuser
,myrpt
->loginlevel
);
9974 rpt_telemetry(myrpt
,REMLOGIN
,NULL
);
9977 return DC_COMPLETEQUIET
;
9978 case 100: /* RX PL Off */
9981 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
9982 return DC_COMPLETEQUIET
;
9983 case 101: /* RX PL On */
9986 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
9987 return DC_COMPLETEQUIET
;
9988 case 102: /* TX PL Off */
9991 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
9992 return DC_COMPLETEQUIET
;
9993 case 103: /* TX PL On */
9996 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
9997 return DC_COMPLETEQUIET
;
9998 case 104: /* Low Power */
9999 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
10001 myrpt
->powerlevel
= REM_LOWPWR
;
10003 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10004 return DC_COMPLETEQUIET
;
10005 case 105: /* Medium Power */
10006 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
10008 if (ISRIG_RTX(myrpt
->remoterig
)) return DC_ERROR
;
10009 myrpt
->powerlevel
= REM_MEDPWR
;
10011 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10012 return DC_COMPLETEQUIET
;
10013 case 106: /* Hi Power */
10014 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
10016 myrpt
->powerlevel
= REM_HIPWR
;
10018 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10019 return DC_COMPLETEQUIET
;
10020 case 107: /* Bump down 20Hz */
10021 multimode_bump_freq(myrpt
, -20);
10022 return DC_COMPLETE
;
10023 case 108: /* Bump down 100Hz */
10024 multimode_bump_freq(myrpt
, -100);
10025 return DC_COMPLETE
;
10026 case 109: /* Bump down 500Hz */
10027 multimode_bump_freq(myrpt
, -500);
10028 return DC_COMPLETE
;
10029 case 110: /* Bump up 20Hz */
10030 multimode_bump_freq(myrpt
, 20);
10031 return DC_COMPLETE
;
10032 case 111: /* Bump up 100Hz */
10033 multimode_bump_freq(myrpt
, 100);
10034 return DC_COMPLETE
;
10035 case 112: /* Bump up 500Hz */
10036 multimode_bump_freq(myrpt
, 500);
10037 return DC_COMPLETE
;
10038 case 113: /* Scan down slow */
10039 myrpt
->scantimer
= REM_SCANTIME
;
10040 myrpt
->hfscanmode
= HF_SCAN_DOWN_SLOW
;
10041 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10042 return DC_COMPLETEQUIET
;
10043 case 114: /* Scan down quick */
10044 myrpt
->scantimer
= REM_SCANTIME
;
10045 myrpt
->hfscanmode
= HF_SCAN_DOWN_QUICK
;
10046 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10047 return DC_COMPLETEQUIET
;
10048 case 115: /* Scan down fast */
10049 myrpt
->scantimer
= REM_SCANTIME
;
10050 myrpt
->hfscanmode
= HF_SCAN_DOWN_FAST
;
10051 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10052 return DC_COMPLETEQUIET
;
10053 case 116: /* Scan up slow */
10054 myrpt
->scantimer
= REM_SCANTIME
;
10055 myrpt
->hfscanmode
= HF_SCAN_UP_SLOW
;
10056 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10057 return DC_COMPLETEQUIET
;
10058 case 117: /* Scan up quick */
10059 myrpt
->scantimer
= REM_SCANTIME
;
10060 myrpt
->hfscanmode
= HF_SCAN_UP_QUICK
;
10061 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10062 return DC_COMPLETEQUIET
;
10063 case 118: /* Scan up fast */
10064 myrpt
->scantimer
= REM_SCANTIME
;
10065 myrpt
->hfscanmode
= HF_SCAN_UP_FAST
;
10066 rpt_telemetry(myrpt
,REMXXX
,(void *)p
);
10067 return DC_COMPLETEQUIET
;
10068 case 119: /* Tune Request */
10070 ast_log(LOG_NOTICE
,"TUNE REQUEST\n");
10071 /* if not currently going, and valid to do */
10072 if((!myrpt
->tunerequest
) &&
10073 ((!strcmp(myrpt
->remoterig
, remote_rig_ft897
) ||
10074 !strcmp(myrpt
->remoterig
, remote_rig_ic706
)) )) {
10075 myrpt
->remotetx
= 0;
10076 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
10077 myrpt
->tunerequest
= 1;
10078 rpt_telemetry(myrpt
,TUNE
,NULL
);
10079 return DC_COMPLETEQUIET
;
10082 case 5: /* Long Status */
10083 rpt_telemetry(myrpt
,REMLONGSTATUS
,NULL
);
10084 return DC_COMPLETEQUIET
;
10085 case 140: /* Short Status */
10086 rpt_telemetry(myrpt
,REMSHORTSTATUS
,NULL
);
10087 return DC_COMPLETEQUIET
;
10104 do_dtmf_local(myrpt
,remdtmfstr
[p
- 200]);
10105 return DC_COMPLETEQUIET
;
10109 return DC_INDETERMINATE
;
10113 static int handle_remote_dtmf_digit(struct rpt
*myrpt
,char c
, char *keyed
, int phonemode
)
10116 int ret
,res
= 0,src
;
10119 ast_log(LOG_NOTICE
,"c=%c phonemode=%i dtmfidx=%i\n",c
,phonemode
,myrpt
->dtmfidx
);
10121 time(&myrpt
->last_activity_time
);
10122 /* Stop scan mode if in scan mode */
10123 if(myrpt
->hfscanmode
){
10130 if ((myrpt
->dtmf_time_rem
+ DTMF_TIMEOUT
) < now
)
10132 myrpt
->dtmfidx
= -1;
10133 myrpt
->dtmfbuf
[0] = 0;
10134 myrpt
->dtmf_time_rem
= 0;
10136 /* if decode not active */
10137 if (myrpt
->dtmfidx
== -1)
10139 /* if not lead-in digit, dont worry */
10140 if (c
!= myrpt
->p
.funcchar
)
10142 if (!myrpt
->p
.propagate_dtmf
)
10144 rpt_mutex_lock(&myrpt
->lock
);
10145 do_dtmf_local(myrpt
,c
);
10146 rpt_mutex_unlock(&myrpt
->lock
);
10150 myrpt
->dtmfidx
= 0;
10151 myrpt
->dtmfbuf
[0] = 0;
10152 myrpt
->dtmf_time_rem
= now
;
10155 /* if too many in buffer, start over */
10156 if (myrpt
->dtmfidx
>= MAXDTMF
)
10158 myrpt
->dtmfidx
= 0;
10159 myrpt
->dtmfbuf
[0] = 0;
10160 myrpt
->dtmf_time_rem
= now
;
10162 if (c
== myrpt
->p
.funcchar
)
10164 /* if star at beginning, or 2 together, erase buffer */
10165 if ((myrpt
->dtmfidx
< 1) ||
10166 (myrpt
->dtmfbuf
[myrpt
->dtmfidx
- 1] == myrpt
->p
.funcchar
))
10168 myrpt
->dtmfidx
= 0;
10169 myrpt
->dtmfbuf
[0] = 0;
10170 myrpt
->dtmf_time_rem
= now
;
10174 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
10175 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
10176 myrpt
->dtmf_time_rem
= now
;
10180 if (phonemode
== 2) src
= SOURCE_DPHONE
;
10181 else if (phonemode
) src
= SOURCE_PHONE
;
10182 else if (phonemode
== 4) src
= SOURCE_ALT
;
10183 ret
= collect_function_digits(myrpt
, myrpt
->dtmfbuf
, src
, NULL
);
10187 case DC_INDETERMINATE
:
10192 if (keyed
) *keyed
= 1;
10197 myrpt
->dtmfidx
= 0;
10198 myrpt
->dtmfbuf
[0] = 0;
10205 case DC_COMPLETEQUIET
:
10206 myrpt
->totalexecdcommands
++;
10207 myrpt
->dailyexecdcommands
++;
10208 strncpy(myrpt
->lastdtmfcommand
, myrpt
->dtmfbuf
, MAXDTMF
-1);
10209 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
10210 myrpt
->dtmfbuf
[0] = 0;
10211 myrpt
->dtmfidx
= -1;
10212 myrpt
->dtmf_time_rem
= 0;
10217 myrpt
->dtmfbuf
[0] = 0;
10218 myrpt
->dtmfidx
= -1;
10219 myrpt
->dtmf_time_rem
= 0;
10227 static int handle_remote_data(struct rpt
*myrpt
, char *str
)
10229 char tmp
[300],cmd
[300],dest
[300],src
[300],c
;
10232 /* put string in our buffer */
10233 strncpy(tmp
,str
,sizeof(tmp
) - 1);
10234 if (!strcmp(tmp
,discstr
)) return 0;
10235 if (!strcmp(tmp
,newkeystr
))
10241 #ifndef DO_NOT_NOTIFY_MDC1200_ON_REMOTE_BASES
10244 if (sscanf(tmp
,"%s %s %x",cmd
,src
,&seq
) != 3)
10246 ast_log(LOG_WARNING
, "Unable to parse ident string %s\n",str
);
10249 mdc1200_notify(myrpt
,src
,seq
);
10253 if (sscanf(tmp
,"%s %s %s %d %c",cmd
,dest
,src
,&seq
,&c
) != 5)
10255 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
10258 if (strcmp(cmd
,"D"))
10260 ast_log(LOG_WARNING
, "Unable to parse link string %s\n",str
);
10263 /* if not for me, ignore */
10264 if (strcmp(dest
,myrpt
->name
)) return 0;
10265 if (myrpt
->p
.archivedir
)
10269 sprintf(str
,"DTMF,%c",c
);
10270 donodelog(myrpt
,str
);
10272 c
= func_xlat(myrpt
,c
,&myrpt
->p
.outxlat
);
10274 res
= handle_remote_dtmf_digit(myrpt
,c
, NULL
, 0);
10277 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
10281 static int handle_remote_phone_dtmf(struct rpt
*myrpt
, char c
, char *keyed
, int phonemode
)
10286 if(phonemode
== 3) /* simplex phonemode, funcchar key/unkey toggle */
10288 if (keyed
&& *keyed
&& ((c
== myrpt
->p
.funcchar
) || (c
== myrpt
->p
.endchar
)))
10290 *keyed
= 0; /* UNKEY */
10293 else if (keyed
&& !*keyed
&& (c
= myrpt
->p
.funcchar
))
10295 *keyed
= 1; /* KEY */
10299 else /* endchar unkey */
10302 if (keyed
&& *keyed
&& (c
== myrpt
->p
.endchar
))
10305 return DC_INDETERMINATE
;
10308 if (myrpt
->p
.archivedir
)
10312 sprintf(str
,"DTMF(P),%c",c
);
10313 donodelog(myrpt
,str
);
10315 res
= handle_remote_dtmf_digit(myrpt
,c
,keyed
, phonemode
);
10318 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
10322 static int attempt_reconnect(struct rpt
*myrpt
, struct rpt_link
*l
)
10324 char *val
, *s
, *s1
, *s2
, *tele
;
10325 char tmp
[300], deststr
[300] = "";
10329 val
= node_lookup(myrpt
,l
->name
);
10332 fprintf(stderr
,"attempt_reconnect: cannot find node %s\n",l
->name
);
10336 rpt_mutex_lock(&myrpt
->lock
);
10337 /* remove from queue */
10338 remque((struct qelem
*) l
);
10339 rpt_mutex_unlock(&myrpt
->lock
);
10340 strncpy(tmp
,val
,sizeof(tmp
) - 1);
10342 s1
= strsep(&s
,",");
10343 if (!strchr(s1
,':') && strchr(s1
,'/') && strncasecmp(s1
, "local/", 6))
10345 sy
= strchr(s1
,'/');
10347 sprintf(sx
,"%s:4569/%s",s1
,sy
+ 1);
10350 s2
= strsep(&s
,",");
10351 snprintf(deststr
, sizeof(deststr
), "IAX2/%s", s1
);
10352 tele
= strchr(deststr
, '/');
10354 fprintf(stderr
,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr
);
10359 l
->connecttime
= 0;
10360 l
->thisconnected
= 0;
10362 l
->chan
= ast_request(deststr
, AST_FORMAT_SLINEAR
, tele
,NULL
);
10364 ast_set_read_format(l
->chan
, AST_FORMAT_SLINEAR
);
10365 ast_set_write_format(l
->chan
, AST_FORMAT_SLINEAR
);
10366 #ifndef NEW_ASTERISK
10367 l
->chan
->whentohangup
= 0;
10369 l
->chan
->appl
= "Apprpt";
10370 l
->chan
->data
= "(Remote Rx)";
10371 if (option_verbose
> 2)
10372 ast_verbose(VERBOSE_PREFIX_3
"rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
10373 deststr
, tele
, l
->chan
->name
);
10374 if(l
->chan
->cid
.cid_num
)
10375 ast_free(l
->chan
->cid
.cid_num
);
10376 l
->chan
->cid
.cid_num
= ast_strdup(myrpt
->name
);
10377 ast_call(l
->chan
,tele
,999);
10382 if (option_verbose
> 2)
10383 ast_verbose(VERBOSE_PREFIX_3
"Unable to place call to %s/%s on %s\n",
10384 deststr
,tele
,l
->chan
->name
);
10387 rpt_mutex_lock(&myrpt
->lock
);
10388 /* put back in queue */
10389 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
10390 rpt_mutex_unlock(&myrpt
->lock
);
10391 ast_log(LOG_WARNING
,"Reconnect Attempt to %s in process\n",l
->name
);
10392 if (!l
->phonemode
) send_newkey(l
->chan
);
10396 /* 0 return=continue, 1 return = break, -1 return = error */
10397 static void local_dtmf_helper(struct rpt
*myrpt
,char c_in
)
10400 pthread_attr_t attr
;
10401 char cmd
[MAXDTMF
+1] = "",c
;
10405 if (myrpt
->p
.archivedir
)
10409 sprintf(str
,"DTMF,MAIN,%c",c
);
10410 donodelog(myrpt
,str
);
10412 if (c
== myrpt
->p
.endchar
)
10414 /* if in simple mode, kill autopatch */
10415 if (myrpt
->p
.simple
&& myrpt
->callmode
)
10418 ast_log(LOG_WARNING
, "simple mode autopatch kill\n");
10419 rpt_mutex_lock(&myrpt
->lock
);
10420 myrpt
->callmode
= 0;
10421 myrpt
->macropatch
=0;
10422 channel_revert(myrpt
);
10423 rpt_mutex_unlock(&myrpt
->lock
);
10424 rpt_telemetry(myrpt
,TERM
,NULL
);
10427 rpt_mutex_lock(&myrpt
->lock
);
10428 myrpt
->stopgen
= 1;
10429 if (myrpt
->cmdnode
[0])
10431 myrpt
->cmdnode
[0] = 0;
10432 myrpt
->dtmfidx
= -1;
10433 myrpt
->dtmfbuf
[0] = 0;
10434 rpt_mutex_unlock(&myrpt
->lock
);
10435 rpt_telemetry(myrpt
,COMPLETE
,NULL
);
10438 else if(!myrpt
->inpadtest
)
10440 rpt_mutex_unlock(&myrpt
->lock
);
10441 if (myrpt
->p
.propagate_phonedtmf
)
10442 do_dtmf_phone(myrpt
,NULL
,c
);
10446 rpt_mutex_unlock(&myrpt
->lock
);
10448 rpt_mutex_lock(&myrpt
->lock
);
10449 if (myrpt
->cmdnode
[0])
10451 rpt_mutex_unlock(&myrpt
->lock
);
10452 send_link_dtmf(myrpt
,c
);
10455 if (!myrpt
->p
.simple
)
10457 if ((!myrpt
->inpadtest
)&&(c
== myrpt
->p
.funcchar
))
10459 myrpt
->dtmfidx
= 0;
10460 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
10461 rpt_mutex_unlock(&myrpt
->lock
);
10462 time(&myrpt
->dtmf_time
);
10465 else if (((myrpt
->inpadtest
)||(c
!= myrpt
->p
.endchar
)) && (myrpt
->dtmfidx
>= 0))
10467 time(&myrpt
->dtmf_time
);
10469 if (myrpt
->dtmfidx
< MAXDTMF
)
10473 myrpt
->dtmfbuf
[myrpt
->dtmfidx
++] = c
;
10474 myrpt
->dtmfbuf
[myrpt
->dtmfidx
] = 0;
10476 strncpy(cmd
, myrpt
->dtmfbuf
, sizeof(cmd
) - 1);
10478 rpt_mutex_unlock(&myrpt
->lock
);
10480 if (c_in
& 0x80) src
= SOURCE_ALT
;
10481 res
= collect_function_digits(myrpt
, cmd
, src
, NULL
);
10482 rpt_mutex_lock(&myrpt
->lock
);
10484 case DC_INDETERMINATE
:
10487 myrpt
->dtmfidx
= 0;
10488 myrpt
->dtmfbuf
[0] = 0;
10491 case DC_COMPLETEQUIET
:
10492 myrpt
->totalexecdcommands
++;
10493 myrpt
->dailyexecdcommands
++;
10494 strncpy(myrpt
->lastdtmfcommand
, cmd
, MAXDTMF
-1);
10495 myrpt
->lastdtmfcommand
[MAXDTMF
-1] = '\0';
10496 myrpt
->dtmfbuf
[0] = 0;
10497 myrpt
->dtmfidx
= -1;
10498 myrpt
->dtmf_time
= 0;
10503 myrpt
->dtmfbuf
[0] = 0;
10504 myrpt
->dtmfidx
= -1;
10505 myrpt
->dtmf_time
= 0;
10508 if(res
!= DC_INDETERMINATE
) {
10509 rpt_mutex_unlock(&myrpt
->lock
);
10515 else /* if simple */
10517 if ((!myrpt
->callmode
) && (c
== myrpt
->p
.funcchar
))
10519 myrpt
->callmode
= 1;
10520 myrpt
->patchnoct
= 0;
10521 myrpt
->patchquiet
= 0;
10522 myrpt
->patchfarenddisconnect
= 0;
10523 myrpt
->patchdialtime
= 0;
10524 strncpy(myrpt
->patchcontext
, myrpt
->p
.ourcontext
, MAXPATCHCONTEXT
);
10526 myrpt
->exten
[myrpt
->cidx
] = 0;
10527 rpt_mutex_unlock(&myrpt
->lock
);
10528 pthread_attr_init(&attr
);
10529 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
10530 ast_pthread_create(&myrpt
->rpt_call_thread
,&attr
,rpt_call
,(void *)myrpt
);
10534 if (myrpt
->callmode
== 1)
10536 myrpt
->exten
[myrpt
->cidx
++] = c
;
10537 myrpt
->exten
[myrpt
->cidx
] = 0;
10538 /* if this exists */
10539 if (ast_exists_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
10541 /* if this really it, end now */
10542 if (!ast_matchmore_extension(myrpt
->pchannel
,myrpt
->patchcontext
,
10543 myrpt
->exten
,1,NULL
))
10545 myrpt
->callmode
= 2;
10546 rpt_mutex_unlock(&myrpt
->lock
);
10547 if(!myrpt
->patchquiet
)
10548 rpt_telemetry(myrpt
,PROC
,NULL
);
10551 else /* othewise, reset timer */
10553 myrpt
->calldigittimer
= 1;
10556 /* if can continue, do so */
10557 if (!ast_canmatch_extension(myrpt
->pchannel
,myrpt
->patchcontext
,myrpt
->exten
,1,NULL
))
10559 /* call has failed, inform user */
10560 myrpt
->callmode
= 4;
10562 rpt_mutex_unlock(&myrpt
->lock
);
10565 if ((myrpt
->callmode
== 2) || (myrpt
->callmode
== 3))
10569 rpt_mutex_unlock(&myrpt
->lock
);
10570 if ((myrpt
->dtmfidx
< 0) && myrpt
->p
.propagate_phonedtmf
)
10571 do_dtmf_phone(myrpt
,NULL
,c
);
10576 /* place an ID event in the telemetry queue */
10578 static void queue_id(struct rpt
*myrpt
)
10580 if(myrpt
->p
.idtime
){ /* ID time must be non-zero */
10581 myrpt
->mustid
= myrpt
->tailid
= 0;
10582 myrpt
->idtimer
= myrpt
->p
.idtime
; /* Reset our ID timer */
10583 rpt_mutex_unlock(&myrpt
->lock
);
10584 rpt_telemetry(myrpt
,ID
,NULL
);
10585 rpt_mutex_lock(&myrpt
->lock
);
10590 /* must be called locked */
10592 static void do_scheduler(struct rpt
*myrpt
)
10596 #ifdef NEW_ASTERISK
10597 struct ast_tm tmnow
;
10601 struct ast_variable
*skedlist
;
10602 char *strs
[5],*vp
,*val
,value
[100];
10604 memcpy(&myrpt
->lasttv
, &myrpt
->curtv
, sizeof(struct timeval
));
10606 if( (res
= gettimeofday(&myrpt
->curtv
, NULL
)) < 0)
10607 ast_log(LOG_NOTICE
, "Scheduler gettime of day returned: %s\n", strerror(res
));
10609 /* Try to get close to a 1 second resolution */
10611 if(myrpt
->lasttv
.tv_sec
== myrpt
->curtv
.tv_sec
)
10614 rpt_localtime(&myrpt
->curtv
.tv_sec
, &tmnow
);
10616 /* If midnight, then reset all daily statistics */
10618 if((tmnow
.tm_hour
== 0)&&(tmnow
.tm_min
== 0)&&(tmnow
.tm_sec
== 0)){
10619 myrpt
->dailykeyups
= 0;
10620 myrpt
->dailytxtime
= 0;
10621 myrpt
->dailykerchunks
= 0;
10622 myrpt
->dailyexecdcommands
= 0;
10625 if(tmnow
.tm_sec
!= 0)
10628 /* Code below only executes once per minute */
10631 /* Don't schedule if remote */
10636 /* Don't schedule if disabled */
10638 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
){
10640 ast_log(LOG_NOTICE
, "Scheduler disabled\n");
10644 if(!myrpt
->p
.skedstanzaname
){ /* No stanza means we do nothing */
10646 ast_log(LOG_NOTICE
,"No stanza for scheduler in rpt.conf\n");
10650 /* get pointer to linked list of scheduler entries */
10651 skedlist
= ast_variable_browse(myrpt
->cfg
, myrpt
->p
.skedstanzaname
);
10654 ast_log(LOG_NOTICE
, "Time now: %02d:%02d %02d %02d %02d\n",
10655 tmnow
.tm_hour
,tmnow
.tm_min
,tmnow
.tm_mday
,tmnow
.tm_mon
+ 1, tmnow
.tm_wday
);
10657 /* walk the list */
10658 for(; skedlist
; skedlist
= skedlist
->next
){
10660 ast_log(LOG_NOTICE
, "Scheduler entry %s = %s being considered\n",skedlist
->name
, skedlist
->value
);
10661 strncpy(value
,skedlist
->value
,99);
10663 /* point to the substrings for minute, hour, dom, month, and dow */
10664 for( i
= 0, vp
= value
; i
< 5; i
++){
10667 while((*vp
== ' ') || (*vp
== 0x09)) /* get rid of any leading white space */
10669 strs
[i
] = vp
; /* save pointer to beginning of substring */
10670 while((*vp
!= ' ') && (*vp
!= 0x09) && (*vp
!= 0)) /* skip over substring */
10673 *vp
++ = 0; /* mark end of substring */
10676 ast_log(LOG_NOTICE
, "i = %d, min = %s, hour = %s, mday=%s, mon=%s, wday=%s\n",i
,
10677 strs
[0], strs
[1], strs
[2], strs
[3], strs
[4]);
10679 if((*strs
[0] != '*')&&(atoi(strs
[0]) != tmnow
.tm_min
))
10681 if((*strs
[1] != '*')&&(atoi(strs
[1]) != tmnow
.tm_hour
))
10683 if((*strs
[2] != '*')&&(atoi(strs
[2]) != tmnow
.tm_mday
))
10685 if((*strs
[3] != '*')&&(atoi(strs
[3]) != tmnow
.tm_mon
+ 1))
10687 if(atoi(strs
[4]) == 7)
10689 if((*strs
[4] != '*')&&(atoi(strs
[4]) != tmnow
.tm_wday
))
10692 ast_log(LOG_NOTICE
, "Executing scheduler entry %s = %s\n", skedlist
->name
, skedlist
->value
);
10693 if(atoi(skedlist
->name
) == 0)
10694 return; /* Zero is reserved for the startup macro */
10695 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.macro
, skedlist
->name
);
10697 ast_log(LOG_WARNING
,"Scheduler could not find macro %s\n",skedlist
->name
);
10698 return; /* Macro not found */
10700 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
)){
10701 ast_log(LOG_WARNING
, "Scheduler could not execute macro %s: Macro buffer full\n",
10703 return; /* Macro buffer full */
10705 myrpt
->macrotimer
= MACROTIME
;
10706 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- 1);
10709 ast_log(LOG_WARNING
,"Malformed scheduler entry in rpt.conf: %s = %s\n",
10710 skedlist
->name
, skedlist
->value
);
10716 /* single thread with one file (request) to dial */
10717 static void *rpt(void *this)
10719 struct rpt
*myrpt
= (struct rpt
*)this;
10720 char *tele
,*idtalkover
,c
,myfirst
,*p
;
10721 int ms
= MSWAIT
,i
,lasttx
=0,val
,remrx
=0,identqueued
,othertelemqueued
;
10722 int tailmessagequeued
,ctqueued
,dtmfed
,lastmyrx
,localmsgqueued
;
10723 struct ast_channel
*who
;
10724 DAHDI_CONFINFO ci
; /* conference info */
10726 struct rpt_link
*l
,*m
;
10727 struct rpt_tele
*telem
;
10728 char tmpstr
[300],lstr
[MAXLINKLIST
];
10731 if (myrpt
->p
.archivedir
) mkdir(myrpt
->p
.archivedir
,0600);
10732 sprintf(tmpstr
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
10733 mkdir(tmpstr
,0600);
10734 rpt_mutex_lock(&myrpt
->lock
);
10736 telem
= myrpt
->tele
.next
;
10737 while(telem
!= &myrpt
->tele
)
10739 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
10740 telem
= telem
->next
;
10742 rpt_mutex_unlock(&myrpt
->lock
);
10743 /* find our index, and load the vars initially */
10744 for(i
= 0; i
< nrpts
; i
++)
10746 if (&rpt_vars
[i
] == myrpt
)
10748 load_rpt_vars(i
,0);
10753 rpt_mutex_lock(&myrpt
->lock
);
10754 while(myrpt
->xlink
)
10757 rpt_mutex_unlock(&myrpt
->lock
);
10759 rpt_mutex_lock(&myrpt
->lock
);
10761 if ((!strcmp(myrpt
->remoterig
, remote_rig_rbi
)) &&
10762 (ioperm(myrpt
->p
.iobase
,1,1) == -1))
10764 rpt_mutex_unlock(&myrpt
->lock
);
10765 ast_log(LOG_WARNING
, "Cant get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
10766 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10767 pthread_exit(NULL
);
10769 strncpy(tmpstr
,myrpt
->rxchanname
,sizeof(tmpstr
) - 1);
10770 tele
= strchr(tmpstr
,'/');
10773 fprintf(stderr
,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt
->rxchanname
);
10774 rpt_mutex_unlock(&myrpt
->lock
);
10775 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10776 pthread_exit(NULL
);
10779 myrpt
->rxchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
10780 myrpt
->dahdirxchannel
= NULL
;
10781 if (!strcasecmp(tmpstr
,"DAHDI"))
10782 myrpt
->dahdirxchannel
= myrpt
->rxchannel
;
10783 if (myrpt
->rxchannel
)
10785 if (myrpt
->rxchannel
->_state
== AST_STATE_BUSY
)
10787 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
10788 rpt_mutex_unlock(&myrpt
->lock
);
10789 ast_hangup(myrpt
->rxchannel
);
10790 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10791 pthread_exit(NULL
);
10793 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
10794 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
10795 #ifdef AST_CDR_FLAG_POST_DISABLED
10796 if (myrpt
->rxchannel
->cdr
)
10797 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10799 #ifndef NEW_ASTERISK
10800 myrpt
->rxchannel
->whentohangup
= 0;
10802 myrpt
->rxchannel
->appl
= "Apprpt";
10803 myrpt
->rxchannel
->data
= "(Repeater Rx)";
10804 if (option_verbose
> 2)
10805 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
10806 tmpstr
,tele
,myrpt
->rxchannel
->name
);
10807 ast_call(myrpt
->rxchannel
,tele
,999);
10808 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
10810 rpt_mutex_unlock(&myrpt
->lock
);
10811 ast_hangup(myrpt
->rxchannel
);
10812 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10813 pthread_exit(NULL
);
10818 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
10819 rpt_mutex_unlock(&myrpt
->lock
);
10820 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10821 pthread_exit(NULL
);
10823 myrpt
->dahditxchannel
= NULL
;
10824 if (myrpt
->txchanname
)
10826 strncpy(tmpstr
,myrpt
->txchanname
,sizeof(tmpstr
) - 1);
10827 tele
= strchr(tmpstr
,'/');
10830 fprintf(stderr
,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt
->txchanname
);
10831 rpt_mutex_unlock(&myrpt
->lock
);
10832 ast_hangup(myrpt
->rxchannel
);
10833 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10834 pthread_exit(NULL
);
10837 myrpt
->txchannel
= ast_request(tmpstr
,AST_FORMAT_SLINEAR
,tele
,NULL
);
10838 if (!strcasecmp(tmpstr
,"DAHDI"))
10839 myrpt
->dahditxchannel
= myrpt
->txchannel
;
10840 if (myrpt
->txchannel
)
10842 if (myrpt
->txchannel
->_state
== AST_STATE_BUSY
)
10844 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
10845 rpt_mutex_unlock(&myrpt
->lock
);
10846 ast_hangup(myrpt
->txchannel
);
10847 ast_hangup(myrpt
->rxchannel
);
10848 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10849 pthread_exit(NULL
);
10851 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
10852 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
10853 #ifdef AST_CDR_FLAG_POST_DISABLED
10854 if (myrpt
->txchannel
->cdr
)
10855 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10857 #ifndef NEW_ASTERISK
10858 myrpt
->txchannel
->whentohangup
= 0;
10860 myrpt
->txchannel
->appl
= "Apprpt";
10861 myrpt
->txchannel
->data
= "(Repeater Tx)";
10862 if (option_verbose
> 2)
10863 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
10864 tmpstr
,tele
,myrpt
->txchannel
->name
);
10865 ast_call(myrpt
->txchannel
,tele
,999);
10866 if (myrpt
->rxchannel
->_state
!= AST_STATE_UP
)
10868 rpt_mutex_unlock(&myrpt
->lock
);
10869 ast_hangup(myrpt
->rxchannel
);
10870 ast_hangup(myrpt
->txchannel
);
10871 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10872 pthread_exit(NULL
);
10877 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
10878 rpt_mutex_unlock(&myrpt
->lock
);
10879 ast_hangup(myrpt
->rxchannel
);
10880 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10881 pthread_exit(NULL
);
10886 myrpt
->txchannel
= myrpt
->rxchannel
;
10887 if (!strncasecmp(myrpt
->rxchanname
,"DAHDI",3))
10888 myrpt
->dahditxchannel
= myrpt
->txchannel
;
10890 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
10891 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
10892 /* allocate a pseudo-channel thru asterisk */
10893 myrpt
->pchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
10894 if (!myrpt
->pchannel
)
10896 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
10897 rpt_mutex_unlock(&myrpt
->lock
);
10898 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
10899 ast_hangup(myrpt
->txchannel
);
10900 ast_hangup(myrpt
->rxchannel
);
10901 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10902 pthread_exit(NULL
);
10904 #ifdef AST_CDR_FLAG_POST_DISABLED
10905 if (myrpt
->pchannel
->cdr
)
10906 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10908 if (!myrpt
->dahdirxchannel
) myrpt
->dahdirxchannel
= myrpt
->pchannel
;
10909 if (!myrpt
->dahditxchannel
)
10911 /* allocate a pseudo-channel thru asterisk */
10912 myrpt
->dahditxchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
10913 if (!myrpt
->dahditxchannel
)
10915 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
10916 rpt_mutex_unlock(&myrpt
->lock
);
10917 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
10918 ast_hangup(myrpt
->txchannel
);
10919 ast_hangup(myrpt
->rxchannel
);
10920 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10921 pthread_exit(NULL
);
10923 ast_set_read_format(myrpt
->dahditxchannel
,AST_FORMAT_SLINEAR
);
10924 ast_set_write_format(myrpt
->dahditxchannel
,AST_FORMAT_SLINEAR
);
10925 #ifdef AST_CDR_FLAG_POST_DISABLED
10926 if (myrpt
->dahditxchannel
->cdr
)
10927 ast_set_flag(myrpt
->dahditxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10930 /* allocate a pseudo-channel thru asterisk */
10931 myrpt
->monchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
10932 if (!myrpt
->monchannel
)
10934 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
10935 rpt_mutex_unlock(&myrpt
->lock
);
10936 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
10937 ast_hangup(myrpt
->txchannel
);
10938 ast_hangup(myrpt
->rxchannel
);
10939 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10940 pthread_exit(NULL
);
10942 ast_set_read_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
10943 ast_set_write_format(myrpt
->monchannel
,AST_FORMAT_SLINEAR
);
10944 #ifdef AST_CDR_FLAG_POST_DISABLED
10945 if (myrpt
->monchannel
->cdr
)
10946 ast_set_flag(myrpt
->monchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
10948 /* make a conference for the tx */
10950 ci
.confno
= -1; /* make a new conf */
10951 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
;
10952 /* first put the channel on the conference in proper mode */
10953 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
10955 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
10956 rpt_mutex_unlock(&myrpt
->lock
);
10957 ast_hangup(myrpt
->pchannel
);
10958 ast_hangup(myrpt
->monchannel
);
10959 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
10960 ast_hangup(myrpt
->txchannel
);
10961 ast_hangup(myrpt
->rxchannel
);
10962 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10963 pthread_exit(NULL
);
10965 /* save tx conference number */
10966 myrpt
->txconf
= ci
.confno
;
10967 /* make a conference for the pseudo */
10969 ci
.confno
= -1; /* make a new conf */
10970 ci
.confmode
= ((myrpt
->p
.duplex
== 2) || (myrpt
->p
.duplex
== 4)) ? DAHDI_CONF_CONFANNMON
:
10971 (DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
);
10972 /* first put the channel on the conference in announce mode */
10973 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
10975 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
10976 rpt_mutex_unlock(&myrpt
->lock
);
10977 ast_hangup(myrpt
->pchannel
);
10978 ast_hangup(myrpt
->monchannel
);
10979 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
10980 ast_hangup(myrpt
->txchannel
);
10981 ast_hangup(myrpt
->rxchannel
);
10982 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
10983 pthread_exit(NULL
);
10985 /* save pseudo channel conference number */
10986 myrpt
->conf
= ci
.confno
;
10987 /* make a conference for the pseudo */
10989 if ((strstr(myrpt
->txchannel
->name
,"pseudo") == NULL
) &&
10990 (myrpt
->dahditxchannel
== myrpt
->txchannel
))
10992 /* get tx channel's port number */
10993 if (ioctl(myrpt
->txchannel
->fds
[0],DAHDI_CHANNO
,&ci
.confno
) == -1)
10995 ast_log(LOG_WARNING
, "Unable to set tx channel's chan number\n");
10996 rpt_mutex_unlock(&myrpt
->lock
);
10997 ast_hangup(myrpt
->pchannel
);
10998 ast_hangup(myrpt
->monchannel
);
10999 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11000 ast_hangup(myrpt
->txchannel
);
11001 ast_hangup(myrpt
->rxchannel
);
11002 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
11003 pthread_exit(NULL
);
11005 ci
.confmode
= DAHDI_CONF_MONITORTX
;
11009 ci
.confno
= myrpt
->txconf
;
11010 ci
.confmode
= DAHDI_CONF_CONFANNMON
;
11012 /* first put the channel on the conference in announce mode */
11013 if (ioctl(myrpt
->monchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
11015 ast_log(LOG_WARNING
, "Unable to set conference mode for monitor\n");
11016 rpt_mutex_unlock(&myrpt
->lock
);
11017 ast_hangup(myrpt
->pchannel
);
11018 ast_hangup(myrpt
->monchannel
);
11019 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11020 ast_hangup(myrpt
->txchannel
);
11021 ast_hangup(myrpt
->rxchannel
);
11022 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
11023 pthread_exit(NULL
);
11025 /* allocate a pseudo-channel thru asterisk */
11026 myrpt
->parrotchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
11027 if (!myrpt
->parrotchannel
)
11029 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
11030 rpt_mutex_unlock(&myrpt
->lock
);
11031 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11032 ast_hangup(myrpt
->txchannel
);
11033 ast_hangup(myrpt
->rxchannel
);
11034 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
11035 pthread_exit(NULL
);
11037 ast_set_read_format(myrpt
->parrotchannel
,AST_FORMAT_SLINEAR
);
11038 ast_set_write_format(myrpt
->parrotchannel
,AST_FORMAT_SLINEAR
);
11039 #ifdef AST_CDR_FLAG_POST_DISABLED
11040 if (myrpt
->parrotchannel
->cdr
)
11041 ast_set_flag(myrpt
->parrotchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11043 /* allocate a pseudo-channel thru asterisk */
11044 myrpt
->voxchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
11045 if (!myrpt
->voxchannel
)
11047 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
11048 rpt_mutex_unlock(&myrpt
->lock
);
11049 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11050 ast_hangup(myrpt
->txchannel
);
11051 ast_hangup(myrpt
->rxchannel
);
11052 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
11053 pthread_exit(NULL
);
11055 ast_set_read_format(myrpt
->voxchannel
,AST_FORMAT_SLINEAR
);
11056 ast_set_write_format(myrpt
->voxchannel
,AST_FORMAT_SLINEAR
);
11057 #ifdef AST_CDR_FLAG_POST_DISABLED
11058 if (myrpt
->voxchannel
->cdr
)
11059 ast_set_flag(myrpt
->voxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11061 /* allocate a pseudo-channel thru asterisk */
11062 myrpt
->txpchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
11063 if (!myrpt
->txpchannel
)
11065 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
11066 rpt_mutex_unlock(&myrpt
->lock
);
11067 ast_hangup(myrpt
->pchannel
);
11068 ast_hangup(myrpt
->monchannel
);
11069 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11070 ast_hangup(myrpt
->txchannel
);
11071 ast_hangup(myrpt
->rxchannel
);
11072 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
11073 pthread_exit(NULL
);
11075 #ifdef AST_CDR_FLAG_POST_DISABLED
11076 if (myrpt
->txpchannel
->cdr
)
11077 ast_set_flag(myrpt
->txpchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
11079 /* make a conference for the tx */
11081 ci
.confno
= myrpt
->txconf
;
11082 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_TALKER
;
11083 /* first put the channel on the conference in proper mode */
11084 if (ioctl(myrpt
->txpchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
11086 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
11087 rpt_mutex_unlock(&myrpt
->lock
);
11088 ast_hangup(myrpt
->txpchannel
);
11089 ast_hangup(myrpt
->monchannel
);
11090 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11091 ast_hangup(myrpt
->txchannel
);
11092 ast_hangup(myrpt
->rxchannel
);
11093 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
11094 pthread_exit(NULL
);
11096 /* if serial io port, open it */
11098 if (myrpt
->p
.ioport
&& ((myrpt
->iofd
= openserial(myrpt
,myrpt
->p
.ioport
)) == -1))
11100 ast_log(LOG_ERROR
, "Unable to open %s\n",myrpt
->p
.ioport
);
11101 rpt_mutex_unlock(&myrpt
->lock
);
11102 ast_hangup(myrpt
->pchannel
);
11103 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
11104 ast_hangup(myrpt
->txchannel
);
11105 ast_hangup(myrpt
->rxchannel
);
11106 pthread_exit(NULL
);
11108 /* Now, the idea here is to copy from the physical rx channel buffer
11109 into the pseudo tx buffer, and from the pseudo rx buffer into the
11110 tx channel buffer */
11111 myrpt
->links
.next
= &myrpt
->links
;
11112 myrpt
->links
.prev
= &myrpt
->links
;
11113 myrpt
->tailtimer
= 0;
11114 myrpt
->totimer
= 0;
11115 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
11116 myrpt
->idtimer
= myrpt
->p
.politeid
;
11117 myrpt
->mustid
= myrpt
->tailid
= 0;
11118 myrpt
->callmode
= 0;
11119 myrpt
->tounkeyed
= 0;
11120 myrpt
->tonotify
= 0;
11121 myrpt
->retxtimer
= 0;
11122 myrpt
->rerxtimer
= 0;
11123 myrpt
->skedtimer
= 0;
11124 myrpt
->tailevent
= 0;
11127 myrpt
->txkeyed
= 0;
11128 time(&myrpt
->lastkeyedtime
);
11129 myrpt
->lastkeyedtime
-= RPT_LOCKOUT_SECS
;
11130 time(&myrpt
->lasttxkeyedtime
);
11131 myrpt
->lasttxkeyedtime
-= RPT_LOCKOUT_SECS
;
11132 idtalkover
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->name
, "idtalkover");
11133 myrpt
->dtmfidx
= -1;
11134 myrpt
->dtmfbuf
[0] = 0;
11135 myrpt
->rem_dtmfidx
= -1;
11136 myrpt
->rem_dtmfbuf
[0] = 0;
11137 myrpt
->dtmf_time
= 0;
11138 myrpt
->rem_dtmf_time
= 0;
11139 myrpt
->inpadtest
= 0;
11140 myrpt
->disgorgetime
= 0;
11141 myrpt
->lastnodewhichkeyedusup
[0] = '\0';
11142 myrpt
->dailytxtime
= 0;
11143 myrpt
->totaltxtime
= 0;
11144 myrpt
->dailykeyups
= 0;
11145 myrpt
->totalkeyups
= 0;
11146 myrpt
->dailykerchunks
= 0;
11147 myrpt
->totalkerchunks
= 0;
11148 myrpt
->dailyexecdcommands
= 0;
11149 myrpt
->totalexecdcommands
= 0;
11150 myrpt
->timeouts
= 0;
11151 myrpt
->exten
[0] = '\0';
11152 myrpt
->lastdtmfcommand
[0] = '\0';
11153 voxinit_rpt(myrpt
,1);
11155 if (myrpt
->p
.startupmacro
)
11157 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
11159 rpt_mutex_unlock(&myrpt
->lock
);
11161 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_RELAXDTMF
,&val
,sizeof(char),0);
11163 ast_channel_setoption(myrpt
->rxchannel
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
11164 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"STARTUP");
11166 if (myrpt
->remoterig
&& !ISRIG_RTX(myrpt
->remoterig
)) setrem(myrpt
);
11171 struct ast_frame
*f
,*f1
,*f2
;
11172 struct ast_channel
*cs
[300],*cs1
[300];
11173 int totx
=0,elap
=0,n
,x
,toexit
=0;
11176 if((myrpt
->disgorgetime
) && (time(NULL
) >= myrpt
->disgorgetime
)){
11177 struct rpt_link
*dl
;
11178 struct rpt_tele
*dt
;
11180 myrpt
->disgorgetime
= 0;
11181 ast_log(LOG_NOTICE
,"********** Variable Dump Start (app_rpt) **********\n");
11182 ast_log(LOG_NOTICE
,"totx = %d\n",totx
);
11183 ast_log(LOG_NOTICE
,"remrx = %d\n",remrx
);
11184 ast_log(LOG_NOTICE
,"lasttx = %d\n",lasttx
);
11185 ast_log(LOG_NOTICE
,"elap = %d\n",elap
);
11186 ast_log(LOG_NOTICE
,"toexit = %d\n",toexit
);
11188 ast_log(LOG_NOTICE
,"myrpt->keyed = %d\n",myrpt
->keyed
);
11189 ast_log(LOG_NOTICE
,"myrpt->localtx = %d\n",myrpt
->localtx
);
11190 ast_log(LOG_NOTICE
,"myrpt->callmode = %d\n",myrpt
->callmode
);
11191 ast_log(LOG_NOTICE
,"myrpt->mustid = %d\n",myrpt
->mustid
);
11192 ast_log(LOG_NOTICE
,"myrpt->tounkeyed = %d\n",myrpt
->tounkeyed
);
11193 ast_log(LOG_NOTICE
,"myrpt->tonotify = %d\n",myrpt
->tonotify
);
11194 ast_log(LOG_NOTICE
,"myrpt->retxtimer = %ld\n",myrpt
->retxtimer
);
11195 ast_log(LOG_NOTICE
,"myrpt->totimer = %d\n",myrpt
->totimer
);
11196 ast_log(LOG_NOTICE
,"myrpt->tailtimer = %d\n",myrpt
->tailtimer
);
11197 ast_log(LOG_NOTICE
,"myrpt->tailevent = %d\n",myrpt
->tailevent
);
11199 dl
= myrpt
->links
.next
;
11200 while(dl
!= &myrpt
->links
){
11201 ast_log(LOG_NOTICE
,"*** Link Name: %s ***\n",dl
->name
);
11202 ast_log(LOG_NOTICE
," link->lasttx %d\n",dl
->lasttx
);
11203 ast_log(LOG_NOTICE
," link->lastrx %d\n",dl
->lastrx
);
11204 ast_log(LOG_NOTICE
," link->connected %d\n",dl
->connected
);
11205 ast_log(LOG_NOTICE
," link->hasconnected %d\n",dl
->hasconnected
);
11206 ast_log(LOG_NOTICE
," link->outbound %d\n",dl
->outbound
);
11207 ast_log(LOG_NOTICE
," link->disced %d\n",dl
->disced
);
11208 ast_log(LOG_NOTICE
," link->killme %d\n",dl
->killme
);
11209 ast_log(LOG_NOTICE
," link->disctime %ld\n",dl
->disctime
);
11210 ast_log(LOG_NOTICE
," link->retrytimer %ld\n",dl
->retrytimer
);
11211 ast_log(LOG_NOTICE
," link->retries = %d\n",dl
->retries
);
11212 ast_log(LOG_NOTICE
," link->reconnects = %d\n",dl
->reconnects
);
11213 ast_log(LOG_NOTICE
," link->newkey = %d\n",dl
->newkey
);
11217 dt
= myrpt
->tele
.next
;
11218 if(dt
!= &myrpt
->tele
)
11219 ast_log(LOG_NOTICE
,"*** Telemetry Queue ***\n");
11220 while(dt
!= &myrpt
->tele
){
11221 ast_log(LOG_NOTICE
," Telemetry mode: %d\n",dt
->mode
);
11224 ast_log(LOG_NOTICE
,"******* Variable Dump End (app_rpt) *******\n");
11231 struct rpt_tele
*telem
;
11233 rpt_mutex_lock(&myrpt
->lock
);
11234 telem
= myrpt
->tele
.next
;
11235 while(telem
!= &myrpt
->tele
)
11237 ast_softhangup(telem
->chan
,AST_SOFTHANGUP_DEV
);
11238 telem
= telem
->next
;
11241 rpt_mutex_unlock(&myrpt
->lock
);
11243 /* find our index, and load the vars */
11244 for(i
= 0; i
< nrpts
; i
++)
11246 if (&rpt_vars
[i
] == myrpt
)
11248 load_rpt_vars(i
,0);
11254 rpt_mutex_lock(&myrpt
->lock
);
11255 if (ast_check_hangup(myrpt
->rxchannel
)) break;
11256 if (ast_check_hangup(myrpt
->txchannel
)) break;
11257 if (ast_check_hangup(myrpt
->pchannel
)) break;
11258 if (ast_check_hangup(myrpt
->monchannel
)) break;
11259 if (myrpt
->parrotchannel
&&
11260 ast_check_hangup(myrpt
->parrotchannel
)) break;
11261 if (myrpt
->voxchannel
&&
11262 ast_check_hangup(myrpt
->voxchannel
)) break;
11263 if (ast_check_hangup(myrpt
->txpchannel
)) break;
11264 if (myrpt
->dahditxchannel
&& ast_check_hangup(myrpt
->dahditxchannel
)) break;
11266 /* Set local tx with keyed */
11267 myrpt
->localtx
= myrpt
->keyed
;
11268 /* If someone's connected, and they're transmitting from their end to us, set remrx true */
11269 l
= myrpt
->links
.next
;
11271 while(l
!= &myrpt
->links
)
11275 if(l
->name
[0] != '0') /* Ignore '0' nodes */
11276 strcpy(myrpt
->lastnodewhichkeyedusup
, l
->name
); /* Note the node which is doing the key up */
11280 /* Create a "must_id" flag for the cleanup ID */
11281 if(myrpt
->p
.idtime
) /* ID time must be non-zero */
11282 myrpt
->mustid
|= (myrpt
->idtimer
) && (myrpt
->keyed
|| remrx
) ;
11283 /* Build a fresh totx from myrpt->keyed and autopatch activated */
11284 /* If full duplex, add local tx to totx */
11285 if (myrpt
->p
.duplex
> 1)
11287 totx
= myrpt
->callmode
;
11288 totx
= totx
|| myrpt
->localtx
;
11292 int myrx
= myrpt
->localtx
|| remrx
|| (!myrpt
->callmode
);
11294 if (lastmyrx
!= myrx
)
11296 voxinit_rpt(myrpt
,!myrx
);
11300 if (myrpt
->callmode
&& (myrpt
->voxtotimer
<= 0))
11302 if (myrpt
->voxtostate
)
11304 myrpt
->voxtotimer
= myrpt
->p
.voxtimeout_ms
;
11305 myrpt
->voxtostate
= 0;
11309 myrpt
->voxtotimer
= myrpt
->p
.voxrecover_ms
;
11310 myrpt
->voxtostate
= 1;
11313 if (!myrpt
->voxtostate
)
11314 totx
= myrpt
->callmode
&& myrpt
->wasvox
;
11316 /* Traverse the telemetry list to see what's queued */
11318 localmsgqueued
= 0;
11319 othertelemqueued
= 0;
11320 tailmessagequeued
= 0;
11322 telem
= myrpt
->tele
.next
;
11323 while(telem
!= &myrpt
->tele
)
11325 if((telem
->mode
== ID
) || (telem
->mode
== IDTALKOVER
)){
11326 identqueued
= 1; /* Identification telemetry */
11328 else if(telem
->mode
== TAILMSG
)
11330 tailmessagequeued
= 1; /* Tail message telemetry */
11332 else if(telem
->mode
== STATS_TIME_LOCAL
)
11334 localmsgqueued
= 1; /* Local message */
11338 if ((telem
->mode
!= UNKEY
) && (telem
->mode
!= LINKUNKEY
))
11339 othertelemqueued
= 1; /* Other telemetry */
11341 ctqueued
= 1; /* Courtesy tone telemetry */
11343 telem
= telem
->next
;
11346 /* Add in any "other" telemetry, unless specified otherwise */
11347 if (!myrpt
->p
.notelemtx
) totx
= totx
|| othertelemqueued
;
11348 /* Update external (to links) transmitter PTT state with everything but */
11349 /* ID, CT, local messages, and tailmessage telemetry */
11350 myrpt
->exttx
= totx
;
11351 totx
= totx
|| myrpt
->dtmf_local_timer
;
11352 /* If half or 3/4 duplex, add localtx to external link tx */
11353 if (myrpt
->p
.duplex
< 2) myrpt
->exttx
= myrpt
->exttx
|| myrpt
->localtx
;
11354 /* Add in ID telemetry to local transmitter */
11355 totx
= totx
|| remrx
;
11356 /* If 3/4 or full duplex, add in ident, CT telemetry, and local messages */
11357 if (myrpt
->p
.duplex
> 0)
11358 totx
= totx
|| identqueued
|| ctqueued
|| localmsgqueued
;
11359 /* If full duplex, add local dtmf stuff active */
11360 if (myrpt
->p
.duplex
> 1)
11362 totx
= totx
|| (myrpt
->dtmfidx
> -1) ||
11365 /* add in parrot stuff */
11366 totx
= totx
|| (myrpt
->parrotstate
> 1);
11367 /* Reset time out timer variables if there is no activity */
11370 myrpt
->totimer
= myrpt
->p
.totime
;
11371 myrpt
->tounkeyed
= 0;
11372 myrpt
->tonotify
= 0;
11375 myrpt
->tailtimer
= myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
?
11376 myrpt
->p
.althangtime
: /* Initialize tail timer */
11379 /* Disable the local transmitter if we are timed out */
11380 totx
= totx
&& myrpt
->totimer
;
11381 /* if timed-out and not said already, say it */
11382 if ((!myrpt
->totimer
) && (!myrpt
->tonotify
))
11384 myrpt
->tonotify
= 1;
11386 rpt_mutex_unlock(&myrpt
->lock
);
11387 rpt_telemetry(myrpt
,TIMEOUT
,NULL
);
11388 rpt_mutex_lock(&myrpt
->lock
);
11391 /* If unkey and re-key, reset time out timer */
11392 if ((!totx
) && (!myrpt
->totimer
) && (!myrpt
->tounkeyed
) && (!myrpt
->keyed
))
11394 myrpt
->tounkeyed
= 1;
11396 if ((!totx
) && (!myrpt
->totimer
) && myrpt
->tounkeyed
&& myrpt
->keyed
)
11398 myrpt
->totimer
= myrpt
->p
.totime
;
11399 myrpt
->tounkeyed
= 0;
11400 myrpt
->tonotify
= 0;
11401 rpt_mutex_unlock(&myrpt
->lock
);
11404 /* if timed-out and in circuit busy after call */
11405 if ((!totx
) && (!myrpt
->totimer
) && (myrpt
->callmode
== 4))
11408 ast_log(LOG_NOTICE
, "timed-out and in circuit busy after call\n");
11409 myrpt
->callmode
= 0;
11410 myrpt
->macropatch
=0;
11411 channel_revert(myrpt
);
11413 /* get rid of tail if timed out */
11414 if (!myrpt
->totimer
) myrpt
->tailtimer
= 0;
11415 /* if not timed-out, add in tail */
11416 if (myrpt
->totimer
) totx
= totx
|| myrpt
->tailtimer
;
11417 /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
11418 /* If tail message, kill the message if someone keys up over it */
11419 if ((myrpt
->keyed
|| remrx
) && ((identqueued
&& idtalkover
) || (tailmessagequeued
))) {
11420 int hasid
= 0,hastalkover
= 0;
11422 telem
= myrpt
->tele
.next
;
11423 while(telem
!= &myrpt
->tele
){
11424 if(telem
->mode
== ID
){
11425 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
11428 if(telem
->mode
== TAILMSG
){
11429 if (telem
->chan
) ast_softhangup(telem
->chan
, AST_SOFTHANGUP_DEV
); /* Whoosh! */
11431 if (telem
->mode
== IDTALKOVER
) hastalkover
= 1;
11432 telem
= telem
->next
;
11434 rpt_mutex_unlock(&myrpt
->lock
);
11435 if (hasid
&& (!hastalkover
)) rpt_telemetry(myrpt
, IDTALKOVER
, NULL
); /* Start Talkover ID */
11436 rpt_mutex_lock(&myrpt
->lock
);
11438 /* Try to be polite */
11439 /* If the repeater has been inactive for longer than the ID time, do an initial ID in the tail*/
11440 /* If within 30 seconds of the time to ID, try do it in the tail */
11441 /* else if at ID time limit, do it right over the top of them */
11442 /* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
11443 if(myrpt
->mustid
&& (!myrpt
->idtimer
))
11446 if ((myrpt
->p
.idtime
&& totx
&& (!myrpt
->exttx
) &&
11447 (myrpt
->idtimer
<= myrpt
->p
.politeid
) && myrpt
->tailtimer
)) /* ID time must be non-zero */
11452 /* If tail timer expires, then check for tail messages */
11454 if(myrpt
->tailevent
){
11455 myrpt
->tailevent
= 0;
11460 else if ((myrpt
->p
.tailmessages
[0]) &&
11461 (myrpt
->p
.tailmessagetime
) && (myrpt
->tmsgtimer
== 0)){
11463 myrpt
->tmsgtimer
= myrpt
->p
.tailmessagetime
;
11464 rpt_mutex_unlock(&myrpt
->lock
);
11465 rpt_telemetry(myrpt
, TAILMSG
, NULL
);
11466 rpt_mutex_lock(&myrpt
->lock
);
11470 /* Main TX control */
11472 /* let telemetry transmit anyway (regardless of timeout) */
11473 if (myrpt
->p
.duplex
> 0) totx
= totx
|| (myrpt
->tele
.next
!= &myrpt
->tele
);
11474 totx
= totx
&& !myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
;
11475 myrpt
->txrealkeyed
= totx
;
11476 totx
= totx
|| (!AST_LIST_EMPTY(&myrpt
->txq
));
11477 if (totx
&& (!lasttx
))
11479 char mydate
[100],myfname
[100];
11482 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
11483 if (myrpt
->p
.archivedir
)
11488 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
11490 sprintf(myfname
,"%s/%s/%s",myrpt
->p
.archivedir
,
11491 myrpt
->name
,mydate
);
11492 myrpt
->monstream
= ast_writefile(myfname
,"wav49",
11493 "app_rpt Air Archive",O_CREAT
| O_APPEND
,0,0600);
11494 if (myrpt
->p
.monminblocks
)
11496 blocksleft
= diskavail(myrpt
);
11497 if (blocksleft
>= myrpt
->p
.monminblocks
)
11498 donodelog(myrpt
,"TXKEY,MAIN");
11499 } else donodelog(myrpt
,"TXKEY,MAIN");
11502 myrpt
->txkeyed
= 1;
11503 time(&myrpt
->lasttxkeyedtime
);
11504 myrpt
->dailykeyups
++;
11505 myrpt
->totalkeyups
++;
11506 rpt_mutex_unlock(&myrpt
->lock
);
11507 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
11508 rpt_mutex_lock(&myrpt
->lock
);
11510 if ((!totx
) && lasttx
)
11512 if (myrpt
->monstream
) ast_closestream(myrpt
->monstream
);
11513 myrpt
->monstream
= NULL
;
11516 myrpt
->txkeyed
= 0;
11517 time(&myrpt
->lasttxkeyedtime
);
11518 rpt_mutex_unlock(&myrpt
->lock
);
11519 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
11520 rpt_mutex_lock(&myrpt
->lock
);
11521 donodelog(myrpt
,"TXUNKEY,MAIN");
11524 /* if DTMF timeout */
11525 if ((!myrpt
->cmdnode
[0]) && (myrpt
->dtmfidx
>= 0) && ((myrpt
->dtmf_time
+ DTMF_TIMEOUT
) < t
))
11527 myrpt
->inpadtest
= 0;
11528 myrpt
->dtmfidx
= -1;
11529 myrpt
->dtmfbuf
[0] = 0;
11531 /* if remote DTMF timeout */
11532 if ((myrpt
->rem_dtmfidx
>= 0) && ((myrpt
->rem_dtmf_time
+ DTMF_TIMEOUT
) < t
))
11534 myrpt
->inpadtest
= 0;
11535 myrpt
->rem_dtmfidx
= -1;
11536 myrpt
->rem_dtmfbuf
[0] = 0;
11539 if (myrpt
->exttx
&& myrpt
->parrotchannel
&&
11540 myrpt
->p
.parrotmode
&& (!myrpt
->parrotstate
))
11544 ci
.confno
= myrpt
->conf
;
11545 ci
.confmode
= DAHDI_CONF_CONFANNMON
;
11548 /* first put the channel on the conference in announce mode */
11549 if (ioctl(myrpt
->parrotchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
11551 ast_log(LOG_WARNING
, "Unable to set conference mode for parrot\n");
11555 sprintf(myfname
,PARROTFILE
,myrpt
->name
,myrpt
->parrotcnt
);
11556 strcat(myfname
,".wav");
11558 sprintf(myfname
,PARROTFILE
,myrpt
->name
,myrpt
->parrotcnt
);
11559 myrpt
->parrotstate
= 1;
11560 myrpt
->parrottimer
= myrpt
->p
.parrottime
;
11561 if (myrpt
->parrotstream
)
11562 ast_closestream(myrpt
->parrotstream
);
11563 myrpt
->parrotstream
= NULL
;
11564 myrpt
->parrotstream
= ast_writefile(myfname
,"wav",
11565 "app_rpt Parrot",O_CREAT
| O_TRUNC
,0,0600);
11570 l
= myrpt
->links
.next
;
11571 while(l
!= &myrpt
->links
)
11575 /* remove from queue */
11576 remque((struct qelem
*) l
);
11577 if (!strcmp(myrpt
->cmdnode
,l
->name
))
11578 myrpt
->cmdnode
[0] = 0;
11579 rpt_mutex_unlock(&myrpt
->lock
);
11580 /* hang-up on call to device */
11581 if (l
->chan
) ast_hangup(l
->chan
);
11582 ast_hangup(l
->pchan
);
11584 rpt_mutex_lock(&myrpt
->lock
);
11585 /* re-start link traversal */
11586 l
= myrpt
->links
.next
;
11592 cs
[n
++] = myrpt
->rxchannel
;
11593 cs
[n
++] = myrpt
->pchannel
;
11594 cs
[n
++] = myrpt
->monchannel
;
11595 if (myrpt
->parrotchannel
) cs
[n
++] = myrpt
->parrotchannel
;
11596 if (myrpt
->voxchannel
) cs
[n
++] = myrpt
->voxchannel
;
11597 cs
[n
++] = myrpt
->txpchannel
;
11598 if (myrpt
->txchannel
!= myrpt
->rxchannel
) cs
[n
++] = myrpt
->txchannel
;
11599 if (myrpt
->dahditxchannel
!= myrpt
->txchannel
)
11600 cs
[n
++] = myrpt
->dahditxchannel
;
11601 l
= myrpt
->links
.next
;
11602 while(l
!= &myrpt
->links
)
11604 if ((!l
->killme
) && (!l
->disctime
) && l
->chan
)
11607 cs
[n
++] = l
->pchan
;
11611 if ((myrpt
->topkeystate
== 1) &&
11612 ((t
- myrpt
->topkeytime
) > TOPKEYWAIT
))
11614 myrpt
->topkeystate
= 2;
11615 qsort(myrpt
->topkey
,TOPKEYN
,sizeof(struct rpt_topkey
),
11618 rpt_mutex_unlock(&myrpt
->lock
);
11620 if (myrpt
->topkeystate
== 2)
11622 rpt_telemetry(myrpt
,TOPKEY
,NULL
);
11623 myrpt
->topkeystate
= 3;
11626 for(x
= 0; x
< n
; x
++)
11628 int s
= -(-x
- myrpt
->scram
- 1) % n
;
11632 who
= ast_waitfor_n(cs1
,n
,&ms
);
11633 if (who
== NULL
) ms
= 0;
11634 elap
= MSWAIT
- ms
;
11635 rpt_mutex_lock(&myrpt
->lock
);
11636 l
= myrpt
->links
.next
;
11637 while(l
!= &myrpt
->links
)
11641 if (l
->voxtotimer
) l
->voxtotimer
-= elap
;
11642 if (l
->voxtotimer
< 0) l
->voxtotimer
= 0;
11644 if (l
->lasttx
!= l
->lasttx1
)
11646 voxinit_link(l
,!l
->lasttx
);
11647 l
->lasttx1
= l
->lasttx
;
11649 myrx
= l
->lastrealrx
;
11650 if ((l
->phonemode
) && (l
->phonevox
))
11652 myrx
= myrx
|| (!AST_LIST_EMPTY(&l
->rxq
));
11653 if (l
->voxtotimer
<= 0)
11657 l
->voxtotimer
= myrpt
->p
.voxtimeout_ms
;
11662 l
->voxtotimer
= myrpt
->p
.voxrecover_ms
;
11666 if (!l
->voxtostate
)
11667 myrx
= myrx
|| l
->wasvox
;
11670 if (l
->linklisttimer
)
11672 l
->linklisttimer
-= elap
;
11673 if (l
->linklisttimer
< 0) l
->linklisttimer
= 0;
11675 if ((!l
->linklisttimer
) && (l
->name
[0] != '0') && (!l
->isremote
))
11677 struct ast_frame lf
;
11679 memset(&lf
,0,sizeof(lf
));
11680 lf
.frametype
= AST_FRAME_TEXT
;
11685 l
->linklisttimer
= LINKLISTTIME
;
11687 __mklinklist(myrpt
,l
,lstr
+ 2);
11690 lf
.datalen
= strlen(lstr
) + 1;
11691 lf
.data
.ptr
= lstr
;
11692 ast_write(l
->chan
,&lf
);
11693 if (debug
> 6) ast_log(LOG_NOTICE
,
11694 "@@@@ node %s sent node string %s to node %s\n",
11695 myrpt
->name
,lstr
,l
->name
);
11700 if ((l
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
11703 if (l
->chan
&& l
->phonemode
== 0)
11706 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
11708 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
11711 if ((l
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 5))
11713 if (debug
== 7) printf("@@@@ rx un-key\n");
11718 if (myrpt
->p
.archivedir
)
11722 sprintf(str
,"RXUNKEY(T),%s",l
->name
);
11723 donodelog(myrpt
,str
);
11725 if(myrpt
->p
.duplex
)
11726 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
11731 if (l
->disctime
) /* Disconnect timer active on a channel ? */
11733 l
->disctime
-= elap
;
11734 if (l
->disctime
<= 0) /* Disconnect timer expired on inbound channel ? */
11735 l
->disctime
= 0; /* Yep */
11740 l
->retrytimer
-= elap
;
11741 if (l
->retrytimer
< 0) l
->retrytimer
= 0;
11744 /* Tally connect time */
11745 l
->connecttime
+= elap
;
11747 /* ignore non-timing channels */
11748 if (l
->elaptime
< 0)
11753 l
->elaptime
+= elap
;
11754 /* if connection has taken too long */
11755 if ((l
->elaptime
> MAXCONNECTTIME
) &&
11756 ((!l
->chan
) || (l
->chan
->_state
!= AST_STATE_UP
)))
11759 rpt_mutex_unlock(&myrpt
->lock
);
11760 if (l
->chan
) ast_softhangup(l
->chan
,AST_SOFTHANGUP_DEV
);
11761 rpt_mutex_lock(&myrpt
->lock
);
11764 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
11765 (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
11767 if (l
->chan
) ast_hangup(l
->chan
);
11769 rpt_mutex_unlock(&myrpt
->lock
);
11770 if ((l
->name
[0] != '0') && (!l
->isremote
))
11772 if (attempt_reconnect(myrpt
,l
) == -1)
11774 l
->retrytimer
= RETRY_TIMER_MS
;
11779 l
->retrytimer
= l
->max_retries
+ 1;
11782 rpt_mutex_lock(&myrpt
->lock
);
11785 if ((!l
->chan
) && (!l
->retrytimer
) && l
->outbound
&&
11786 (l
->retries
>= l
->max_retries
))
11788 /* remove from queue */
11789 remque((struct qelem
*) l
);
11790 if (!strcmp(myrpt
->cmdnode
,l
->name
))
11791 myrpt
->cmdnode
[0] = 0;
11792 rpt_mutex_unlock(&myrpt
->lock
);
11793 if (l
->name
[0] != '0')
11795 if (!l
->hasconnected
)
11796 rpt_telemetry(myrpt
,CONNFAIL
,l
);
11797 else rpt_telemetry(myrpt
,REMDISC
,l
);
11799 if (myrpt
->p
.archivedir
)
11803 if (!l
->hasconnected
)
11804 sprintf(str
,"LINKFAIL,%s",l
->name
);
11806 sprintf(str
,"LINKDISC,%s",l
->name
);
11807 donodelog(myrpt
,str
);
11809 /* hang-up on call to device */
11810 ast_hangup(l
->pchan
);
11812 rpt_mutex_lock(&myrpt
->lock
);
11815 if ((!l
->chan
) && (!l
->disctime
) && (!l
->outbound
))
11817 if(debug
)ast_log(LOG_NOTICE
, "LINKDISC AA\n");
11818 /* remove from queue */
11819 remque((struct qelem
*) l
);
11820 if(myrpt
->links
.next
==&myrpt
->links
)channel_revert(myrpt
);
11821 if (!strcmp(myrpt
->cmdnode
,l
->name
))myrpt
->cmdnode
[0] = 0;
11822 rpt_mutex_unlock(&myrpt
->lock
);
11823 if (l
->name
[0] != '0')
11825 rpt_telemetry(myrpt
,REMDISC
,l
);
11827 if (myrpt
->p
.archivedir
)
11830 sprintf(str
,"LINKDISC,%s",l
->name
);
11831 donodelog(myrpt
,str
);
11833 /* hang-up on call to device */
11834 ast_hangup(l
->pchan
);
11836 rpt_mutex_lock(&myrpt
->lock
);
11841 if (myrpt
->linkposttimer
)
11843 myrpt
->linkposttimer
-= elap
;
11844 if (myrpt
->linkposttimer
< 0) myrpt
->linkposttimer
= 0;
11846 if (myrpt
->linkposttimer
<= 0)
11852 myrpt
->linkposttimer
= LINKPOSTTIME
;
11854 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
11856 /* if is not a real link, ignore it */
11857 if (l
->name
[0] == '0') continue;
11858 nstr
+= strlen(l
->name
) + 1;
11860 str
= ast_malloc(nstr
+ 256);
11863 ast_log(LOG_NOTICE
,"Cannot ast_malloc()\n");
11867 strcpy(str
,"nodes=");
11868 for(l
= myrpt
->links
.next
; l
!= &myrpt
->links
; l
= l
->next
)
11870 /* if is not a real link, ignore it */
11871 if (l
->name
[0] == '0') continue;
11873 if (!l
->mode
) lst
= 'R';
11874 if (!l
->thisconnected
) lst
= 'C';
11875 if (nstr
) strcat(str
,",");
11876 sprintf(str
+ strlen(str
),"%c%s",lst
,l
->name
);
11879 p
= strstr(tdesc
, "version");
11882 if(sscanf(p
, "version %d.%d", &vmajor
, &vminor
) == 2)
11883 sprintf(str
+ strlen(str
),"&apprptvers=%d.%d",vmajor
,vminor
);
11886 sprintf(str
+ strlen(str
),"&apprptuptime=%d",(int)(now
-starttime
));
11887 sprintf(str
+ strlen(str
),
11888 "&totalkerchunks=%d&totalkeyups=%d&totaltxtime=%d&timeouts=%d&totalexecdcommands=%d",
11889 myrpt
->totalkerchunks
,myrpt
->totalkeyups
,(int) myrpt
->totaltxtime
/1000,
11890 myrpt
->timeouts
,myrpt
->totalexecdcommands
);
11891 rpt_mutex_unlock(&myrpt
->lock
);
11892 statpost(myrpt
,str
);
11893 rpt_mutex_lock(&myrpt
->lock
);
11896 if (myrpt
->keyposttimer
)
11898 myrpt
->keyposttimer
-= elap
;
11899 if (myrpt
->keyposttimer
< 0) myrpt
->keyposttimer
= 0;
11901 if (myrpt
->keyposttimer
<= 0)
11907 myrpt
->keyposttimer
= KEYPOSTTIME
;
11909 if (myrpt
->lastkeyedtime
)
11911 n
= (int)(now
- myrpt
->lastkeyedtime
);
11913 sprintf(str
,"keyed=%d&keytime=%d",myrpt
->keyed
,n
);
11914 rpt_mutex_unlock(&myrpt
->lock
);
11915 statpost(myrpt
,str
);
11916 rpt_mutex_lock(&myrpt
->lock
);
11919 myrpt
->dailytxtime
+= elap
;
11920 myrpt
->totaltxtime
+= elap
;
11922 i
= myrpt
->tailtimer
;
11923 if (myrpt
->tailtimer
) myrpt
->tailtimer
-= elap
;
11924 if (myrpt
->tailtimer
< 0) myrpt
->tailtimer
= 0;
11925 if((i
) && (myrpt
->tailtimer
== 0))
11926 myrpt
->tailevent
= 1;
11927 if ((!myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
) && myrpt
->totimer
) myrpt
->totimer
-= elap
;
11928 if (myrpt
->totimer
< 0) myrpt
->totimer
= 0;
11929 if (myrpt
->idtimer
) myrpt
->idtimer
-= elap
;
11930 if (myrpt
->idtimer
< 0) myrpt
->idtimer
= 0;
11931 if (myrpt
->tmsgtimer
) myrpt
->tmsgtimer
-= elap
;
11932 if (myrpt
->tmsgtimer
< 0) myrpt
->tmsgtimer
= 0;
11933 if (myrpt
->voxtotimer
) myrpt
->voxtotimer
-= elap
;
11934 if (myrpt
->voxtotimer
< 0) myrpt
->voxtotimer
= 0;
11937 myrpt
->parrottimer
= myrpt
->p
.parrottime
;
11941 if (myrpt
->parrottimer
) myrpt
->parrottimer
-= elap
;
11942 if (myrpt
->parrottimer
< 0) myrpt
->parrottimer
= 0;
11944 /* do macro timers */
11945 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
11946 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
11947 /* do local dtmf timer */
11948 if (myrpt
->dtmf_local_timer
)
11950 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
11951 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
11953 do_dtmf_local(myrpt
,0);
11954 /* Execute scheduler appx. every 2 tenths of a second */
11955 if (myrpt
->skedtimer
<= 0){
11956 myrpt
->skedtimer
= 200;
11957 do_scheduler(myrpt
);
11960 myrpt
->skedtimer
-=elap
;
11963 rpt_mutex_unlock(&myrpt
->lock
);
11966 if (myrpt
->p
.parrotmode
&& (myrpt
->parrotstate
== 1) &&
11967 (myrpt
->parrottimer
<= 0))
11974 /* first put the channel on the conference in announce mode */
11975 if (ioctl(myrpt
->parrotchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
11977 ast_log(LOG_WARNING
, "Unable to set conference mode for parrot\n");
11980 if (myrpt
->parrotstream
)
11981 ast_closestream(myrpt
->parrotstream
);
11982 myrpt
->parrotstream
= NULL
;
11983 myrpt
->parrotstate
= 2;
11984 rpt_telemetry(myrpt
,PARROT
,(struct rpt_link
*) myrpt
->parrotcnt
++);
11986 if (myrpt
->cmdAction
.state
== CMD_STATE_READY
)
11987 { /* there is a command waiting to be processed */
11989 myrpt
->cmdAction
.state
= CMD_STATE_EXECUTING
;
11991 rpt_mutex_unlock(&myrpt
->lock
);
11993 status
= (*function_table
[myrpt
->cmdAction
.functionNumber
].function
)(myrpt
,myrpt
->cmdAction
.param
, myrpt
->cmdAction
.digits
, myrpt
->cmdAction
.command_source
, NULL
);
11994 // get the lock again
11995 rpt_mutex_lock(&myrpt
->lock
);
11996 myrpt
->cmdAction
.state
= CMD_STATE_IDLE
;
11997 } /* if myrpt->cmdAction.state == CMD_STATE_READY */
11999 c
= myrpt
->macrobuf
[0];
12001 if (c
&& (!myrpt
->macrotimer
) &&
12002 starttime
&& (t
> (starttime
+ START_DELAY
)))
12004 char cin
= c
& 0x7f;
12005 myrpt
->macrotimer
= MACROTIME
;
12006 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
12007 if ((cin
== 'p') || (cin
== 'P'))
12008 myrpt
->macrotimer
= MACROPTIME
;
12009 rpt_mutex_unlock(&myrpt
->lock
);
12010 if (myrpt
->p
.archivedir
)
12014 sprintf(str
,"DTMF(M),MAIN,%c",cin
);
12015 donodelog(myrpt
,str
);
12017 local_dtmf_helper(myrpt
,c
);
12018 } else rpt_mutex_unlock(&myrpt
->lock
);
12019 if (who
== myrpt
->rxchannel
) /* if it was a read from rx */
12023 f
= ast_read(myrpt
->rxchannel
);
12026 if (debug
) printf("@@@@ rpt:Hung Up\n");
12029 if (f
->frametype
== AST_FRAME_VOICE
)
12031 #ifdef _MDC_DECODE_H_
12032 unsigned char ubuf
[2560];
12037 if ((!myrpt
->localtx
) && (!myrpt
->p
.linktolink
)) {
12038 memset(f
->data
.ptr
,0,f
->datalen
);
12041 #ifdef _MDC_DECODE_H_
12042 sp
= (short *) f
->data
;
12043 /* convert block to unsigned char */
12044 for(n
= 0; n
< f
->datalen
/ 2; n
++)
12046 ubuf
[n
] = (*sp
++ >> 8) + 128;
12048 n
= mdc_decoder_process_samples(myrpt
->mdc
,ubuf
,f
->datalen
/ 2);
12051 unsigned char op
,arg
;
12052 unsigned short unitID
;
12054 mdc_decoder_get_packet(myrpt
->mdc
,&op
,&arg
,&unitID
);
12057 ast_log(LOG_NOTICE
,"Got (single-length) packet:\n");
12058 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
12059 op
& 255,arg
& 255,unitID
);
12061 if ((op
== 1) && (arg
== 0))
12063 myrpt
->lastunit
= unitID
;
12064 mdc1200_notify(myrpt
,NULL
,myrpt
->lastunit
);
12065 mdc1200_send(myrpt
,myrpt
->lastunit
);
12068 if ((debug
> 2) && (i
== 2))
12070 unsigned char op
,arg
,ex1
,ex2
,ex3
,ex4
;
12071 unsigned short unitID
;
12073 mdc_decoder_get_double_packet(myrpt
->mdc
,&op
,&arg
,&unitID
,
12074 &ex1
,&ex2
,&ex3
,&ex4
);
12075 ast_log(LOG_NOTICE
,"Got (double-length) packet:\n");
12076 ast_log(LOG_NOTICE
,"op: %02x, arg: %02x, UnitID: %04x\n",
12077 op
& 255,arg
& 255,unitID
);
12078 ast_log(LOG_NOTICE
,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
12079 ex1
& 255, ex2
& 255, ex3
& 255, ex4
& 255);
12083 /* apply inbound filters, if any */
12084 rpt_filter(myrpt
,f
->data
,f
->datalen
/ 2);
12086 if (ioctl(myrpt
->dahdirxchannel
->fds
[0], DAHDI_GETCONFMUTE
, &ismuted
) == -1)
12090 if (dtmfed
) ismuted
= 1;
12094 memset(f
->data
.ptr
,0,f
->datalen
);
12096 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
12098 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
12100 if (f
) f2
= ast_frdup(f
);
12102 f1
= myrpt
->lastf2
;
12103 myrpt
->lastf2
= myrpt
->lastf1
;
12104 myrpt
->lastf1
= f2
;
12108 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
12110 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
12114 ast_write(myrpt
->pchannel
,f1
);
12118 #ifndef OLD_ASTERISK
12119 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
12122 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
12124 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
12128 else if (f
->frametype
== AST_FRAME_DTMF
)
12130 c
= (char) f
->subclass
; /* get DTMF char */
12133 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
12135 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
12137 if (!myrpt
->keyed
) continue;
12138 c
= func_xlat(myrpt
,c
,&myrpt
->p
.inxlat
);
12139 if (c
) local_dtmf_helper(myrpt
,c
);
12142 else if (f
->frametype
== AST_FRAME_CONTROL
)
12144 if (f
->subclass
== AST_CONTROL_HANGUP
)
12146 if (debug
) printf("@@@@ rpt:Hung Up\n");
12151 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
12153 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
12155 if (debug
== 7) printf("@@@@ rx key\n");
12157 time(&myrpt
->lastkeyedtime
);
12158 myrpt
->keyposttimer
= KEYPOSTSHORTTIME
;
12160 if (myrpt
->p
.archivedir
)
12162 donodelog(myrpt
,"RXKEY,MAIN");
12164 if (f
->datalen
&& f
->data
.ptr
)
12166 char *val
, busy
= 0;
12168 if (debug
) ast_log(LOG_NOTICE
,"Got PL %s on node %s\n",(char *)f
->data
.ptr
,myrpt
->name
);
12169 // ctcss code autopatch initiate
12170 if (strstr((char *)f
->data
.ptr
,"/M/")&& !myrpt
->macropatch
)
12174 myrpt
->macropatch
=1;
12175 rpt_mutex_lock(&myrpt
->lock
);
12176 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
)){
12177 rpt_mutex_unlock(&myrpt
->lock
);
12181 myrpt
->macrotimer
= MACROTIME
;
12182 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- 1);
12183 if (!busy
) strcpy(myrpt
->lasttone
,(char*)f
->data
.ptr
);
12185 rpt_mutex_unlock(&myrpt
->lock
);
12187 else if (strcmp((char *)f
->data
.ptr
,myrpt
->lasttone
))
12189 val
= (char *) ast_variable_retrieve(myrpt
->cfg
, myrpt
->p
.tonemacro
, (char *)f
->data
.ptr
);
12192 if (debug
) ast_log(LOG_NOTICE
,"Tone %s doing %s on node %s\n",(char *) f
->data
.ptr
,val
,myrpt
->name
);
12193 rpt_mutex_lock(&myrpt
->lock
);
12194 if ((MAXMACRO
- strlen(myrpt
->macrobuf
)) < strlen(val
)){
12195 rpt_mutex_unlock(&myrpt
->lock
);
12199 myrpt
->macrotimer
= MACROTIME
;
12200 strncat(myrpt
->macrobuf
,val
,MAXMACRO
- 1);
12202 rpt_mutex_unlock(&myrpt
->lock
);
12204 if (!busy
) strcpy(myrpt
->lasttone
,(char*)f
->data
.ptr
);
12206 } else myrpt
->lasttone
[0] = 0;
12209 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
12211 if ((!lasttx
) || (myrpt
->p
.duplex
> 1) || (myrpt
->p
.linktolink
))
12213 if (debug
== 7) printf("@@@@ rx un-key\n");
12214 if(myrpt
->p
.duplex
&& myrpt
->keyed
) {
12215 rpt_telemetry(myrpt
,UNKEY
,NULL
);
12219 time(&myrpt
->lastkeyedtime
);
12220 myrpt
->keyposttimer
= KEYPOSTSHORTTIME
;
12221 if (myrpt
->p
.archivedir
)
12223 donodelog(myrpt
,"RXUNKEY,MAIN");
12230 if (who
== myrpt
->pchannel
) /* if it was a read from pseudo */
12232 f
= ast_read(myrpt
->pchannel
);
12235 if (debug
) printf("@@@@ rpt:Hung Up\n");
12238 if (f
->frametype
== AST_FRAME_VOICE
)
12240 ast_write(myrpt
->txpchannel
,f
);
12242 if (f
->frametype
== AST_FRAME_CONTROL
)
12244 if (f
->subclass
== AST_CONTROL_HANGUP
)
12246 if (debug
) printf("@@@@ rpt:Hung Up\n");
12254 if (who
== myrpt
->txchannel
) /* if it was a read from tx */
12256 f
= ast_read(myrpt
->txchannel
);
12259 if (debug
) printf("@@@@ rpt:Hung Up\n");
12262 if (f
->frametype
== AST_FRAME_CONTROL
)
12264 if (f
->subclass
== AST_CONTROL_HANGUP
)
12266 if (debug
) printf("@@@@ rpt:Hung Up\n");
12274 if (who
== myrpt
->dahditxchannel
) /* if it was a read from pseudo-tx */
12276 f
= ast_read(myrpt
->dahditxchannel
);
12279 if (debug
) printf("@@@@ rpt:Hung Up\n");
12282 if (f
->frametype
== AST_FRAME_VOICE
)
12284 struct ast_frame
*f1
;
12286 if (myrpt
->p
.duplex
< 2)
12288 if (myrpt
->txrealkeyed
)
12290 if ((!myfirst
) && myrpt
->callmode
)
12293 AST_LIST_TRAVERSE(&myrpt
->txq
, f1
,
12295 for(;x
< myrpt
->p
.simplexpatchdelay
; x
++)
12298 memset(f1
->data
.ptr
,0,f1
->datalen
);
12299 AST_LIST_INSERT_TAIL(&myrpt
->txq
,f1
,frame_list
);
12304 AST_LIST_INSERT_TAIL(&myrpt
->txq
,
12306 } else myfirst
= 0;
12308 AST_LIST_TRAVERSE(&myrpt
->txq
, f1
,
12312 memset(f
->data
.ptr
,0,f
->datalen
);
12317 f
= AST_LIST_REMOVE_HEAD(&myrpt
->txq
,
12323 while((f1
= AST_LIST_REMOVE_HEAD(&myrpt
->txq
,
12324 frame_list
))) ast_frfree(f1
);
12326 ast_write(myrpt
->txchannel
,f
);
12328 if (f
->frametype
== AST_FRAME_CONTROL
)
12330 if (f
->subclass
== AST_CONTROL_HANGUP
)
12332 if (debug
) printf("@@@@ rpt:Hung Up\n");
12341 rpt_mutex_lock(&myrpt
->lock
);
12342 l
= myrpt
->links
.next
;
12343 while(l
!= &myrpt
->links
)
12346 struct timeval now
;
12355 /* see if any other links are receiving */
12356 m
= myrpt
->links
.next
;
12357 while(m
!= &myrpt
->links
)
12359 /* if not us, count it */
12360 if ((m
!= l
) && (m
->lastrx
)) remrx
= 1;
12363 rpt_mutex_unlock(&myrpt
->lock
);
12365 if ((who
== l
->chan
) || (!l
->lastlinktv
.tv_sec
) ||
12366 (ast_tvdiff_ms(now
,l
->lastlinktv
) >= 19))
12368 l
->lastlinktv
= now
;
12369 remnomute
= myrpt
->localtx
&&
12370 (!(myrpt
->cmdnode
[0] ||
12371 (myrpt
->dtmfidx
> -1)));
12372 totx
= (((l
->isremote
) ? (remnomute
) :
12373 myrpt
->exttx
) || remrx
) && l
->mode
;
12374 if (l
->phonemode
== 0 && l
->chan
&& (l
->lasttx
!= totx
))
12378 ast_indicate(l
->chan
,AST_CONTROL_RADIO_KEY
);
12382 ast_indicate(l
->chan
,AST_CONTROL_RADIO_UNKEY
);
12384 if (myrpt
->p
.archivedir
)
12389 sprintf(str
,"TXKEY,%s",l
->name
);
12391 sprintf(str
,"TXUNKEY,%s",l
->name
);
12392 donodelog(myrpt
,str
);
12397 rpt_mutex_lock(&myrpt
->lock
);
12398 if (who
== l
->chan
) /* if it was a read from rx */
12400 rpt_mutex_unlock(&myrpt
->lock
);
12401 f
= ast_read(l
->chan
);
12404 rpt_mutex_lock(&myrpt
->lock
);
12405 __kickshort(myrpt
);
12406 rpt_mutex_unlock(&myrpt
->lock
);
12407 if ((!l
->disced
) && (!l
->outbound
))
12409 if ((l
->name
[0] == '0') || l
->isremote
)
12412 l
->disctime
= DISC_TIME
;
12413 rpt_mutex_lock(&myrpt
->lock
);
12414 ast_hangup(l
->chan
);
12421 ast_hangup(l
->chan
);
12423 rpt_mutex_lock(&myrpt
->lock
);
12426 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
12428 rpt_mutex_lock(&myrpt
->lock
);
12429 if (l
->chan
) ast_hangup(l
->chan
);
12431 l
->hasconnected
= 1;
12432 l
->retrytimer
= RETRY_TIMER_MS
;
12434 l
->connecttime
= 0;
12435 l
->thisconnected
= 0;
12438 rpt_mutex_lock(&myrpt
->lock
);
12439 /* remove from queue */
12440 remque((struct qelem
*) l
);
12441 if (!strcmp(myrpt
->cmdnode
,l
->name
))
12442 myrpt
->cmdnode
[0] = 0;
12443 __kickshort(myrpt
);
12444 rpt_mutex_unlock(&myrpt
->lock
);
12445 if (!l
->hasconnected
)
12446 rpt_telemetry(myrpt
,CONNFAIL
,l
);
12447 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
12448 if (myrpt
->p
.archivedir
)
12452 if (!l
->hasconnected
)
12453 sprintf(str
,"LINKFAIL,%s",l
->name
);
12455 sprintf(str
,"LINKDISC,%s",l
->name
);
12456 donodelog(myrpt
,str
);
12458 if (l
->lastf1
) ast_frfree(l
->lastf1
);
12460 if (l
->lastf2
) ast_frfree(l
->lastf2
);
12462 /* hang-up on call to device */
12463 ast_hangup(l
->chan
);
12464 ast_hangup(l
->pchan
);
12466 rpt_mutex_lock(&myrpt
->lock
);
12469 if (f
->frametype
== AST_FRAME_VOICE
)
12473 if ((l
->phonemode
) && (l
->phonevox
))
12475 n1
= dovox(&l
->vox
,
12476 f
->data
.ptr
,f
->datalen
/ 2);
12477 if (n1
!= l
->wasvox
)
12479 if (debug
)ast_log(LOG_DEBUG
,"Link Node %s, vox %d\n",l
->name
,n1
);
12482 if (n1
) l
->voxtotimer
= myrpt
->p
.voxtimeout_ms
;
12483 else l
->voxtotimer
= 0;
12485 if (l
->lastrealrx
|| n1
)
12490 AST_LIST_TRAVERSE(&l
->rxq
, f1
,
12492 for(;x
< myrpt
->p
.simplexphonedelay
; x
++)
12495 memset(f1
->data
.ptr
,0,f1
->datalen
);
12496 AST_LIST_INSERT_TAIL(&l
->rxq
,
12502 AST_LIST_INSERT_TAIL(&l
->rxq
,f1
,frame_list
);
12503 } else myfirst
= 0;
12505 AST_LIST_TRAVERSE(&l
->rxq
, f1
,frame_list
) x
++;
12508 memset(f
->data
.ptr
,0,f
->datalen
);
12513 f
= AST_LIST_REMOVE_HEAD(&l
->rxq
,frame_list
);
12515 if (ioctl(l
->chan
->fds
[0], DAHDI_GETCONFMUTE
, &ismuted
) == -1)
12519 /* if not receiving, zero-out audio */
12520 ismuted
|= (!l
->lastrx
);
12521 if (l
->dtmfed
&& l
->phonemode
) ismuted
= 1;
12525 memset(f
->data
.ptr
,0,f
->datalen
);
12527 memset(l
->lastf1
->data
.ptr
,0,l
->lastf1
->datalen
);
12529 memset(l
->lastf2
->data
.ptr
,0,l
->lastf2
->datalen
);
12531 if (f
) f2
= ast_frdup(f
);
12534 l
->lastf2
= l
->lastf1
;
12539 memset(l
->lastf1
->data
.ptr
,0,l
->lastf1
->datalen
);
12541 memset(l
->lastf2
->data
.ptr
,0,l
->lastf2
->datalen
);
12545 ast_write(l
->pchan
,f1
);
12552 memset(f
->data
.ptr
,0,f
->datalen
);
12553 ast_write(l
->pchan
,f
);
12556 #ifndef OLD_ASTERISK
12557 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
12560 memset(l
->lastf1
->data
.ptr
,0,l
->lastf1
->datalen
);
12562 memset(l
->lastf2
->data
.ptr
,0,l
->lastf2
->datalen
);
12566 if (f
->frametype
== AST_FRAME_TEXT
)
12568 handle_link_data(myrpt
,l
,f
->data
.ptr
);
12570 if (f
->frametype
== AST_FRAME_DTMF
)
12573 memset(l
->lastf1
->data
.ptr
,0,l
->lastf1
->datalen
);
12575 memset(l
->lastf2
->data
.ptr
,0,l
->lastf2
->datalen
);
12577 handle_link_phone_dtmf(myrpt
,l
,f
->subclass
);
12579 if (f
->frametype
== AST_FRAME_CONTROL
)
12581 if (f
->subclass
== AST_CONTROL_ANSWER
)
12583 char lconnected
= l
->connected
;
12585 __kickshort(myrpt
);
12587 l
->hasconnected
= 1;
12588 l
->thisconnected
= 1;
12590 if (!l
->phonemode
) send_newkey(l
->chan
);
12591 if (!l
->isremote
) l
->retries
= 0;
12594 rpt_telemetry(myrpt
,CONNECTED
,l
);
12595 if (myrpt
->p
.archivedir
)
12600 sprintf(str
,"LINKTRX,%s",l
->name
);
12602 sprintf(str
,"LINKMONITOR,%s",l
->name
);
12603 donodelog(myrpt
,str
);
12610 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
12612 if (debug
== 7 ) printf("@@@@ rx key\n");
12617 if (myrpt
->p
.archivedir
)
12621 sprintf(str
,"RXKEY,%s",l
->name
);
12622 donodelog(myrpt
,str
);
12628 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
12630 if (debug
== 7) printf("@@@@ rx un-key\n");
12635 if (myrpt
->p
.archivedir
)
12639 sprintf(str
,"RXUNKEY,%s",l
->name
);
12640 donodelog(myrpt
,str
);
12643 if(myrpt
->p
.duplex
)
12644 rpt_telemetry(myrpt
,LINKUNKEY
,l
);
12647 if (f
->subclass
== AST_CONTROL_HANGUP
)
12650 rpt_mutex_lock(&myrpt
->lock
);
12651 __kickshort(myrpt
);
12652 rpt_mutex_unlock(&myrpt
->lock
);
12653 if ((!l
->outbound
) && (!l
->disced
))
12655 if ((l
->name
[0] == '0') || l
->isremote
)
12658 l
->disctime
= DISC_TIME
;
12659 rpt_mutex_lock(&myrpt
->lock
);
12660 ast_hangup(l
->chan
);
12666 if (l
->chan
) ast_hangup(l
->chan
);
12668 rpt_mutex_lock(&myrpt
->lock
);
12671 if (l
->outbound
&& (l
->retries
++ < l
->max_retries
) && (l
->hasconnected
))
12673 rpt_mutex_lock(&myrpt
->lock
);
12674 if (l
->chan
) ast_hangup(l
->chan
);
12676 l
->hasconnected
= 1;
12678 l
->retrytimer
= RETRY_TIMER_MS
;
12679 l
->connecttime
= 0;
12680 l
->thisconnected
= 0;
12683 rpt_mutex_lock(&myrpt
->lock
);
12684 /* remove from queue */
12685 remque((struct qelem
*) l
);
12686 if (!strcmp(myrpt
->cmdnode
,l
->name
))
12687 myrpt
->cmdnode
[0] = 0;
12688 __kickshort(myrpt
);
12689 rpt_mutex_unlock(&myrpt
->lock
);
12690 if (!l
->hasconnected
)
12691 rpt_telemetry(myrpt
,CONNFAIL
,l
);
12692 else if (l
->disced
!= 2) rpt_telemetry(myrpt
,REMDISC
,l
);
12693 if (myrpt
->p
.archivedir
)
12697 if (!l
->hasconnected
)
12698 sprintf(str
,"LINKFAIL,%s",l
->name
);
12700 sprintf(str
,"LINKDISC,%s",l
->name
);
12701 donodelog(myrpt
,str
);
12703 if (l
->lastf1
) ast_frfree(l
->lastf1
);
12705 if (l
->lastf2
) ast_frfree(l
->lastf2
);
12707 /* hang-up on call to device */
12708 ast_hangup(l
->chan
);
12709 ast_hangup(l
->pchan
);
12711 rpt_mutex_lock(&myrpt
->lock
);
12716 rpt_mutex_lock(&myrpt
->lock
);
12719 if (who
== l
->pchan
)
12721 rpt_mutex_unlock(&myrpt
->lock
);
12722 f
= ast_read(l
->pchan
);
12725 if (debug
) printf("@@@@ rpt:Hung Up\n");
12727 rpt_mutex_lock(&myrpt
->lock
);
12730 if (f
->frametype
== AST_FRAME_VOICE
)
12732 if (l
->chan
) ast_write(l
->chan
,f
);
12734 if (f
->frametype
== AST_FRAME_CONTROL
)
12736 if (f
->subclass
== AST_CONTROL_HANGUP
)
12738 if (debug
) printf("@@@@ rpt:Hung Up\n");
12741 rpt_mutex_lock(&myrpt
->lock
);
12746 rpt_mutex_lock(&myrpt
->lock
);
12751 rpt_mutex_unlock(&myrpt
->lock
);
12753 if (who
== myrpt
->monchannel
)
12755 f
= ast_read(myrpt
->monchannel
);
12758 if (debug
) printf("@@@@ rpt:Hung Up\n");
12761 if (f
->frametype
== AST_FRAME_VOICE
)
12763 if (myrpt
->monstream
)
12764 ast_writestream(myrpt
->monstream
,f
);
12766 if (f
->frametype
== AST_FRAME_CONTROL
)
12768 if (f
->subclass
== AST_CONTROL_HANGUP
)
12770 if (debug
) printf("@@@@ rpt:Hung Up\n");
12778 if (myrpt
->parrotchannel
&& (who
== myrpt
->parrotchannel
))
12780 f
= ast_read(myrpt
->parrotchannel
);
12783 if (debug
) printf("@@@@ rpt:Hung Up\n");
12786 if (!myrpt
->p
.parrotmode
)
12790 if (myrpt
->parrotstream
)
12792 ast_closestream(myrpt
->parrotstream
);
12793 myrpt
->parrotstream
= 0;
12795 sprintf(myfname
,PARROTFILE
,myrpt
->name
,myrpt
->parrotcnt
);
12796 strcat(myfname
,".wav");
12798 } else if (f
->frametype
== AST_FRAME_VOICE
)
12800 if (myrpt
->parrotstream
)
12801 ast_writestream(myrpt
->parrotstream
,f
);
12803 if (f
->frametype
== AST_FRAME_CONTROL
)
12805 if (f
->subclass
== AST_CONTROL_HANGUP
)
12807 if (debug
) printf("@@@@ rpt:Hung Up\n");
12815 if (myrpt
->voxchannel
&& (who
== myrpt
->voxchannel
))
12817 f
= ast_read(myrpt
->voxchannel
);
12820 if (debug
) printf("@@@@ rpt:Hung Up\n");
12823 if (f
->frametype
== AST_FRAME_VOICE
)
12825 n
= dovox(&myrpt
->vox
,f
->data
.ptr
,f
->datalen
/ 2);
12826 if (n
!= myrpt
->wasvox
)
12828 if (debug
) ast_log(LOG_DEBUG
,"Node %s, vox %d\n",myrpt
->name
,n
);
12830 myrpt
->voxtostate
= 0;
12831 if (n
) myrpt
->voxtotimer
= myrpt
->p
.voxtimeout_ms
;
12832 else myrpt
->voxtotimer
= 0;
12835 if (f
->frametype
== AST_FRAME_CONTROL
)
12837 if (f
->subclass
== AST_CONTROL_HANGUP
)
12839 if (debug
) printf("@@@@ rpt:Hung Up\n");
12847 if (who
== myrpt
->txpchannel
) /* if it was a read from remote tx */
12849 f
= ast_read(myrpt
->txpchannel
);
12852 if (debug
) printf("@@@@ rpt:Hung Up\n");
12855 if (f
->frametype
== AST_FRAME_CONTROL
)
12857 if (f
->subclass
== AST_CONTROL_HANGUP
)
12859 if (debug
) printf("@@@@ rpt:Hung Up\n");
12869 ast_hangup(myrpt
->pchannel
);
12870 ast_hangup(myrpt
->monchannel
);
12871 if (myrpt
->parrotchannel
) ast_hangup(myrpt
->parrotchannel
);
12872 myrpt
->parrotstate
= 0;
12873 if (myrpt
->voxchannel
) ast_hangup(myrpt
->voxchannel
);
12874 ast_hangup(myrpt
->txpchannel
);
12875 if (myrpt
->txchannel
!= myrpt
->rxchannel
) ast_hangup(myrpt
->txchannel
);
12876 if (myrpt
->dahditxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->dahditxchannel
);
12877 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
12878 myrpt
->lastf1
= NULL
;
12879 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
12880 myrpt
->lastf2
= NULL
;
12881 ast_hangup(myrpt
->rxchannel
);
12882 rpt_mutex_lock(&myrpt
->lock
);
12883 l
= myrpt
->links
.next
;
12884 while(l
!= &myrpt
->links
)
12886 struct rpt_link
*ll
= l
;
12887 /* remove from queue */
12888 remque((struct qelem
*) l
);
12889 /* hang-up on call to device */
12890 if (l
->chan
) ast_hangup(l
->chan
);
12891 ast_hangup(l
->pchan
);
12895 if (myrpt
->xlink
== 1) myrpt
->xlink
= 2;
12896 rpt_mutex_unlock(&myrpt
->lock
);
12897 if (debug
) printf("@@@@ rpt:Hung up channel\n");
12898 myrpt
->rpt_thread
= AST_PTHREADT_STOP
;
12899 pthread_exit(NULL
);
12904 static void *rpt_master(void *ignore
)
12907 pthread_attr_t attr
;
12908 struct ast_config
*cfg
;
12911 /* init nodelog queue */
12912 nodelog
.next
= nodelog
.prev
= &nodelog
;
12913 /* go thru all the specified repeaters */
12916 #ifndef OLD_ASTERISK
12917 /* wait until asterisk starts */
12918 while(!ast_test_flag(&ast_options
,AST_OPT_FLAG_FULLY_BOOTED
))
12921 #ifdef NEW_ASTERISK
12922 rpt_vars
[n
].cfg
= ast_config_load("rpt.conf",config_flags
);
12924 rpt_vars
[n
].cfg
= ast_config_load("rpt.conf");
12926 cfg
= rpt_vars
[n
].cfg
;
12928 ast_log(LOG_NOTICE
, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
12929 pthread_exit(NULL
);
12931 while((this = ast_category_browse(cfg
,this)) != NULL
)
12933 for(i
= 0 ; i
< strlen(this) ; i
++){
12934 if((this[i
] < '0') || (this[i
] > '9'))
12937 if(i
!= strlen(this)) continue; /* Not a node defn */
12938 memset(&rpt_vars
[n
],0,sizeof(rpt_vars
[n
]));
12939 rpt_vars
[n
].name
= ast_strdup(this);
12940 val
= (char *) ast_variable_retrieve(cfg
,this,"rxchannel");
12941 if (val
) rpt_vars
[n
].rxchanname
= ast_strdup(val
);
12942 val
= (char *) ast_variable_retrieve(cfg
,this,"txchannel");
12943 if (val
) rpt_vars
[n
].txchanname
= ast_strdup(val
);
12944 rpt_vars
[n
].remote
= 0;
12945 rpt_vars
[n
].remoterig
= "";
12946 val
= (char *) ast_variable_retrieve(cfg
,this,"remote");
12949 rpt_vars
[n
].remoterig
= ast_strdup(val
);
12950 rpt_vars
[n
].remote
= 1;
12952 val
= (char *) ast_variable_retrieve(cfg
,this,"radiotype");
12953 if (val
) rpt_vars
[n
].remoterig
= ast_strdup(val
);
12954 ast_mutex_init(&rpt_vars
[n
].lock
);
12955 ast_mutex_init(&rpt_vars
[n
].remlock
);
12956 ast_mutex_init(&rpt_vars
[n
].statpost_lock
);
12957 rpt_vars
[n
].tele
.next
= &rpt_vars
[n
].tele
;
12958 rpt_vars
[n
].tele
.prev
= &rpt_vars
[n
].tele
;
12959 rpt_vars
[n
].rpt_thread
= AST_PTHREADT_NULL
;
12960 rpt_vars
[n
].tailmessagen
= 0;
12961 #ifdef _MDC_DECODE_H_
12962 rpt_vars
[n
].mdc
= mdc_decoder_new(8000);
12967 ast_config_destroy(cfg
);
12970 for(i
= 0; i
< n
; i
++)
12972 load_rpt_vars(i
,1);
12974 /* if is a remote, dont start one for it */
12975 if (rpt_vars
[i
].remote
)
12977 if(retreive_memory(&rpt_vars
[i
],"init")){ /* Try to retreive initial memory channel */
12978 if (!strcmp(rpt_vars
[i
].remoterig
,remote_rig_rtx450
))
12979 strncpy(rpt_vars
[i
].freq
, "446.500", sizeof(rpt_vars
[i
].freq
) - 1);
12981 strncpy(rpt_vars
[i
].freq
, "146.580", sizeof(rpt_vars
[i
].freq
) - 1);
12982 strncpy(rpt_vars
[i
].rxpl
, "100.0", sizeof(rpt_vars
[i
].rxpl
) - 1);
12984 strncpy(rpt_vars
[i
].txpl
, "100.0", sizeof(rpt_vars
[i
].txpl
) - 1);
12985 rpt_vars
[i
].remmode
= REM_MODE_FM
;
12986 rpt_vars
[i
].offset
= REM_SIMPLEX
;
12987 rpt_vars
[i
].powerlevel
= REM_LOWPWR
;
12991 else /* is a normal repeater */
12993 rpt_vars
[i
].p
.memory
= rpt_vars
[i
].name
;
12994 if(retreive_memory(&rpt_vars
[i
],"radiofreq")){ /* Try to retreive initial memory channel */
12995 if (!strcmp(rpt_vars
[i
].remoterig
,remote_rig_rtx450
))
12996 strncpy(rpt_vars
[i
].freq
, "446.500", sizeof(rpt_vars
[i
].freq
) - 1);
12997 else if (!strcmp(rpt_vars
[i
].remoterig
,remote_rig_rtx150
))
12998 strncpy(rpt_vars
[i
].freq
, "146.580", sizeof(rpt_vars
[i
].freq
) - 1);
12999 strncpy(rpt_vars
[i
].rxpl
, "100.0", sizeof(rpt_vars
[i
].rxpl
) - 1);
13001 strncpy(rpt_vars
[i
].txpl
, "100.0", sizeof(rpt_vars
[i
].txpl
) - 1);
13002 rpt_vars
[i
].remmode
= REM_MODE_FM
;
13003 rpt_vars
[i
].offset
= REM_SIMPLEX
;
13004 rpt_vars
[i
].powerlevel
= REM_LOWPWR
;
13006 ast_log(LOG_NOTICE
,"Normal Repeater Init %s %s %s\n",rpt_vars
[i
].name
, rpt_vars
[i
].remoterig
, rpt_vars
[i
].freq
);
13008 if (!rpt_vars
[i
].p
.ident
)
13010 ast_log(LOG_WARNING
,"Did not specify ident for node %s\n",rpt_vars
[i
].name
);
13011 ast_config_destroy(cfg
);
13012 pthread_exit(NULL
);
13014 pthread_attr_init(&attr
);
13015 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
13016 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
13022 /* Now monitor each thread, and restart it if necessary */
13023 for(i
= 0; i
< n
; i
++)
13026 if (rpt_vars
[i
].remote
) continue;
13027 if (rpt_vars
[i
].rpt_thread
== AST_PTHREADT_STOP
)
13030 rv
= pthread_kill(rpt_vars
[i
].rpt_thread
,0);
13033 if(time(NULL
) - rpt_vars
[i
].lastthreadrestarttime
<= 15)
13035 if(rpt_vars
[i
].threadrestarts
>= 5)
13037 ast_log(LOG_ERROR
,"Continual RPT thread restarts, killing Asterisk\n");
13038 exit(1); /* Stuck in a restart loop, kill Asterisk and start over */
13042 ast_log(LOG_NOTICE
,"RPT thread restarted on %s\n",rpt_vars
[i
].name
);
13043 rpt_vars
[i
].threadrestarts
++;
13047 rpt_vars
[i
].threadrestarts
= 0;
13049 rpt_vars
[i
].lastthreadrestarttime
= time(NULL
);
13050 pthread_attr_init(&attr
);
13051 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
13052 ast_pthread_create(&rpt_vars
[i
].rpt_thread
,&attr
,rpt
,(void *) &rpt_vars
[i
]);
13053 /* if (!rpt_vars[i].xlink) */
13054 ast_log(LOG_WARNING
, "rpt_thread restarted on node %s\n", rpt_vars
[i
].name
);
13060 struct nodelog
*nodep
;
13061 char *space
,datestr
[100],fname
[300];
13064 ast_mutex_lock(&nodeloglock
);
13065 nodep
= nodelog
.next
;
13066 if(nodep
== &nodelog
) /* if nothing in queue */
13068 ast_mutex_unlock(&nodeloglock
);
13071 remque((struct qelem
*)nodep
);
13072 ast_mutex_unlock(&nodeloglock
);
13073 space
= strchr(nodep
->str
,' ');
13080 strftime(datestr
,sizeof(datestr
) - 1,"%Y%m%d",
13081 localtime(&nodep
->timestamp
));
13082 sprintf(fname
,"%s/%s/%s.txt",nodep
->archivedir
,
13083 nodep
->str
,datestr
);
13084 fd
= open(fname
,O_WRONLY
| O_CREAT
| O_APPEND
,0600);
13087 ast_log(LOG_ERROR
,"Cannot open node log file %s for write",space
+ 1);
13091 if (write(fd
,space
+ 1,strlen(space
+ 1)) !=
13094 ast_log(LOG_ERROR
,"Cannot write node log file %s for write",space
+ 1);
13103 ast_config_destroy(cfg
);
13104 pthread_exit(NULL
);
13107 static int rpt_exec(struct ast_channel
*chan
, void *data
)
13109 int res
=-1,i
,rem_totx
,rem_rx
,remkeyed
,n
,phone_mode
= 0;
13110 int iskenwood_pci4
,authtold
,authreq
,setting
,notremming
,reming
;
13111 int ismuted
,dtmfed
,phone_vox
= 0;
13112 #ifdef OLD_ASTERISK
13113 struct localuser
*u
;
13115 char tmp
[256], keyed
= 0,keyed1
= 0;
13116 char *options
,*stringp
,*tele
,c
,*altp
,*memp
;
13119 struct ast_frame
*f
,*f1
,*f2
;
13120 struct ast_channel
*who
;
13121 struct ast_channel
*cs
[20];
13122 struct rpt_link
*l
;
13123 DAHDI_CONFINFO ci
; /* conference info */
13125 int ms
,elap
,nullfd
;
13126 time_t t
,last_timeout_warning
;
13127 struct dahdi_radio_param z
;
13128 struct rpt_tele
*telem
;
13131 nullfd
= open("/dev/null",O_RDWR
);
13132 if (ast_strlen_zero(data
)) {
13133 ast_log(LOG_WARNING
, "Rpt requires an argument (system node)\n");
13137 strncpy(tmp
, (char *)data
, sizeof(tmp
)-1);
13139 /* if time has externally shifted negative, screw it */
13140 if (t
< starttime
) t
= starttime
+ START_DELAY
;
13141 if ((!starttime
) || (t
< (starttime
+ START_DELAY
)))
13143 ast_log(LOG_NOTICE
,"Node %s rejecting call: too soon!\n",tmp
);
13144 ast_safe_sleep(chan
,3000);
13148 ast_log(LOG_NOTICE
,"parsing argument=%s \n",tmp
);
13150 altp
=strstr(tmp
, "|*");
13156 memp
=strstr(tmp
, "|M");
13163 strsep(&stringp
, "|");
13166 ast_log(LOG_NOTICE
,"options=%s \n",options
);
13167 if(memp
>0)ast_log(LOG_NOTICE
,"memp=%s \n",memp
);
13168 if(altp
>0)ast_log(LOG_NOTICE
,"altp=%s \n",altp
);
13171 /* see if we can find our specified one */
13172 for(i
= 0; i
< nrpts
; i
++)
13174 /* if name matches, assign it and exit loop */
13175 if (!strcmp(tmp
,rpt_vars
[i
].name
))
13177 myrpt
= &rpt_vars
[i
];
13182 pbx_builtin_setvar_helper(chan
, "RPT_STAT_ERR", "");
13186 pbx_builtin_setvar_helper(chan
, "RPT_STAT_ERR", "NODE_NOT_FOUND");
13187 ast_log(LOG_WARNING
, "Cannot find specified system node %s\n",tmp
);
13188 return (priority_jump(NULL
,chan
));
13191 numlinks
=linkcount(myrpt
);
13193 if(options
&& *options
== 'q')
13199 pbx_builtin_setvar_helper(chan
, "RPT_STAT_RXKEYED", "1");
13201 pbx_builtin_setvar_helper(chan
, "RPT_STAT_RXKEYED", "0");
13204 pbx_builtin_setvar_helper(chan
, "RPT_STAT_TXKEYED", "1");
13206 pbx_builtin_setvar_helper(chan
, "RPT_STAT_TXKEYED", "0");
13208 snprintf(buf2
,sizeof(buf2
),"%s=%i", "RPT_STAT_XLINK", myrpt
->xlink
);
13209 pbx_builtin_setvar(chan
, buf2
);
13210 snprintf(buf2
,sizeof(buf2
),"%s=%i", "RPT_STAT_LINKS", numlinks
);
13211 pbx_builtin_setvar(chan
, buf2
);
13212 snprintf(buf2
,sizeof(buf2
),"%s=%d", "RPT_STAT_WASCHAN", myrpt
->waschan
);
13213 pbx_builtin_setvar(chan
, buf2
);
13214 snprintf(buf2
,sizeof(buf2
),"%s=%d", "RPT_STAT_NOWCHAN", myrpt
->nowchan
);
13215 pbx_builtin_setvar(chan
, buf2
);
13216 snprintf(buf2
,sizeof(buf2
),"%s=%d", "RPT_STAT_DUPLEX", myrpt
->p
.duplex
);
13217 pbx_builtin_setvar(chan
, buf2
);
13218 snprintf(buf2
,sizeof(buf2
),"%s=%d", "RPT_STAT_PARROT", myrpt
->p
.parrotmode
);
13219 pbx_builtin_setvar(chan
, buf2
);
13220 //snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_PHONEVOX", myrpt->phonevox);
13221 //pbx_builtin_setvar(chan, buf2);
13222 //snprintf(buf2,sizeof(buf2),"%s=%d", "RPT_STAT_CONNECTED", myrpt->connected);
13223 //pbx_builtin_setvar(chan, buf2);
13224 snprintf(buf2
,sizeof(buf2
),"%s=%d", "RPT_STAT_CALLMODE", myrpt
->callmode
);
13225 pbx_builtin_setvar(chan
, buf2
);
13226 snprintf(buf2
,sizeof(buf2
),"%s=%s", "RPT_STAT_LASTTONE", myrpt
->lasttone
);
13227 pbx_builtin_setvar(chan
, buf2
);
13229 res
=priority_jump(myrpt
,chan
);
13233 if(options
&& *options
== 'o')
13235 return(channel_revert(myrpt
));
13239 if((altp
)&&(*options
== 'Z'))
13241 rpt_push_alt_macro(myrpt
,altp
);
13247 /* if not phone access, must be an IAX connection */
13248 if (options
&& ((*options
== 'P') || (*options
== 'D') || (*options
== 'R') || (*options
== 'S')))
13252 pbx_builtin_setvar_helper(chan
, "RPT_STAT_BUSY", "0");
13254 myrpt
->bargechan
=0;
13255 if(options
&& strstr(options
, "f")>0)
13257 myrpt
->bargechan
=1;
13263 radiochan
=strtod(data
,NULL
);
13264 // if(myrpt->nowchan!=0 && radiochan!=myrpt->nowchan && !myrpt->bargechan)
13266 if(numlinks
>0 && radiochan
!=myrpt
->nowchan
&& !myrpt
->bargechan
)
13268 pbx_builtin_setvar_helper(chan
, "RPT_STAT_BUSY", "1");
13269 ast_log(LOG_NOTICE
, "Radio Channel Busy.\n");
13270 return (priority_jump(myrpt
,chan
));
13272 else if(radiochan
!=myrpt
->nowchan
|| myrpt
->bargechan
)
13274 channel_steer(myrpt
,memp
);
13277 if(altp
)rpt_push_alt_macro(myrpt
,altp
);
13279 if (*options
== 'D') phone_mode
= 2;
13280 if (*options
== 'S') phone_mode
= 3;
13281 ast_set_callerid(chan
,"0","app_rpt user","0");
13283 ast_channel_setoption(chan
,AST_OPTION_TONE_VERIFY
,&val
,sizeof(char),0);
13284 if ((*(options
+ 1) == 'V') || (*(options
+ 1) == 'v')) phone_vox
= 1;
13288 #ifdef ALLOW_LOCAL_CHANNELS
13289 /* Check to insure the connection is IAX2 or Local*/
13290 if ( (strncmp(chan
->name
,"IAX2",4)) && (strncmp(chan
->name
,"Local",5)) ) {
13291 ast_log(LOG_WARNING
, "We only accept links via IAX2 or Local!!\n");
13295 if (strncmp(chan
->name
,"IAX2",4))
13297 ast_log(LOG_WARNING
, "We only accept links via IAX2!!\n");
13301 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
){ /* Do not allow incoming radio connections if disabled */
13302 ast_log(LOG_NOTICE
, "Connect attempt to node %s with tx disabled", myrpt
->name
);
13306 if (options
&& (*options
== 'R'))
13308 /* Parts of this section taken from app_parkandannounce */
13309 char *return_context
;
13310 int l
, m
, lot
, timeout
= 0;
13311 char tmp
[256],*template;
13312 char *working
, *context
, *exten
, *priority
;
13315 rpt_mutex_lock(&myrpt
->lock
);
13316 m
= myrpt
->callmode
;
13317 rpt_mutex_unlock(&myrpt
->lock
);
13319 if ((!myrpt
->p
.nobusyout
) && m
)
13321 if (chan
->_state
!= AST_STATE_UP
)
13323 ast_indicate(chan
,AST_CONTROL_BUSY
);
13325 while(ast_safe_sleep(chan
,10000) != -1);
13329 if (chan
->_state
!= AST_STATE_UP
)
13332 if (!phone_mode
) send_newkey(chan
);
13335 l
=strlen(options
)+2;
13336 orig_s
=ast_malloc(l
);
13338 ast_log(LOG_WARNING
, "Out of memory\n");
13342 strncpy(s
,options
,l
);
13344 template=strsep(&s
,"|");
13346 ast_log(LOG_WARNING
, "An announce template must be defined\n");
13352 timeout
= atoi(strsep(&s
, "|"));
13356 return_context
= s
;
13358 if(return_context
!= NULL
) {
13359 /* set the return context. Code borrowed from the Goto builtin */
13361 working
= return_context
;
13362 context
= strsep(&working
, "|");
13363 exten
= strsep(&working
, "|");
13365 /* Only a priority in this one */
13366 priority
= context
;
13370 priority
= strsep(&working
, "|");
13372 /* Only an extension and priority in this one */
13378 if(atoi(priority
) < 0) {
13379 ast_log(LOG_WARNING
, "Priority '%s' must be a number > 0\n", priority
);
13383 /* At this point we have a priority and maybe an extension and a context */
13384 chan
->priority
= atoi(priority
);
13385 #ifdef OLD_ASTERISK
13386 if(exten
&& strcasecmp(exten
, "BYEXTENSION"))
13390 strncpy(chan
->exten
, exten
, sizeof(chan
->exten
)-1);
13392 strncpy(chan
->context
, context
, sizeof(chan
->context
)-1);
13393 } else { /* increment the priority by default*/
13397 if(option_verbose
> 2) {
13398 ast_verbose( VERBOSE_PREFIX_3
"Return Context: (%s,%s,%d) ID: %s\n", chan
->context
,chan
->exten
, chan
->priority
, chan
->cid
.cid_num
);
13399 if(!ast_exists_extension(chan
, chan
->context
, chan
->exten
, chan
->priority
, chan
->cid
.cid_num
)) {
13400 ast_verbose( VERBOSE_PREFIX_3
"Warning: Return Context Invalid, call will return to default|s\n");
13404 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
13405 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
13407 ast_masq_park_call(chan
, NULL
, timeout
, &lot
);
13409 if (option_verbose
> 2) ast_verbose( VERBOSE_PREFIX_3
"Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot
, timeout
, return_context
);
13411 snprintf(tmp
,sizeof(tmp
) - 1,"%d,%s",lot
,template + 1);
13413 rpt_telemetry(myrpt
,REV_PATCH
,tmp
);
13423 struct ast_hostent ahp
;
13424 struct hostent
*hp
;
13426 char hisip
[100],nodeip
[100],*val
, *s
, *s1
, *s2
, *s3
, *b
,*b1
;
13428 /* look at callerid to see what node this comes from */
13429 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
13431 ast_log(LOG_WARNING
, "Does not have callerid on %s\n",tmp
);
13434 /* get his IP from IAX2 module */
13435 memset(hisip
,0,sizeof(hisip
));
13436 #ifdef ALLOW_LOCAL_CHANNELS
13437 /* set IP address if this is a local connection*/
13438 if (strncmp(chan
->name
,"Local",5)==0) {
13439 strcpy(hisip
,"127.0.0.1");
13441 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
13444 pbx_substitute_variables_helper(chan
,"${IAXPEER(CURRENTCHANNEL)}",hisip
,sizeof(hisip
) - 1);
13449 ast_log(LOG_WARNING
, "Link IP address cannot be determined!!\n");
13453 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
13454 ast_shrink_phone_number(b1
);
13455 if (!strcmp(myrpt
->name
,b1
))
13457 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
13463 ast_log(LOG_WARNING
, "Node %s Invalid for connection here!!\n",b1
);
13468 /* look for his reported node string */
13469 val
= node_lookup(myrpt
,b1
);
13472 ast_log(LOG_WARNING
, "Reported node %s cannot be found!!\n",b1
);
13475 strncpy(tmp
,val
,sizeof(tmp
) - 1);
13477 s1
= strsep(&s
,",");
13478 if (!strchr(s1
,':') && strchr(s1
,'/') && strncasecmp(s1
, "local/", 6))
13480 sy
= strchr(s1
,'/');
13482 sprintf(sx
,"%s:4569/%s",s1
,sy
+ 1);
13485 s2
= strsep(&s
,",");
13488 ast_log(LOG_WARNING
, "Reported node %s not in correct format!!\n",b1
);
13491 if (strcmp(s2
,"NONE")) {
13492 hp
= ast_gethostbyname(s2
, &ahp
);
13495 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s2
);
13498 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
13499 #ifdef OLD_ASTERISK
13500 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
13502 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
13504 s3
= strchr(hisip
,':');
13506 if (strcmp(hisip
,nodeip
))
13508 s3
= strchr(s1
,'@');
13509 if (s3
) s1
= s3
+ 1;
13510 s3
= strchr(s1
,'/');
13512 s3
= strchr(s1
,':');
13514 hp
= ast_gethostbyname(s1
, &ahp
);
13517 ast_log(LOG_WARNING
, "Reported node %s, name %s cannot be found!!\n",b1
,s1
);
13520 memcpy(&ia
,hp
->h_addr
,sizeof(in_addr_t
));
13521 #ifdef OLD_ASTERISK
13522 ast_inet_ntoa(nodeip
,sizeof(nodeip
) - 1,ia
);
13524 strncpy(nodeip
,ast_inet_ntoa(ia
),sizeof(nodeip
) - 1);
13526 if (strcmp(hisip
,nodeip
))
13528 ast_log(LOG_WARNING
, "Node %s IP %s does not match link IP %s!!\n",b1
,nodeip
,hisip
);
13535 /* if is not a remote */
13536 if (!myrpt
->remote
)
13539 int reconnects
= 0;
13541 rpt_mutex_lock(&myrpt
->lock
);
13543 rpt_mutex_unlock(&myrpt
->lock
);
13546 ast_log(LOG_WARNING
, "Cannot connect to node %s, system busy\n",myrpt
->name
);
13549 /* look at callerid to see what node this comes from */
13550 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
13552 ast_log(LOG_WARNING
, "Doesnt have callerid on %s\n",tmp
);
13556 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
13557 ast_shrink_phone_number(b1
);
13558 if (!strcmp(myrpt
->name
,b1
))
13560 ast_log(LOG_WARNING
, "Trying to link to self!!\n");
13563 rpt_mutex_lock(&myrpt
->lock
);
13564 l
= myrpt
->links
.next
;
13565 /* try to find this one in queue */
13566 while(l
!= &myrpt
->links
)
13568 if (l
->name
[0] == '0')
13573 /* if found matching string */
13574 if (!strcmp(l
->name
,b1
)) break;
13578 if (l
!= &myrpt
->links
)
13581 l
->retries
= l
->max_retries
+ 1;
13583 reconnects
= l
->reconnects
;
13585 rpt_mutex_unlock(&myrpt
->lock
);
13588 rpt_mutex_unlock(&myrpt
->lock
);
13589 /* establish call in tranceive mode */
13590 l
= ast_malloc(sizeof(struct rpt_link
));
13593 ast_log(LOG_WARNING
, "Unable to malloc\n");
13594 pthread_exit(NULL
);
13596 /* zero the silly thing */
13597 memset((char *)l
,0,sizeof(struct rpt_link
));
13599 strncpy(l
->name
,b1
,MAXNODESTR
- 1);
13603 l
->thisconnected
= 1;
13604 l
->hasconnected
= 1;
13605 l
->reconnects
= reconnects
;
13606 l
->phonemode
= phone_mode
;
13607 l
->phonevox
= phone_vox
;
13612 ast_set_read_format(l
->chan
,AST_FORMAT_SLINEAR
);
13613 ast_set_write_format(l
->chan
,AST_FORMAT_SLINEAR
);
13614 /* allocate a pseudo-channel thru asterisk */
13615 l
->pchan
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
13618 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
13619 pthread_exit(NULL
);
13621 ast_set_read_format(l
->pchan
,AST_FORMAT_SLINEAR
);
13622 ast_set_write_format(l
->pchan
,AST_FORMAT_SLINEAR
);
13623 #ifdef AST_CDR_FLAG_POST_DISABLED
13625 ast_set_flag(l
->pchan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13627 /* make a conference for the tx */
13629 ci
.confno
= myrpt
->conf
;
13630 ci
.confmode
= DAHDI_CONF_CONF
| DAHDI_CONF_LISTENER
| DAHDI_CONF_TALKER
;
13631 /* first put the channel on the conference in proper mode */
13632 if (ioctl(l
->pchan
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
13634 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
13635 pthread_exit(NULL
);
13637 rpt_mutex_lock(&myrpt
->lock
);
13638 if ((phone_mode
== 2) && (!phone_vox
)) l
->lastrealrx
= 1;
13639 l
->max_retries
= MAX_RETRIES
;
13640 /* insert at end of queue */
13641 insque((struct qelem
*)l
,(struct qelem
*)myrpt
->links
.next
);
13642 __kickshort(myrpt
);
13643 rpt_mutex_unlock(&myrpt
->lock
);
13644 if (chan
->_state
!= AST_STATE_UP
) {
13646 if (!phone_mode
) send_newkey(chan
);
13648 if (myrpt
->p
.archivedir
)
13653 sprintf(str
,"LINK(P),%s",l
->name
);
13655 sprintf(str
,"LINK,%s",l
->name
);
13656 donodelog(myrpt
,str
);
13658 if (!phone_mode
) send_newkey(chan
);
13659 return AST_PBX_KEEPALIVE
;
13661 /* well, then it is a remote */
13662 rpt_mutex_lock(&myrpt
->lock
);
13663 /* if remote, error if anyone else already linked */
13664 if (myrpt
->remoteon
)
13666 rpt_mutex_unlock(&myrpt
->lock
);
13668 if (myrpt
->remoteon
)
13670 ast_log(LOG_WARNING
, "Trying to use busy link on %s\n",tmp
);
13671 #ifdef AST_CDR_FLAG_POST_DISABLED
13673 ast_set_flag(chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13677 rpt_mutex_lock(&myrpt
->lock
);
13679 if (myrpt
->p
.rptnode
)
13685 for(i
= 0; i
< nrpts
; i
++)
13687 if (!strcasecmp(rpt_vars
[i
].name
,myrpt
->p
.rptnode
))
13689 if ((rpt_vars
[i
].links
.next
!= &rpt_vars
[i
].links
) ||
13690 rpt_vars
[i
].keyed
||
13691 ((rpt_vars
[i
].lastkeyedtime
+ RPT_LOCKOUT_SECS
) > now
) ||
13692 rpt_vars
[i
].txkeyed
||
13693 ((rpt_vars
[i
].lasttxkeyedtime
+ RPT_LOCKOUT_SECS
) > now
))
13695 rpt_mutex_unlock(&myrpt
->lock
);
13696 ast_log(LOG_WARNING
, "Trying to use busy link (repeater node %s) on %s\n",rpt_vars
[i
].name
,tmp
);
13697 #ifdef AST_CDR_FLAG_POST_DISABLED
13699 ast_set_flag(chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13703 while(rpt_vars
[i
].xlink
!= 3)
13707 ast_softhangup(rpt_vars
[i
].rxchannel
,AST_SOFTHANGUP_DEV
);
13708 rpt_vars
[i
].xlink
= 1;
13711 rpt_mutex_unlock(&myrpt
->lock
);
13712 if (ast_safe_sleep(chan
,500) == -1)
13714 #ifdef AST_CDR_FLAG_POST_DISABLED
13716 ast_set_flag(chan
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13720 rpt_mutex_lock(&myrpt
->lock
);
13727 if ( (!strcmp(myrpt
->remoterig
, remote_rig_rbi
)||!strcmp(myrpt
->remoterig
, remote_rig_ppp16
)) &&
13728 (ioperm(myrpt
->p
.iobase
,1,1) == -1))
13730 rpt_mutex_unlock(&myrpt
->lock
);
13731 ast_log(LOG_WARNING
, "Can't get io permission on IO port %x hex\n",myrpt
->p
.iobase
);
13734 myrpt
->remoteon
= 1;
13735 #ifdef OLD_ASTERISK
13738 rpt_mutex_unlock(&myrpt
->lock
);
13739 /* find our index, and load the vars initially */
13740 for(i
= 0; i
< nrpts
; i
++)
13742 if (&rpt_vars
[i
] == myrpt
)
13744 load_rpt_vars(i
,0);
13748 rpt_mutex_lock(&myrpt
->lock
);
13749 tele
= strchr(myrpt
->rxchanname
,'/');
13752 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
13753 rpt_mutex_unlock(&myrpt
->lock
);
13754 pthread_exit(NULL
);
13757 myrpt
->rxchannel
= ast_request(myrpt
->rxchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
13758 myrpt
->dahdirxchannel
= NULL
;
13759 if (!strcasecmp(myrpt
->rxchanname
,"DAHDI"))
13760 myrpt
->dahdirxchannel
= myrpt
->rxchannel
;
13761 if (myrpt
->rxchannel
)
13763 ast_set_read_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
13764 ast_set_write_format(myrpt
->rxchannel
,AST_FORMAT_SLINEAR
);
13765 #ifdef AST_CDR_FLAG_POST_DISABLED
13766 if (myrpt
->rxchannel
->cdr
)
13767 ast_set_flag(myrpt
->rxchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13769 #ifndef NEW_ASTERISK
13770 myrpt
->rxchannel
->whentohangup
= 0;
13772 myrpt
->rxchannel
->appl
= "Apprpt";
13773 myrpt
->rxchannel
->data
= "(Link Rx)";
13774 if (option_verbose
> 2)
13775 ast_verbose(VERBOSE_PREFIX_3
"rpt (Rx) initiating call to %s/%s on %s\n",
13776 myrpt
->rxchanname
,tele
,myrpt
->rxchannel
->name
);
13777 rpt_mutex_unlock(&myrpt
->lock
);
13778 ast_call(myrpt
->rxchannel
,tele
,999);
13779 rpt_mutex_lock(&myrpt
->lock
);
13783 fprintf(stderr
,"rpt:Sorry unable to obtain Rx channel\n");
13784 rpt_mutex_unlock(&myrpt
->lock
);
13785 pthread_exit(NULL
);
13788 myrpt
->dahditxchannel
= NULL
;
13789 if (myrpt
->txchanname
)
13791 tele
= strchr(myrpt
->txchanname
,'/');
13794 fprintf(stderr
,"rpt:Dial number must be in format tech/number\n");
13795 rpt_mutex_unlock(&myrpt
->lock
);
13796 ast_hangup(myrpt
->rxchannel
);
13797 pthread_exit(NULL
);
13800 myrpt
->txchannel
= ast_request(myrpt
->txchanname
,AST_FORMAT_SLINEAR
,tele
,NULL
);
13801 if (!strncasecmp(myrpt
->txchanname
,"DAHDI",3))
13802 myrpt
->dahditxchannel
= myrpt
->txchannel
;
13803 if (myrpt
->txchannel
)
13805 ast_set_read_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
13806 ast_set_write_format(myrpt
->txchannel
,AST_FORMAT_SLINEAR
);
13807 #ifdef AST_CDR_FLAG_POST_DISABLED
13808 if (myrpt
->txchannel
->cdr
)
13809 ast_set_flag(myrpt
->txchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13811 #ifndef NEW_ASTERISK
13812 myrpt
->txchannel
->whentohangup
= 0;
13814 myrpt
->txchannel
->appl
= "Apprpt";
13815 myrpt
->txchannel
->data
= "(Link Tx)";
13816 if (option_verbose
> 2)
13817 ast_verbose(VERBOSE_PREFIX_3
"rpt (Tx) initiating call to %s/%s on %s\n",
13818 myrpt
->txchanname
,tele
,myrpt
->txchannel
->name
);
13819 rpt_mutex_unlock(&myrpt
->lock
);
13820 ast_call(myrpt
->txchannel
,tele
,999);
13821 rpt_mutex_lock(&myrpt
->lock
);
13825 fprintf(stderr
,"rpt:Sorry unable to obtain Tx channel\n");
13826 rpt_mutex_unlock(&myrpt
->lock
);
13827 ast_hangup(myrpt
->rxchannel
);
13828 pthread_exit(NULL
);
13834 myrpt
->txchannel
= myrpt
->rxchannel
;
13835 if (!strncasecmp(myrpt
->rxchanname
,"DAHDI",3))
13836 myrpt
->dahditxchannel
= myrpt
->rxchannel
;
13838 /* allocate a pseudo-channel thru asterisk */
13839 myrpt
->pchannel
= ast_request("DAHDI",AST_FORMAT_SLINEAR
,"pseudo",NULL
);
13840 if (!myrpt
->pchannel
)
13842 fprintf(stderr
,"rpt:Sorry unable to obtain pseudo channel\n");
13843 rpt_mutex_unlock(&myrpt
->lock
);
13844 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
13845 ast_hangup(myrpt
->txchannel
);
13846 ast_hangup(myrpt
->rxchannel
);
13847 pthread_exit(NULL
);
13849 ast_set_read_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
13850 ast_set_write_format(myrpt
->pchannel
,AST_FORMAT_SLINEAR
);
13851 #ifdef AST_CDR_FLAG_POST_DISABLED
13852 if (myrpt
->pchannel
->cdr
)
13853 ast_set_flag(myrpt
->pchannel
->cdr
,AST_CDR_FLAG_POST_DISABLED
);
13855 if (!myrpt
->dahdirxchannel
) myrpt
->dahdirxchannel
= myrpt
->pchannel
;
13856 if (!myrpt
->dahditxchannel
) myrpt
->dahditxchannel
= myrpt
->pchannel
;
13857 /* make a conference for the pseudo */
13859 ci
.confno
= -1; /* make a new conf */
13860 ci
.confmode
= DAHDI_CONF_CONFANNMON
;
13861 /* first put the channel on the conference in announce/monitor mode */
13862 if (ioctl(myrpt
->pchannel
->fds
[0],DAHDI_SETCONF
,&ci
) == -1)
13864 ast_log(LOG_WARNING
, "Unable to set conference mode to Announce\n");
13865 rpt_mutex_unlock(&myrpt
->lock
);
13866 ast_hangup(myrpt
->pchannel
);
13867 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
13868 ast_hangup(myrpt
->txchannel
);
13869 ast_hangup(myrpt
->rxchannel
);
13870 pthread_exit(NULL
);
13872 /* save pseudo channel conference number */
13873 myrpt
->conf
= myrpt
->txconf
= ci
.confno
;
13874 /* if serial io port, open it */
13876 if (myrpt
->p
.ioport
&& ((myrpt
->iofd
= openserial(myrpt
,myrpt
->p
.ioport
)) == -1))
13878 rpt_mutex_unlock(&myrpt
->lock
);
13879 ast_hangup(myrpt
->pchannel
);
13880 if (myrpt
->txchannel
!= myrpt
->rxchannel
)
13881 ast_hangup(myrpt
->txchannel
);
13882 ast_hangup(myrpt
->rxchannel
);
13883 pthread_exit(NULL
);
13885 iskenwood_pci4
= 0;
13886 memset(&z
,0,sizeof(z
));
13887 if ((myrpt
->iofd
< 1) && (myrpt
->txchannel
== myrpt
->dahditxchannel
))
13889 z
.radpar
= DAHDI_RADPAR_REMMODE
;
13890 z
.data
= DAHDI_RADPAR_REM_NONE
;
13891 res
= ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
);
13892 /* if PCIRADIO and kenwood selected */
13893 if ((!res
) && (!strcmp(myrpt
->remoterig
,remote_rig_kenwood
)))
13895 z
.radpar
= DAHDI_RADPAR_UIOMODE
;
13897 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
13899 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
13902 z
.radpar
= DAHDI_RADPAR_UIODATA
;
13904 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
13906 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
13910 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1)
13912 ast_log(LOG_ERROR
,"Cannot set hook\n");
13915 iskenwood_pci4
= 1;
13918 if (myrpt
->txchannel
== myrpt
->dahditxchannel
)
13921 ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_HOOK
,&i
);
13922 /* if PCIRADIO and Yaesu ft897/ICOM IC-706 selected */
13923 if ((myrpt
->iofd
< 1) && (!res
) &&
13924 ((!strcmp(myrpt
->remoterig
,remote_rig_ft897
)) ||
13925 (!strcmp(myrpt
->remoterig
,remote_rig_ic706
)) ||
13926 (!strcmp(myrpt
->remoterig
,remote_rig_tm271
))))
13928 z
.radpar
= DAHDI_RADPAR_UIOMODE
;
13930 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
13932 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
13935 z
.radpar
= DAHDI_RADPAR_UIODATA
;
13937 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
13939 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
13944 myrpt
->remoterx
= 0;
13945 myrpt
->remotetx
= 0;
13946 myrpt
->retxtimer
= 0;
13947 myrpt
->rerxtimer
= 0;
13948 myrpt
->remoteon
= 1;
13949 myrpt
->dtmfidx
= -1;
13950 myrpt
->dtmfbuf
[0] = 0;
13951 myrpt
->dtmf_time_rem
= 0;
13952 myrpt
->hfscanmode
= 0;
13953 myrpt
->hfscanstatus
= 0;
13954 if (myrpt
->p
.startupmacro
)
13956 snprintf(myrpt
->macrobuf
,MAXMACRO
- 1,"PPPP%s",myrpt
->p
.startupmacro
);
13958 time(&myrpt
->start_time
);
13959 myrpt
->last_activity_time
= myrpt
->start_time
;
13960 last_timeout_warning
= 0;
13962 myrpt
->tele
.next
= &myrpt
->tele
;
13963 myrpt
->tele
.prev
= &myrpt
->tele
;
13965 rpt_mutex_unlock(&myrpt
->lock
);
13966 ast_set_write_format(chan
, AST_FORMAT_SLINEAR
);
13967 ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
13970 /* if we are on 2w loop and are a remote, turn EC on */
13971 if (myrpt
->remote
&& (myrpt
->rxchannel
== myrpt
->txchannel
))
13974 ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_ECHOCANCEL
,&i
);
13976 if (chan
->_state
!= AST_STATE_UP
) {
13978 if (!phone_mode
) send_newkey(chan
);
13981 if (myrpt
->rxchannel
== myrpt
->dahdirxchannel
)
13983 if (ioctl(myrpt
->dahdirxchannel
->fds
[0],DAHDI_GET_PARAMS
,&par
) != -1)
13985 if (par
.rxisoffhook
)
13987 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
13988 myrpt
->remoterx
= 1;
13993 if (myrpt
->p
.archivedir
)
13995 char mycmd
[100],mydate
[100],*b
,*b1
;
14000 mkdir(myrpt
->p
.archivedir
,0600);
14001 sprintf(mycmd
,"%s/%s",myrpt
->p
.archivedir
,myrpt
->name
);
14004 strftime(mydate
,sizeof(mydate
) - 1,"%Y%m%d%H%M%S",
14006 sprintf(mycmd
,"mixmonitor start %s %s/%s/%s.wav49 a",chan
->name
,
14007 myrpt
->p
.archivedir
,myrpt
->name
,mydate
);
14008 if (myrpt
->p
.monminblocks
)
14010 blocksleft
= diskavail(myrpt
);
14011 if (myrpt
->p
.remotetimeout
)
14013 blocksleft
-= (myrpt
->p
.remotetimeout
*
14014 MONITOR_DISK_BLOCKS_PER_MINUTE
) / 60;
14016 if (blocksleft
>= myrpt
->p
.monminblocks
)
14017 ast_cli_command(nullfd
,mycmd
);
14018 } else ast_cli_command(nullfd
,mycmd
);
14019 /* look at callerid to see what node this comes from */
14020 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
14024 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
14025 ast_shrink_phone_number(b1
);
14027 sprintf(mycmd
,"CONNECT,%s",b1
);
14028 donodelog(myrpt
,mycmd
);
14030 myrpt
->loginuser
[0] = 0;
14031 myrpt
->loginlevel
[0] = 0;
14032 myrpt
->authtelltimer
= 0;
14033 myrpt
->authtimer
= 0;
14036 if (myrpt
->p
.authlevel
> 1) authreq
= 1;
14041 cs
[n
++] = myrpt
->rxchannel
;
14042 cs
[n
++] = myrpt
->pchannel
;
14043 if (myrpt
->rxchannel
!= myrpt
->txchannel
)
14044 cs
[n
++] = myrpt
->txchannel
;
14045 if (!phone_mode
) send_newkey(chan
);
14046 /* start un-locked */
14049 if (ast_check_hangup(chan
)) break;
14050 if (ast_check_hangup(myrpt
->rxchannel
)) break;
14054 telem
= myrpt
->tele
.next
;
14055 while(telem
!= &myrpt
->tele
)
14057 if (telem
->mode
== SETREMOTE
) setting
= 1;
14058 if ((telem
->mode
== SETREMOTE
) ||
14059 (telem
->mode
== SCAN
) ||
14060 (telem
->mode
== TUNE
)) reming
= 1;
14061 else notremming
= 1;
14062 telem
= telem
->next
;
14067 /* find our index, and load the vars */
14068 for(i
= 0; i
< nrpts
; i
++)
14070 if (&rpt_vars
[i
] == myrpt
)
14072 load_rpt_vars(i
,0);
14078 if (myrpt
->p
.remotetimeout
)
14082 r
= (t
- myrpt
->start_time
);
14083 if (r
>= myrpt
->p
.remotetimeout
)
14085 saynode(myrpt
,chan
,myrpt
->name
);
14086 sayfile(chan
,"rpt/timeout");
14087 ast_safe_sleep(chan
,1000);
14090 if ((myrpt
->p
.remotetimeoutwarning
) &&
14091 (r
>= (myrpt
->p
.remotetimeout
-
14092 myrpt
->p
.remotetimeoutwarning
)) &&
14093 (r
<= (myrpt
->p
.remotetimeout
-
14094 myrpt
->p
.remotetimeoutwarningfreq
)))
14096 if (myrpt
->p
.remotetimeoutwarningfreq
)
14098 if ((t
- last_timeout_warning
) >=
14099 myrpt
->p
.remotetimeoutwarningfreq
)
14101 time(&last_timeout_warning
);
14102 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
14107 if (!last_timeout_warning
)
14109 time(&last_timeout_warning
);
14110 rpt_telemetry(myrpt
,TIMEOUT_WARNING
,0);
14115 if (myrpt
->p
.remoteinacttimeout
&& myrpt
->last_activity_time
)
14119 r
= (t
- myrpt
->last_activity_time
);
14120 if (r
>= myrpt
->p
.remoteinacttimeout
)
14122 saynode(myrpt
,chan
,myrpt
->name
);
14123 ast_safe_sleep(chan
,1000);
14126 if ((myrpt
->p
.remotetimeoutwarning
) &&
14127 (r
>= (myrpt
->p
.remoteinacttimeout
-
14128 myrpt
->p
.remotetimeoutwarning
)) &&
14129 (r
<= (myrpt
->p
.remoteinacttimeout
-
14130 myrpt
->p
.remotetimeoutwarningfreq
)))
14132 if (myrpt
->p
.remotetimeoutwarningfreq
)
14134 if ((t
- last_timeout_warning
) >=
14135 myrpt
->p
.remotetimeoutwarningfreq
)
14137 time(&last_timeout_warning
);
14138 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
14143 if (!last_timeout_warning
)
14145 time(&last_timeout_warning
);
14146 rpt_telemetry(myrpt
,ACT_TIMEOUT_WARNING
,0);
14152 who
= ast_waitfor_n(cs
,n
,&ms
);
14153 if (who
== NULL
) ms
= 0;
14154 elap
= MSWAIT
- ms
;
14155 if (myrpt
->macrotimer
) myrpt
->macrotimer
-= elap
;
14156 if (myrpt
->macrotimer
< 0) myrpt
->macrotimer
= 0;
14158 /* do local dtmf timer */
14159 if (myrpt
->dtmf_local_timer
)
14161 if (myrpt
->dtmf_local_timer
> 1) myrpt
->dtmf_local_timer
-= elap
;
14162 if (myrpt
->dtmf_local_timer
< 1) myrpt
->dtmf_local_timer
= 1;
14164 rpt_mutex_lock(&myrpt
->lock
);
14165 do_dtmf_local(myrpt
,0);
14166 rpt_mutex_unlock(&myrpt
->lock
);
14168 rem_totx
= myrpt
->dtmf_local_timer
&& (!phone_mode
);
14169 rem_totx
|= keyed
&& (!myrpt
->tunerequest
);
14170 rem_rx
= (remkeyed
&& (!setting
)) || (myrpt
->tele
.next
!= &myrpt
->tele
);
14171 if(!strcmp(myrpt
->remoterig
, remote_rig_ic706
))
14172 rem_totx
|= myrpt
->tunerequest
;
14174 if((debug
> 6) && rem_totx
) {
14175 ast_log(LOG_NOTICE
,"Set rem_totx=%i. dtmf_local_timer=%i phone_mode=%i keyed=%i tunerequest=%i\n",rem_totx
,myrpt
->dtmf_local_timer
,phone_mode
,keyed
,myrpt
->tunerequest
);
14177 if (keyed
&& (!keyed1
))
14182 if (!keyed
&& (keyed1
))
14188 /* if login necessary, and not too soon */
14189 if ((myrpt
->p
.authlevel
) &&
14190 (!myrpt
->loginlevel
[0]) &&
14195 myrpt
->authtelltimer
= AUTHTELLTIME
- AUTHTXTIME
;
14199 if (rem_rx
&& (!myrpt
->remoterx
))
14201 myrpt
->remoterx
= 1;
14202 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
14204 if ((!rem_rx
) && (myrpt
->remoterx
))
14206 myrpt
->remoterx
= 0;
14207 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
14209 /* if auth requested, and not authed yet */
14210 if (authreq
&& (!myrpt
->loginlevel
[0]))
14212 if ((!authtold
) && ((myrpt
->authtelltimer
+= elap
)
14216 rpt_telemetry(myrpt
,LOGINREQ
,NULL
);
14218 if ((myrpt
->authtimer
+= elap
) >= AUTHLOGOUTTIME
)
14220 break; /* if not logged in, hang up after a time */
14225 if ((myrpt
->retxtimer
+= elap
) >= REDUNDANT_TX_TIME
)
14227 myrpt
->retxtimer
= 0;
14228 if ((myrpt
->remoterx
) && (!myrpt
->remotetx
))
14229 ast_indicate(chan
,AST_CONTROL_RADIO_KEY
);
14231 ast_indicate(chan
,AST_CONTROL_RADIO_UNKEY
);
14234 if ((myrpt
->rerxtimer
+= elap
) >= (REDUNDANT_TX_TIME
* 2))
14237 myrpt
->rerxtimer
= 0;
14240 if (rem_totx
&& (!myrpt
->remotetx
))
14242 /* if not authed, and needed, do not transmit */
14243 if ((!myrpt
->p
.authlevel
) || myrpt
->loginlevel
[0])
14246 ast_log(LOG_NOTICE
,"Handle rem_totx=%i. dtmf_local_timer=%i tunerequest=%i\n",rem_totx
,myrpt
->dtmf_local_timer
,myrpt
->tunerequest
);
14248 myrpt
->remotetx
= 1;
14249 /* asdf maw ??? is this really what you want? Doesn't it always get executed? */
14250 if((myrpt
->remtxfreqok
= check_tx_freq(myrpt
)))
14252 time(&myrpt
->last_activity_time
);
14253 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->dahditxchannel
))
14255 z
.radpar
= DAHDI_RADPAR_UIODATA
;
14257 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
14259 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
14265 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_KEY
);
14267 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXKEY");
14271 if ((!rem_totx
) && myrpt
->remotetx
) /* Remote base radio TX unkey */
14273 myrpt
->remotetx
= 0;
14274 if(!myrpt
->remtxfreqok
){
14275 rpt_telemetry(myrpt
,UNAUTHTX
,NULL
);
14277 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->dahditxchannel
))
14279 z
.radpar
= DAHDI_RADPAR_UIODATA
;
14281 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
14283 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
14289 ast_indicate(myrpt
->txchannel
,AST_CONTROL_RADIO_UNKEY
);
14291 if (myrpt
->p
.archivedir
) donodelog(myrpt
,"TXUNKEY");
14293 if (myrpt
->hfscanmode
){
14294 myrpt
->scantimer
-= elap
;
14295 if(myrpt
->scantimer
<= 0){
14298 myrpt
->scantimer
= REM_SCANTIME
;
14299 rpt_telemetry(myrpt
,SCAN
,0);
14300 } else myrpt
->scantimer
= 1;
14303 rpt_mutex_lock(&myrpt
->lock
);
14304 c
= myrpt
->macrobuf
[0];
14305 if (c
&& (!myrpt
->macrotimer
))
14307 myrpt
->macrotimer
= MACROTIME
;
14308 memmove(myrpt
->macrobuf
,myrpt
->macrobuf
+ 1,MAXMACRO
- 1);
14309 if ((c
== 'p') || (c
== 'P'))
14310 myrpt
->macrotimer
= MACROPTIME
;
14311 rpt_mutex_unlock(&myrpt
->lock
);
14312 if (myrpt
->p
.archivedir
)
14315 sprintf(str
,"DTMF(M),%c",c
);
14316 donodelog(myrpt
,str
);
14318 if (handle_remote_dtmf_digit(myrpt
,c
,&keyed
,0) == -1) break;
14320 } else rpt_mutex_unlock(&myrpt
->lock
);
14321 if (who
== chan
) /* if it was a read from incomming */
14323 f
= ast_read(chan
);
14326 if (debug
) printf("@@@@ link:Hung Up\n");
14329 if (f
->frametype
== AST_FRAME_VOICE
)
14331 if (ioctl(chan
->fds
[0], DAHDI_GETCONFMUTE
, &ismuted
) == -1)
14335 /* if not transmitting, zero-out audio */
14336 ismuted
|= (!myrpt
->remotetx
);
14337 if (dtmfed
&& phone_mode
) ismuted
= 1;
14341 memset(f
->data
.ptr
,0,f
->datalen
);
14343 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
14345 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
14347 if (f
) f2
= ast_frdup(f
);
14349 f1
= myrpt
->lastf2
;
14350 myrpt
->lastf2
= myrpt
->lastf1
;
14351 myrpt
->lastf1
= f2
;
14355 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
14357 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
14362 ast_write(myrpt
->txchannel
,f1
);
14364 ast_write(myrpt
->txchannel
,f
);
14368 #ifndef OLD_ASTERISK
14369 else if (f
->frametype
== AST_FRAME_DTMF_BEGIN
)
14372 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
14374 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
14378 if (f
->frametype
== AST_FRAME_DTMF
)
14381 memset(myrpt
->lastf1
->data
.ptr
,0,myrpt
->lastf1
->datalen
);
14383 memset(myrpt
->lastf2
->data
.ptr
,0,myrpt
->lastf2
->datalen
);
14385 if (handle_remote_phone_dtmf(myrpt
,f
->subclass
,&keyed
,phone_mode
) == -1)
14387 if (debug
) printf("@@@@ rpt:Hung Up\n");
14392 if (f
->frametype
== AST_FRAME_TEXT
)
14394 if (handle_remote_data(myrpt
,f
->data
.ptr
) == -1)
14396 if (debug
) printf("@@@@ rpt:Hung Up\n");
14401 if (f
->frametype
== AST_FRAME_CONTROL
)
14403 if (f
->subclass
== AST_CONTROL_HANGUP
)
14405 if (debug
) printf("@@@@ rpt:Hung Up\n");
14410 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
14412 if (debug
== 7) printf("@@@@ rx key\n");
14414 myrpt
->rerxtimer
= 0;
14417 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
14419 myrpt
->rerxtimer
= 0;
14420 if (debug
== 7) printf("@@@@ rx un-key\n");
14427 if (who
== myrpt
->rxchannel
) /* if it was a read from radio */
14429 f
= ast_read(myrpt
->rxchannel
);
14432 if (debug
) printf("@@@@ link:Hung Up\n");
14435 if (f
->frametype
== AST_FRAME_VOICE
)
14439 if(!strcmp(myrpt
->remoterig
, remote_rig_kenwood
))
14442 if (myreming
|| (!remkeyed
) ||
14443 ((myrpt
->remote
) && (myrpt
->remotetx
)) ||
14444 ((myrpt
->remmode
!= REM_MODE_FM
) &&
14446 memset(f
->data
.ptr
,0,f
->datalen
);
14447 ast_write(myrpt
->pchannel
,f
);
14449 else if (f
->frametype
== AST_FRAME_CONTROL
)
14451 if (f
->subclass
== AST_CONTROL_HANGUP
)
14453 if (debug
) printf("@@@@ rpt:Hung Up\n");
14458 if (f
->subclass
== AST_CONTROL_RADIO_KEY
)
14460 if (debug
== 7) printf("@@@@ remote rx key\n");
14461 if (!myrpt
->remotetx
)
14467 if (f
->subclass
== AST_CONTROL_RADIO_UNKEY
)
14469 if (debug
== 7) printf("@@@@ remote rx un-key\n");
14470 if (!myrpt
->remotetx
)
14479 if (who
== myrpt
->pchannel
) /* if is remote mix output */
14481 f
= ast_read(myrpt
->pchannel
);
14484 if (debug
) printf("@@@@ link:Hung Up\n");
14487 if (f
->frametype
== AST_FRAME_VOICE
)
14491 if (f
->frametype
== AST_FRAME_CONTROL
)
14493 if (f
->subclass
== AST_CONTROL_HANGUP
)
14495 if (debug
) printf("@@@@ rpt:Hung Up\n");
14503 if ((myrpt
->rxchannel
!= myrpt
->txchannel
) &&
14504 (who
== myrpt
->txchannel
)) /* do this cuz you have to */
14506 f
= ast_read(myrpt
->txchannel
);
14509 if (debug
) printf("@@@@ link:Hung Up\n");
14512 if (f
->frametype
== AST_FRAME_CONTROL
)
14514 if (f
->subclass
== AST_CONTROL_HANGUP
)
14516 if (debug
) printf("@@@@ rpt:Hung Up\n");
14525 if (myrpt
->p
.archivedir
)
14527 char mycmd
[100],*b
,*b1
;
14529 /* look at callerid to see what node this comes from */
14530 if (!chan
->cid
.cid_num
) /* if doesn't have caller id */
14534 ast_callerid_parse(chan
->cid
.cid_num
,&b
,&b1
);
14535 ast_shrink_phone_number(b1
);
14537 sprintf(mycmd
,"DISCONNECT,%s",b1
);
14538 donodelog(myrpt
,mycmd
);
14540 /* wait for telem to be done */
14541 while(myrpt
->tele
.next
!= &myrpt
->tele
) usleep(100000);
14542 sprintf(tmp
,"mixmonitor stop %s",chan
->name
);
14543 ast_cli_command(nullfd
,tmp
);
14545 rpt_mutex_lock(&myrpt
->lock
);
14546 myrpt
->hfscanmode
= 0;
14547 myrpt
->hfscanstatus
= 0;
14548 myrpt
->remoteon
= 0;
14549 rpt_mutex_unlock(&myrpt
->lock
);
14550 if (myrpt
->lastf1
) ast_frfree(myrpt
->lastf1
);
14551 myrpt
->lastf1
= NULL
;
14552 if (myrpt
->lastf2
) ast_frfree(myrpt
->lastf2
);
14553 myrpt
->lastf2
= NULL
;
14554 if ((iskenwood_pci4
) && (myrpt
->txchannel
== myrpt
->dahditxchannel
))
14556 z
.radpar
= DAHDI_RADPAR_UIOMODE
;
14558 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
14560 ast_log(LOG_ERROR
,"Cannot set UIOMODE\n");
14563 z
.radpar
= DAHDI_RADPAR_UIODATA
;
14565 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_RADIO_SETPARAM
,&z
) == -1)
14567 ast_log(LOG_ERROR
,"Cannot set UIODATA\n");
14571 if (ioctl(myrpt
->dahditxchannel
->fds
[0],DAHDI_HOOK
,&i
) == -1)
14573 ast_log(LOG_ERROR
,"Cannot set hook\n");
14577 if (myrpt
->iofd
) close(myrpt
->iofd
);
14579 ast_hangup(myrpt
->pchannel
);
14580 if (myrpt
->rxchannel
!= myrpt
->txchannel
) ast_hangup(myrpt
->txchannel
);
14581 ast_hangup(myrpt
->rxchannel
);
14583 if (myrpt
->p
.rptnode
)
14585 rpt_mutex_lock(&myrpt
->lock
);
14586 for(i
= 0; i
< nrpts
; i
++)
14588 if (!strcasecmp(rpt_vars
[i
].name
,myrpt
->p
.rptnode
))
14590 rpt_vars
[i
].xlink
= 0;
14594 rpt_mutex_unlock(&myrpt
->lock
);
14596 #ifdef OLD_ASTERISK
14597 LOCAL_USER_REMOVE(u
);
14602 #ifndef OLD_ASTERISK
14603 /*!\brief callback to display list of locally configured nodes
14604 \addtogroup Group_AMI
14606 static int manager_rpt_local_nodes(struct mansession
*s
, const struct message
*m
)
14609 astman_append(s
, "<?xml version=\"1.0\"?>\r\n");
14610 astman_append(s
, "<nodes>\r\n");
14611 for (i
=0; i
< nrpts
; i
++)
14613 astman_append(s
, " <node>%s</node>\r\n", rpt_vars
[i
].name
);
14615 astman_append(s
, "</nodes>\r\n");
14616 astman_append(s
, "\r\n"); /* Properly terminate Manager output */
14617 return RESULT_SUCCESS
;
14618 } /* manager_rpt_local_nodes() */
14623 * Append Success and ActionID to manager response message
14626 static void rpt_manager_success(struct mansession
*s
, const struct message
*m
)
14628 const char *id
= astman_get_header(m
, "ActionID");
14629 if (!ast_strlen_zero(id
))
14630 astman_append(s
, "ActionID: %s\r\n", id
);
14631 astman_append(s
, "Response: Success\r\n");
14635 * Dump statistics to manager session
14638 static int rpt_manager_do_stats(struct mansession
*s
, const struct message
*m
, char *str
)
14640 int i
,j
,numoflinks
;
14641 int dailytxtime
, dailykerchunks
;
14643 int totalkerchunks
, dailykeyups
, totalkeyups
, timeouts
;
14644 int totalexecdcommands
, dailyexecdcommands
, hours
, minutes
, seconds
;
14645 long long totaltxtime
;
14646 struct rpt_link
*l
;
14647 char *listoflinks
[MAX_STAT_LINKS
];
14648 char *lastdtmfcommand
,*parrot_ena
;
14649 char *tot_state
, *ider_state
, *patch_state
;
14650 char *reverse_patch_state
, *sys_ena
, *tot_ena
, *link_ena
, *patch_ena
;
14651 char *sch_ena
, *input_signal
, *called_number
, *user_funs
, *tail_type
;
14652 char *transmitterkeyed
;
14653 const char *node
= astman_get_header(m
, "Node");
14656 static char *not_applicable
= "N/A";
14658 tot_state
= ider_state
=
14659 patch_state
= reverse_patch_state
=
14660 input_signal
= not_applicable
;
14661 called_number
= lastdtmfcommand
= transmitterkeyed
= NULL
;
14664 for(i
= 0; i
< nrpts
; i
++)
14666 if ((node
)&&(!strcmp(node
,rpt_vars
[i
].name
))){
14667 rpt_manager_success(s
,m
);
14669 myrpt
= &rpt_vars
[i
];
14671 if(myrpt
->remote
){ /* Remote base ? */
14672 char *loginuser
, *loginlevel
, *freq
, *rxpl
, *txpl
, *modestr
;
14673 char offset
,powerlevel
,rxplon
,txplon
,remoteon
,remmode
,reportfmstuff
;
14674 char offsetc
,powerlevelc
;
14676 loginuser
= loginlevel
= freq
= rxpl
= txpl
= NULL
;
14677 /* Make a copy of all stat variables while locked */
14678 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
14679 if((remoteon
= myrpt
->remoteon
)){
14680 if(!ast_strlen_zero(myrpt
->loginuser
))
14681 loginuser
= ast_strdup(myrpt
->loginuser
);
14682 if(!ast_strlen_zero(myrpt
->loginlevel
))
14683 loginlevel
= ast_strdup(myrpt
->loginlevel
);
14684 if(!ast_strlen_zero(myrpt
->freq
))
14685 freq
= ast_strdup(myrpt
->freq
);
14686 if(!ast_strlen_zero(myrpt
->rxpl
))
14687 rxpl
= ast_strdup(myrpt
->rxpl
);
14688 if(!ast_strlen_zero(myrpt
->txpl
))
14689 txpl
= ast_strdup(myrpt
->txpl
);
14690 remmode
= myrpt
->remmode
;
14691 offset
= myrpt
->offset
;
14692 powerlevel
= myrpt
->powerlevel
;
14693 rxplon
= myrpt
->rxplon
;
14694 txplon
= myrpt
->txplon
;
14696 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
14697 astman_append(s
, "IsRemoteBase: YES\r\n");
14698 astman_append(s
, "RemoteOn: %s\r\n",(remoteon
) ? "YES": "NO");
14701 astman_append(s
, "LogInUser: %s\r\n", loginuser
);
14702 ast_free(loginuser
);
14705 astman_append(s
, "LogInLevel: %s\r\n", loginlevel
);
14706 ast_free(loginlevel
);
14709 astman_append(s
, "Freq: %s\r\n", freq
);
14728 astman_append(s
, "RemMode: %s\r\n", modestr
);
14741 astman_append(s
, "RemOffset: %c\r\n", offsetc
);
14742 if(rxplon
&& rxpl
){
14743 astman_append(s
, "RxPl: %s\r\n",rxpl
);
14746 if(txplon
&& txpl
){
14747 astman_append(s
, "TxPl: %s\r\n",txpl
);
14751 switch(powerlevel
){
14762 astman_append(s
,"PowerLevel: %c\r\n", powerlevelc
);
14764 astman_append(s
, "\r\n");
14765 return 0; /* End of remote base status reporting */
14768 /* ELSE Process as a repeater node */
14769 /* Make a copy of all stat variables while locked */
14770 rpt_mutex_lock(&myrpt
->lock
); /* LOCK */
14771 dailytxtime
= myrpt
->dailytxtime
;
14772 totaltxtime
= myrpt
->totaltxtime
;
14773 dailykeyups
= myrpt
->dailykeyups
;
14774 totalkeyups
= myrpt
->totalkeyups
;
14775 dailykerchunks
= myrpt
->dailykerchunks
;
14776 totalkerchunks
= myrpt
->totalkerchunks
;
14777 dailyexecdcommands
= myrpt
->dailyexecdcommands
;
14778 totalexecdcommands
= myrpt
->totalexecdcommands
;
14779 timeouts
= myrpt
->timeouts
;
14782 /* Traverse the list of connected nodes */
14783 reverse_patch_state
= "DOWN";
14785 l
= myrpt
->links
.next
;
14786 while(l
&& (l
!= &myrpt
->links
)){
14787 if(numoflinks
>= MAX_STAT_LINKS
){
14788 ast_log(LOG_NOTICE
,
14789 "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS
);
14792 if (l
->name
[0] == '0'){ /* Skip '0' nodes */
14793 reverse_patch_state
= "UP";
14797 listoflinks
[numoflinks
] = ast_strdup(l
->name
);
14798 if(listoflinks
[numoflinks
] == NULL
){
14808 input_signal
= "YES";
14810 input_signal
= "NO";
14813 transmitterkeyed
= "YES";
14815 transmitterkeyed
= "NO";
14817 if(myrpt
->p
.parrotmode
)
14818 parrot_ena
= "ENABLED";
14820 parrot_ena
= "DISABLED";
14822 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].txdisable
)
14823 sys_ena
= "DISABLED";
14825 sys_ena
= "ENABLED";
14827 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].totdisable
)
14828 tot_ena
= "DISABLED";
14830 tot_ena
= "ENABLED";
14832 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].linkfundisable
)
14833 link_ena
= "DISABLED";
14835 link_ena
= "ENABLED";
14837 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].autopatchdisable
)
14838 patch_ena
= "DISABLED";
14840 patch_ena
= "ENABLED";
14842 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].schedulerdisable
)
14843 sch_ena
= "DISABLED";
14845 sch_ena
= "ENABLED";
14847 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].userfundisable
)
14848 user_funs
= "DISABLED";
14850 user_funs
= "ENABLED";
14852 if(myrpt
->p
.s
[myrpt
->p
.sysstate_cur
].alternatetail
)
14853 tail_type
= "ALTERNATE";
14855 tail_type
= "STANDARD";
14857 if(!myrpt
->totimer
)
14858 tot_state
= "TIMED OUT!";
14859 else if(myrpt
->totimer
!= myrpt
->p
.totime
)
14860 tot_state
= "ARMED";
14862 tot_state
= "RESET";
14865 ider_state
= "QUEUED IN TAIL";
14866 else if(myrpt
->mustid
)
14867 ider_state
= "QUEUED FOR CLEANUP";
14869 ider_state
= "CLEAN";
14871 switch(myrpt
->callmode
){
14873 patch_state
= "DIALING";
14876 patch_state
= "CONNECTING";
14879 patch_state
= "UP";
14883 patch_state
= "CALL FAILED";
14887 patch_state
= "DOWN";
14890 if(strlen(myrpt
->exten
)){
14891 called_number
= ast_strdup(myrpt
->exten
);
14894 if(strlen(myrpt
->lastdtmfcommand
)){
14895 lastdtmfcommand
= ast_strdup(myrpt
->lastdtmfcommand
);
14897 rpt_mutex_unlock(&myrpt
->lock
); /* UNLOCK */
14899 astman_append(s
, "IsRemoteBase: NO\r\n");
14900 astman_append(s
, "NodeState: %d\r\n", myrpt
->p
.sysstate_cur
);
14901 astman_append(s
, "SignalOnInput: %s\r\n", input_signal
);
14902 astman_append(s
, "TransmitterKeyed: %s\r\n", transmitterkeyed
);
14903 astman_append(s
, "Transmitter: %s\r\n", sys_ena
);
14904 astman_append(s
, "Parrot: %s\r\n", parrot_ena
);
14905 astman_append(s
, "Scheduler: %s\r\n", sch_ena
);
14906 astman_append(s
, "TailLength: %s\r\n", tail_type
);
14907 astman_append(s
, "TimeOutTimer: %s\r\n", tot_ena
);
14908 astman_append(s
, "TimeOutTimerState: %s\r\n", tot_state
);
14909 astman_append(s
, "TimeOutsSinceSystemInitialization: %d\r\n", timeouts
);
14910 astman_append(s
, "IdentifierState: %s\r\n", ider_state
);
14911 astman_append(s
, "KerchunksToday: %d\r\n", dailykerchunks
);
14912 astman_append(s
, "KerchunksSinceSystemInitialization: %d\r\n", totalkerchunks
);
14913 astman_append(s
, "KeyupsToday: %d\r\n", dailykeyups
);
14914 astman_append(s
, "KeyupsSinceSystemInitialization: %d\r\n", totalkeyups
);
14915 astman_append(s
, "DtmfCommandsToday: %d\r\n", dailyexecdcommands
);
14916 astman_append(s
, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands
);
14917 astman_append(s
, "LastDtmfCommandExecuted: %s\r\n",
14918 (lastdtmfcommand
&& strlen(lastdtmfcommand
)) ? lastdtmfcommand
: not_applicable
);
14919 hours
= dailytxtime
/3600000;
14920 dailytxtime
%= 3600000;
14921 minutes
= dailytxtime
/60000;
14922 dailytxtime
%= 60000;
14923 seconds
= dailytxtime
/1000;
14924 dailytxtime
%= 1000;
14926 astman_append(s
, "TxTimeToday: %02d:%02d:%02d.%d\r\n",
14927 hours
, minutes
, seconds
, dailytxtime
);
14929 hours
= (int) totaltxtime
/3600000;
14930 totaltxtime
%= 3600000;
14931 minutes
= (int) totaltxtime
/60000;
14932 totaltxtime
%= 60000;
14933 seconds
= (int) totaltxtime
/1000;
14934 totaltxtime
%= 1000;
14936 astman_append(s
, "TxTimeSinceSystemInitialization: %02d:%02d:%02d.%d\r\n",
14937 hours
, minutes
, seconds
, (int) totaltxtime
);
14939 sprintf(str
, "NodesCurrentlyConnectedToUs: ");
14941 strcat(str
,"<NONE>");
14944 for(j
= 0 ;j
< numoflinks
; j
++){
14945 sprintf(str
+strlen(str
), "%s", listoflinks
[j
]);
14946 if(j
< numoflinks
- 1)
14950 astman_append(s
,"%s\r\n", str
);
14952 astman_append(s
, "Autopatch: %s\r\n", patch_ena
);
14953 astman_append(s
, "AutopatchState: %s\r\n", patch_state
);
14954 astman_append(s
, "AutopatchCalledNumber: %s\r\n",
14955 (called_number
&& strlen(called_number
)) ? called_number
: not_applicable
);
14956 astman_append(s
, "ReversePatchIaxrptConnected: %s\r\n", reverse_patch_state
);
14957 astman_append(s
, "UserLinkingCommands: %s\r\n", link_ena
);
14958 astman_append(s
, "UserFunctions: %s\r\n", user_funs
);
14960 for(j
= 0; j
< numoflinks
; j
++){ /* ast_free() all link names */
14961 ast_free(listoflinks
[j
]);
14964 ast_free(called_number
);
14966 if(lastdtmfcommand
){
14967 ast_free(lastdtmfcommand
);
14969 astman_append(s
, "\r\n"); /* We're Done! */
14973 astman_send_error(s
, m
, "RptStatus unknown or missing node");
14980 * Implement the RptStatus Manager Interface
14983 static int manager_rpt_status(struct mansession
*s
, const struct message
*m
)
14985 int i
,res
,len
,index
;
14986 int uptime
,hours
,minutes
;
14988 const char *cmd
= astman_get_header(m
, "Command");
14990 enum {MGRCMD_RPTSTAT
,MGRCMD_NODESTAT
};
14995 static struct mgrcmdtbl mct
[] = {
14996 {"RptStat",MGRCMD_RPTSTAT
},
14997 {"NodeStat",MGRCMD_NODESTAT
},
14998 {NULL
,0} /* NULL marks end of command table */
15003 len
= 1024; /* Allocate a working buffer */
15004 if(!(str
= ast_malloc(len
)))
15007 /* Check for Command */
15008 if(ast_strlen_zero(cmd
)){
15009 astman_send_error(s
, m
, "RptStatus missing command");
15013 /* Try to find the command in the table */
15014 for(i
= 0 ; mct
[i
].cmd
; i
++){
15015 if(!strcmp(mct
[i
].cmd
, cmd
))
15019 if(!mct
[i
].cmd
){ /* Found or not found ? */
15020 astman_send_error(s
, m
, "RptStatus unknown command");
15025 index
= mct
[i
].index
;
15027 switch(index
){ /* Use the index to go to the correct command */
15029 case MGRCMD_RPTSTAT
:
15030 /* Return Nodes: and a comma separated list of nodes */
15031 if((res
= snprintf(str
, len
, "Nodes: ")) > -1)
15037 for(i
= 0; i
< nrpts
; i
++){
15039 if((res
= snprintf(str
+strlen(str
), len
, "%s,",rpt_vars
[i
].name
)) < 0){
15045 if((res
= snprintf(str
+strlen(str
), len
, "%s",rpt_vars
[i
].name
)) < 0){
15053 rpt_manager_success(s
,m
);
15056 astman_append(s
, "<NONE>\r\n");
15058 astman_append(s
, "%s\r\n", str
);
15060 uptime
= (int)(now
- starttime
);
15061 hours
= uptime
/3600;
15063 minutes
= uptime
/60;
15066 astman_append(s
, "RptUptime: %02d:%02d:%02d\r\n",
15067 hours
, minutes
, uptime
);
15069 astman_append(s
, "\r\n");
15072 case MGRCMD_NODESTAT
:
15073 res
= rpt_manager_do_stats(s
,m
,str
);
15078 astman_send_error(s
, m
, "RptStatus invalid command");
15087 #ifdef OLD_ASTERISK
15088 int unload_module()
15090 static int unload_module(void)
15095 #ifdef OLD_ASTERISK
15096 STANDARD_HANGUP_LOCALUSERS
;
15098 for(i
= 0; i
< nrpts
; i
++) {
15099 if (!strcmp(rpt_vars
[i
].name
,rpt_vars
[i
].p
.nodes
)) continue;
15100 ast_mutex_destroy(&rpt_vars
[i
].lock
);
15101 ast_mutex_destroy(&rpt_vars
[i
].remlock
);
15103 res
= ast_unregister_application(app
);
15105 #ifdef NEW_ASTERISK
15106 ast_cli_unregister_multiple(rpt_cli
,sizeof(rpt_cli
) /
15107 sizeof(struct ast_cli_entry
));
15109 /* Unregister cli extensions */
15110 ast_cli_unregister(&cli_debug
);
15111 ast_cli_unregister(&cli_dump
);
15112 ast_cli_unregister(&cli_stats
);
15113 ast_cli_unregister(&cli_lstats
);
15114 ast_cli_unregister(&cli_nodes
);
15115 ast_cli_unregister(&cli_local_nodes
);
15116 ast_cli_unregister(&cli_reload
);
15117 ast_cli_unregister(&cli_restart
);
15118 ast_cli_unregister(&cli_fun
);
15119 ast_cli_unregister(&cli_fun1
);
15120 res
|= ast_cli_unregister(&cli_cmd
);
15122 #ifndef OLD_ASTERISK
15123 res
|= ast_manager_unregister("RptLocalNodes");
15124 res
|= ast_manager_unregister("RptStatus");
15129 #ifdef OLD_ASTERISK
15132 static int load_module(void)
15136 ast_pthread_create(&rpt_master_thread
,NULL
,rpt_master
,NULL
);
15138 #ifdef NEW_ASTERISK
15139 ast_cli_register_multiple(rpt_cli
,sizeof(rpt_cli
) /
15140 sizeof(struct ast_cli_entry
));
15143 /* Register cli extensions */
15144 ast_cli_register(&cli_debug
);
15145 ast_cli_register(&cli_dump
);
15146 ast_cli_register(&cli_stats
);
15147 ast_cli_register(&cli_lstats
);
15148 ast_cli_register(&cli_nodes
);
15149 ast_cli_register(&cli_local_nodes
);
15150 ast_cli_register(&cli_reload
);
15151 ast_cli_register(&cli_restart
);
15152 ast_cli_register(&cli_fun
);
15153 ast_cli_register(&cli_fun1
);
15154 res
= ast_cli_register(&cli_cmd
);
15156 #ifndef OLD_ASTERISK
15157 res
|= ast_manager_register("RptLocalNodes", 0, manager_rpt_local_nodes
, "List local node numbers");
15158 res
|= ast_manager_register("RptStatus", 0, manager_rpt_status
, "Return Rpt Status for CGI");
15161 res
|= ast_register_application(app
, rpt_exec
, synopsis
, descrip
);
15165 #ifdef OLD_ASTERISK
15166 char *description()
15173 STANDARD_USECOUNT(res
);
15179 return ASTERISK_GPL_KEY
;
15183 #ifdef OLD_ASTERISK
15186 static int reload(void)
15191 for(n
= 0; n
< nrpts
; n
++) rpt_vars
[n
].reload
= 1;
15196 #ifndef OLD_ASTERISK
15197 /* STD_MOD(MOD_1, reload, NULL, NULL); */
15198 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Radio Repeater/Remote Base Application",
15199 .load
= load_module
,
15200 .unload
= unload_module
,